Design of Audio Player Using Visual Studio

  • Download Binaries - 7.17 KB
  • Download Source - 9.19 KB

Introduction

I always thought that developing Extensions for Visual Studio is very hard task. And I'm sure it was, but today it's really easy to create your own Extensions and even share them with everyone worldwide.

This was my first experience in developing extensions for Visual Studio and I hope - not the last.

I like listening to Internet radio or music from my PC while working with my code. Sometimes switching between different radio stations (for example when some station goes down) it is difficult because I also have to switch my "context" to find another station.

Then I thought that it would be really cool if I could do this from Visual Studio. It could even increase my productivity! That's how the idea of player extension for Visual Studio came to me.

Prerequisite for Extension Development

For developing Visual Studio 2010 Extensions you will need the following:

  • Visual Studio 2010 RC
  • Visual Studio 2010 SDK RC

Using Extension

Playlists for Player Extension are text files in some strange format (that's because I created it).

Playlist may look like this:

16bit radio >>> http://www.16bit.fm/play/16bit.fm_192.m3u dance radio >>> http://danceradio.ru/playlist160.m3u Dinamyte Radio >>> http://80.254.15.12:8000/listen.pls song 1 >>> D:/0/11.mp3 song 2 >>> D:/0/12.mp3

Where '>>>' is a delimiter. Everything to the left from delimiter is a name of the radio station (song/playlist or anything that can be played by Windows Media Player except video). You can print whatever you like here.

Actual path to the media is placed to the right from the delimiter.

mediaplayerinvisualstudio1.png

First of all you have to create your playlist (in your preferred text editor) then load it with the Player Extension (button 'Load'). Next select media which you want to listen to from the list.

After that you can you standart controls (Play/Pause, Stop, Volume slider).

Developing Media Player Extension for Visual Studio 2010

While developing Player Extension I had to face two problems:

  • How to play media from different sources?
  • How to make player common for all pages (I mean code editors in Visual Studio)?

Ways to solve those problems are discussed in the next chapter

Using the Code

Creating Project

First of all we need create project.

mediaplayerinvisualstudio2.png

Player should be placed to the text editor so we choose Editor Margin from Extensibility menu. I named the project "InternetRadioPlayer." Right after creating the project you'll get a few files that are already written for you.

Most interesting for us now is InternetRadioPlayer.cs and InternetRadioPlayerFactory.cs. InternetRadioPlayerFactory.cs is a factory that creates our controls for each code editor page. We will not change it we will place all useful code to InternetRadioPlayer.cs. But first let's create player class and player control.

Player Class

What do we need to play sound? Yes, the player! Let's create one.

I tried to find a good media library or control in Internet but finally I came out with the simplest solution - using the MediaElement from WPF control library. It can play media from almost any source: single songs, videos, playlists, Internet radio etc.

Now let's create a new class file and name it Player.cs

          using          System;          using          System.Collections.Generic;          using          System.Linq;          using          System.Text;          using          System.Windows.Controls;          using          System.IO;          using          System.Text.RegularExpressions;          namespace          InternetRadioPlayer {          public          class          Player     {          private          MediaElement _player;          public          PlayerState State {          get;          set; }          private          Dictionary<string, string> _playlist =          new          Dictionary<string, />();          private          static          Player _instance;          public          event          EventHandler Changed;          public          Dictionary<string, string> Playlist         {          get          {          return          _playlist;             }         }          public          double          Volume         {          get          {          return          _player.Volume;             }          set          {                 _player.Volume =          value;                 OnChanged();             }         }          public          static          Player Instance         {          get          {          if          (_instance ==          null)                 {                     _instance =          new          Player();                 }          return          _instance;             }         }          public          int          SelectedIndex {          get;          set; }          private          Player()         {             _player =          new          MediaElement();             _player.LoadedBehavior = MediaState.Manual;             _player.UnloadedBehavior = MediaState.Manual;         }          public          void          SetSource(int          index,          string          uri)         {             SelectedIndex = index;             _player.Source =          new          Uri(uri);             State = PlayerState.Stopped;             OnChanged();         }          public          void          Play()         {             _player.Play();             State = PlayerState.Playing;             OnChanged();         }          public          void          Stop()         {             _player.Stop();             State = PlayerState.Stopped;             OnChanged();         }          public          void          Pause()         {             _player.Pause();             State = PlayerState.Paused;             OnChanged();         }          public          void          Unload()         {          if          (State != PlayerState.Stopped)             {                 _player.Stop();             }             State = PlayerState.Unknown;         }          public          void          LoadPlaylist(string          fileName)         {             _playlist.Clear();             string[] lines = File.ReadAllLines(fileName);          foreach          (var          item          in          lines)             {                 string[] str = Regex.Split(item,          "          >>>");                 _playlist.Add(str[0].Trim(), str[1].Trim());             }             OnChanged();         }          private          void          OnChanged()         {          if          (Changed !=          null)             {                 Changed(this,          null);             }         }     }          public          enum          PlayerState     {         Unknown,         Stopped,         Paused,         Playing     } }

Nothing is very hard to understand in this code. The player has four states: Unknown (nothing is loaded yet), Stopped, Paused and Playing. A few methods change player state. The LoadPlayList method loads playlist from selected file.

There is also an event Changed which tells subscribers (player user controls) to update the UI.

Another interesting thing here is a static variable instance. Remember I told you that there was a problem while making player common for all text editor pages.

InternetRadioPlayerFactory creates instances of player control for each page. This means that if we had a standalone player encapsulated in each control we would have the situation when different songs are being played from different pages.

Having static instance of Player and a private constructor don't allow user controls to create new instances of Player.

Player Control

Now let's create a user control for our player. Click "Add new item" and choose User Control (WPF) from WPF tab. Name it PlayerControl.

          <          UserControl                              x:Class          ="          InternetRadioPlayer.PlayerControl"                              xmlns          ="          http://schemas.microsoft.com/winfx/2006/xaml/presentation"                              xmlns:x          ="          http://schemas.microsoft.com/winfx/2006/xaml"                              xmlns:mc          ="          http://schemas.openxmlformats.org/markup-compatibility/2006"                              xmlns:d          ="          http://schemas.microsoft.com/expression/blend/2008"                              mc:Ignorable          ="          d"                              Height          ="          30"                              Width          ="          440"          >          <          Border                              BorderThickness          ="          1"                              CornerRadius          ="          3,3,3,3"                              Width          ="          436"                              Height          ="          30"          >          <          Border.BorderBrush          >          <          SolidColorBrush                              Color          ="          {DynamicResource {x:Static SystemColors.DesktopColorKey}}"          /          >          <          /Border.BorderBrush          >          <          Grid                              Height          ="          30"                              Width          ="          440"                              >          <          ComboBox                              Name          ="          comboBox1"                              Height          ="          20"                              Width          ="          134"                              Margin          ="          179,4,127,6"                              SelectionChanged          ="          comboBox1_SelectionChanged"                              ToolTip          ="          Choose Playlist"                              IsEnabled          ="          False"                              /          >          <          Button                              Content          ="          Play"                              Height          ="          22"                              HorizontalAlignment          ="          Left"                              Margin          ="          5,3,0,5"                              Name          ="          btnPlay"                              VerticalAlignment          ="          Center"                              Width          ="          55"                              Click          ="          btnPlay_Click"                              /          >          <          Button                              Content          ="          Stop"                              Height          ="          22"                              HorizontalAlignment          ="          Left"                              Margin          ="          62,3,0,5"                              Name          ="          btnStop"                              VerticalAlignment          ="          Center"                              Width          ="          55"                              Click          ="          btnStop_Click"                              /          >          <          Button                              Content          ="          Load"                              Height          ="          22"                              HorizontalAlignment          ="          Right"                              Margin          ="          0,3,265,5"                              Name          ="          btnLoad"                              VerticalAlignment          ="          Center"                              Width          ="          55"                              Click          ="          btnLoad_Click"          /          >          <          Slider                              Height          ="          24"                              Margin          ="          313,2,0,0"                              HorizontalAlignment          ="          Left"                              Name          ="          slider1"                              VerticalAlignment          ="          Center"                              Width          ="          121"                              Maximum          ="          1"                              Value          ="          0.5"                              ValueChanged          ="          slider1_ValueChanged"                              /          >          <          /Grid          >          <          /Border          >          <          /UserControl          >        

Everything is really easy here.

And code-behind here does the following:

          using          System;          using          System.Collections.Generic;          using          System.Linq;          using          System.Text;          using          System.Windows;          using          System.Windows.Controls;          using          System.Windows.Data;          using          System.Windows.Documents;          using          System.Windows.Input;          using          System.Windows.Media;          using          System.Windows.Media.Imaging;          using          System.Windows.Navigation;          using          System.Windows.Shapes;          using          Microsoft.VisualStudio.Text.Editor;          using          Microsoft.Win32;          using          System.IO;          using          System.Text.RegularExpressions;          namespace          InternetRadioPlayer {          </          span          >                    </          span          >          public          partial          class          PlayerControl : UserControl     {          private          Player _player;          public          PlayerControl(Player player)         {             _player = player;             _player.Changed +=          new          EventHandler(_player_Changed);             InitializeComponent();         }          void          _player_Changed(object          sender, EventArgs e)         {             UpdateState();         }          private          void          btnPlay_Click(object          sender, RoutedEventArgs e)         {          try          {          if          (_player.State == PlayerState.Playing)                     _player.Pause();          else          _player.Play();                   UpdateButtonContent();             }          catch          (Exception)             {                 MessageBox.Show("          Error");             }         }          private          void          comboBox1_SelectionChanged(object          sender, SelectionChangedEventArgs e)         {          try          {          if          (comboBox1.SelectedValue !=          null)                 {          if          (comboBox1.SelectedIndex != _player.SelectedIndex)                     {                         _player.SetSource(comboBox1.SelectedIndex,                            comboBox1.SelectedValue.ToString());                         _player.Play();                                                  UpdateButtonContent();                     }                 }             }          catch          (Exception)             {                 MessageBox.Show("          Error loading stream");             }         }          private          void          btnLoad_Click(object          sender, RoutedEventArgs e)         {             _player.Unload();             OpenFileDialog dlg =          new          OpenFileDialog();          if          (dlg.ShowDialog().Value)             {          try          {                     _player.LoadPlaylist(dlg.FileName);                     comboBox1.ItemsSource = _player.Playlist;                       comboBox1.DisplayMemberPath =          "          Key";                     comboBox1.SelectedValuePath =          "          Value";                     comboBox1.SelectedIndex =          0;                       _player.SetSource(comboBox1.SelectedIndex,                        comboBox1.SelectedValue.ToString());                       UpdateButtonContent();                     comboBox1.IsEnabled =          true;                 }          catch          (Exception)                 {                     MessageBox.Show("          Error while loading playlist");                 }             }         }          private          void          btnStop_Click(object          sender, RoutedEventArgs e)         {             _player.Stop();             UpdateButtonContent();         }          private          void          slider1_ValueChanged(object          sender, RoutedPropertyChangedEventArgs<double /> e)         {             _player.Volume = slider1.Value;         }          private          void          UpdateState()         {             slider1.Value = _player.Volume;               comboBox1.ItemsSource = _player.Playlist;             comboBox1.DisplayMemberPath =          "          Key";             comboBox1.SelectedValuePath =          "          Value";             comboBox1.Items.Refresh();          if          (comboBox1.SelectedIndex != _player.SelectedIndex)             {                 comboBox1.SelectedIndex = _player.SelectedIndex;             }               UpdateButtonContent();         }          private          void          UpdateButtonContent()         {             btnPlay.IsEnabled =          false;             btnStop.IsEnabled =          false;          switch          (_player.State)             {          case          PlayerState.Stopped:                     btnPlay.IsEnabled =          true;                     btnPlay.Content =          "          Play";          break;          case          PlayerState.Playing:                     btnPlay.IsEnabled =          true;                     btnStop.IsEnabled =          true;                     btnPlay.Content =          "          Pause";          break;          case          PlayerState.Paused:                     btnPlay.IsEnabled =          true;                     btnStop.IsEnabled =          true;                     btnPlay.Content =          "          Play";          break;          case          PlayerState.Unknown:          break;             }         }     } }

PlayerControl takes Player instance as a constructor parameter, we could just get it from Player.Instance but that doesn't matter.

Summary

At this moment we came to final solution structure

mediaplayerinvisualstudio3.png

The last thing we have to do is adding some code to our InternetRadioPlayer.cs. In the next code we are going to create PlayerControl controls and add them to the text editor.

          using          System;          using          System.Windows.Controls;          using          System.Windows.Media;          using          Microsoft.VisualStudio.Text.Editor;          namespace          InternetRadioPlayer {          </          span          >                    </          span          >          class          InternetRadioPlayer : Canvas, IWpfTextViewMargin     {          public          const          string          MarginName =          "          InternetRadioPlayer";          private          IWpfTextView _textView;          private          bool          _isDisposed =          false;          private          PlayerControl _player =          new          PlayerControl(Player.Instance);          </          span          >          </          span          >          </          span          >          </          span          >          </          span          >          </          span          >          public          InternetRadioPlayer(IWpfTextView textView)         {             _textView = textView;          this.Height =          30;          this.ClipToBounds =          true;                         this.Children.Add(_player);         }          private          void          ThrowIfDisposed()         {          if          (_isDisposed)          throw          new          ObjectDisposedException(MarginName);         }          #region IWpfTextViewMargin Members                    </          span          >          </          span          >                            </          span          >          public          System.Windows.FrameworkElement VisualElement         {                                    get          {                 ThrowIfDisposed();          return          this;             }         }          

0 Response to "Design of Audio Player Using Visual Studio"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel