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: wwdc2002-510
$eventId
ID of event: wwdc2002
$eventContentId
ID of session without event part: 510
$eventShortId
Shortened ID of event: wwdc02
$year
Year of session: 2002
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC02 • Session 510

Printing and Mac OS X

Digital Media • 1:06:57

Apple continues to enhance Mac OS X printing with exciting new features. This session is a comprehensive update on its new features and capabilities. Highlights include the integration of the Mac OS X printing architecture and the Common UNIX Printing System (CUPS). The latest printing UI enhancements and changes to the printing APIs are also discussed.

Speakers: Richard Blanchard, Paul Danbold

Unlisted on Apple Developer site

Transcript

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

Good morning, everyone. Welcome to Session 510, which is printing and Mac OS X. Hopefully you caught the big news that one of the things we're doing in Jaguar is actually replacing a significant part of the printing architecture. A little bit of that was talked about very briefly in the keynote, and we went into great detail at yesterday's Darwin printing session where we really went into detail on the Common Unix printing system, which is going to be the new sort of underpinnings of Mac OS X's printing architecture.

What we wanted to do in today's session is really look at framing how this large architectural change is going to impact developers. In many ways, it's positive. You're not going to have to do much renovation of your existing printing code, if at all, or your driver code. They should just work.

And you'll hear that reinforced several times during today's presentation. Additionally, we want to expose you to the new possibilities that are capable with CUPS, and we'll end Mac OS X, so we'll do that today. But one thing I want to make clear is, one of the reasons why we did this, it's a pretty drastic change in an operating system that's a little over a year old.

And one of the reasons it was done was because we got an incredible amount of feedback on the printing architecture last year after the WWDC printing session. And that feedback was clear that developers wanted to get access to the internals of the printing system. We had applications able to print. We had a defined driver architecture. So for common printing tasks in Mac OS X, it was basically a complete picture.

But what we were really surprised to find is the number of developers who wanted to add value into the printing system. And we feel we've accomplished that by moving to a completely open architecture. So what I'd like to do is welcome Rich Blanchard, the engineering manager for printing, on stage to take you through the presentation. Thank you.

Thank you, Travis. I appreciate it. I wanted to start today by thanking all of you developers for I think what Travis called feedback over the last year and a half about printing. Your feedback comes to us in many different ways. A lot of times it's radar. Sometimes it's through DTS. But all of that comes to us, and we do read it all. In fact, every month, I go over all the bugs we have open outstanding, and I make sure they have the right classification, they're nailed in the right release.

And as I do that, since I've been doing that for so long, I come up with a system. And part of that system is as I skim through the bugs, I have this big questions list. And a bug can make it in the big questions list by meeting two criteria. One, that bug, in order to address it, must require significant infrastructure or architectural changes. Two, all the big questions have to be independent. So I built up this list.

It's about 20 right now. And I wanted to give you some examples of those big questions. I'm also going to thank you because you're all so very polite when you give us this feedback. Although sometimes it's phrased somewhat pointedly, and I wanted to give you an example of some of that.

For example, OS 9 has USB printer sharing. OS X, the most advanced operating system in the world, does not. What are you guys doing? So it's pretty pointed. Two, Apple is marketing OS X as a UNIX well integrated with a professional user interface. Except when you print. If you go to the command line and you try and print, you can't print to the same printer as you can print to from your Cocoa and Carbon applications. So again, fairly pointed feedback. Some other feedback comes from people who are trying to move applications over to OS X.

We've had a lot of feedback from accounting people. They say, "Okay, can you just point us to the place where you log all the files you print?" And my first answer is, "Yeah, that's dev null." But we actually don't log that stuff. And so I don't have a good answer there. So, you know, you nod your head and you go, "Yeah, you're right." And I put it in that big questions pile.

And a lot of PostScript interpreters. "Hey, where do I put my PostScript interpreter in the system so that it's part of the printing path?" We actually have some hand wave answers for this. Well, you kind of read this printer module and maybe an IO module over here. I don't know anybody who succeeded in doing it, and that's our fault. We haven't really given you a good answer.

So I look at this list of big questions, and once I can lift my head back up and not be too depressed, I decide, okay, we'll go back to the beginning. What are the goals for our print system? What do we really want out of it? And one of the goals is we want our printing APIs and our printing system to survive.

Okay, that's kind of a low bar, I know, but I think some of you with not really even great memories can probably remember a couple of Apple print systems that maybe haven't survived. You can even look at Java. Java is on the second generation of their print APIs.

So not all printing APIs do survive. And when they don't survive, when they fail, they take a bunch of applications with them, and it's incredibly painful. So lowest bar, hey, we need to survive. But, of course, we want to do more than that, right? We want to thrive. We want to have an application -- or, I'm sorry, a print system that your applications can get all the features they need in order to make both of our customers happy. Not both of our customers. The customers that both of us share happy.

Will the two customers please raise your hands? But we want to thrive. We also want an architecture that's -- clear enough that you can write middleware pieces and figure out where they fit in and how you can expand our print system. That's important. And one that's attractive enough so printer manufacturers will want to write printer drivers for OS X.

So those are the goals. So we have this big list of big questions. God, how are we going to solve that? And we have these really basic goals. And it became pretty clear that the only way we were going to answer those big questions and stay true to those goals was by making very drastic changes. Scary changes. Okay? Big changes. And that's what the rest of my talk is about today. These big changes. We're putting a new print spooler in the system. Really simple, clear statement.

Not really that scary. Until you realize that's the back half of printing. So I'm telling you we're replacing half of printing. We're making dramatic changes to the user interface. I think the user interface is the front quarter of printing. So we're dramatically changing the front quarter and replacing the back half, but everything else.

But that everything else, we like a lot of things. The current print system, there are things in there we like a lot and there are things in there we're very, very proud of. And those things are not changing. And so while this is a dramatic change, it's important to hold on to that fact that there's a lot there we really like.

And the pieces we really like the most out of the current printing system actually come from you. They're your applications and they're your printer modules to sort your printer drivers. So even though we're making these changes, compatibility is key. We didn't want to break your applications and your printer modules. I know you guys love learning APIs, but... So we're extending our APIs. We're not replacing them.

