Last active
December 16, 2015 11:39
-
-
Save rozklad/5428707 to your computer and use it in GitHub Desktop.
AS3 media player
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package { | |
import flash.geom.*; | |
import flash.display.Loader; | |
import flash.display.MovieClip; | |
import flash.display.Stage; | |
import flash.display.StageScaleMode; | |
import flash.display.StageAlign; | |
import flash.display.StageDisplayState; | |
import flash.events.Event; | |
import flash.events.IOErrorEvent | |
import flash.events.MouseEvent; | |
import flash.events.NetStatusEvent; | |
import flash.events.ProgressEvent; | |
import flash.events.AsyncErrorEvent; | |
import flash.media.Video; | |
import flash.media.Sound; | |
import flash.media.SoundChannel; | |
import flash.media.SoundTransform; | |
import flash.net.URLRequest; | |
import flash.net.navigateToURL; | |
import flash.net.NetConnection; | |
import flash.net.NetStream; | |
import flash.text.TextField; | |
import flash.text.TextFieldAutoSize; | |
import flash.utils.setInterval; | |
import flash.utils.clearInterval; | |
// Respects ActionScript 3.0 Coding Conventions: http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions | |
public class Player extends MovieClip { | |
// Settings and factory defaults | |
var settings:Object = {}; | |
var factory:Object = { name: 'Player sample', // Name to show in status bar | |
link: 'http://www.example.com', // Link to pop up by clicking on name | |
//audio: 'media/custom.mp3', // Default audiofile path | |
audio: false, | |
video: 'media/video.mp4', // Default videofile path | |
thumb: 'media/poster.jpg', // Default thumbnail path | |
linkColor: 'CCCCCC', // Color of links | |
hoverColor: 'FFFFFF', // Hover color of links | |
buffer: 5, // Buffer time in seconds | |
expandedBuffer: 20, // Expanded buffer | |
inactiveToHide: 5, // Inactive time needed to hide controls in seconds | |
controlsHeight: 40, // Height of controls panel | |
controlsMargin: 0, // Margin of controls panel (goes for status bar as well) | |
soundVolume: 0.6, // Startup volume of sound | |
autoplay: false, // Automatically play on load (true/false) | |
scrubVolume: true, // True enables volume scrubbing, false sets volume to on/off button | |
debug: true, // Debug mode (true/false) | |
startMode: true, // Starting screen mode | |
startMargin: 0, // Starting screen mode margin | |
animate: true // Animate hide and show actions | |
} | |
// netStream | |
var nc:NetConnection; | |
var ns:NetStream; | |
var meta:Object; | |
// True = video, False = audio | |
var media:Boolean; | |
// Save position for resuming audio | |
var position:Number; | |
// Video data | |
var path:String; | |
var video:Video; | |
var audio:Sound; | |
var channel:SoundChannel; | |
var sound:SoundTransform; | |
var duration:Number; | |
var amountLoaded:Number; | |
var amountPlayed:Number; | |
var currentTime:int; | |
// References to objects | |
var thumbScreen:MovieClip; | |
var videoScreen:MovieClip; | |
var curtain:MovieClip; | |
var controls:MovieClip; | |
var status:MovieClip; | |
// Indicators | |
var played:Boolean = false; | |
var started:Boolean = false; | |
var controlsState:Boolean = true; | |
var inactive:int = 0; | |
// Intervals | |
var interval = intervalInit(0); | |
var sideInterval; | |
// Helper variables | |
var lastMouseX:int; | |
var lastMouseY:int; | |
// -------------------------------------------------------------------- | |
// | |
// Player methods | |
// | |
// -------------------------------------------------------------------- | |
/** | |
* Player | |
* | |
* Constructor method assigns object references from flash movie | |
* to actionscript class. | |
* | |
* @access public | |
* @param thumbScreenRef MovieClip Reference to thumbnail screen | |
* @param videoScreenRef MovieClip Reference to video screen | |
* @param curtainRef MovieClip Reference to curtain | |
* @param controlsRef MovieClip Reference to controls panel | |
* @param statusRef MovieClip Reference to status bar | |
* @return void | |
*/ | |
public function Player(thumbScreenRef:MovieClip, videoScreenRef:MovieClip, curtainRef:MovieClip, controlsRef:MovieClip, statusRef:MovieClip):void { | |
thumbScreen = thumbScreenRef; | |
videoScreen = videoScreenRef; | |
curtain = curtainRef; | |
controls = controlsRef; | |
status = statusRef; | |
addEventListener(Event.ADDED_TO_STAGE, init); // Fire init() when class loaded to stage (addChild() function fires Event.ADDED_TO_STAGE) | |
} | |
// -------------------------------------------------------------------- | |
/** | |
* init | |
* | |
* Initialization of essential settings and functions. Uses custom events | |
* to chain initialization. (When A is loaded => init B, When B is loaded => | |
* init C etc.) | |
* | |
* @access private | |
* @param event Event event data by listener | |
* @return void | |
*/ | |
private function init(event:Event):void { | |
removeEventListener(Event.ADDED_TO_STAGE, init); // Remove firing init() | |
settings = settingsFactory(stage.loaderInfo.parameters); // Load settings or use factory defaults | |
stage.addEventListener('prepared', thumbInit); | |
stage.addEventListener('thumbLoaded', streamInit); | |
stage.addEventListener('streamLoaded', controlsInit); | |
stage.addEventListener('controlsLoaded', statusInit); | |
stage.addEventListener('statusLoaded', soundInit); | |
prepare(); // Init first init method to start chain initialization | |
stage.addEventListener(Event.RESIZE, resize); // Respond to resize | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Resize methods | |
// | |
// -------------------------------------------------------------------- | |
private function resize(event:Event):void { | |
resizeControls(); | |
resizeStatus(); | |
resizeVideo(); | |
resizeThumb(); | |
} | |
private function resizeWidth(element:MovieClip):void { | |
element.bg.width = stage.stageWidth - 2*settings.controlsMargin; | |
} | |
private function getCenter(element:MovieClip):int { | |
return element.width/2; | |
} | |
private function getMiddle(element:MovieClip):int { | |
return element.height/2; | |
} | |
private function resizeControls():void { | |
resizeWidth(controls); | |
controls.bg.height = settings.controlsHeight; | |
controls.y = stage.stageHeight - controls.bg.height - settings.controlsMargin; | |
controls.playBtn.x = getCenter(controls.playBtn); | |
controls.playBtn.y = getMiddle(controls.playBtn); | |
controls.bg.x = 0; | |
controls.bg.y = 0; | |
controls.fullBtn.x = stage.stageWidth - getCenter(controls.fullBtn) - settings.controlsMargin; | |
controls.soundBtn.x = stage.stageWidth - getCenter(controls.soundBtn) - controls.fullBtn.width - settings.controlsMargin; | |
controls.volumeScrubber.x = controls.soundBtn.x; | |
resizeControlsScrubber(); | |
} | |
private function resizeControlsScrubber():void { | |
controls.scrubber.container.width = stage.stageWidth - 2*settings.controlsMargin - controls.soundBtn.width - controls.fullBtn.width*1.5 - controls.playBtn.width; | |
controls.scrubber.x = controls.playBtn.width*1.25; | |
} | |
private function resizeStatus():void { | |
resizeWidth(status); | |
status.heading.bg.width = stage.stageWidth; | |
status.y = settings.controlsMargin; | |
status.buffer.y = stage.stageHeight/2 - status.buffer.height/2; | |
status.buffer.width = stage.stageWidth; | |
} | |
private function resizeVideo():void { | |
status.heading.content.text = stage.stageWidth + ' ' + stage.stageHeight; | |
videoScreen.width = stage.stageWidth; | |
videoScreen.height = stage.stageHeight; | |
} | |
private function resizeThumb():void { | |
thumbScreen.width = stage.stageWidth; | |
thumbScreen.height = stage.stageHeight; | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Interval | |
// | |
// -------------------------------------------------------------------- | |
// Could be achived through Timer Class | |
// -------------------------------------------------------------------- | |
private function intervalInit(kind:int):Number { | |
switch (kind) { | |
case 0: | |
{ | |
return setInterval(streamInterval, 100); | |
break; | |
} | |
case 1: | |
{ | |
return setInterval(scrubbingInterval, 10); | |
break; | |
} | |
case 2: | |
{ | |
return setInterval(scrubberInterval, 10); | |
break; | |
} | |
case 3: | |
{ | |
return setInterval(bufferInterval, 100); | |
break; | |
} | |
default: | |
{ | |
return 0; | |
} | |
} | |
} | |
private function streamInterval() { | |
updateTrack(); | |
currentTime = Math.ceil(ns.time); | |
updateTime(currentTime); | |
controls.timer.x = controls.scrubber.played.width + controls.timer.width - controls.scrubber.scrubber.width; | |
checkMovement(); | |
} | |
private function scrubberInterval():void { | |
updateTrack(); | |
controls.timer.x = mouseX - controls.timer.width/2; | |
currentTime = pos2Time(controls.timer.x, controls.scrubber.container); | |
updateTime(currentTime); | |
} | |
private function scrubbingInterval():void { | |
controls.timer.x = controls.scrubber.scrubber.x + controls.timer.width - controls.scrubber.scrubber.width; | |
currentTime = pos2Time(controls.timer.x, controls.scrubber.container); | |
updateTime(currentTime); | |
} | |
private function bufferInterval():void { | |
updateTrack(); | |
currentTime = Math.ceil(ns.time); | |
updateTime(currentTime); | |
controls.timer.x = controls.scrubber.played.width + controls.timer.width - controls.scrubber.scrubber.width; | |
var buffered = getBuffered(); | |
if (buffered > 99) { | |
status.buffer.visible = false; | |
} else { | |
status.buffer.visible = true; | |
status.buffer.text = String(buffered) + '%'; | |
} | |
} | |
function getBuffered():int { | |
return Math.round((ns.bufferLength/ns.bufferTime)*100); | |
} | |
private function checkMovement():void { | |
var posMouseX = stage.mouseX; | |
var posMouseY = stage.mouseY; | |
if (played) { | |
if (lastMouseX == posMouseX && lastMouseY == posMouseY) | |
inactive++; | |
else | |
inactive = 0; | |
} | |
if (inactive < settings.inactiveToHide * 10) { | |
if (!controlsState) | |
controlsShow(); | |
} else { | |
if (controlsState) | |
controlsHide(); | |
} | |
lastMouseX = posMouseX; | |
lastMouseY = posMouseY; | |
} | |
private function updateTime(currentTime) { | |
controls.timer.content.text = formatTime(currentTime); | |
} | |
private function formatTime(time:int):String { | |
var secs:String = (time % 60).toString(); | |
secs = (secs.length == 1 ? '0' : '') + secs; | |
var mins:String = Math.floor(time / 60).toString(); | |
mins = (mins.length == 1 ? '0' : '') + mins; | |
return mins + ':' + secs; | |
} | |
private function mouse2Time():int { | |
return pos2Time(mouseX - controls.timer.width/2, controls.scrubber.container); | |
} | |
private function pos2Time(scrubber:int, track:MovieClip):int { | |
return Math.ceil(duration * (scrubber/track.width)); | |
} | |
private function updateTrack():void { | |
amountPlayed = ns.time / duration; | |
amountLoaded = ns.bytesLoaded / ns.bytesTotal; | |
if (amountPlayed < 0.05 && duration < 20) | |
amountPlayed = 0; // Show less than 5% played as 0% for extremely short videos | |
controls.scrubber.loaded.width = amountLoaded * controls.scrubber.container.width; | |
controls.scrubber.played.width = amountPlayed * controls.scrubber.container.width; | |
controls.scrubber.scrubber.x = controls.scrubber.played.width; | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Volume methods | |
// | |
// -------------------------------------------------------------------- | |
private function volumeButton(show:Boolean):void { | |
if (settings.scrubVolume) { | |
controls.volumeScrubber.visible = show; | |
controls.soundBtn.visible = false; | |
volumeScrubberDefault(); | |
} else { | |
controls.volumeScrubber.visible = true; | |
controls.soundBtn.visible = show; | |
} | |
} | |
private function volumeDefault():void { | |
volumeButton(true); | |
} | |
private function volumeScrubberDefault():void { | |
var buttons:Array /* of MovieClips */ = [controls.volumeScrubber.volume0, controls.volumeScrubber.volume20, controls.volumeScrubber.volume40, | |
controls.volumeScrubber.volume60, controls.volumeScrubber.volume80, controls.volumeScrubber.volume100, | |
controls.volumeScrubber.volumeMAX]; | |
for (var i = 0; i<buttons.length; i++) { | |
buttonize(buttons[i], btnOver, volumeOut, pressVolume); | |
} | |
} | |
private function volumeOut(event:MouseEvent):void { | |
if (media) { | |
if (voumeGetPieceVolume(event) > ns.soundTransform.volume) | |
event.currentTarget.gotoAndPlay('out'); | |
} else { | |
if (voumeGetPieceVolume(event) > channel.soundTransform.volume) | |
event.currentTarget.gotoAndPlay('out'); | |
} | |
} | |
private function voumeGetPieceVolume(event:MouseEvent):Number { | |
var pieceName:String = event.currentTarget.name.substr(6,3); | |
var pieceVolume:Number = 0.0; | |
if (pieceName == 'MAX') { | |
pieceVolume = 100; | |
} else { | |
pieceVolume = Number(pieceName); | |
} | |
return pieceVolume/100; | |
} | |
private function volumeReflect(volume:Number, originalVolume:Number):void { | |
var buttons:Array /* of MovieClips */ = [controls.volumeScrubber.volume20, controls.volumeScrubber.volume40, | |
controls.volumeScrubber.volume60, controls.volumeScrubber.volume80, controls.volumeScrubber.volume100]; | |
var volumes:Array /* of Numbers */ = [0.2, 0.4, 0.6, 0.8, 1.0]; | |
var loops:int = buttons.length; | |
for (var i = 0; i<loops; i++) { | |
if (volume>=volumes[i]) | |
buttons[i].gotoAndPlay('over'); | |
else | |
buttons[i].gotoAndPlay('out'); | |
} | |
} | |
private function pressVolume(event:MouseEvent):void { | |
switch (event.currentTarget.name) | |
{ | |
case 'volume0': | |
{ | |
soundSet(0); | |
break; | |
} | |
case 'volume20': | |
{ | |
soundSet(0.2); | |
break; | |
} | |
case 'volume40': | |
{ | |
soundSet(0.4); | |
break; | |
} | |
case 'volume60': | |
{ | |
soundSet(0.6); | |
break; | |
} | |
case 'volume80': | |
{ | |
soundSet(0.8); | |
break; | |
} | |
case 'volume100': | |
{ | |
soundSet(1); | |
break; | |
} | |
case 'volumeMAX': | |
{ | |
soundSet(1); | |
break; | |
} | |
} | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Controls methods | |
// | |
// -------------------------------------------------------------------- | |
private function controlsScrubberDefault():void { | |
controls.scrubber.loaded.width = 1; | |
controls.scrubber.played.width = 1; | |
controlsHideTimer(); | |
} | |
private function controlsHideTimer():void { | |
controls.timer.visible = false; | |
} | |
private function controlsShowTimer():void { | |
controls.timer.visible = true; | |
} | |
private function controlsHide():void { | |
debug('controlsHide'); | |
if (settings.animate) | |
controlsAnimate(false); | |
else | |
controls.visible = false; | |
controlsState = false; | |
} | |
private function controlsShow():void { | |
debug('controlsShow'); | |
if (settings.animate) | |
controlsAnimate(true); | |
else | |
controls.visible = true; | |
controlsState = true; | |
} | |
private function controlsAnimate(show:Boolean):void { | |
clearInterval(sideInterval); | |
if (show) | |
sideInterval = setInterval(controlsAnimateShow, 10); | |
else | |
sideInterval = setInterval(controlsAnimateHide, 10); | |
} | |
private function controlsAnimateShow():void { | |
controls.y -= 1; | |
if (controls.y <= stage.stageHeight - settings.controlsHeight) { | |
clearInterval(sideInterval); | |
} | |
} | |
private function controlsAnimateHide():void { | |
controls.y += 1; | |
if (controls.y >= stage.stageHeight) { | |
clearInterval(sideInterval); | |
} | |
} | |
private function controlsInit(event:Event):void { | |
debug('controlsInit'); | |
// Set scale mode to NO_SCALE (does not resize elements) and put stage to top left corner | |
stage.scaleMode = StageScaleMode.NO_SCALE; | |
stage.align = StageAlign.TOP_LEFT; | |
controlsBtns(); | |
controlsChange(); | |
controlsScrubberDefault(); | |
controlsSwitch(false); | |
stage.dispatchEvent(new Event('controlsLoaded')); | |
stage.dispatchEvent(new Event(Event.RESIZE)); // Fire resize right away to adjust to default resolution | |
} | |
private function controlsSwitch(show:Boolean):void { | |
if ( ! started) { | |
controls.playBtn.x = controls.playBtn.x + settings.startMargin; | |
controls.playBtn.y = controls.playBtn.y - settings.startMargin; | |
controls.bg.width = controls.playBtn.width + status.heading.content.width; | |
controls.bg.y = controls.bg.y - settings.startMargin; | |
controls.bg.x = controls.bg.x + settings.startMargin; | |
status.heading.x = controls.playBtn.x + getCenter(controls.playBtn); | |
status.heading.y = stage.stageHeight - settings.controlsHeight - settings.startMargin; | |
} else { | |
statusHide(); | |
resizeControls(); | |
status.heading.y = 0; | |
status.heading.x = settings.controlsMargin; | |
} | |
controls.scrubber.visible = show; | |
controls.fullBtn.visible = show; | |
controls.soundBtn.visible = show; | |
volumeButton(show); | |
} | |
private function controlsBtns():void { | |
var buttons:Array /* of MovieClips */ = [controls.fullBtn, controls.playBtn, controls.pauseBtn, controls.soundBtn, controls.scrubber.container]; | |
var functions:Array /* of functions */ = [pressFullScreen, pressResume, pressPause, pressSound, pressScrubber]; | |
var loops:int = buttons.length; | |
for (var i = 0; i<loops; i++) { | |
buttonize(buttons[i], btnOver, btnOut, functions[i]); | |
} | |
thumbScreen.addEventListener(MouseEvent.CLICK, pressResume); | |
videoScreen.addEventListener(MouseEvent.CLICK, pressToggle); | |
scrubberShowTimerOver(); | |
controls.scrubber.scrubber.addEventListener(MouseEvent.MOUSE_DOWN, scrubberDown); | |
controls.scrubber.scrubber.mouseChildren = false; | |
controls.scrubber.scrubber.buttonMode = true; | |
volumeDefault(); | |
} | |
// -------------------------------------------------------------------- | |
// Turn MovieClip into button | |
// -------------------------------------------------------------------- | |
private function buttonize(button:MovieClip, functionOver, functionOut, functionPress) { | |
button.addEventListener(MouseEvent.MOUSE_OVER, functionOver); | |
button.addEventListener(MouseEvent.MOUSE_OUT, functionOut); | |
button.mouseChildren = false; | |
button.buttonMode = true; | |
button.addEventListener(MouseEvent.CLICK, functionPress); | |
} | |
// -------------------------------------------------------------------- | |
// Scrubber methods | |
// -------------------------------------------------------------------- | |
function scrubberShowTimerOver():void { | |
controls.scrubber.addEventListener(MouseEvent.MOUSE_OVER, scrubberOver); | |
controls.scrubber.addEventListener(MouseEvent.MOUSE_OUT, scrubberOut); | |
} | |
function scrubberHideTimerOver():void { | |
controls.scrubber.removeEventListener(MouseEvent.MOUSE_OVER, scrubberOver); | |
controls.scrubber.removeEventListener(MouseEvent.MOUSE_OUT, scrubberOut); | |
} | |
function scrubberDown(event:MouseEvent):void { | |
scrubberHideTimerOver(); | |
scrubberClick(); | |
clearInterval(interval); | |
interval = intervalInit(1); | |
controls.scrubber.scrubber.startDrag(false, new Rectangle(0, controls.scrubber.scrubber.y, controls.scrubber.container.width, 0)); | |
stage.addEventListener(MouseEvent.MOUSE_UP, scrubberUp); | |
} | |
function scrubberUp(event:MouseEvent):void { | |
scrubberShowTimerOver(); | |
stage.removeEventListener(MouseEvent.MOUSE_UP, scrubberUp); | |
controls.scrubber.scrubber.stopDrag(); | |
scrubIt(); | |
scrubberOut(event); | |
} | |
function scrubIt():void { | |
stage.dispatchEvent(new MediaEvent('seek', seeking((controls.scrubber.scrubber.x/controls.scrubber.container.width)*duration))); | |
} | |
function scrubberOver(event:MouseEvent):void { | |
clearInterval(interval); | |
interval = intervalInit(2); | |
controlsShowTimer(); | |
} | |
function scrubberOut(event:MouseEvent):void { | |
clearInterval(interval); | |
interval = intervalInit(0); | |
controlsHideTimer(); | |
} | |
function scrubberClick():void { | |
if (!played) | |
stage.dispatchEvent(new Event('play')); | |
} | |
function btnOver(event:MouseEvent):void { | |
event.currentTarget.gotoAndPlay('over'); | |
} | |
function btnOut(event:MouseEvent):void { | |
event.currentTarget.gotoAndPlay('out'); | |
} | |
private function controlsChange():void { | |
if (played) { | |
controls.playBtn.visible = false; | |
controls.pauseBtn.visible = true; | |
} else { | |
controls.playBtn.visible = true; | |
controls.pauseBtn.visible = false; | |
} | |
} | |
function pressFullScreen(event:Event):void { | |
if (stage.displayState == StageDisplayState.NORMAL) { | |
stage.displayState = StageDisplayState.FULL_SCREEN; | |
} else { | |
stage.displayState = StageDisplayState.NORMAL; | |
} | |
} | |
function pressToggle(event:Event):void { | |
if (played) | |
pressPause(event); | |
else | |
pressResume(event); | |
} | |
function pressResume(event:Event):void { | |
if (settings.autoplay == false) { | |
stage.dispatchEvent(new Event('play')); | |
settings.autoplay = true; | |
} else { | |
stage.dispatchEvent(new Event('resume')); | |
} | |
controlsChange(); | |
} | |
function pressPause(event:Event):void { | |
stage.dispatchEvent(new Event('pause')); | |
controlsChange(); | |
} | |
function pressSound(event:Event):void { | |
soundToggle(); | |
} | |
function pressScrubber(event:Event):void { | |
stage.dispatchEvent(new MediaEvent('seek', seeking(mouse2Time()))); | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Sound methods | |
// | |
// -------------------------------------------------------------------- | |
private function soundInit(event:Event):void { | |
debug('soundInit'); | |
soundSet(settings.soundVolume); | |
} | |
private function soundToggle():void { | |
if (ns.soundTransform.volume > 0) | |
soundSet(0); | |
else | |
soundSet(settings.soundVolume); | |
} | |
private function soundSet(volume:Number):void { | |
if (media) { | |
volumeReflect(volume, ns.soundTransform.volume); | |
ns.soundTransform = new SoundTransform(volume); | |
} else { | |
volumeReflect(volume, channel.soundTransform.volume); | |
channel.soundTransform = new SoundTransform(volume); | |
} | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Buffer methods | |
// | |
// -------------------------------------------------------------------- | |
private function showBuffer():void { | |
status.buffer.visible = true; | |
clearInterval(interval); | |
interval = intervalInit(3); | |
} | |
private function hideBuffer():void { | |
status.buffer.visible = false; | |
clearInterval(interval); | |
interval = intervalInit(0); | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Status methods | |
// | |
// -------------------------------------------------------------------- | |
private function statusHide():void { | |
status.visible = false; | |
} | |
private function statusShow():void { | |
status.visible = true; | |
} | |
private function statusToggle():void { | |
status.visible = !status.visible; | |
} | |
private function statusInit(event:Event):void { | |
debug('statusInit'); | |
hideBuffer(); | |
status.heading.content.text = settings.name; | |
status.heading.content.autoSize = TextFieldAutoSize.LEFT; | |
status.heading.addEventListener(MouseEvent.CLICK, goMedia); | |
linkify(status.heading); | |
stage.dispatchEvent(new Event('statusLoaded')); | |
} | |
function linkify(object):void { | |
object.addEventListener(MouseEvent.MOUSE_OVER, textRollOver); | |
object.addEventListener(MouseEvent.MOUSE_OUT, textRollOut); | |
object.buttonMode = true; | |
object.mouseChildren = false; | |
textBasic(object); | |
} | |
function textBasic(object):void { | |
textChange(object, settings.linkColor); | |
} | |
function textHover(object):void { | |
textChange(object, settings.hoverColor); | |
} | |
function textChange(object, color):void { | |
var original = object.content.text; | |
object.content.htmlText = '<font color="#' + color + '">' + original + '</font>'; | |
} | |
function textRollOut(e:MouseEvent):void { | |
textBasic(e.currentTarget); | |
} | |
function textRollOver(e:MouseEvent):void { | |
textHover(e.currentTarget); | |
} | |
function goMedia(event:Event):void { | |
goLink(settings.link); | |
} | |
function goLink(link):void { | |
var request:URLRequest = new URLRequest(link); | |
try { | |
navigateToURL(request, '_blank'); | |
} catch (error:Error) { | |
debug('URL Request failed on: ' + link); | |
} | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Stream methods | |
// | |
// -------------------------------------------------------------------- | |
private function streamInit(event:Event):void { | |
debug('streamInit'); | |
if (media) { | |
video = new Video(); | |
video.x = 0; | |
video.y = 0; | |
video.attachNetStream(ns); | |
videoScreen.addChild(video); | |
linkStreamMethods(); | |
} else { | |
audio = new Sound(); | |
channel = new SoundChannel(); | |
audio.load(new URLRequest(path)); | |
linkAudioMethods(); | |
} | |
if (settings.autoplay) | |
stage.dispatchEvent(new Event('play')); | |
stage.dispatchEvent(new Event('streamLoaded')); | |
} | |
private function linkAudioMethods():void { | |
stage.addEventListener('play', audioPlay); | |
stage.addEventListener('resume', audioResume); | |
stage.addEventListener('pause', audioPause); | |
} | |
private function linkStreamMethods():void { | |
stage.addEventListener('play', nsPlay); | |
stage.addEventListener('resume', nsResume); | |
stage.addEventListener('pause', nsPause); | |
stage.addEventListener('seek', nsSeek); | |
} | |
private function audioPlay(event:Event):void { | |
channel = audio.play(); | |
soundSet(settings.soundVolume); | |
nsTogglePlayed(); | |
} | |
private function audioResume(event:Event):void { | |
channel = audio.play(position); | |
nsTogglePlayed(); | |
} | |
private function audioPause(event:Event):void { | |
position = channel.position; | |
nsTogglePlayed(); | |
channel.stop(); | |
} | |
private function nsPlay(event:Event):void { | |
thumbHide(); | |
ns.play(path); | |
nsTogglePlayed(); | |
debug('Video ' + path + ' is playing'); | |
} | |
private function nsResume(event:Event):void { | |
nsTogglePlayed(); | |
statusHide(); | |
ns.resume(); | |
} | |
private function nsPause(event:Event):void { | |
nsTogglePlayed(); | |
statusShow(); | |
ns.pause(); | |
} | |
private function nsTogglePlayed():void { | |
played = !played; | |
if ( ! started) { | |
started = true; | |
controlsSwitch(true); | |
} | |
debug('Playing' + String(played)); | |
} | |
private function nsSeek(event:MediaEvent):void { | |
ns.seek(event.data.seconds); | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Thumb methods | |
// | |
// -------------------------------------------------------------------- | |
private function thumbInit(event:Event):void { | |
debug('thumbInit'); | |
var thumbLoader:Loader = new Loader(); | |
var thumb:URLRequest = new URLRequest(settings.thumb); | |
thumbLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, thumbLoaded); | |
thumbLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, thumbProgress); | |
thumbLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, thumbError); | |
thumbLoader.load(thumb); | |
thumbScreen.addChild(thumbLoader); | |
} | |
private function thumbHide():void { | |
thumbScreen.visible = false; | |
} | |
private function thumbProgress(event:ProgressEvent):void { | |
trace(Math.round((event.bytesLoaded/event.bytesTotal)*100) + '%'); | |
} | |
/** | |
* thumbLoaded | |
* | |
* ThumbLoaded => dispatch thumbLoaded event | |
* to proceed. | |
*/ | |
private function thumbLoaded(event:Event):void { | |
curtainHide(); | |
stage.dispatchEvent(new Event('thumbLoaded')); | |
debug('Thumb ' + settings.thumb + ' was loaded'); | |
} | |
/** | |
* thumbError | |
* | |
* ThumbError => dispatch thumbLoaded event | |
* and try to proceed without thumb. | |
*/ | |
private function thumbError(event:IOErrorEvent):void { | |
curtainHide(); | |
stage.dispatchEvent(new Event('thumbLoaded')); | |
debug('ioErrorHandler: ' + event.text); | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Curtain methods | |
// | |
// -------------------------------------------------------------------- | |
private function curtainResize():void { | |
curtain.width = stage.stageWidth; | |
curtain.height = stage.stageHeight; | |
} | |
private function curtainHide():void { | |
curtain.visible = false; | |
} | |
private function curtainShow():void { | |
curtain.visible = true; | |
} | |
private function curtainToggle():void { | |
curtain.visible = !curtain.visible; | |
} | |
// -------------------------------------------------------------------- | |
// | |
// NetStream methods | |
// | |
// -------------------------------------------------------------------- | |
private function prepare():void { | |
debug('prepate'); | |
media = setMediaType(); | |
nc = new NetConnection(); | |
nc.connect(null); | |
ns = new NetStream(nc); | |
meta = new Object(); | |
meta.onMetaData = onMetaData; | |
ns.client = meta; | |
ns.bufferTime = settings.buffer; | |
ns.addEventListener(NetStatusEvent.NET_STATUS, netStreamStatus); | |
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler); | |
stage.dispatchEvent(new Event('prepared')); | |
} | |
private function setMediaType():Boolean { | |
if (settings.audio == false) { | |
path = settings.video; | |
return true; | |
} else { | |
path = settings.audio; | |
return false; | |
} | |
} | |
private function onMetaData(metaData:Object):void { | |
video.width = metaData.width; | |
video.height = metaData.height; | |
duration = metaData.duration; | |
} | |
function asyncErrorHandler(event:AsyncErrorEvent):void { | |
debug(event.text); | |
} | |
private function netStreamStatus(event:NetStatusEvent):void { | |
switch(event.info.code) | |
{ | |
case 'NetStream.FileStructureInvalid': | |
{ | |
debug('NetStream.FileStructureInvalid'); | |
break; | |
} | |
case 'NetStream.NoSupportedTrackFound': | |
{ | |
debug('NetStream.NoSupportedTrackFound'); | |
break; | |
} | |
case 'NetStream.Buffer.Full': // buffer is full | |
{ | |
debug('NetStream.Buffer.Full'); | |
ns.bufferTime = settings.exapndedBuffer; | |
hideBuffer(); | |
break; | |
} | |
case 'NetStream.Buffer.Empty': // buffer is empty | |
{ | |
debug('NetStream.Buffer.Empty'); | |
ns.bufferTime = settings.buffer; | |
if (ns.bytesLoaded < ns.bytesTotal) { | |
showBuffer(); | |
} | |
break; | |
} | |
case 'NetStream.Play.Start': // ns.play() fires start | |
{ | |
debug('NetStream.Play.Start'); | |
showBuffer(); | |
break; | |
} | |
case 'NetStream.Seek.Notify': // ns.seek() fires notify (scrubber / rewind) | |
{ | |
debug('NetStream.Seek.Notify'); | |
showBuffer(); | |
break; | |
} | |
case 'NetStream.Seek.InvalidTime': // Scrubber ahead of loaded | |
{ | |
debug('NetStream.Seek.InvalidTime'); | |
break; | |
} | |
case 'NetStream.Play.Stop': // End of netStream | |
{ | |
debug('NetStream.Play.Stop'); | |
stage.dispatchEvent(new MediaEvent('seek', seeking(0))); | |
controls.pauseBtn.dispatchEvent(new MouseEvent(MouseEvent.CLICK)); | |
break; | |
} | |
case 'NetStream.Play.Flush': // Flush of netStream | |
{ | |
debug('NetStream.Play.Flush'); | |
break; | |
} | |
} | |
} | |
private function seeking(seconds:int):Object { | |
var seeking = new Object(); | |
seeking.seconds = seconds; | |
return seeking; | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Settings methods | |
// | |
// -------------------------------------------------------------------- | |
private function settingsFactory(settings:Object):Object { | |
for (var key in factory) { | |
if (settings[key] == undefined) | |
settings[key] = factory[key]; | |
} | |
return settings; | |
} | |
// -------------------------------------------------------------------- | |
// | |
// Support methods | |
// | |
// -------------------------------------------------------------------- | |
private function debug(message:String):void { | |
if (settings.debug == true) | |
trace(message); | |
} | |
// -------------------------------------------------------------------- | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment