Files
vue-pult/server/simple-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

171 lines
6.8 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.
// Простой радио плеер для 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;