package { /* * A Kaleidoscope Demonstration in Actionscript 3 * from http://shinedraw.com (with some extension by Ken http://hdcolors.com) */ import flash.events.MouseEvent; import flash.system.ApplicationDomain; import flash.events.Event; import flash.system.System; import flash.system.Security; import flash.display.MovieClip; import flash.desktop.NativeApplication; import flash.display.*; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.display.StageDisplayState; import flash.display.Sprite; import flash.events.*; import flash.media.Sound; import flash.events.Event; import flash.events.MouseEvent; import flash.external.*; import flash.filesystem.*; import flash.filters.*; import flash.geom.*; import flash.media.*; import flash.net.*; import flash.system.*; import flash.net.FileReference; import flash.system.ApplicationDomain; import flash.text.TextFieldAutoSize; import flash.utils.*; import flash.utils.ByteArray; import flash.events.MouseEvent; import flash.text.*; import flash.events.Event; import flash.xml.*; import flash.ui.Mouse; import mx.controls.Label; import mx.graphics.codec.JPEGEncoder; import mx.graphics.codec.PNGEncoder; import BMPEncoder; import Kaleidoscope; import EmbedFilter; public class VideoKaleidoscope3840x2160 extends MovieClip { private var APP_WIDTH:Number=3840; private var APP_HEIGHT:Number=2160; private var overlapFactor:Number=.00097; static var optionX:Number=344; static var optionY:Number=12; static var optionHeight:Number=32; static var optionSpacing:Number=46; private var showStatus:Boolean=false; private var shader:Shader; private var filter:ShaderFilter; private var spherizeFactor:Number=.3; private var refraction:Number=1; private var showInfo:Boolean=false; private var fullScreenForScreenCapture:Boolean=true; private var endFrameRate:Number=30; private var stageFrameRate:Number=30; private var targetRotation:Number=360; private var targetSeconds=60; private var fadeSeconds:Number=3; private var minVertex:Number=30; private var maxVertex:Number=30; private var capturePath:String=File.desktopDirectory.nativePath+"\\kaleidoscope_screenshots"; private var imageFormat:String="BMP"; private var lastSongFrame:Number=0; private var txtEndFrameRate=new TextField(); private var txtTargetSeconds=new TextField();; private var txtFadeSeconds=new TextField(); private var txtMinVertex=new TextField();; private var txtMaxVertex=new TextField(); private var txtCapturePath=new TextField(); private var txtSongURL=new TextField(); private var txtSpherizeFactor=new TextField(); private var txtImageFormat=new TextField(); private var txtfullScreenForScreenCapture=new TextField(); private var txtStatus=new TextField(); private var fadeFrames:Number; private var totalFramesPerImage:Number; private var rotationFrames; private var speedFactor; private var fadeLength; private var incrementDegrees; private var degreesPerSecond; private var degreesPerFrame; private var song=""; private var lastFrame:Number=0; private var IMAGE_DIAMETER:Number; private var IMAGE_RADIUS:Number; private var topMandala : Kaleidoscope; private var bottomMandala:Kaleidoscope; private var loader:URLLoader; private var cliploaded:Boolean; private var back_mc:MovieClip; private var image:Bitmap; private var prefix:String; private var filename:FileReference; private var xmlLoader:FileReference; private var nextFileName:FileReference; private var myFileList:FileReferenceList; private var myFileListLength:Number; private var outputDirectory:File; private var inputDirectory:File; private var angle:Number=0; private var image_loader:Loader; private var win:NativeWindow; private var statusLabel:TextField=new TextField(); private var beginFullScreenLabel:TextField=new TextField(); private var largeFileNameLabel:TextField=new TextField(); private var nextImage:Bitmap; private var startSeconds:Number; private var numVertex:Number=5; private var frameRefractionIndex:Array=new Array(); private var peakVolume:Array=new Array(); private var averageVolume:Array=new Array(); private var idArray:Array=new Array(); private var fileNameArray:Array=new Array(); private var sequenceFrameNumber=0; private var imageFrameNumber=0; private var statusDisplay=false; private var fileNameFormat:TextFormat = new TextFormat(); private var topContainerBitmapData:BitmapData; private var topContainerBitmap:Bitmap; private var topContainer:Sprite private var bottomContainerBitmapData:BitmapData; private var bottomContainerBitmap:Bitmap; private var bottomContainer:Sprite private var myMask:Shape = new Shape(); private var myJPGEncoder= new JPEGEncoder(100); private var myBMPEncoder= new BMPEncoder(); private var myPNGEncoder= new PNGEncoder(); private var volumeXMLLoader:URLLoader=new URLLoader(); private var startTime=0; private var currentTime=0; private var startTimeThisImage:Number; private var endTime:Number=0; private var elapsedTimeTotal:Number=0; private var elapsedTimeThisImage:Number; private var myClock:Number; private var maxTime:Number=1/stageFrameRate; private var inputXML:File; private var myFileListIndex:Number; private var currentFileIndex:Number; private var screenSaveBitmapData:BitmapData; public function VideoKaleidoscope3840x2160() { bottomMandala=null; topMandala=null; bottomContainerBitmapData=new BitmapData(APP_WIDTH,APP_HEIGHT,false,0x000000) topContainerBitmapData=new BitmapData(APP_WIDTH,APP_HEIGHT,false,0x000000) myFileListIndex=0; NativeApplication.nativeApplication.autoExit=true; IMAGE_DIAMETER = Math.sqrt(APP_WIDTH*APP_WIDTH+APP_HEIGHT*APP_HEIGHT); IMAGE_RADIUS=IMAGE_DIAMETER/2; stage.frameRate=stageFrameRate; btnRender.visible=false; btnRender.x=0; btnRender.y=0; var myFormat:TextFormat = new TextFormat(); myFormat.size=24; myFormat.align=TextFormatAlign.RIGHT; myFormat.color=0x000000; myFormat.font="Arial"; var myFormatLeft:TextFormat=myFormat; myFormatLeft.align=TextFormatAlign.LEFT; var toggleFormat:TextFormat = new TextFormat(); toggleFormat.size=24; toggleFormat.align=TextFormatAlign.CENTER; toggleFormat.color=0xFFFFFF; toggleFormat.font="Arial"; txtEndFrameRate.type=TextFieldType.INPUT; txtTargetSeconds.type=TextFieldType.INPUT; txtFadeSeconds.type=TextFieldType.INPUT; txtMinVertex.type=TextFieldType.INPUT; txtMaxVertex.type=TextFieldType.INPUT; txtImageFormat.type=TextFieldType.DYNAMIC; txtfullScreenForScreenCapture.type=TextFieldType.DYNAMIC; txtCapturePath.type=TextFieldType.INPUT; txtSongURL.type=TextFieldType.INPUT; txtSpherizeFactor.type=TextFieldType.INPUT; txtEndFrameRate.background=true; txtEndFrameRate.backgroundColor=0xFFFFFF; txtEndFrameRate.x=optionX; txtEndFrameRate.y=optionY; txtEndFrameRate.width=100; txtEndFrameRate.height=optionHeight; txtEndFrameRate.defaultTextFormat=myFormat; txtTargetSeconds.background=true; txtTargetSeconds.backgroundColor=0xFFFFFF; txtTargetSeconds.x=optionX; txtTargetSeconds.y=optionY+optionSpacing*2; txtTargetSeconds.width=100; txtTargetSeconds.height=optionHeight; txtTargetSeconds.defaultTextFormat=myFormat; txtFadeSeconds.background=true; txtFadeSeconds.backgroundColor=0xFFFFFF; txtFadeSeconds.x=optionX; txtFadeSeconds.y=optionY+optionSpacing*3; txtFadeSeconds.width=100; txtFadeSeconds.height=optionHeight; txtFadeSeconds.defaultTextFormat=myFormat; txtMinVertex.background=true; txtMinVertex.backgroundColor=0xFFFFFF; txtMinVertex.x=optionX; txtMinVertex.y=optionY+optionSpacing*4; txtMinVertex.width=100; txtMinVertex.height=optionHeight; txtMinVertex.defaultTextFormat=myFormat; txtMaxVertex.background=true; txtMaxVertex.backgroundColor=0xFFFFFF; txtMaxVertex.x=optionX; txtMaxVertex.y=optionY+optionSpacing*5; txtMaxVertex.width=100; txtMaxVertex.height=optionHeight; txtMaxVertex.defaultTextFormat=myFormat; txtfullScreenForScreenCapture.selectable=false; txtfullScreenForScreenCapture.background=true; txtfullScreenForScreenCapture.backgroundColor=0xFF0000; txtfullScreenForScreenCapture.x=optionX; txtfullScreenForScreenCapture.y=optionY+optionSpacing*7; txtfullScreenForScreenCapture.width=100; txtfullScreenForScreenCapture.height=optionHeight; txtfullScreenForScreenCapture.defaultTextFormat=toggleFormat; txtImageFormat.selectable=false; txtImageFormat.background=true; txtImageFormat.backgroundColor=0xFF0000; txtImageFormat.x=optionX; txtImageFormat.y=optionY+optionSpacing*8; txtImageFormat.width=100; txtImageFormat.height=optionHeight; txtImageFormat.defaultTextFormat=toggleFormat; txtCapturePath.background=true; txtCapturePath.backgroundColor=0xFFFFFF; txtCapturePath.x=optionX; txtCapturePath.y=optionY+optionSpacing*9; txtCapturePath.width=(1000-optionX)-10; txtCapturePath.height=optionHeight; txtCapturePath.defaultTextFormat=myFormatLeft; txtSongURL.background=true; txtSongURL.backgroundColor=0xFFFFFF; txtSongURL.x=optionX; txtSongURL.y=optionY+optionSpacing*10; txtSongURL.width=(1000-optionX)-10; txtSongURL.height=optionHeight; txtSongURL.defaultTextFormat=myFormatLeft; txtSongURL.text=song; txtSpherizeFactor.background=true; txtSpherizeFactor.backgroundColor=0xFFFFFF; txtSpherizeFactor.x=optionX; txtSpherizeFactor.y=optionY+optionSpacing*11; txtSpherizeFactor.width=100; txtSpherizeFactor.height=optionHeight; txtSpherizeFactor.defaultTextFormat=myFormatLeft; txtSpherizeFactor.text=spherizeFactor; txtEndFrameRate.text=endFrameRate; txtTargetSeconds.text=targetSeconds; txtFadeSeconds.text=fadeSeconds; txtMinVertex.text=minVertex; txtMaxVertex.text=maxVertex; txtCapturePath.text=capturePath; txtImageFormat.text=imageFormat; if(fullScreenForScreenCapture) txtfullScreenForScreenCapture.text="NO"; else txtfullScreenForScreenCapture.text="YES"; txtStatus.background=true; txtStatus.backgroundColor=0xFFFFFF; txtStatus.x=0; txtStatus.y=0; txtStatus.width=400; txtStatus.height=optionHeight; txtStatus.defaultTextFormat=myFormat; txtStatus.visible=false; addChild(txtStatus); addChild(txtEndFrameRate); addChild(txtTargetSeconds); addChild(txtFadeSeconds); addChild(txtMinVertex); addChild(txtMaxVertex); addChild(txtCapturePath); addChild(txtSongURL); addChild(txtSpherizeFactor); addChild(txtImageFormat); addChild(txtfullScreenForScreenCapture); stage.align=StageAlign.TOP_LEFT; stage.scaleMode=StageScaleMode.NO_SCALE; stage.frameRate=stageFrameRate; var myFilter:EmbedFilter=new EmbedFilter(); shader=myFilter.getShader(); filter=new ShaderFilter(shader); shader.data.radius.value=[IMAGE_RADIUS]; shader.data.center.value=[APP_WIDTH/2,APP_HEIGHT/2]; shader.data.refractionIndex.value=[refraction]; startUp(); } public function startUp():void { fileNameFormat.size = 50; fileNameFormat.font="Lucida Console"; largeFileNameLabel.x=0; largeFileNameLabel.y=0; largeFileNameLabel.backgroundColor=0x000000; largeFileNameLabel.textColor=0xFFFFFF; statusLabel.backgroundColor=0x000000; statusLabel.textColor=0xFFFFFF; statusLabel.x=0; statusLabel.y=1000; btnStart.addEventListener(MouseEvent.CLICK, startFullScreen); txtfullScreenForScreenCapture.addEventListener(MouseEvent.CLICK, togglefullScreenForScreenCapture); txtImageFormat.addEventListener(MouseEvent.CLICK, toggleImageFormat); } private function findInputDirectory():void { trace("findInputDirectory"); inputDirectory = new File(); inputDirectory.addEventListener(Event.SELECT,onInputDirectorySelected); inputDirectory.addEventListener(Event.CANCEL,onCancel); inputDirectory.browseForDirectory("Please select INPUT directory"); } private function toggleImageFormat(evt:Event) { if(imageFormat=="JPG") { imageFormat="PNG"; txtImageFormat.text=imageFormat; } else if(imageFormat=="PNG") { imageFormat="BMP"; txtImageFormat.text=imageFormat; } else if(imageFormat=="BMP") { imageFormat="JPG"; txtImageFormat.text=imageFormat; } trace(imageFormat); } private function togglefullScreenForScreenCapture(evt:Event) { fullScreenForScreenCapture=!fullScreenForScreenCapture; if(fullScreenForScreenCapture) txtfullScreenForScreenCapture.text="NO"; else txtfullScreenForScreenCapture.text="YES"; } private function onInputDirectorySelected(evt:Event):void { trace("oninputDirectorySelected"); inputDirectory.removeEventListener(Event.SELECT,onInputDirectorySelected); inputDirectory=evt.target as File; loadXML(); //findImageFiles(); } private function findInputXML():void { trace("findInputDirectory"); clearAll(); inputXML = new File(); inputXML.addEventListener(Event.SELECT,onInputXMLSelected); inputXML.addEventListener(Event.CANCEL,onCancel); inputXML.browseForOpen("Please Select INPUT XML Image List"); } private function onInputXMLSelected(evt:Event):void { trace("oninputDirectorySelected"); inputXML.removeEventListener(Event.SELECT,onInputDirectorySelected); inputXML=evt.target as File; inputDirectory=inputXML.parent; if(song.length<1) loadXML(); else { loadVolumeXML(); } //findImageFiles(); } private function findImageFile():void { trace("findImageFile"); angle=0; filename=new FileReference(); filename.browse( [new FileFilter("Images", "*.jpg;*.gif;*.png")] ); filename.addEventListener(Event.SELECT,onFileSelected); } private function onFileSelected(evt:Event):void { trace("onFileSelected"); //var newArchiveDirectory:File=outputDirectory.resolvePath("_completed"); //newArchiveDirectory.createDirectory(); filename.addEventListener(Event.COMPLETE, onFileLoaded); filename.addEventListener(IOErrorEvent.IO_ERROR, onFileLoadError); filename.load(); } private function onCancel(evt:Event):void { NativeApplication.nativeApplication.exit(); } private function loadFile():void { removeEventListener(Event.ENTER_FRAME,onEnterFrame); myFileListIndex++; trace("loading file "+myFileListIndex+" "+fileNameArray[myFileListIndex]); filename=new FileReference(); filename=inputDirectory.resolvePath(fileNameArray[myFileListIndex]); fileNameArray[currentFileIndex]=filename.name; filename.addEventListener(Event.COMPLETE, onFileLoaded); filename.addEventListener(IOErrorEvent.IO_ERROR, onFileLoadError); filename.load(); } private function onFileLoaded(evt:Event):void { trace(fileNameArray[currentFileIndex]+ "Successfully loaded."); filename.removeEventListener(Event.COMPLETE, onFileLoaded); var fileReference:FileReference=evt.target as FileReference; var data:ByteArray=fileReference["data"]; trace("loading image..."); image_loader=new Loader(); image_loader.loadBytes(data); image_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded); } private function onFileLoadError(evt:Event):void { trace("onFileLoadError"); filename.removeEventListener(IOErrorEvent.IO_ERROR, onFileLoadError); } private function imageLoaded(evt:Event):void { trace("image sucessfully loaded"); var scaleFactor:Number; var thisBitmapData:BitmapData=new BitmapData(image_loader.width,image_loader.height,false,0x000001); thisBitmapData.draw(image_loader.content); if(thisBitmapData.width < IMAGE_DIAMETER || thisBitmapData.height < IMAGE_DIAMETER) { var scaleClip:Sprite=new Sprite(); if(thisBitmapData.width0) bottomMandala=topMandala; else bottomMandala= new Kaleidoscope(thisBitmapData,numVertex,startingAngle,APP_WIDTH,APP_HEIGHT,overlapFactor); topMandala = new Kaleidoscope(thisBitmapData,numVertex,startingAngle,APP_WIDTH,APP_HEIGHT,overlapFactor); trace("kaleidoscope "+myFileListIndex+" created."); addMandala(); } private function onMouseClick(evt:Event):void { currentFileIndex=myFileListLength; //findImageFiles(); } private function updateLog():void { if(capturePath.substr(capturePath.length-1,1) != "\\") capturePath=capturePath+"\\"; var logFile:File = new File(capturePath+"\\__kaleidoscope.log"); var logStream:FileStream=new FileStream(); var id=idArray[myFileListIndex]; var filename=fileNameArray[myFileListIndex]; var output:String="Frame: "+sequenceFrameNumber+"/"+lastSongFrame+"\r\n"; output=output+"Timecode: "+getTimeCode(sequenceFrameNumber,endFrameRate)+"\r\n"; output=output+"Seconds: "+(sequenceFrameNumber/endFrameRate).toFixed(2)+"\r\n"; output=output+"Minutes: "+(sequenceFrameNumber/endFrameRate/60).toFixed(2)+"\r\n"; output=output+"Index="+id+", filename="+filename+"\r\n"; output=output+"ImageFrameNumber="+imageFrameNumber+"\r\n"; output=output+"Song="+song+"\r\n"; output=output+"FramePeakVolume="+peakVolume[sequenceFrameNumber]+"\r\n"; output=output+"FrameAverageVolume="+peakVolume[sequenceFrameNumber]+"\r\n"; output=output+"SpherizeFactor="+spherizeFactor+"\r\n"; output=output+"RefractionIndex="+frameRefractionIndex[sequenceFrameNumber]+"\r\n"; try { logStream.open(logFile,FileMode.WRITE); logStream.writeMultiByte(output,"utf-8"); logStream.close(); } catch (thisError:Error) {}; return; } private function savePic(thisFile:String):void { thisFile="000000"+thisFile; if(capturePath.substr(capturePath.length-1,1) != "\\") capturePath=capturePath+"\\"; var fileName:String=capturePath+"screenshot"+thisFile.substr(thisFile.length-6,6)+"."+imageFormat.toLowerCase(); var ba:ByteArray; var saveFile:File = new File(fileName); stage.scaleMode="noScale"; screenSaveBitmapData.draw(stage,new Matrix()); //var bitmap:Bitmap=new Bitmap(screenSaveBitmapData); if(imageFormat=="BMP") ba = myBMPEncoder.encode(screenSaveBitmapData); if(imageFormat=="JPG") ba = myJPGEncoder.encode(screenSaveBitmapData); if(imageFormat=="PNG") ba = myPNGEncoder.encode(screenSaveBitmapData); var stream:FileStream = new FileStream(); stream.open(saveFile, FileMode.WRITE); stream.writeBytes(ba,0,ba.length); stream.close(); addEventListener(Event.ENTER_FRAME,onEnterFrame); } private function onEnterFrame(evt:Event) { currentTime=getTimer(); removeEventListener(Event.ENTER_FRAME,onEnterFrame); imageFrameNumber++; sequenceFrameNumber++; if(song.length>0) { refraction=frameRefractionIndex[sequenceFrameNumber]; shader.data.refractionIndex.value=[refraction]; } elapsedTimeThisImage=(currentTime-startTimeThisImage)/1000; elapsedTimeTotal=(currentTime-startTime)/1000; angle=imageFrameNumber*incrementDegrees; removeChild(topContainerBitmap); topMandala.rotate(angle); topContainerBitmapData.draw(topMandala,new Matrix()); topContainerBitmap=new Bitmap(topContainerBitmapData); if(refraction<1) { topContainerBitmap.filters=[filter]; } else { topContainerBitmap.filters=[]; } if(imageFrameNumber<=fadeFrames && myFileListIndex>0) { var topFrameAlpha=imageFrameNumber/fadeFrames; topContainerBitmap.alpha=topFrameAlpha; trace("fade cycle...fadeFrame="+(imageFrameNumber).toString()+ " alpha="+topFrameAlpha); if(myFileListLength>1) { removeChild(bottomContainerBitmap); bottomMandala.rotate(angle); bottomContainerBitmapData.draw(bottomMandala,new Matrix()); bottomContainerBitmap=new Bitmap(bottomContainerBitmapData); if(refraction<1) { bottomContainerBitmap.filters=[filter]; } else { bottomContainerBitmap.filters=[]; } addChild(bottomContainerBitmap); } } else { topContainerBitmap.alpha=1; } addChild(topContainerBitmap); if(capturePath.length>0) updateLog(); if(!fullScreenForScreenCapture) savePic(sequenceFrameNumber.toString()); if(lastSongFrame>0 && sequenceFrameNumber>lastSongFrame) { stopFullScreen(); clearAll(); applicationExit(); } if(imageFrameNumber0) endFrameRate=txtEndFrameRate.text; if(txtTargetSeconds.text>0) targetSeconds=txtTargetSeconds.text; if(txtFadeSeconds.text>0) fadeSeconds=txtFadeSeconds.text; if(txtMinVertex.text>0) minVertex=txtMinVertex.text; if(txtMaxVertex.text>0) maxVertex=txtMaxVertex.text; if(txtCapturePath.text>"") capturePath=trimWhitespace(txtCapturePath.text); if(txtSongURL.text.length>1) song=trimWhitespace(txtSongURL.text); if(txtSpherizeFactor.text.length>0) { spherizeFactor=txtSpherizeFactor.text; } fadeFrames=endFrameRate*fadeSeconds; rotationFrames=targetSeconds*endFrameRate; speedFactor=endFrameRate/stageFrameRate; fadeLength=stageFrameRate*fadeSeconds; totalFramesPerImage=endFrameRate*targetSeconds; incrementDegrees=targetRotation/totalFramesPerImage; degreesPerSecond=targetRotation/targetSeconds; degreesPerFrame=degreesPerSecond/stageFrameRate; targetSeconds*=speedFactor; fadeSeconds*=speedFactor; screenSaveBitmapData = new BitmapData(APP_WIDTH,APP_HEIGHT,false,0x00000000) stage.frameRate=stageFrameRate; findInputXML(); } public function startSlideShow(evt:MouseEvent=null):void { btnRender.removeEventListener(MouseEvent.CLICK, startSlideShow); removeChild(btnRender); //Mouse.hide(); //var soundTrack:Sound = new Sound(new URLRequest("http://10.10.0.200/journey.mp3")); //soundTrack.play(); myClock=getTimer(); myFileListIndex=-1; loadFile(); } public function stopFullScreen():void { stage.displayState=StageDisplayState.NORMAL; return; } public function loadXML():void { trace("loadxml"); xmlLoader=new FileReference(); xmlLoader=inputXML; xmlLoader.addEventListener(Event.COMPLETE, completeXMLHandler); xmlLoader.load(); } public function loadVolumeXML():void { trace("loadvolumexml"); var fileName="http://mp3cruncher.org/?mp3File="+song+"&frameRate="+endFrameRate; trace(fileName); var volumeXMLURL:URLRequest=new URLRequest(fileName); volumeXMLLoader.addEventListener(Event.COMPLETE, completeVolumeXMLHandler); volumeXMLLoader.addEventListener(IOErrorEvent.IO_ERROR,IOErrorHandler); volumeXMLLoader.load(volumeXMLURL); } private function IOErrorHandler( event:ErrorEvent ):void { trace( "got you.!!! " + event.toString() ); } public function completeVolumeXMLHandler(event:Event):void { var averagingWindow:Number=2; trace("completexmlhandler"); var filecounter:Number=0; var pulseVolume:Number=0; var lookAhead:Number=0; var result:XML=new XML(volumeXMLLoader.data); var myXML:XMLDocument=new XMLDocument(); myXML.ignoreWhite=true; myXML.parseXML(result.toXMLString()); var node:XMLNode=myXML.firstChild; var frames:int=int(node.childNodes.length); for(var i:int=0;i 59) min = min - (hour * 60); var sec:int = Math.floor(time % 60); var milli:Number = time - Math.floor(time); var frame:int = Math.round(milli*inputFrameRate); var shour:String = hour.toString(); var smin:String = min.toString(); var ssec:String = sec.toString(); var sframe:String = frame.toString(); if (shour.length < 2) shour = "0" + shour; if (smin.length < 2) smin = "0" + smin; if (ssec.length < 2) ssec = "0" + ssec; if (sframe.length < 2) sframe = "0" + sframe; var tc:String = shour+":" + smin + ":" + ssec + ":" + sframe; return tc; } } }