Curso Windows Phone – Como desenvolver uma APP para rádio online via Shoutcast

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:


<!--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:

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

...
using System.Windows.Media;
using Silverlight.Media;
using System.Globalization;

Restante do código C#…

...
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("http://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.

diskette Download do Exemplo

 

Post Relacionado: 

Grande abraço,
Eduardo Henrique Rizo

Coordenador de Internet da Universidade do Oeste Paulista (Unoeste) e professor universitário de disciplinas relacionadas ao desenvolvimento de sistemas para Web, gerenciamento de servidores, serviços e redes.

Marcado com: , , , , , , , , , , , ,
Publicado em Windows Phone
28 comentários em “Curso Windows Phone – Como desenvolver uma APP para rádio online via Shoutcast
  1. […] Como desenvolver uma APP para rádio online via Shoutcast […]

  2. Sid disse:

    Boa tarde Eduardo,
    estou com problemas para ouvir radios pelo Shoutcast:
    Há pouco tempo, bastava clicar em alguma estação que ela era reproduzida automaticamente. Atualmente, é baixado um arquivo (tunein-sation.pls) que não é reconhecido pelo player (WMP).
    Vc sabe o que mudou?
    Obrigado

  3. Esse codigo funciona somente para Radios do Shoutcast, ou serve para outras radios online?

    • Creio que funcione para outras rádios também, mas sinceramente não fiz testes.

      []s
      Eduardo

      • Ah sim, queria saber também, se existe algum método de eu mudar a URI da rádio. Por exemplo pra q eu possa adicionar varias opções de rádios para o usuário escolher, e a troca entre elas fosse dinâmica.

      • Bom, nesse caso penso que a URI poderia ser um parâmetro (string) a ser informado a um determinado método de acordo com a seleção que a pessoa fizer.

        []s
        Eduardo

      • Estou tendo um pouco de dificuldade para criar isso, pois sou novato em desenvolvimento. Se for possivel gostaria de uma ajuda para criar tal função.

      • Bem, se você observar o meu código verá que a chamada à URL ocorre dentro do click do botão btnPlay. No caso que te falei você poderia ter um método a ser chamado pela mesma ação do botão, mas nesse caso você iria selecionar a URL de acordo com ListBox, por exemplo, que iria apresentar as opções para o usuário da APP. Entendeu?

  4. Leandro disse:

    Olá Eduardo, tudo bem?

    Estou com uma dificuldade. Você mostrou que precisa importar o Silverlight.Media, porém quando tento importar, ocorre um erro. Há algum lugar para que eu possa estar baixando o .dll?

    Obrigado pela ajuda!
    😀

  5. João Miguel disse:

    Opa, boa noite, como faço para fazer a referencia? Pois quando eu coloco o local do arquivo q vc pediu o programa da erro dizendo “A diference for a higher version or incompatible assembly cannot be added to the project.”

  6. Ulisses disse:

    Não consigo referenciar o shoutcast no meu projeto. Não sei o que estou fazendo de errado. Pode me ajudar por favor?
    Abraços

  7. Ulisses disse:

    Olá professor!

    Na verdade, não há mensagem de erro, simplesmente não sei como fazer essa referência.
    Clico com o botão direito do mouse em meu projeto, escolho a opção adicionar referência, depois clico em Browser, mas o sistema não localiza esse diretório Bin como consta abaixo

    ShoutcastMSS_v1_beta2\Src\Silverlight.Media.Shoutcast\Bin\Debug

    Se poder me ensinar como faço para adicionar o Shoutcast ao meu projeto agradeço.

    Abraço!

    • Ulisses, bom dia!
      Se não me engano, é necessário que você abra o projeto do Shoutcast no Visual Studio e o compile. Depois disso, faça a referência da DLL em sua APP.

      Abraços,
      Eduardo H. Rizo

  8. Ulisses disse:

    Boa tarde professor!

    Consegui fazer a integração ao projeto, mas surgiu um outro problema.
    Mesmo mudando o final do endereço http://74.111.222.121:99999, não toca nenhuma música. Ocorre a mensagem de erro: “Erro: 3108 The remote server returned na error: NotFound.”

    Pesquisei muito na Internet, mas não encontrei nada a respeito. Onde o senhor encontrou este endereço http://74.111.222.121:99999?

    Abraços

  9. Ulisses disse:

    Obrigado professor. Abraço

  10. Lucas disse:

    Hola, podrías dejar el ejemplo descargable?
    Desde ya muchísimas gracias!

  11. Lucas disse:

    Hola! muy buena la aplicativo, pero me this costando Que funcione en Segundo plano, nos podrias dar una ayuda? o subirnos algun ejemplo de Como hacer en that funcione Segundo plano?((background task, lockscreen task)

  12. Pedro disse:

    Bom dia Eduardo,
    Novamente parabéns pelo Blog,
    ótimo exemplo de rádio, porem a mesma não é executada quando por exemplo o celular é bloqueado, poderia demostrar algum exemplo ou indicar alguma forma para que a Radio funcione em segundo plano?

Deixar mensagem para Victor Hugo Melo Cancelar resposta

Sorocaba e Região
Prestadora de serviços RIZZO GS - Sorocaba/SP

Serviços de limpeza, conservação, recepção, copa, portaria, vigia, zeladoria, jardim, elétrica, hidráulica, pintura, etc.

Contato: (15) 3357-4263 / (15) 3357-4502 - contato@rizzogs.com.br

Website: http://www.rizzogs.com.br