Как стать автором
Обновить

Как я создавал приложение для прослушивания интернет радио

Итак, доброго времени суток, дамы и господа! Сегодня мы рассмотрим историю о том, как я создавал приложение для прослушивания интернет радио.

Первая версия программы была сделана ужасно и выглядела так:

image

Сделал её когда опыта программирования и знаний было немного очень мало. Программа написана на C#, проект типа Windows Forms. О существовании WPF я знал, но толком в нем не разбирался. Программа создана просто – перетаскал на форму PictureBox-ы, поставил кнопку Play/Pause, Label-ы, ListBox, а полосу регулирования громкости скачал с CodeProject, подключил библиотеку Windows Media Player.

Код приложения – это сплошные проверки “if”. Знаю, руки бы мне за такое оторвать! Например, событие происходящее при нажатии на кнопку Play:

if (isPlaying == true)
{
try
{
wmp.controls.stop();
MainButton.BackgroundImage = Properties.Resources.play;
isPlaying = false;
label1.Text = wmp.currentPlaylist.Item[0].name;
if (Properties.Settings.Default.Theme == "Orange")
{
PlayState.BackgroundImage = Image.FromFile("Skins/Orange/PlayingSmall_Playing.png");
}
else if (Properties.Settings.Default.Theme == "Aqua")
{
PlayState.BackgroundImage = Image.FromFile("Skins/Aqua/PlayingSmall_Playing.png");
}
else if (Properties.Settings.Default.Theme == "Red")
{
PlayState.BackgroundImage = Image.FromFile("Skins/Red/PlayingSmall_Playing.png");
}
}
catch
{
MessageBox.Show("Возникла непредвиденная ошибка.Отсутсвует интернет подключение.\nПроверьте интернет подключение или перезапустите приложение", "Ошибка");
}
}
else if (isPlaying == false)
{
try
{
wmp.controls.play();
MainButton.BackgroundImage = Properties.Resources.pause;
isPlaying = true;
label1.Text = wmp.currentPlaylist.Item[0].name;
if (Properties.Settings.Default.Theme == "Orange")
{
PlayState.BackgroundImage = Image.FromFile("Skins/Orange/PlayingSmall_Pause.png");
}
else if (Properties.Settings.Default.Theme == "Aqua")
{
PlayState.BackgroundImage = Image.FromFile("Skins/Aqua/PlayingSmall_Pause.png");
}
else if (Properties.Settings.Default.Theme == "Red")
{
PlayState.BackgroundImage = Image.FromFile("Skins/Red/PlayingSmall_Pause.png");
}
}
catch
{
MessageBox.Show("Возникла непредвиденная ошибка.Отсутсвует интернет подключение.\nПроверьте интернет подключение или перезапустите приложение", "Ошибка");
}
}


Или проверка изменения радиостанции:

try
{
if (RadioListView.SelectedItems[0].Text == "EuropaPlus")
{
wmp.URL = "http://cast.radiogroup.com.ua:8000/europaplus";
wmp.controls.play();
Properties.Settings.Default.LastRadio = "http://cast.radiogroup.com.ua:8000/europaplus";
label1.Text = wmp.currentPlaylist.Item[0].name;
Properties.Settings.Default.Save();
}
else if (RadioListView.SelectedItems[0].Text == "Наше Радио")
{
wmp.URL = "http://cast.radiogroup.com.ua:8000/nashe";
wmp.controls.play();
Properties.Settings.Default.LastRadio = "http://cast.radiogroup.com.ua:8000/nashe";
label1.Text = wmp.currentPlaylist.Item[0].name;
Properties.Settings.Default.Save();
}
……


Мало того код ужасный, плюс ещё имеется один большой недостаток, а именно, если какая-то радиостанция уйдёт в небытие, то её никак не убрать из программы, разве что подправить код и заново скомпилировать.

Но об этом я тогда даже не задумывался, так как радовался, что сделал, наверное, что-то стоящее и интересное.

Прошло некоторое время. Я учился программировать, экспериментировал. Очередной раз, когда задался вопросом «что бы ещё программировать?» я наткнулся на проект этого убогого радио и решил, что надо переписать программу надо сделать версию получше.

Создал новый проект Windows Forms. Поставил на форму кнопку, пару Label-ов, TabControl, ListBox, тот же самый Slider. Добавил новое окно настроек. Воспроизведение происходит по-прежнему с помощью библиотеки Windows Media Player.

Теперь уже событие клика кнопки Play/Pause выглядит так:

if (!isPlaying)
{
play.BackgroundImage = Properties.Resources.play;
isPlaying = true;
player.controls.pause();
}
else if (isPlaying)
{
play.BackgroundImage = Properties.Resources.pause;
isPlaying = false;
player.controls.play();
}


Загрузка радиостанций идёт из xml файла. То есть теоретически каждый желающий сможет добавить неограниченное количество радиостанций. Структура xml файла:

EuropaPlus
Наше Радио
Premium
EuropaPlus2
RRadio
Kazantip
Kiss FM
Radio Record
Horizon FM
Best FM
Abc Christmas



А вот и код который загружает радиостанции в ListBox:

string fileName = "stations.xml";

public void LoadStations()
{
if (File.Exists(fileName))
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);
XmlNodeList stationNodes = xmlDoc.SelectNodes("//stations/station");
foreach (XmlNode stationNode in stationNodes)
{
string name = stationNode.InnerText;
//FullList – это listbox
FullList.Items.Add(name);
}
xmlDoc.Save(fileName);
}
else
{
MessageBox.Show("Не найдены радиостанции.Увы мой господин.\nНе судьба!Загрузите их с сайта разработчика или переустановите программу.");
}
}


