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.
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.
OutputDebugString
. If Girder is run under the Visual
Studio debugger, this will display in the Output window. For example, girder.exe
can be set as the application to run for the DVDSpy DLL project.
g_matches
array.
Some C++ macros are used to make the syntax a little more attractive.
BEGIN_MODULE
block for each application.
It gives the name of the application's executable file and the first
segment of the name of all the application's events.
BEGIN_MATCH
... END_MATCH
block for each intercepted call (usually a windows message).
BEGIN_EXTRACT
marker defines the boundary between
the match predicates and the information extraction.
BEGIN_MATCH
to BEGIN_EXTRACT
the
entries each define a condition which must be satisfied by the
intercepted message. For instance, the message code, or the class of the
target window.
BEGIN_EXTRACT
to END_MATCH
the
entries each define a piece of information that is extracted from the
message (or more generally the state of the application) and passed to
Girder. Each such entry turns into a single Girder event with one
payload string.
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.
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.
The best way to see what messages are sent by an application when it is running is to run Spy++ with message logging.
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.
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.
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.
BEGIN_MODULE(XXX)
.
#if 0
to #if
1
.
DVDSpy monitor window started. Girder event: 'dvdplay.SetText.Class' pld='#32770'. Girder event: 'dvdplay.SetText.Text' pld='DVD Player'. Girder event: 'dvdplay.SetText.Class' pld='VideoRenderer'. Girder event: 'dvdplay.DVD.Domain' pld='STOP'. Girder event: 'dvdplay.DVD.TitleNo' pld=''. Girder event: 'dvdplay.DVD.Chapter' pld=''. Girder event: 'dvdplay.DVD.Duration' pld=''. Girder event: 'dvdplay.DVD.Elapsed' pld=''.This shows the application setting its window title and that the DVD Navigator is indeed used.
Girder event: 'dvdplay.DVD.Domain' pld='DVD'. Girder event: 'dvdplay.DVD.TitleNo' pld='01'. Girder event: 'dvdplay.DVD.Chapter' pld='01'. Girder event: 'dvdplay.DVD.Duration' pld='01:00:00'. Girder event: 'dvdplay.DVD.Elapsed' pld='00:00:00'. Girder event: 'dvdplay.DVD.Elapsed' pld='00:00:01'. Girder event: 'dvdplay.DVD.Elapsed' pld='00:00:02'. Girder event: 'dvdplay.DVD.Elapsed' pld='00:00:03'. Girder event: 'dvdplay.DVD.Elapsed' pld='00:00:04'. Girder event: 'dvdplay.DVD.Elapsed' pld='00:00:05'.
WM_TIMER
, the filter graph was not given a chance. Had
there been no DVD Navigator, it would have generated some events.
BEGIN_MODULE(dvdplay) BEGIN_MATCH() ENTRY_NUM(MATCH_MESSAGE, WM_TIMER) ENTRY_NUM(MATCH_MEDIA_SPY, MS_DVD_NAVIGATOR) BEGIN_EXTRACT() NENTRY_NUM(Domain, EXTRACT_MEDIA_SPY, MS_DVD_DOMAIN) NENTRY_NUM(TitleNo, EXTRACT_MEDIA_SPY, MS_DVD_TITLE) NENTRY_NUM(Chapter, EXTRACT_MEDIA_SPY, MS_DVD_CHAPTER) NENTRY_NUM(Duration, EXTRACT_MEDIA_SPY, MS_DVD_TOTAL) NENTRY_NUM(Elapsed, EXTRACT_MEDIA_SPY, MS_DVD_TIME) END_MATCH()
BEGIN_NMATCH(Close) ENTRY_NUM(MATCH_MESSAGE, WM_DESTROY) ENTRY_STR(MATCH_CLASS, "VideoRenderer") BEGIN_EXTRACT() ENTRY_STR(EXTRACT_CONSTANT, "") END_MATCH()
Dev: 15 dvdplay.Close 14:30:22 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Elapsed 14:30:15 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Duration 14:30:15 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Chapter 14:30:15 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.TitleNo 14:30:15 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Domain 14:30:15 Sunday, April 21, 2002 Pld1: STOP Dev: 15 dvdplay.Elapsed 14:30:14 Sunday, April 21, 2002 Pld1: 00:00:05 Dev: 15 dvdplay.Elapsed 14:30:13 Sunday, April 21, 2002 Pld1: 00:00:04 Dev: 15 dvdplay.Elapsed 14:30:12 Sunday, April 21, 2002 Pld1: 00:00:03 Dev: 15 dvdplay.Elapsed 14:30:11 Sunday, April 21, 2002 Pld1: 00:00:02 Dev: 15 dvdplay.Elapsed 14:30:10 Sunday, April 21, 2002 Pld1: 00:00:01 Dev: 15 dvdplay.Duration 14:30:11 Sunday, April 21, 2002 Pld1: 01:00:00 Dev: 15 dvdplay.Chapter 14:30:11 Sunday, April 21, 2002 Pld1: 01 Dev: 15 dvdplay.TitleNo 14:30:11 Sunday, April 21, 2002 Pld1: 01 Dev: 15 dvdplay.Domain 14:30:11 Sunday, April 21, 2002 Pld1: DVD Dev: 15 dvdplay.Domain 14:30:11 Sunday, April 21, 2002 Pld1: PLAY Dev: 15 dvdplay.Elapsed 14:28:46 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Duration 14:28:46 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Chapter 14:28:46 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.TitleNo 14:28:46 Sunday, April 21, 2002 Pld1: Dev: 15 dvdplay.Domain 14:28:46 Sunday, April 21, 2002 Pld1: STOP Dev: 18 GirderEnabled 14:28:33 Sunday, April 21, 2002 Dev: 18 GirderOpen 14:28:25 Sunday, April 21, 2002