Print dialog extensions, your printer modules continue to work. And to show you how much we care about those existing APIs, we've expended a lot of engineering time working with a really great technical publications team to correct, clarify, and extend the existing printing documentation. And thanks to DTS, you can go to developer.apple.com/printing. It's easy to remember now. And you'll see all these links to all the new documentation. And we have more coming. So we're making big changes. Your APIs will keep working. Your applications will keep working. And we've even invested further in those APIs for you.

So I wanted to go into depth a little bit more on exactly what those changes are. So the new print spooler you probably found out is the Common UNIX Printing System, CUPS, Easy Software Products, is the creator. So why CUPS? Why a new print spooler? Well, it gives us those big answers that we needed.

Printer sharing comes with CUPS. So once we put CUPS in the system, as it is on the CDs that you have now with Jaguar, you can share between two OS X machines printers. This guy can print to this guy's printer. We had a great wireless demo on Tuesday, I believe.

Command line integration is another one of the big answers. With CUPS in the system, you can go to the command line and you can LPR to the exact same printers you can see from your Cocoa and Carbon applications. They're equal, which is very nice. Accounting is there. You can actually go read a real file instead of a device and get the pages that have been printed, who printed them, when, how long it took.

And RIP support. We have a very, very specific answer for where a PostScript RIP sits in our system. In fact, we remove a PostScript RIP in order to deliver OS X. So there's this hole that you don't have to be that creative to figure out, hey, maybe that's where the PostScript RIP goes.

We had some other goals. We wanted to be a better team player. We understand that Macs are going to be living in environments that are not just Mac only. So we wanted to work better in educational labs, better in corporations, better in publishing houses, and we wanted to be more transparent.

As much as I like talking to you each year, you need to get information more than once a year. And so we want to be transparent so you can see what we're doing throughout that year and not have to wait until this incredible day. So we support standards. That's the number one way we're going to fit in better. CUPS supports out of the box the Internet Printing Protocol, IPP. It's an open standard from the printer working group of the IEEE. It's an IETF standard as well.

So you can go there, you can get that standard, you can download it, and you go, "Okay, this is what Apple's trying to put on the wire when they're communicating between their two boxes." So when doing printer sharing, we're trying to use IPP. There's the standard. Hey, look, they're not doing it. You can nail us on it because there's a well-defined documentation for it.

We continue to use PostScript printer description files. It's an Adobe standard for describing printer capabilities. It's a big part of CUPS. It's used for PostScript printers and non-PostScript printers in CUPS. We use that again. You can go to someplace outside of Apple, read some documentation, go, "Okay, that's what they're trying to do." Well, how are we going to be well understood? How can we be transparent? Well, CUPS is open source.

It's released under the GNU General Public License. You can get it from Easy Software from CUPS.org. You can get it from our Darwin repository. And the great thing about the Darwin repository is that's our repository. As we make changes for Jaguar, when we check in a change as we work day to day, it goes right into that repository. You can see every day what we're doing with our print spooler.

So there shouldn't be too many surprises. Maybe you can even tell us, "Hey, you know that stuff you checked in yesterday? You may want to check it out." So that's important. We're also widely used on Linux systems. CUPS is widely used on Linux systems. It's also buildable and usable on Solaris, AIX, FreeBSD, a lot of different UNIXs.

An important part there is you can actually go to somebody other than Apple and say, "Hey, you know, how does this CUPS thing work?" Because there are people out there who are experts who are not us. And we're happy to answer the questions, but if you post to a news group, maybe we're not going to get to it. Or maybe you need to hire a consultant. They're out there. There are people out there who understand our print system that is not us.

So to help you understand our print system, I wanted to show you where we're coming from and where we are today. This is a slide we've been showing substantially unchanged for several years now. This is the 10.1 printing system. It was also the 10.0 printing system. You can see your application on the left side of it. Print server's in the middle. It's sort of where the bull's-eye is. We're going to get to that. It's going to be disappearing here in a minute. And then the print job manager, which hosts your printer modules and your IO modules.

So bang, print server's gone. We have CUPS there in the middle of the system, back end of the system. There's one other subtle change as we went from that slide to this slide. In the previous 10.1 system, what you used to submit normally was a PDF file to the print server. And along with that came an Apple job ticket. That's different with CUPS now. You get the PDF file and you get a set of IPP, Internet Printing Protocol attributes. So there's a subtle change there.

Brand new print spooler. So to break that down a little further, this was Michael Sweet, the author of CUPS, went over this pretty well yesterday in the Darwin printing session. But when you print with the CUPS daemon, CUPS server, it generates a print server. And it's a printer that's going to print. And it's going to print a print chain of processes in order to print.

And that print chain is generally talked about as a triplet. There's a filter to do file conversions from the file type that came in, in our case, PDF, to the file type you want to have go out. There's a CUPS driver. That's the last stage of the filtering. It kind of gets the data ready for the printer. And then there's a back end, which actually does the communication.

But of course we are also supporting your printer module so these pieces still stay. PrintJobManager still exists for those of you who have had to write print modules and know how that works in your I/O modules. It's still housed by PrintJobManager. So I wanted to give you a quick walk through of what happens from your application down to your printer modules when you print. We'll assume your application is Carbon. And for this example, we're going to assume that your printer is a PostScript AppleTalk printer. So your Carbon application probably is going to draw with Quick Draw.

When it does, we convert that into Quartz drawing commands, and that gets spooled as PDF. So even though you're drawing Quick Draw, our spool files, unless you do something special, our spool files are all PDF, which is important. We take all the settings that come out of the print dialog, convert them into IPP attributes, and then we take those two pieces of information and we hand them to the server.

Server, CUPS, looks at this and goes, "Hey, wow, I've got PDF. The printer you're targeting is PostScript. I've got to get from PDF to PostScript. So what am I going to do?" And it looks through the system, and on OS X it finds a piece of quartz technology that can convert PDF to PostScript.

So it runs that and it hands it the file and says, "Hey, I need you to convert this to PostScript." It starts running and it writes to its standard out a PostScript stream. It's not a device-ready PostScript stream, but it's a PostScript stream with all the drawing commands.

CUPS also said, "Hey, well, I need somebody who can make it device-ready." So attached to the standard out of that converter, I'm going to put another process that knows how to take that PostScript stream and make it device-ready, insert the feature code to ask for duplex, copies, and all those sort of things. And then the last step, "Hey, I need to talk to an AppleTalk printer.

So I need some piece that knows how to talk Pap." So I'm going to run a third process. It's reading his standard in, which is the device-ready PostScript, and is writing to the printer. So this is the print chain. That's how you get from your Quick Draw all the way down to PostScript going to a Pap printer.

