A arquitetura de som do ActionScript 3.0 é poderosa, mas complexa. Aplicativos que precisam apenas de recursos básicos de carregamento e reprodução de som podem usar uma classe que oculte um pouco da complexidade fornecendo um conjunto mais simples de chamadas e eventos de métodos. No mundo de padrões de design de software, essa classe é chamada de
facade
.
A classe SoundFacade apresenta uma única interface para executar as seguintes tarefas:
-
Carregamento de arquivos de som usando um objeto Sound, um objeto SoundLoaderContext e uma classe SoundMixer.
-
Reprodução de arquivos de som usando os objetos Sound e SoundChannel.
-
Despacho de eventos de progresso da reprodução.
-
Pausa e reinício da reprodução do som usando os objetos Sound e SoundChannel.
A classe SoundFacade tenta oferecer mais da funcionalidade das classes de som do ActionScript com menos complexidade.
O código a seguir mostra a declaração da classe, as propriedades da classe e o método construtor
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();
}
}
A classe SoundFacade estende a classe EventDispatcher para poder despachar seus próprios eventos. O código da classe primeiro declara propriedades de um objeto Sound e de um objeto SoundChannel. A classe também armazena o valor da URL do arquivo de som e uma propriedade
bufferTime
a ser usada ao transmitir o som em fluxo. Além disso, ele aceita alguns valores de parâmetros boolianos que afetam o comportamento do carregamento e da reprodução:
-
O parâmetro
autoLoad
indica ao objeto que o carregamento do som deve iniciar assim que esse objeto é criado.
-
O parâmetro
autoPlay
indica que a reprodução do som deve iniciar assim que dados de som suficientes estiverem carregados. Se esse for um fluxo de som, a reprodução será iniciada assim que dados suficientes, conforme especificado pela propriedade
bufferTime
, estiverem carregados.
-
O parâmetro
streaming
indica que a reprodução desse arquivo pode ser iniciada antes do carregamento ser concluído.
O parâmetro
bufferTime
é padronizado como um valor de -1. Se o método construtor detectar um valor negativo no parâmetro
bufferTime
, ele definirá a propriedade
bufferTime
como o valor de
SoundMixer.bufferTime
. Isso permite que o aplicativo seja padronizado para o valor global
SoundMixer.bufferTime
conforme desejado.
Se o parâmetro
autoLoad
for definido como
true
, o método construtor chamará imediatamente o método
load()
seguinte para iniciar o carregamento do arquivo de som:
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);
}
O método
load()
cria um novo objeto Sound e adiciona ouvintes para todos os eventos de som importantes. Em seguida, ele indica ao objeto Sound para carregar o arquivo de som usando um objeto SoundLoaderContext para passar o valor de
bufferTime
.
Como a propriedade
url
pode ser alterada, uma ocorrência de SoundFacade pode ser usada para reproduzir arquivos de som diferentes em sucessão: simplesmente altere a propriedade
url
e chame o método
load()
e o novo arquivo de som será carregado.
Os três métodos ouvintes de eventos a seguir mostram como o objeto SoundFacade rastreia o progresso do carregamento e decide quando iniciar a reprodução do som:
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();
}
}
O método
onLoadOpen()
é executado quando o carregamento do som é iniciado. Se o som puder ser reproduzido em modo de streaming, o método
onLoadComplete()
definirá o sinalizador
isReadyToPlay
como
true
imediatamente. O sinalizador
isReadyToPlay
determina se o aplicativo pode iniciar a reprodução do som, talvez em resposta a uma ação do usuário, como um clique em um botão de reprodução. A classe SoundChannel gerencia o buffer de dados de som, portanto não há necessidade de verificar explicitamente se dados suficientes foram carregados antes de chamar o método
play()
.
O método
onLoadProgress()
é executado periodicamente durante o processo de carregamento. Ele simplesmente despacha um clone de seu objeto ProgressEvent para uso pelo código que usa esse objeto SoundFacade.
Quando os dados do som estiverem totalmente carregados, o método
onLoadComplete()
é executado, chamando o método
play()
para sons que não sejam de fluxo, se necessário. O próprio método
play(
) é mostrado a seguir.
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();
}
}
}
O método
play()
chamará o método
Sound.play()
se o som estiver pronto para execução. O objeto SoundChannel resultante é armazenado na propriedade
sc
. Em seguida, o método
play()
cria um objeto Timer que será utilizado para despachar eventos de progresso da reprodução em intervalos regulares.