Mar 22 2011

IE8 “hidden” feature (at least for me)

A quickie note to remind myself that some times looking in the least expected place can lead you to great discoveries.

I’m working on a website and we are currently at the testing phase, and amazingly enough, believe it or not, it happens to be some “subtle” differences in terms of CSS and JS sh!t between IE8 and IE7 (surprised?), so given that I have IE8 on my piece of machinery (although never use it) I went into all the trouble of downloading, installing, configuring Windows Virtual PC and an WinXP image with IE7 to proceed with my tests/fixes. A few hours later messing around with IE8 a little bit I discovered that its “Developer Tools” have a Browser View Mode!!! a super big WTF!!!

Shame on me for not giving a little more credit to IE8 and not googling or asking, before wasting a lot of time. Probably if I had the will of using it a bit more often I would had noticed that this option was there and saved some time and a lot of F! words… damn!


Jul 28 2010

Funny Spam

Yesterday I was going through a whole pile of spam comments I had on this humble blog and there were some really funny spam comments, I mean, c’mon spam is bad and all but man there are some that at least give you a chuckle. Just for the sake of remaining in posterity here is my top 10 in no particular order :D

  • I can’t belive that you created all the operate to share this! Awesome. With out Bloggers like you, we would never get so amazing information’s!

haha, thanks for the compliment dear spammer! Comments like this are the ones that keep me going

  • My Girl friend just broke up with me and I have uploaded every nude PIC I have of her to the net. Just go to [insert link here] Enjoy!

LOL!

  • Terrific work! This is the type of information that should be shared around the web. Shame on the search engines for not positioning this post higher!

I know! I’m awesomeness! Shame on those f%cking search engines that do not place my blog on top of every damn site on the internet!!!!

  • really appreciate YOU — thanks a lot!

Thanks! everybody should!!! hahaha

  • Why doesn’t Tarzan have a beard?

WTF?! Caught me…

  • Awesome post, you get a free iPad

Where can I claim it?

  • I like that you think. Thank you for share very

Was this posted by damn Yoda!?

  • HELP! I’m currently being held prisoner by the Russian mafia

Hmm too bad, I once was held prisoner by the Italian…

  • Bless ..RETARDED ! whats ur prob;em P.s Learn to spell before making a post like that

I’m hoping this one is really spam! However, on my defense English is not my native language

  • Blog liked, but a lot of unnecessary comments.

Like the one you posted damn spammer!

What would be life without SPAM!? ;)

Cheers!


Jul 26 2010

Making PDFs and SWFs talk to each other

Lately I’ve been thinking on what to blog and either haven’t found anything particular to talk about or just don’t have the will to do it. I have a bunch of unpublished posts on hold due to lack of time to finish the code samples and what not, so I decided to post a bit on what I have my hands on as of today.  Perhaps later I’ll try to just finish what’s left undone, perhaps not.

Anyway, these days I’ve been working on a crazy PDF – Flash integration and have been getting my hands dirty on Acrobat Javascript and figuring out what would be the best way to make a SWF file talk to a PDF document and vice verse — I have to accept though that I was not even aware that a PDF document could be scripted, WTF!, and further on do all sorts of crazy sh!t like accessing databases, consume web services, etc.

Given that the integration had to happen inside the web browser, using Adobe Air was not an option, so the first item on the TODO list was to be able to “render” a PDF document within a flash movie. I quoted render because the flash player does not support it so the approach (or hack if you will) consisted on placing the PDF object on top of the SWF giving the fake impression that the PDF is contained within the SWF application. Once I was able to place my PDF doc on top of my SWF, I had to figure out how to make both of them talk to each other. To my surprise, it turned out to be very simple.

To keep things simple, the sole requirement is to make our SWF movie to respond-or-act depending on the interaction that our user has on a PDF form. Let see what it takes to accomplish this task.

(Click here to see the example, tested in Firefox and Chrome, and the code, right-click view source enabled. Obviously it is required to have a Adobe Reader installed)

First, we’ll create our flash application. I’m using Flex 3 by the way, but you are completely free to do it in whatever version you like ;) Basically this “app” will have a button to get our PDF document, and the necessary visual elements to display whenever the user does something within the interactive PDF form. And a special container that will act as our PDF placeholder and also take care of all of its position and resizing actions.

