package { import flash.display.Sprite; import flash.events.Event; [SWF(width=465,height=465,frameRate=60)] public class YouTubeSwitcher extends Sprite { private static const MAX_PLAYER_NUM:int = 2; // objects private var box:SearchBox; private var players:Array; private var parentPlayer:ParentPlayer; // containers private var parentCont:Sprite; private var playerCont:Sprite; private var textsCont:Sprite; private var boxCont:Sprite; public function YouTubeSwitcher() { makeContainers(); makePlayers(); setSearchBox(); addEventListener( Event.ADDED_TO_STAGE, function( event:Event ):void{ box.setFocus(); }); } /** * --------------------------- * public methods * --------------------------- */ public function changeVideo( event:PlayerEvent ):void{ if( playerCont.numChildren ) playerCont.removeChildAt(0); var player:YouTubePlayer; if( players.length > event.index ){ player = players[ event.index ]; if( player.available ){ playerCont.addChild( player ); } } } /** * --------------------------- * private methods * --------------------------- */ private function start( event:PlayerEvent ):void{ parentPlayer.removeEventListener( PlayerEvent.PLAY, start ); parentPlayer.start( 136/2, MAX_PLAYER_NUM ); parentPlayer.addEventListener( PlayerEvent.CHANGE_VIDEO, changeVideo ); } private function setParent():void{ parentPlayer = new ParentPlayer(); parentPlayer.addEventListener( PlayerEvent.PLAYER_READY, function( event:PlayerEvent ):void{ parentPlayer.removeEventListener( PlayerEvent.PLAYER_READY, arguments.callee ); parentPlayer.search("scrumdiddlyumptious"); }); parentPlayer.addEventListener( PlayerEvent.VIDEO_CUED, function( event:PlayerEvent ):void{ parentPlayer.removeEventListener( PlayerEvent.VIDEO_CUED, arguments.callee ); parentPlayer.play(); }); parentPlayer.addEventListener( PlayerEvent.PLAY, start ); parentCont.addChild( parentPlayer ); } private function makeContainers():void{ addChild( parentCont = new Sprite()); addChild( playerCont = new Sprite()); addChild( textsCont = new Sprite()); addChild( boxCont = new Sprite()); } private function makePlayers():void{ players = []; var count:int=0; for( var i:int=0;i<MAX_PLAYER_NUM;i++){ var player:YouTubePlayer = new YouTubePlayer(); players.push( player ); player.addEventListener( PlayerEvent.PLAYER_READY, function( event:PlayerEvent ):void{ player.removeEventListener( PlayerEvent.PLAYER_READY, arguments.callee ); if( ++count == MAX_PLAYER_NUM ) setParent(); }); } } private function setSearchBox():void{ box = new SearchBox( this ); boxCont.addChild( box ); box.addEventListener( SearchBoxEvent.REQUEST, function( event:SearchBoxEvent ):void{ var player:YouTubePlayer; var tmp:Array = players.slice(0); while( tmp.length ){ player = tmp.splice( Math.floor( Math.random() * tmp.length ))[0]; if( !player.available ) break; } player.search( event.keyword ); player.addEventListener( PlayerEvent.VIDEO_CUED, function( event:PlayerEvent ):void{ player.removeEventListener( PlayerEvent.VIDEO_CUED, arguments.callee ); player.play(); }); }); } } } import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.net.URLLoader; import flash.net.URLRequest; import flash.system.Security; import flash.utils.escapeMultiByte; class YouTubePlayer extends Sprite{ private static const PLAYER_URL:String = "http://www.youtube.com/apiplayer?version=3"; private static const YOUTUBE_DOMAIN:String = "www.youtube.com"; private static const SEARCH_URL_BASE:String = "http://gdata.youtube.com/feeds/api/videos?vq="; protected var player:Object; protected var defaultVolume:Number = 80; private var loader:Loader; public var available:Boolean = false; public function YouTubePlayer() { setBlack(); setPlayer(); } public function search( keyword:String ):void{ treasureHunt( escapeMultiByte( keyword ) ); } public function play():void{ player.playVideo(); addEventListener( Event.ADDED, addedHandler ); addEventListener( Event.REMOVED, removedHandler ); } public function addedHandler( event:Event ):void{ player.setVolume( defaultVolume ); } public function removedHandler( event:Event ):void{ player.setVolume(0); } /** * --------------------------- * private methods * --------------------------- */ private function setBlack():void{ graphics.beginFill(0); graphics.drawRect( 0, 0, 465, 465 ); } private function setPlayer():void{ Security.allowDomain(YOUTUBE_DOMAIN); loader = new Loader(); loader.contentLoaderInfo.addEventListener( Event.INIT, loaderInitHandler ); loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, function( event:IOErrorEvent ):void{ loader.load( new URLRequest(PLAYER_URL)); }); loader.load( new URLRequest(PLAYER_URL)); } private function loaderInitHandler( event:Event ):void{ addChild( loader ); loader.content.addEventListener( "onReady", function( event:Event ):void{ player = loader.content; player.setSize( 465, 465 ); player.setPlaybackQuality("small") player.setVolume( defaultVolume ); player.addEventListener( "onStateChange", playerStateChangeHandler ); dispatchEvent( new PlayerEvent( PlayerEvent.PLAYER_READY )); }); } private function treasureHunt( keyword:String ):void{ var maxResults:String = "&max-results=" + 1; var url:String = SEARCH_URL_BASE + keyword + maxResults + "&format=1"; var xmlLoader:URLLoader = new URLLoader(); xmlLoader.addEventListener( Event.COMPLETE, function( event:Event ):void{ default xml namespace = new Namespace("http://www.w3.org/2005/Atom"); var str:String = String( xmlLoader.data ).substr( 38 ); readXML( XML( str )); }); xmlLoader.load( new URLRequest( url )); } private function readXML( xml:XML ):void{ var id:String = String( xml.entry.id ).split("/").pop(); player.cueVideoById(id); } private function playerStateChangeHandler( event:Event ):void{ var data:Object = Object( event ).data; switch( int( data )){ case 1: dispatchEvent( new PlayerEvent( PlayerEvent.PLAY )); available = true; break; case 5: dispatchEvent( new PlayerEvent( PlayerEvent.VIDEO_CUED )); break; } } } import flash.events.Event; class ParentPlayer extends YouTubePlayer { private var videoNum:int; private var secBPM:Number; private var prevIndex:int; public function ParentPlayer() { super(); visible = true; } public override function addedHandler(event:Event):void{ } public override function removedHandler(event:Event):void{ } public function start( bpm:Number, videoNum:int ):void{ this.videoNum = videoNum; this.secBPM = toSec( bpm ); player.setVolume(100); addEventListener( Event.ENTER_FRAME, enterFrameHandler ); function toSec( bpm:Number ):Number{ return 60 / bpm; } } private function enterFrameHandler( event:Event ):void{ var currentTime:Number = player.getCurrentTime() - .1; var currentIndex:int = Math.floor( currentTime / secBPM ) % ( videoNum + 1 ); if( currentIndex != prevIndex ) { dispatchEvent( new PlayerEvent( PlayerEvent.CHANGE_VIDEO, false, false, Math.abs( currentIndex ))); } prevIndex = currentIndex; } } import flash.events.Event; class PlayerEvent extends Event { public static const PLAYER_READY:String = "playerReady"; public static const PLAY:String = "play"; public static const VIDEO_CUED:String = "videoCued"; public static const CHANGE_VIDEO:String = "changeVideo"; public var index:int; public function PlayerEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, index:int=-1) { super(type, bubbles, cancelable ); this.index = index; } } import flash.events.Event; class SearchBoxEvent extends Event { public static const REQUEST:String = "request"; public var keyword:String; public function SearchBoxEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, keyword:String = "dummy") { super(type, bubbles, cancelable); this.keyword = keyword; } } import flash.events.KeyboardEvent; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.ui.Keyboard; class SearchBox extends TextField { private var switcher:YouTubeSwitcher; public function SearchBox( switcher:YouTubeSwitcher ) { this.switcher = switcher; var format:TextFormat = new TextFormat("Century", 18, 0 ); format.align = TextFormatAlign.CENTER; defaultTextFormat = format; background = true; backgroundColor = 0xFFFFFF; type = TextFieldType.INPUT; x = 100; y = 465/2-10; width = 265; height = 20; } public function setFocus():void{ stage.focus = this; text = "WORDS TO SEARCH FOR"; setSelection( 0, text.length ); stage.addEventListener( KeyboardEvent.KEY_DOWN, function( event:KeyboardEvent ):void{ if( event.keyCode == Keyboard.ENTER ){ dispatchEvent( new SearchBoxEvent( SearchBoxEvent.REQUEST, false, false, text )); text = ""; } }); } } YouTube Mixer