[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.

  • Alberto Costa

    Eae galera, alguém testou esse código recentemente? Tentei a mesma url, com outra url e mesmo assim não funcionou. Alguem alguma luz????

  • Eduardo Henrique Rizo

    Olá AlbertoMonteiro, Kelvyn Richard e demais colegas do Blog. Em primeiro lugar agradeço as criticas em relação ao post, pois elas nos deixam inquietos e sabedores de que sempre precisamos melhorar, no entanto, minha intenção com ele não é seguir um padrão de desenvolvimento X ou Y e nem mesmo mostrar a solução/projeto completo.
    Minha intensão é apresentar a possibilidade e mostrar alguns trechos de código que permitam aos leitores “enxergar” as possibilidades de uso e aplica-las em suas próprias APPs.
    Grande abraço,
    Eduardo H. Rizo

  • Agnaldo Santana da Silva

    Pessoal por favor, será que tem como desvincular o l920 da claro?

    • Robson Carvalho

      Tem sim amigo, procura ai o Nokia Care Suíte (NCS). Mas pega um tutorial bom para não danifica seu aparelho e também vc ira perder a garantia do aparelho caso vc use o método. Antes a galera usava o NaviFirm mas foi bloqueado http://windowsphonebrasil.com.br/acesso-publico-ao-navifirm-e-bloqueado/.
      OBS: Lei bem antes de fazer o procedimento e aconselho so fazer caso vc consiga intender, pq se n souber vc pode ate mata o seu aparelho.

  • AlbertoMonteiro

    Você poderia pelo menos usar MVVM….

  • Kelvyn Richard

    Queria entender pelo menos uma linha do que fui escrito, conseguir abrir apenas o programa MAiN