Posts Tagged ‘AMO’

Centering an AIM Module Plugin Window

Wednesday, February 4th, 2009

The window.external.window.center() is a handy function in the AIM Modules API that you can use when all you want to do is center a window without regard for the buddy list. If you want to center a plugin window in a way that accounts for the buddy list, then you will need to write your own function. A solution I actually needed in one of my plugins.

In order to center a window, we need to know what monitor it’s in. Here is a function that returns the monitor for a given window:

function findMonitorForWindow(tWnd)
{
    // loop over all monitors until we find the one where
    // the top left corner of the target window is in
    for (var i=0; true; i++) 
    {
        var m = client.findWindow('_monitor'+i);
        if (m.exists)
        {
            if ( tWnd.x >= m.x && tWnd.x < (m.x + m.width) &&
                 tWnd.y >= m.y && tWnd.y < (m.y + m.height) ) 
                return m;
        }
        else
            break;
    }
    // default to first monitor
    return client.findWindow('_monitor0');
}

NOTE: ‘client’ above is the window.external.client object that has been assigned to a global variable.

Now that we can find the monitor for a given window, we can center the window any way we want in this monitor. Here is a function that centers the window over the region not occupied by a docked buddy list.

function BuddyListAwareCenterWindow(tWnd)
{
    // The standard center function:
    var center = function(o,w,n) { return (o + ((w-n)/2) ); }
 
    var tWndMonitor = findMonitorForWindow(tWnd);
    var blWnd = client.findWindow('_buddylist');
    var blWndMonitor = findMonitorForWindow(blWnd);
    var blWidth = 0, blOffset = 0;
 
    // are both windows in the same monitor?
    if (tWndMonitor.monitorIndex == blWndMonitor.monitorIndex)
    {
        // adjust centering width if bl is docked on either left or right
        if (blWnd.x == 0 || (blWndMonitor.width - blWnd.width) == blWnd.x )
            blWidth = blWnd.width;
        // adjust centering offset if docked on left.
        if (blWnd.x == 0)
            blOffset = blWnd.width;
    }
 
    tWnd.move( 
        center(tWndMonitor.x +  blOffset, tWndMonitor.width - blWidth, tWnd.width),
        center(tWndMonitor.y, tWndMonitor.height, tWnd.height) );
}

There are some edge cases like when a window is bigger than the space it’s centered on, but this solution should help you get started.

Closing a Docked AIM Module Window

Thursday, January 22nd, 2009

It has come to my attention that you can’t programmatically close an AIM Module window while it is docked. The window.external.window.close() method does not appear to work in this situation.

For now, the only workaround is to un-dock the window before closing it:

// global aliases as described in a prior post
wnd = window.external.window;
client = window.external.client;
prefs = window.external.prefs;
 
function CloseDockedWindowWorkAround()
{
    // un-dock the window briefly.
    if (client.apiVersion == 1)
       client.docked = false;
    wnd.close();
}

This workaround will be needed in AIM 6.8 through AIM 6.9 Beta 2 (they all return an API version of 1).

I will get this issue fixed in the next AIM 6.9 beta since the plugin window is briefly shown in its undocked state before disappearing.

NOTE: This only applies to the dockable plugin window. All extra windows opened by the plugin can be closed without this workaround since those windows can never be docked.

Tips on Developing AMO Plugins

Monday, January 19th, 2009

AIM 6.8 and the AIM 6.9 betas all support AIM Modules. These are HTML and JavaScript based plugins that have full access to the Open AIM API plus client level services like HTTP requests and window management.

One of the nicest aspects of AMO plugins is that you can install and uninstall them without having to sign off. This is fantastic from both a development and user perspective.

I recommend that you get an extra plugin key for developing plugins. Once you publish version 1 and set a finger print (optional) you will not be able to develop your plugin further with that key since only plugins with the registered fingerprint will be allowed to load. The solution to this is to get an extra key that you use for development purposes. Don’t forget to change to the deploy key before publishing.

Here are five tips to help get you started on developing your first plugin:

1 You can install a plugin by running the .amo file. I typically do “start plugin.amo” from the command line or make file. AIM registers itself as a handler for this file extension. You can install a plugin even while offline.

1You should enable the debugging setting in IE for other apps. This helps you attach the JavaScript debugger during development and warns you about unhandled exceptions. With debugging enabled (i.e. not disabled), you can insert “debugger;” statements in your code to trigger the debugger. Go to the Internet Settings control panel and uncheck the highlighted option is to do this.

Enable IE Debugging for AMO plugins

1Create aliases for the window.external.* objects. This makes it easier to use these by assigning them to a variable. I put these at the top of my JavaScript file:

debug=1;
prefs = window.external.prefs;
client= window.external.client;
wnd = window.external.window;
plugin= client.pluginInfo;

1Set the AMO_TRACE_ENABLE environment variable to “true” in order to use the window.external.client.trace(msg) function that sends output to the debugger. I do it via the Environment Variables dialog in the System Properties control panel (Windows+Break key, click on Advanced tab, then “Environment Variables” button.)

Set AMO_TRACE_ENABLE environment variable

I also create a trace function that helps me leave trace message that are suppressed when the plugin is deployed. This is a good practice. Note that this code uses the global variables ‘debug’ and ‘client’ that I set up the previous tip. Remember to set debug=0 when you deploy your plugin.

function trace(m)
{
    if (debug)
        client.trace(m);
}

1If your plugin fails to install for some reason, make sure your plugin.xml file is well-formed and that the minimum required attributes are there. Here are the minimum. The UUID must be your key with {}’s:

<?xml version="1.0" encoding="utf-8"?>
<plugin 
    schema     = "1"
    type       = "html"
    uuid       = "{00000000-0000-0000-0000-000000000000}"
    name      = "any name you want"
    .
    .
    .
</plugin>

Bonus Tip: See my posts tagged with “tips” for more.

Reading an AIM SDK Preference via JavaScript

Thursday, January 15th, 2009

Last year AOL released AIM 6.8 which is the first version of AIM to support plugins written in HTML and JavaScript. These plugins are called AIM Modules. They are a zip file that contains the plugin’s manifest, content, and code with a .amo extension. NOTE: a.m.o (addons.mozilla.org) and AMO plugins are not related.

A complete introduction to AMOs is beyond the scope of this post. You can read more about the AIM Module Plugin API on the AIM Developer web site. I have written a few of these plugins under the AMO Factory brand.

In my previous post, I demonstrated how to read a preference via C++. Here is a sample that accomplishes the same in JavaScript.

// Make a shorter name for this. See the AMO API for docs on this class
client = window.external.client;
// Get the primary IAccSession object. 
// (primary is the first account that signs on.)
session = client.primarySession;
// Get the IAccPreferences object for this session
prefs = session.prefs;
 
// See the IAccPreferences API
function safeGetPref(spec, default)
{
    try {
        // method names of AIMcc objects are not case sensitive.
        return prefs.GetValue(spec);
    } catch (e) {}
    return default;
}
 
function canDisclosePluginsToBuddyFeed()
{
    return safeGetPref("aimcc.privacy.disclosePluginsToBuddyFeed", 
        false);
}
 
if (canDisclosePluginsToBuddyFeed()) 
{
    alert('preference is true');
}

I recommend that you use try/catch blocks around AIMcc method calls since they can return COM error results that throw exceptions in JavaScript. The safeGetPref() function takes care of this and returns the default value if AIMcc returns any error.

TIP: The e.number property in the catch block has the HRESULT as a negative number. You can find the symbolic name for this error via the Symbol Lookup dialog in my CoreWitness plugin. Just enter the number in the find box to do the reverse lookup.

Easy tool for generating AIM plugin fingerprints

Sunday, December 7th, 2008

Ever wanted a command line version of acchash.exe that simply displays the fingerprint and copies it to the clipboard without any mouse clicks?

Here you go:

use Digest::SHA;
use Win32::Clipboard;
 
$file = shift;
 
if ( -e $file && -f $file )
{
   $hash = uc( Digest::SHA->new(256)->addfile($file, 'b')->hexdigest );
   print "Plugin Fingerprint for '$file' (copied to clipboard): $hash\n";
   Win32::Clipboard()->Set( $hash );
}
else
{
   print "Usage: gushash [plugin_file_to_hash]\n";
}

Save this as gushash.pl in a location where your command shell can find it.

You will need Perl and the Digest-SHA package to use this script. The latter can be obtained through the ppm (Perl Package Manager) tool that is installed with Perl.

I’m always making little tools like this in Perl and Python to help me automate stuff.

This is here in case someone finds it useful…

AIM Vote ‘08 Plugin for AIM 6.8+

Thursday, October 30th, 2008

I just wanted to highlight a new plugin that was recently added to the AIM Gallery. The AIM Vote ‘08 plugin lets you vote for Obama or McCain and then see who your buddies vote for. Your vote is only visible while you are online and you can change your mind at any time.

Here is a capture from the AIM Gallery Web page:

AIM Vote on the AIM Gallery

This plugin is all aces in my book; Best part is that I did not even write it but I know the man that did.

Just look at the face of your candidate when he is winning or losing. Well done “Tommy Gunn”!

Click here to go to the AIM Gallery site where you can download this plugin.

Enjoy and be sure to vote on November 4th.

AIM 6.9 Beta 2

Tuesday, October 21st, 2008

AOL released the second beta of AIM 6.9 today.

This new build has some interesting changes as mentioned on the AOL beta site release notes:

  • Sign in as invisible is now an option in the sign in window — This check box is not sticky so you can’t check it and expect it to be checked the next time you sign in or out. This is a feature that was previously only available in my IM Tweaks plugin.
  • The UI has been streamlined. We have removed some of the redundant menus and options — Less is more or less :). Be sure to send feedback on what you like or don’t like here.
  • The buddy find feature is now similar to FireFox. Just press Ctrl+F from the Buddy List® window and begin typing the name of your buddy. You can close the find box to give yourself more room to show your Buddy List by clicking on the X button next to it.
  • Search the web from your IM window. Just enter a query in the search box to open your browser and see the results. AIM Search is “powered by AOL search” and “enhanced by Google”.
  • The AMO API continues to be improved in this version. Most of the changes are internal with a few API extensions. AIM 6.8 AMO plugins are also supported in AIM 6.9. I will cover some of these new API additions in a future post.
  • One new feature not mentioned in the official release notes is a new option in the context menu of the IM compose box (Ctrl+D) that allows you to “paste as plain text”. This makes it ultra-easy to paste web content without messing up your fonts.

Here is a screen shot of AIM 6.9 beta 1 and beta 2 Buddy List windows with some of the highlighted changes. As you can see we moved the IM, Buddy List config, and Actions menu to the top under the main menu bar and gave them new icons. All plugin commands that were in the Actions menu are now in the menu with the gear icon.

You can download the latest AIM beta here. Let me know what you think.

CoreWitness 1.0.7 Shipped

Monday, July 28th, 2008

I have updated the CoreWitness Plugin. This version has two new features called DAccEvents Wizard and Symbol Lookup.

The DAccEvents Wizard helps you generate the code needed to handle Open AIM events in your own clients and plugins. It can generate code in C++ and JavaScript. The latter is useful for developing AMO plugins.

The Symbol Lookup window lets you quickly find the value of a particular constant. You can search by entering a partial name to see all the symbols containing that name. Or, you can do a reverse look up by entering a numeric value to see all the symbols with that value. You can click on any of the static text elements under the list box to copy the text to the clipboard. Clicking on the symbol’s name will copy an assignment statement to the clipboard.

You can find more information including screen shots and a download link here.

AIM 6.8 Beta—AIMing with AMO

Monday, May 19th, 2008

Just got back from a business trip. I highly recommend flying business class, especially on Lufthansa.

Last Friday, AIM released an updated beta build of AIM 6.8. I am calling this version of AIM “Plugin-Central“. AIM has added more plugin functionality than ever before including support for these new AIM Module (AMO) plugins that are HTML/CSS and JavaScript based. If you want to see how an AMO plugin works simply rename the “.amo” file to “.zip” and peek inside. I will say more on how you can write your own AMO in a future post.

I highly recommend that you give this beta a shot. You can even find my first ever AMO on gallery.aim.com under the pen name of “IM Freaq”. “IM Freaqs” is a simple little plugin that shows the ten most frequent buddies you interact with. It’s my personal favorite so far. Here is the about screen shot of IM Freaqs (courtesy of AOL):

About IM Freaqs

As Greg mentioned in his post, I also helped out with the twitterMan 4.0 plugin. Writing an AMO is pure fun.

With AIM 6.8 you can easily manage your pluigins. Just click on the “Manage” link at the bottom of the Buddy List to open the plugin manager. From there you can enable, configure, re-order, and uninstall any plugin without having to sign off. Existing AIM plugins, that are not AMOs, can also be uninstalled if they support this new feature. My RX-Plugin, IM Tweaks, and CoreWitness plugins support AIM 6.8, including the ability to uninstall them from the plugin manager.

Let me know if you have any questions or comments on AIM 6.8 and IM Freaqs, etc. I appreciate all feedback.

Thanks and enjoy.