Nov 21

 

It has been a great week at MAX ‘08, providing great experience for me and looking at all the new technology Adobe has to offer. Love the Keynote, Sneak Peaks, Great People and the excellent MAX Party!

Developer Point of View
Particularly interesting to me, in order of interest is Alchemy - C and C++ codes for Flash, Cocomo, ability to have P2P video in Flash, Flex 4 Gumbo and Server Side Actionscript, and Flash Catalyst (formly Thermo)

With Alchemy, it simply means the ceiling is now higher for us the developers. Anything is now possible now on the client side and developers will have to at least have an overview of how it works in order to be able to utilize the wide array of libraries existed nowadays and incorporate them in their client. Website owners should seriously look into this piece of technology to see how they can use Alchemy to create new experiences for their users. Using Alchemy, you can achieve things that are never possible in Flash (like the Quake demo in MAX ) and thus it also give rise to new business opportunities. I will be spending the next few weeks to dive deep into Alchemy and will post up some experiments I have here.

Cocomo is SaaS from a Social Networking point of view. Tied closely to Acrobat.com, it allows developers to tap into existing components in Acrobat.com, like video chat capability and real time file sharing, and use them in their own application. It is definitely a welcoming for us developers as it gives us another option to create RIA without installing our own infrastructure. 

Flex 4 , as most people might already know, will have better skinning workflow, better performance, separation between component business logic and UI elements, support of shapes and graphics in MXML (like degrafa). It also introduce a own new set of components extended from the FxComponent (like UIComponent in Flex 3), 2 way binding, and the feature that makes everyone claps - a “layer” property in the component that defines the depth rather than the childIndex! All these in a new MXML 2009 namespace ;)

And of course, Flash Catalyst (Fc), formerly Thermo, is also heavily showcased during the event. Fc allow designers to create their graphics in Photoshop or Illustrator, export them in a format FXG, and continue to work in Fc, and effectively saving the files as MXML into a Flex project! While I personally do not think Fc take off quickly as a tool of dictating the entire site UI (remember the Dreamweaver symdrome? ), but I do believe it will become real popular for developers in terms of component skinning. As Ryan Stewart demoed in MAX, with just a few click, it will skin a component like scrollbar automatically, which is a huge step from Flex 3. 

Community Manager Point of View

MAX provides a lot of opportunities for User group managers (UGM) to network with other User group managers and Adobe’s community managers . This time, Adobe launches Adobe Group, which FUG is part of it!. Flex Camp is also now officially Flash Camp. It is very encouraging that Adobe is pushing for the community than ever before, providing us the UGM with valuable resources and directly support. 

I also meet up with the UGM from Hong Kong, Taiwan and Seoul. Try to spot us in the photo below.

It is great when we start to see people from SEA and who knows, we might start seeing some asia speakers for MAX in the future!

Overall
Its been a great 3 days at MAX and an even better week in San Francisco. Now there is lots of new technologies to play, with the bar rise much higher than before! Work hard developers!

Lastly, not related to MAX, but hey I am on Seesmix!!!

 

Nov 06

The Problem
For many developers, this can be a no-brainer problem to start with. Most (if not all ) mashups uses videos from YouTube. There are tons of resources online that teach us how to “scrap” the FLV of youtube videos so we can play it in our own applications.

Going a few months back, YouTube had already released the chromeless player , a plain player without controls for playing youtube videos. However, there is no immediately “need” for developers to change their player to suit the chromeless player. Afterall, “if it ain’t broken, don’t fix it”. Last week however, YouYube removed some parameters in their APIs calls, effectively making some “scrapping” process not working. There are still some workarounds to get the FLV of their videos, but even if developers can “hack” to make it work, it is still against YouTube TOS. For many developers, the most straight forward solution is, well, use the chromeless player.

Chromeless Player is made in AS2 but I code in AS3
Now that the solution is pointing to Chromless Player, with the coherent and straightforward YouTube documentations, developers can easily fit the Chromeless Player into their application. For AS2 developers, it is a task of merely loading the SWF and passing commands to it. For AS3 developers, the problem arise as AS3 swfs cannot communicate with AS2 swfs directly. Thus, AS3 developers can load the Chromeless Player, but they cannot effectively communicate with it to get the play time, stop the video, pause the video etc.

AS2 Wrapper , LocalConnection to AS3
After searching around on google, many are facing this problem and the solution points down to using localconnection. Matthew Encinas posted this solution here, which works great. It involves creating an AS2 wrapper, which connects to a localconnection instance. The AS3 wrapper then load the AS2 wrapper, which in turns loads the Chromeless Player. To make things easier to understand, I have created a diagram below:

Codes from Matthew Encinas: http://groups.google.com/group/youtube-api-gdata/browse_thread/thread/3c98068961296b38/07ecb5ee1168cefb?lnk=gst&q=as3#07ecb5ee1168cefb