So, you all caught those three slides? This is the compatibility story. The compatibility story when you print will go from a Cocoa application this time. Now you're using NS drawing commands. Again, that gets captured as Quartz drawing commands and spooled as PDF. The PDF goes to disk. We take the print settings that come out of the print dialer. We turn them into IPP attributes. We hand them to the print spooler.

Same story, a very similar story to the Carbon Printing System. But now CUPS is going to look at it and go, "Oh, well, now you want to talk to a printer that's hosted by a printer module that was written, say, for 10.1 or 10.0." So what does it have to do? Well, it has to run a filter just like it does before. And we've made PrintJobManager look like a filter for CUPS.

So the PDF file gets handed to PrintJobManager and he does what he's always done, run the printer module, run a converter, run an I/O module. So that's why everything continues to work for printer The abilities of CUPS are pretty incredible. It does a lot of things. And it's important that you understand we're not going to bring out all those things, certainly not in Jaguar, and my suspicion is not ever.

We're going to target our customers. What is the feature set that makes the most sense for our customers? But it's important that you understand what features we're not bringing out now and may not ever bring out. But CUPS has authentication, it has encryption, it supports quotas, it supports printer classes, which are groups of printers which look like one printer to everybody else on the net. And it has a web administration.

The first set of those things we're just not going to support right now in Jaguar. If you change CUPS underneath us to enable those things, our UI and everything still works. So we're compatible with them, but we're not going to put in UI to enable any of this.

Web administration is a little different. We're also not putting in UI to say, "Okay, here's how you get to the web administration," but it's there. If you're on a system, you can fire up Explorer, you can connect to the IPP port, and you can get a web page that shows you all the printers, their current status, and that is there. It's great for remote administration, that kind of thing.

So the best way to understand CUPS, understand what's in there, what we're using and what we're not using is, and I sold this too hard yesterday so I'm going to sell it a little softly today. You must buy this book if you want to understand Darwin printing or OS X printing. That was a little softer than yesterday. This is a great book. It's written by Michael Sweet. He's the architect of CUPS. It explains the internet printing protocol better than anywhere else I've ever found.

Better than anywhere else I've looked a lot. You should watch the Darwin session. Michael Sweet, again the architect of CUPS, gave the Darwin printing session yesterday tons of information. I told him his job was to overload the people in the audience. I think he did. Just tons of information. There's online documentation. It's at CUPS.org. It's also on your Jaguar CDs.

And read the code. Again, we're open source. And it's a hard thing to get your mind around this whole open source concept. The concept that you can see exactly what we do every day with our spooler. The concept that you can actually go fix bugs and instead of just giving us the bug report, go here's the bug report and here's the fix. So we want you to get your head around that. It's taken me a while.

But some people just get it. And I wanted to give a quick example of somebody who got it. This is Global Graphics. They saw the announcement from Easy Software back in March and said, hey, Apple has licensed our stuff. Now, Apple, we didn't want to announce this until the WWDC, so there's this hole between March and now.

But these guys guessed that maybe we were going to announce something sometime, so they went and they downloaded CUPS. And we had been working with the CUPS folks, so it built on OS X already. So back in March, you could build it on OS X. So they downloaded it, built it. Said, hey, we've got these PostScript pieces. We have pieces that convert PostScript to PDF and PostScript to raster. So maybe we can move that to OS X. So they moved it to OS X. And they said, well, maybe we can plug it into CUPS.

And they plugged it into CUPS, and all of a sudden, they had a PostScript rip in a CUPS system running on OS X. There was no UI for it, right, because they didn't have our pieces. They did this completely independently. But they completely understood the open source thing, got it, and built everything. And, you know, OS X is built upon Unix.

So if you have some Unix software, it's easy to port. CUPS has great documentation, and it's easy to understand. And, you know, with those two messages, maybe you might think it would take them less than two days in order to get a PostScript rip onto our system. But two days is what it took them. Fairly impressive. And the result is you can actually print to a raster printer a PostScript file from Global Graphics. So I wanted to really applaud these guys because they got it, and they did it quickly.

So how do you get it, and how do you do it quickly? So, if you go look in the code, there is a configuration file, cubsd.conf, that has a lot of comments and all the switches for the print spooler. And you can go in there and read it and immediately understand all the different things you can and cannot do with the spooler. So it's a great place to start.

Filters, you can go look at the documentation for filters and figure out how to plug in some technology you have. It might not be a PostScript RIP. It might be a Microsoft Word converter. It might be some strange graphics format converter. Whatever you like, it's an easy way to get things into the print system.

CUPS has a lot of different logs. If you want to present that kind of information to the user, there's accounting logs, there's error logs, access logs. The access log is kind of interesting because it's actually in common log format. So if you have analog or any of those other tools, you can actually read it and generate HTML reports right out the back door.

The last piece is GIMP print. It's actually not in the CUPS source code, but it's a sister project, if you will. It's a set of open source printer drivers. You go out there, they split up 300 printers. We've worked with them as well. If you download that project, it will build now on OS X, and it will work with CUPS. So it's a pretty good story. And if you have drivers that you're developing that you'd like to be open source, it's a great project to be involved in.

Places outside of the code to look at, because I think there are a couple of you who might want to go there instead. CUPS.org PWG.org is the printer working group. This is the printer working group of the IEEE. This is where you'll find the IPP specifications. It's a pretty good site. There's a lot of interesting information there and you can see some of the projects that are ongoing.

And of course the GIMP print SourceForge site. So for user interface, we had to make some changes in order to support all this new power that was coming into the system. And what do you do when you get a lot of power? Well, the initial reaction was to do something like this, which take essentially that CUPS configuration file and blast it all out to the user. But we knew we didn't want to do that. Please don't do this. It's not fair to our users. But it does give you some idea of what CUPS can do.

But what did we do? So we revamped Print Center. In fact, we rewrote it. We put in new printer browsers. They're more asynchronous. They behave better. They look better. And earlier in the year, you probably saw, along with iPhoto, we rolled out a new simple print dialog for users, consumer type users, and the concept of printer presets where a manufacturer device can wrap all of his complicated settings. If I'm printing a photo, I want this paper, and it should have this gamma setting, and I should be enhancing this part. You can wrap that all up into one single element that the user can select. So that was the idea behind presets.

So the PrintCenter rewrite took place in Cocoa, and I also want to take a moment to applaud them. So by rewriting it, we were able to shrink the code size by a factor of five, the number of lines of source code, which is pretty incredible, especially when it's more powerful, it does more, and we pick up a lot of the Cocoa features. For instance, you can go in there and now customize, as a user, what you want to see in PrintCenter.

So big hand for Cocoa. They were--it was a terrific thing to work with. And I wanted to show you quickly what PrintCenter looks like, and there are a couple other demos that may work. We'll see. But give you an idea of what can be customized and what our goals were there in PrintCenter.

Here's Print Center. It defaults to a look that's very similar today with the exception of the toolbar. But the idea was a lot of our users are home users. They have maybe one printer. Unlikely they have more than that. And they don't want to be bothered with a lot of the different parts of it. So what we show them is the name of the printer and the status. Simple, nothing going on. But a lot of you, in particular, might want more information.

So, Just like you'd expect from a good Cocoa application, you can customize the toolbar. You can add all sorts of stuff up there and get the tools that you want close This was probably one of the major sources of feedback from you was, "Hey, can you put this button right at the front of PrintCenter? I want to be able to configure right from PrintCenter, right from the start." So with this configuration, you can do it. We also have a lot more information available from PrintCenter.

Get some of this up here. You can see who's hosting a computer because we now have printer sharing. We can tell you where it is. We can tell you what type it is. And if you look here, there are a couple interesting elements. We have a local printer. This is Epson connected right here.

We have a printer that's right next to it that's being shared by the machine right here. And we have another machine that's over at this address 206.14.52.56. That machine's about 100 miles north of here. When I set up this PowerBook, I actually went into the CUPS configuration file. We don't have UI for this.

But I told it, "Hey, I want you not only to look on your local subnet, but I want you to go talk to this Mac OS X machine that's sitting up here in Sonoma and get all its printers." And it happens to be sharing one printer. So we have two local machines and one that's a long way away.

That was the idea behind PrintCenter. I'm going to leave PrintCenter behind very quickly. I want to talk a little bit about the remote printing aspect of it. Cubs, by default, will pull, as I said, the local subnet. And that's pretty powerful, and that's what we're going to bring out in Jaguar. But there is this ability to go out and talk to remote printers.

And I work with my brother, actually, and he's the man who is sitting at a desk right now with that desk jet sitting next to him. And, you know, I love my younger brother. But every once in a while, I need to send him a little message to kind of keep him honest.

So this is the Epson C80, which comes up selected. If I go to the print dialog, select the DeskJet 930, there'll be a small delay here. What's happening right now is we're talking to that machine and we're saying, "Hey, can you tell me about yourself?" And, of course, this delay in a real demo is a little longer than you might like.

There you go. How about that? Okay. So it's talking to the machine, thank God, and it pulls down a PPD that describes that machine. And so what we can do once that information comes back down, we now cache it so we now have it, is we can actually build the real UI for this driver. So even though this is a remote printer, we can present the custom HP UI. I think that's pretty impressive. I like that.

I know I had to beg for it, but I appreciate it. So we'll just print that, and that's now actually heading north, and it'll wake my brother up, and maybe he will get back to work. So I've got one more demo for you here, and this one needs a little bit of background. Printing is in the graphics and imaging group. That's the group that we work in, the printing team. And the other parts of the graphics and imaging group are teams like OpenGL and the Quartz Compositor, the Quartz Xtreme group.

And you've probably seen a lot of their demos. It's kind of tough being in that group because they have great demos and printing, we have to work a little harder. So you kind of get a little small inferiority complex working with them. So what we did for the graphics and imaging overview the other day is we did this wireless printing demo. So there was all this great compositing demos, and then we came along with the wireless printing demo, and I was pretty happy with that. It sort of felt like we held our own.

But then later, there was the compositing session where they had held their really great demos for, and now I really have an inferiority complex. So there is an old circus saying, which is, if the other high wire act has better tricks, you need to raise the wire and remove the net. And that's what we're going to do. I've got a demo for you that nobody inside of Apple or outside of Apple has seen. I'm the only person who's ever seen this. I've seen it work once. Okay? And we're going to try this.

do is open up this Epson here. It's an Epson printer. It's a Raster printer. Start with that. The idea at first was essentially I wrote this during, in between print sessions the last couple days. We've had this request a little bit, which was, hey, you know, why can't I drag, say, a PDF file into a queue so it can print? So this is the old desktop printer type behavior. So we can do that and that would work and you can trust me and people have actually seen that.

But that wasn't enough because of all the great compositing demos. So I took the Global Graphics code that they had sent over our way and what they had in there, one piece they had, could convert PostScript to PDF. So I put that in underneath CUPS and told CUPS about it.

So now CUPS knows, okay, if I got a PDF file, a PostScript file, I can get to PDF. Well, Quartz has a piece already in there that can go from PDF to raster, and then the printer module for the Epson can go the rest of the way. So, conceptually, if we drag a PostScript file into this print queue, it would accept the drop, hand it to CUPS, CUPS would go, "Oh, wow, PostScript." Okay, well, I can get that to PDF and go, "Well, I can use Quartz to go PDF to Epson," and then it will hand it in, and we will print.

So, not this one, it is that one. The status is going to be a little shaky here. I'm not sure I got the status working. Oh, man. Okay, well, like I said, I've seen this work once. And what I'm going to do is just dance here for a moment. Hope the printing comes out.

So was that all very clear, what's actually trying to have happen? Hey, wait a minute. How about that? Okay, here we go. So this is about a 20-page PostScript document. It's cranking out. It's going very quickly because it's a great printer. And PostScript to Raster, which we've never been able to do on the system.

[Transcript missing]

So, just wanted to give you a quick summary so far before I hand off the microphone. We're making big changes in OS X printing. It's very important. It's the principle or it's the user interface. Please, please do not leave this room without the message that we are maintaining compatibility for your applications, for your printer modules, and for your printer dialog extensions. We are trying to make this as easy a change for you as possible given the extent of the changes we're making.

And so I tried to not really scare you, but sort of give you a good grasp of the number of changes that are coming. Paul Danbold is now going to come up here and calm you down, show you the new APIs, show you that they're very similar to the old APIs and that the old APIs still work.

So, Paul? Thank you very much. Okay, thanks Rich. Good morning. And if I can figure out how to change the -- which button do I press? Ah, I have to turn it around the right way. Okay. Which button were you pressing? There we go. Got it. Come on.

All right, as Rich said, I'm going to talk about new APIs, talk a little bit about new sample code, new documentation. Along the way, a few guidelines and words of advice for anybody in the business of producing or consuming print jobs. So we'll start with the new APIs. These are all application APIs.

These are all things relevant for Carbon application developers. In particular, some of the things we're talking about here I think are going to be useful for people who are printing without a print dialog, for people writing printer utilities. And when we come to talk about preset APIs, it's for people who want to take advantage of presets like iPhoto. So we'll start with the no dialog APIs.

If I can get this gadget working. Okay. On 10.1 today, we've got accessor functions for the page format and print settings objects, so you can set up a print job and print it through a print loop without using any print dialogs. There's no way to suppress our spooling dialog when we're generating the spool file.

So it's obviously something we were remiss in addressing. So we've added four new APIs, so-called no-dialog APIs. You can use these instead of the existing print loop APIs. They take the same arguments. Basically, if you call these, you're just telling the printing system, I don't want to see your progress dialog while the job's being generated.

So I'd say use these if your application doesn't use our print dialogs. Also use these if, for example, you want to use a print loop to support a saver's PDF function in your application. You could also use these if you want to generate and display your own progress dialog. But I'd ask you not to do that unless you've got a really good reason, because we'd rather most applications, when they're printing, the user sees the same spooling dialog.

Richard Blanchard, Paul Danbold Looks like that printer's very busy, sir. Okay, so those are very easy. The next set of functions we call the PM Printer functions. In 10.1 today, you can call a function called PM Session Create Printer List. It'll hand you back a list of printer names. That's the same set of names that you see in Print Center and in the print dialog when you're looking at available printers.

And you can also call a function called PM Session Get Current Printer, which will hand you back a PM Printer object. From which you can find out, for example, resolution settings for the printer, and if it's a PostScript printer, the URL to the PPD file. But it's pretty limited, so we're making the PM Printer function a first-class citizen in Jaguar.

And there's a new way of getting PM Printer objects, and then there's a long list of accessor functions. PM Server Create Printer List. You should use this instead of PM Session Create Printer List, not just because you don't have to create a session to call it, but because it'll hand you back in a row of different ways. PM Printer List. You should use this instead of PM Printer objects, and once you've got those objects, you can then hand them to a bunch of new APIs to get some hopefully useful information.

PM Printer List. You should use this instead of PM Printer objects, and once you've got those objects, you can then hand them to a bunch of new APIs to get some hopefully useful information. The Get Name function just hands you back the name of the printer that you'd see in Print Center. Get ID will hand you back the unique internal name we use for every printer queue. Something that you may have seen if you've been running Jaguar.

The new Print Center allows you to enter a text string describing the location of a printer. This is very useful if you're sharing a printer and you want to tell everybody that's in the hallway or in your office, whatever. So the Get Location API will return to you the string that the user typed in when he or she created the queue. Most of the other functions are, I think, helpfully named, so it's pretty obvious what they do.

There's a few more here. A couple of words about the second one. PM Printer is PostScript capable. I guess the use of it is obvious. You should use this instead of the old API called PM Is PostScript Driver. Use this to find out if the target printer is PostScript capable. And for example, if you had an application that had a print dialog extension that had some features for non-PostScript printers and a different set for PostScript printers, you'd call this function. And then change your UI accordingly.

Get State. That function will tell you whether the PM printer that you're passing into the function, whether its associated printer is idle or busy or maybe the queue stopped. So there's a few more. So basically, this is a useful set of functions. I think some applications make care to use them. Certainly if you're writing a printer utility, you'll probably find these useful.

Preset Functions So, as Rich mentioned, when iPhoto came out, we introduced the simplified print dialog. We also introduced this notion of presets. Presets are basically just collections of printer module settings, and by picking a preset, it's basically a one-click shortcut to going into the print dialog panels and picking paper type and print quality mode and things like that.

So, very useful, especially for iPhoto users. And our thinking is that other applications will want to take advantage of presets. So, we're adding a few APIs to do that. And the one at the top here is probably the one that most of you want to call, the Enable Printer Presets API. Just call that before you bring up the print dialog, and then the presets pop-up menu will be populated with the presets for the current printer, assuming the printer driver has presets, and hopefully most will. So, totally straightforward to offer presets in your print dialog.

Now, that's not exactly the same as having a print dialog where the applications dialog shows some application controls and just the presets pop-up, and then there's an advanced settings, advanced options button that allows you to toggle between the simplified dialog and one that displays all the print dialog panels. We're working on some sample code for that, and we'll post that as soon as we can.

If you need to delve deeper into presets, and maybe printer utilities may want to do this, there's some more functions. Copy presets will simply hand you back the presets associated with the PM printer that you pass into the function. Having got those presets, you can call the Get Attributes API. That will hand you back the detailed information about what's in the preset, which is basically an ID, a name, and a dictionary containing all the printer module settings.

Copy Name will hand you back the localized name of the preset. And then, once you pick the one you want to use, maybe you don't have a print dialog and you want to do this, call the Create Print Settings function, and it'll create print settings embodying the preset options.

So, this is particularly useful, for example, if you want to generate, say, a test print on a particular paper type, a particular quality mode, you don't want to use a print dialog, but you want to do this within your application. So, call these functions, and you'd have some control over the printers, over features like paper type and print quality.

Okay, so those are the new APIs. There's a few more going into Jaguar. You'll see them, some of them in the seed that you got this week and a few more that I may mention later in future seeds. We'll talk about some new sample code. Some of this isn't so new, but it certainly appeared since we were here last year.

The first three, App Using Sheets, Carbon Quartz Drawing, and the Draw Picture, are already available on DTS's sample code site. You can get them on the Toolbox CD. They're all Carbon apps, and we'll be talking a little bit about what they do. PDE Print is not available yet.

It's some sample code that will accompany the print dialog extension documentation that's going to be published, the final version published, in a few weeks from now. App Using Sheets simply tells you how to support document modal printing and bring your print and page setup dialogs down to Sheets. It's so easy. It's just one function, PM session use Sheets, and a couple of callbacks.

Carbon Quartz Drawing shows you how easy it is to mix Quick Draw and Quartz 2D graphics on the same screen and in your print job. Also how to generate a PDF file from that content. Very useful piece of sample code. And if you go to the graphics sample code page, you'll find CG Draw Picture, which is a little different. That shows you how to render a Quick Draw pic inside a Core Graphics context.

Those two projects basically show you how to move from maybe the old world that you were working with on Mac OS X and 9 when you were supplementing what you couldn't do in Quick Draw with your own Post-Crit drawing on X. The better way to do that is to start using Quartz 2D.

And as I mentioned, PDE Print, that's the sample code to show you how easy it is to add print dialog extensions to the print panel. So about a week ago, instead of showing you the code inside these projects, we just put together a simple test app, which I'll show you. "So we can switch over to the demo machine.

I'm sure you can read that. It's big enough. So we've just got a sample project here. Two components, an application and a print dialog extension. And I'm just going to point out a few snippets of code out of it, and then we'll put the application through its paces. So the first thing is that the application supports document modal printing, brings down the dialogs as sheets, and here's the function.

It's just called, and a few lines below in the code, you'll see the call to PM session, print dialog, and hey, presto, your dialog's going to come down as a sheet. Elsewhere in the project, there's a similar call to bring down the page setup dialog as a sheet. Let's see. I've got to get my crib Notes out, so I go to the right.

Okay, the next thing to point out is this test app supports spooling multiple jobs in parallel. So it's multi-threaded. And the code we got to do that came from, as you can see from the comment there, the Carbon Event code listing in inside Mac. So it's cooperatively multi-threaded. This enables us to spool a print job from one window, one document, in parallel with spooling a print job from another. And we'll see that in a moment. Let's see what else.

The other thing our test app does is it mixes QuickDraw and Quartz2D when it's printing. The example we've got here will print a watermark using Quartz2D on top of a document whose contents are drawn with QuickDraw. And if we look up here, This is our function that draws our pages.

It starts off by doing some quick draw stuff. Comes down this function. We'll draw some text on screen using text font and draw string, etc. And then when the time comes we want to draw the watermark, we call, because we're going to use called graphics, we call beginCGContext.

We need to translate between the Quick Draw and the Core Graphics coordinate spaces. So this QDY to CGY is the macro that just flips the Y axis. And then inside this code, which I won't show you for time reasons, it starts off, it changes the Core Graphics CTMs so that we can draw a text at an angle on the page. And then it makes a few @ZUI calls to draw the watermark text, 50% opacity on the page.

And then, when we're done with drawing in Quartz 2D, we call the end context function. I guess the thing to point out here is you don't see any code to save and restore the graphic state. You don't need to because the begin and end functions take care of that for you. So the G state's preserved as you switch between Quick Draw and Core Graphics.

What else do we have? The other thing here, just a simple line of code. You can see below it, we bring up the print dialog. The PM session enable printer presets just tells the printing system that you want to see the presets when you bring up the print dialog. That's just one line of code.

Here's a function that registers the application's print dialog extension. Pretty simple. It goes and finds its bundle, assumes the plug-ins inside the bundle, and...

[Transcript missing]

Let's move over for a moment to the Print Dialog Extension code. The thing to point out here is that it's Nib-based. In other words, we use Interface Builder to lay out the controls in our Print Dialog Extension. A whole lot easier than writing a lot of Control Manager code. The Nib-based code is a very straightforward and easy to use. You can see a call up here to find the Nib file.

Then we call createWindow from Nib in the initialization function to build the UI for the Print Panel. Last of all, this function here will put whatever the user selected in the print dialog into the print settings ticket. So if the user has picked a watermark feature, that setting will go into the print settings ticket and then back in the application code.

If I can find it. Okay. So here in the application code, we're going to pull that setting out of the print settings ticket, and that will tell the application how to draw its pages at print time. In other words, whether to image the watermark. So that's just a quick look at the code. Let's see if this thing runs.

Very simple app. It's got one window here. We can create multiple windows. If we go to the print dialog, we'll see it pops down as a sheet. That's good. If we go to presets, we'll see this particular printer, this S900's presets. If we pull down the PD panel, we can get to our application's PD, which is pretty simple. It just offers the choice of printing watermarks.

We've got tooltips built in here, which is nice. One thing I didn't show you in the code is if we click on the help button, the PD actually has an event handler to catch the help command. It's registered its own help book, so now we've got information via help view on telling the user what the What those PDE functions did. So, that's useful.

So, it's pretty straightforward. What I'm going to do is just print a couple of pages here to the printer. For demo purposes, I'm going to come back and I'm going to print a few pages to preview. So we'll pick Watermark Under and print all of the 500 pages.

[Transcript missing]

Let me just see if I can stop this job. I guess this is where I tell you a joke, but I can't think of one right now. My printer seems to be taking control of the system here. Hopefully, when we've printed those three pages, I can use the system again. Maybe not.

I'm going to give up in one second. I don't seem to be able to kill it either. Well, I'm going to move along right now. Had that demo worked, I would have shown you two print jobs falling in parallel and showing you the results in preview. We can switch back to the slides quickly. Come up, Seija, later. I'll show you it working.

All right. So, just going to run through a few, I think, well-known reminders for all application developers. Basically, just telling you what we want you to do. when you're writing your printing code. The first one is a repeat from what I said last year, and probably the year before.

Use the so-called session APIs. Early adopters of Carbon printing may have started using the non-session ones. We really need you to use the session ones. For the reason that the non-session ones are deprecated, we don't cover them anymore in our documentation or sample code. Any new functionality that we bring up will, where appropriate, always be session-based. And go to our print loop sample code, which has been posted for a long time now. And you'll see basically how to bring up the print dialogs, how to execute a print loop.

The other thing I really want to push fairly hard on now is support document modal printing and look at the sample code, bring up all your page setup and print dialogs as sheets. Very easy to do. If you're a Carbon application, the sample code that we just showed you is where you want to start. If you're a Cocoa developer, you ought to make sure that you use the begin sheet with print info method in your NSPage layout and NSPrintPanel objects. All Carbon, all Cocoa applications should bring down their dialogs as sheets.

The other thing that I sort of demoed for you is how easy it is to write print dialog extensions. And if you came from the Mac OS 9 or older world, probably familiar with using the so-called append-dittle mechanism to add controls to the print dialog. Well, using print dialog extensions is a whole lot better, more powerful, you have more control over the UI. Coding it is pretty straightforward. And we encourage you to look out for the final print dialog extension documentation and the sample code when it comes out in a few weeks.

