- Клиентская часть Vue 3 + Vite - Серверная часть Node.js + WebSocket - Система авторизации и смен - Управление игровыми портами - Поддержка тем (светлая/темная) - Адаптивный дизайн 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
167 lines
5.4 KiB
JavaScript
167 lines
5.4 KiB
JavaScript
// Прямое управление громкостью через Windows Audio Session API
|
||
const { spawn } = require('child_process');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
class WindowsDirectAudio {
|
||
constructor() {
|
||
this.musicProcess = null;
|
||
this.musicVolume = 70;
|
||
this.isDucked = false;
|
||
this.duckVolume = 20;
|
||
}
|
||
|
||
play(filePath, volume = 70) {
|
||
this.stop();
|
||
|
||
if (!fs.existsSync(filePath)) {
|
||
console.error('[DIRECT-AUDIO] Файл не найден:', filePath);
|
||
return false;
|
||
}
|
||
|
||
// Применяем громкость с учетом приглушения
|
||
const effectiveVolume = this.isDucked ? this.duckVolume : volume;
|
||
const volumeDecimal = effectiveVolume / 100;
|
||
|
||
console.log('[DIRECT-AUDIO] Воспроизведение:', path.basename(filePath));
|
||
console.log('[DIRECT-AUDIO] Эффективная громкость:', effectiveVolume + '%');
|
||
|
||
// PowerShell скрипт с прямым управлением громкостью
|
||
const script = `
|
||
# Загружаем Windows Media Player
|
||
Add-Type -AssemblyName presentationcore
|
||
$player = New-Object System.Windows.Media.MediaPlayer
|
||
|
||
# Устанавливаем начальную громкость
|
||
$player.Volume = ${volumeDecimal}
|
||
|
||
# Открываем файл
|
||
$player.Open("${filePath.replace(/\\/g, '\\\\')}")
|
||
|
||
# Ждем загрузки
|
||
$timeout = 0
|
||
while ($player.NaturalDuration.HasTimeSpan -eq $false -and $timeout -lt 50) {
|
||
Start-Sleep -Milliseconds 100
|
||
$timeout++
|
||
}
|
||
|
||
if ($player.NaturalDuration.HasTimeSpan -eq $false) {
|
||
Write-Host "ERROR: Failed to load file"
|
||
exit 1
|
||
}
|
||
|
||
# Запускаем воспроизведение
|
||
$player.Play()
|
||
Write-Host "STATUS:PLAYING:${effectiveVolume}"
|
||
|
||
# Файл для команд управления громкостью
|
||
$controlFile = "$env:TEMP\\audio_control_$PID.txt"
|
||
|
||
# Главный цикл
|
||
while ($true) {
|
||
# Проверяем файл с командами
|
||
if (Test-Path $controlFile) {
|
||
$command = Get-Content $controlFile -First 1
|
||
Remove-Item $controlFile -Force -ErrorAction SilentlyContinue
|
||
|
||
if ($command -match "^VOLUME:(\d+)$") {
|
||
$newVolume = [int]$matches[1] / 100
|
||
$player.Volume = $newVolume
|
||
Write-Host "VOLUME_CHANGED:$($matches[1])"
|
||
} elseif ($command -eq "STOP") {
|
||
break
|
||
}
|
||
}
|
||
|
||
# Проверяем завершение
|
||
if ($player.Position -ge $player.NaturalDuration.TimeSpan) {
|
||
Write-Host "STATUS:FINISHED"
|
||
break
|
||
}
|
||
|
||
Start-Sleep -Milliseconds 50
|
||
}
|
||
|
||
$player.Stop()
|
||
$player.Close()
|
||
`;
|
||
|
||
this.musicProcess = spawn('powershell', [
|
||
'-NoProfile',
|
||
'-WindowStyle', 'Hidden',
|
||
'-Command', script
|
||
], {
|
||
windowsHide: true
|
||
});
|
||
|
||
this.musicVolume = volume;
|
||
|
||
// Обработчики событий
|
||
this.musicProcess.stdout.on('data', (data) => {
|
||
const output = data.toString().trim();
|
||
console.log('[DIRECT-AUDIO]', output);
|
||
});
|
||
|
||
this.musicProcess.stderr.on('data', (data) => {
|
||
console.error('[DIRECT-AUDIO] Ошибка:', data.toString());
|
||
});
|
||
|
||
this.musicProcess.on('close', (code) => {
|
||
console.log('[DIRECT-AUDIO] Процесс завершен:', code);
|
||
this.musicProcess = null;
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
stop() {
|
||
if (this.musicProcess) {
|
||
console.log('[DIRECT-AUDIO] Остановка воспроизведения');
|
||
|
||
// Отправляем команду остановки
|
||
const controlFile = `${process.env.TEMP}\\audio_control_${this.musicProcess.pid}.txt`;
|
||
try {
|
||
fs.writeFileSync(controlFile, 'STOP');
|
||
} catch (err) {
|
||
// Принудительная остановка
|
||
this.musicProcess.kill();
|
||
}
|
||
|
||
this.musicProcess = null;
|
||
}
|
||
}
|
||
|
||
setVolume(volume) {
|
||
this.musicVolume = volume;
|
||
|
||
if (this.musicProcess) {
|
||
const effectiveVolume = this.isDucked ? this.duckVolume : volume;
|
||
const controlFile = `${process.env.TEMP}\\audio_control_${this.musicProcess.pid}.txt`;
|
||
|
||
try {
|
||
fs.writeFileSync(controlFile, `VOLUME:${effectiveVolume}`);
|
||
console.log('[DIRECT-AUDIO] Отправлена команда изменения громкости:', effectiveVolume);
|
||
} catch (err) {
|
||
console.error('[DIRECT-AUDIO] Ошибка изменения громкости:', err.message);
|
||
}
|
||
}
|
||
}
|
||
|
||
duck() {
|
||
console.log('[DIRECT-AUDIO] Приглушение музыки');
|
||
this.isDucked = true;
|
||
this.setVolume(this.musicVolume); // Пересчитает с учетом isDucked
|
||
}
|
||
|
||
unduck() {
|
||
console.log('[DIRECT-AUDIO] Восстановление громкости');
|
||
this.isDucked = false;
|
||
this.setVolume(this.musicVolume); // Пересчитает с учетом isDucked
|
||
}
|
||
|
||
isPlaying() {
|
||
return this.musicProcess !== null;
|
||
}
|
||
}
|
||
|
||
module.exports = WindowsDirectAudio; |