The most important aspect of our Flex application is the canvas control, as it will serve as our PDF document placeholder. Obviously the PDF document won’t be loaded within the canvas control, because is not possible, but what it’ll do instead is determine the position and size of our PDF object that will get loaded and displayed within our HTML page. This PDF placeholder, which I repeat is a Canvas, has the following code that is used to load the PDF object (by the way is a total rip-off, plus a couple of other things I needed, of the IFrame component that can be found over here, thanks guys):

public function set source(source: String): void
        {
            if (source)
            {
                if (! ExternalInterface.available)
                {
                    throw new Error("ExternalInterface is not available in this container. Internet Explorer ActiveX, Firefox, Mozilla 1.7.5 and greater, or other browsers that support NPRuntime are required.");
                }
                __source = source;
                ExternalInterface.call("loadPDFObject", source);
                movePDFObject();
            }
        }

, basically what the code on the PDFContainer class does is invoke some javascript functions, through ExternalInterface, to load the PDF document and place it within a previously define HTML DIV. Also, has some other methods to handle resizing and positioning in case we want to re-size or reposition our PDF placeholder canvas within our flex application. For this particular example I won’t make use of any reisizing and reposition stuff, other than the initial.

Ok, I will move on to the PDF part now, and we’ll get back to our Flex app later. As I mentioned at the beginning of this post, you can do all kinds of things within a PDF document – you can add some Javascript to it in order for it to communicate with databases, web services, etc. For our example we are only going to add the necessary stuff to move around data between our PDF document and our Flex application. Acrobat Javascript is basically a framework built on top javascript, so you pretty much can do all the things you’d normally do with javascript, plus a lot of other cool stuff related to the PDF themselves.

It is worth mentioning that all javascript within a PDF happens within its contextt, it is isolated from the external container in case that the PDF is embedded within an HTML page. That being said some of the JS functions that you’d normally use on an HTML container don’t have the same effect within the PDF document, for example, to display an alert on a HTML page you would do:

alert("My Alert");

If you script that on your PDF document nothing will happen, no alert will pop out. In order to display an alert within the PDF document you’ll do instead

app.alert("My Alert");

The “app” object bascailly represents the Acrobat application and provides you access to a bunch functions and routines that are specific to Acrobat. On the other hand there is the “Document” object, which is the most important as it enables the communication between the PDF document itself, the one that is in the viewer, and the Javascript interpreter. Through that object, which usually you refer to it using “this”, you can use some handy methods and properties for accessing the PDF document. For example, let say you have a form that contains a text field named “MySuperCoolTxtField” (pretty lame name I know), you could get its value like:

this.getField("MySuperCollTxtField").value

, it sorts of reminds me to the getElementById method available in JS. Doesn’t it ? Anyway, this is not intended to be an Acrobat JS tutorial nor I do have the expertise to elaborate on one, so if you are interested on going furhter with Arobat JS here are some helpful guides.

Moving on to you initial purpose … where was I ?

Ok, now we are going to create a simple PDF form (here you can take a look at it) to make our little test. Well I actually have it ready, so I’ll just mention pretty much the gist. Here is the final PDF form. It is worth mentioning that you’ll need Acrobat Pro in order to be able to create interactive forms and add JS to your documents and stuff. Basically what the form will do is to trigger events whenever one of its controls got/loses focus, which will be hopefully catched by our HTML JS.

If you take a look at the form you’ll see that we have 4 controls, 3 textfields and one button. We have NameTxt, LocationTxt, and EmailTxt, and the SaveBtn. Each of the text controls have two actions attached. An action represents an function that you would like tog get executed as a response of an event triggered by the control. For example for this text controls Acrobat allows you to add actions for the events MouseUp, MouseDown, MouseExit, OnBlur, OnFocus, and MouseEnter. For this example I just added actions for the OnBlur and OnFocus events of all of the three text controls. See screenshot below.

Actions