Help! LocalConnection naming problem!
The problem with this approach is that you are using a fixed localconnection name for your swf. If your player is a video player, which can have multiple instances at the same time, you will receive an error that the localconnection is already in used. To solve this problem, append something like ?key= when loading the AS2 Wrapper, and using that to name your localconnection name

Sample Classes
Modifying Matthew’s code, with the localconnection fix gives us the following 2 piece of codes:

AS2 Codes (the youtubewrapper.swf)

System.security.allowDomain('www.youtube.com');
System.security.allowDomain('gdata.youtube.com');
System.security.allowInsecureDomain('gdata.youtube.com');
System.security.allowInsecureDomain('www.youtube.com');
var loadInterval:Number;
var ytplayer:MovieClip = this.createEmptyMovieClip("ytplayer",
this.getNextHighestDepth());
 var key   = _root.key;
 
var swf:String = "http://www.youtube.com/apiplayer";
//This created a connection for AS3 to talk to it
var _as3_to_as2:LocalConnection = new LocalConnection();
_as3_to_as2.connect("AS3_to_AS2_" + key);
//This is to connect to a connection started by the AS3 file
var _as2_to_as3:LocalConnection = new LocalConnection();
ytPlayerLoaderListener = {};
ytPlayerLoaderListener.onLoadInit = function() {
    loadInterval = setInterval(checkPlayerLoaded, 250);
} 
 
function checkPlayerLoaded():Void {
    if (ytplayer.isPlayerLoaded()) {
                //Let the AS3 file know that the player is loaded
                // the function onSwfLoadComplete exists within the AS3 file
                _as2_to_as3.send("AS2_to_AS3_" + key, "onSwfLoadComplete");
                clearInterval(loadInterval); // IMPORTANT - kill the interval
                ytplayer.addEventListener("onStateChange", onPlayerStateChange);
                ytplayer.addEventListener("onError", onPlayerError); 
 
        }
} 
 
function onPlayerStateChange(newState:Number) {
	 // Possible values are unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)
 
	  _as2_to_as3.send("AS2_to_AS3_" + key, "onPlayerStateChange", newState); 
 
	 switch(newState)
	 {
			case -1:
		 	case "unstarted":
			break;
			case 0:
 
			case "ended":
			clearInterval(playInt)
			break;
 
			case 1:
			case "playing":
		playInt = setInterval(onPlay, 1000)
 
			break;
			case 2:
			case "paused":
			break
			case 3:
			case "buffering":
			 clearInterval(playInt)
			break
			case 5:
			case "video cued":
			break;
	 }
 
} 
 
function sendCurrentTime():Void
{
	var current = ytplayer.getCurrentTime()
 
	var duration = ytplayer.getDuration() 
 
_as2_to_as3.send("AS2_to_AS3_" + key, "onDuration", current, duration); 
 
}
function onPlay()
{
 
	sendCurrentTime();
}
function onPlayerError(errorCode:Number) {
    //do something on player error
} 
 
var ytPlayerLoader:MovieClipLoader = new MovieClipLoader();
ytPlayerLoader.addListener(ytPlayerLoaderListener);
ytPlayerLoader.loadClip(swf, ytplayer);
//////// CREATE EVENT HANDLERS
// These functions can be called from within the AS3 file
// This is the window where AS3 will access the API
// You can add any of the Javascript Api here
_as3_to_as2.pauseVideo = function(){
    ytplayer.pauseVideo();
}; 
 
_as3_to_as2.playVideo = function(){
    ytplayer.playVideo();
}; 
 
_as3_to_as2.stopVideo = function(){
    ytplayer.stopVideo();
}; 
 
_as3_to_as2.loadVideoById = function(id){
        ytplayer.loadVideoById(id, 0);
}; 
 
//setSize(width:Number, height:Number):Void
_as3_to_as2.setSize  = function(swidth:Number, sheight:Number):Void
{
	ytplayer.setSize(swidth, sheight)
}
 
_as3_to_as2.cueVideoById = function(video_id:String, second:Number):Void
{
	ytplayer.cueVideoById(video_id,  second)
}
 
function doDispatchEvent ()
{
 
}

AS3 Codes

