- Клиентская часть Vue 3 + Vite - Серверная часть Node.js + WebSocket - Система авторизации и смен - Управление игровыми портами - Поддержка тем (светлая/темная) - Адаптивный дизайн 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
171 lines
6.8 KiB
JavaScript
171 lines
6.8 KiB
JavaScript
// Простой радио плеер для Windows используя PowerShell и Windows Media Player
|
||
const { spawn } = require('child_process');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
class SimpleRadioPlayer {
|
||
constructor() {
|
||
this.radioProcess = null;
|
||
this.isPlaying = false;
|
||
this.volume = 70;
|
||
this.currentUrl = null;
|
||
this.playerPid = null;
|
||
}
|
||
|
||
play(url) {
|
||
this.stop();
|
||
|
||
// Добавляем протокол если его нет
|
||
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||
url = 'http://' + url;
|
||
}
|
||
|
||
console.log('[RADIO] 📻 Запуск радио:', url);
|
||
this.currentUrl = url;
|
||
|
||
// PowerShell скрипт для воспроизведения через Windows Media Player
|
||
const script = `
|
||
Add-Type -AssemblyName presentationCore
|
||
$player = New-Object System.Windows.Media.MediaPlayer
|
||
$player.Open([System.Uri]"${url}")
|
||
$player.Volume = ${this.volume / 100}
|
||
$player.Play()
|
||
|
||
# Выводим PID процесса
|
||
Write-Host "PID:$PID"
|
||
|
||
# Держим процесс активным и слушаем команды
|
||
while ($true) {
|
||
Start-Sleep -Seconds 1
|
||
}`;
|
||
|
||
// Сохраняем скрипт во временный файл
|
||
const scriptPath = path.join(__dirname, 'temp_radio.ps1');
|
||
fs.writeFileSync(scriptPath, script);
|
||
|
||
// Запускаем PowerShell
|
||
this.radioProcess = spawn('powershell', [
|
||
'-ExecutionPolicy', 'Bypass',
|
||
'-File', scriptPath
|
||
]);
|
||
|
||
this.radioProcess.stdout.on('data', (data) => {
|
||
const output = data.toString();
|
||
console.log('[RADIO] Вывод:', output);
|
||
|
||
// Извлекаем PID
|
||
const pidMatch = output.match(/PID:(\d+)/);
|
||
if (pidMatch) {
|
||
this.playerPid = pidMatch[1];
|
||
console.log('[RADIO] PID процесса:', this.playerPid);
|
||
}
|
||
});
|
||
|
||
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.isPlaying = true;
|
||
}
|
||
|
||
stop() {
|
||
if (this.radioProcess) {
|
||
console.log('[RADIO] ⏹️ Остановка радио');
|
||
this.radioProcess.kill();
|
||
this.radioProcess = null;
|
||
}
|
||
this.isPlaying = false;
|
||
this.currentUrl = null;
|
||
this.playerPid = 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)) {
|
||
if (this.playerPid) {
|
||
// Устанавливаем громкость для конкретного PID
|
||
spawn(nircmdPath, ['setappvolume', `/${this.playerPid}`, (this.volume / 100).toString()], {
|
||
stdio: 'ignore',
|
||
windowsHide: true
|
||
});
|
||
console.log('[RADIO] ✅ Громкость процесса установлена через nircmd для PID:', this.playerPid);
|
||
} else {
|
||
// Пробуем установить для всех процессов PowerShell
|
||
spawn(nircmdPath, ['setappvolume', 'powershell.exe', (this.volume / 100).toString()], {
|
||
stdio: 'ignore',
|
||
windowsHide: true
|
||
});
|
||
console.log('[RADIO] ✅ Громкость установлена для всех процессов PowerShell');
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Если nircmd нет, используем VBScript для изменения громкости MediaPlayer
|
||
if (this.isPlaying && this.currentUrl) {
|
||
console.log('[RADIO] 🔄 Перезапускаем с новой громкостью...');
|
||
const url = this.currentUrl;
|
||
this.stop();
|
||
setTimeout(() => this.play(url), 500);
|
||
return;
|
||
}
|
||
|
||
// Фолбэк - системная громкость через PowerShell
|
||
console.log('[RADIO] ⚠️ Устанавливаем системную громкость (nircmd не найден)');
|
||
const volumeScript = `
|
||
Add-Type -TypeDefinition @'
|
||
using System.Runtime.InteropServices;
|
||
[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("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||
interface IMMDevice {
|
||
int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
|
||
}
|
||
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||
interface IMMDeviceEnumerator {
|
||
int f();
|
||
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
|
||
}
|
||
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
|
||
public class Audio {
|
||
static IAudioEndpointVolume Vol() {
|
||
var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
|
||
IMMDevice dev = null;
|
||
Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(0, 1, out dev));
|
||
IAudioEndpointVolume epv = null;
|
||
var epvid = typeof(IAudioEndpointVolume).GUID;
|
||
Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, 23, 0, out epv));
|
||
return epv;
|
||
}
|
||
public static void SetVolume(float level) {
|
||
Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(level, System.Guid.Empty));
|
||
}
|
||
}
|
||
'@
|
||
[Audio]::SetVolume(${this.volume / 100})`;
|
||
|
||
spawn('powershell', ['-Command', volumeScript], { stdio: 'ignore' });
|
||
}
|
||
}
|
||
|
||
module.exports = SimpleRadioPlayer; |