Friday, November 7, 2008

QTKit and boost

I have started working on sound. Somewhere close to he start of the project I focused on getting the project to compile. The support for WAV files butted straight on to MFC so I compiled it out with a #define _NO_WAV. What it means is to work through this code I can remove the #define and work through the compile errors.

The support for WAV files in Cello is quite simple. WAV is converted to PCM using functions in MFC, and this PCM is then converted into the correct variant by some Cello code. So I need to be able to convert WAV (and other formats) to PCM. Trawling through Apple's sample code the way forward seems to be , as I suspected, to use QuickTime. I last used QuickTime, with any seriousness, about 13-14 years ago so it has changed a little.

The recent change is QTKit. QTKit is the Cocoa API for QuickTime. The new API introduces a new Cocoa object QTMovie that provides functionality like reading movies from a file. The first thing I need to do is mesh this into C++.

I could mix C++ and Objective-C without restriction but I would rather not. There are issues with two incompatible exception models - and I would like to keep the Cello engine as close as to the PC version as possible. Also I would like to write a version of the existing WAV handling class, which works, rather than to mesh in a new mishmash.

My approach, therefor, is to provide a C/C++ interface for the objects that I use, much like Apple have done with CoreFoundation. This is what I have been doing with some of the CoreFoundation objects that have richer Cocoa APIs than C APIs.

What I plan to do is to define a type for the Cocoa QTMovie as is done in CoreFoundation
typedef struct __QTMovie *QTMovieRef;
This means that I can use boost::intrusive_ptr to manage it
typedef boost::intrusive_ptr<__qtmovie> auto_QTMovie;
void intrusive_ptr_add_ref(QTMovieRef p);
void intrusive_ptr_release(QTMovieRef p);
And all I need to do is in the body of the implementation (the .mm file) to cast to a QTMovie
void intrusive_ptr_add_ref(QTMovieRef p)
{
[(QTMovie *)p retain];
}

void intrusive_ptr_release(QTMovieRef p)
{
[(QTMovie *)p release];
}
So an example function might look like this:
auto_QTMovie NewMovieFromUrl(CFURLRef url)
{
NSError *theError = NULL;
QTMovie *theMovie =
[[QTMovie alloc] initWithURL:(NSURL *)url error:&theError];
ThrowIfCFError((CFErrorRef)theError);
return auto_QTMovie((QTMovieRef)theMovie, false);
}

No comments: