Sound-Beispiel: Podcast-Player

Flash Player 9 und höher, Adobe AIR 1.0 und höher

Ein Podcast ist eine über das Internet verteilte Sounddatei, die entweder speziell angefordert oder abonniert wurde. Podcasts werden in der Regel als Serie veröffentlicht, die auch als ein Podcast-Kanal bezeichnet wird. Da Podcast-Episoden zwischen einer Minute und mehreren Stunden umfassen können, werden sie im Allgemeinen während der Wiedergabe gestreamt. Podcast-Episoden, die auch als Objekte bezeichnet werden, liegen in der Regel im MP3-Format vor. Auch Video-Podcasts sind sehr populär. Diese Beispielanwendung gibt jedoch nur Audio-Podcasts wieder, die MP3-Dateien verwenden.

Dieses Beispiel ist keine Podcast Aggregator-Anwendung mit vollständigem Funktionsumfang. Beispielsweise verwaltet sie keine Abonnements von bestimmten Podcasts oder speichert Aufzeichnungen darüber, welche Podcasts der Benutzer bereits gehört hat. Sie kann jedoch als Startpunkt für einen Podcast-Aggregator mit einem größeren Funktionsumfang dienen.

Das Beispiel „Podcast Player“ veranschaulicht die folgenden ActionScript-Programmiertechniken:

  • Lesen eines externen RSS-Feed und Einlesen des XML-Inhalts

  • Erstellen einer SoundFacade-Klasse zum einfachen Laden und Wiedergeben von Sounddateien

  • Anzeigen des Fortschritts der Soundwiedergabe

  • Unterbrechen und Fortsetzen der Soundwiedergabe

Die Anwendungsdateien für dieses Beispiel finden Sie unter www.adobe.com/go/learn_programmingAS3samples_flash_de . Die Dateien der Anwendung „Podcast Player“ befinden sich im Ordner „Samples/PodcastPlayer“. Die Anwendung umfasst die folgenden Dateien:

Datei

Beschreibung

PodcastPlayer.mxml

oder

PodcastPlayer.fla

Die Benutzeroberfläche der Anwendung im Flex-Format (MXML) oder Flash-Format (FLA).

comp/example/programmingas3/podcastplayer/PodcastPlayer.as

Document-Klasse mit der Benutzeroberflächenlogik für den Podcast-Player (nur Flash).

SoundPlayer.mxml

Eine MXML-Komponente, die Wiedergabeschaltflächen und Fortschrittleisten anzeigt sowie die Soundwiedergabe steuert (nur für Flex).

main.css

Stile für die Benutzeroberfläche der Anwendung (nur Flex).

images/

Symbole zum Gestalten der Schaltflächen (nur Flex).

comp/example/programmingas3/podcastplayer/SoundPlayer.as

Klasse für das SoundPlayer-Movieclipsymbol mit der Benutzeroberflächenlogik für den Soundplayer (nur Flash).

comp/example/programmingas3/podcastplayer/PlayButtonRenderer.as

Benutzerdefinierter Zellen-Renderer für die Anzeige einer Wiedergabe-Schaltfläche in einer Zelle eines Datengitters (nur Flash).

com/example/programmingas3/podcastplayer/RSSBase.as

Eine Basisklasse, die allgemeine Eigenschaften und Methoden für die RSSChannel- und die RSSItem-Klasse bereitstellt.

com/example/programmingas3/podcastplayer/RSSChannel.as

Eine ActionScript-Klasse, die Daten über einen RSS-Kanal enthält.

com/example/programmingas3/podcastplayer/RSSItem.as

Eine ActionScript-Klasse, die Daten über ein RSS-Objekt enthält.

com/example/programmingas3/podcastplayer/SoundFacade.as

Die ActionScript-Hauptklasse der Anwendung. Diese Klasse kapselt die Methoden und Ereignisse der Sound- und der SoundChannel-Klasse ein und fügt eine Unterstützung für das Unterbrechen und Fortsetzen der Wiedergabe hinzu.

com/example/programmingas3/podcastplayer/URLService.as

Eine ActionScript-Klasse, die Daten von einer Remote-URL empfängt.

playerconfig.xml

Eine XML-Datei, die eine Liste der RSS-Feeds enthält, die Podcast-Kanäle darstellen.

comp/example/programmingas3/utils/DateUtil.as

Klasse, die zur einfachen Datumsformatierung verwendet wird (nur Flash).

Lesen von RSS-Daten eines Podcast-Kanals

Zunächst liest die Anwendung „Podcast Player“ Informationen über die Anzahl an Podcast-Kanälen und deren Episoden:

1. Als Erstes liest die Anwendung eine XML-Konfigurationsdatei mit einer Liste der Podcast-Kanäle ein und zeigt diese Kanalliste dem Benutzer an.

2. Nachdem der Benutzer einen der Podcast-Kanäle ausgewählt hat, liest das Programm den RSS-Feed des Kanals ein und zeigt eine Liste der Kanalepisoden an.

In diesem Beispiel wird die URLLoader utility-Klasse dazu verwendet, um textbasierte Daten von einem remoten Speicherort oder aus einer lokalen Datei zu empfangen. Zunächst erstellt der Podcast Player ein URLLoader-Objekt, um eine Liste der RSS-Feeds im XML-Format aus der Datei „playerconfig.xml“ abzurufen. Dann, wenn der Benutzer einen bestimmten Feed in der Liste markiert, wird ein neues URLLoader-Objekte erstellt, um die RSS-Daten von der URL dieses Feeds zu lesen.

Vereinfachen des Ladens und der Soundwiedergabe mithilfe der SoundFacade-Klasse

Die ActionScript 3.0-Soundarchitektur ist leistungsfähig, aber komplex. Anwendungen, die nur einfache Funktionen zum Laden und zur Wiedergabe von Sounds umfassen müssen, können mithilfe einer Klasse erstellt werden, die einige der komplexen Funktionen ausblendet, und nur einen einfachen Satz von Methoden aufruft und Ereignissen bereitstellt. In der Welt des Softwaredesigns wird eine solche Klasse als facade (Fassade) bezeichnet.

Die SoundFacade-Klasse stellt eine einfache Schnittstelle für die folgenden Aufgaben bereit:

  • Laden von Sounddateien mithilfe eines Sound-Objekts, eines SoundLoaderContext-Objekts und der SoundMixer-Klasse

  • Wiedergabe von Sounddateien mithilfe eines Sound-Objekts und eines SoundChannel-Objekts

  • Auslösen von Ereignissen zum Wiedergabefortschritt

  • Unterbrechen und Fortsetzen der Soundwiedergabe mithilfe eines Sound-Objekts und eines SoundChannel-Objekts

Die SoundFacade-Klasse versucht, den wichtigsten Teil der Funktionsmerkmale der ActionScript-Soundklassen bei geringerer Komplexität bereitzustellen.

Im folgenden Code wird die Deklaration der Klasse, der Klasseneigenschaften und der SoundFacade() -Konstruktormethode gezeigt:

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(); 
        } 
    }

Die SoundFacade-Klasse erweitert die EventDispatcher-Klasse, sodass sie eigene Ereignisse auslösen kann. Zunächst deklariert der Klassencode Eigenschaften für ein Sound- und ein SoundChannel-Objekt. Außerdem speichert die Klasse den URL-Wert der Sounddatei und eine bufferTime -Eigenschaft, die beim Streamen des Sounds verwendet werden. Weiterhin akzeptiert sie einige boolesche Parameterwerte, die sich auf das Verhalten beim Laden und bei der Wiedergabe auswirken:

  • Der autoLoad -Parameter weist das Objekt an, dass der Sound geladen werden soll, sobald dieses Objekt erstellt wurde.

  • Der autoPlay -Parameter gibt an, dass die Soundwiedergabe beginnen soll, sobald ausreichend Daten geladen wurden. Handelt es sich um einen Streaming-Sound, beginnt die Wiedergabe, sobald ausreichend Daten geladen wurden. Die erforderliche Datenmenge wird mit der Eigenschaft bufferTime vorgegeben.

  • Der streaming -Parameter gibt an, dass die Wiedergabe dieser Sounddatei beginnen kann, wenn das Laden der Daten vollständig abgeschlossen wurde.

Der bufferTime -Parameter hat einen Standardwert von -1. Wenn die Konstruktormethode einen negativen Wert im bufferTime -Parameter erfasst, stellt sie die bufferTime -Eigenschaft auf den Wert SoundMixer.bufferTime ein. Damit kann die Anwendung den globalen SoundMixer.bufferTime -Wert als Standardwert annehmen.

Wenn der autoLoad -Parameter auf true gesetzt ist, ruft die Konstruktormethode unmittelbar die folgende load() -Methode auf, um das Laden der Sounddatei zu starten:

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); 
}

Die load() -Methode erstellt ein neues Sound-Objekt und fügt Listener für alle wichtigen Soundereignisse hinzu. Dann weist sie das Sound-Objekt an, die Sounddatei zu laden. Dabei verwendet sie ein SoundLoaderContext-Objekt, um den bufferTime -Wert zu übergeben.

Da die url -Eigenschaft geändert werden kann, können mit einer SoundFacade-Instanz verschiedene Sounddateien nacheinander wiedergegeben werden: Ändern Sie einfach die url -Eigenschaft und rufen Sie die load() -Methode auf – die neue Sounddatei wird geladen.

Die folgenden drei Ereignis-Listener-Methoden zeigen, wie das SoundFacade-Objekt den Ladefortschritt verfolgt und dann entscheidet, wann der Sound wiedergegeben wird:

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(); 
    } 
}

Die onLoadOpen() -Methode wird ausgeführt, wenn das Laden des Sounds beginnt. Wenn der Sound im Streaming-Modus wiedergegeben werden kann, stellt die onLoadComplete() -Methode das isReadyToPlay -Flag direkt auf true ein. Das isReadyToPlay -Flag legt fest, ob die Anwendung die Soundwiedergabe starten kann, eventuell als Reaktion auf eine Benutzeraktion wie das Klicken auf die Wiedergabe-Schaltfläche. Die SoundChannel-Klasse verwaltet die Pufferung der Sounddaten, es ist also nicht erforderlich, explizit zu überprüfen, ob ausreichend Daten geladen wurden, bevor die play() -Methode aufgerufen wird.

Die onLoadProgress() -Methode wird während des Ladeprozesses in regelmäßigen Abständen ausgeführt. Sie sendet einfach einen Klon ihres ProgressEvent-Objekts für den Code, der dieses SoundFacade-Objekt verwendet.

Nachdem die Sounddaten vollständig geladen wurden, wird die onLoadComplete() -Methode ausgeführt, die bei Bedarf die play() -Methode für nicht gestreamte Sounds aufruft. Die play() -Methode wird im Folgenden gezeigt.

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(); 
        } 
    } 
}

Die play() -Methode ruft die Sound.play() -Methode auf, wenn der Sound bereit zur Wiedergabe ist. Das resultierende SoundChannel-Objekt wird in der sc -Eigenschaft gespeichert. Dann erstellt die play() -Methode ein Timer-Objekt, das in regelmäßigen Abständen Wiedergabefortschrittsereignisse auslöst.

Anzeigen des Wiedergabefortschritts

Das Erstellen eines Timer-Objekts zur Steuerung der Wiedergabeüberwachung ist ein komplexer Vorgang, den Sie jedoch nur einmal ausführen müssen. Durch die Kapselung dieser Timer-Logik in eine wiederverwendbare Klasse wie die SoundFacade-Klasse können Anwendungen auf die gleichen Fortschrittsereignisse überwachen, wenn ein Sound geladen und wenn er wiedergegeben wird.

Das Timer-Objekt wird von der SoundFacade.play() -Methode erstellt, die jede Sekunde eine TimerEvent-Instanz auslöst. Die folgende onPlayTimer() -Methode wird immer dann ausgeführt, wenn ein neues TimerEvent-Ereignis eintrifft:

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); 
}

Die onPlayTimer() -Methode implementiert die Technik zur Einschätzung der Größe, die im Abschnitt Überwachen der Wiedergabe beschrieben wurde. Dann erstellt sie eine neue ProgressEvent-Instanz mit dem Ereignistyp SoundFacade.PLAY_PROGRESS ; die bytesLoaded -Eigenschaft ist auf die aktuelle Position des SoundChannel-Objekts eingestellt und die bytesTotal -Eigenschaft auf die geschätzte Länge der Sounddaten.

Unterbrechen und Fortsetzen der Wiedergabe

Die im vorangegangenen Abschnitt vorgestellte SoundFacade.play() -Methode akzeptiert einen pos -Parameter, der einer Startposition in den Sounddaten entspricht. Wenn der pos -Wert Null beträgt, startet der Sound am Anfang der Datei.

Darüber hinaus akzeptiert die SoundFacade.stop() -Methode einen pos -Parameter. Dies wird im Folgenden gezeigt:

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

Immer, wenn die SoundFacade.stop() -Methode aufgerufen wird, stellt sie die pausePosition -Eigenschaft so ein, dass die Anwendung weiß, wo sie den Abspielkopf positionieren soll, wenn der Benutzer die Wiedergabe des gleichen Sounds fortsetzen möchte.

Die im Folgenden gezeigten Methoden SoundFacade.pause() und SoundFacade.resume() rufen die Methoden SoundFacade.stop() und SoundFacade.play() auf und übergeben jedes Mal einen pos -Parameterwert.

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

Die pause() -Methode übergibt den aktuellen SoundChannel.position -Wert an die play() -Methode, die diesen Wert in der pausePosition -Eigenschaft speichert. Die resume() -Methode startet die Wiedergabe des gleichen Sounds mit dem pausePosition -Wert als Startpunkt neu.

Aufwerten der Beispielanwendung „Podcast Player“

Dieses Beispiel stellt einen Podcast-Player mit Grundfunktionen dar und illustriert die Verwendung der wiederverwendbaren SoundFacade-Klasse. Sie können weitere Funktionen hinzufügen, um diese Anwendung aufzuwerten. Dazu gehören unter anderem folgende Funktionen:

  • Speichern einer Liste der Feeds und Nutzungsinformationen über jede Episode in einer SharedObject-Instanz, die der Benutzer beim nächsten Ausführen der Anwendung aufrufen kann

  • Ermöglichen, dass Benutzer eigene RSS-Feeds zur Liste der Podcast-Kanäle hinzufügen können

  • Speichern der Position des Abspielkopfs, wenn der Benutzer eine Episode stoppt oder verlässt, sodass der Benutzer sie beim nächsten Ausführen der Anwendung an der gleichen Stelle fortsetzen kann

  • Herunterladen von MP3-Dateien zur Offlinewiedergabe, wenn der Benutzer keine Verbindung mit dem Internet hergestellt hat

  • Hinzufügen von Abonnementfunktionen, die regelmäßig auf neue Episoden in einem Podcast-Kanal prüfen und die Episodenliste automatisch aktualisieren

  • Hinzufügen von Funktionen zum Suchen und Browsen nach Podcasts von einem Podcast-Hosting-Dienst wie z. B. Odeo.com