Investigation of CircleCube Video Player (Day 4)
来源:互联网 发布:三相电动机绕组数据 编辑:程序博客网 时间:2024/04/29 06:32
Review of the Structure Design
At the moment, the most helpless functions have been cut off. Only the basic and should be retained features remain. And it's time to figure out the whole program's structure.
Mainly, the application has four view states: normal, playlist view,detail view and share view, and it can interchange among these states. But we've removed the three states, only the normal state left.
Because in the play list view state, user can play any arbitrary video at run-time, by clicking on the item in list. And the player may be playing a video at that time. So the video player has multi-state, and can jump over these states, we need introduce extra vars to keep track of the change of its state. And currentStatus is for that.
We now trace this variable through out the program.
internal var currentStatus:String="ready";public function playDown(arg1:flash.events.MouseEvent=null):void{trace("begin playDown - currentStatus: " + currentStatus);vid.visible = true;get_pl();var loc1:*=currentStatus;switch (loc1) {case "ready":{videoTimer.start();if (autoVidLoad) {ns.play(video_flv);if (autoVidPlay) {currentStatus = "playing";vcr.playB.icon.gotoAndStop("playing");vid.setChildIndex(video, vid.numChildren - 2);}else {currentStatus = "loading";ns.pause();vcr.playB.icon.gotoAndStop("paused");autoVidPlay = true;clearVideoStatus();}}else {autoVidLoad = true;}break;}case "loading":{currentStatus = "playing";ns.resume();vcr.playB.icon.gotoAndStop("playing");vid.setChildIndex(video, vid.numChildren - 2);break;}case "playing":{currentStatus = "paused";ns.pause();vcr.playB.icon.gotoAndStop("paused");break;}case "paused":{currentStatus = "playing";ns.resume();vcr.playB.icon.gotoAndStop("playing");vid.setChildIndex(video, vid.numChildren - 2);break;}case "complete":{ns.seek(0);ns.resume();videoTimer.start();currentStatus = "playing";vcr.playB.icon.gotoAndStop("playing");vid.setChildIndex(video, vid.numChildren - 2);break;}default:{trace("ERROR: " + currentStatus);}}return;}public function videoComplete():*{ns.pause();videoTimer.stop();currentStatus = "complete";var loc1:*;vcr.bar.bg.width = loc1 = 0 * vcr.bar.bar.width;vcr.bar.loadbar.width = loc1;vcr.bar.playbar.width = 0 * vcr.bar.bar.width;vcr.bar.scrub.x = 0;vcr.playB.icon.gotoAndStop("paused");clearVideoStatus();vid.setChildIndex(video, vid.numChildren - 2);return;}
According to the code, currentStaus may be the following values:
ready
loading
playing
paused
complete
which means it has five basic status. The initial value is 'ready', and can change to others four values, only under one condition that it will change to loading, which is when autoVidPlayis false. This value has its initial value set to true, and will be over ridden according to xml and Javascript, but xml has its autostart set to true, so this var keeps as true through the initialization stage, apart from that, the program only has logic to change it to true if it's false, none for changing it to false. So it is not really of use. And run the original program, and play around it, see the output:
......begin playDown - currentStatus: readyloading still: files/285533_preview.jpgonMetaData duration: 24.72begin playDown - currentStatus: playingbegin playDown - currentStatus: pausedpl_play 2begin playDown - currentStatus: readyloading still: files/285533_preview.jpgonMetaData duration: 24.72video stop firedbegin playDown - currentStatus: completepl_play 3begin playDown - currentStatus: readyloading still: files/285533_preview.jpgonMetaData duration: 24.72pl_play 0begin playDown - currentStatus: readyloading still: files/285533_preview.jpgonMetaData duration: 24.72begin playDown - currentStatus: playingpl_play 5begin playDown - currentStatus: readyloading still: files/285533_preview.jpgonMetaData duration: 24.72video stop firedbegin playDown - currentStatus: completebegin playDown - currentStatus: playingpl_play 0begin playDown - currentStatus: readyloading still: files/285533_preview.jpgonMetaData duration: 24.72begin playDown - currentStatus: playing
If the video stops, and user clicks the button which would invoke playDown() function, before that currentStatus is 'complete' previously, whereas after user's clicking, it changes to 'playing', or 'pausing'; if user clicks a item in the play list to play another video(a output of 'pl_play n' will show up to indicate that), then it will change to ready, by some other functions, and let's find them out:
public function pl_play(arg1:Number=0):void { trace("pl_play", arg1); pl_index = arg1; if (pl_index < 0 && !pl_loop) { pl_index = 0; } else if (pl_index < 0 && pl_loop) { pl_last(); } if (pl_index >= pl_total && !pl_loop) { pl_index = 0; } else if (pl_index >= pl_total && pl_loop) { pl_first(); } else { currentStatus = "ready"; pl_duration = false; playDown(); pl_click(); hidePlayOverlay(); } return; }
And it seems that only the code inside else block will be executed eventaully. It set currentStatus to 'ready'. But one question arises: what doespl_durationdo???
Here are the functions that access it:
internal var pl_duration:Boolean=false; public function onMetaData(arg1:Object):void { if (duration == -1 || !pl_duration) { duration = Number(arg1["duration"]); trace("onMetaData duration:", duration); pl_duration = true; playerLayout(); } return; } public function onXMPData(arg1:Object):void { if (duration == -1 || !pl_duration) { duration = Number(arg1["duration"]); trace("onXMPdata duration:", duration); pl_duration = true; playerLayout(); } return; } public function pl_last():void { pl_index = (pl_total - 1); currentStatus = "ready"; pl_duration = false; playDown(); pl_click(); hidePlayOverlay(); return; } public function pl_first():void { pl_index = 0; currentStatus = "ready"; pl_duration = false; playDown(); pl_click(); hidePlayOverlay(); return; } public function pl_next():void { var loc1:*; pl_index++; if (pl_index >= pl_total && !pl_loop) { pl_index = 0; } else if (pl_index >= pl_total && pl_loop) { pl_first(); } else { currentStatus = "ready"; pl_duration = false; playDown(); pl_click(); hidePlayOverlay(); } return; } public function pl_previous():void { var loc1:*; pl_index--; if (pl_index < 0 && !pl_loop) { pl_index = 0; } else if (pl_index < 0 && pl_loop) { pl_last(); } else { currentStatus = "ready"; pl_duration = false; playDown(); pl_click(); hidePlayOverlay(); } return; } public function pl_play(arg1:Number=0):void { trace("pl_play", arg1); pl_index = arg1; if (pl_index < 0 && !pl_loop) { pl_index = 0; } else if (pl_index < 0 && pl_loop) { pl_last(); } if (pl_index >= pl_total && !pl_loop) { pl_index = 0; } else if (pl_index >= pl_total && pl_loop) { pl_first(); } else { currentStatus = "ready"; pl_duration = false; playDown(); pl_click(); hidePlayOverlay(); } return; }
What I am about to do is to remove the 'loading' status, and the logic around, we don't need it at all.
Beside from removing the code for 'loading' state, also removing everything aboutautoVidPlay:
And also remove averything about autoVidLoad, since its always true.
as file(remove ready state, mouse-over event, permalink and description version)
Take a break............................................................................
Now, draft the structure of the program's logic flow, regardless of the user interaction logic.
The vcrLayout() is called in the constructor of main class, and then called by the videoTimer handler functionvideoStatus(),videoStatus() is invoked per 0.1 second. And is it necessary to run vcrLayout() so frequantly? Take a look at it:
public function vcrLayout():* { var loc3:*=null; vcrSort(); vcr.x = 0; vcr.y = stage.stageHeight - vcr.bg.height; vcr.bg.width = stage.stageWidth; vcrWidthFixed = 0; var loc1:*=(vcrArray.length - 1); var loc2:*=0; while (loc2 < vcrArray.length) { if (vcrArray[loc2] != vcr.empty) { vcrArray[loc2].visible = true; if (!(vcrArray[loc2].fixed == "fluid") && !(vcrArray[loc2].fixed == "variable")) { vcrWidthFixed = vcrWidthFixed + vcrArray[loc2].fixed; vcrArray[loc2].myWidth = vcrArray[loc2].fixed; } else if (vcrArray[loc2].fixed != "variable") { loc3 = vcrArray[loc2]; loc1 = loc2; } else { vcrWidthFixed = vcrWidthFixed + vcrArray[loc2].timeDisplay.width; vcrArray[loc2].myWidth = vcrArray[loc2].timeDisplay.width; } } ++loc2; } vcrFluidWidth = stage.stageWidth - vcrWidthFixed - vcr_padding * 2; var loc4:*; loc3.bg.width = loc4 = vcrFluidWidth; loc3.bar.width = loc4; loc2 = 0; while (loc2 <= loc1) { vcrLeft = loc2 != 0 ? vcrArray[(loc2 - 1)].x + vcrArray[(loc2 - 1)].myWidth : vcr_padding; vcrArray[loc2].x = vcrLeft; vcrArray[loc2].y = 0; ++loc2; } loc2 = (vcrArray.length - 1); while (loc2 > loc1) { vcrLeft = loc2 != (vcrArray.length - 1) ? vcrArray[loc2 + 1].x - vcrArray[loc2].myWidth : stage.stageWidth - vcr_padding - vcrArray[loc2].myWidth; vcrArray[loc2].x = vcrLeft; vcrArray[loc2].y = 0; --loc2; } return; }
remane the variables generated by the decompiler, to improve the readablity:
Laying the Components:
public function vcrLayout():* { var _mc:*=null; vcrSort(); vcr.x = 0; vcr.y = stage.stageHeight - vcr.bg.height; vcr.bg.width = stage.stageWidth; vcrWidthFixed = 0; var _total:int=(vcrArray.length - 1);trace(vcrArray.length); var _i:int=0; while (_i < vcrArray.length) { if (vcrArray[_i] != vcr.empty) { vcrArray[_i].visible = true; if (!(vcrArray[_i].fixed == "fluid") && !(vcrArray[_i].fixed == "variable")) { vcrWidthFixed = vcrWidthFixed + vcrArray[_i].fixed; vcrArray[_i].myWidth = vcrArray[_i].fixed; } else if (vcrArray[_i].fixed != "variable") { _mc = vcrArray[_i]; _total = _i; } else { vcrWidthFixed = vcrWidthFixed + vcrArray[_i].timeDisplay.width; vcrArray[_i].myWidth = vcrArray[_i].timeDisplay.width; } } ++_i; } vcrFluidWidth = stage.stageWidth - vcrWidthFixed - vcr_padding * 2; _mc.bg.width = vcrFluidWidth; _mc.bar.width = vcrFluidWidth; _i = 0;trace("_total: " + _total); while (_i <= _total) {trace(_i); vcrLeft = _i != 0 ? vcrArray[(_i - 1)].x + vcrArray[(_i - 1)].myWidth : vcr_padding; vcrArray[_i].x = vcrLeft;trace("vcrArray[" + _i + "]: x=" + vcrLeft); vcrArray[_i].y = 0; ++_i; } _i = (vcrArray.length - 1); while (_i > _total) { vcrLeft = _i != (vcrArray.length - 1) ? vcrArray[_i + 1].x - vcrArray[_i].myWidth : stage.stageWidth - vcr_padding - vcrArray[_i].myWidth; vcrArray[_i].x = vcrLeft; vcrArray[_i].y = 0; --_i; } return; }
At the beginning, it calls vcrSort(), it sort the elements in thevcrArrayby their weight. The result is, the less the weight goes, the more left the element laid in vcr MC.
Array.sortOn() reference on Adobe.com
Each element has another property-fixed, it may be: 'fluid', 'variable' or a numeric value,20 in this program.
According to the program, only one element can be fluid, means its width is determined by how much space left for it. And bar is fluid. current time and total time are variable, their width are determined by theirTextField's width. And others' width are fixed, as their fixed property specify. So the first while loop insidevcrSort() calculates the position and then, the second while loop place the elements left to the bar, which is fluid; align them on left; the last one loop lay the right ones, aligns them on right:
So, actually, the fixed property of the elements are not volatile at all, besides, the first call to vcrLayout() happans before the xml loaded, and there is no re-assignment to the elements' fixed properties, so the later call to vcrLayout() are useless; there'sno need to run it each timevideoStatus() runs.
And now we go back to the structure diagram of the program:
- Investigation of CircleCube Video Player (Day 4)
- Investigation of CircleCube Video Player (Day 1)
- Investigation of CircleCube Video Player (Day 2)
- Investigation of CircleCube Video Player (Day 3)
- Investigation of CircleCube Video Player (Day 5)
- Investigation of CircleCube Video Player (Day 6)
- Investigation of CircleCube Video Player (Day 7)
- Quick Conclusion about CircleCube Video Player
- From pruned CircleCube Video Player to e-Notice module - Movie Gallery Player
- the archtechture of flash video player
- Actionscript 2.0 Flash "HD VIDEO" - Investigation
- HTML5 Video Player
- Open Video Player (OVP)
- Adobe 0day video
- Investigation of Why InetAddress.isReachable() Returning false
- Investigation on performance of data load
- video player 的解码实现
- video player demo in android
- 网易图片浏览模块分析:gallery,预加载
- linux kernel 从入口到start_kernel 的代码分析
- synapse之URL重写
- PKCS1Padding
- Oracle学习交流(1)-----SQL语言基础
- Investigation of CircleCube Video Player (Day 4)
- 在Xcode下使用SVN
- Oracle学习交流(2) -----管理数据库对象
- 而立,不惑和知天命—程序员的三个层次
- java操作oracle中blob
- Windows 7下安装ORACLE Developer 10.1.2.0.2
- 我的screen配置文件
- 在ObjectArx中调用dll中的导出对话框或控件时的注意事项
- 【原创】文件过滤驱动sfilter学习笔记