サウンドの例:Podcast Player

Flash Player 9 以降、Adobe AIR 1.0 以降

ポッドキャストとは、オンデマンドで、またはサブスクリプションによってインターネット配信されるサウンドファイルです。 通常、ポッドキャストは、ポッドキャストチャンネルとも呼ばれるシリーズの一部としてパブリッシュされています。 ポッドキャストエピソードは、1 分で終わるものから数時間かかるものまであるため、再生しながらストリーミングされます。 ポッドキャストエピソードは別名アイテムとも呼ばれ、多くの場合は MP3 ファイル形式で配信されます。 ビデオポッドキャストも一般的ではありますが、このサンプルアプリケーションでは MP3 ファイルを使用するオーディオポッドキャストのみを再生します。

この例は、フル機能を備えたポッドキャストアグリゲーターアプリケーションではありません。 例えば、このアプリケーションは特定のポッドキャストへのサブスクリプションを管理したり、アプリケーションの次回実行時のために、ユーザーがどのポッドキャストを聴いていたかを覚えるということはありません。 だたし、より多くの機能を備えたポッドキャストアグリゲーターのたたき台として使用することができます。

Podcast Player の例では、次の ActionScript プログラミング手法を示します。

  • 外部 RSS フィードの読み取りと、XML コンテンツの解析

  • SoundFacade クラスを作成することによる、サウンドファイルのロードと再生の簡便化

  • サウンド再生の進行状況の表示

  • サウンド再生の一時停止と再開

このサンプルのアプリケーションのファイルを入手するには、 www.adobe.com/go/learn_programmingAS3samples_flash_jp を参照してください。 Podcast Player アプリケーションのファイルは、Samples/PodcastPlayer フォルダーにあります。 このアプリケーションは次のファイルで構成されています。

ファイル

説明

PodcastPlayer.mxml

または

PodcastPlayer.fla

アプリケーションのユーザーインターフェイスです(Flex 用の MXML、または Flash 用の FLA)。

comp/example/programmingas3/podcastplayer/PodcastPlayer.as

ポッドキャストプレーヤー用のユーザーインターフェイスロジックを含んだドキュメントクラスです(Flash 専用)。

SoundPlayer.mxml

再生ボタンとプログレスバーを表示し、サウンド再生を制御する MXML コンポーネントです(Flex 専用)。

main.css

アプリケーションユーザーインターフェイスのスタイルです(Flex 専用)。

images/

ボタンのスタイル設定に使用するアイコンです(Flex 専用)。

comp/example/programmingas3/podcastplayer/SoundPlayer.as

サウンドプレーヤー用のユーザーインターフェイスロジックを含んだ、SoundPlayer ムービークリップシンボルのクラスです(Flash 専用)。

comp/example/programmingas3/podcastplayer/PlayButtonRenderer.as

再生ボタンをデータグリッドセル内に表示するためのカスタムセルレンダラーです(Flash 専用)。

com/example/programmingas3/podcastplayer/RSSBase.as

RSSChannel クラスと RSSItem クラスに共通のプロパティとメソッドを提供する基本クラスです。

com/example/programmingas3/podcastplayer/RSSChannel.as

RSS チャンネルに関するデータを保有する ActionScript クラスです。

com/example/programmingas3/podcastplayer/RSSItem.as

RSS アイテムに関するデータを保有する ActionScript クラスです。

com/example/programmingas3/podcastplayer/SoundFacade.as

アプリケーションのメイン ActionScript クラスです。 Sound クラスおよび SoundChannel クラスのメソッドとイベントをカプセル化し、再生の一時停止と再開をサポートします。

com/example/programmingas3/podcastplayer/URLService.as

リモート URL からデータを取得する ActionScript クラスです。

playerconfig.xml

ポッドキャストチャンネルを示す RSS フィードのリストが記された XML ファイルです。

comp/example/programmingas3/utils/DateUtil.as

日付の書式指定を簡単に実行するためのクラスです(Flash 専用)。

ポッドキャストチャンネルの RSS データの読み取り

Podcast Player アプリケーションは、最初にいくつかのポッドキャストチャンネルとエピソードに関する情報を読み取ります。

