wordpress flash API – sample code – Part 2

Posted in AMFPHP, Actionscript 3.0, Wordpress on June 8th, 2009 by Omar Faleh – 1 Comment

This post is part two of the AMF/PHP connector class that I started in a previous thread talking about the PHP part

now.. we go to flash. The first class is the DataConnector which establishes the connection to the AMF/PHP connector and calls the function
we declare a variable called callTitle which is assigned based on which function we’re calling. this variable is then used to decide what action to do in the event listener.

package data
{
	import events.Communicator;

	import flash.events.*;
	import flash.net.NetConnection;
	import flash.net.Responder;

	public class DataConnector extends EventDispatcher
	{

		private var gateway			:String ;
		private var callTitle		        :String = "";
		private var connection		:NetConnection;
		private var responder		:Responder;

		public function DataConnector()
		{

			gateway	= "./connectors/gateway.php";

			responder = new Responder(onResult, onFault);
			connection = new NetConnection;
			connection.connect(gateway);
		}

		public function getCategoryList(parentCatName:String = ""):void
		{
			callTitle = "getCategoryList";
			parentCategory = parentCatName;
			connection.call("functions.getCategoryList", responder , parentCatName);
		}
		public function getCategoryPosts(_catName:String = ""):void
		{
			callTitle = "getCategoryPosts";
			catName = _catName;
			connection.call("functions.getCategoryPosts", responder , catName);
		}

		public function getPostList():void
		{
			callTitle = "getPostList";
			connection.call("functions.getPostList", responder);
		}

		public function getPost(id:String):void
		{
			callTitle = "getPost";
			postID = id;
			connection.call("functions.getPost", responder , postID);
		}

		private function onResult(result:Object):void
		{
			switch (callTitle)
			{
			 	case "getCategoryList":
			 		result = result as Array;
			 		var _cat:Array = new Array();
			 		for (var i:int=0; i <result.length; i++)
					{
						var _obj:Object = new Object();
						_obj.id 	= result[i].id ;
						_obj.title 	= result[i].title ;
						_obj.desc	= result[i].description;
						cat.push(obj)
					}
					// now do something with that array
			 	break;

			 	case "getPostList":
			 	       result = result as Array;
			 		var _cat:Array = new Array();
			 		for (var i:int=0; i<result.length; i++)
					{
						var _obj:Object = new Object();
						_obj.id 	= result[i].id ;
						_obj.title 	= result[i].title ;
						cat.push(obj)
					}
					// now do something with that array
			 	break;

			 	case "getCategoryPosts":
			 	       result = result as Array;
			 		var _cat:Array = new Array();
			 		for (var i:int=0; i<result.length; i++)
					{
						var _obj:Object = new Object();
						_obj.index= result[i].index ;
						_obj.id 	= result[i].id ;
						_obj.title 	= result[i].title ;
						cat.push(obj)
					}
					// now do something with that array
			 	break;

			 	case "getPost":
			 		result = result as Object;
					// do something with the object
					// like trace(result.post.title) , trace(result.post.content) , trace(result.post.date)
					// and:
					// for (var i:int=0; i< result.meta.length; i++)
					// {
					//       trace(result.meta[i].index , " : " , result.meta[i].value);
					// }
			 	break;

			}
		}

		private function onFault(fault:Object):void
		{
			trace(String(fault.description));
		}
	}
}

This class can now be called from the parent class (Main for example) in the following fashion:

package
{
	import data.DataConnector;
	import flash.display.Sprite;
	import flash.events.*;

	public class Main extends Sprite
	{
		private var _dataConnector :D ataConnector;

               public function Main()
		{
			_dataConnector = new DataConnector();
			_dataConnector.getCategoryList("cat1");
		}
         }
}

the way I usually do its is follow this sequence:
Main -> DataConnector -> call Function
DataConnector ->receive Call result and handle Data
DataConnector -> Dispatch Event with the handled Data
Main -> receive the event in an event listener -> use the data.

but again, this sequence is very dependant on the structure of your classes and projects.. so now you’re on your own…

hope this was helpful enough

wordpress flash API – sample code – Part 1

Posted in AMFPHP, Actionscript 3.0, Wordpress on June 8th, 2009 by Omar Faleh – 1 Comment

so after some expermintations, I could finally get around to posting my findings.. available for people to grab should they wish to.

a big credit is due to Tim Wilson on his library which was the basis of all the work I have done in here. I only changed the return types of the functions to be of custom data types instead of XML.

steps of reproduction:
1- download the AMFPHP package from http://sourceforge.net/project/showfiles.php?group_id=72483#files

