PluginSDK

From Shareaza Wiki
Jump to navigation Jump to search

Plugin SDK

Welcome to the Shareaza Plugin SDK. With this toolkit you can create plugins which work with the Shareaza. application, extending its functionality into new areas. Shareaza provides a comprehensive plugin architecture, offering access to its internal object model and exposing a variety of events and data hierarchies.

Types of Plugin

Shareaza supports many different types of plugin, to provide different types of support to the application.

General Plugins

General Plugins are perhaps the most easily recognised. They appear in the list of plugins in Shareaza settings, and usually have some kind of presence in the GUI of the program. They can add commands to menus and toolbars, create windows and dialog boxes, interact with the user, etc. This is the most common plugin type, and has the most "power".

Image Services Plugins

Image Services Plugins provide Shareaza with support for a particular image file format. Shareaza comes equipped with a number of image services plugins for common file formats such as BMP, JPEG, etc, however additional file formats can be supported by creating new image services plugins. Image services can also be created for video files, providing a thumbnail image.

Download Preview Plugins

Download Preview Plugins perform special processing when previewing partially downloaded files, repairing corrupt or missing data to allow the preview to work properly. Different download preview plugins can handle different file types, and undertake different repair actions. For multimedia files this often includes repairing the datastream, rebuilding frame indexes, etc.

Library Builder Plugins

Library Builder Plugins allow Shareaza to collect internal meta-data from files in the user's library. By creating new library builder plugins, Shareaza can intelligently scan and classify new file types, and provide more meaningful meta-data in search results.

Audio Visualisation Plugins

Audio Visualisation Plugins are used by Shareaza's media player to display animated graphics that respond to sound being played by the user. Visualisation plugins can provide the graphics themselves, or serve as a "wrapper" to support visualisation plugins from another application.

Media Player Plugins

Media Player Plugins or Media Services plugins provide multimedia playback capabilities to the Shareaza application, and are used in the Media window within the GUI. Unlike the other plugin types, there can only be one media plugin installed at any given time. Note that the plugin is only responsible for actual playback and control -- the user interface is provided by Shareaza.

What is a Plugin?

Shareaza plugins are COM objects. COM stands for Component Object Model, and is a common framework for developing software components which can be accessed independently from any particular language, and without knowledge of their implementation. This is achieved by programming with interfaces.

Objects in COM must implement one or more interface. Each interface defines a set of methods (and properties) that other software can use to interact with the object. Shareaza plugins implement one or more of Shareaza's plugin interfaces, depending on what kind of functionality they want to provide to application. Shareaza itself exposes a number of objects (and interfaces) which plugins can use to access the Shareaza application.

It is possible to create COM objects in a variety of languages and development systems, however the examples in this documentation cover the use of Microsoft Visual C++ and ATL, the Active Template Library. ATL is a terrific toolkit for creating light-weight COM objects in C++. Alternatively you can use MFC, the Microsoft Foundation Classes, which often provide more detailed support for GUI-heavy plugins.

The Shareaza Plugin SDK includes the ShareazaOM.h file, which contains definitions for all of the COM interfaces used by Shareaza. This file can be included in C or C++ based plugin projects. Other languages can import the COM type library from Shareaza.exe.

Plugin Registration

Because Shareaza plugins are COM objects, they must record certain details in the registry before they can be used. This is known as "registration". Most COM development systems (including ATL) provide this service automatically.

Plugins must also register themselves within the Shareaza registry key:

     HKEY_LOCAL_MACHINE\Software\Shareaza\Shareaza\Plugins\TYPE

The TYPE key above needs to be replaced with the type of plugin being registered. For example, general purpose plugins register under the General key:

     HKEY_LOCAL_MACHINE\Software\Shareaza\Shareaza\Plugins\General 

Plugins should create a text value under the appropriate key. The name of the value will depend on the plugin type, and could either be a descriptive name for the user, or a file extension the plugin wishes to be responsible for, etc. Please see the documentation specific to the plugin type for more information. The value is the CLSID of the object, in standard registry format.

Registering Using ATL

It makes sense to perform the COM registration and Shareaza plugin registration at the same time. ATL provides an easy way to do custom registry additions based on simple RGS scripts located in the plugin's resource list. The registration script from the ImageViewer general plugin is shown below:

HKCR {

 Shareaza.ImageViewerPlugin.1 = s 'Shareaza Image Viewer Plugin'
 {
   CLSID = s '{2EE9D739-7726-41cf-8F18-4B1B8763BC63}'
 }
 Shareaza.ImageViewerPlugin = s 'Shareaza Image Viewer Plugin'
 {
   CurVer = s 'Shareaza.ImageViewerPlugin.1'
 }
 NoRemove CLSID
 {
   ForceRemove {2EE9D739-7726-41cf-8F18-4B1B8763BC63} = s 'Shareaza Image Viewer Plugin'
   {
     ProgID = s 'Shareaza.ImageViewerPlugin.1'
     VersionIndependentProgID = s 'Shareaza.ImageViewerPlugin'
     InprocServer32 = s '%MODULE%'
     {
       val ThreadingModel = s 'Apartment'
     }
   }
 }

}

