// The following is a Flash AS3 example
// The example uses the Flash UIComponents and provides a demonstration of how
// to interact with the highest level component, MediaDisplayComponent all
// components including the MediaDisplayComponent already exist on the stage
// The example illustrates the major events that playbacks dispatch as well
// as some (not all) of the properties that they possess
package
{
// flash controls
import fl.controls.Button;
import fl.controls.CheckBox;
import fl.controls.ComboBox;
import fl.controls.NumericStepper;
import fl.controls.TextArea;
import fl.controls.TextInput;
import fl.data.DataProvider;
// player objects
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
// media framework
import com.dreamsocket.events.BufferTimeEvent;
import com.dreamsocket.events.DownloadEvent;
import com.dreamsocket.events.MediaRequestEvent;
import com.dreamsocket.events.MediaExceptionEvent;
import com.dreamsocket.events.PlayEvent;
import com.dreamsocket.events.StateChangeEvent;
import com.dreamsocket.events.TimeEvent;
import com.dreamsocket.flash.components.MediaDisplayComponent;
import com.dreamsocket.layout.HorizontalAlign;
import com.dreamsocket.layout.VerticalAlign;
import com.dreamsocket.media.IMediaSource;
import com.dreamsocket.media.ScaleMode;
import com.dreamsocket.media.MediaObject;
import com.dreamsocket.media.MediaSourceSelector;
import com.dreamsocket.media.MediaSource;
import com.dreamsocket.media.ByteRangeNS;
import com.dreamsocket.media.byteRangeNSClasses.ByteRangeNSRequestBuilder;
import com.dreamsocket.media.streamingNSClasses.StreamingNSRequestBuilder;
import com.dreamsocket.media.streamingNSClasses.StreamingNSRequestFactory;
public class TestMediaDisplayComponent extends Sprite
{
// playback control
public var control:MediaDisplayComponent;
// button used for clearing traced output
public var ui_clearBtn:Button;
// buttons used for controlling playback
public var ui_playBtn:Button;
public var ui_pauseBtn:Button;
public var ui_seekBtn:Button;
public var ui_loadBtn:Button;
public var ui_stopBtn:Button;
// check boxes for setting playback properties
public var ui_autoDetectChk:CheckBox;
public var ui_autoPlayChk:CheckBox;
public var ui_rewindChk:CheckBox;
// controls for changing alignment
public var ui_hAlign:ComboBox;
public var ui_vAlign:ComboBox;
// control for changing scaleMode
public var ui_scaleMode:ComboBox;
// control for changing the playback type if you turn autoDetectPlayback off
public var ui_format:ComboBox;
// editable comboBox used for setting the url of the media to load
public var ui_mediaURLTxt:ComboBox;
// numeric steppers for changing playback dimensions
public var ui_height:NumericStepper;
public var ui_width:NumericStepper;
// numeric stepper used to seek media (typically a slider)
public var ui_position:NumericStepper;
// numeric stepper used to set volume (typically be a slider)
public var ui_volume:NumericStepper;
// textfield for setting the poster (Image slate associated with the media)
public var ui_posterURLTxt:TextInput;
// text area used for showing output
public var ui_traceTxt:TextArea;
// text fields used for showing various properties of the playback
public var ui_bufferProgressTxt:TextField;
public var ui_bufferingTxt:TextField;
public var ui_currentDownloadProgressTxt:TextField;
public var ui_downloadingTxt:TextField;
public var ui_durationTxt:TextField;
public var ui_currentTimeTxt:TextField;
public var ui_formatLabel:TextField;
public var ui_stateTxt:TextField;
public var ui_timeDownloadedTxt:TextField;
public var ui_timeSeekableTxt:TextField;
public var ui_totalDownloadProgressTxt:TextField;
// background behind the playback
public var ui_bounds:Sprite;
public function TestMediaDisplayComponent()
{
// in our example we don't need to setup a stream builders because the defaults will create the stream request properly
// we provide the example to show you how you would do it
// stream builders are important in case you need to setup streams across CDNs that have odd app paths, security tokens, non reusable connections, etc
// by doing this you can just pass full URLs to the player and it can configure the requests
// it is also important to note that at lower levels like StreamingNS
// stream builders aren't imported so you have the option of creating connections and request differently
var streamFactory:StreamingNSRequestFactory = StreamingNSRequestFactory.getInstance();
// In this example..
// Create a builder that matches any server, an application that is called pmsales/integration, and any file type
// The builder will:
// reuse the netconnection
// not add the stream extension (ex: foo.flv becomes foo)
// not add the stream type (ex if it were true: foo.flv would become flv:foo)
// and define the application as pmsales/integration
streamFactory.addBuilder("*", "pmsales/integration", "*", new StreamingNSRequestBuilder({allowNCReuse:true,useStreamExtension:false, useStreamType:false, app:"pmsales/integration"}));
// for all byte range request set the default request builder (NOTE: you can create your own with IByteRangeNSRequestBuilder)
// the first parameter gives a string in the URL to match
// the second parameter gives a template to associate with that match
// the template is used to create the byte range requests
// in this case urls will be built like http://clients.dreamsocket.com/test/stream.php?file=test.flv&start=20
ByteRangeNS.defaultRequestBuilder = new ByteRangeNSRequestBuilder("http://examples.dreamsocket.com/asmediaframework/byterangens/?file=", "http://examples.dreamsocket.com/asmediaframework/byterangens/?file=${FILE_URL}&start=${FILE_POS}");
// default the media poster to the sample jpg
ui_posterURLTxt.text = "test.jpg";
// test urls
// when set the playback will immediately switch formats if needed and play the file
var testURLs:Array = [
"test.flv",
"test.jpg",
"test.mp3",
"SWFMediaAsset.swf",
"http://examples.dreamsocket.com/asmediaframework/byterangens/?file=test.flv",
"rtmp://pmsalesfs.fplive.net/pmsales/integration/AnalystOpener500.flv"
];
// playback types to use if autoDetectPlayback is false
var formats:Array = [
"progressiveNS",
"byteRangeNS",
"streamingNS",
"timedImage",
"sound",
"soundWithImage",
"timelineSWF"
];
// possible vertical alignments of the playback
var vAlign:Array = [
VerticalAlign.MIDDLE,
VerticalAlign.TOP,
VerticalAlign.BOTTOM
];
// possible horizontal alignments of the playback
var hAlign:Array = [
HorizontalAlign.CENTER,
HorizontalAlign.LEFT,
HorizontalAlign.RIGHT
];
// possible scaleModes for the playback
var scaleModes:Array = [
ScaleMode.UNIFORM,
ScaleMode.FILL,
ScaleMode.NONE
];
// set up the alignment controls with their values
this.ui_hAlign.dataProvider = new DataProvider(hAlign);
this.ui_vAlign.dataProvider = new DataProvider(vAlign);
// set up the playbackType selector which is used when autoDetectPlayback is false
this.ui_format.dataProvider = new DataProvider(formats);
this.ui_format.selectedIndex = 0;
this.ui_format.enabled = false;
// set up the scaleMode selector
this.ui_scaleMode.dataProvider = new DataProvider(scaleModes);
// setup the media url selector
this.ui_mediaURLTxt.editable = true;
this.ui_mediaURLTxt.dataProvider = new DataProvider(testURLs);
this.ui_mediaURLTxt.selectedIndex = 0;
// setup the controls that change the playback's size
this.ui_width.minimum = 1;
this.ui_width.maximum = 465;
this.ui_width.value = 320;
this.ui_height.minimum = 1;
this.ui_height.maximum = 320;
this.ui_height.value = 240;
// default autoPlay control to true
this.ui_autoPlayChk.selected = true;
// default autoDetectPlayback control to true
this.ui_autoDetectChk.selected = true;
// set the playback seek control to nonseekable defaults
this.ui_position.value = 0;
this.ui_position.minimum = 0;
this.ui_position.maximum = 0;
// the following is an example of setting the source selector to a custom media selector and playback resolver
// there is a default resolver, but this illustrates how to do a custom one
control.sourceSelector = new MediaSourceSelector(new CustomPlaybackResolver());
// listen for all media events generated by the playback
control.addEventListener(BufferTimeEvent.BUFFER_TIME_STARTED, this.onBufferState);
control.addEventListener(BufferTimeEvent.BUFFER_TIME_PROGRESS, this.onBufferProgress);
control.addEventListener(BufferTimeEvent.BUFFER_TIME_STOPPED, this.onBufferState);
control.addEventListener(MediaRequestEvent.MEDIA_REQUEST_CLOSED, this.onEvent);
control.addEventListener(MediaRequestEvent.MEDIA_REQUEST_LOADING, this.onEvent);
control.addEventListener(MediaRequestEvent.MEDIA_REQUEST_OPENING, this.onEvent);
control.addEventListener(MediaRequestEvent.MEDIA_REQUEST_READY, this.onMediaReady);
control.addEventListener(PlayEvent.PLAY_STARTED, this.onEvent);
control.addEventListener(PlayEvent.PLAY_RESUMED, this.onEvent);
control.addEventListener(PlayEvent.PLAY_PAUSED, this.onEvent);
control.addEventListener(PlayEvent.PLAY_ENDED, this.onEvent);
control.addEventListener(PlayEvent.PLAY_STOPPED, this.onEvent);
control.addEventListener(StateChangeEvent.STATE_CHANGED, this.onStateChanged);
control.addEventListener(TimeEvent.TIME_DURATION_CHANGED, this.onDurationChanged);
control.addEventListener(TimeEvent.TIME_SEEKABLE_CHANGED, this.onSeekableChanged);
control.addEventListener(TimeEvent.TIME_POSITION_CHANGED, this.onTimePositionChanged);
control.addEventListener(DownloadEvent.DOWNLOAD_STARTED, this.onDownloadState);
control.addEventListener(DownloadEvent.DOWNLOAD_PROGRESS, this.onDownloadProgress);
control.addEventListener(DownloadEvent.DOWNLOAD_STOPPED, this.onDownloadState);
control.addEventListener(MediaExceptionEvent.MEDIA_ASYNC_EXCEPTION, this.onEvent);
control.addEventListener(MediaExceptionEvent.MEDIA_IO_EXCEPTION, this.onEvent);
control.addEventListener(MediaExceptionEvent.MEDIA_SECURITY_EXCEPTION, this.onEvent);
// assign handlers that respond to ui control events
ui_autoDetectChk.addEventListener("click", this.onSetAutoDetect);
ui_clearBtn.addEventListener("click", this.onClearTrace);
ui_autoPlayChk.addEventListener("click", this.onSetAutoPlay);
ui_playBtn.addEventListener("click", this.onPlayPress);
ui_pauseBtn.addEventListener("click", this.onPausePress);
ui_seekBtn.addEventListener("click", this.onSeekPress);
ui_loadBtn.addEventListener("click", this.onRequestAsset);
ui_rewindChk.addEventListener("click", this.onSetAutoRewind);
ui_volume.addEventListener("change", this.onSetVolume);
ui_stopBtn.addEventListener("click", this.onStop);
ui_format.addEventListener("change", this.onSetFormat);
ui_width.addEventListener("change", this.onSetSize);
ui_height.addEventListener("change", this.onSetSize);
ui_scaleMode.addEventListener("change", this.onSetScaleMode);
ui_vAlign.addEventListener("change", this.onSetAlignment);
ui_hAlign.addEventListener("change", this.onSetAlignment);
}
function onBufferProgress(p_evt:BufferTimeEvent):void
{
// media bufferProgress has changed, show percent
// NOTE: buffer progress can occur when paused
// if creating a slideshow, you can use this at the beginning when state is LOADING
// if you only want to show buffering while playing (like typical video players) only show progress when the playback's state is BUFFERING
// you can get state changes from the StateChangeEvent
ui_bufferProgressTxt.text = String(p_evt.progress.toFixed(2));
}
function onBufferState(p_evt:BufferTimeEvent):void
{
// an item has stopped or started buffering
// NOTE: this state change is independent of pause, which allows for showing loading between elements of a slideshow
// if you only want to show buffering while playing (like typical video players) only show progress when the playback's state is BUFFERING
// you can get state changes from the StateChangeEvent
ui_bufferingTxt.text = (p_evt.type == BufferTimeEvent.BUFFER_TIME_STARTED) ? "TRUE" : "FALSE";
}
function onClearTrace(p_evt:Object):void
{
// wipe the text output clean
ui_traceTxt.text = "";
}
function onDurationChanged(p_evt:Object):void
{
// show the duration changed
// this occurs when media switches or when it becomes "ready"
// with DVR as media progresses, this could change as well
ui_durationTxt.text = String(control.duration);
}
function onDownloadProgress(p_evt:DownloadEvent):void
{
// percent of current download progress
// this is always in the range of 0 - 1 (streaming is 0)
// ByteRange request this value represents the % of the current range requested, when ended would be 1
ui_currentDownloadProgressTxt.text = String(p_evt.currentProgress.toFixed(2));
// percent of total download progress
// this is always in the range of 0 - 1 (streaming is 0)
// ByteRange requests this value represent the % of the total file byte range,
// therefore if the the requested range was 50% into the video, when the range completed total downloaded would be .5
// this allows you to create load bars like YouTube's (they use byte range requests)
// These loaders start at the point of seek in the scrubber and move forwared from there
ui_timeDownloadedTxt.text = String(control.timeDownloaded.start + " : " + control.timeDownloaded.end.toFixed(2));
// here you could also use bytesDownloaded to show a bytes based number
// control.bytesDownloaded.start, control.bytesDownloaded.start
}
function onDownloadState(p_evt:DownloadEvent):void
{
// both DOWNLOAD_STARTED & DOWNLOAD_STOPPED events are being routed here
// check which event occured to show when media has started or stopped downloading
// media stops downloading when it has completely finished or when it has been cancelled
ui_downloadingTxt.text = (p_evt.type == DownloadEvent.DOWNLOAD_STARTED) ? "TRUE" : "FALSE";
}
function onEvent(p_evt:Object):void
{
// record some of the events here
ui_traceTxt.text += p_evt + "\n\n";
}
function onMediaReady(p_evt:Object):void
{
// the media has whatever intrinsic metadata it needs and is ready to play
onSetSize(p_evt);
}
function onPausePress(p_evt:Object):void
{
// pause button pressed, pause the media
// if pressed during a load and prior to play when autoPlay is true, it flags the media to pause when ready
control.pause();
}
function onPlayPress(p_evt:Object):void
{
// play button, pressed play the media
// if pressed during a load and prior to play when autoPlay is false, it flags the media to play when ready
control.play();
}
function onRequestAsset(p_evt:Object):void
{
// clear out any events we recorded to output
ui_traceTxt.text = "";
// set the seek controls limit to 0
ui_position.maximum = 0;
// set the media for the playback
// NOTE: poster is an associated image
control.media = new MediaObject(new MediaSource(ui_mediaURLTxt.text), ui_posterURLTxt.text);
}
function onSeekableChanged(p_evt:TimeEvent):void
{
// the amount a media can be seeked has changed
// use the timeSeekable property to determine the range at which you can seek
// streaming and byte range media this is the duration once the media is ready
// live this is 0
// progressive is the timed downloaded
// dvr could be a floating range
// limit the control so that it doesn't allow the user to seek ahead
ui_position.maximum = control.timeSeekable.end;
// show the seekable time
// NOTE: DVR could also use control.timeSeekable.start
ui_timeSeekableTxt.text = String(control.timeSeekable.end.toFixed(2));
}
function onSeekPress(p_evt:Object):void
{
// seek to a time in the media
// a TimeEvent.TIME_POSITION_CHANGED will fire immediately if the seek is in a valid range
// and the currentTime property will also be reflected immediately
control.currentTime = (ui_position.value);
}
function onSetAutoDetect(p_evt:Object):void
{
// if turning on autodetect, dont allow users to select format and provide UI feedback
this.ui_format.enabled = !this.ui_autoDetectChk.selected;
this.ui_formatLabel.textColor = this.ui_autoDetectChk.selected ? 0xCCCCCC : 0x000000;
// toggle autoDetectPlayback
// if selected it attempts to auto choose your media format
// you can can create your own IPlaybackResolver which takes a URL and returns a playback based on what you decide that URL is
// there is a default PlaybackResolver being used
this.control.autoDetectPlayback = this.ui_autoDetectChk.selected;
// if turning off autodetect let's set the playback type to what is defined in the playback selector control
if(!this.ui_autoDetectChk.selected)
this.control.playbackType = String(this.ui_format.value);
}
function onSetAutoPlay(p_evt:Object):void
{
// determine whether media will automatically start playing when it is loaded
control.autoPlay = ui_autoPlayChk.selected;
}
function onSetAutoRewind(p_evt:Object):void
{
// set whether the media will automatically rewind and pause when it ends
// or whether it will stop at the end when it completes
// if autoRewind is set to true, the state will be set to STOPPED at completion, otherwise it is set to ENDED
// this allows you to have different view states depending on your state
// in both cases the PlayEvent.PLAY_ENDED will fire
// if auto rewound, TimeEvent.TIME_POSITION_CHANGED will also fire
control.autoRewind = ui_rewindChk.selected;
}
function onSetAlignment(p_evt:Object):void
{
// vertically align the media within its bounds (top, middle, bottom)
control.verticalAlign = String(ui_vAlign.value);
// horizontally align the media within its bounds (left, center, right)
control.horizontalAlign = String(ui_hAlign.value);
}
function onSetFormat(p_evt:Object):void
{
// since we are changing formats, for the example lets close the existing media
// This ensures you aren't switching to an incompatible type
control.close();
// instead of letting autoDetectPlayback choose what the format is, set it explicitly
// playback types are the exact names that they were registered when the playback was added to the factory
// or they are the aliases registered with the exact name
// in the component all playbacks are preregistered and aliases added
this.control.playbackType = String(this.ui_format.value);
}
function onSetScaleMode(p_evt:Object):void
{
// change the scale mode of the playback
// this can be uniform, fill, none (constants are found in com.dreamsocket.media.ScaleMode)
// uniform maintains aspect ratio
// fill fits the media to the exact size of its bounds
// none causes the media not to scale
// if set to none this will also crop the image based on its alignment
control.scaleMode = ui_scaleMode.value;
}
function onSetSize(p_evt:Object):void
{
// set the size of the background element in the example
ui_bounds.width = ui_width.value;
ui_bounds.height = ui_height.value;
// set the size of the actual playback control
control.setActualSize(ui_width.value, ui_height.value);
}
function onSetVolume(p_evt:Object):void
{
// set the volume of the playback using a 0-1 range
control.volume = ui_volume.value;
}
function onStateChanged(p_evt:StateChangeEvent):void
{
// the media has changed state, the states are found in com.dreamsocket.media.MediaState
// BUFFERING, CLOSED, ENDED, ERROR, LOADING, PAUSED, PLAYING, STOPPED
// these are definitive states which you can use to determine what you want to show at any given time
// Take note that the Flex GUMBO components are based on states, so the components are preprepped for their arrival
ui_stateTxt.text = p_evt.newState.toUpperCase();
}
function onStop(p_evt:Object):void
{
// stop button pressed, this resets media to the beginning, stops it playing, and sets the state to STOPPED
// it does not stop it loading, the close method cancels media loads
control.stop();
}
function onTimePositionChanged(p_evt:TimeEvent):void
{
// current time changed so show it
// additionally we could use com.dreamsocket.media.TimeFormatter here
// ex: if we wanted to show hours : minutes : seconds (01:20:30)
// create a formatter using a string that has the hours, minutes, and seconds tokens to replace
// var fmtr:TimeFormatter = new TimeFormatter("${H}:${M}:${S}");
// ui_currentTimeTxt.text = fmtr.format(control.currentTime);
ui_currentTimeTxt.text = String(control.currentTime.toFixed(2));
}
}
}
import com.dreamsocket.media.IMediaSource
import com.dreamsocket.media.IPlaybackResolver;
import com.dreamsocket.media.PlaybackResolver;
// The following is a custom playback resolver that analyzes the media object and determines
// what type of playback. The MediaDisplayComponent has a default resolver which handles almost all
// resolves except byte range netstreams. This is an example of how you might want to implement a resolver
internal class CustomPlaybackResolver implements IPlaybackResolver
{
protected var m_defaultResolver:PlaybackResolver;
public function CustomPlaybackResolver()
{
super();
this.m_defaultResolver = new PlaybackResolver();
}
public function resolvePlayback(p_source:IMediaSource):void
{
if(p_source == null || p_source.url == null || p_source.playback != null) return;
var URL:String = p_source.url;
// the URL is a path the a byte range stream, set the playback to byterangens
if(URL.indexOf("examples.dreamsocket.com/asmediaframework/byterangens") != -1)
{
p_source.playback = "byterangens";
}
else
{
this.m_defaultResolver.resolvePlayback(p_source);
}
}
}