WWDC2003 Session 620
Transcript
Kind: captions Language: en all right good afternoon welcome to section 620a II and for those of you 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 it's reaching out to Apple api's 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 think that's cool because Java is portable and all that and we think that's great as well but just by having your application run on our system Apple's api's and services actually reach in and extend it for you automatically somewhat because of our built some of our built-in features and some of the technology we did with the awt rewrite in top Coco however most of them 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 ati's and get a little bit more close to the platform as well as discussing how to get closer to the platform we talked about some of the pitfalls of getting a little too close to the platform so we're going to talk first of all about 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 api's and we'll give you a lot of examples about that we'll talk about launchers we'll talk about the embedded movie you a demo of our cocoa component will talk about some disk recording ati's which I have had the pleasure to discover and came over the past few weeks up until two o'clock this morning 12 hours ago and even a little bit of address book we'll have I'll also get up and do a demo of all that code so 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 QA getting you know into some of the 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 to get things in because of that we give multi-language input for free we get in quill for free how many of you people remember the inkwell demo for my thing well I can't remember what 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 you get the drivers right and inkwell will actually do input into your into your Java app and you haven't had to write a lot 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 or who knows but it is it is 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 applescript GUI scripting that we talked about and have demonstrated in some of the other talks Greg is going to come up and actually show you more of that in just about 30 seconds menu items is another thing you get for free without any effort for coding on your part in a WT style applications you get the services menu for absolutely for free you get the spell checking you get speech speaker this 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 10 where it's actually part of it it just says 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 okay did any of you see the Java State of the Union where I did this demo no okay bout 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 you to stay the Union and I'll get to that 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 fact and it uses the brush my 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 a 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 it I also set it up that it works as an applet and so you could see that inside of Safari the Java brushed metal look and feel shows up while and this is a key point for a little later when it's an applet it's a red transparent window when its application it's a great transparent window and it's the same same darn thing you know nice trivial simple kind of goofy demonstration and so 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 10 can help you write better java applications so first off we have the apple animating here there's a great program on mac OS tchenka ports to buzz one way to speed up your program is not to have it draw a lot so one thing that courts to bug has here is flash screen updates when I first wrote this I was repainting the entire transparent window every time it was a little slow and then I went and figured out that i could make sure i only draw the job of parts i'm interested in it kind of slows things down a little bit when courts does this but you could 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 Apple script what I have is an applescript I have an apple script here that will use the mac OS 10 accessibility and Java accessibility integration the Java API is have accessibility where all your users can learn about the buttons like they can use screen readers or zoom in where it's large if they have difficulty seeing or some such but what's also cools the accessibility api's are also Apple scriptable so it uses the same thing what you see here is its telling Java the first window which is this window and then it goes and it finds the button title 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 job a logo so this is pure Java code being Apple scripted your program can be used now I'll add a picture and a friend man and lastly a picture of God 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 10 no extra Java code is necessary if you have custard 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 job of accessibility setup so necklace time no seeum you have a custom component you'd have to wire it up the job of accessibility and then when it runs on mac OS 10 a short 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 java dev 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 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 a QuickTime flash you name it you got it I even have this setup because I like to twist with people's heads this is the applet version of this Java program running and running in the cocoa component there's still something a little wrong yeah but you know oh no this did not happen when I all I'm disappointed huh well that's no fun here we go oh they got to now okay well you know I did it in a day so I could show you very oh well there we go I could show you in very easily how I did this we have this great component composer cocoa component that we added to our awt this is where its custom McIlroy's time work that's the name 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 set URL that you just pass a string to it this is the send message api 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 yeah it's really 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 0 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 NS string and then call load request on it so it works very nice and easily um what else was I going to show you I believe that's all for now if you want to learn more about Mac os10 accessibility there's a session tomorrow morning and I imagine they'll have more than Apple GUI scripting and the other built-in accessibility API is that there are more of a real screen reader that all your users would use thank actually 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 it 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 when 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 Coco 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 want to talk about was extended apple scripting so what we've shown you so far is how to screw up the GUI how to strip the stuff that comes for free with accessibility so standard scripting we've already handle 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 automatically scripting as you just saw so advanced scripting I mean if there are applescript aficionados in this audience then what they're kind of looking I can't see them luckily because they'd 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 cases 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 him the jump and he would have told them to do other kinds of things so if this is the kind of Apple script thing you want to do then you have to learn a lot more about Apple scripting so what happens is that Coco offers lots of wrappers for these nowadays they're all in NS script something or other classes and you add dictionaries and hang them on to your hang them on to your a proper 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 than Coco will go and find out and update it for you automatically now the very interesting thing is that we've had apple scripting at this level available to Coco Java programmers for several years now an incident in one of the examples there so if you like Coco a lot and you like Java a lot we've always kind of steered you towards Coco 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 44 pure job for swing phase programs I'm not saying it's impossible it's just I didn't I wasn't able to unravel in the past two weeks so there may be hope for it though that's just kind of a caveat on what we were 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 the thread I'm going to assume that all of you have sat in front of at least jdb or hopefully even GV and have seen you know a back trace of your program running if you've seen a back trace 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 back tre so I took out a few frames so what's the fridge it's just basic review it's a from the kernels of you pointed to set it's a set of registers and the stack that goes with the flow control it gets scheduled and all that processes start with one threads 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 was its carbon or whether that's Koko's this has always been true we have had to stand on our heads in 131 in order to not kick off carbon at the wrong time in the past we are not standing on our head anymore in the 141 stuff we are actually 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 gone from somewhere it just looks like this you you gather are your arguments you you find this VM thing Jay and I create vm you then once you have a vm you go off and you find your main class you get all these fields or method descriptors and whatnot you invoke it it goes off it does something sometimes you know it you know creates a jframe which brings up your app and then the main thread just returns so 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 and then of course we have to put a little bit of code back there respond the thread and to get it going and then the key element there is that very first thread has to do this thing called running the run loop so 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 you know the vm started or gathering arguments and stuff and running the run loop it will if it's done properly spawn up a second thread which goes off launches find 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 I or whatever you're going to have a second thread if it's got gooey if it's launched a jframe then there's a thread that we've created on your behalf which we call the event the awt event queue thread the that first thread if I get named it explicitly we call the app kit main thread and of course there could be other threads in your program I know that from the vm perspective the vm has a few threads going on telling you what's what helping helping make java really happen and then you have your own thread as well so the duties of that first thread that run loop is a data structure and what it has is a number of inputs inputs like the keyboard the mouse different kinds of i/o communications to other helper processes and things like that they manage that in a run loop and for every input that's in that run loop there's a handler for it more or lessen when you run the run Luke you're basically saying grab an input and dispatch it to the handler so in our case for example if you get some kind of mouse event or something the awt peer implementation takes that input from as a cocoa of that and transforms it and sticks it over onto a cue that's read by the by day to be T of n Q thread so that's how threading fred's get set up and run on every Mac os10 application so we don't really care of that second thread that just started a jframe goes away but if you had just taken raw code from some other system over and that first thread went away and 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 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 os10 system so that whole business we call launchers so we have actually q standard mechanisms on the system already we have the one that underlies use urban Java and use have been java H you know there's one little magic program that does all the little duties it 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 tee program that get 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 you set up those arguments and pick which vm you run i'm not going to talk about picking VMs right now it's it's a little dicey the 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 thread a legacy code and you know not everybody comes here with pure Java code some of it actually glues down into sockets or glues it into other kinds of stuff and it's just got to be there if you have sorted the legacy code if you have say properties with change on a per launch basis different maximum memory sizes different attributes for graphic state things like that that's a kind of a semi-literate reason to not you live with our standard launcher scheme if you have a non-standard main for example you know there's no rule once you launch your own vm that you have to go thru static main that's just a Java a user been Java rule it's not 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 jus Civic who helped give an excellent talk yesterday has written a little example of that and it's on the web and the place that normal examples are at developer apple com Java go to the examples page and find out 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 accept that and the most recent release we somehow forgot to include it so it's in previous releases it will come back but at the NS movies you example what that does is that show you shows you how to embed cocoa components now Greg just got up there into the 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 Coco's app kit we have provided EA to the key cocoa component in order for you to play around with your own views or somebody else's views that they've written in koko 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 appear for us it's appear for the rest of you so the cocoa component ranges for all kinds of stuff to happen it feels those events it paints it paints on the App kit main thread and you as a sub class or just implement a few methods in order to interact with it and it's very simple to use as you as you saw for that the architecture is there to get messages from one side to the other and as I said the we have example code out there but I thought I'd actually show you how simple it is so again basic idea here is that we have a job up here we have a cocoa view you need to keep them related so the Java parts going to sit in the Java painting hierarchy and secretly over on the App get 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 you subclass cocoa component and you load your little native library and you create your little special view so Coco component actually called that method create NSU you don't even have to worry about that you have to add some value to it so in this case we're going to define three constants in the movie of you case we're going to give them a URL to load tell them to play tell them to stop and these going to be linked to buttons so when the buttons hit and ask it to play or ask it to stop they're going to send this little message with this little integer value across and in the play and stop value no extra values in the set URL we're actually going to 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 aw message class that Greg described earlier it's the same implementation in this case it feels that message ID and does a switch on the three values that 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 them any tutorial on it but trust me that it's apart from the syntax is very much like Java so in this case the NS movie alec is going to go allocate a little instance of that guy and then you're going to initialize it with the following method in it with URL mumbai reference i think is the actual method to the out to thee to the initializer and the URL we give it is a is a string we actually take a string and turn it into a URL object and the by reference i can't remember with the doc said on that so that's very easy you create or you set the movie you actually create a movie and set it to the movie view the via the trickiest part for many people is writing the jni code you know so you got to have a jni code in order to create that NS view and here we have the cocoa movie view that was the subclass we just did we alloc init it 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 met an example you all have all read it and i'm 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 a disk recording comes in two frameworks it comes in a sea-based straight framework just recording we're using plain see carbon like see you can have c or dr la dee da dee da dee da if you like programming and carbon then i'm not why i'm not sure why you're in this room but 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 base 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 is true was true in 131 if you try to interact directly with the GUI that the framework that that we that the aw uses to implement spears if you interact with it directly you are treading on very thin ice because the things we have to do to own those pure classes and keep track of what's going on well we do what we have to do and sometimes if you go try triggering gooey actions independent of what we're doing we get into all kinds of crossing 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 the two that move you 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 that you can ask whether there's needy and or not 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 to 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 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 app kit main thread and actually trigger those actions to trigger work on the AWT or trigger work on the app kit 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 J&I methods to call in and just set up set up some work so let me jump to a demo right now there's one other thing I thought was in my slides that didn't happen yet so i'll talk about that directly if we could switch to demo machine too 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 you know for past several years so I actually started with a 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 rebuild the demo that that is out there in the developer examples case and it's all worked except one little glitch I won't even tell you about that let's look let's show you let's show you one thing first of all we 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 it's sure the cocoa component so if you haven't seen this GUI before now you do I've actually set it up and sort of full screen mode a little bit because it's going to facilitate something in just a moment let's let's find address book for example 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 take a look at what's going on notice that if I go back and start taking other items then that top window reflects what's going on on the left and in this case the find results 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 giant I routine to get the first name of me and set the status field up with that with a welcome message with with my with the me name on the Jana on the hard part you know see the diving into the Apple API is right there now if that's not visible I can zoom it in a little bit ourselves that visible in the back seems to be all right so how hard is it to get knees first name you have an address book factory you get the shared address book there's one and only address book and you ask a who yass good for me you send the me message to the result of that and it brings back a navy person object which is just a big fancy dictionary big fancy property list so you ask it for the first name property you get back a string and you return that first name turned into a Java a java string and that I won't that's a utility up about here takes a string ja enough strings or unicode characters so basically we 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 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 a little bit now what this is what I've turn this in and 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 the ipod and click an application it'll you know have a little custom little application to show the movies that I also hold on there so for example we see this 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 a pink Cadillac of all things so you know you get the idea you get to start and stop the movie and 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 it 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 finders perspective when we try burning it again and voila it's preparing the disc it's writing the disc it's closing the diff actually I'm not quite sure how all how it happens all that fast because the verify step takes an extraordinary lengths of time from my perspective and we have a CD with the Greek movies burned on with the Greek 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 eighth of ET view voila look at that that menu item magically appeared during the middle of my running app my running applet when I'm a 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 if you're 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 put some chives in there but in any case Steph input channel was actually important 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 that we give you for free let me let me actually show you some of those code steps while we do that so another so I have a little so let's find everywhere I've written disc 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 just burning one we add a button that says movie burnt movie view go ahead and burn whenever I click click that and that's the buttons the buttons action second step is as we saw before to send a that's the second one sorry to send the message across to the other side not very hard third step we switch on burn movie and if we 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 colon slash slash la dee da dee da dee da something dot mov what we want is the file stuff stripped off and actually the whole last component we're actually going to burn the directory that contains the movie in it so 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 life path components so in that one little line we've actually stripped that URL down to a directory path we tell 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 there might be 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 asked if the media's blank because they could have added something 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 the dictionary of the results you get like the current status you say is this thing done and you send status back to their side release it your release the burner certain statuses have a percentage so preparing it's writing and all the sorts of stuff we get the percentage and and quantify 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 one and two in the morning let me show you what it used to look like in the core foundation style code we have good device you get the array you get the count you get the value with the index you return it you have to turn that string into 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 disc 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 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 a good cocoa code to make that simpler let me let me show you Xcode in a little bit of let me show 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 of one in the morning I didn't convert these constants in two constants like that so if I want to find out what that constant would be all I have to do is option double click on it 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 could find this constant so in fact it's not too far away so there's actually stat if it turns out that each of these guys have a counterpart without the k that shows up as an nsstring directly so I can get rid of all these warnings by getting rid of these caves it's what it boils down to so I won't necessarily do that 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 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 and in this case let's pick this guy so at the beginning I said that I 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 so I just decided I had to call it IE for whatever reason so motorcycles are great to look at when they're when they're not moving at all but of course the reason nicer see in action sir I did it is its last night I captive audience [Music] is actually illegal to lift your back knee off the ground so luckily the resolution on this isn't very good for that but you know you got to be really careful when you're out on public roadway so anyway that's it for the demo I think I've shown most of what I needed to see foot back to slide click apply my clicker and actually the address book that's where that slide when I knew I had an extra slide in there the address book ap eyes are as I showed you what I tried to do in this talk is is is give 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 set the speed such as multi-session sets all kinds of options on the nice little panel and when you've 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 app kit side and this burn panel just gets very confused so there are some things you can do and there's 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 best message I have here all right let's go to let's go to some Q&A well we still have a couple of the talks I'm sorry the WebKit api's 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 help make that happen you