1. アプリケーションはまず、ポッドキャストチャンネルのリストを含む XML 設定ファイルを読み取り、チャンネルのリストを表示します。

2. ユーザーがいずれかのポッドキャストチャンネルを選択すると、チャンネルの RSS フィードが読み取られ、チャンネルエピソードのリストが表示されます。

この例では、URLLoader ユーティリティクラスを使用し、テキストベースのデータをリモートまたはローカルのファイルから取得します。 Podcast Player はまず URLLoader オブジェクトを作成し、playerconfig.xml ファイルから XML 形式の RSS フィードのリストを取得します。 次に、ユーザーがリストから特定のフィードを選択すると、新しい URLLoader オブジェクトが作成され、フィードの URL から RSS データを読み取ります。

SoundFacade クラスを使用した、サウンドのロードと再生の簡便化

ActionScript 3.0 のサウンドアーキテクチャは強力ですが、複雑でもあります。 サウンドの基本的なロード機能と再生機能しか必要としないアプリケーションでは、シンプルなメソッド呼び出しとイベントによって複雑さを隠すことができるクラスを使用することができます。 ソフトウェア設計パターンの分野で、このようなクラスはファサードと呼ばれます。

SoundFacade クラスは、次のタスクを実行するために単一のインターフェイスを提供します。

  • Sound オブジェクト、SoundLoaderContext オブジェクト、および SoundMixer クラスを使用したサウンドファイルのロード

  • Sound オブジェクトと SoundChannel オブジェクトを使用したサウンドファイルの再生

  • playback progress イベントの送出

  • Sound オブジェクトと SoundChannel オブジェクトを使用したサウンド再生の一時停止と再開

SoundFacade クラスは、ActionScript サウンドクラスの大半の機能を、複雑さを軽減した形で提供します。

次のコードは、クラス宣言、クラスプロパティおよび SoundFacade() コンストラクターメソッドを示します。

public class SoundFacade extends EventDispatcher 
{ 
    public var s:Sound; 
    public var sc:SoundChannel; 
    public var url:String; 
    public var bufferTime:int = 1000; 
 
    public var isLoaded:Boolean = false; 
    public var isReadyToPlay:Boolean = false; 
    public var isPlaying:Boolean = false; 
    public var isStreaming:Boolean = true; 
    public var autoLoad:Boolean = true; 
    public var autoPlay:Boolean = true; 
         
    public var pausePosition:int = 0; 
         
    public static const PLAY_PROGRESS:String = "playProgress"; 
    public var progressInterval:int = 1000; 
    public var playTimer:Timer; 
         
    public function SoundFacade(soundUrl:String, autoLoad:Boolean = true, 
                                    autoPlay:Boolean = true, streaming:Boolean = true,  
                                    bufferTime:int = -1):void 
    { 
        this.url = soundUrl; 
 
        // Sets Boolean values that determine the behavior of this object 
        this.autoLoad = autoLoad; 
        this.autoPlay = autoPlay; 
        this.isStreaming = streaming; 
 
        // Defaults to the global bufferTime value 
        if (bufferTime < 0) 
        { 
            bufferTime = SoundMixer.bufferTime; 
        } 
 
        // Keeps buffer time reasonable, between 0 and 30 seconds 
        this.bufferTime = Math.min(Math.max(0, bufferTime), 30000); 
         
        if (autoLoad) 
        { 
            load(); 
        } 
    }

SoundFacade クラスは、独自のイベントを送出できるよう EventDispatcher クラスを拡張します。 クラスコードは、まず Sound オブジェクトと SoundChannel オブジェクトのプロパティを宣言します。 このクラスは、サウンドをストリーミングするときに使用する、サウンドファイルの URL の値と bufferTime プロパティも格納します。さらに、ロードおよび再生の動作に影響するブールパラメーター値のいくつかを受け取ります。

  • autoLoad パラメーターは、オブジェクトが作成されると同時にサウンドのロードを開始するようオブジェクトに指示します。

  • autoPlay パラメーターは、十分な量のサウンドデータがロードされると同時に、サウンドの再生を開始するよう指示します。ストリーミングサウンドであれば、 bufferTime プロパティで指定されるデータ量がロードされると再生が開始されます。

  • streaming パラメーターは、ロードが完了する前にサウンドファイルの再生を開始できることを示します。

bufferTime パラメーターのデフォルト値は -1 です。コンストラクターメソッドが bufferTime パラメーターに負の値を検知した場合、 bufferTime プロパティを SoundMixer.bufferTime の値に設定します。これにより、アプリケーションのデフォルト値は、必要に応じてグローバルな SoundMixer.bufferTime の値になります。

autoLoad パラメーターが true に設定されている場合、コンストラクターメソッドはすぐに次の load() メソッドを呼び出し、サウンドファイルのロードを開始します。

public function load():void 
{ 
    if (this.isPlaying) 
    { 
        this.stop(); 
        this.s.close(); 
    } 
    this.isLoaded = false; 
     
    this.s = new Sound(); 
     
    this.s.addEventListener(ProgressEvent.PROGRESS, onLoadProgress); 
    this.s.addEventListener(Event.OPEN, onLoadOpen); 
    this.s.addEventListener(Event.COMPLETE, onLoadComplete); 
    this.s.addEventListener(Event.ID3, onID3); 
    this.s.addEventListener(IOErrorEvent.IO_ERROR, onIOError); 
    this.s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onIOError); 
     
    var req:URLRequest = new URLRequest(this.url); 
     
    var context:SoundLoaderContext = new SoundLoaderContext(this.bufferTime, true); 
    this.s.load(req, context); 
}

load() メソッドは新しい Sound オブジェクトを作成し、すべての重要なサウンドイベントのリスナーを追加します。その後、 bufferTime 値に渡す SoundLoaderContext オブジェクトを使用して、Sound オブジェクトにサウンドファイルをロードするよう指示します。

url プロパティは変更することができるので、SoundFacade インスタンスを使用して異なるサウンドファイルを連続して再生することができます。 url プロパティを変更して load() メソッドを呼び出すだけで、新しいサウンドファイルがロードされます。

次の 3 つのイベントリスナーメソッドは、SoundFacade オブジェクトがどのようにロードの進行状況をトラッキングし、サウンドを再生するタイミングを決定するかを示します。

public function onLoadOpen(event:Event):void 
{ 
    if (this.isStreaming) 
    { 
        this.isReadyToPlay = true; 
        if (autoPlay) 
        { 
            this.play(); 
        } 
    } 
    this.dispatchEvent(event.clone()); 
} 
 
public function onLoadProgress(event:ProgressEvent):void 
{  
    this.dispatchEvent(event.clone()); 
} 
 
public function onLoadComplete(event:Event):void 
{ 
    this.isReadyToPlay = true; 
    this.isLoaded = true; 
    this.dispatchEvent(evt.clone()); 
     
    if (autoPlay && !isPlaying) 
    { 
        play(); 
    } 
}

サウンドのロードが開始すると、 onLoadOpen() メソッドが実行されます。サウンドをストリーミングモードで再生できる場合、 onLoadComplete() メソッドは isReadyToPlay フラグをすぐに true に設定します。 isReadyToPlay フラグは、「再生」ボタンをクリックするなどのユーザーアクションに反応して、アプリケーションがサウンドの再生を開始できるかどうかを決定します。SoundChannel クラスはサウンドデータのバッファリングを管理するので、 play() メソッドを呼び出す前に十分なデータ量がロードされたかどうかを明示的に確認する必要はありません。

ロードプロセス中は、 onLoadProgress() メソッドが定期的に実行されます。このメソッドは、SoundFacade オブジェクトを使用するコードによって使用される ProgressEvent オブジェクトのクローンを送出するだけです。

サウンドデータが完全にロードされると、 onLoadComplete() メソッドが実行されます。必要であれば、非ストリーミングサウンドのために play() メソッドを呼び出します。 play() メソッドを以下に示します。

public function play(pos:int = 0):void 
{ 
    if (!this.isPlaying) 
    { 
        if (this.isReadyToPlay) 
        { 
            this.sc = this.s.play(pos); 
            this.sc.addEventListener(Event.SOUND_COMPLETE, onPlayComplete); 
            this.isPlaying = true; 
             
            this.playTimer = new Timer(this.progressInterval); 
            this.playTimer.addEventListener(TimerEvent.TIMER, onPlayTimer); 
            this.playTimer.start(); 
        } 
    } 
}