On the OnFocus action we have this.sendOnFocusMessage("NameTxt");, and on the OnBlur action we have this.sendOnBlurMessage("NameTxt"); . If we click on Edit with a particular action selected an editor will pop out to display the current code associated to that action, if any. We have the same function for all of the other controls with the difference that we send its correspoing name as the function argument (“LocationTxt” and “EmailTxt” respectively).

If you recall, “this” refers to the Document it self, so we are calling a function that exists within the document scope. You can add as many code to your document as you wish, if you happen to have your Acrobat ready you’ll need to go to Main Menu -> Advanced -> Document Processing -> Document Javascripts, which will open a window that will list all of the code/functions associated with your Document.

This is the code that we have on those functions,

function sendOnBlurMessage(fieldName)
{
    if(!this.hostContainer)
        app.alert("No hostContainer object found");
    else
    {
        try
        {
            var fieldValue = this.getField(fieldName).value;
            if( fieldValue.length == 0 ) fieldValue = " "; 
 
            this.hostContainer.postMessage(["OnBlur", fieldName, fieldValue]);
        }
        catch(e)
        {
            //Display some error
        }
    }
}
 
function sendOnFocusMessage(fieldName)
{
    if(!this.hostContainer)
        app.alert("No hostContainer object found");
    else
    {
        try
        {
            this.hostContainer.postMessage(["OnFocus", fieldName]);
        }
        catch(e)
        {
            //Display some error, this alert will be displayed within the PDF document
        }
    }
}

Ok, before I go any further let me point out a couple of things … If you look at the above code, they pretty much looks normal, however there is a dude called hostContainer. WTF? Ok, hostContainer is an object that your document has access to in order to communicate with its host container, DUH!!!! that sounded stupid, for example an HTML page; hostContainer will be null if you open your document on your PDF viewer application, otherwise, when opened inside an HTML, this object will hold a reference to it. Look at hostContainer as something along the lines of ExternalInterface. The hostContainer basically uses the postMessage function to send messages, and also can have event handlers registered in order to respond to specific actions. Notice that the argument that postMessage expects, which is mandatory, is an array of strings.

As to what the functions do, well, basically whenever a control looses focus they send a message to tell the container was it, and when they get focus also pass the data entered by the user. I guess we have everything we need on our PDF document, so let’s move on to our actual HTML JS. That was simple!

In our HTML javascript we need to do a couple of things – first register message handlers to our PDF object, and create our actual handlers. So, we ended up with something like the following:

function registerPDFMessageHandlers()
{
	try
	{
		var PDFObject = document.getElementById("PDFObjectID");
		PDFObject.messageHandler = {
				onMessage:onMessageHandler,
				onError:onErrorHandler
		};
	}
	catch(e)
	{
		alert("Error: " + e);
	}
}
 
function onMessageHandler(params)
{
	// params - Array
	// 0: Action triggered
	// 1: FieldName
	// 2: FieldValue
	var action = params[0];
	var fieldName = params[1];
	var fieldValue = params[2];
 
	var swf = getMovie("PDFSample");
 
	if( swf )
	{
		switch( action )
		{
			case Action.onFocus:
				swf.sendOnFocus(fieldName);
			break;
 
			case Action.onBlur:
				swf.sendOnBlur(fieldName, trim(fieldValue));
			break;
		}
	}
	else
	{
		alert( "SWF Object not found" );
	}
}
 
function onErrorHandler(error, message)
{
	alert("Error: " + error);
}

The registerPDFMessageHandlers register the proper message handlers on our PDF object, which means that whenever the postMessage method gets invoked (insider our PDF object) the event handlers will get called. I forgot to mention earlier, but our hostContainer acts on 3 differente evets, onMessage, invoked at a successfully postMessage action, onError and onDisclose. You can take a look at the documentation for further information. registerPDFMessageHandlers is called right after our PDF object is loaded, remeber that the loadPDFObject function is called by our Flex application through ExternalInterface.

The function defined as our onMessage event handler, onMessageHandler, is the one that handles the message data that is passed from our PDF document. What it does is very simple stupid, it basically see whether is recieving an OnBlur or OnFocus action and calls the appropiate SWF functions, previously discussed, that have been exposed by ExternalInterface. It is pretty much self explanatory all of it.

