[Desenvolvimento] Como desenvolver uma APP Windows Phone para rádio online via Shoutcast

6

sc-logoOlá pessoal, tudo bom?

Nesse post demonstro como desenvolver uma APP para Windows Phone onde você possa ouvir uma rádio online que esteja hospedada no serviço Shoutcast.

Codeplex

No site do Codeplex há vários projetos OpenSource para acesso ao stream do servidor Shoutcast, sendo que o utilizado para esse exemplo chama-se Shoutcast MediaStreamSource. Faça o download do mesmo para que posteriormente ele seja integrado/referenciado ao seu projeto do Windows Phone.

Será necessário compilar o projeto citado acima para que o mesmo gere a DLL com as classes que iremos precisar.

Sua APP – XAML

No Visual Studio, crie uma APP para Windows Phone e nela faça referência à DLL do Shoutcast. Para esse exemplo, a DLL referenciada foi Silverlight.Media.Phone disponível na estrutura de diretórios ShoutcastMSS_v1_beta2\Src\Silverlight.Media.Shoutcast\Bin\Debug do projeto que baixou do Codeplex.

No arquivo MainPage.xaml, fiz uma interface simples apenas para demonstrar o uso da servidor Shoutcast. Veja o trecho de código abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
  <TextBlock Text="BLOG DO EDUARDO H. RIZO" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
  <TextBlock Text="shoutcast..." Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
 
<!--ContentPanel - place additional content here-->
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
  <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
    <Button Name="btnPlay" Content="Play" Click="btnPlay_Click" Width="150" />
    <Button x:Name="btnPause" Content="Pause" Click="btnPause_Click" Width="150" />
  </StackPanel>
  <ProgressBar Name="pbCarregando" IsIndeterminate="false" />
  <TextBlock Name="txtStatus" Text="" TextWrapping="Wrap" HorizontalAlignment="Center" />
</StackPanel>

No início do mesmo arquivo (MainPage.xaml) foram feitas declarações para controle dos status do MediaPlayer da página. Observe o trecho de código:

1
2
3
4
5
6
7
...
shell:SystemTray.IsVisible="True" Unloaded="PageUnloaded">
<phone:PhoneApplicationPage.Resources>
  <MediaElement x:Key="mediaPlayer" Volume="1.0" BufferingProgressChanged="MediaElement_BufferingProgressChanged"
  MediaFailed="MediaElement_MediaFailed" CurrentStateChanged="MediaElement_CurrentStateChanged" />
</phone:PhoneApplicationPage.Resources>
...

shoutcast-app-wp

Realizada a codificação da porção XAML, vamos ao C# e a implementação dos métodos necessários…

Sua APP – C#

Tendo realizada a implementação do código em XAML para composição do layout (nesse exemplo de forma muito simples), vejamos a implementação dos métodos para execução das ações desejadas.

Faça o using dos seguintes namespaces:

1
2
3
4
...
using System.Windows.Media;
using Silverlight.Media;
using System.Globalization;

Restante do código C#…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
namespace ExemploShoutcast
{
  [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Quando sair da página, o ShoutcastMediaStreamSource será retirado (disposed).")]
  public partial class MainPage : PhoneApplicationPage
  {
  /// <summary>
  /// Representa um sream do Shoutcast
  /// </summary>
  private ShoutcastMediaStreamSource source;
 
  /// <summary>
  /// Interrompe a atualização do status caso algum erro ocorra
  /// </summary>
  private bool errorOccured;
 
  /// <summary>
  /// Obtem o elemento Media da página
  /// </summary>
  private MediaElement MediaPlayer
  {
    get { return this.Resources["mediaPlayer"] as MediaElement; }
  }
 
  // Constructor
  public MainPage()
  {
    InitializeComponent();
  }
 
  private void MediaElement_BufferingProgressChanged(object sender, RoutedEventArgs e)
  {
    UpdateStatus();
  }
 
  private void MediaElement_MediaFailed(object sender, ExceptionRoutedEventArgs e)
  {
    errorOccured = true;
    txtStatus.Text = string.Format(CultureInfo.InvariantCulture, "Erro: {0}", e.ErrorException.Message);
  }
 
  private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
  {
    UpdateStatus();
  }
 
  private void btnPlay_Click(object sender, RoutedEventArgs e)
  {
    if (MediaPlayer.CurrentState != MediaElementState.Paused)
    {
      ResetMediaPlayer();
 
      Uri uri = new Uri("https://74.111.222.121:99999"); //Ajuste de acordo com sua necessidade
      source = new ShoutcastMediaStreamSource(uri);
      source.MetadataChanged += source_MetadataChanged;
      MediaPlayer.SetSource(source);
    }
    MediaPlayer.Play();
    pbCarregando.IsIndeterminate = true;
  }
 
  private void btnPause_Click(object sender, RoutedEventArgs e)
  {
    if (MediaPlayer.CurrentState == MediaElementState.Playing || MediaPlayer.CurrentState == MediaElementState.Opening || MediaPlayer.CurrentState == MediaElementState.Buffering)
      MediaPlayer.Pause();
  }
 
  void source_MetadataChanged(object sender, RoutedEventArgs e)
  {
    UpdateStatus();
  }
 
  private void UpdateStatus()
  {
    if (errorOccured)
      return;
    else
    {
      MediaElementState state = MediaPlayer.CurrentState;
      string status = string.Empty;
 
      switch(state)
      {
        case MediaElementState.Buffering:
          status = string.Format(CultureInfo.InvariantCulture, "Buffering...{0:0%}", this.MediaPlayer.BufferingProgress);
        break;
        case MediaElementState.Playing:
          status = string.Format(CultureInfo.InvariantCulture, "Title: {0}", this.source.CurrentMetadata.Title);
          if (status.Trim() != "Titulo:")
            pbCarregando.IsIndeterminate = false;
        break;
        default:
          status = state.ToString();
        break;
      }
 
      txtStatus.Text = status;
    }
  }
 
  private void ResetMediaPlayer()
  {
    if ((this.MediaPlayer.CurrentState != MediaElementState.Stopped) && (this.MediaPlayer.CurrentState != MediaElementState.Closed))
    {
      this.MediaPlayer.Stop();
      this.MediaPlayer.Source = null;
      this.source.Dispose();
      this.source = null;
    }
 
    this.errorOccured = false;
  }
 
  private void PageUnloaded(object sender, EventArgs e)
  {
    ResetMediaPlayer();
  }

Não é tão difícil, certo? Se tudo tiver ocorrido como esperado, ao clicar sobre o botão Play, você poderá ouvir as músicas da sua rádio online do Shoutcast.

shoutcast-app-wp-playing

Daqui para frente é só melhorar a interface e explorar outros projetos OpenSource para o Shoutcast que estão disponíveis no Codeplex.

Post Relacionado: 

Grande abraço,
Eduardo Henrique Rizo (@eduardorizo)

Fonte: Blog do Eduardo H. Rizo

Share.

About Author

Bacharel em Ciência da Computação pela FIPP/Unoeste, Pós-Graduado em Desenvolvimento de Sistemas Web, Segurança da Informação e Avaliação do Ensino e da Aprendizagem, Professor universitário e responsável pelo setor de desenvolvimento de sistemas web da Universidade do Oeste Paulista. MCP e MCPS pela Microsoft e nas horas vagas dedica um pouco do seu tempo escrevendo posts técnicos sobre desenvolvimento de sistemas web, windows phone, gerenciamento de servidores e outros assuntos para a comunidade.