サウンドが再生できる状態になると、 play() メソッドは Sound.play() メソッドを呼び出します。生成される SoundChannel オブジェクトは、 sc プロパティに格納されます。その後、 play() メソッドは Timer オブジェクトを作成します。これを使用すると、playback progress イベントを定期的に送出することができます。

再生の進行状況の表示

Timer オブジェクトを作成して再生を監視する処理は複雑なので、コードの実行は一度きりにする必要があります。 この Timer ロジックを、SoundFacade クラスのような再利用可能なクラスにカプセル化することで、アプリケーションはサウンドのロード時や再生時に同様の progress イベントを監視することができます。

SoundFacade.play() メソッドによって作成される Timer オブジェクトは、TimerEvent インスタンスを毎秒送出します。以下に示す onPlayTimer() メソッドは、新しい TimerEvent が受信されるたびに実行されます。

public function onPlayTimer(event:TimerEvent):void  
{ 
    var estimatedLength:int =  
        Math.ceil(this.s.length / (this.s.bytesLoaded / this.s.bytesTotal)); 
    var progEvent:ProgressEvent =  
        new ProgressEvent(PLAY_PROGRESS, false, false, this.sc.position, estimatedLength); 
    this.dispatchEvent(progEvent); 
}

onPlayTimer() メソッドは、 再生の監視 の節で説明したサイズ予測方法を実装します。イベントタイプ SoundFacade.PLAY_PROGRESS で新しい ProgressEvent インスタンスが作成されます。そのとき、 bytesLoaded プロパティは SoundChannel オブジェクトの現在位置に設定され、 bytesTotal プロパティはサウンドデータの予測長に設定されます。

再生の一時停止と再開

前述の SoundFacade.play() メソッドは、サウンドデータの開始位置に対応する pos パラメーターを受け取ります。 pos 値がゼロの場合、サウンドは最初から再生されます。

SoundFacade.stop() メソッドは、次に示す pos パラメーターも受け取ります。

public function stop(pos:int = 0):void 
{ 
    if (this.isPlaying) 
    { 
        this.pausePosition = pos; 
        this.sc.stop(); 
        this.playTimer.stop(); 
        this.isPlaying = false; 
    }     
}

SoundFacade.stop() メソッドが呼び出されると pausePosition プロパティが設定されるので、アプリケーションは同じサウンドの再生を再開する場合の再生ヘッドの位置を特定できます。

以下に示す SoundFacade.pause() メソッドおよび SoundFacade.resume() メソッドは、それぞれ SoundFacade.stop() メソッドおよび SoundFacade.play() メソッドを呼び出し、呼び出すたびに pos パラメーター値を渡します。

public function pause():void 
{ 
    stop(this.sc.position); 
} 
 
public function resume():void 
{ 
    play(this.pausePosition); 
}

pause() メソッドは、現在の SoundChannel.position 値を play() メソッドに渡します。このメソッドは、この値を pausePosition プロパティに格納します。 resume() メソッドは、開始位置として pausePosition 値を使用し、同じサウンドを再生を開始します。

Podcast Player の拡張例

この例では、再利用可能な SoundFacade クラスを主に使用する、必要最小限の機能だけを備えた Podcast Player を示します。 次のような機能を追加して、アプリケーションの利便性を高めることもできます。

  • フィードのリストと、各エピソードに関する使用情報を SharedObject インスタンスに格納します。このインスタンスは、アプリケーションの次回実行時に使用することができます。

  • ユーザー独自の RSS フィードを、ポッドキャストチャンネルのリストに追加します。

  • ユーザーがエピソードを停止または終了したときの再生ヘッドの位置を記憶します。そうすると、アプリケーションの次回実行時に同じ場所から再開することができます。

  • ユーザーがインターネットに接続していない場合も、オフライン状態でエピソードを聞くために、MP3 ファイルをダウンロードします。

  • ポッドキャストチャンネルの新しいエピソードを定期的に確認してエピソードリストを自動的に更新する、サブスクリプション機能を追加します。

  • Odeo.com などのポッドキャストホスティングサービスの API を使用し、ポッドキャスト検索および閲覧機能を追加します。