- Клиентская часть Vue 3 + Vite - Серверная часть Node.js + WebSocket - Система авторизации и смен - Управление игровыми портами - Поддержка тем (светлая/темная) - Адаптивный дизайн 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
104 lines
4.0 KiB
JavaScript
104 lines
4.0 KiB
JavaScript
// Универсальное воспроизведение звука для Linux и Windows
|
||
const { exec, spawn } = require('child_process');
|
||
const fs = require('fs');
|
||
const os = require('os');
|
||
const path = require('path');
|
||
|
||
class UniversalSound {
|
||
constructor(filePath) {
|
||
// Получаем абсолютный путь к файлу
|
||
this.path = path.resolve(filePath);
|
||
this.process = null;
|
||
this.isPlaying = false;
|
||
console.log(`[AUDIO] Звуковой файл загружен: ${this.path}`);
|
||
}
|
||
|
||
stop() {
|
||
if (this.process && this.isPlaying) {
|
||
console.log(`[AUDIO] Останавливаем воспроизведение: ${this.path}`);
|
||
this.process.kill();
|
||
this.process = null;
|
||
this.isPlaying = false;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
play(onStart = null, onEnd = null) {
|
||
console.log(`[AUDIO] Воспроизведение: ${this.path}`);
|
||
|
||
// Останавливаем предыдущее воспроизведение если есть
|
||
this.stop();
|
||
|
||
// Проверяем существование файла
|
||
if (!fs.existsSync(this.path)) {
|
||
console.error(`[AUDIO] Файл не найден: ${this.path}`);
|
||
return this;
|
||
}
|
||
|
||
const platform = os.platform();
|
||
let command, args;
|
||
|
||
// Выбираем команду в зависимости от ОС
|
||
if (platform === 'linux') {
|
||
// Для Linux используем aplay
|
||
command = 'aplay';
|
||
args = [this.path];
|
||
} else if (platform === 'win32') {
|
||
// Для Windows используем разные методы в зависимости от формата
|
||
const ext = path.extname(this.path).toLowerCase();
|
||
|
||
if (ext === '.wav') {
|
||
// Для WAV используем SoundPlayer
|
||
const escapedPath = this.path.replace(/\\/g, '\\\\').replace(/"/g, '""');
|
||
command = 'powershell';
|
||
args = ['-c', `(New-Object Media.SoundPlayer '${escapedPath}').PlaySync();`];
|
||
} else {
|
||
// Для MP3 и других форматов используем Windows Media Player
|
||
command = 'powershell';
|
||
args = ['-WindowStyle', 'Hidden', '-Command', `
|
||
Add-Type -AssemblyName presentationCore
|
||
$player = New-Object System.Windows.Media.MediaPlayer
|
||
$player.Open([Uri]"${this.path}")
|
||
Start-Sleep -Milliseconds 500
|
||
$player.Play()
|
||
while ($player.Position -lt $player.NaturalDuration.TimeSpan) {
|
||
Start-Sleep -Milliseconds 100
|
||
}
|
||
$player.Close()
|
||
`];
|
||
}
|
||
} else if (platform === 'darwin') {
|
||
// Для macOS используем afplay
|
||
command = 'afplay';
|
||
args = [this.path];
|
||
} else {
|
||
console.error(`[AUDIO] Неподдерживаемая ОС: ${platform}`);
|
||
return this;
|
||
}
|
||
|
||
console.log(`[AUDIO] Выполняем команду: ${command} ${args.join(' ')}`);
|
||
|
||
// Запускаем процесс
|
||
this.process = spawn(command, args);
|
||
this.isPlaying = true;
|
||
|
||
if (onStart) onStart();
|
||
|
||
this.process.on('close', (code) => {
|
||
console.log(`[AUDIO] Воспроизведение завершено: ${this.path}, код: ${code}`);
|
||
this.isPlaying = false;
|
||
this.process = null;
|
||
if (onEnd) onEnd();
|
||
});
|
||
|
||
this.process.on('error', (error) => {
|
||
console.error(`[AUDIO] Ошибка процесса: ${error.message}`);
|
||
this.isPlaying = false;
|
||
this.process = null;
|
||
});
|
||
|
||
return this;
|
||
}
|
||
}
|
||
|
||
module.exports = UniversalSound;
|