tmytのらくがき

個人の日記レベルです

BackgroundAudioPlayerのすゝめ

MangoでBackgroundTasksってのがサポートされて、その中にBackgroundAudioってのがあってそれを使うとお手軽にオーディオプレイヤーアプリが作れちゃう。みんなもそれでアプリつくってプライベートクラウドを有効活用しようよ!というお話です。
長いので続きでどうぞ。

準備

VSで新規ソリューションでWindows Phone アプリケーションを作る。

オーディオ再生エージェントを追加する

ソリューションエクスプローラのソリューションを右クリック、追加(D)|新しいプロジェクト(N)

Windows Phone オーディオ再生エージェント を選択してプロジェクトに追加

ここまででソリューション構成はこうなっているはず

最後にメインのアプリへAudioPlaybackAgent1の参照を追加する
PhoneApp4の参照設定を右クリック、参照の追加(R)

プロジェクト タブからAudioPlaybackAgent1を選択してOK

これでBackgroundAudioがアプリから使用できるようになりました。

オーディオ再生エージェントを使ってオーディオを再生する

まずは一番簡単な例から。

PhoneApp4のMainPage.xamlへボタンを追加します。

<!-- ちょーてきとー -->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Button Click="Button_Click" Content="Play" />
</Grid>

コードビハインドに次のを書きます。

using Microsoft.Phone.BackgroundAudio;
private void Button_Click(object sender, RoutedEventArgs e)
{
    BackgroundAudioPlayer.Instance.Track = 
        new AudioTrack(
            new Uri("http://example.com/music.mp3"), 
            "Sample Track",
            "Some Artist",
            "Unknown Album",
            null);
    BackgroundAudioPlayer.Instance.Play();
}

ファイルのパスとかは各自いい感じに埋めてください。タイトルとかアーティストとかは、ボリュームコントロールのところとか、ロック画面とかに出ます。

ここまで出来たらとりあえず音楽鳴ります。実行してボタンを押すとバックグラウンドで再生されます。アプリ殺したって問題ないです。

オーディオ再生エージェントをもう少しちゃんとコントロールするには

AudioPlaybackAgent1のAudioPlayer.csにAudioPlayerAgentクラスを実装したクラスのテンプレートが記述してあります。
今ひとつこれ日本語化されてなくてあれげな感じなんですが、これは書いときましょうというところをピックアップして。

OnPlayStateChanged関数

再生状態が変更されたときに呼び出される関数で、状態に応じていろいろな処理を出来ます。
これ、テンプレートにバグがあって、PlayState.TrackEndedの時にGetPreviousTrackを呼び出すようになっていますが、再生終わったときに一つ前のトラック呼ばれても困るので、ここを書き換えて

case PlayState.TrackEnded:
    player.Track = GetNextTrack();
    break;

というように変更しておきましょう。ほかのイベントは必要なら適宜。

OnUserAction関数

ユーザがなにか操作したときに呼ばれます。BackgroundAudioPlayer.Instance.Play() とかしたときに呼ばれるのもここ。
ここで、再生するトラックがセットされていないときはIsolatedStorageからプレイリストを読み出してパースするなどの処理をするといいです。

GetNextTrack関数

現在再生中のトラックの次を取得する関数。なんかいい感じに実装してください。
たとえばこんな感じ。

private AudioTrack GetNextTrack()
{
    AudioTrack track = null;
    // 次にまだトラックがあるならそれを返す
    if (++trackNum < tracks.Count)
        track = tracks[trackNum];
    return track;
}

nullを返すと再生は終了します。

GetPreviousTrack関数

GetNextTrack関数と同じように、こっちは再生中のトラックの一つ前のトラックを返します。こっちもいい感じで実装してください。
こんな感じです。

private AudioTrack GetPreviousTrack()
{
    AudioTrack track = null;
    // 一つ前にまだトラックがあるならそれを返す
    if (--trackNum >= 0)
        track = tracks[trackNum];
    return track;
}

他にもエラー時に呼ばれる関数とかいろいろありますが、ちゃんとしたアプリを作らないのであれば実装しなくても問題無いです。*1ちゃんとしたアプリ書くときはエラー処理とかした方がいいですけど、おうちのサーバからストリームしてプライベートクラウドをBackgroundAudioで有効活用しよぅ!っていう用途ならこれぐらいの実装で十分です。
みなさんもアプリ作って、サーバ側も実装して、快適な音楽ライフを送りませんか?

*1:暴言