Extending the DVDSpy Girder plug-in for new applications

When there is a clean interface

Extracting player information usually involves some kind of spying, by which is meant intercepting the application's calls to some system facility. A few applications have an extension API of their own that allows user-added code to participate in the application. Such an extension can receive updates from the application through the API and forward relevant state along to DVDSpy, which will turn it into Girder events.

Sending a WM_COPYDATA message to the top-level window whose name is "Girder DVDSpy Monitor Window" generates an event inside Girder. The dwData of the message is the integer value, and the lpData is two adjacent null-terminated strings for the event name and the string value, respectively. The cbData must be the entire length, including the second null character.

This is how the WMP and Winamp interfaces work.

Basic requirements

The source distribution of DVDSpy can be downloaded from the Girder Developers area.

Extending DVDSpy requires Visual Studio. Visual C++ is needed for compiling the plug-in itself. Some of the tools that come with Visual C++, in particular Spy++, are invaluable in determining what to intercept.

It is a good idea to start by making sure that compiling DVDSpy without any changes locally works.

Seeing the events

To check that new events are coming out of Girder properly, they need to be displayed someplace.

Definition structure

Intercepts of applications calls are defined in DisplaySpyHook.cpp within the g_matches array. Some C++ macros are used to make the syntax a little more attractive.

The XXX module

The source includes a module named XXX, which is commented out. It has several matches that do not filter out very much and several extractions which get indentification information as well as potential contents.

Adding back this module, editing the name to match the name of the target application executable file, and running the application with the modified plug-in will give a good initial gauge of how information might be extracted.

DVD Navigator

Almost all DVD player applications use the DirectShow DVD Navigator to manage the overall state of the player. DVDSpy can extract information from the navigator related to chapter position and elapsed time. This is often all that is needed (except for an event when the player closes).

Filter graphs

A number of media player applications use DirectX filter graphs to modularize their playing. DVDSpy can extract information from an active filter graph related to position and source.

Some players, like ZoomPlayer, can play both DVDs and media files. In that case, both the MS_DVD_NAVIGATOR and the MS_FILTER_GRAPH should be in the resultant module.

If the player uses a WDM TV tuner, MS_TV_TUNER may also apply.

Looking at messages

If an application does not use the DVD Navigator or filter graphs, application state needs to be gotten by looking at what it actually displays on the screen. Simple applications that use standard Windows controls will use Windows messages to update those controls.

The best way to see what messages are sent by an application when it is running is to run Spy++ with message logging.

Intercepting text display

One technique remains for intercepting display updates from applications that do not use Windows messages. That is to patch calls to the TextOut Windows function. Spy++ cannot be used to log these calls. But the TextOut match in the XXX module will produce events that may show a pattern of updates.

In most cases, the meaning of the TextOut will depend on the precise position on the screen at which it is drawn. This makes the extraction depend strongly on the particular version of the application. So, this technique should really only be used as a last resort.

The Close event

The trick to getting an event when the main window of the application closes is avoiding false matches. The application will typically open and close windows when doing innocuous things like editing the application settings. Usually one of the main windows is distinguished by its Window class.

Since windows are destroyed just after the are closed, it is hard to use Spy++ to find out the distinguishing characteristics of the main windows as they are closed. The log will not be able to find the window from the message log. Since these windows are usually created early on, it is possible to find them in Spy++ before closing the application. The XXX module also includes a match that will produce Girder events for all window closes.

An example

Here is a step-by-step cookbook for adding support for the dvdplay application. This application is mostly just a sample of how to write a DirectShow DVD player in C++ with MFC. But it seems to ship with Windows and end up in the windows system directory.

The dvdplay application is easy to support in DVDSpy. But it is not there already because so far as I know no one actually uses it is their default player. So, such support would just be a waste of space. This makes it an ideal example.

Sharing

If you add support for a new application, please try to get your changes migrated back into the main distribution.