/*****************************************************
*
* Copyright 2009 Adobe Systems Incorporated. All Rights Reserved.
*
*****************************************************
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
*
* The Initial Developer of the Original Code is Adobe Systems Incorporated.
* Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems
* Incorporated. All Rights Reserved.
*
*****************************************************/
package org.osmf.traits
{
import flash.errors.IllegalOperationError;
import org.osmf.events.LoadEvent;
import org.osmf.events.LoaderEvent;
import org.osmf.media.MediaResourceBase;
import org.osmf.utils.OSMFStrings;
/**
* Dispatched when the state of the LoadTrait has changed.
*
* @eventType org.osmf.events.LoadEvent.LOAD_STATE_CHANGE
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
[Event(name="loadStateChange", type="org.osmf.events.LoadEvent")]
/**
* Dispatched when total size in bytes of data being loaded has changed.
*
* @eventType org.osmf.events.LoadEvent.BYTES_TOTAL_CHANGE
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
[Event(name="bytesTotalChange",type="org.osmf.events.LoadEvent")]
/**
* LoadTrait defines the trait interface for media that must be loaded before it
* can be presented. It can also be used as the base class for a more specific
* LoadTrait subclass.
*
* <p>If <code>hasTrait(MediaTraitType.LOAD)</code> returns <code>true</code>,
* use the <code>MediaElement.getTrait(MediaTraitType.LOAD)</code> method
* to get an object of this type.</p>
*
* @see LoadState
* @see org.osmf.media.MediaElement
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public class LoadTrait extends MediaTraitBase
{
/**
* Constructor.
*
* @param loader The LoaderBase instance that will be used to load the
* media for the media element that owns this trait.
* @param resource The MediaResourceBase instance that represents the media resource
* to be loaded.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function LoadTrait(loader:LoaderBase, resource:MediaResourceBase)
{
super(MediaTraitType.LOAD);
this.loader = loader;
_resource = resource;
_loadState = LoadState.UNINITIALIZED;
if (loader != null)
{
// We set the highest possible priority to ensure that our handler
// is the first to process the loader's event. The reason for this
// is to ensure that clients that work with both a loader and a
// LoadTrait always perceive a consistent state between the two (which
// could be subverted if the loader updates its state, then the client
// gets the event, then the LoadTrait updates its state).
loader.addEventListener(LoaderEvent.LOAD_STATE_CHANGE, onLoadStateChange, false, int.MAX_VALUE, true);
}
}
/**
* Resource representing the piece of media to be loaded into
* this LoadTrait.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function get resource():MediaResourceBase
{
return _resource;
}
/**
* The load state of this trait. See LoadState for possible values.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function get loadState():String
{
return _loadState;
}
/**
* Loads this the media into this LoadTrait.
* Updates the load state.
* Dispatches the <code>loadStateChange</code> event with every state change.
*
* <p>Typical states are <code>LOADING</code> while the media is loading,
* <code>READY</code> after it has successfully completed loading,
* and <code>LOAD_ERROR</code> if it fails to complete loading.</p>
*
* <p>If the LoadState is <code>LOADING</code> or <code>READY</code>
* when the method is called, throws an error.</p>
*
* @see LoadState
* @throws IllegalOperationError If this trait is unable to load
* itself or if the LoadState is <code>LOADING</code> or
* <code>READY</code>.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function load():void
{
if (loader)
{
if (_loadState == LoadState.READY)
{
throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.ALREADY_READY));
}
if (_loadState == LoadState.LOADING)
{
throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.ALREADY_LOADING));
}
else
{
loader.load(this);
}
}
else
{
throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.MUST_SET_LOADER));
}
}
/**
* Unloads this LoadTrait. Updates the load state.
* Dispatches the <code>loadStateChange</code> event with every state change.
*
* <p>Typical states are <code>UNLOADING</code> while the media is unloading,
* <code>UNINITIALIZED</code> after it has successfully completed unloading,
* and <code>LOAD_ERROR</code> if it fails to complete unloading.</p>
*
* <p>If the LoadState is not <code>READY</code> when the
* method is called, throws an error.</p>
*
* @param loadTrait The LoadTrait to unload.
* @see LoadState
*
* @throws IllegalOperationError If this trait is unable to unload
* itself, or if the LoadState is not <code>READY</code>.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function unload():void
{
if (loader)
{
if (_loadState == LoadState.UNLOADING)
{
throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.ALREADY_UNLOADING));
}
if (_loadState == LoadState.UNINITIALIZED)
{
throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.ALREADY_UNLOADED));
}
loader.unload(this);
}
else
{
throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.MUST_SET_LOADER));
}
}
/**
* The number of bytes of data that have been loaded.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function get bytesLoaded():Number
{
return _bytesLoaded;
}
/**
* The total size in bytes of the data being loaded.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
public function get bytesTotal():Number
{
return _bytesTotal;
}
// Internals
//
/**
* Sets the load state for this LoadTrait.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected final function setLoadState(newState:String):void
{
if (_loadState != newState)
{
loadStateChangeStart(newState);
_loadState = newState;
loadStateChangeEnd();
}
}
/**
* Sets the number of bytes of data that have been loaded.
*
* @throws ArgumentError If value is negative, NaN, or greater than bytesTotal.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected final function setBytesLoaded(value:Number):void
{
if (isNaN(value) || value > bytesTotal || value < 0)
{
throw new ArgumentError(OSMFStrings.getString(OSMFStrings.INVALID_PARAM));
}
if (value != _bytesLoaded)
{
bytesLoadedChangeStart(value);
_bytesLoaded = value;
bytesLoadedChangeEnd();
}
}
/**
* Sets the total size in bytes of the data being loaded.
*
* @throws ArgumentError If value is negative or smaller than bytesLoaded.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected final function setBytesTotal(value:Number):void
{
if (value < _bytesLoaded || value < 0)
{
throw new ArgumentError(OSMFStrings.getString(OSMFStrings.INVALID_PARAM));
}
if (value != _bytesTotal)
{
bytesTotalChangeStart(value);
_bytesTotal = value;
bytesTotalChangeEnd();
}
}
/**
* Called immediately before the <code>bytesLoaded</code> property is changed.
* <p>Subclasses can override this method to communicate the change to the media.</p>
*
* @param newValue New <code>bytesLoaded</code> value.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected function bytesLoadedChangeStart(newValue:Number):void
{
}
/**
* Called just after the <code>bytesLoaded</code> property has changed.
*
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected function bytesLoadedChangeEnd():void
{
}
/**
* Called immediately before the <code>bytesTotal</code> property is changed.
* <p>Subclasses can override this method to communicate the change to the media.</p>
*
* @param newValue New <code>bytesTotal</code> value.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected function bytesTotalChangeStart(newValue:Number):void
{
}
/**
* Called just after the <code>bytesTotal</code> property has changed.
* Dispatches the bytesTotalChange event.
* <p>Subclasses that override should call this method to
* dispatch the bytesTotalChange event.</p>
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected function bytesTotalChangeEnd():void
{
dispatchEvent(new LoadEvent(LoadEvent.BYTES_TOTAL_CHANGE, false, false, null, _bytesTotal));
}
/**
* Called immediately before the <code>loadState</code>
* property is changed.
* <p>Subclasses can override this method to communicate the change to the media.</p>
*
* @param newState New <code>loadState</code> value.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected function loadStateChangeStart(newState:String):void
{
}
/**
* Called just after the <code>loadState</code> property is
* change.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 1.5
* @productversion OSMF 1.0
*/
protected function loadStateChangeEnd():void
{
dispatchEvent(new LoadEvent(LoadEvent.LOAD_STATE_CHANGE, false, false, _loadState));
}
private function onLoadStateChange(event:LoaderEvent):void
{
if (event.loadTrait == this)
{
setLoadState(event.newState);
}
}
private var loader:LoaderBase;
private var _resource:MediaResourceBase;
private var _loadState:String;
private var _bytesLoaded:Number;
private var _bytesTotal:Number;
}
}