Pull to refresh

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

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

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

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

При обнаружении ошибок пишите в ЛС.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.