Вот что в итоге получилось:

image

Этому результату я был очень рад.

Опять пролетело какое-то время. Я научился делать приложения для Windows Phone и, соответственно, уже понимал что-то в WPF.
И вот теперь наступает, на мой взгляд, самая интересная часть этой статьи.

Совсем недавно я встретил программу плеер VK – Meridian. Дизайн этой программы мне очень понравился. И тут я задался вопросом: «Почему бы не сделать программу Radio с таким же дизайном, ну или хотя бы что-то подобное?». К тому же был выложен исходник этой программы, которую я попытался изучить. Но сначала ничего дельного из этого не вышло. Пришлось искать. Поискав в google, наткнулся на статью на хабре. Скачал проект.

Создал новый проект WPF. Для приведения окна в желаемый вид добавил в проект скачанные файлы и привязал стиль к главному окну приложения. Поменял цвет окна, расположение значка, добавил новую кнопку “always on top” и вот что в итоге получилось:

image

Выглядит неплохо.

Для того, чтобы приложение было удобным и функциональным, решил разделить главное окно на 3 части. В первой части будут типы радиостанций, во второй список радиостанций относящиеся к определенному типу и, наконец, в третьей части будет логотип радиостанции. Стиль кнопки play/pause, volume, settings, listbox и scrollbar взял из исходников того самого Meridian Vk player.

После долгих мучений был получен такой код:

<Window x:Class="Radio.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Radio.Controls"
Title="Radio"
Height="460"
Width="620"
MinHeight="400"
MinWidth="510"
Icon="/icon.ico"
WindowStartupLocation="CenterScreen"
Style="{StaticResource VS2012WindowStyle}"
Loaded="Window_Loaded">

<Window.TaskbarItemInfo>
<TaskbarItemInfo x:Name="TaskbarItem">
<TaskbarItemInfo.ThumbButtonInfos>
<ThumbButtonInfo x:Name="TaskbarPlayButton" ImageSource="/Radio;component/Images/Taskbar/play_thumb.png" Click="TaskbarPlayButton_Click"/>
<ThumbButtonInfo x:Name="TaskbarPauseButton" ImageSource="/Radio;component/Images/Taskbar/pause_thumb.png" Click="TaskbarPauseButton_Click"/>
</TaskbarItemInfo.ThumbButtonInfos>

</Window.TaskbarItemInfo>

<Grid x:Name=«MainContentPanel» >
<Grid.ColumnDefinitions>
/>
/>
/>
</Grid.ColumnDefinitions>



<Grid x:Name=«LeftContentPanel»>
<Grid.RowDefinitions>
/>
/>
</Grid.RowDefinitions>

<ListBox ScrollViewer.HorizontalScrollBarVisibility=«Disabled» x:Name=«StationTypeList» Grid.Row=«0» Background=«Transparent» Style="{StaticResource CommonListBoxStyle}" ItemContainerStyle="{StaticResource SimpleListBoxItem}" SelectionChanged=«StationTypeList_SelectionChanged»>
<ListBox.ItemTemplate>
/>

</ListBox.ItemTemplate>


<Border Grid.Row=«1» BorderThickness=«0,1,0,0» BorderBrush="#828790">
<Grid x:Name=«ControlsPanel» Height=«100» >
<Grid.ColumnDefinitions>
/>
/>
/>
</Grid.ColumnDefinitions>

<StackPanel Grid.Column=«0»>
<Button x:Name=«SettingsButton» HorizontalAlignment=«Center» Height=«18» Width=«18» Margin=«12,41,0,0» Style="{StaticResource SettingsButtonStyle}" Click=«SettingsButton_Click»/>


<StackPanel Grid.Column=«1»>
/>


<StackPanel Grid.Column=«2»>
<controls:VolumeControl x:Name=«VolumeController» Volume=«100» Margin=«0,35,0,0» />








<Grid x:Name=«RightContentPannel» Grid.Column=«1» Background=«Transparent»>


<ListBox ScrollViewer.HorizontalScrollBarVisibility=«Disabled» x:Name=«StationsList» Grid.Row=«0» Background=«Transparent» Style="{StaticResource CommonListBoxStyle2}" ItemContainerStyle="{StaticResource SimpleListBoxItem}" SelectionChanged=«StationsList_SelectionChanged»>
<ListBox.ItemTemplate>
/>

</ListBox.ItemTemplate>




<Border Grid.Column=«2» BorderThickness=«1,0,0,0» BorderBrush="#828790" >
<Grid Grid.Row=«0» >
<Grid.RowDefinitions>
/>
/>
</Grid.RowDefinitions>

<Image x:Name=«StationImageA» Margin=«15,5,15,5» Grid.Row=«0» Source=«Images/splash.png» Stretch=«Fill»/>
<TextBlock x:Name=«StationNameA» Grid.Row=«1» Text="" FontSize=«17» Foreground="#007ACC" FontWeight=«ExtraBold» Margin=«15,0,5,0»/>
<TextBlock x:Name=«StationMusicA» Grid.Row=«1» Text="" FontSize=«17» Foreground=«White» Margin=«15,25,0,0» TextWrapping=«Wrap»/>







Результат:

image

Опять же чего-то не хватает, не так ли? Слишком серо и не интересно. Поэтому решил добавить фоновые картинки для каждой отдельной радиостанции и для общего приложения. Каждый тип радиостанций(список слева) обладает своей фоновой картинкой. Все названия типов радиостанций записаны в отдельный xml файл — stations.xml и для каждого типа свой xml файл уже с радиостанциями.

Это структура файла stations.xml:

<?xml version="1.0" encoding="utf-8"?>
<stations version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
Club
Stations/club.xml
Images/StationTypes/club.png

Pop
Stations/pop.xml
Images/StationTypes/pupmusic.png

Rap/HipHop/RnB
Stations/rap_hiphop.xml
Images/StationTypes/rap.png

Игровые
Stations/gaming.xml
Images/StationTypes/game.png

……


К примеру структура файла club.xml:

<?xml version="1.0" encoding="utf-8"?>
<stations version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
161FM
stream.161.fm
:8000/256
Images/Stations/club/161fm.png

1Mix Radio – EDM Stream
georgios.1mix.co.uk:8022/;stream.nsv
Images/Stations/club/1mixEDM.png

ElectroPOP
pub5.di.fm/di_electropop


Shtorm.FM клубный
live.shtorm.fm:8000/mp3
Images/Stations/club/shtormclub.png

…..


При желании каждый сможет добавить свои разделы, радиостанции и их картинки.
В результате получилось это:

image

Для воспроизведения радиостанции была выбрана библиотека Bass.Net. Важной отличительной способностью это библиотеки в том, что она умеет показывать имя текущей песни. Решил ее использовать. Но с самого начала возникли проблемы. При выборе радиостанции окно застревало на несколько секунд. Понятно, что происходит подключение к интернет радиостанции, загрузка и наконец его воспроизведение. Пришлось сделать событие воспроизведения радиостанции через BackgroundWorker. И всё заработало должным образом. Ниже представлены скрины программы.

image
image
image
image
image
image

При обнаружении ошибок пишите в ЛС.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.