197 lines
7.1 KiB
C#
197 lines
7.1 KiB
C#
using System.Net;
|
||
using System.Text;
|
||
using NAudio.Wave;
|
||
|
||
class Program
|
||
{
|
||
private static WaveOutEvent? outputDevice;
|
||
private static MediaFoundationReader? audioStream;
|
||
private static bool isPaused = false;
|
||
private static float volume = 0.5f;
|
||
private static bool isRunning = true;
|
||
private static string streamUrl = "";
|
||
private static string currentTrack = "Неизвестно";
|
||
|
||
static void Main()
|
||
{
|
||
Console.Title = "Radio CLI";
|
||
Console.CursorVisible = false;
|
||
Console.WindowHeight = 7;
|
||
Console.WindowWidth = 60;
|
||
|
||
SelectStation();
|
||
|
||
Thread metadataThread = new Thread(GetStreamMetadata) { IsBackground = true };
|
||
metadataThread.Start();
|
||
|
||
try
|
||
{
|
||
StartPlayback();
|
||
|
||
while (isRunning)
|
||
{
|
||
DisplayCompactUI();
|
||
var key = Console.ReadKey(true).Key;
|
||
switch (key)
|
||
{
|
||
case ConsoleKey.P:
|
||
TogglePause();
|
||
break;
|
||
case ConsoleKey.Add:
|
||
case ConsoleKey.OemPlus:
|
||
AdjustVolume(0.05f);
|
||
break;
|
||
case ConsoleKey.Subtract:
|
||
case ConsoleKey.OemMinus:
|
||
AdjustVolume(-0.05f);
|
||
break;
|
||
case ConsoleKey.Q:
|
||
isRunning = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Ошибка: {ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
StopPlayback();
|
||
Console.CursorVisible = true;
|
||
Console.WriteLine("\nРадио остановлено. Нажмите любую клавишу...");
|
||
Console.ReadKey();
|
||
}
|
||
}
|
||
|
||
static void SelectStation()
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("Выберите радиостанцию:");
|
||
Console.WriteLine("1) DALA FM (http://178.88.167.62:8080/DALA_320)");
|
||
Console.WriteLine("2) Руки Вверх! (https://stream03.pcradio.ru/Ruki_Vverh-med)");
|
||
Console.WriteLine("3) Дорожное Радио (http://dorognoe.hostingradio.ru:8000/radio)");
|
||
Console.WriteLine("4) Ввести свою ссылку");
|
||
Console.Write("Введите номер (1-4): ");
|
||
|
||
string choice = Console.ReadLine() ?? "";
|
||
switch (choice)
|
||
{
|
||
case "1":
|
||
streamUrl = "http://178.88.167.62:8080/DALA_320";
|
||
break;
|
||
case "2":
|
||
streamUrl = "https://stream03.pcradio.ru/Ruki_Vverh-med";
|
||
break;
|
||
case "3":
|
||
streamUrl = "http://dorognoe.hostingradio.ru:8000/radio";
|
||
break;
|
||
case "4":
|
||
Console.Write("Введите ссылку на поток: ");
|
||
streamUrl = Console.ReadLine() ?? "";
|
||
break;
|
||
default:
|
||
Console.WriteLine("Некорректный ввод, попробуйте снова.");
|
||
SelectStation();
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void StartPlayback()
|
||
{
|
||
try
|
||
{
|
||
audioStream = new MediaFoundationReader(streamUrl);
|
||
outputDevice = new WaveOutEvent();
|
||
outputDevice.Init(audioStream);
|
||
outputDevice.Volume = volume;
|
||
outputDevice.Play();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Ошибка воспроизведения: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
static void DisplayCompactUI()
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("┌──────────────────────────────────────────────┐");
|
||
Console.WriteLine("│ DALA FM - Народное радио │");
|
||
Console.WriteLine("├──────────────────────────────────────────────┤");
|
||
Console.WriteLine($"│ Статус: {(isPaused ? "Пауза" : "Играет").PadRight(8)} Громкость: {(int)(volume * 100)}% │");
|
||
Console.WriteLine("├──────────────────────────────────────────────┤");
|
||
Console.WriteLine($"│ Сейчас играет: {currentTrack.PadRight(30)} │");
|
||
Console.WriteLine("├──────────────────────────────────────────────┤");
|
||
Console.WriteLine("│ P:Пауза +/-:Громкость Q:Выход │");
|
||
Console.WriteLine("└──────────────────────────────────────────────┘");
|
||
}
|
||
|
||
static void TogglePause()
|
||
{
|
||
if (outputDevice == null) return;
|
||
|
||
if (isPaused)
|
||
{
|
||
outputDevice.Play();
|
||
isPaused = false;
|
||
}
|
||
else
|
||
{
|
||
outputDevice.Pause();
|
||
isPaused = true;
|
||
}
|
||
}
|
||
|
||
static void AdjustVolume(float delta)
|
||
{
|
||
if (outputDevice == null) return;
|
||
|
||
volume = Math.Clamp(volume + delta, 0f, 1f);
|
||
outputDevice.Volume = volume;
|
||
}
|
||
|
||
static void StopPlayback()
|
||
{
|
||
outputDevice?.Stop();
|
||
outputDevice?.Dispose();
|
||
audioStream?.Dispose();
|
||
}
|
||
|
||
static void GetStreamMetadata()
|
||
{
|
||
try
|
||
{
|
||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(streamUrl);
|
||
request.Headers.Add("Icy-MetaData", "1");
|
||
request.Timeout = 5000;
|
||
|
||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||
using (Stream stream = response.GetResponseStream())
|
||
{
|
||
if (stream == null) return;
|
||
byte[] buffer = new byte[4096];
|
||
int bytesRead;
|
||
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0 && isRunning)
|
||
{
|
||
string responseString = Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||
if (responseString.Contains("StreamTitle='"))
|
||
{
|
||
int start = responseString.IndexOf("StreamTitle='") + 13;
|
||
int end = responseString.IndexOf("';", start);
|
||
if (end > start)
|
||
{
|
||
currentTrack = responseString[start..end];
|
||
}
|
||
}
|
||
Thread.Sleep(2000);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception)
|
||
{
|
||
currentTrack = "Не удалось получить метаданные";
|
||
}
|
||
}
|
||
}
|