2- unzip the package in your flash export folder (WWW for example, or DEPLOY, or whatever you call it).. put all the AMF files inside a folder and name it as you wish (I am going to call it connectors for example

3- in services/DatabaseRequest.php fill in your appropriate username/password/db name and hostname

4-go to services/functions.php and write your functions there.. I am using these functions:

function getPostList()
{
	$dbc = new DatabaseRequest();
	$db_query = $dbc->call("SELECT * FROM wp_posts WHERE post_status='publish' AND post_type !='page' ORDER BY ID DESC");		

	$posts = array();
	$i =0;

	while ($fields = mysql_fetch_array($db_query))
	{
		$posts[$i] = array(id=>$fields['ID'] , title => $fields['post_title']);
		$i ++;
	}

	return $posts;
}

and

function getCategoryList($parentCategorySlug)
{ 

	$dbc = new DatabaseRequest();

	$query = "SELECT wp_terms.slug, wp_terms.name, wp_term_taxonomy.description FROM wp_terms, wp_term_taxonomy WHERE wp_terms.term_id = wp_term_taxonomy.term_id AND wp_term_taxonomy.taxonomy = 'category'".
				(($parentCategorySlug != "") ? "AND wp_term_taxonomy.parent IN ( SELECT term_id FROM wp_terms WHERE wp_terms.slug LIKE '".$parentCategorySlug."')" : "") ;

	$db_query = $dbc->call($query);        

	$arr = array();
	$i=0;

	while ($fields = mysql_fetch_array($db_query))
	{
		$arr[$i] = array(title =>$fields['name'] , id => $fields['slug'] , description=>$fields['description']);
		$i ++;
	}
	return $arr;
}

and

function getCategoryPosts($categorySlug)
{
	$dbc = new DatabaseRequest();
	$db_query = $dbc->call("SELECT * FROM wp_posts
							LEFT JOIN wp_term_relationships ON ( wp_posts.ID = wp_term_relationships.object_id )
							LEFT JOIN wp_term_taxonomy ON ( wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id )
              				WHERE wp_posts.post_status = 'publish' AND wp_term_taxonomy.taxonomy = 'category' AND wp_term_taxonomy.term_id in
							(SELECT term_id FROM wp_terms WHERE wp_terms.slug LIKE '".$categorySlug."')" );

	$posts = array();
	$i =0;

	while ($fields = mysql_fetch_array($db_query))
	{
		$indexQuery = "SELECT meta_value FROM wp_postmeta  WHERE post_id =".$fields['ID']." AND meta_key LIKE 'index'";
		$db_query1 = $dbc->call($indexQuery );
		$index = mysql_fetch_array($db_query1);

		$posts[$i] = array(index => $index[0] , id => $fields['ID'] , title =>$fields['post_title']);
		$i++;
	}
	return $posts;
}

and

function getPost($postID)
{

	$dbc = new DatabaseRequest();
       $query ="
		SELECT * FROM wp_posts	WHERE wp_posts.ID=".$postID." AND wp_posts.post_status = 'publish'";

	$db_query = $dbc->call($query);

	$fields = mysql_fetch_array($db_query);
	$post = $fields[0];
	$arr=array();

	if(count($fields) == 1)
	{
		createFailMessage('Post Not Found');
	}
	else
	{
	$post = array(	id=> $fields['ID'] ,
				title=>$fields['post_title'] ,
				content => $fields['post_content'] ,
				date=> $fields['post_modified_gmt']
				 );

	// Get any Custom Fields for this Post.
	$additionalFields = $dbc->call("SELECT * FROM wp_postmeta WHERE post_id='".$fields['ID']."';");
	$extrFields = array();
	$j=0;
	while ($customField = mysql_fetch_array($additionalFields))
	{
		$extrFields[$j] = array(
				index => $customField['meta_key'],
				value => $customField['meta_value']
			);
		$j++;
	}

	$result = array(post => $post , meta =>$extrFields);

	return $result;
}

the beauty of AMF/PHP is that you can get returns in the form of objects, arrays, multidimensional arrays, and objects that has properties that are a mix of arrays and regular data types..

so now, we have all the PHP functions that need to be called in order to get data from the Database… notice that in the getPost function, I am also returning the meta fields associated with the post, based on that post ID.

the flash part of that communication will be in part 2 of this post

papervision 3D optimization tip #1

Posted in Actionscript 3.0, Other on May 29th, 2009 by Omar Faleh – Be the first to comment

I am not a big papervision fan, and I don’t usually hide it.

PV3D is interesting and versatile, and allows great flexibility in developing great websites and apps, however it’s always a pain to optimize, and I always end up spending 40% of my development time dealing with memory leaks, optimization techniques, objects that don’t really get removed from stage, events that don’t get fired.. etc… and now that I moved to flex development and have a profiler running on my applications, I see the incredible amount of junk that remain alive in the stage after 3d objects are removed.

so I started a quest to look for optimization techniques on the net, and bank them to get a reference for later projects.. here is the first one, courtesy of Seb Lee-Delisle

http://interactivehug.com/2008/04/21/john-iacoviello-papervision3d-optimization-tips/#comment-463

if you set your bitmap sizes to exponents of two, ie, 64, 128, 256, 512 etc. that way the built-in mipmapping in the FlashPlayer will enable much faster and smoother bitmap scaling and manipulation.

So a bitmap sized 512 x 512 will work a lot better than one that is 500 x 500

this is really interesting, we never actually take those things into consideration when we develop our code as we get the files from designers. will do some benchmarking and get back on that topic

wordpress flash API – pre production

Posted in AMFPHP, Actionscript 3.0, Wordpress on February 28th, 2009 by Omar Faleh – 2 Comments

I am in my 3rd week down the ugly road of redesigning my pathetic 5 year old, HTML only website now with broken databases)

as any other flash programmer would do, we try to use everything we know in remaking our website, which eventually leaves us stuck not doing anything cos we try to integrate everything at the same time

so I decided to go with the Backend CMS option (not that I have regularly updated content or anything) but more for the search engine optimisation reasons. so I decided to go with the natural solution of using wordpress as a backend, and connecto to its database using something…. and that “something” became a whole week work of research..

turns out that, as popular wordpress is, there is no out-of-the-box solution (open source of course) that you can use to connect to it.
the closest found was Tim Wilson’s Press Connect . which provides a very nice connection, only the only way I found to use it was through AS2 with the XML.sendAndLoad() interface.. and that of course does not work if you are planning to use AS3

so I decided to take the plunge and write my own connectors, basing my self on Tim Wilson’s code, and use AMFPHP to be the middle man. production started officially last thursday, and I am hoping that by the end of the weekend I will have most of my connectors ready for use.. and will probably share it on my blog for those who need some help doing what I am trying to do..

so, stay tuned…

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller

Posted in Actionscript 3.0, Code Snippets on February 13th, 2009 by Omar Faleh – 7 Comments

one of those little things that are not clearely documented or explained anywhere on the Adobe flash documentation..
I was calling a function to load an image and add it to stage, and everytime I called that image, I was getting this error:

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller

after 2 hours of trials and errors and 1 hour of web search, I finally found the answer below.

within this code:

package{
	import flash.display.DisplayObject;
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.net.URLRequest;
public class img extends Sprite
{
	private var loader:Loader = new Loader();
	...
	..
	public function loadBgImage():void
	{
		var randDate:Date = new Date();
		if (holder.getChildByName("bgImg"))
		{
			if (holder.contains(holder.getChildByName("bgImg")))
				holder.removeChild(holder.getChildByName("bgImg"))
		}
		var request:URLRequest = new URLRequest("images/bg.jpg?randPath="+randDate.getTime());
		loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler, false, 0, true);
		loader.load(request);
	}
	public function completeHandler(e:Event):void
	{

		var bm:Bitmap = e.target.contentas Bitmap;
		bm.smoothing = true;
		var sp:Sprite = new Sprite();
		sp.addChild(bm);
		sp.name = "bgImg";
		holder.addChild(sp);
	}
}

it works fine the first time.. however, while in runtime, if you try to call loadBgImage() again, you will get this error:

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller

and after lots of research, it turns out that this occurs when the Loader is declared as a global variable in the class (i.e: when we don’t say :var loader:Loader = new Loader() every time we call the function) and the load() function is called again after the first load

when the COMPLETE event is fired, if we add the loader to stage as a e.target.content, then we are actually adding the only instance of that loader (Loader is a DisplayObject after all)
so, if we try to remove it in the load function and remove it before calling the function again:

holder.removeChild(holder.getChildByName("bgImg"))

then we are actually removing the only instance of that loader, so when we try to call it again onloader.load(), the instance is not found..

Thanks to the fine gentelmen at Actionscript.or, this discussion solved my problem:
http://www.actionscript.org/forums/archive/index.php3/t-138634.html

so, the best way to do this is:
1- cast the content to a display Object, and unload the loader, and then add the newly created display Object to the stage : see below


public function completeHandler(e:Event):void
{
	var theImage:DisplayObject = e.target.content;
	loader.unload()
	var bm:Bitmap = theImage as Bitmap;
	bm.smoothing = true;
	var sp:Sprite = new Sprite();
	sp.addChild(bm);
	sp.name = "bgImg";
	holder.addChild(sp);
}

or, the second way to do this is:
2- get the bitmap data of that loaded content, make a clone, instantiate a new bitmap based on that bitmap data, and add that one to stage like this:


public function completeHandler(e:Event):void
{

	var bm:Bitmap = new Bitmap(((e.target.content as Bitmap).bitmapData as BitmapData).clone());
	bm.smoothing = true;
	var sp:Sprite = new Sprite();
	sp.addChild(bm);
	sp.name = "bgImg";
	holder.addChild(sp);
}

Bulk Loader and SWF Caching issues

Posted in Actionscript 3.0, Code Snippets on January 28th, 2009 by Omar Faleh – 1 Comment

while working with bulk loader on a big project recently, we were hit by one problem that took me a while to solve.
the problem was basically this: if you load an swf with bulkloader, everything looks fine and well..
unload it, try to load it again and it won’t load.. simply becase it is already in the cache of the browser , so the COMPLETE event was never firedthe second time.

I tried to set the {forceCache:false} in the case of loading an swf and that didn’t work also (it added a random string number after the name of the swf, and the container flash won’t load the swf at all in that case)

so.. here is the result of a full day of investigation

if (loader.hasItem(this.id[0] , true))
{
	loader.remove(this.id[0]);
}
loader.add(this.bg[0], { id:this.id[0]} );	

this way, the onComplete event will get fired after loading the swf for the second time, even though it’s already loaded and present in the cache

simple.. yet not documented properly

Double Buffering for smooth netstream FLV playback

Posted in Actionscript 2.0, Actionscript 3.0, Code Snippets on May 28th, 2008 by Omar Faleh – 5 Comments

This post is to highlight the double buffering technique (also known as dynamic buffering) that “should” make video streaming in flash alot smoother without having to prebuffer anything.

This technique works on progressive video download as well as streaming:

var startBufferLength:Number= 2; //keep this in the range 2-4+
var xpandedBufferLength:Number = 15;  //arbitrarily highnc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.setBufferTime(3);
ns.autoPlay = false;
ns.onStatus = Delegate.create(this, handleVideoStatus);//(if this was AS3 the syntax will be:
//ns.addEventListener(NetStatusEvent.NET_STATUS, handleVideoStatus);

// if this was Actionscript 3, this following line would be:
// private function handleStatus(event:NetStatusEvent):void 

function handleVideoStatus(infoObject:Object)
{

	switch (infoObject.code) {
		case "NetConnection.Connect.Success":

		break;

		case "NetStream.Buffer.Full":
			ns.bufferTime = xpandedBufferLength;
		break;

		case "NetStream.Buffer.Empty":
			ns.bufferTime = startBufferLength;
		break;

		case "NetStream.Play.Start":
			// the video has started playing, do something here
		break;

		case "NetStream.Play.Stop" :
			// the video has stopped playing (finished)
		break;

	}
}

Reading from and writing to shared object

Posted in Actionscript 2.0, Code Snippets on May 28th, 2008 by Omar Faleh – Be the first to comment

Reading the shared object:

var my_so:SharedObject = SharedObject.getLocal("SomeName");
var trackingDate:Date = my_so.data.theDate

writing to a shared object:

var my_so:SharedObject = SharedObject.getLocal("SomeName");
var _date = new Date();
my_so.data.theDate = _date;
my_so.flush(10000);

and clearing a shared object (erasing its content)

var my_so:SharedObject = SharedObject.getLocal("SomeName");
my_so.clear();

Loader flash calls a function from the loaded flash

Posted in Actionscript 3.0, Code Snippets on May 28th, 2008 by Omar Faleh – Be the first to comment

let’s imagine this scenario:
A.swf loads B.swf
after load is completed,A.swf needs to execute a function in B.swf called runCommands() for example.. here is the code for that (this is the code inside A.swf):

import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.*;
import flash.net.URLRequest;

...

var loaderRequest:URLRequest = new URLRequest("B.swf");
var movieLoader:Loader = new Loader();
movieLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
movieLoader.load(loaderRequest)....

function completeHandler(_event:Event)
{

	var _loaderInfo:LoaderInfo = _event.target as LoaderInfo;
	var loadedObject:Object = _loaderInfo.content;
	loadedObject.runCommands()
}

Custom Events

Posted in Actionscript 3.0, Code Snippets on December 2nd, 2007 by Omar Faleh – Be the first to comment

Creating custom events in AS3 is really easy, and very powerful. example:

lets say that there is a custom event that should be fired when a “Tween Lite” animation is done playing. we start by creating the custom event :

package  {
	import flash.events.*;

	public class FinishedEvent extends Event{

		private var trackingValue:String;
		public static var DO_SOMETHING= "do_something"

		public function FinishedEvent(type:String , someValue:String) {
 			super(type);
			trackingValue = someValue;

		}

		public function getDispatcherName()
 		{
 			return  trackingValue;
 		}
	}
}

read more »