Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2000-305
$eventId
ID of event: wwdc2000
$eventContentId
ID of session without event part: 305
$eventShortId
Shortened ID of event: wwdc00
$year
Year of session: 2000
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC00 • Session 305

QuickTime: The Road to Mac OS X

Digital Media • 1:01:54

Apple continues to lead the way in digital media creation, media publishing, and consumer multimedia, including the latest in Internet multimedia delivery. Come learn about the migration of QuickTime onto Mac OS X.

Speakers: Tom Dowdy, Greg Chapman, Sam Bushell

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Please welcome Tom Dowdy. Thank you. Good morning. This session is entitled QuickTime: The Road to Mac OS X, which, contrary to what you might be thinking, is not San Carlos Street out there. What are we going to be talking about this morning? We're going to be talking about QuickTime on the OS X platform and things that you need to know about QuickTime on the OS X platform for your application.

We're also going to cover some new things that are true for all platforms, including the Mac OS X platform, that are different from the last time we got together a year ago. We're going to talk about extending the QuickTime platform. This is on the existing Mac platform on Windows and, of course, on Mac OS X.

The important thing to know about QuickTime on Mac OS X is that QuickTime is a first-class citizen of Mac OS X. Most of the things that you've come to know and love about QuickTime are the same. They haven't really changed. A few things are gone, a few things have been added, and there's some new opportunities for you, the developer. You can call QuickTime from either the Carbon or Cocoa API set. You can also call QuickTime from Java. Here's the classic picture of Mac OS X. You can see that QuickTime is layered down with all of the other graphical goodies that are on Mac OS X.

What's the same? The same APIs are available on Mac OS X, on Windows, on Mac OS 9, Mac OS 8, and Mac OS 7. We finally, this year, cut off Mac OS 6. So those of you that still have applications that are targeted for the 607 platform, sorry, that's the end for you. I think most people have read by now.

All of the major codexes you've come to know and love are there on QuickTime for Mac OS X. That includes streaming, VR, the wired actions you just heard about, the URL data handlers. In fact, There may be more there than you are used to if you're used to using QuickTime on other platforms. We'll get to that in just a moment.

There are a few things we had to take away. Not very much, though. In fact, we had a difficult time coming up with what exactly we did remove for Mac OS X. The major one from an API standpoint is the various Git file preview calls, such as standard Git file preview or custom Git file preview.

These are no longer necessary. Nav Services provides the preview services for opening and closing documents on Mac OS X, so there's no need for additional work that we are going to be doing. Simply use Nav Services in your application and you'll be fine. Some codecs that were related to legacy types of technology that are no longer available on Mac OS X, those codecs also don't need to be there.

There's some excellent new opportunities for you if you're new to QuickTime or you're new to the Mac OS X platform. Some of the new features that we've been talking about in QuickTime are available first on the Mac OS X platform. In fact, they're in the PR4 CD that you got here at the conference. Flash 4 and Cubic VR are good examples of this. Those technologies are there for you to play with and enjoy right now. They'll be available for you to play with and enjoy later this summer for the other platforms.

One of the important things that has been asked earlier in the conference, and unfortunately I didn't get a chance to grab the Carbon guys before they were doing their presentation, is the issue of the event run loop, or the timer events, and idling of movies within your application.

So, I'm going to do a little demo here, and then we're going to come back and talk about idling. So if I'd have demo two up. Oh, we see that demo two has gone to sleep. I think the audio/video is back now, so we should be able to get it back up. Alright. So here we are. We're running the QuickTime player application. Just if you haven't seen this enough so far in the conference. Open up a movie here.

I'll start playing this. Now you can see that the movie continues to play, even when other things are going on in the computer. That's because of the various multitasking services that are available in Mac OS X. It's a little difficult to see probably on the projector, but the movie is actually transparently being displayed through the menu, as I've got the menu bar down here, which is kind of a nice little feature, being composited live.

One of the things that wasn't pointed out though, and that if you had seen the demo at the Mac-- I'm going to start this movie again. If you'd seen this demo at Macworld, you wouldn't have noticed-- and David Schmuck, who are the founders of QuickTime. The first thing you'll notice, because it wasn't true, is that the equalizer bars in the lower right-hand corner of the movie continue to move.

This is idling and user interaction of the application that's not specific to QuickTime. In addition, the play bar at the bottom of the movie and the time of where we are in the movie on the left-hand side continue to advance as the movie is played even though the mouse is down.

I'll stop that there and we'll go back to slides. Why is this important? This is important because this is a section of the application that could not possibly be handled by QuickTime itself. These are user interface idling services that are unique to this application. So it's the application's responsibility to service the idling. That includes the idling of the movie and the idling of its own user interface.

In specific, if you, the application, are doing the movie idling, It's important for you to be involved because of the following reason. The idling calls in QuickTime have an implied API around them, which is that the origin of the window affects where the movie is displayed within your application.

If we idled the movies on your behalf, we would not know where you may have set focus within your window. Those of you who are used to using Power Plant or other such frameworks realize that you focus on various subviews within your superview of the window. That process involves setting the origin of the window.

As that focus would be moving from button to button or subview to subview within your application's window, if we suddenly came along and idled one of the movies for you, you'd find the iMovie Kids movie suddenly playing on top of your pause button, rather than where in the window it was supposed to go. Because of this, and because of the fact that your application also has other movie-related idle tasks to do, we do not idle the movies on your behalf.

was the demo. Let's talk about some changes inside your application. On the road to OS X, the QuickTime team also went down that road. We had a lot of work to do to get QuickTime performing well on OS X and running the way it's supposed to. Most of these things we'd already done for many of our components.

Some of them we hadn't done at all for any of our components, so we had to go through these steps ourself. If you have been to any of the Carbon sessions, you've probably heard some of these things before, so I'm not going to belabor them over and over again.

There are two that are particularly important, I think, and so I'm going to call them out. You're making a lot of major changes to your application, potentially, in the process of carbonizing it. You're going to be re-qualifying it and re-qualifying it on a new OS. Now is a really good time to remove some of the older legacy code that you might have hanging around.

A good example of this is applications or codecs that check for the presence of color quickdraw, even though they're compiled for PowerPC. The PowerPC has always had color quickdraw. That check is unnecessary. It's slowing down the loading of the application, slowing down the loading of the codec, and adding additional dependencies on parts of the system that you really don't need to be worrying about.

So take a pause, look at your app. That file that you haven't touched since 1989, you might want to look at once or twice. Another really good trick that we discovered inside the QuickTime team, you want to be compiling your application with the maximum amount of type checking turned on, because graph ports, windows, dialog pointers are no longer freely castable back and forth.

If you're not performing casting yourself, the compiler will catch this type of behavior and point it out to you very quickly. You'll be able to correct it, move on, make the appropriate Carbon calls, and your application will be sailing along. However, every once in a while, somebody, either through habit or knowledge that, a lack of knowledge that this is not necessary, will be performing additional casts between one type and another.

It's a good idea to search your application for graph pointers, window pointers, and dialog pointers. The searches I have here, you'll notice they don't have a beginning parentheses on them. That's because if you search for graph pointer closed parentheses, you'll also catch all the casts to type color graph port as well. Any time you see one of these casts, you should examine that code. Try to figure out why it's being done and correct it if necessary. This is especially important if you're using Carbon on OS 9 as part of your bring-up strategy for OS X.

These types of compiler errors or casting errors will not be caught by running on OS 9, where graph pointers, window pointers, and dialog pointers may still be freely castable back and forth. But when you try to bring your application up on OS X, they'll crash very hard. Much easier to fix this by grepping inside of your development system than playing with GDB on the other system.

Here's a very important point. Mac OS X is a preemptive multitasking operating system. If you have an application that has interrupts, completion routines associated with those interrupts, you need to be aware that interrupts can be running in a separate thread. And these threads can preempt one another. The specific case that you would never see on the classic Macintosh operating system is that while you are servicing an interrupt in one of your callback routines, your main thread might start running again. This can happen on Mac OS X and will happen on Mac OS X.

If your code is not ready to deal with this, if you're not appropriately putting mutexes, semaphores, or other types of OS-level protection around global variables that you're accessing both from your main thread and your interrupt completion routine, you're going to have a very difficult time tracking down these problems when you're running on Mac OS X. These same issues arrived on Windows, and they're problems that we've been having to deal with inside of QuickTime for quite some time now.

So when we were bringing our code up on Mac OS X, we needed to make sure that we were doing all the same level of protection on Mac OS X as we do on Windows. As a matter of fact, just two days ago, we tracked down a bug where we'd missed one.

So with that, I'd like to bring out Greg Chapman, have him come and talk to you about new features that are available on all the platforms in the last year in QuickTime. Greg? Thank you. I'm going to be talking about some of the new things that we've added to QuickTime since the last time we had a developers conference. Three things in particular.

Variable bitrate audio is something that we've been asked for a lot. We finally added that to support the variable bitrate MP3 files. Of course, you could actually open files and URLs before this, but there's some new twists that need reviewing. Kevin Calhoun talked about this a little bit in the streaming session yesterday, but we'll go through that in a little bit more detail.

The coolest thing about all these new features, and variable bitrate audio is just an example, is that existing apps will pick up this support for free. You don't have to rev your app. There are a couple of exceptions in this case. The main exception is if you call the sound manager directly to play audio, then you need to know a few things. I'm going to give you some of the highlights, point you at the real documentation. We've got lots of documentation on these new features, and you'll be ready to go. There's a new constant variable compression.

It's actually been in the sound.h header for a long time, but it's never been supported. It's right next to fixed compression. We support it now. It's great. Several structures have been extended. If you don't know what those structures are, you don't need to know that they've been extended, and we'll just take care of it for you.

The biggest problem that you're going to have to deal with in your code is if you call the sound converter APIs and you want to be able to convert to or from VBR audio. There's a new API. It's well documented on our website. The old Sound Converter Convert Buffer API had a lot of assumptions about relationships between input and output buffers that, of course, get completely blown away by VBR audio.

Sound Converter Fill Buffer is much more flexible. You can use it for VBR and for CBR audio. We recommend that you do that. You pass it a callback routine that it will call every time it needs more source data, and that callback will get called a completely variable number of times.

There are a couple of flags that it will return to let you know what its status is, if it couldn't fill its output buffer, or if it has data left over. Your code can deal with that pretty simply. The QuickTime 401 PDF is going to be referenced several times in the slides. This has a whole pile of information about some of these new features. It's easy to find up on our website.

64-bit file offset support has been in QuickTime for a while. We supported it on Windows because they had a file system that would support these large files. With Mac OS 9 and QuickTime 4.1, 64-bit file offset support, really huge files, is supported on all of our platforms. Again, existing apps will pick this up with no change, no problem at all. The two exceptions, one exception is if your app creates or modifies movies, then you need to be able to read and write these new type of movie atoms.

We're real careful not to use the new movie atoms unless the file actually is bigger than 2 gigs, so that if the file is a small movie file, your old app will be able to read it without having to rev. The other exception is if you write a component that provides file access. In this case, not only do you need to call the new APIs in the toolbox to deal with the file, but you actually have to implement some new component calls in your component.

[Transcript missing]

There's a new document that's coming out this week. I believe it's already posted on the website. Inside QuickTime, the QuickTime file format. This is way more detailed than you're going to need unless you're one of those lucky people that gets to parse movie files by hand a bite at a time without the use of QuickTime, and then you'll really want to read that manual.

Opening files and URLs doesn't sound very exciting, but there are three cool things I want to tell you about, and apparently one of them is really cool. DataRefs are an abstraction of various types of data sources, and Kevin talked about this yesterday. and David For using to get to URLs.

New Movie from DataRef can actually open files as well. If you use New Movie from File, that's fine, but you can set up a DataRef that points at a file. You can set up a DataRef that points at a handle. You can set up DataRefs that point at lots of things.

This is actually an extensible part of QuickTime. You could write a component that extends QuickTime and adds a new type of DataRef and QuickTime would then be able to read data from your source. New Movie from DataRef can open any piece of media that QuickTime understands. Get Graphics Importer for DataRef is specific for still images. You can open still images with New Movie from DataRef, but you'll get a movie with one frame in it, which may be useful, but probably isn't.

As I said, files are data refs. A data ref is just a handle, and it contains some piece of information that points you at a data source. In this case, the handle just contains an alias. And then you pass in to new movie from data ref, there's a second parameter that you tell it what type of data ref it is.

Pretty straightforward. The next slide is going to take that gold code and change it to open a URL instead of a file. But the call to new movie from DataRef is identical. There you go. URL is a C string. Don't forget that null termination. Put it in a handle.

Pass it off to new movie from DataRef. As Kevin said yesterday, the web can be slow. Async movie loading is new in QuickTime 4.1, but it's just an extension of what we were already doing. We already had the concept of FastStart, where the movie can start playing before all the media is down. But in FastStart, the entire movie header does need to be downloaded before you can play. So a new movie from DataRef doesn't return until the entire movie header has been downloaded. and in some cases over slow connections, that can be pretty slow.

What you can do is use the New Movie Async OK flag, which will take FastStart one step further. New Movie from DataRef will return immediately. with basically an empty movie, which you then can't play. The return movie isn't all there, and you have to continue tasking the movie. If you're using a movie controller, which we recommend, you continue passing events to the movie controller because this async opening of the movie doesn't happen at interrupt time, it happens at task time. As you task it, more of the movie comes down.

GetMovieLowState is the API you call to find out when your movie is playable. There's several states. It's loading means that the header isn't all the way down yet, so please don't start playing yet. It's playable. Complete actually means that all the media is down. The fast start has finished and the whole movie is down, so now you can turn on saving in your app or something like that.

You can get an error state back, and there's another API to call to get movie state, or get movie error, to find out what the error is. The states are on a numeric scale. You should use arithmetic comparisons because we reserve the right to insert new states in between. But if you say, you know, is less than playable, don't play it. That's always going to be good forever.

Now we get to the really cool thing. I'm going to demo this for you in just a minute. You can call new movie from DataRef or get graphics imported for DataRef on any file that QuickTime understands. You don't need to know anything at all about the file format.

We wrote a simple app that's so lame it doesn't even know about graphics importers. It just calls new movie from DataRef on anything you drop on it, sets up a movie controller, sets it up to play, and starts tasking the movie controller. And let's see what that lame app can do. Go over to demo one.

There it is, we call it Simple Movie Player. Let's just drag a whole bunch of still images onto it. Now these will open as movies, but that's alright, we'll get to see them anyway. Oh, we have a JPEG. We have a BMP file for you Windows fanatics. An SGI image. Let's see, what do we got here? I can scale this down so you can see more of it. A Photoshop file that we modified extensively for our stupid movie.

We have a ping. We have a target file. Oh, here's a Mac Paint image. That's great. We have a TIFF. Let's see what else we can do. Got a bunch of audio files here. This movie player just does the same thing to all of them. Here's an interesting WAV file we found somewhere.

I actually dragged that off of my Windows machine. Here's an AIFF. You know, all pretty standard. Here's a cheap MIDI file. We can play those too. Sound Designer 2. Here's an MP3. We've just got a whole pile of things, and Simple Movie Player doesn't do anything different for any of these. He doesn't know what these files are, he just makes those API calls, and everything works.

Let's see, we've got a couple of little more movie-like things. Here's a flick animation. Ah, here's an interesting AVI file. What lets you learn about the world in a whole new way? Boo-hiss. Okay, here's an animated GIF of an iMac for you. Okay, there we go. Here's a DV stream, straight off a camera.

One seed, two seed, red seed, blue seed. You can play that. Here's some more interesting things we can do. Here's a flash animation, an SWF file. Oh, you got mouse rollovers? You know, the app doesn't know anything from mouse rollovers. No big deal. Here's an RTSP file that, let's see what's playing on BBC World.

This is always a risk because you don't know what's playing on BBC World. Some horrible tragedy that happened today, I don't know. Now streaming is interesting because you come in not at a given rate. So you end up with gray and then it comes blue. So there's the BBC.

Here's one of those really cool Matthew movies that he set up. If anybody saw that demo, it's kind of fun. It's a calculator in a movie. Let's take the tangent of that. I don't know how he does the trig functions, because we don't have wired actions for trig functions. He must be rotating sprites or something. I don't know.

That's insane. And here is what I feel is the key feature of QuickTime 4.1. Something people have been asking for for a long time. This is huge, so this app doesn't really know how to scale very well. I can scale it down by half so you can see it. This is a TIFF fax. We finally support in QuickTime 4.1.

This is kind of an interesting patent if you read this here. It's a three-zone bed cover with an inflatable human form. If you could see farther down, it actually says that that's for security reasons, so some burglar would actually think there's more than one of you there. I don't know. There's a lot of TIFF faxes at the patent office, you will find. We can go back to slides. Thank you.

And with that, I'd like to introduce you to Sam Bushell. He actually wrote the TIFF Facts Importer, so you can thank him for that. Welcome, Sam. Thank you. Good morning. Do you appreciate TIFF Facts? I'm glad you care. Tom and Greg have talked about using QuickTime on various platforms. I'd like to talk about QuickTime as a platform itself. QuickTime is a platform for doing stuff with media.

and David In my words. So if you have some media technology and you bring it into QuickTime, you gain interoperability with hundreds of existing applications. The way you extend QuickTime is by writing components, and that's what I'm going to talk to you about. So first let's survey some component types that are pretty important.

If you've developed a media compression technology which you'd like to support within QuickTime, then the way you do that is by implementing a compressor and decompressor component pair to implement it. Now, your compressed data will automatically be stored using the QuickTime file format. All you have to deal with is the tiny step of moving between the sound or video and your compressed data.

If you write the compressor, then it will appear in all of the standard compression dialogs for that media type. For streaming, there are two important component types at this level. There's packetizer components, which break out compressed media data into packets that can be sent over the wire. And then there's reassembler components, which combine those packets back into media samples which are ready for decompression.

Now, you don't necessarily have to write those. QuickTime is able to stream your content without you having a custom packetizer and reassembler. But in that situation, you don't get any codec-specific resilience to data loss. For example, if you're watching a video stream and you lose one packet out of a video frame, then the user doesn't get to see that entire video frame or any subsequent frames until the next keyframe. So that's a big loss. On the other hand, if you devise an RTP payload format that can incorporate some cleverness that's specific to your data format and is able to recover from some packet loss, then you can implement a packetizer and reassembler pair to make that work.

Still image is my favorite. QuickTime's model for still image support on the import side is split into two pieces: graphics importers, which handle the specifics of file formats, and image decompressors, which handle the specifics of the compressed media data inside them. Now, graphics importers have taken off as a platform in themselves.

You'll see a lot of applications which list the file formats they support as these 12 plus any other that QuickTime supports. By writing a graphics importer for your file format, you insert yourself into all of these applications. The situation is similar with graphics exporters, although there are fewer applications that are interested in writing files than there are that read them.

When writing graphics exporters, you have the choice of whether you keep your compression technology inside the graphics exporter or whether you package it inside a separate image compressor. If it's inside the image compressor, then that will appear in all of the standard compression dialogs. It's up to you whether that's the way you want to go. For instance, we don't think it's a sensible idea to have Mac Paint appear in the static video compression dialog, because not many people want to have one-bit 7x11 movies. It just isn't a very popular format.

People often start thinking of QuickTime's movie import components as file translators. Start off with an XYZ file, write out a movie file, but they're actually a whole lot cooler than that, as Greg demonstrated. A movie import component simply needs to be able to parse some file and identify where the compressed media samples are in that file, and then create a movie header in memory that references those samples inside the file. Once you've done that, QuickTime can play the movie straight out of that original file. This is called import in place, and it's why you can take an animated GIF or an AVI file and open it in simple text or a simple app like that.

Writing video effects is a lot of fun and it's pretty easy. We have lots of samples. I'll show you a demo of a really cool third-party video effect in just a moment. Now, media handler components are the part of QuickTime that implement individual tracks inside a movie. If you have a time-based media technology which doesn't fit into the existing models that the existing track types in QuickTime handle, you can implement it in a custom media handler. An example of that is PuppetTime.

If your company develops hardware that can bring media into the computer or play it back out of the computer, then you'd write one of these components to enable QuickTime applications to take advantage of it. A particularly important one of these is the bottom one, Video Digitizers. I should point out for those of you who are interested in Video Digitizers that there is a Birds of a Feather session tonight at 6:30 p.m.

I believe the room is A1 or A2, but there'll be people standing around there that look like QuickTime engineers and people who are

[Transcript missing]

Some of the component interfaces inside QuickTime involve an awful lot of fairly dull bookkeeping details that don't relate to every implementation. To let you focus on the piece where you add value, we've implemented a collection of base components which handle the most common details for you. In some cases, it's very hard to get these details correct by yourself.

For example, the base image decompressor helps you handle asynchronous queued schedule decompression Without handling the queue yourself, we look after that. We look after all of the reentrancy, the race conditions, and mutex protection for the queue, and a bunch of other related issues. We found that we could get rid of a lot of bugs in QuickTime when we switched over a bunch of our other image decompressor components to use the base codec. So if you're going to write any of these components, please start with the base components for these categories. You will save yourself a lot of strife. And now, I'm going to demonstrate some cool third-party things.

[Transcript missing]

It has a little bit of audio in it. And with QuickTime Player, I can choose export movie to QuickTime movie and then select a filter and you get a preview here. It's definitely installed, but it's not real time. It's actually quite slow. So I've did this movie ahead of time so that you can get to enjoy it.

This video effect was developed by the same people responsible for some of the special effects in the movie What Dreams May Come. It's a really phenomenal visual thing to look at. And so they decided to make it available to general customers of people using QuickTime and a few other apps for the

[Transcript missing]

So, okay, there's a video effect being used by a QuickTime application. You can extend QuickTime. That's interesting.

Here's another situation. Here's a file format from a company called BitJazz. The file format is called PhotoJazz. It's a lossless compression format for pictures. It's fairly expressive. These are all the same picture, so you don't get to see much difference between them. There's a Photoshop version, a Ping version, and the PhotoJazz version. And their big deal is that they claim to do better compression than everyone else. They're certainly a lot smaller than the parrot in Photoshop. They're a good one.

[Transcript missing]

But if your business is developing a file format or compression technology, it's a tough job if you have to go and talk to individual application developers just to get them to support it. These guys wrote the QuickTime components to support this, a graphics importer and a graphics exporter, and they have different levels of graphics exporter that you can-- of writing support that you can get by paying them different amounts of money. But everyone gets the viewer for free, as you see. So that's PhotoJazz running inside PictureViewer. In each case, this is just extending a QuickTime application, which is often the way we demonstrate things because, well, they're the applications that we're familiar with.

What's rather more interesting for users is where they're taking a third-party application and having that application's power extended by...

[Transcript missing]

Painting uses QuickTime video effects as filters. And so I can choose Video Go here, and one of the other choices besides oil painting is chalk. This is going to give you an idea of why it's not really real time for doing a video effect. It takes a moment, but it's a great effect.

So here we have a third-party application and two different third-party components all working together. I don't believe, or I don't know, but there's no sign that any of these individual third-party vendors had to communicate with each other in order to establish a standard. Just the involvement of QuickTime here has enabled them to work together. I think that's neat.

So let's talk about writing your own components now that you've seen what the competition can do. There's an awful lot of sample code on the QuickTime developer website, which does include a wide variety of sample components. They're sometimes a little bit buried, and you may have to try several before you find the right one for what you're trying to do. Rather than discuss these individual samples, I'm going to talk about some of the key concepts that are absolutely important for any kind of component that you want to develop.

First of all, I'm going to talk about component dispatches. Now, conceptually, a component is a cohesive module of code that works for a particular purpose, like a Tiff Fax graphics importer. Each component has a single entry point, known as the dispatcher, and it knows about the functions that are implemented by that component, and it knows how to route the calls that come in to those components. Now, notice that the functions on this All have numbers next to them. These numbers are called selectors. Negative selectors are common to all component types. Non-negative ones, that's zero and positive numbers, are specific to the component type you're dealing with, and sometimes the component subtype.

The four top ones you see here are component functions that have to be implemented by every component. They're open, which allocates storage for your component and anything else that you need. Close, which gets rid of it. Can do, which finds out whether a particular selector is implemented by your component. And version, for determining the difference between-- for establishing the version of your component, in case someone needs to know that.

So the job of the dispatcher is to know the relationship between a number and a function, and to call the right one at the right time. It doesn't seem like a big deal. Unfortunately, it's a nuisance. It's easy to get wrong. There are fiddly details that are different on different platforms.

We have a tool that helps address these problems called Component Dispatch Helper. That's what we use internally for writing almost all of our QuickTime components. And it isn't perfect, but it's well used. And it does generate both the dispatcher and the can do from a single list, so they don't get out of sync. It's also faster and more robust than doing it by hand once you've got the hang of it.

So it is also demonstrated by some of the pieces of sample code, although the sample code also demonstrates alternatives to using it. So I'm not going to explain how to use it in great detail, but it's very useful to be able to

[Transcript missing]

Now, if your component doesn't implement some selectors, you still need to put empty slots there so that functions with later selectors go into the right slots in the table.

The component dispatch helper, because of the limitations of macros in C, doesn't protect you from that kind of stuff. So you need to be a little bit careful and need to have in mind what this is actually doing when you use it. But if you do, you should probably be okay.

Let's also talk about the way we describe components. There's a resource called the THNG resource, or the Thing resource. Now, a little bit of history. The component manager was originally called the Thing Manager. and Component instances were Thing instances. Legend has it that Apple's technical writers found it too hard to write meaningful documentation about Things and begged the engineering team to call them Components instead.

Who knows Let's have a look at a Thing resource for a 68k component, a classic type. We have fields that have the type, subtype, and manufacturer codes. There's four character codes. We have a flags field. We have resource type and IDs that identify the code resource and some strings. And there's some other stuff in there that I've omitted for clarity. Note that the first byte of the code resource is the entry point here. Every time you make a component call on a 68K component, it'll JSR to that.

We don't use the code resource field for PowerPC components. Instead, we added something back years ago, which was an extension called the Component Platform Array. You can actually have a single thing resource that describes the code to be used on multiple platforms, and the component manager chooses the right one when it registers that component. So, if you have the Component Platform Array, you have to set a bit called hasMultiplePlatforms. Even if there's only one, it's a rather poorly named constant. We admit that, but there's not much we can do to change it in the past now.

Also note that the flags have been moved down from where they were to part of the component platform array. This means that different component implementations, different code on different platforms, can actually have different flags, which is sometimes a useful property. So in this case, the code resource is a PowerPC PEF container with a routine descriptor-- sorry, the main entry point for that PEF container is a routine descriptor that's wrapped around the dispatcher.

What about Mac OS X? Well, I've just moved the diagram across. This is the same as you were seeing on the previous slide. I've just chopped off the top bit. On Mac OS X, there are two linkage models. There's the Code Fragment Manager, and there's also Maco, the Mac object format. However, Mac OS X does not support code and code resources. It has to be in the data fork somehow.

For CFM, the code is in a PEF container inside the data fork, and it's described by a CFRAG resource. Now, you can have multiple PEF containers in a single data fork, so you don't have to have a proliferation of files, but you have a single CFRAG resource that describes them all. And the number that is normally a resource ID is actually a tag that has to match a field inside, an entry inside that extended CFRAG resource.

With Marco, the entry point is identified by a symbol name, and so the symbol name is stored in a string resource with type DLLE. Now, since the namespace for Marco symbols is flat, you should take care to give your entry point a distinctive name. Otherwise, you might have the situation where two different vendors both chose my component entry point, and the results of a collision like that would be highly unpleasant. Also note that there are no routine descriptors on Mac OS X. In both cases here, the entry point is the dispatcher itself, not RAT. Accordingly, the platform type has changed from PowerPC to PowerPC native entry point.

Let's go over that again. On Mac OS X, the entry point is not wrapped in a routine descriptor. And the platform type is PowerPC native entry point. Another thing, CarbonLib components. Components should only link to CarbonLib on Mac OS X, not on Mac OS 9. It turns out that the CarbonLib extension on Mac OS 8 and 9 currently only provides support for applications and some plug-ins, not for general components. There are some technical reasons behind that.

If you want to deliver a single file that your users can use on each platform, however, you can. Your thing resources would have two component platforms in the component platform array, and one of them would be PowerPC platform, which would link to InterfaceLib and have a routine descriptor, and one of them would be one for 10, which would say PowerPC native entry point, have no routine descriptor, and be in the data fork. and link to CovenLib. Also note that the DLLE, you might have guessed by the name, the mechanism that we use on Mac OS is the same as we use on Windows. So if you're familiar with one side, the other side should be pretty easy.

In some situations, you need to register your component twice. For example, if you want to write a graphics importer or a movie importer, the component subtype for that component might be interpreted as a file type, or you could set a bit that said it should be interpreted as a file name suffix. You probably want people to be able to open your files if they have one of those right, but not the other, in which case you need to register your component twice so that the lookups both work correctly.

There's a good shorthand for doing this called a component alias. It's slightly more efficient than having two thing resources that both describe the same code. It basically tells the component manager to register a second component with the same code as the first, but with a different subtype or different flags.

So what happens when things go wrong when you're working on these components? If your component doesn't load initially, first thing to ask is, did it get registered okay? You could write some code like this and run it, or you could use one of the tools that I'll If you've established that the component is registered, you should find out whether it actually executes. You could set a breakpoint in your open routine and run some code like this.

The usual things that go wrong when we're working on components, we find that people often forget the hasMultiplePlatforms bit, partly because it had that poor name. This flag really means this is not a 68K component, so you need to set this bit for practically all components you write now. If this bit isn't set, that'll prevent the component from registering.

Now, other problems that occur where the component gets to register, but it can't ever be opened. Basically, troubleshooting these involves working from the thing resource through to your code and making sure that all the steps along the way are correctly set up. That the resource ID in the thing resource points to the DLE string, and that that has a name that matches the next step and so forth, and that the entry point that's in that string is exported from your library.

So there are a few tools which are very useful for browsing the components that are installed on a computer. I'm going to demonstrate a couple of these in a moment. The free one is MaxBug. Every version of MaxBug that you can use with current versions of Mac OS 9 has a built-in debugger command called Thing.

I'll show you that in a sec. There are also a couple of nice shareware tools with graphical interfaces. There's one that's new today, I think. It's certainly new this week, called Thing Detective. There's a free subversion called Thing Reporter from Unthinkable Research. There's also, I think, Thing from Tactic Software.

Before I show you those tools, I'd like to mention another thing that's very useful when you're actually working on a component. It's very annoying if you have to restart every time you make a change in the code and recompile and rebuild. Instead, if you drag your component onto a small application called Reinstaller, Reinstaller 3 at the moment, it will unregister the previous version of your component and register the new one in its place. You don't need to restart to make that work. And I will demonstrate that as well, because I have plenty of time. So, let's go and have a look at some of these things. Down here we have Thing Detective from Unthinkable Research.

There are a lot of components installed in this machine. And you can -- this is a nice graphical view of them. They all have a name, or most of them have a name. They have a type. Subtype, and you can sort by all of these things. Let's go and see if we can find the components that we were playing with earlier. Let's look for PhotoJazz. Here we are.

Here's the graphics exporter component. Let's keep going down and find the graphics importer. Here we are. So let's see what it can tell us about this. It tells us the type, subtype, and manufacturer. It says there aren't currently any instances. If I went and opened that in Picture Viewer, this number would change to 1.

can also tell us about the file it came from. It can tell us information about the Thing resource. It's actually found a bug. It's actually found that the icon resources are missing or perhaps should just not be listed. I don't actually recommend that you store icons inside your Thing resources. They're mostly a waste of space in the file. They're not used by many parts of the browsing applications. You can if you want.

But it doesn't make any difference. This is a totally benign problem. There's also something we added in QuickTime 4.0 called public resource maps. These are a way of attaching extra information to components. There are a few places where this is nice. It basically lets us make some of the APIs much faster, such as the dialog that came up that showed the QuickTime effects. It's faster for it to build that list because it can work out the names and the properties of individual video effects without having to load and open each one in turn.

If you can just pull information out using the component resource map, the component public resource map, then that's a lot faster. We can also browse the flags that this component has set, and it knows about some of these by name, which is rather neat. It can also run the can do function on the component to see which things it supports, and you can see this supports all of the required selectors and one that's not required. And here are all of the ones that are specific to graphics importers.

and What are component aliases? You can also tell us a bit about them. Here, this component is a second alias. You notice the subtype for the first one was j little z, little z space. This one is in uppercase, and there's a bit that's set in the

[Transcript missing]

So it's the second alias to the first component. So this is a component alias, and you can tell here, and here's the component that it's an alias to.

So this is a way of going through and checking that your component is correctly set up and that it's saying all of the things that you think it should. It's a nice way to be able to interact with your software. Thing Detective is available now. You can go to the website at www.unthinkable.com. There's the plug. We also have some image decompressors. I said that video filters were implemented as a special case of decompressors. And here's the Video Go one from Revision Effects.

So that's the nice, pretty view. If you're a programmer, or you happen to-- if you're a programmer, and you know how to use maxbug, and you're not frightened by it, then there is the alternative that I mentioned, using the thingd command. I'm going to drop into maxbug now. Don't be afraid.

Okay, I can print out a list of the components that are here. There's a lot of them, so I'd have to page through. I can also type thing and then one particular component type just to print out, for instance, let's print out the RTP reassembler components. They're the ones that are installed on this computer. I can print out a list of the open components by saying thing-o, and here you see that there are a few components that are open. Oh, I must have MoviePlayer running.

There's some help in the dcommand help for that. It's obviously nicer to use a graphical view for some things, but if you happen to be crashed and you're working out why, it's very useful to have the thing dcommand as well. Let's leave this line installed there. Let's talk about while you're debugging a new component.

I have here one of the sample components on the website. It's a set of graphics importer, movie importer, and image decompressor for a file format called Electric Image. And I've modified this slightly. I've put all of the components that were pre-built into one file, and I've also changed their names to have spaces so that you'll see them in the window behind me. But first of all, let's bring up QuickTime Player. Oh, it's the same one. Cool. And let's try opening...

[Transcript missing]

What a fun file format this is.

You'll also notice that these components have all appeared in this list. And if we would watch the open instances, these numbers would probably have jumped up and down as well. So that's a great way of confirming that things are basically working well. And to some extent, it can help you with troubleshooting. I think that's all I can think of with those.

So, let's summarize. We seem to be early in Tom was talking about Mac OS X, and basically not much has changed. A few things that you need to clean up as part of your carbonization of your application aren't a big deal. Greg pointed out some of the APIs that we had that were added in QuickTime 4.1. While you're carbonizing your application, it's a good time to have a look at those and see if you'd like to support 64-bit file offsets, VBR sound if you're a sound app, and certainly URL capabilities in your app. Those can be a lot of fun.

We have a QuickTime feedback forum. We don't tend to do Q&A in QuickTime sessions because one person's question tends to be interesting to about 10% of the audience, not 90%. However, for those of you who are really interested in hearing what other people have to complain about, I recommend that you come along to the QuickTime feedback forum. It's today. It's at 3:00 or 3:30 p.m. in Room J1. And it'll be a lot of fun. There'll be lots of people on the stage and under the big spotlight.

The QuickTime API mailing list is a great resource for asking questions or having other kinds of discussion about API-level programming issues. There are a number of QuickTime engineers who read the list, and when we have time, we sometimes reply to things. Sometimes we don't have time, or sometimes people don't ask in very polite manners.

But If you're lucky, even if one of us doesn't have the time, another developer will have been down the same path as you're trying to tread, and they can help you out as well. So it's got a nice community. Some of the things that... Some of the specific things that you'd like to find out can be found in the Iceflow notes. There's a whole lot of stuff on the QuickTime developer section of Apple's websites.

There's all of the sample code, there's all of the tech pubs, there's tech notes. There's also the QuickTime engineering team's ice flow notes, which are extremely condensed bits of information about specific issues that we think are really important or perhaps have a very strong focus for some group of developers.

There's also a PDF file on the web, which we seem to mention every session, about the new things in QuickTime 4.1. It's not that hard to find. You should go and look. If you get to the QuickTime roadmap, I think there's a red link to go to the PDF, and I heartily recommend it. It's grand. But I think that's it. I think we're done. I look forward to seeing you at the feedback forum. Thank you.