Copyright © 2019 Advanced Media Workflow Association. All rights reserved.

Dodo and its place in the Evolution of AAF

 

Dodo is a Macro processor written specifically for the AAF SDK, dodo is just a C++ program it'll run anywhere.

 

The makefiles for executing dodo are GNUmakefiles.

 

It performs a function similar to MIDL in the Windows environment and generates header and wrapper files for different compilers and layers of the code.

A large number of the core source files for the SDK are in fact derived rather than original. This is to overcome differences in Compiler syntax on the various platforms as well as to support an abstract Data Model layer and a COM API on top.

Since the generated files are checked in to SourceForge you don't need to run dodo unless you are adding a new interface (you aren't allowed to change existing interfaces) or changing the generated code (in a compatible way) e.g. updating a comment.

The main derived files are shown in the following diagram:

all of the ref-impl/src/com-api wrappers

and particular files: ref-impl/src/impl/ImplAAFRoot.cpp and ImplAAFRoot.h

The AAF.h and AAF.idl files are effectively made by concatenating all the individual interface header files into one.

The AAF COM API manual is automatically generated from the AAF.idl file.

the AAF.h files in the Platform-specific directories

The derived files all have the word GENERATED in the initial comment and license info.

Although nobody can stop you adding new interfaces to the local include directory of your particular SDK while developing and debugging new code, at some stage of the checkin process you will have to go further back up the evolutionary chain and generate a Dodo file for your interface so that it can be used under all the supported platform variants of the SDK.

The AAF/dodo directoryn is not part of the standard platform modules checked out of CVS. You will need to specifically checkout dodo with a

cvs co dodo

command either at the top level (in the directory above AAF) or in the AAF directory itself.

Adding Interfaces

You cannot extend individual interfaces, rule number one of the COM-style interface is Invariance of interface you can however extend the API by adding new interfaces.

You may not remove or change existing interfaces, this is in order to maintain compatibility of older applications with newer libraries.

When a new interface is added it gets a new IID, only the new applications know that they can successfully QueryInterface() for that new IID.

The new interface does not respond to both the new and the old UUIDs, it would break binary compatibility to get the new interface in response to a QI() for the old one.

Typically new interfaces are interfaces to new functionality, However, there's a common special case of adding a new interface to existing functionality.

 

Let's say I have (in no particular syntax)

  • interface foo
    {
    method a();
    method b();
    .. lots of methods ...
    method p();
    method q();
    }

 

But you want to add an r() method. You could address this by adding the following new interface:

  • interface foo1
    {
    method r(); // only
    }

 

foo1 has a different IID than foo. However new clients would have to use both foo and foo1. Another way I could address this would be to add the following new interface:

  • interface fooEx
    {
    method a();
    method b();
    .. lots of methods ...
    method p();
    method q();
    method r();
    }

fooEx has the same methods as foo except with the addition of r().

This way new clients can ignore foo and only use fooEx.

Note that, just as for foo1, fooEx has a different IID than foo. For the convenience of new clients we've repeated all the methods of foo (at least the ones we didn't want to change) in fooEx. Now since foo and fooEx are very similar interfaces we can (and probably should in AAF) have foo and fooEx share the same implementation.

Note that this is an issue for implementors, not for clients, and is a different concept than having "the new interface respond to both the new and the old UUIDs".

For an example of how this is done in AAF see interface IAAFTypeDefVariableArray and interface IAAFTypeDefVariableArrayEx.

 

The naming convention seems to be foo fooEx fooEx1 ...

With Dodo you make fooEx.dod by copying foo.dod, giving it a new IID, and modifying it. If you want to share implementations, dodo knows, if you tell it, how to have an implementation support more than one interface, again see IAAFTypeDefVariableArray and IAAFTypeDefVariableArrayEx.

Dodo also knows how to have the same interface supported by more that one implementation, see IAAFEndian.

 

Rebuilding Derived Headers

For specific information on running Dodo see the preliminary Dodo Reference Manual or the platfrom-specific make instructions for a Dodo Make.