I know top X lists are almost passe at this point, but that’s not going to stop me from giving a shout-out to some of the applications that daily make my life easier:
MarcoPolo is a neat little application that is capable of executing actions based on a set of rules. That is, if something on the system changes (such as an IP address, power status, USB or even the light level), it can execute a series of commands (such as mounting network drives, setting the screensaver, changing the default printer, etc). It can even run arbitrary shell scripts!
Why this is useful to me: At dealnews, we (the dev team) all use MacBook Pros for our development work and constantly alternate between home and office. Whenever I arrive at work in the morning, the minute I plug my MacBook into the network, MarcoPolo senses that the IP address has changed from my home and changes the default printer, mounts some network shares, adjusts the screensaver settings, and runs a few other custom shell scripts I have to set up my environment. All without having to do a single thing. When I get home, it executes still more commands to change to a remote development environment. Completely effortless.
XMeeting is a SIP softphone (and videoconferencing application, but I’ve never used the video features) that allows you to connect to a SIP server and place calls using your laptop.
Why this is useful to me: At dealnews, we run Asterisk as our phone system (see my earlier posts on Asterisk). One of the many nice features of Asterisk is its standards compatibility - that is, you can use anything that can talk SIP with Asterisk. Since CounterPath has apparently decided that Leopard compatibility for their free softphone (X-Lite) is not a priority, XMeeting comes to the rescue. As a bonus, it actually acts like a Mac application and doesn’t do the stupid things that X-Lite did (like messing with the system volume).
Quicksilver is the single application I cannot live without. On a Mac without it I am almost lost. More than just a launcher, it is a tool to help you work more efficiently. You can press Ctrl+Space and type what you want and Quicksilver will launch what you need. That’s a horrible description for how cool this app is.
**Why this is useful to me: **Without Quicksilver, I am lost. It makes it literally so fast to move around your Mac without taking you hands off the keyboard. A quick hit of Ctrl+Space gives you the ability to launch programs, open files, navigate contacts and send emails, and make quick notes among many othe things that this program can do. It is essential to my everyday life as a Mac user.
DejaMenu is a neat little program that will display the current application’s main menu as a popup menu where the mouse is whenever a key combination is pressed.
**Why this is useful to me: **I use my MacBook Pro with a second monitor when I’m at the office. One of the things that has infuriated me for awhile as a Mac user with multiple monitors is the inability to have the top menu bar either on each monitor respresenting the application on that monitor, or the ability to have it move with whatever monitor the mouse is on. It’s irritating to have to go back to the main monitor when the application is running on a different one. DejaMenu allows you to pop the application menu wherever your mouse is, which makes things a little easier. Additionally, I mapped the key combination to a button on my Logitech MX-1000 to make things even easier.
While in general I only use this blog for discussing programming, computers and my life as an engineer in dot-com, it’s only natural that, every now and then, a personal post will slip in. And this is as good a reason as any.
On December 26th, I asked my girlfriend of almost three years to marry me.
Net got me to thinking. In the article, they talk about vaguely defined “benchmarks” showing that Windows XP with the beta of Service Pack 3 outperformed Windows Vista with Service Pack 1.
I can only say one thing: duh. Quite frankly, I would have been more surprised if Vista had outperformed XP.
This really is an apples and oranges comparison because Vista is a newer and more complex operating system. And I’m not exactly a Microsoft fanboy, either - I’m typing this on a Mac, using a Java journal client. Of course it is going to run slower on the same equipment than an operating system that was released six years ago. I’m sure Windows 98SE will beat the pants off of XP on the same equipment, too. Leopard, released a few months ago, won’t even run on hardware circa when OS X first came out and will almost certainly run slower on machines that were top of the line when Tiger was released. Hey, while we’re at it, we could compare Doom to UT3 to see which runs faster!
If they wanted to do a more fair comparison, they would have compared them on different machines - top of the line machines when their respective operating systems were released, using adjusted benchmarks. Being that machines are much faster now than they were in 2001, I wager that the difference between them would be a lot less.
There’s been a good bit of debate about Leopard’s new translucent menu bar. For me, it doesn’t cause many issues. However, some of my coworkers despise it and, to be fair, I can see the arguments that many of the people who dislike it have: it doesn’t add anything to the OS and actually makes it more difficult to read the text.
Well, here’s a litle tweak that will set the menu bar back to a white background. In the terminal, you can use the following command to change the default appearance of the bar:
Restart your Mac, and voila! White menu bar! Changed your mind? Set it back:
Restart your Mac and your menu bar is back to being translucent.
Just to let everyone know, we’re trying to get a little meetup.com group going for those developers interested in PHP and MySQL in the Huntsville and Northern Alabama regions. I’ll be attending, and I know Brian will be giving mini-talks for the first few meetings. You can visit Brian Moon’s blog for more information.
So it’s been awhile since I’ve written. In that time, my girlfriend has moved in
here with me in Huntsville and, as always, dealnews has
kept me very busy. However, it has not prevented me from occasionally trying my
hand at something new.
A week or so ago I decided that I was going to learn
Python. However, as part of my nature, I simply can’t
“learn” a language without having a purpose. For instance, I have never been
able to simply read a book on programming - I needed a reason. So I’ve been
giving myself reasons to do little tasks here and there in Python. One of them
came to me just today.
I have recently moved all of my development at dealnews from the PC to a
Macbook. I’ve never been an OS-bigot - always use the right tool for the job,
and the Mac - which in many ways is just Unix with pretty make-up - is the
perfect platform. However, I still use many of the peripherals I purchased for
my PC, including my Microsoft Natural Egronomic
Keyboard
that I adore. At home, I still use a PC (until I can afford a new Mac Pro),
albeit with the same keyboard.
One of the things I really love about the keyboard is that it has various
buttons that are just … buttons. They can be mapped to do anything you want
them to. There are five multi-function buttons at the top that can be mapped to
run programs. So I’m sitting here thinking, “self” (because that is what I call
myself), “why not write a little program to run on the click of that button and
go to the next or previous track in iTunes, so that changing the music doesn’t
involve any more effort out of my busy programming day than hitting an
additional keystroke”. But, it must work both at home and at work, meaning that
it must run in Windows and Mac.
Enter Python
I knew from previous experimenting in .NET that iTunes exposes a COM object on
Windows. With that in mind, I quickly found this
page that
described almost exactly what I wanted to do in Windows. So that left the
Macintosh. After an hour or so of digging on Apple’s website, I found this
page
that described how to access the COM on the Mac - and wouldn’t you know, the
functions are slightly different.
After that, it was pretty easy:
So yeah. It’s kind of code monkeyed together, but not bad for someone who’s only
been doing Python for a week in the evenings. Passing either a -n or -p to the
script causes it to command iTunes to go forward or back. Of note, to work on
Windows, it does need the COM components from the Python for Windows
extensions.
I’m gonna expand this script some more in the future, but for now it does what I
need.
Ladies and Gentleman! Welcome to the PHP Templating Celebrity Deathmatch!
I actually do like the idea behind templating. I know there are varying
arguments about whether or not templating is appropriate for PHP, though those
are not the focus of this entry.
The big idea behind templating is separation of
concerns, that is,
breaking a program into parts that are easily manageable and don’t overlap in
functionality. In an ideal world, templating would provide the added advantage
of allowing a programmer to be a programmer and not a web designer - and
allowing a web designer to be a web designer and not a programmer - by keeping
the logic underlying the presentation layer to a minimum. However, I have never
found this to be true in any project I’ve worked on in my professional career.
One of the big benefits, as far as I see, is that it makes code much easier to
read. This may not be true for everyone, but I would much rather be confronted
with smooth, separated templated code rather than a jumbled PHP mess. It’s
easier to read and far, far easier to adapt and change.
While I was attending OSCON a few
weeks ago, I heard mention of a new PHP templating engine that was written in C
and native compiled into a PHP extension. This would make it much, much faster
than anything written in PHP itself - in theory. This project, called Blitz, was
making some pretty grand claims on their website, so I wanted to put them to the
test - at least a small timing test.
In this test, I am going to be comparing Smarty (the
most widely used PHP templating engine and an official PHP project),
Blitz (a new templating engine
currently under very active development that is native compiled as a PHP
extension), and standard PHP includes.
For the purposes of this test, I wrote a quick timing function that uses
microtime() to record how much time has elapsed between each call of
mark_time(). The code is available in the accompanying project.
A Note About The Tests
These are not meant to be exhastive tests by any means. These tests are just
designed to give you 5,000 foot overview of the current state of PHP templating.
They only evaluate page generation time and not other metrics such as CPU load,
IO load, or memory usage. Furthermore, I selected three scenarios that I have
commonly used in templating; there may be some scenarios that I haven’t tested
where one method may outperform others. And, as with any benchmarking, they are
dependent on my system - YMMV.
Test 1: Instantiation
This is a simple test that determines how much time it takes to power up the
templating engine and get it loaded into memory for PHP to use. For the purposes
of this test, we will just be comparing Smarty and Blitz, as there is no need
for instantiation with a standard PHP include. We’ll start with Smarty first.
smarty_instantiation.php
Smarty’s instantiation time was 0.0058109760284424 or 0.005 seconds in human
terms.
blitz_instantiation.php:
Blitz’s instantiation time was 3.0994415283203E-5, or 0.00003 seconds in human
terms.
It may not seem like a big difference, but this is one area where having Blitz
as a PHP extension makes a huge difference over Smarty being written in PHP
and included. Because PHP must traverse the include_path to find Smarty.class
before including it, it causes PHP to be slowed down before it can even
instantate the Smarty object. To be fair, I decided to run a second test again
with the include out of the timing mark.
smarty_instantiation2.php
Even without having to search the include_path for Smarty, it still took
6.5088272094727E-5, or 0.00007 seconds to instantate the Smarty object - almost
twice as long as it took to instantate the Blitz object. However, this is not a
realistic scenario in any way - there is no way that PHP can have saved any time
and still have access to the Smarty object!
Winner: Blitz
Test 2: Simple Template Rendering
In this test, we will be comparing simple template rendering in Blitz, Smarty
and PHP includes. In this test we will create a simple HTML template with two
variables that need to be replaced, then render and display them to the user
using each engine or, in the case of PHP, straight PHP. So, let’s get started!
We’ll run Blitz first, since it won the previous test.
blitz_simple_render.php
Blitz took an impressive 0.00011801719665527, or 0.0001 to render a simple HTML
document with two replaces. Smarty’s next:
smarty_simple_render.php
Because Smarty is a compiling engine (it compiles the templates to PHP and
caches them), the first run is always the most costly - in this case, an
atrocious 0.058284997940063 or 0.06. Even on subsequent runs, 0.0065691471099854
or 0.007, again much slower than Blitz. Finally, standard PHP includes:
php_simple_render.php
Surprisingly, standard PHP includes took 0.00030016899108887, or 0.0003 seconds,
much faster than Smarty, but three times as slow as Blitz. Once again, this
likely has to do with PHP having to traverse the include_path before finding the
appropriate file. If you specify the _absolute path on the filesystem _to the
file above, the time took becomes 0.00010490417480469, or 0.0001, roughly equal
to Blitz on any given run. However, because Blitz is able to parse the template
with a minimum of fuss whereas I have to explicitly specify the filesystem path
for PHP to get equal performance, this round also goes to Blitz.
Winner: Blitz
Test 3: Complex Templating
In this case, we are going to be doing complex templating. This test includes
three template-based includes, one foreach loop over an array, and a large array
of generated data. Just for the curious, the generation of the data is not going
to be counted towards the timing. In this case, we have generated a 10,000 item
array and are going to have each engine iterate over it.
blitz_complex_render.php
Blitz ran the test in 0.072134971618652, or 0.07 seconds, not too shabby
considering it had to iterate over a 10,000 item multidimensional array.
smarty_complex_render.php
Again, because Smarty is a compiling engine, the first run is always the most
expensive - in this case, a whopping 0.31642484664917, or 0.3 seconds.
Subsequent runs fell in the range of 0.099456838607788, or 0.1 seconds, three
times as fast as the first run but still slower than Blitz. Finally, standard
PHP includes:
php_complex_render.php
In this test, raw PHP includes came in at 0.055343866348267, or 0.06, the
fastest of all and yet just a small bit faster than Blitz.
Winner: PHP
Conclusion
Blitz won two of the three tests and came in a close second in the last. Of
course, one could argue that PHP “won” the first test since there was no need to
be tested on instantiation.
Considering the short amount of time Blitz has been under active development,
its sheer speed is rather amazing. From a templating standpoint, Blitz is the
fastest unless you are willing to jump through lots of little hoops to make
standard PHP includes work for you, and even at that point, the performance as
far as total page generation time goes is roughly equal, though native PHP may
have a slight advantage.
However, unfortunately, the very strength of Blitz (it being written in C and
compiled into a PHP extension) is its greatest weakness. Because so many
websites are served off shared hosts without the ability of users to use
external extensions, most of the community will never have the ability to take
advantage of Blitz. Only those with access to the machine, or more specifically
the php.ini file, will have the ability to use Blitz unless it were to be merged
into the PHP tree. Even in the best case, considering how many shared hosts are
still running PHP4, I wouldn’t expect to see anything like this soon, if ever.
Perversely, the very weakness of Smarty (that it is written in PHP and included)
is its strength, for the reasons above. Smarty is the slowest templating engine
tested, however because it is just PHP, it can be included and run like any
other PHP script - meaning all the people on shared hosting can make use of it
with a minimum of fuss. And in Smarty’s defense, there are many features (such
as template variable modifiers) Smarty has that are simply not available in
Blitz. These features come with the tradeoff of a massive loss in speed. It was
honestly surprising to me how slow it was.
Ultimately, it is the decision of the programmer as to what is the right method
to use. If you want the advantages of templating as far as seperation of
concerns and ease of maintenance and you have the ability, Blitz is probably a
good choice for you. If you still want the ease of maintenance and separation of
concerns provided by templating and are willing to make the tradeoff for a
massive loss of speed, Smarty is a possibility also. If sheer pure speed is your
primary concern and you’re not willing to make any kind of tradeoffs, going with
raw PHP is probably your best option provided you fine tune it a bit to get the
absolute best performance out of it.
I figure that if I’m going to start using this blog to post the wanderings and
wonderings of a mid-level engineer at a dot-com company (I work at
dealnews to be specific, and I guess I should include the
standard disclosure that my employer does not endose or support anything that I
say/do here), perhaps I should give some substance to my first post. So, I
figure I would write a post on something I have plenty of experience with:
PHP.
But what to write about? Surely, there must be ten million PHP tutorials on the
‘net and I don’t need to add to the noise already out there as to what
are/aren’t the best practices using PHP, so I thought about using PHP in some
lesser known areas. And here is one lesser known, but very cool area: you can
use PHP to route phone calls!
At a previous employer, I worked with Asterisk as a
software development consultant. My primary role was to build web interfaces to
Asterisk (and other telecom hardware) backends, though while working as a
consultant I learned quite a bit about extending Asterisk to do crazy cool
things.
“It’s Just Software!”
Asterisk is an open-source software PBX that
was created by Mark Spencer (an Auburn grad and now
CEO at digium). It is quickly becoming a
challenger in the PBX market (fact: we use it at dealnews), and an entire
industry has sprung up around Asterisk and open-source IP telephony.
For the purposes of this tutorial, I’m going to assume that you already have
Asterisk installed and configured to your liking, and are now wishing to extend
it beyond what it is capable of doing with the builtin dialplan applications. If
this is not a good assumption in your case, may I highly suggest the Asterisk
Tutorial
at voip-info.org, or even better, the O’Reilly Asterisk
book, which is a little dated but
still quite relevant to most beginner-level stuff.
Meet AGI, CGI’s hard-working cousin:
AGI, or the Asterisk Gateway Interface, is the key to extending Asterisk beyond
what it is capable of doing on its own. AGI gives Asterisk the ability to run
and interact with scripts and programs outside of Asterisk. AGIs can be written
in any language that can be executed on a Linux system (and there have been AGIs
written in PHP, Python, Perl, C, Bash and just about every other language out
there). Since PHP is my language of choice, that is what I’m going to
concentrate on in this tutorial.
Asterisk AGIs are actually incredibly simple creatures. When run from within the
Asterisk dialplan, they simply send commands to Asterisk using standard output
and read the results on standard input. Its what happens between those that is
really, really cool.
Enough Talk! Code or GTFO!
So, let’s get started!
First, you need to set up your script environment. I recommend doing this in an
include-able file so that you can reuse it in future AGIs. There are a few
commands you need to know about:
Okay, that’s not too bad!
Now, we’re going to do a little more advanced stuff. Every time an AGI script executes, Asterisk passes a number (about 20) values to the script. These AGI headers take the form of “key: value”, one per line separated with a line feed (\n), concluding with a blank line. Before we can do this, we need to write a few functions to read from AGI input, write to Asterisk, Execute commands, and write to the Asterisk CLI. These are the functions I use:
So what are we doing here? Well, the first line, we strip out the line feed in each chunk we get from stdin. Then, we check to see if $debug is set and, if so, echo what we read to standard error. Finally, we return the line we just read. Pretty simple, right? Well, this little funtion will save you lots of time. Next, we need a way to write data:
This function is even more simple: it just writes out to standard error if $debug is on, and outputs whatever was sent to it with an additional new line. This next function, however, is more complex.
Woah, complex! Well, not really. execute() is the swiss army knife of AGI programming: it allows you to do interactive stuff inside this AGI script.
First, as you can see, it calls the write() function we just wrote, writing an AGI command to Asterisk. Then it looks for a response on standard in. A response from Asterisk takes the form of “result=<result> <data>”. So, we use preg_match to get this out for us and put it into something usable. We do the debug output again, then return the array or 0 or -1 in the event of failures.
Just two more functions to go:
As you can see, these two functions are very simple. One gives verbose output to the Asterisk CLI, and the other is the error function we declared using set_error_handler above.
Back to reading in variables. Now that we have the ability to read in, let’s read in the default variables that are passed to the script by Asterisk. We do this using the following code chunk:
This creates an $_AGI associative array (in the spirit of $_POST, $_GET, etc) for you to use containing all the items Asterisk passed in. For each read() line, in the first line we split it to get the key and value (this could probably have been done better with a regular expression, but I got a copy of some AGI code from a friend and modified it many moons ago before I began using regular expressions). Then, we strip out the “agi_” that Asterisk adds to the key because it is superfluous, and trim out the spaces and other garbage from the value, adding them to an array.
Putting It All Together:
Congratuations! You now have all the tools necessary to write an AGI! I suggest (as above) putting those in an include so you can reuse as necessary.
So what next? Now, you write an AGI script!
Let’s start with a simple example:
That simple! Of course, all this AGI does is read the date and time to the
caller, then exit, but it just shows that AGIs can do really powerful things,
really simply.
“Calling” you AGI:
So now you have this AGI written and you want to use it, but you don’t know how.
Well this is pretty easy too!
AGIs should be placed in whatever directory you define for “astagidir” in your
asterisk.conf file. Unless you changed it, this will be
/var/lib/asterisk/agi-bin. Next, be sure that the file is executed by setting
the executable bit “chmod +x ". You may also have to fiddle with the
permissions: the asterisk user or group need the ability to read and execute the
script.
Then, you just call it from your dialplan, like so:
Now, after you “extensions reload” of course, you should be able to dial 1000, and watch your AGI spring into action!
A more complex example:
This is an AGI I wrote at dealnews when someone in the office requested the ability to custom set names to caller IDs and have it work on all phones. Keep in mind that this is only half of the solution (the other half is a web interface).
This demonstrates one of the main advantages to using AGIs, and PHP in
particular: the ability to easily interact with databases. In this program, I’m
using the caller ID supplied by the carrier to fetch a corresponding name from a
database and send it back along with the call.
Routing calls is accomplished by calling the EXEC
function with DIAL, giving you the
ability, with a little work, to route calls based on the database. Pretty neat
for a language thought of only as web coding. Indeed, there is a large list of
commands that AGIs can use, and variables passed into them, available
here.
Help! It doesn’t work!
Relax! Problems happen from time to time.
One of the most common faults is forgetting to set the +x bit on the file to make it executable. Permissions problems are also relatively common.
For More Information:
voip-info.org - a.k.a. “the wiki,” is the
major information repository for Asterisk knowledge specifically, and IP
telephony in general.
You know, I’m only a little over two years removed from college. I still
remember what living in and around a college campus, in a college town, is like.
Hell, I really miss it - I miss the hell out of Auburn. I miss the community
feel; biking to campus, taking classes, hanging out with friends, going to bars
and just the general feel of the area.
It seems so fitting, and yet I didn’t even realize I had done it. And now that I
realize it, I’m a bit sad.
As of yesterday, I’ve been out of college for two years. It seems fitting then,
that yesterday I finally cut the last remaining tie I had to Auburn and gave up
the 334 cellphone number I’ve had for six years in favor of a more functional
256 Huntsville number. Yeah, it’s just a number, but it’s still a little sad to
me. Hell, I don’t even pay bills to the University anymore, most of my friends
have gone on or graduated, and I’m going on two years in Huntsville, but that
number was the last reminder of college and of not having responsibilities.
On the plus side, I did get a slick new Motorola Razr, though I feel like I’m
Will Smith in Men In Black and I’m gonna break this thing. I hope it’s better
than the LG it is replacing.