Now, going back to our Flex application…. man! this has been a long post! if you are still reading all of this crap I applaud you, seriously!!! you are the man!!

The last part that I want to go over briefly is the code that handles the javascript calls made after our HTML container recieves PDF news, thus make in it look as if our Flex application is instantly and directly communicating with our PDF document. We have two methods exposed by ExternalInteface, one to handle OnFocus message, and the other one to handle OnBlur messages. We could have on sole method to handle all of the messaging however just for the sake of this example I decided two have one for each of the events happening within our PDF form.

private function _onFocusSendCommand(fieldName:Object):void
{
	if( this.alertWrapper != null )
	{
		this.floatingAlertSpanshot = new UIComponent();
 
		snapshotData = new BitmapData(this.floatingAlertSprite.width, this.floatingAlertSprite.height, true);
		snapshotData.draw(this.floatingAlertSprite, new Matrix());
		snapshotBmp = new Bitmap(snapshotData);
 
		this.floatingAlertSpanshot.x = this.alertWrapper.x;
		this.floatingAlertSpanshot.y = this.alertWrapper.y;
		this.floatingAlertSpanshot.addChild(snapshotBmp);
 
		this.addChild(this.floatingAlertSpanshot);
		this.alertWrapper.alpha = 0;
		this.alertWrapper.removeChild(this.floatingAlertSprite);
		this.floatingAlertSprite = null;
 
		var t:GTween = new GTween(this.floatingAlertSpanshot, 0.2, {alpha:0});
	}
	else
	{
		this.alertWrapper = new UIComponent();
		this.alertWrapper.alpha = 0;
		this.addChild(this.alertWrapper);
	}
 
	var alertMsg:String;
	var alertPos:Point = new Point();
	alertPos.x = this.pdfContainer.x + this.pdfContainer.width + 20;
 
	switch( fieldName )
	{
		case Constants.PDF_NAME_FIELD:
			alertMsg = Constants.ENTER_NAME_MESAGE;
			alertPos.y = this.pdfContainer.y + 190;
		break;
 
		case Constants.PDF_LOCATION_FIELD:
			alertMsg = Constants.ENTER_LOCATION_MESSAGE;
			alertPos.y = this.pdfContainer.y + 230;
		break;
 
		case Constants.PDF_EMAIL_FIELD:
			alertMsg = Constants.ENTER_EMAIL_MESSAGE;
			alertPos.y = this.pdfContainer.y + 270;
		break;
	}
 
	this.floatingAlertSprite = new FloatingAlert(alertMsg, "Important Tip");
 
	alertWrapper.addChild(this.floatingAlertSprite);
	alertWrapper.x = alertPos.x;
	alertWrapper.y = alertPos.y;
 
	var gt:GTween = new GTween(alertWrapper, 0.2, {alpha:1});
}
 
private function _onBlurSendCommand(fieldName:Object, fieldValue:Object):void
{
	var fieldValueStr:String = fieldValue as String;
	this[fieldName] = (fieldValueStr.length != 0 && fieldValueStr != "") ? fieldValueStr : null;
	var infoStr:String = "";
 
	infoStr += (this.NameTxt != null) ? "Your name is '" + this.NameTxt + "'. " : "";
	infoStr += ( this.LocationTxt != null ) ? "You are located at '" + this.LocationTxt + "'. " : "";
	infoStr += ( this.EmailTxt != null ) ? "Ohh, and BTW, this email address '" + this.EmailTxt + "' will get lots of spam from me." : "";
 
	if( infoStr == "" ) infoStr = "Please fill out the form on the left";
 
	this.dataBoard.message = infoStr;
}
 
private function _loadPDF(e:Event):void
{
	this.loadBtn.enabled = false;
	this.pdfContainer.source = "form.pdf";
 
	var tw:GTween = new GTween(this.dataBoardWrapper, 0.25, {x:this.pdfContainer.x + this.pdfContainer.width + 20});
}

