blob: 9a828822e0d2a27c6c030f96272310f133e1d049 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package mx.effects
{
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.media.Sound;
import flash.media.SoundLoaderContext;
import flash.net.URLRequest;
import mx.effects.effectClasses.SoundEffectInstance;
import mx.managers.ISystemManager;
import mx.managers.SystemManager;
import mx.resources.IResourceManager;
import mx.resources.ResourceManager;
/**
* Dispatched when the sound file finishes loading.
*
* @eventType flash.events.Event.COMPLETE
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="complete", type="flash.events.Event")]
/**
* Dispatched when ID3 data is available for an MP3 sound file.
*
* @eventType flash.events.Event.ID3
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="id3", type="flash.events.Event")]
/**
* Dispatched when an error occurs during the loading of the sound file.
*
* @eventType flash.events.IOErrorEvent.IO_ERROR
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="ioError", type="flash.events.IOErrorEvent")]
/**
* Dispatched periodically as the sound file loads.
*
* <p>Within the event object, you can access the number of bytes
* currently loaded and the total number of bytes to load.
* The event is not guaranteed to be dispatched, which means that
* the <code>complete</code> event might be dispatched
* without any <code>progress</code> events being dispatched.</p>
*
* @eventType flash.events.ProgressEvent.PROGRESS
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="progress", type="flash.events.ProgressEvent")]
[ResourceBundle("effects")]
/**
* The SoundEffect class plays an MP3 audio file.
* For example, you could play a sound when a user clicks a Button control.
* This effect lets you repeat the sound, select the source file,
* and control the volume and pan.
*
* <p>You specify the MP3 file using the <code>source</code> property.
* If you have already embedded the MP3 file, using the <code>Embed</code>
* keyword, you can pass the Class object of the MP3 file to the
* <code>source</code> property.
* Otherwise, specify the full URL to the MP3 file.</p>
*
* @mxml
*
* <p>The <code>&lt;mx:SoundEffect&gt;</code> tag
* inherits all of the tag attributes of its superclass,
* and adds the following tag attributes:</p>
*
* <pre>
* &lt;mx:SoundEffect
* <b>Properties</b>
* id="ID"
* autoLoad="true|false"
* bufferTime="1000"
* loops="0"
* panEasingFunction=""
* panFrom="0"
* source=""
* startTime="0"
* useDuration="true|false"
* volumeEasingFunction="true|false"
* volumeTo="1"
*
* <b>Events</b>
* complete="<i>No default</i>"
* id3="<i>No default</i>"
* ioError="<i>No default</i>"
* progress="<i>No default</i>"
* /&gt;
* </pre>
*
* @see mx.effects.effectClasses.SoundEffectInstance
* @see flash.media.Sound
*
* @includeExample examples/SoundEffectExample.mxml
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public class SoundEffect extends Effect
{
include "../core/Version.as";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @param target The Object to animate with this effect.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function SoundEffect(target:Object = null)
{
super(target);
instanceClass = SoundEffectInstance;
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
*/
private var needsLoading:Boolean = false;
/**
* @private
* Used for accessing localized Error messages.
*/
private var resourceManager:IResourceManager =
ResourceManager.getInstance();
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// autoLoad
//----------------------------------
/**
* @private
* Storage for the autoLoad property.
*/
private var _autoLoad:Boolean = true;
[Inspectable(category="General", defaultValue="true")]
/**
* If <code>true</code>, load the MP3 file
* when the <code>source</code> has been specified.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get autoLoad():Boolean
{
return _autoLoad;
}
/**
* @private
*/
public function set autoLoad(value:Boolean):void
{
_autoLoad = value;
}
//----------------------------------
// bufferTime
//----------------------------------
[Inspectable(category="General", defaultValue="1000")]
/**
* The SoundEffect class uses an internal Sound object to control
* the MP3 file.
* This property specifies the minimum number of milliseconds
* worth of sound data to hold in the Sound object's buffer.
* The Sound object waits until it has at least
* this much data before beginning playback,
* and before resuming playback after a network stall.
*
* @default 1000
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var bufferTime:Number = 1000;
//----------------------------------
// isLoading
//----------------------------------
/**
* This property is <code>true</code> if the MP3 has been loaded.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get isLoading():Boolean
{
if (_sound)
{
return _sound.bytesTotal > 0;
}
return false;
}
//----------------------------------
// loops
//----------------------------------
[Inspectable(category="General", defaultValue="0")]
/**
* The number of times to play the sound in a loop, where a value of
* 0 means play the effect once, a value of 1 means play the effect twice,
* and so on. If you repeat the MP3 file, it still uses the setting of the
* <code>useDuration</code> property to determine the playback time.
*
* <p>The <code>duration</code> property takes precedence
* over this property.
* If the effect duration is not long enough to play the sound
* at least once, the sound does not loop.</p>
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var loops:int = 0;
//----------------------------------
// panEasingFunction
//----------------------------------
/**
* The easing function for the pan effect.
* Use this function to interpolate between the values
* of <code>panFrom</code> and <code>panTo</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var panEasingFunction:Function;
//----------------------------------
// panFrom
//----------------------------------
[Inspectable(category="General", defaultValue="0.0")]
/**
* Initial pan of the Sound object.
* The value can range from -1.0 to 1.0, where -1.0 uses only the left
* channel, 1.0 uses only the right channel, and 0.0 balances the sound
* evenly between the two channels.
*
* @default 0.0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var panFrom:Number;
//----------------------------------
// panTo
//----------------------------------
[Inspectable(category="General", defaultValue="0.0")]
/**
* Final pan of the Sound object.
* The value can range from -1.0 to 1.0, where -1.0 uses only the left channel,
* 1.0 uses only the right channel, and 0.0 balances the sound evenly
* between the two channels.
*
* @default 0.0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var panTo:Number;
//----------------------------------
// sound
//----------------------------------
/**
* @private
*/
private var _sound:Sound;
/**
* The Sound object that the MP3 file has been loaded into.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get sound():Sound
{
return _sound;
}
//----------------------------------
// source
//----------------------------------
/**
* @private
* Storage for the source property.
*/
private var _source:Object;
[Inspectable(category="General", defaultValue="null")]
/**
* The URL or class of the MP3 file to play.
* If you have already embedded the MP3 file, using the <code>Embed</code> keyword,
* you can pass the Class object of the MP3 file to the <code>source</code> property.
* Otherwise, specify the full URL to the MP3 file.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get source():Object
{
return _source;
}
/**
* @private
*/
public function set source(value:Object):void
{
if (_sound)
{
try
{
_sound.close();
}
catch(e:IOError)
{
// Ignore these
}
removeSoundListeners();
}
_source = value;
if (_source is Class)
{
var cls:Class = Class(_source);
_sound = new cls();
attachSoundListeners();
}
else if (_source is String)
{
needsLoading = true;
_sound = new Sound();
attachSoundListeners();
}
else
{
var message:String = resourceManager.getString(
"effects", "incorrectSource");
throw new Error(message);
}
if (autoLoad)
load();
}
//----------------------------------
// startTime
//----------------------------------
[Inspectable(category="General", defaultValue="0")]
/**
* The initial position in the MP3 file, in milliseconds,
* at which playback should start.
*
* @default 0
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var startTime:Number = 0;
//----------------------------------
// useDuration
//----------------------------------
[Inspectable(category="General", defaultValue="true")]
/**
* If <code>true</code>, stop the effect
* after the time specified by the <code>duration</code>
* property has elapsed.
* If <code>false</code>, stop the effect
* after the MP3 finishes playing or looping.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var useDuration:Boolean = true;
//----------------------------------
// volumeEasingFunction
//----------------------------------
/**
* The easing function for the volume effect.
* This function is used to interpolate between the values
* of <code>volumeFrom</code> and <code>volumeTo</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var volumeEasingFunction:Function;
//----------------------------------
// volumeFrom
//----------------------------------
[Inspectable(category="General", defaultValue="1.0")]
/**
* Initial volume of the Sound object.
* Value can range from 0.0 to 1.0.
*
* @default 1
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var volumeFrom:Number;
//----------------------------------
// volumeTo
//----------------------------------
[Inspectable(category="General", defaultValue="1.0")]
/**
* Final volume of the Sound object.
* Value can range from 0.0 to 1.0.
*
* @default 1
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var volumeTo:Number;
//--------------------------------------------------------------------------
//
// Overridden methods
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function initInstance(instance:IEffectInstance):void
{
super.initInstance(instance);
var soundEffectInstance:SoundEffectInstance =
SoundEffectInstance(instance);
soundEffectInstance.source = source;
soundEffectInstance.sound = sound;
soundEffectInstance.panFrom = panFrom;
soundEffectInstance.panTo = panTo;
soundEffectInstance.volumeFrom = volumeFrom;
soundEffectInstance.volumeTo = volumeTo;
soundEffectInstance.panEasingFunction = panEasingFunction;
soundEffectInstance.volumeEasingFunction = volumeEasingFunction;
soundEffectInstance.loops = loops;
soundEffectInstance.startTime = startTime;
soundEffectInstance.useDuration = useDuration;
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* Loads the MP3 if the <code>source</code> property points to a URL.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function load():void
{
if (_sound && _source && _source is String && needsLoading)
_sound.load(new URLRequest(String(_source)), new SoundLoaderContext(bufferTime));
}
/**
* @private
*/
private function attachSoundListeners():void
{
if (_sound)
{
_sound.addEventListener(Event.COMPLETE, soundEventHandler);
_sound.addEventListener(ProgressEvent.PROGRESS, soundEventHandler);
_sound.addEventListener(IOErrorEvent.IO_ERROR, soundEventHandler);
_sound.addEventListener(Event.ID3, soundEventHandler);
}
}
/**
* @private
*/
private function removeSoundListeners():void
{
if (_sound)
{
_sound.removeEventListener(Event.COMPLETE, soundEventHandler);
_sound.removeEventListener(ProgressEvent.PROGRESS, soundEventHandler);
_sound.removeEventListener(IOErrorEvent.IO_ERROR, soundEventHandler);
_sound.removeEventListener(Event.ID3, soundEventHandler);
}
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* Just act as a proxy for all events from the sound.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private function soundEventHandler(event:Event):void
{
dispatchEvent(event);
}
}
}