Enterprise IT • 50:33
Mac OS X offers a rich set of native services that Java developers can take advantage of. There are many considerations and guidelines for accessing native APIs from Java or invoking the Java VM on Mac OS X. We cover AppleScript, input methods, and custom NSViews for your Java applications.
Speakers: Blaine Garst, Greg Bolsinga
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
All right. Good afternoon. Welcome to session 620 IE. And for those of you who want to know what that's about, stay tuned. You'll find out at the end. What are we going to talk about today? Reaching out to other, reaching out to Apple APIs. So the basic premise of this talk is that you have a Java application already, for the most part. I mean, if you're going to be writing one, that's cool too, but let's assume you have a pure Java API, pure Java application that runs on our platform. And you might, you know, you might have a Java application that runs on our platform.
You know, think that that's cool because Java's portable and all that, and we think that's great as well. But just by having your application run on our system... Apples, APIs, and services actually reach in and extend it for you automatically somewhat because of some of our built-in features and some of the technology we did with the AWT rewrite in Top of Cocoa.
However, most of it, and so we'll see a little bit of some of those free extensions that you get a little bit. But also, this talk is about how your app can reach down and reach into some of Apple's APIs and get a little bit more close to the platform.
As well as discussing how to get closer to the platform, we talk about some of the pitfalls of getting a little too close to the platform. So, we're going to talk, first of all, about the things you get for free. You've seen some of that in a couple of the sessions already.
We're going to talk about the threading architecture, which is... In my opinion, which is the one that counts since I wrote the talk, is the one thing you really need to know about when you're talking about getting into our APIs. And we'll give you a lot of examples about that.
We'll talk about launchers. We'll talk about the embedded movie view demo of our Cocoa component. We'll talk about some disk recording APIs, which I have had the pleasure to discover and tame over the past few weeks, up until even 2 o'clock this morning, 12 hours ago. and even a little bit of address book.
will have, I'll also get up and do a demo of all that code so that you can actually see that it's real. And we'll hopefully end even a little earlier than some of the other sessions have because I thought that this might be a good place for us to actually spend some time in Q&A getting into some of the depth. So things you get for free. Cocoa input methods.
We have, because of the AWT rewrite in Cocoa, we use Cocoa to get things in. Because of that, we get multi-language input for free. We get Inkwell for free. How many of you people remember the Inkwell demo from, I think, I can't remember when it was. But it actually works. It works without any coding on your part. You can actually hook a little pad up to your device and get the drivers right.
And Inkwell will actually do input into your Java app. And you haven't had to write a line of code for that. We're not going to demonstrate that today because of the vagaries of disk drivers and Panther and pre-release machine. Well, who knows. But it is done. The accessibility implementation is the key to many of these free services. It gets you, of course, accessibility.
But it also gets you the Apple script, GUI scripting that we talked about and have demonstrated in some of the other talks. Greg's going to come up and actually show you more of that in just about 30 seconds. Menu items is another thing that you get for free.
Without any effort or coding on your part, in AWT-style applications, you get the services menu absolutely for free. You get the spell checking. You get speech, speakless item kind of thing. And... There's just... There's a pile of things that you actually get for free. So it's really cool to write Java to begin with.
But it's even cooler to deploy it on Mac OS X where it's actually part of an... It just is... It's one of our... It's extensible just by being on our system. Other people can use it in many ways. So without further ado, let's let Greg drive for a little while.
I'm on demo this one. OK. Did any of you see the Java State of the Union where I did this demo? No. OK, about half. So I have a little bit of this demo, and I've also added to it that you'll see in a little bit. And I'll talk a little bit more about how I did it in some more detail. So first off, what I have is just a plain Java application.
This is a little different than the one I showed in State of the Union, and I'll get to that a little later. There's this big area down here I'll talk about in a second. So this is a swing application. I used to say it's pure swing, but not anymore. I'll get to that in a sec.
And it uses the brush metal look and feel. And this is just standard Java. This little window to the right has transparency. And we could do things like this. And it's a little hard to see, but you could add a whole bunch of little things. This is a pure transparent window, all in pure Java code.
Just an AWT window where I set it to a background color that has an alpha value. And then the Quartz Extreme Compositor takes care of the rest. And so it's pretty fun that we have this. And I also set it up that it works as an applet. And so you could see that inside of Safari, the Java brush metal look and feel shows up. And this is a key point for a little later. When it's an applet, it's a real thing. It's a red transparent window. When it's an application, it's a gray transparent window. And it's the same darn thing. You know, nice, trivial, simple.
I'll talk a little bit about how I did this. Or some ways -- rather, what I'm going to talk about is how you can see that the native integration that Java has with Mac OS X can help you write better Java applications. So first off, we have the Apple animating here.
There's a great program on Mac OS X called Quartz Debug. One way to speed up your program is not to have it draw a lot. So one thing that Quartz Debug has here is flash screen updates. When I first wrote this, I was repainting the entire transparent window every time, and it was a little slow.
And then I went and figured out that I can make sure I only draw the Java parts that I'm interested in. It kind of slows things down a little bit when Quartz does this, but you can make sure that you're only drawing what you need to. So some more of the native integration that we have. I'm going to quit this and start it over so that I can run my AppleScript. What I have is an AppleScript.
I have an AppleScript here that will use the Mac OS X accessibility and Java accessibility integration. The Java APIs have accessibility where all your users can learn about the buttons. They can use screen readers or zoom in where it's large if they have difficulty seeing or some such. But what's also cool is the accessibility APIs are also AppleScriptable. So it uses the same thing.
What you see here is it's telling Java the first window, which is this window. And then it goes and it finds the button titled Add Image, and it clicks it. So the API is pretty simple. You have to enable it in your system preferences under Universal Access to get access to this. But I'm going to run this really quickly, and then I'm going to show you a little bit more. Thanks, Greg. First, I'll add the Apple logo.
Now adding the Java logo. So this is pure Java code being Apple scripted. Your program can be used in ways you don't even understand. And lastly a picture of Scott. Now it will start bouncing around. Now let's turn on the transparency. Back to you, Greg. Okay. So as you can see, this is a good integration between Java and Mac OS X. No extra Java code is necessary.
If you have custom-- so there is extra Java code necessary if you write custom component controls. All the standard AWT and swing components that come from Sun have the Java accessibility set up, so Mac OS X will see them. If you have a custom component, you'd have to wire it up to Java accessibility, and then when it runs on Mac OS X, it should work fine.
So what am I going to show you now? I really like the demos I saw of embedding WebKit, and I've even seen some questions about it on JavaDev. The last two days, I've been doing that. and it actually took me two days because I had a bad Panther install. But it should have taken only an hour. So here's WebKit inside of a pure Java application.
It's pretty, it's so terribly simple how I did this. It's really powerful. I mean, just imagine with any Java program, you can now display any data that is visible in a web browser. So QuickTime, Flash, you name it, you got it. I even have this set up.
[Transcript missing]
It's no fun. There we go. Oh, they've got two now. OK, well, you know, I did it in a day. So I could show you very-- oh, well, there we go. I could show you very easily how I did this. We had this great Cocoa component that we added to our AWT. This is where its custom Mac OS/Time work.
That's the NAV code. So here's the Java code. It's a Cocoa component. It's just a component that you add a single view, which creates an NS view. You return the pointer to that as an int. I added a method called setURL that you just pass a string to it. This is the sendMessage API. It is a standard API defined in the Cocoa component.
You do some things to set up the sizes so that it fits in there. And on the native side, I have my-- can you all read that? It's very easy. I made my own object. I allocate. You just return it. My object is a web view from WebKit.
I just made it size zero because Java will take care of, the Cocoa component will take care of resizing it. And then when it gets a message, I translate the Java string to an NSString and then call load request on it. So it works very nice and easily.
What else was I going to show you? I believe that's all for now. If you want to learn more about Mac OS X accessibility, there's a session tomorrow morning, and I imagine they'll have more than Apple GUI scripting and the other built-in Accessibility APIs that there are. More of a real screen reader that all your users would use. Thank you.
Actually, a great lead-in for some of the rest of my slides, which we haven't seen. So I'll be talking a little bit more about the kinds of stuff he was doing right there, but let's talk just a little bit more about that WebView thing that he was doing. So as you saw, it's nearly trivial to make that happen. There's a whole talk on that tomorrow in, I don't have the time on that one, it's session 420.
So please go to that if you have specific questions about the do's and don'ts of that in a Cocoa context, admittedly, even though what we're going to show you is most of that still applies even with this fancy little Cocoa component. The other thing I wanted to talk about... was extended AppleScripting. So what we've shown you so far is how to script the GUI, how to script the stuff that comes for free with accessibility.
So standard scripting, we've already handled the five common events that every app already deals with. And in fact, you get a handle on that with the extended AWT more directly. So with accessibility, we get automatic GUI scripting, as you just saw. So advanced scripting. I mean, if there are AppleScript aficionados in this audience, then they're kind of looking... I can't see them, luckily, because they'll be looking at me a little askance, because advanced scripting has to do with building up a dictionary of terms and actions and properties about your application. So in Greg's case, if he were a true AppleScript aficionado, he would have had people, you know, to represent Greg and Scott, and he would have told the people to hop and dance and fight and jump around.
He would have told them to jump, and he would have told them to do other kinds of things. So if this is the kind of AppleScripting you want to do, then you have to learn a lot more about AppleScripting. So what happens is that Cocoa offers lots of wrappers for these nowadays.
They're all in NSScript something or other classes, and you add dictionaries and hang them onto your... hang them onto your app wrapper. The interesting thing about Cocoa is it's got a bunch of built-in key value kinds of notions, such that if you go, you know, set jump height, if there's a jump height instance variable, then Cocoa will go and find that and update it for you automatically.
Now, the very interesting thing is that we've had AppleScripting at this level available to Cocoa Java programmers for some time, and it's been around for several years now, and it's in one of the examples there. So if you like Cocoa a lot, and you like Java a lot, we've always kind of steered you towards Cocoa Java. The glue that goes on right now between extending AppleScript and the basic technology that's in there right now is not quite unraveled enough for us to get to this more advanced level for pure Java.
So we're going to have to wait and see if we can get to that level. So we're going to have to wait and see if we can get to that level for swing-based programs. I'm not saying it's impossible, it's just I wasn't able to unravel it in the past two weeks. So there may be hope for it, though. That's just kind of a caveat on what we've done so far.
Let me talk about threading architecture now. This is the one thing you need to remember at the end of this talk. So what's a thread? I'm going to assume that all of you have sat in front of at least JDB or hopefully even GDB and have seen a backtrace of your program running.
If you've seen a backtrace, then you know what a thread is. If you've seen multiple threads, you obviously know what multiple threads are. So here's just an example backtrace. I took out a few frames. So what's a thread? Just basic review. From the kernel's viewpoint, it's a set of registers in the stack that goes with the flow of control. It gets scheduled and all that. Processes start with one thread. This is Unix.
The first thread spawns others if they're needed, and on a Macintosh for a GUI application, there are always lots of threads running. The key thing about Java is that the first thread on any Mac OS application, the first thread has special duties because the first thread initializes the GUI libraries underneath everything. Whether that's Carbon or whether that's Cocoa, this has always been true. We have had to stand on our heads in 1.3.1 in order to not kick off Carbon at the wrong time in the past.
We are not standing on our head anymore in the 1.4.1 stuff. We took the bull by the horns and actually said we have to start things up a little differently. So let's talk about that a little bit in more detail. If you have code that you've gotten, launch code that you've gotten from somewhere, it just looks like this. You gather all your arguments, you find this VM thing, JNI create VM. Then once you have a VM, you go off and you find your main class.
You get all these method descriptors and whatnot. You invoke it, it goes off, it does something. Sometimes it creates a J frame, which brings up your app, and then the main thread just returns. On Apple, however... We have to do things a little bit differently. What we do is we take these steps and we move them over into another thread.
Then of course we have to put a little bit of code back there to spawn the thread and to get it going. Then the key element there is that very first thread has to do this thing called running the run loop. Maybe you know what that's about, maybe you don't. You'll learn a little bit more about it in just a moment.
So, as I said before, the very first thread has the duty of, you know, Getting the VM started, or of gathering arguments and stuff and running the run loop. It will, if it's done properly, spawn off a second thread, which goes off, launches, finds your main, kicks in your main, and hangs out there as long as you want. As long as that first thread does something interesting, gathers IO or whatever, you're going to have a second thread. If it's got GUI, if it's launched a JFrame, then there's a thread that we've created on your behalf, which we call the AWT event queue thread.
[Transcript missing]
The AWT peer implementation takes that input as a Cocoa event and transforms it and sticks it over onto a queue that's read by the AWT event queue thread. And so that's how threading threads get set up and run on every Mac OS X application. So we don't really care if that second thread that just started a J frame goes away.
But if you had just taken raw code from some other system over and that first thread went away, then guess what? There's no thread running any run loop. And so your UI is still kind of hanging out there, but there's no input ever going to go to it. And so that's what happens when you just take straight code that deals with libraries and getting stuff started and try to port it directly to a Mac OS X system.
So, that whole business we call launchers. So we have actually two standard mechanisms on the system already. We have the one that underlies user bin Java and user bin Java H. You know, there's this one little magic program that does all those little duties. Oh, the second one is our launcher stub that we set up.
If you use jar bundler or if you use Xcode to build an application, then there's a little tiny little C program that gets started. It's found in your contents Mac OS, whatever your app name is, and that knows how to do lots of stuff, including this little thread business.
The launcher, The launcher also knows how to read the Info.plist and set up those arguments and pick which VM you run. I'm not gonna talk about picking VMs right now. It's a little dicey. The JNI code that gets everything started and gets run is, of course, in your Java VM framework.
So some of you, however, are going to be bound and determined to write a launcher. We still advise you to try not to. But if you have existing threads of legacy code, and not everybody comes here with pure Java code, some of it actually glues down into sockets or glues into other kinds of stuff, and it's just got to be there. If you have threads of legacy code, if you have, say, properties that change on a per-launch basis, different maximum memory sizes, different... attributes for a graphic state, things like that.
That's a kind of a semi-legitimate reason to not live with our standard launcher scheme. If you have a non-standard main, for example, there's no rule once you launch your own VM that you have to go through a static main. That's just a user-bent Java rule. It's not a hard and fast rule.
If you have any other reason, I know there's somebody out here in the audience who I won't name, but... has so many reasons he can't explain them to me why they have to have their own launcher. So we figured that we might as well give you some example code to get you started because it is a little bit of a pain. So Ted Jusevic, who helped give an excellent talk yesterday, has written a little example of that and it's on the web in the place that normal examples are at developerapple.com, Java. Go to the examples page and find that.
Please start with that code. It's good. It works. It takes you through all those steps that are tedious but necessary. I'd like to talk now a little bit about something that's also, this one's not actually out on the web. This is in the developer examples. It's part of what is now the Java SDK except that in the most recent release we somehow forgot to include it.
So it's in previous releases. It will come back, but it's the NSMovie. I'll give you an example. And what that does is that shows you how to embed Cocoa components. Now Greg just got up there and did a whirlwind tour of Cocoa components and I'll give you one maybe just as fast, maybe a little bit longer, a little bit later. But the basic idea is that, as you know, AWT peers are built upon Cocoa's app kit.
We have provided EAWT Cocoa component in order for you to play around with your own views or somebody else's views that they've written in Cocoa already. This is not quite the base. It's not really the subclass of the peers, but it's sort of a peer for the rest of you. It's not a peer for us.
It's a peer for the rest of you. So the Cocoa component arranges for all kinds of stuff to happen. It fields those events. It paints. It paints on the AppKit main thread. And you as a subclasser just implement a few methods in order to interact with it. And it's very simple to use as you saw for that. The architecture is there to get messages from one side to the other. And as I said, we have example code out there. But I thought I'd actually show you how simple it is. So again, the basic idea here is that we have a Java peer.
We have a Cocoa view. You need to keep them related. So the Java part's going to sit in the Java painting hierarchy. And secretly over on the AppKit side, there's going to be a similar hierarchy going on as well. So we have to keep those two things related. from the Java viewpoint, use subclass Cocoa Component. And you load your little native library. And you create your little special view.
So, Cocoa component actually calls that method createNSVue. You don't even have to worry about that. You have to add some value to it. So in this case, we're gonna define three constants. In the movie view case, we're gonna give them a URL to load, tell them to play, tell them to stop, and these are gonna be linked to buttons. So when the buttons hit and ask it to play or ask it to stop, they're gonna send this little message with this little integer value across and in the play and stop value, no extra values. In the setURL, we're actually gonna send the string across.
So that's pretty easy from the Java perspective. On the Cocoa side, you have a little bit more complicated class. You saw that AWT message class that Greg described earlier. It's the same implementation. In this case, it fields that message ID and does a switch on the three values it could have. Here you see the Cocoa. I don't know how many people have seen Objective-C syntax, before.
I'm not going to give a mini tutorial on it, but trust me that it's, apart from the syntax, very much like Java. So in this case, the NSMovie alloc is going to go allocate a little instance of that guy, and then he's going to initialize it with the following method. Init with URL.
[Transcript missing]
The trickiest part for many people is writing the JNI code. So you gotta have a JNI code in order to create that NSView. And here we have the Cocoa Movie View. That was the subclass we just did. We alloc and edit. Tell the movie to go ahead and start showing and then return that pointer back to be managed automatically for you on the other side. That's pretty simple.
So simple, we made it an example, and you all have all read it, and I've just been boring you up to this point. So this is stuff you haven't seen before. Let's talk about disk recording for just a moment. Now, disk recording... comes in two frameworks. It comes in a C-based straight framework disk recording where using plain C, carbon-like C, you can have DR, la-di-da, la-di-da, la-di-da stuff.
If you like programming in Carbon, then I'm not sure why you're in this room. There's also an Objective-C framework for this as well. So you don't have to program at the CF level, but if you don't like Objective-C, you can. There's also an Objective-C-based disk recording UI framework. Now this is actually very interesting.
Both frameworks use a run loop to drive the work and drive notifications. So you basically set up a little input on your run loop, tell it to start working, and then notifications are sent to you when it does its thing. And you don't know how it's doing it. Is it spinning another thread? Is it talking to another process? You don't know, and frankly, you don't care. What you do know is that those notifications is where you interact with this.
So what is true? What's true in 1.3.1? If you try to interact directly with the GUI, that the framework that the AWT uses to implement the peers. If you interact with it directly, you are treading on very thin ice because the things we have to do to own those peer classes and keep track of what's going on Well, we do what we have to do. And sometimes if you go try triggering GUI actions, independent of what we're doing, we get into all kinds of crossing problems. I won't mention locks by name right here, but if you've ever tried any of this stuff, I think you know what I mean.
Nevertheless, I had to ask myself, how hard would it be to at least add a burn button to that movie view? So let's talk about burn logic for a moment. So what do you need to do to burn a CD? You have to get what's known as the device, that actual CD thing. You can tell it to open the floppy tray, close it. You can ask whether there's media in it or not. It's all kinds of fun stuff to do. You get a device and a folder to burn. You set up this notification center, like I've talked about.
You start the burn, then you process the notifications. No big deal. And then finally, afterwards, you clean up. So just to make it very clear, what we need to do is we need to do a lot of work. So what we're going to do in this case is you're sitting in the AWT side.
and you need to send that message to go burn a movie. It needs to go over to the AppKit main thread and actually trigger those actions to trigger work on the AWT or trigger work on the AppKit side on the main event loop. So as you process notifications, however, you actually want to give feedback to the AWT side. And so you have to use JNI methods to call in and just set up some work. So let me jump to a demo right now. There's one other thing.
thought was in my slides that didn't happen yet. So I'll talk about that directly. If we could switch to demo machine two. You've done it. Very nice. So, in this demo, what I'm also going to try to do is show you a little bit of Xcode. Now, it has been said that Xcode does not natively deal with Java build targets and things like that, but, well.
That's true. And it still supports all the Jam-based targets and stuff that have existed for the past several years. So I actually started with an old project and converted it and then said, well, maybe there's secret stuff going on. So I'm just going to throw away that and start from scratch. So I actually started from scratch and rebuilt the demo that is out there in the developer examples case.
And it all worked except one little glitch. I won't even tell you about that. But let's... Let's show you one thing, first of all. Let me take one more detour. Let me launch Address Book. You'll notice that I've actually set the Address Book up as me. I've set me up as me. Oops. That's just for reference. So now let's show the Cocoa component.
So if you haven't seen this GUI before, now you do. I've actually set it up in sort of full screen mode a little bit.
[Transcript missing]
So notice that this whole view switched to be the find results. Now, this button lets you pull up an all-in-one kind of editor window. And the virtue of that window here is that you can flip between your address, between your find results, very easily and take a look at what's going on.
Notice that if I go back and start picking other items, then that top window reflects what's going on on the left. And in this case, the find results, the address book find results, drive that list up there. So the first part... is in my application. What I'm going to have is a little status field, and it's going to call a JNI routine to get the first name of me and set the status field up with a welcome message with the me name.
On the hard part, you know, the C, the diving into Apple APIs, is right there. Now, if that's not visible, I can zoom it in a little bit. Is that visible in the back? seems to be. All right, so how hard is it to get me's first name? You have an address book factory. You get the shared address book. There's one and only address book. And you ask it for me. You send the me message to the result of that, and it brings back an AV person object, which is just a big, fancy dictionary, big, fancy property list.
Yeah. So you ask it for the first name property, you get back a string, and you return that first name turned into a Java string. And that's a utility up... about here. It takes a string. NSStrings are Unicode characters, so basically we get the length, make sure it's within range, and then you get Unicode characters out of it, filling up this array first with Unicode characters, then you make a new string and return it. No big problem. Let's actually show this app running so you'll see what's going on.
So here it is. There's my name right there. And we got that by fetching the address book on launch and just to personalize it a little bit. Now, what this is, what I've turned this in is sort of my personal movie viewer application. I have my movies on my iPod, and so I just plug the iPod into here, and when I'm done with this application, I'll just switch over to the iPod and click an application, and it'll have a little custom little application to show the movies that I also hold on there. So, for example, we see this... is coming along, and we have some photos that I made when I was on vacation over in the Greek islands. So the first one is of a pink Cadillac, of all things.
So you get the idea. You get to start and stop the movie. And the fun thing here is, of course, you get to burn. So I'm going to press Burn. Oops, we have some status right away that shows up and says we have no media. So let's go ahead and put some media in.
Now, what I'm going to do is, in this case, I'm going to let the finder intercept the media insert. We're going to let the finder say, we don't really know what to do with it. We're just going to leave it around. Then this program is going to come up and capture that and burn.
So what we do is we ignore it from the finder's perspective, and we try burning it again. And voila, it's preparing the disk. It's writing the disk. Closing the disk. Actually, I'm not quite sure how it happens all that fast because the verify step takes an extraordinary length of time from my perspective.
We have a CD with the Greek movies burned onto it. Let me show you a couple other things. First of all, If we turn on this funny thing called Character Palette, you see this icon show up over here. Now, here I am in my AWT view. Voila, look at that. That menu item magically appeared during the middle of my running app. My running app, well, no, my running app. That was not there before. It'll go away if I turn it off.
Now, what does that palette do? For this app, actually, not a whole lot. I added this funny little text window just so that we could show that if you were really interested in adding, say, Cyrillic alphabetic characters to your app, you could put some chas in there. But in any case, if this input panel was actually of importance to you or your customers, you should know that you haven't written a line of code to get it to happen. So I just think that's one of the fabulous kinds of built-in things that we give you for free. Let me... Let me actually show you some of those code steps.
[Transcript missing]
So let's find everywhere I've written disk burning into the app. I actually put numbers on them so that we could actually see the steps a little bit more carefully. So here's disk burning one. We add a button that says, movie view, go ahead and burn whenever I click. Click that, and that's the button's action. Second step is, as we saw before, to send-- The second one, sorry. To send the message across to the other side.
Very hard. Third step, we've switched on Burn Movie and-- If we've selected a movie, we go ahead and say, do burn on it. Now, take a look at this little bit of code right here. What we've taken as input is file:// something.mov. What we want is the file stuff stripped off, and actually the whole last component, we're actually gonna burn the directory that contains the movie in it.
In Cocoa, to get the last half of the string, or to strip off the file colon slash slash, you say substring from index. To get everything but the last path component, you say string by deleting last path component. So in that one little line, we've actually stripped that URL down to a directory path.
We tell ourselves to burn it. Now this is actually not a lot of code. What do we need to do? You find out all the devices that are on the system. This code isn't totally robust because there might not be an object at index zero, but we just grabbed the first one.
We acquire what's known as a media reservation. Go to the DR documentation to figure out what that means. So that just means we grab the device. We ask, is the media present? If not, we send a message back. We ask if the media is blank, because they could have added something else in there. Again, we send status and release the reservations. Assuming we've got media, we've got the device, everything's going, we allocate a burner object. We set up the writing information. And we set up this notification center, and we tell it to go ahead and start burning.
So the burns come in, you get a property list, a dictionary of the results. You get like the current status. So you say, is this thing done? And you send status back to the other side. You release it, you release the burner. Certain statuses have a percentage, so it's preparing, it's writing, and all those sorts of stuff.
We get the percentage and quantify it back into an integer and send it back. So that's actually not a lot of code. I actually wrote this routine twice. This routine I wrote between 1:00 and 2:00 in the morning. Let me show you what it used to look like in for core foundation style code. We have GetDevice.
You get the array, you get the count, you get the value at the index, you return it. You have to turn that string into an FS ref. I actually did the character stripping and stuff in this guy. You have to ask whether it's reserved. You have to go get some status, look up some dictionary values.
Luckily, I didn't have to write all this code. I stole it from the disk burning example. Here's that callback notification routine that takes those strings and turns them into useful error messages and sends them back across. So, in any case, this is an entire file. It's about four times as long as the Objective-C stuff. I'm really happy to say that there is some good Cocoa code to make that simpler.
Let me show you Xcode in a little bit of... Let me show it to you in action a little bit. First of all, let's go back to those find results. So I had that funny, weird... text field, and I don't really like that. So let's go ahead and rebuild the project.
So as we rebuild the project, we will get some errors and warnings show up. So we get all these funny errors and warnings. Now, what are they about? Well, it's because at one in the morning I didn't convert
[Transcript missing]
And if the whole help system were here, we would have had something pop up there. But that didn't quite happen. Let's pop it up by hand and see whether or not we can find this constant.
So in fact, it's not too far away. So there's actually a status. It turns out that each of these guys have a counterpart
[Transcript missing]
All the way through, but let's go ahead and do this again. You'll see that we end up with fewer warning messages this time.
So we've seen the documentation window. Sometimes I have found it useful to actually pull up the entire build window that you may have seen or remember from the project builder instantiation. But in any case, sometimes link errors and other things are best resolved using the standard build window. So let's see whether or not we can run this again.
In this case, let's pick this guy. So at the beginning, I said that I'd tell you what that IE stood for. Turns out that on some motorcycles, they have model numbers. And in this case, This happened to be my latest toy. It happens to be a Monster 620 IE. And so I just decided I had to call it IE.
for whatever reason. So motorcycles are great to look at when they're not moving at all. But of course, they're even nicer
[Transcript missing]
We're going to be using a lot of wheel off the ground, so luckily the resolution on this isn't very good for that. But, you know, you've got to be really careful when you're out on public roadways.
That's it for the demo. I think I've shown most of what I needed to see. Let's flip back to slides. If I could find my clicker. And actually, the address book-- that's where that slide went. I knew I had an extra slide in there. The address book APIs are as I showed you. What I tried to do in this talk is-- is giving you a sample of what you can try to get into. Nope, I need to go back to this demo. I'm sorry. I have to show you one other piece of code back here.
There's also a nice little piece of code. Here it is. Now this is super succinct. This is run a setup panel to go pick your device. sets the speed, sets it multi-session, sets all kinds of options on a nice little panel. And when you're done setting up the panel, you hit OK. It comes back.
And then you pop up this burn progress panel and tell it to go run. It's very simple, and it doesn't work. It's a shame. But it is because the AWT needs to own things, needs to own locks that's going on over on the AppKit side. And this burn panel just gets very confused.
So there are some things you can do, and there are some things you can't do. You guys have to be careful about what you try to do because you want your apps to run for a long time. I guess that's the best message I have here. All right, let's go to some Q&A. Okay.
We still have a couple other talks. I'm sorry. The WebKit API is tomorrow. We have a feedback session tomorrow morning in the marina. And we have our performance talk, of course, tomorrow afternoon, which has a lot of great details about what's really going on with the processors and what we've done to help make that happen.