So, what the code above does ? Well nothing cool in particular, the _onFocusSendCommand method is called whenever a control in our PDF gets focus, and what the Flex application does is to display an alert message to let the user know the type of data that is expecting for that component. On the other hand, the _onBlurSendCommand gets executed whenever a control in our PDF document has lost its focus and perhaps has some info in it. So whenever that method is executed a cool alert is displayed to tell the user which information has been entered so far in the PDF form. Lastly, the _loadPDF method, well as it name implies LOADS THE DAMN PDF!!! :) it just sets the PDFContainer’s source property to whatever is the PDF URL and invokes the javascript function that loads and displays our PDF object within our HTML page.

To make our PDF document recieve messages from our HTML container is just a matter of adding the proper message handlers, as we did in HTML JS, inside our PDF document javascript code, and call PDFObject.postMessage(whatever) within our javascript. If we set up the proper onMessage handler in our PDF it will be invoked whenever a postMessage is executed in our HTML container. And to add our SWF into the equation is just a matter of adding the proper ExternalInterface callbacks to do. Probably a topic worth a following post, I’ll just need to clean up somethings up and I’ll post it some day.

I hope, if you made it this far, that you liked what you read and found it useful as I did :) There are a lot of cool stuff that could be accomplish way beyond of what was explained here. This is not intended to be a thorough guide on how to interact with your PDFs but to serve as a starting point and give you an overall idea of how you can start to do so. There are a lot of other features that can be pulled off with a Acrobat javascript, again, if you are on to this here you can find interesting documentation.

Thanks for stopping by, your comments, and cheers, now is time for me to grab a beer!


Feb 7 2010

Using the Zend Dispatcher to simulate URL rewriting

I haven’t post anything in quite a while, mostly due to the large amount of work I’ve been juggleing lately and because I did not have the energy to write even the stupidest little thing.

Anyway, I decided to come out from my blogging hiatus and share something that I stumble upon during the course of one of the projects I’ve been working this past weeks.

A few days ago while working on a project in which my team and I are using the Zend Framework (which I hate and not-love-but-like at the same time), getting close to our release date I noticed that we ended up with having some funky URLs for accessing some parts of the application, I mean there’s nothing bad of having an URL  in the form of /module/controller/action/param/value, which is OK at some point, however somehow some of the most relevant modules of the application ended up with having the logic on the module’s index controller, and on top of that on the index action of the controller, so some of the web pages that are going to receive the most of the traffic ended up having an access URL like this: http://mysupercoolsite.com/item/index/index/90 – a big WTF from my side, index/index ??! . Ok, somethings were not well planned at the outset nor given the necessary attention- my bad – although this “issue” does not affect anything whatsoever, I just think it doesn’t look good!!! and perhaps it says that you did not do a good job designing the application in the first place (probably I’m just overreacting. I’m pretty sure though, that the client would’ve told us – “Hey! I want beautiful and meaningful URLs! what the fuck are those index/index for? Get them out of there ASAP!”- We needed some re-factoring and changes, but being so close to the “D” day that was not an option. Doing some tricks with mod_rewrite neither it was.

Enter the Dispatcher.

Ok, before I move on, let me tell you that I don’t consider myself a Zend Framework expert, I have used it on some projects but never got too deep into it, so perhaps there’s a better and simpler option that I might have overlooked.

So, I had to figure out how to catch the request before dispatching it and be able to modify some of its values on the fly, in order to translate a beautiful URL to the bizarre one we had in our application and still be transparent to the end user. I found some articles that discussed this stuff at some extent, but with no actual solution – I did not find in the ZF docs either a straight-forward example or explanation on how to do this when you use modules.

I decided to stop fucking around and get to the point – I knew that the Dispatcher was the solution, because its the one that takes the request, gets the module/controller name and process it (instantiates whatever controller and calls its action). By default you’re application is tied to the Zend_Controller_Dispatcher_Standard, so what I thought is “well, if I can get the module, controller, and action names, and the param/values coming in the request before the dispatch process, perhaps just adding a method that does some sort of pseudo-rewriting shit will do the trick”.

I started by extending Zend_Controller_Dispatcher_Standard instead of Zend_Controller_Dispatcher_Abstract, why? no real reason, why not? The idea was to extend it by adding a method that lets you add, what I call, translations (or “pseudo” rewrite rules), and run those translations against a given request that the dispatcher gets, and if it does match some rules well modify it and until then dispatch it.

