Actionscript Media Framework

Sorry, you need to install flash to see this content.

Example Code

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