Лабораторный практикум 4
Лабораторная работа №18. Проигрыватель музыки
Задание
Создать приложение для Windows Phone 7, проигрывающее музыку в фоне. Предусмотреть возможность перехода к предыдущей/следующей песне и постановки на паузу. Добавить для приложения тайл, который будет меняться при проигрывании песни.
Освоение
- фоновое воспроизведение музыки
- тайлы
Описание
Создадим новый проект Silverlight for Windows Phone – Windows Phone Application.
Добавим в него папку Audio, а в нее несколько аудио-файлов, формат которых поддерживает Windows Phone 7. Установим значение свойства "Build Action" в "Content", а "Copy to Output Directory" в "Copy if newer".
Добавим два изображения размера 173x173 (для тайлов). Назовем их, например, "Tile1.png" и "Tile2.png". Установим для данных изображений свойство "Build Action" в "Content".
Примечание: тайлы – это изображения, отображающиеся на главной странице Windows Phone 7. Они могут иметь пояснительные надписи и обратную сторону – другое изображение, которое будет периодически появляться. Для того чтобы добавить тайл приложения на главную страницу, в списке приложений нажмите на ваше приложение и удерживайте. В появившемся контекстном меню выберете "pin to start" Рис. 5.3 :
В код главной страницы добавим функцию установки тайла. При проигрывании мелодии в параметр IsPlay будем передавать true, в противном случае – false.
private void SetTile(bool IsPlay = false)
{
ShellTile apptile = ShellTile.ActiveTiles.First();
StandardTileData appTileData = new StandardTileData();
appTileData.Title = "";
appTileData.Count = 0;
if (IsPlay)
{
appTileData.BackgroundImage = new Uri("/Tile2.png", UriKind.RelativeOrAbsolute);
}
else
{
appTileData.BackgroundImage = new Uri("/Tile1.png", UriKind.RelativeOrAbsolute);
}
apptile.Update(appTileData);
}
SetTile();
Также в коде должна быть добавлена директива:
using Microsoft.Phone.Shell;
Теперь добавим в решение (solution) новый проект Silverlight for Windows Phone – Windows Phone Audio Playback Agent. В наш основной проект добавим ссылку на данный проект: Add Reference… – Projects - <имя проекта аудио-плейера>.
В файл AudioPlayer.cs добавим директиву:
using System.Collections.Generic;
Затем в класс добавим две глобальные переменные: номер текущей песни и список песен. В список песен сразу добавим имена файлов наших песен. Также можно указать название, автора и альбом.
private static int currentTrackNumber = 0;
private static List<AudioTrack>_playList = new List<AudioTrack>
{
new AudioTrack(new Uri("Elena Gheorghe - Balkan Girls.mp3", UriKind.Relative),
"Balkan Girls",
"Elena Gheorghe",
"Eurovision 2010",
null),
new AudioTrack(new Uri("Lara Fabian - I Guess I Loved You.mp3", UriKind.Relative),
"I Guess I Loved You",
"Lara Fabian",
"Unknown",
null),
new AudioTrack(new Uri("velvet-prodavec_kukol.mp3", UriKind.Relative),
"Продавец кукол",
"Вельвет",
"Unknown",
null),
//remote URI
new AudioTrack(new Uri("http://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute),
"Episode 29",
"Windows Phone Radio",
"Windows Phone Radio Podcast",
null)
};
private void PlayNextTrack(BackgroundAudioPlayer player)
{
if (++currentTrackNumber >= _playList.Count)
{
currentTrackNumber = 0;
}
PlayTrack(player);
}
private void PlayPreviousTrack(BackgroundAudioPlayer player)
{
if (--currentTrackNumber < 0)
{
currentTrackNumber = _playList.Count - 1;
}
PlayTrack(player);
}
private void PlayTrack(BackgroundAudioPlayer player)
{
// Sets the track to play. When the TrackReady state is received,
// playback begins from the OnPlayStateChanged handler.
player.Track = _playList[currentTrackNumber];
}
Изменим функции OnPlayStateChanged() и OnUserAction() :
protected override void OnPlayStateChanged(BackgroundAudioPlayer player,
AudioTrack track, PlayState playState)
{
switch (playState)
{
case PlayState.TrackReady:
// The track to play is set in the PlayTrack method.
player.Play();
break;
case PlayState.TrackEnded:
PlayNextTrack(player);
break;
}
NotifyComplete();
}
protected override void OnUserAction(BackgroundAudioPlayer player,
AudioTrack track, UserAction action, object param)
{
switch (action)
{
case UserAction.Play:
if (isPaused)
player.Play();
else
PlayTrack(player);
isPaused = false;
break;
case UserAction.Pause:
player.Pause();
isPaused = true;
break;
case UserAction.SkipPrevious:
PlayPreviousTrack(player);
isPaused = false;
break;
case UserAction.SkipNext:
PlayNextTrack(player);
isPaused = false;
break;
}
NotifyComplete();
}
Теперь откроем файл App.xaml основного проекта.
Добавим 2 директивы:
using System.IO.IsolatedStorage; using System.Windows.Resources;
Поскольку фоновый аудио-проигрыватель умеет воспроизводить музыку только из изолированного проигрывателя, добавим в класс App функцию, которая будет копировать в проигрыватель песни из ресурсов. Вызов функции добавим в конструктор класса.
private void CopyToIsolatedStorage()
{
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
string[] files = new string[] { "Elena Gheorghe - Balkan Girls.mp3",
"Lara Fabian - I Guess I Loved You.mp3",
"velvet-prodavec_kukol.mp3" };
foreach (var _fileName in files)
{
if (!storage.FileExists(_fileName))
{
string _filePath = "Audio/" + _fileName;
StreamResourceInfo resource = Application.GetResourceStream(new Uri(_filePath, UriKind.Relative));
using (IsolatedStorageFileStream file = storage.CreateFile(_fileName))
{
int chunkSize = 4096;
byte[] bytes = new byte[chunkSize];
int byteCount;
while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0)
{
file.Write(bytes, 0, byteCount);
}
}
}
}
}
}
Вернемся к главной странице. В файл разметки добавим несколько текстовых блоков для вывода информации о текущей песне и меню, состоящее из 3 кнопок: назад, воспроизведение/пауза, вперед.
Теперь перейдем к коду главной страницы. Добавим директиву:
using Microsoft.Phone.BackgroundAudio;
В конструкторе подпишемся на изменение состояния воспроизведения:
BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);
Добавим обработчик события:
void Instance_PlayStateChanged(object sender, EventArgs e)
{
switch (BackgroundAudioPlayer.Instance.PlayerState)
{
case PlayState.Playing:
((ApplicationBarIconButton)ApplicationBar.Buttons[1])
.IconUri = new Uri(PATH_TO_PAUSE_IMG, UriKind.Relative);
SetTile(true);
break;
case PlayState.Paused:
case PlayState.Stopped:
((ApplicationBarIconButton)ApplicationBar.Buttons[1])
.IconUri = new Uri(PATH_TO_PLAY_IMG, UriKind.Relative);
SetTile(false);
break;
}
if (null != BackgroundAudioPlayer.Instance.Track)
{
txtAuthor.Text = BackgroundAudioPlayer.Instance.Track.Artist;
txtAlbum.Text = BackgroundAudioPlayer.Instance.Track.Album;
txtDur.Text = String.Format("{0:00}", BackgroundAudioPlayer.Instance.Track.Duration.Minutes) + ":" +
String.Format("{0:00}", BackgroundAudioPlayer.Instance.Track.Duration.Seconds);
PageTitle.Text = BackgroundAudioPlayer.Instance.Track.Title;
...
}
}
Обработчики нажатий на кнопки меню:
private void Menu1_Click(object sender, EventArgs e)
{
BackgroundAudioPlayer.Instance.SkipPrevious();
}
private void Menu2_Click(object sender, EventArgs e)
{
if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)
{
BackgroundAudioPlayer.Instance.Pause();
}
else
{
BackgroundAudioPlayer.Instance.Play();
}
}
private void Menu3_Click(object sender, EventArgs e)
{
BackgroundAudioPlayer.Instance.SkipNext();
}
При закрытии приложения музыка будет продолжать воспроизводиться. При повторном открытии приложения будем выдавать пользователю информацию о текущей песне. Для этого переопределим метод OnNavigatedTo() главной страницы:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//если при хагрузке приложения уже играет музыка
if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)
{
txtAuthor.Text = BackgroundAudioPlayer.Instance.Track.Artist;
txtAlbum.Text = BackgroundAudioPlayer.Instance.Track.Album;
txtDur.Text = String.Format("{0:00}", BackgroundAudioPlayer.Instance.Track.Duration.Minutes) + ":" +
String.Format("{0:00}", BackgroundAudioPlayer.Instance.Track.Duration.Seconds);
PageTitle.Text = BackgroundAudioPlayer.Instance.Track.Title;
((ApplicationBarIconButton)ApplicationBar.Buttons[1])
.IconUri = new Uri(PATH_TO_PAUSE_IMG, UriKind.Relative);
...
}
else
{
txtAuthor.Text = "";
txtAlbum.Text = "";
txtDur.Text = "";
PageTitle.Text = PAGE_DEFAULT_TITLE_TEXT;
((ApplicationBarIconButton)ApplicationBar.Buttons[1]).IconUri =
new Uri(PATH_TO_PLAY_IMG, UriKind.Relative);
...
}
}
