Лабораторный практикум 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); ... } }