package com.mypackage.view
{ 
 
import flash.display.Loader;
        import flash.events.Event;
        import flash.events.StatusEvent;
        import flash.net.LocalConnection;
        import flash.net.URLRequest;
        import flash.system.Security;
 
import mx.core.Application;
        import mx.core.UIComponent;
        import mx.events.FlexEvent;
        [Event(name="init", type="flash.events.Event")]
        public class YouTube extends  UIComponent
        {
                private var _loader:Loader;
                private var _as3_to_as2:LocalConnection;
                private var _as2_to_as3:LocalConnection;
                public function YouTube(){
 
Application.application.addEventListener(FlexEvent.APPLICATION_COMPLETE, init)
                }
 
public function init(e:FlexEvent){
                        Security.allowDomain('www.youtube.com');
                        Security.allowDomain('gdata.youtube.com');
                        Security.allowInsecureDomain('gdata.youtube.com');
                        Security.allowInsecureDomain('www.youtube.com');
                        _as3_to_as2 = new LocalConnection();
                        _as3_to_as2.addEventListener(StatusEvent.STATUS,
onLocalConnectionStatusChange);
                        _as2_to_as3 = new LocalConnection();
                        _as2_to_as3.addEventListener(StatusEvent.STATUS,
onLocalConnectionStatusChange);
                        _as2_to_as3.client = this;
                        //This enables the local connection to
//use functions of this class
 
_as2_to_as3.connect("AS2_to_AS3_" + key);
                        _loader = new Loader();
                        _loader.contentLoaderInfo.addEventListener(Event.INIT, onWrapperInit)
                        _loader.load(new URLRequest("youtubewrapper.swf?key=" + key));
                }
               private var key :String = generateKey()
                private function onWrapperInit(e:Event):void
                {
 
}
                private function generateKey():String
                {
                	return this.generationCharCode()
                }
 
protected function generationCharCode():String
 		{
 			var code:String = ""
 			while(code.length < 10)
 			{
 				var cc :uint = Math.floor(Math.random() * 1000 ) % 123
 				if(cc < 48 || (cc >= 58 && cc <= 64) ||  (cc >= 91 && cc <= 96))
 				{
 
continue;
 				}
 
code += String.fromCharCode(cc)
 			}
 			return code;
 
}
                public function stopVideo():void {
                	this.current = this.total = 0;
 
_as3_to_as2.send("AS3_to_AS2_" + key, "stopVideo");
                }
                public function playVideo():void {
                        _as3_to_as2.send("AS3_to_AS2_" + key, "playVideo");
                }
                public function pauseVideo():void {
                        _as3_to_as2.send("AS3_to_AS2_" + key, "pauseVideo");
                }
                public function loadVideoById(id:String):void {
                        _as3_to_as2.send("AS3_to_AS2_" + key, "loadVideoById", id);
                }
 
public function setSize(width:Number, height:Number):void
                {
                	_as3_to_as2.send("AS3_to_AS2_" + key, "setSize", width, height);
                }
                public function cueVideoById(video_id:String, seconds:Number):void
                {
                	_as3_to_as2.send("AS3_to_AS2_" + key, "cueVideoById", video_id, seconds)
 
}
 
public function onPlayerStateChange(stateName):void
                {
 
}
                public function onDuration(current, total):void
                {
 
this.current = current
                	this.total = total;
                }
 
[Bindable]    public var current:Number;
 
[Bindable]   public var total:Number;
 
public function onSwfLoadComplete():void {
                        addChild(_loader);
                        dispatchEvent(new Event(Event.INIT));
                }
 
private function onLocalConnectionStatusChange(e:StatusEvent):void{
                        // error was thrown without this handler
                }
        }
}

Happy YouTubing!

Nov 06

I am so thrill when I see this video! Lee Brimelow blow us away with this video he made himself with a Canon HV20, Premiere CS4 and of course his wonderful editing skills.

Get the Flash Player to see this player.

Thank you Lee ! You rock! This video make my day!

Nov 01


Image from APLINK

 

I am very honored to be part of the speakers’ panel for Digital Media Festival 2008, the augural conference in Singapore for Web 2.0 and Social Media. I spoke on Building your Community 2.0, using Seesmic as one of its examples, as well as sites like GetSatisfaction, Twitter and ways to gather feedbacks from your Community.

At the backstage, I go around interviewing the great speakers. I managed to get Hugh Hancock, the man to coin the term “Machinima”, answering some questions the seesmic community posted, as well as Timo Vuorensola, director of Star Wreck, on community collaboration of videos

See the videos below and input your comments!

Interview with Hugh Hancock:
Where should they put their videos to ? http://seesmic.com/videos/HSJ7EcUwRy
Which game should they start with ? http://seesmic.com/videos/TFqB5frY5t
How do we create complex animation? http://seesmic.com/videos/8QCJ8JDQp4
How do we have customized scenes? http://seesmic.com/videos/qzL7osRpnv

Interview with Timo Vourensola

The event boast a wide variety of booths and technology showcase. I managed to interview with a couple of companies like Paymo as well as Garena
 

Paymo is a mobile payment solution, similar to Paypal, but enables anyone who has a handphone to pay using SMS. Definitely a good micropayment solution that I can look into for future events or even donations!

Garena is a Community Portal for Gamers to find fellow gamers to join in games like DOTA, WoW, CS, etc. At the point of interview, over 100k of gamers are connected on the portal playing games, a very impressive numbers!

  

Stefano Virgilli on his talk and creative crew:

Congrats SITF, @itr8 and the organizing committee for the success! Its been a great experience and I am looking forward to DMFest 2009!

 


Video title:

Description: