Tuesday, May 19, 2009

How to play a sound in a Firefox extension

What if you are working on a Firefox extension that needs to play a sound when an event occurs? Do you know what libraries to use or what you should do to accomplish this simple task? I am going to answer these questions for you!

Let's assume that the sound that we are going to play is in our content folder inside the extension, how do we retrieve the file path dynamically, i.e, depending on where the extension was installed?

First of all you have to know that Mozilla has a service called nsIExtensionManager that provides you with functions to execute tasks related to the extension like for example getting the path to the extension installation folder, so how do we use it?

We need to first instantiate the extension manager interface this way:

var em = Components.classes["@mozilla.org/extensions/manager;1"].getService(Components.interfaces.nsIExtensionManager);

Then to get the installation folder of our extension we do this:

var installationLocation = em.getInstallLocation(EXTENSION_ID);

As you can see in this code we are using a constant called EXTENSION_ID, you need to set this constant in your code with the ID of your extension. The ID of your extension is the ID you defined in your install.rdf file.

OK, we now have the installation location of our extension, so we now have to get the full location of the sound file we want to use and for that we are going to use the getItemFile function.

installationLocation.getItemFile(EXTENSION_ID, "chrome/chromeFiles/content/sound.wav");

As you can see here, we are looking for the file based on the extension installation location and we are indicating where in the extension to look. We said before we have our file in the content folder of the extension, so we pass that path as a parameter.

Until now what we have is the file location inside the extension, but we still need to create a file object to play the sound, right? Well, to create a file we use the Mozilla interface nsILocalFile and we instantiate and set the path contained in the fileLocation object like this:

var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);

file.initWithPath(fileLocation.path);


We can double check and make sure that the file really exists:

if (!file.exists()) {
// If the file doesn't exists, then return null
return null;
}

Now, if the file exists we can then play it, but how? Mozilla provides with an interface to play sounds, it is called nsISound and we instantiate it like this:

var player = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);

When playing a sound, the player needs to receive the location of the file as a nsIURI object, so we still need to convert our file into a nsIURI object and we do this by using the nsIIOService interface.

var ios = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
var sound = ios.newFileURI(file);

Now we just need to play it!

player.play(sound);


...and that is it! Very simple!!

Monday, May 4, 2009

How to create a Windows Vista Gadget

We have discussed in previous posts how to create a very simple Google Gadget and how to add preferences to it, but in this post we are going to discuss how to create Windows Vista Gadget that you can place on your Windows Vista Sidebar or desktop.

Vista Gadgets are created using XML, HTML, CSS and Javascript, so if you are familiar with all these technologies, you won't have any problem.

OK, now I am going to guide you through the steps of creating a very simple Windows Vista Gadget that displays the current time based on your computer's clock.

So let's first start by creating a new folder with the name of your gadget, in our case let's call the gadget MyClock. Under our root gadget folder, create two folders one named css and the other one named js.

Vista Gadgets use a XML file as a descriptor for the gadget, so let's create a new file under the gadget root folder called myclock.xml with the following content:

<?xml version="1.0" encoding="utf-8" ?>
<gadget>
<name>My Clock</name>
<namespace>com.mycompany.myclock</namespace>
<version>1.0.0</version>
<author>
<info url="www.mycompany.com" />
<logo src="logo.png" />
</author>
<copyright>MyCompany © 2009</copyright>
<description>Windows Vista Gadget to check the current time.</description>
<icons>
<icon width="80" height="80" src="icon.png" />
</icons>
<hosts>
<host name="sidebar">
<base type="HTML" apiVersion="1.0.0" src="myclock.html" />
<permissions>full</permissions>
<platform minPlatformVersion="0.3" />
</host>
</hosts>
</gadget>

In the gadget manifest above we are saying that our gadget is named My Clock, we are also providing information about the author and most importantly we are saying that this gadget is going to reside on the sidebar and that the base point is the file named myclock.html.

As you can see, in the manifest we are referring to two images: logo.png and icon.png. The file logo.png is used when displaying the author information inside the Vista Gadgets directory, it is generally your company's logo, and icon.png is used on the Vista Gadgets gallery to describe the gadget, it is basically the gadget's icon. For these just create a couple of PNG files and place them on the gadget root folder.

For more information about the gadgets manifest check http://msdn.microsoft.com/en-us/library/aa965879(VS.85).aspx

Our next step is to create a Javascript file where we are going to place all the necessary Javascript code to create and to display the clock. Just create a new file under the js directory and name it myclock.js and add the following code to it:

var clockContainer = "";

function gadgetSetup(clockId) {
clockContainer = document.getElementById(clockId);
setClock();
}

function setClock(){
var mytime = new Date();
var hours = mytime.getHours();
var minutes = mytime.getMinutes();
var seconds = mytime.getSeconds();

var label = "AM";
if (hours > 12){
label = "PM";
hours = hours-12;
}
if (hours == 0) {
hours = 12;
}
if (minutes <= 9) {
minutes = "0" + minutes;
}
if (seconds <= 9) {
seconds = "0" + seconds;
}
clockContainer.innerHTML = hours + ":" + minutes + ":" + seconds + " " + label;

setTimeout("setClock()", 1000);
}

Now that we have the necessary Javascript code, let's create a new file under the root folder named myclock.html, this file is the main HTML file that acts as base point for the gadget.

Now that you have the HTML file created, add the following code:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link href="css/myclock.css" rel="stylesheet" type="text/css" />
<script type='text/javascript' src='js/myclock.js' charset="utf-8"></script>
</head>

<body onLoad="gadgetSetup('myclock');">
<div id="myclock" class="clock">

</div>
</body>

</html>

In the HTML file what we have a DIV tag that is going to hold the clock, also we are saying that when the page is being loaded, call the gadgetSetup function that we previously defined in myclock.js.

Now we have the HTML and the Javascript code to display the clock, but we haven't done much to make it look nice, so let's create a new file under the css directory and name it myclock.css. Add the following code to this file:

body {
margin: 0px;
width: 120px;
height: 50px;
border: 2px solid #000;
}

#myclock {
width: 120px;
height: 50px;
background: red;
color: FFF;
text-align: center;
padding: 20px;
}

We are giving the gadget a size of 120px by 50px and we want to make it red and the text is going to be displayed in white.

Ok, we now have the main contents of our vista gadget clock, so how we install it? Very simple, take all the contents of the gadget root folder and compress it into a zip file named MyClock.zip, change the compressed file extension from .zip to .gadget and double click on the file. Windows Vista will recognize the .gadget file as a Vista Gadget installer and it would ask you if you really want to install this gadget, so click yes.

You should now see your new gadget on your sidebar. If you want you can drag it out the sidebar and put it into your desktop.

Hope this helps!!