HKLM {

 NoRemove Software
 {
   NoRemove Shareaza
   {
     NoRemove Shareaza
     {
       NoRemove Plugins
       {
         NoRemove General
         {
           val 'Shareaza Image Viewer' = s '{2EE9D739-7726-41cf-8F18-4B1B8763BC63}'
         }
       }
     }
   }
 }

}

HKCU {

 NoRemove Software
 {
   NoRemove Shareaza
   {
     NoRemove Shareaza
     {
       NoRemove Plugins
       {
         val '{2EE9D739-7726-41cf-8F18-4B1B8763BC63}' = d 1
       }
     }
   }
 }

}

Note that the last section is optional, and applies to general plugins only. It sets the plugin to "enabled" in the current user's settings. Similarly, the threading model listed in this example is Apartment, which is appropriate for general purpose plugins and media player plugins only. All other plugin types should use Both.

When creating or editing a registry script, always make sure the CLSIDs are correct. Generally there should be only one CLSID in a single script, and it should match the globally unique CLSID of the object you are working on. Never reuse CLSIDs from existing plugins!

Mini HowTo

This is taken from a forum post by Mike

The image viewer plugin is a good template to use for creating new plugins. The image viewer is EXTREMELY well commented, so there is far more documentation in there than there is here. But I'll outline it here anyway:

The framework seems complicated at first but it's fairly simple once you figure out what's what.

The main interface to worry about is IGeneralPlugin. That's the interface you need to implement on your plugin object. You then register your plugin both as a standard COM class, and as a Shareaza general plugin.

If you take a look at IGeneralPlugin you will see that there are only a handful of methods to implement. When the plugin is loaded Shareaza will call the IGeneralPlugin methods to tell your plugin what is happening. It calls SetApplication to give you a reference to the core Shareaza object model that you can save for later use. You can usually ignore QueryCapabilities and OnSkinChanged. That just leaves Configure, which you can implement if you want to. Configure is called if the user selects your plugin in settings and clicks the configure button.

So, IGeneralPlugin is done. Now it's a case of actually building functionality. A common task is adding new menu items or toolbar buttons to the Shareaza GUI to allow the user to send commands to your plugin. If your plugin will handle user commands, it must implement a second interface called ICommandPlugin.

Again, ICommandPlugin only has 4 easy methods to implement. When Shareaza calls RegisterCommands, your plugin should register any new commands that it intends to handle. Sometimes you might want to handle existing commands defined in Shareaza (eg "connect to network", etc). Other times you might want to define new commands specific to the plugin, so you must register them (see below).

Then, Shareaza will call InsertCommands. Now your plugin has a chance to insert any new menu items or toolbar buttons into the Shareaza GUI. It can insert commands that are part of Shareaza, or, it can insert new commands that it has just registered during RegisterCommands. See below on inserting commands.

At this point the GUI is ready. Shareaza will call OnUpdate whenever it needs to determine the status of a command that your plugin has registered. It passes the registered command ID, and expects you to fill in whether the command is currently visible, enabled, and checked. Return S_OK if you are handling the command, or S_FALSE otherwise.

When a user invokes any command, plugin registered or not, Shareaza will call OnCommand with the ID. Check the command ID and do your processing if you want. Return S_OK if you handled it, or S_FALSE if you want Shareaza to keep looking for someone else to handle it. Return an error code e.g. E_UNEXPECTED if you didn't handle the command and Shareaza should NOT keep looping.

Easy!

Now, registering commands. All GUI stuff is handled by the IUserInterface module, which you can get from the IApplication module that you received in SetApplication.

To register a command, call:

pUserInterface->RegisterCommand( L"YourPluginName_CommandName", NULL, &command_id_variable );

All commands are given a name so that they can be referenced in XML. By convention, commands registered by plugins are named "pluginname_commandname". The method will return the registered command ID number for that command. That's the number you'll check in OnUpdate/OnCommand, etc.

Inserting commands is a much more involved topic -- I'll just summarize and say that you use the IUserInterface pointer to get access to any Shareaza menu or toolbar that you want, and you can modify them as you see fit.

You can also create whole new menus and toolbars at this point, either manually via code, or by loading a bit of standard Shareaza GUI XML. You can do that via:

pInterface->AddFromResource( your_dll_hinstance, resource_id_number );

Shareaza will load the given XML resource from your DLL and parse it as a modifying skin.

I think I'll stop there. There is of course lots more cool stuff. You can handle other events, e.g. with IExecutePlugin. You can create Shareaza windows in the GUI by implementing IPluginWindowOwner and asking IUserInterface to create a new window for you (it'll give you a IPluginWindow), etc. Lots of coolness.

Take a look at "A Quick Walkthrough of Plugin Development"