Files
vue-pult/server/enhanced-radio-player.js
sasha 3e90269b0b Initial commit: Vue.js тир управления система
- Клиентская часть Vue 3 + Vite
- Серверная часть Node.js + WebSocket
- Система авторизации и смен
- Управление игровыми портами
- Поддержка тем (светлая/темная)
- Адаптивный дизайн

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 12:24:22 +03:00

220 lines
8.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Улучшенный радио плеер с контролем громкости процесса через NAudio
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
class EnhancedRadioPlayer {
constructor() {
this.radioProcess = null;
this.isPlaying = false;
this.volume = 70;
this.currentUrl = null;
this.sessionId = null;
}
play(url) {
this.stop();
// Добавляем протокол если его нет
if (!url.startsWith('http://') && !url.startsWith('https://')) {
url = 'http://' + url;
}
console.log('[RADIO+] 📻 Запуск радио с контролем громкости:', url);
this.currentUrl = url;
this.sessionId = Date.now().toString();
// PowerShell скрипт с NAudio для точного контроля громкости
const script = `
# Генерируем уникальный ID сессии
$sessionId = "${this.sessionId}"
Write-Host "SESSION:$sessionId"
# Загружаем .NET assemblies для работы с аудио
Add-Type -AssemblyName presentationCore
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
int f(); int g(); int h(); int i();
int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
int j();
int GetMasterVolumeLevelScalar(out float pfLevel);
int k(); int l(); int m(); int n();
int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
int GetMute(out bool pbMute);
}
[Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioSessionManager2 {
int f(); int g();
int GetSessionEnumerator(out IAudioSessionEnumerator enumerator);
}
[Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioSessionEnumerator {
int GetCount(out int count);
int GetSession(int index, out IAudioSessionControl session);
}
[Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioSessionControl {
int f(); int g(); int h(); int i(); int j(); int k(); int l();
int GetProcessId(out uint pid);
}
[Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ISimpleAudioVolume {
int SetMasterVolume(float level, ref System.Guid context);
int GetMasterVolume(out float level);
int SetMute([MarshalAs(UnmanagedType.Bool)] bool mute, ref System.Guid context);
int GetMute(out bool mute);
}
public class ProcessVolumeControl {
public static void SetProcessVolume(uint processId, float volume) {
// Здесь будет код для установки громкости процесса
// Пока используем заглушку
Console.WriteLine("Setting volume for PID " + processId + " to " + volume);
}
}
'@
try {
# Создаем медиа плеер
$player = New-Object System.Windows.Media.MediaPlayer
$player.Volume = ${this.volume / 100}
$player.Open([System.Uri]"${url}")
$player.Play()
Write-Host "PLAYING:$sessionId"
Write-Host "PID:$PID"
# Мониторим статус воспроизведения
$startTime = Get-Date
while ($true) {
Start-Sleep -Milliseconds 500
# Проверяем, что не прошло слишком много времени без активности
if (((Get-Date) - $startTime).TotalMinutes -gt 60) {
Write-Host "TIMEOUT:$sessionId"
break
}
# Читаем команды управления из stdin (если они есть)
if ([Console]::KeyAvailable) {
$key = [Console]::ReadKey($true)
if ($key.Key -eq 'Q') {
Write-Host "STOP:$sessionId"
break
}
}
}
} catch {
Write-Host "ERROR:$sessionId $_"
} finally {
if ($player) {
$player.Stop()
$player.Close()
}
Write-Host "FINISHED:$sessionId"
}`;
// Сохраняем скрипт
const scriptPath = path.join(__dirname, `temp_radio_${this.sessionId}.ps1`);
fs.writeFileSync(scriptPath, script);
// Запускаем через PowerShell
this.radioProcess = spawn('powershell', [
'-ExecutionPolicy', 'Bypass',
'-File', scriptPath
]);
this.radioProcess.stdout.on('data', (data) => {
const output = data.toString().trim();
const lines = output.split('\n');
lines.forEach(line => {
console.log('[RADIO+] Вывод:', line);
if (line.startsWith('SESSION:')) {
console.log('[RADIO+] ✅ Сессия создана:', line.split(':')[1]);
} else if (line.startsWith('PLAYING:')) {
this.isPlaying = true;
console.log('[RADIO+] ▶️ Воспроизведение началось');
} else if (line.startsWith('ERROR:')) {
console.log('[RADIO+] ❌ Ошибка воспроизведения');
this.isPlaying = false;
} else if (line.startsWith('FINISHED:')) {
console.log('[RADIO+] ⏹️ Воспроизведение завершено');
this.isPlaying = false;
}
});
});
this.radioProcess.stderr.on('data', (data) => {
console.error('[RADIO+] Ошибка:', data.toString());
});
this.radioProcess.on('exit', (code) => {
console.log('[RADIO+] Процесс завершен с кодом:', code);
this.isPlaying = false;
// Удаляем временный файл
try {
fs.unlinkSync(scriptPath);
} catch (e) {}
});
this.radioProcess.on('error', (err) => {
console.error('[RADIO+] Ошибка запуска:', err.message);
this.isPlaying = false;
});
}
stop() {
if (this.radioProcess) {
console.log('[RADIO+] ⏹️ Остановка радио');
this.radioProcess.kill();
this.radioProcess = null;
}
this.isPlaying = false;
this.currentUrl = null;
this.sessionId = null;
}
setVolume(volume) {
this.volume = Math.max(0, Math.min(100, volume));
console.log('[RADIO+] 🔊 Установка громкости:', this.volume);
// Пробуем nircmd для точного контроля
const nircmdPath = path.join(__dirname, 'tools', 'nircmd.exe');
if (fs.existsSync(nircmdPath)) {
// Устанавливаем громкость для всех PowerShell процессов
spawn(nircmdPath, ['setappvolume', 'powershell.exe', (this.volume / 100).toString()], { stdio: 'ignore' });
console.log('[RADIO+] ✅ Громкость установлена через nircmd');
return;
}
// Если радио играет, перезапускаем с новой громкостью
if (this.isPlaying && this.currentUrl) {
console.log('[RADIO+] 🔄 Перезапуск с новой громкостью...');
const url = this.currentUrl;
this.stop();
setTimeout(() => this.play(url), 1000);
}
}
getStatus() {
return {
isPlaying: this.isPlaying,
currentUrl: this.currentUrl,
volume: this.volume,
sessionId: this.sessionId
};
}
}
module.exports = EnhancedRadioPlayer;