First step,

class MyCustom_Dispatcher extends Zend_Controller_Dispatcher_Standard{
 
}

Ok, we are doing great so far, then I set a private variable to hold all translations (or rules if you will) added to the dispatcher for consideration. And then my method to add translations to it

public function addTranslation($params)
{
if ( !is_array($params) )
{
throw new Exception('Invalid dispatcher translation');
return;
}
 
if ( null === $params['target'] || ( null === $params['module'] && null === $params['controller']) )
{
throw new Exception('Invalid dispatcher translation');
return;
}
 
if ( null === $this->_translations ) $this->_translations = array();
 
array_push($this->_translations, $params);
}

Ok, I have my method to add translations, Yay! now what? Well, next the method to run those translations against an incoming request (some code omitted for the sake of brevity), here is an example of this method.

private function runTranslations(Zend_Controller_Request_Abstract &$request, $m, $c, $a)
{
 
	if ( $this->_translations !== null )
	{
		foreach( $this->_translations as $trans )
		{
			if ( $trans['module'] !== null )
			{
				if ( $trans['controller'] !== null && $trans['controller'] == $c && $trans['module'] == $m)
				{
					if ( $trans['target']['module'] !== null ) $request->setModuleName($trans['target']['module']);
					if ( $trans['target']['controller'] !== null ) $request->setControllerName($trans['target']['controller']);
					if ( $trans['target']['action'] !== null ) $request->setActionName($trans['target']['action']);
 
					if ( $trans['params'] !== null )
					{
						foreach($trans['params'] as $key=>$value)
						{
							$request->setParam($key, $request->getParam($value));
						}
					}
 
					return;
				}
			}
		}
	}
	return;
}

Ok, now I have my method that will run the translation rule against an incoming request, and if necessary make some adjustments to it. But before we move on, where does this “translations” are evaluated ? Well, we have to override the dispatch method to include some custom actions.

public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)
{
	$moduleName = $request->getModuleName();
	$controllerName = $request->getControllerName();
	$actionName = $request->getActionName();
 
	$this->runTranslations($request, $moduleName, $controllerName, $actionName);
 
	parent::dispatch($request, $response);
}

Basically, before dispatching our actions we evaluate our request against the predefined rules our dispatcher has – in simpler words we are just taking a request and modifying/overwritting its controller, module, action, params that it target to. Ok, I think that’s it for our custom dispatcher. Now, where on earth do I tell my application to dump the stupid standard dispatcher and use my cool one ? That’s in our application’s bootstrap class. If you are already overriding the constructor of your dispatcher fine, if not you’ll need to in order to change the front controller dispatcher, and at the same time define your translations or rewriting rules.

public function __construct($application)
{
	parent::__construct($application);
 
	$customDispatcher = new MyCustom_Dispatcher();
 
	$params = array(
		'module' => 'default',
		'controller' => 'item',
		'target' => array('module'=> 'items', 'controller' => 'index', 'action' => 'index'),
		'params' => array('itemid' => 'action')
	);
 
	$customDispatcher->addTranslation($params);
 
	$front = Zend_Controller_Front::getInstance();
	$front->setDispatcher($customDispatcher);
}

Some explanation of the params set in the code block above. The way translation works, is that you have to tell in which way the request is coming, and what it translates to, so the application knows what to do with it. By the code above, I’m saying to the dispatcher, please add a rule that whenever a request comes to “default” module and the “item” controller, you really want to target the “index” action at the “index” controller of the “items” module. There’s no “item” controller within the “default” module. Also, since our “real” module-controller-action expects a parameter called “itemid”, you notify the dispatcher that the request will contain this value as its action. For example,

http://aaa.com/item/10 = http://aaa.com/items/index/index/itemid/10

Since the framework sees item/10 as controller “item”, action “10″, that’s why you have to tell the dispatcher that you parameter value is represented as the “action”.

There you have, now we can tell our client that he’ll have beautiful URLs. The end user never gets to see the real identity of our bizarre URL. This is a very particular use case, that it was derived from improper design in the first place, that worked for us, it does not mean that is the best approach or that it will work for everybody, its just a sort of hack/experiment that I just wanted to share because I’m a cool guy.