This next topic really deserves a lot more time than we have today, but basically we want everybody moving from the old world, the legacy way of printing with mixing Quick Draw with PostScript, to the new world, which is to use the PDF print path and to take advantage of the Quartz 2D. So just to let you know, the old way, the so-called Laser Iterate Compatibility path, is still in the printing system. It's in 10.1. It'll be in Jaguar.

The Get and Set Document Format Generation APIs are shown in the PrintLoop sample code, show you how to tell the printing system that you want to generate a PICT with PostScript spool file instead of a PDF path. So that works and will continue to work, but there are much better things you can do.

And the sample code that we mentioned a moment ago, using calls like QD Begin CG Contacts, QD End CG Contacts, mixing Quartz 2D with Quick Draw, that's really what you should be using. So that's something we should be looking at now and taking advantage of. So that, as you've seen, shows you how to mix Quick Draw and Quartz on screen and when you print.

I think it's very possible that a lot of you may be using the Pick With PostScript path because your application wants to support EPS graphics. When somebody drops an EPS graphic onto your document, you want to print it right to a PostScript printer. And so you felt that you had to use the Pick With PostScript path for that purpose. Well, in Jaguar, new in the header, not today, but in a future seed, there's this PMCG image create with EPS data provider function. I'd like to see a George Bush say that one.

And that basically just tells the printing system you want to embed EPS graphics in the PDF spool file. You get both the postscript representation of the graphic. You also get the preview image. So it will print correctly to both postscript and non-postscript printers. So look out for that in a future version of Jaguar.

Okay, so that's enough for the application checklist. Now to talk a few minutes about driver things that we want people to do if you're in the business of writing a printer module. The first thing, as mentioned earlier, is iPhoto uses presets. We want or expect other applications to be interested in using presets.

And so, obviously, users will like all their printer modules to support presets. The documentation on presets, explaining the internals of presets and how to create them, was posted shortly after iPhoto went live. And very straightforward. Richard Blanchard, Paul Danbold I'm sure DTS is standing by to help you if you have any questions.

But add presets to your printer module bundles, and then all the applications iPhoto and other applications calling the Enable Presets API will be able to take advantage of your printer's presets. Printing and color, again another topic that could take a whole session. Just limit this to a couple of comments.

One is Well known that Mac users have the highest expectations for things like print quality, fidelity, color matching when they print. So they expect every printer driver to come with a great set of ColorSync profiles when they're taking advantage of ColorSync. So our message to you is really try your best to produce great ColorSync profiles that support all the media types your printers support, all the print quality modes you support. And again, we're very open to talking to you and helping you achieve that.

Richard Blanchard, Paul Danbold And then the other thing, of course, you need to do when you've created these profiles is make sure you register them all. Registering them is very straightforward. You just provide a list of them when you're creating the printer info ticket, which is something that happens when the queue is created. We register your profiles actually on your behalf.

And the thing to check is that when you run the ColorSync utility, that if you go to the printer section, you can see all your profiles. That means that an advanced user may be able to override your profiles. Richard Blaencarad, Paul Danbold And so that's one of the things that we're trying to do. We're trying to make sure that we're getting the right printer profiles with one that he or she's generated.

It also means that high-end applications like Photoshop can see what printer profiles are available. And it's also useful for color-proofing applications. So a lot of good stuff to be done if you support ColorSync. Richard Blaencarad, Paul Danbold Another one on the list, in the 10.1 version of PrintCenter, if you pulled down the printers menu, there was a configure printer item, which was occasionally enabled when PrintCenter knew the location of the printer's utility.

In the new version of PrintCenter, which Rich showed you a few minutes ago, we've actually made it even more obvious to the user how to get to the utility in both the printer list and the printer queue windows. There's a big button that when Jaguar ships will be a lot prettier.

It will provide the user with a simple way of getting from PrintCenter to launching your utility and doing whatever your utility does, like align heads and print test pages, etc. It's very simple to tell PrintCenter where your utility is located. You just put a key in your Info.plist file, PM utility URL, and the value of that key is the path to wherever you installed your utility.

Having mentioned install your utility, I want to tell you that we really don't want utilities and other printer software scattered over the hard disk. We'd much prefer you to install all your printer components in library, printers, and the directory you create there for your printer modules and associated software. If you feel obliged to put links to your printer utility elsewhere, then yes, it's okay to put an alias inside the utilities directory that will link to the real utility that's inside library printers.

Another thing relative to installers is to make sure you know about the Make Queues tool. Make Queues does a lot of what Print Center does without a UI. When you boot your Mac or when you hot plug a printer, Make Queues executes some code which will automatically create a USB printer queue. Your installer can also use Make Queues to refresh the USB printer queue. Execute Make Queues with the -r switch and we'll go through and recreate all the USB printer queues.

Another thing, you know, our direction is to make setting up queues as painless and as free from user action as possible. And I'm sure everybody knows that we can automatically create queues for USB printers without the user going into PrintCenter. And we want to continue in that direction and make it as simple as possible to create queues for the novice user without having to know anything about how the printer's connected or even, you know, the name of the printer module. Nothing like that should get in the way of the user being able to print.

So, we are publishing all the source code for our various printing I/O modules. The USB and the LPR source code is available on request from DTS. But I want to make sure you understand the reason why we make that source code available is so that you can point out bugs or deficiencies in our code, not so that you can create custom versions of our USB modules, our LPR modules, etc. So, treat that source code as an opportunity to tell us what enhancements need to be made to support your devices.

And last and definitely not least, you're obviously very interested in all the CUPS stuff. The message for today is, if you're working on printer module projects for new printers, continue to do that. Don't abandon anything you're working on already. As Jaguar gets ready to ship, then come talk to us and certainly by the time Jaguar is released, we will have a lot more detailed information to tell you about the pros and cons of CUPS-style drivers and backends versus the existing printer modules and IOMs.

A few seconds to talk about USB and printing. There's quite a lot of details here and I'll skip them and tell you to come and talk to us later about this. We are introducing a printing class driver in Jaguar. It will enable you to better support, for example, multifunction devices, printers that can scan, copy, and sometimes fax as well as print. Maybe your printer has some special, say, non-compliant USB characteristics. The printing class driver will make support for your device a lot easier.

And although it's not in the seed that was released this week, hopefully the next seed of Jaguar will have the printing class driver code and readme file. We encourage you to take a look at it if you are a printer vendor or driver developer and give us feedback. We want to make sure this works. This is a useful piece of code to enable support, for example, multifunction devices. multifunction devices when Jaguar ships.

Another thing you may be interested to know is that our USB code now supports more device ID keys. We use device ID keys to match the physical printer we find on the bus with a printer module that's on the hard disk. So, Jaguar will be supporting the compatibility ID.

We also support the serial number ID as well as the product ID. And where needed, the hub's location ID so that we can, for example, support multiple printers of the same type, identical printers on the bus. And last on this list, there are devices out there that present multiple USB interfaces, maybe unidirectional, bidirectional, and some perhaps proprietary interface. We've added an attribute now so that the printer module can tell the I/O module which USB interface to use in talking to the printer.

Last but definitely not least in these slides, a few words about the new documentation. And, as Rich said, the tech pubs group at Apple did a great job this year. We got a lot more documentation than we ever had a year ago. Three of the items on this in the next slide are actually available in book form. None of these include the CUPS information.

So, we'll keep tech pubs busy, and we'll obviously have to update some of these books, but... Actually, I mentioned books. Some of these are available in book form. All of them are available downloaded from the tech pub's website, and they're also on the reference library CD. So, about the Mac OS X printing system, basically just introduces you to the architecture and the user model.

Cocoa printing documentation has been updated since last year. The PostScript printer description file documentation tells you how we find PPDs on the disk and how we bind them to printer queues and how we expose PPD-based features in the print dialogues. The Extending Print Dialog Documentation just has one more engineering review and then we'll post it. It'll be the definitive document on how to create print dialog extensions for your applications or print modules.

Supporting printing in your Carbon application is another of the books that you can order. It tells you how the print dialogs work, how the page format and print settings objects can be used, about page recs and paper recs, things like that. It's a good read. The big book of printing, it's not that big, but I got a copy here, is a Carbon Printing Manager reference. I think it's 180 pages.

So it tells you all about the little over 100 Carbon Printing Manager APIs, all their associated data structures and constants. Rich was plugging in the CUPS book. When you finish reading the CUPS book, buy this, put it by your bedside. It's great late night reading. And last, definitely not least, is the iPhoto documentation. If your printer vendor tells you about the internals of presets and how to create them, and again, we're hoping that you add those to your printer module bundles.

We also have some new detailed API reference documentation. The plugin interfaces, that you'll probably want to read when you're writing your printer module, your print dialog extensions. And there's new documentation explaining how all our job ticket and template APIs work. I'll mention a new tech note as well.

It's not really a 10 thing, but we've got a new tech note, I think it's 2049, tells you how you should create what we call a PDAT resource for your Mac OS 9 or 8 print driver. We rely upon these PDAT resources to tell the Carbon printing manager, when it's running in Carbon on Mac OS 8 and 9, how to find various settings in your print record. The settings like page orientation and copies and color mode, etc.

It's very important for Carbon applications running on 8 and 9 to work with drivers that have these PDAT resources. Apple provided a few in the Carbon lib resource, but we're no longer doing that. Now we're looking to developers of print drivers to do that. So, tech note 2049 is sort of a must read for Mac OS 8 and 9 driver developers.

That's it from me. I've got a summary slide just to show you or remind you what we've covered today. Rich took you through the big changes, the cup stuff, all the functionality that enables. Cocoa Print Center and changes to the UI. I think you'll find that when you're running Jaguar at home, you'll see a lot of stuff that we haven't been able to demo today and it's all pretty good. We just talked about some of the new APIs going into Jaguar for applications. We looked at some sample code and new documentation.

Rich had some, some

[Transcript missing]

Before I take you through the roadmap, I just want to offer some comments on today's session. We're really excited about the opportunity that the new printing architecture offers developers because what we've done is essentially put a new architecture which is incredibly extensible, incredibly flexible, it's very approachable because it's open source, and so that's really going to empower the, you know, the new printing architecture.

Software developers want to get at the middle of the printing system. But there's also another great story that you really don't have to change anything if you're an application developer, if you're a print driver manufacturer. So all in all, it's a really great story. And the possibilities are endless. Like, for example, we saw the technology demonstration with global graphics post-script interpreter being used in line with our print system.

And it was essentially a little bit of coding, drop it in, and it just works. So it's an exciting opportunity, particularly if you're a core technology vendor, because you can approach the platform in a very defined direction that enables you to just plug yourself in. So we're really proud of that.

So what I want to do now is quickly go over the roadmap. And what I'll do is skip ahead, because we want to get a time for a good Q&A session. And we will start with the sessions that are left today in WWDC. Obviously, we're at 5.10, which is printing in Mac OS X. Sessions that are left are 5.13, OpenGL Advanced 3D. Obviously, OpenGL is a big threat at this year's WWDC. It doesn't necessarily relate to printing, but a lot of things we're doing with Quartz Extreme are based on top of OpenGL.

And if you want to find out more about OpenGL, go to 5.13. Also, same for OpenGL performance and optimization. That's a good session to learn a lot of the fast paths that exist now in the OpenGL implementation of Mac OS X. Another sort of companion technology that we have in graphics and imaging is image capture framework.

And that's often going to provide the input data that what the user is later going to print. And so we have a session on it. We're going to be doing that on image capture. And one of the nice announcements that we've made relative to image capture is we've expanded it from just supporting digital cameras to supporting scanners as well. So that's going to be on Friday.

Lastly, one of the remaining sessions is 5.16, Graphics and Imaging Performance Tuning. You know, over the past year, a big source of information that's been required for developers, or at least asked by developers, is how do I make my application go faster under Mac OS X? Because the graphics implementation is different. The visual pipeline's different. And that's where we're gonna cover a lot of those details. So a lot of your questions, if you have performance issues on Mac OS X, are gonna be answered there.

And then, finally, I wanted to make it clear that the feedback forum, which is Friday afternoon, also includes printing. So if you have any comments to make on any of the things we've talked about today, or concerns or questions, you can bring those to the feedback forum, and there'll be the engineering managers for each area of graphics and imaging will be there, and we'll be able to respond to those questions. So now what I'd like to do-- well, before I do that, let me actually just give you my contact information.

If you need to contact me relative to anything we've discussed in this session, this is my email address. I handle printing as well. You've seen me in a lot of other contexts at this WWDC, but, like I said, CUPS, how it's gonna be integrated into Mac OS X, other developer-related questions relating to graphics and imaging, please feel free to send me an email.