Conclusion: The Zend Dispatcher is the entry point where you can do whatever you want to do with any incoming request before send it to execution. Cheers! :D

Mario.


Nov 5 2009

Recording Audio and Video with Red5

What’s up people, these last days (and weeks) I’ve been working with Red5, and learning along the way because I had never used it beyond ‘Hello world’ type experiments, and it’s a shame I did not started to play with it earlier, because is so damn cool. Thanks a lot Red5 Team!

Anyway, I’ve seen some folks here and there asking on how to record a live webcam/mic stream using Red5, and some long ago when I searched for that I did not find a straightforward answer (AKA gimme the code :D ), so for those fellas that are badass lazy as I am, and that their hopes are to find all the help (AKA gimme the code) on Google, here’s a little example that should get your ass going (if you were too lazy to try this suggestion which you should do if you want to really learn )

Ok, I’ll assume you have everything in order so we can go ahead and get our cameras and microphones:

1
2
3
var myCam:Camera = Camera.getCamera();
var myMic:Microphone = Microphone.getMicrophone();
myMic.setLoopback(true);

, then create our net stream and attach the live video/audio to it. Here you could add some validations to verify that you are getting your camera and mic feed as expected (e.g. not null), I will omit it however because my fingers are getting tired.

1
2
3
4
5
6
7
// Create our net stream, by the way for the sake of brevity let's assume you have all your connection sh!t together
var stream:NetStream = new NetStream(myNetConnection);
// add a listener so we know when our stuff is ready for recording
stream.addEventListener(NetStatusEvent.NET_STATUS, onRecStreamStatus);
stream.attachCamera(myCam );
stream.attachAudio(myMic);
stream.publish('myStream', 'live');

Now the stream status event handler, as you’ll see, when your stream has started to “stream” ha! :D then you are ready to record,

1
2
3
4
5
6
7
private function onRecStreamStatus(e:NetStatusEvent):void
{
        if ( e.info.code == "NetStream.Publish.Start" )
        {
             myConnection.call('startRecordingStream', null);
        }
}

This line myConnection.call('startRecordingStream', null); invokes the method ‘startRecordingStream’ on our Red5 service which is responsible for handling our streams and recording/saving them accordingly… and it could look something like this…is Java by the way :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//Java
 
public void startRecordingStream(IConnection conn)
{
	String clientId = conn.getClient().getId();
	IScope scope = conn.getScope();
 
	String streamName = clientId + "_" + String.valueOf(System.currentTimeMillis());
 
	try
	{
		ClientBroadcastStream stream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), "myStream" );
		stream.saveAs(streamName, false);
		// You could, if you wish of course, notify the user that the recording has actually started
		// You just have to add the recordingStarted public function on your flash application
		ServiceUtils.invokeOnConnection(conn, "recordingStarted", new Object[]{clientId});
	}
	catch(Exception e)
	{
		// You could notify the user that the recording failed for some stupid reason
		// sometimes things does not go well :)
		// You just have to add the recordingStarted public function on your flash application
		ServiceUtils.invokeOnConnection(conn, "recordingFailed", new Object[]{clientId});
	}
}

And if you want to have a button to stop recording on your flash app., just throw a button and when is clicked invokes a method on your Red5 service for stopping the recording process. Something like this:

1
2
3
//AS3
//assuming this is on a click handler or whatever
myConnection.call('stopRecordingStream', null);
1
2
3
4
5
6
7
8
//Java
public void stopRecordingStream(IConnection conn)
{
	String clientId = conn.getClient().getId();
	ClientBroadcastStream stream = (ClientBroadcastStream) this.getBroadcastStream(conn.getScope(), "myStream");
	stream.stopRecording();
	ServiceUtils.invokeOnConnection(conn, "recordingStopped", new Object[]{clientId});
}

As Dominick pointed out on his blog post, you should get your recorded stream under red5/webapps/YouBadAssApplication/streams.

There are lot of things that have to be done in order to have video/voice application running smoothly, however I hope this helps you in realizing how simple Red5 makes things for us. Let me know if I missed something, if there are other workarounds you have found, or whatever you might wanna say :P

Cheers!