WWDC2001 Session 507
Transcript
Kind: captions Language: en please welcome John summers quick time Java engineering thank you and welcome to session 507 quick time for Java now today we're going to be taking you through some of the new features in quick time for Java specifically those that support QuickTime 5 features but before we do that I want to move on to show you basically the QuickTime for Java is built of two major components QuickTime which is Apple's proprietary media architecture it's mature cross-platform flexible as a rich set of services which support industry standard media formats such as dynamic media that is audio and video and a wealth of still image importers and exporters and also interactive media such as QuickTime VR and wired sprites Java from Sun Microsystems is a modern object-oriented interpreted language you can deploy Java cross-platform as standalone applications java applications and applets so that briefly is the basis of cook time for java this is what it's built on now the actual implementation of QuickTime for Java QuickTime for Java is a cross-platform Java class library accessing the native QuickTime C libraries it has a core layer which is an object model that represents the QuickTime C API this is represented as a set of Java classes which have been grouped into logical packages also QuickTime for Java has a sophisticated application framework of obstructed media services to simplify the integration of QuickTime and Java quick time for Java delivers on the promise of Java in that it has an identical API across all supported platforms and operating systems you can write Java applications which use QuickTime for Java on any of the supported applications and deliver that jar to to run on all the supported platforms so in brief QuickTime Java architecture relies on core services from QuickTime from Java and from the operating system QuickTime for Java 5 which is the version of QuickTime for Java shipping in Apple's current version of QuickTime that is QuickTime version 5 supports a new brand-new operating system Mac OS 10 with apple's implementation of java 2 standard edition as well quicktime for Java 5 continue to support classic Mac OS with Macintosh runtime for Java 2.1 and above and this is based on Java development kit one one eight QuickTime for Java five also continues to support and has enhanced support for Microsoft operating systems the windows 95 98 ME family and Windows NT and 2000 family operating systems and require to have installed a Sun compliant jump Java Runtime Edition 1.1 and also will run with Java to QuickTime for Java 5 has specific enhancements for this new and new Java 2 environment there are improvements to the Java 2 security model and I believe there is a session tomorrow if you're interested in Java security specific enhancements in QuickTime for Java have been changes due to issues with garbage collection with the hot spot clock Impala so quick time for Java five has new support for the new features in QuickTime 5 some of the new features in QuickTime 5 is the XML package ton for Java has an XML parser package which allows you access and we'll talk about this later and QuickTime 5 also has a new broadcast API and QuickTime for Java 5 supports quick times broadcast API with the presentation package and Michael will give you a demonstration of that this afternoon as well time for Java 5 has full coverage of the QuickTime for API all of the QuickTime functionality up to and including QuickTime 5 are available through QuickTime for Java as well this release of QuickTime for Java 5 has additional functionality and enhanced services now I'd like to go on to to a key piece of multimedia presentations which is time-based multimedia presentations we can think of a movie time base as having two particular has a rate which is the rate at which the time base is moving and also a current time which is that for a movie time base it's the place in time where the playhead is quick time for Java implements time-based callbacks so that you can receive notification in your quick time your quick time for java application that is a an application written in java and utilizing quicktime for java you can get receive notification of time-based events as you can see from the diagram when the playhead reaches a certain time in the movie you can execute your own java code now what are these time-based events they can execute at a certain time that is at a certain time within the movie at intervals you may want to have a ticker in the movie so that you get notified every second or and also you can have callbacks which fire at extremes so you can find get notification that your movie has finished and you can also have callbacks for notification of rate change that is when the movie starts when the movie stops now when a movie starts playing the rate change goes from zero a rate change of zero means the movies not playing to a rate change of 1 means the movie is moving forward at normals at normal play rate to play the movie backwards you would change the right to minus 1 now the reason why I'm going on about time bases is that because they've been reworked in QuickTime for Java 5 they are now much more efficient they have they are now implemented using high priority of native threads for efficiency they deliver your Java code executing very close to the time that the callback was actually fired also this this rework means that it could QuickTime callbacks now have an implicit borrowing mechanism you no longer have to have a time at asking thread polling for when these events occur so now I'd like to move on to the demo to actually show you QuickTime callbacks here we have on 10 a java application written which use a lot which utilizes quick time for java specifically this application has been written to have a number of callbacks the first callback I'll demonstrate is time-jumping as you can see in the console we can find out where the movie where the user scrubs the controller to now we will start the movie and you will notice that we have a rate callback change I'll just stop the movie a rate callback change a rate change callback so the rate goes to 1 that is the movies playing also we have a ticker that is a time a time callback which is being called every second now because of the reworked time-based implementation you'll see the accuracy we can't measure that the latency of the top from the time that the callback is actually called to the time that your Java code executes we can't measure it on 10 so we'll restart the movie and as you can see you have time base callback being called once a second just out of interest this is a says a timescale about 20 million years per second this is a flaw dynamic simulation of the collision of two galaxies and if we stop the movie right goes to zero start the movie again now the movie has stopped and two events have occurred we have an extreme score back to say that the movie has reached the end of the time-base we also have another rate callback a rate callback so the movie has stopped the rate has gone to zero and I think we'll go back to slides now to explain this oops excuse me some advice some advice for actually using time-based callbacks is that time-based callbacks require explicit cleanup that is on exit you must call counsel and clean up counsel will cancel the callback and clean up will remove system resources in use if you want to stop or just reschedule the callback use canceled use the cancel method of time base class for more sophisticated timing services you should really look at the application framework where there are some very nice classes such as the timer class and its target client ticklish objects and also if you want to make a presentation which has different elements which are time slow that is the rate of one object will control the rate of all the other media objects within that presentation then the application framework has some very nice services for time slaving now I'd like to introduce a new feature and an enhancement of the QuickTime VR instance methods in QuickTime Java 5 specifically we are supporting the interaction properties of QuickTime vr5 these new interaction properties deal with panorama mouse click properties this is the time from when the time or the number of pixels moved before the mouse click gesture becomes an ordinary panning gesture that is the mouse click will timeout also speed of angle change properties this is a multiplier factor for the pan and tilt you'll see you'll see this quite well in the demo that basically if you if the user is panning across he's using the mouse to pan across a panorama and you change the pan tilt speed the panorama will speed up or slow down similarly for VR objects you have a mouse motion scale which allows you to change the number of pixels the user must move the mouse in order to either rotate to rotate the object and also we have a getter and setter for zoom speed you can change the zoom speed which is the zoom in on the z axis for quick time vr objects have two modes they have a rotation or translation that is normally you can rotate a VR object or you can put it into translation mode so that if it zoomed in see the user interaction will be to move the stet single image rather than rotating the object and in quick time quick time for Java we give you access to the two the two properties translate onmousedown which allows you to change the translate or rotate property the property to either rotate or translate or the nudge mode and this is similar to the mouse down mode except it works with the arrow keys and there we have three States rotate translate or the same as the translate our mouse down now I'd like to show you a demonstration over QuickTime VR with these properties now here we have a quicktime BR and well first of all the the java application has printed out some information first of all we've installed an intercept Proc now we've been able to do this with QuickTime for Java 4 and this is one of the powerful things about QuickTime for Java it's very easy to create great dynamic functionality within a presentation of they are we've also have another callback which is the mouse over proc and this is basically the one we will be setting getting and setting and checking some of these new properties now the pan tilt speed that is the factor that multiplies the users interaction with the panorama is when we come into the panorama is set to 5 which is the default and just for reference the field of view is almost 40 degrees when we enter a hotspot as you can see Michael has entered a hot spot before that the speed would go up to 8 so that if we pan slowly towards this hot spot when it enters the hot spot I'll have a notification and we'll increase the speed and when we leave the hot spot it will slow back down again the field of view has not been changed I'll go back in because I also have another more functionality in this demonstration that when we click we zoom in and when we leave the hot spot it reverts to normal so here we have a hot spot this topped hot spot number 74 where if we entered and if we entered the hot spot with while panning the speed would increase again so we'll do that as we enter the hot spot we go past it quite quickly now the mouse hysteresis and the property I'll just demonstrate that so basically I'm going to click in this hot spot and we have a time out of 30 ticks half a second we can change that property I haven't done this in this particular demonstration so here we have another hot spot and this one will be a very slow hot spot so we'll pan into it quite quickly and the user experience is that over their particular hot spot that's an important hot spot you've slowed down okay can we return to slides please now this sort of functionality is very easy to achieve a QuickTime VR with QuickTime for Java I have some demonstration some of the source code this is very simple source code basically we create a qtvr instance using the movie controller and getting the qtvr track from the movie then we set the mouse over prop and the execute function which is a which is an override of the qtvr mouse over hotspot implementation has two actions basically it looks at the action selector coming in and when we enter a hotspot we set the pan tilt speed to some function of the hotspot ID this is a very quick demo else when we leave the hotspot we reset the pan tilt speed to normal now I'd like to move on and let Michael tell you about the improved support for the sound manager thank you John I love having the clicker okay today we're going to talk about some of the new sound manager support in QuickTime for Java 5 this has been greatly enhanced from our previous release to include the additional support of asynchronous recording and playback we've also provided the functionality of being able to access the equalizer for the sound channel so you can get get the values of the treble and bass equalizers and also you can play with level metering turn that on and off get the status of that now keep in mind that this is the classic sound manager support that is built into QuickTime it's not the same as the core Audio API which is native in Mac OS 10 there are some other sessions later on in the show it will in fact there's some today and a few tomorrow on that and that API is accessible from Java however since it's 10 only we recommend that if you do need to do cross-platform sound development the e is our sound manager support in QuickTime and since we've added a whole lot of new functionality which makes it really nice to use so what have we done in the new sound manager we've added an extended scheduled sound header class this allows you to send buffered sound commands we've also added an SC Status class and with that you can get the status of the sound channel you can determine whether it's busy whether there's a sound playing and and other operations we also have an si completion class that enables you to register a completion routine that will be a get called upon completion of asynchronous recording so that your application can be notified when recording is complete and then save that sound somewhere or play it back to the user and finally we've added some additional constants in the sound constants class to expose some of those new constants that weren't previously available and these include things like new sound commands as we're going to talk about in the next slide so how do you use the new sound manager and what else have we done we've enhanced the sound channel class significantly to provide support for du command and also do immediate the do command when you call that places the sound command such as a callback command or a buffer command or a playback command into the command queue and execute that command immediately we're that's the do immediate call whereas the do command will place that command into the queue of commands to be executed by the sound channel and when the sound channel is executed all its prior cued commands and we'll go ahead and execute that one as well so the primary difference between doing media is that it skips that that cue reverses du command which places the command at the end of the queue we also have support for a new callback command which we'll talk about in detail later which enables you to to get a callback when when your command is executed and we also have some new informational accessors that I alluded to previously the get level of metering on and off and also a set level metering on and off so let's look at how you use these in your code the first thing we're going to talk about is recording a sampled sound and these slides are not not in full detail we do have some excellent sound examples as part of the SDK so if you really want to take a look at this in detail versus this high level discussion please go see that and we will show you where to download that at the end of our presentation so the first thing you need to do to record a sample sound is prepare the sound Channel and the way you do that is you create a new sound input device by calling new SPV device and passing in whatever permissions are appropriate for that type of device for example most microphones you can't write to so you'd want to just do read with that also you need to allocate a new sound channel and pass the number of channels the rate the sample size and the compression type of the sound that you'll be using and you can also just retrieve that from the sound input device if you want so you can get the defaults for that so it's actually pretty easy once you've created the sound Channel you create a new sound input parameter block which you need to pass in that you need to create the new SP be passing the device that you'll be using and then the buffer size which is the size of that you're going to use tip for the data and also the sound handle you need to pass in where that's going to be stored in the sound handle then you can optionally specify a completion proc that will get called upon completion of the recording and you call that by overriding and the the si completion class and then overriding the execute method so once you've done all that and you want to record the sound simply called record from your SP B object and then the sound will start recording so that's recording let's look at playback to playback the sound asynchronously which is the more interesting case you need to prepare a sound command in this case we're demonstrating how to use it with the buffer command which will do asynchronous callback versus the play command which doesn't so you create a new sound command object specifying the command that you wish D is and then in the case of a buffer command you also need to set the buffer that you'll be playing from and give that to command so you do that by calling step buffer and then finally called do command on the sound Channel and that will place that buffer command at the end of the queue in the sound Channel if you wish to schedule a callback you need to create a sound command excuse me a callback command and put that into the channel as well but before you do so when you allocate the sound channel you specify the sound callback to be used at that time so a good example of reasons why you'd want to do this is if you need a sound in the background that's going to loop over and over again so you could create a sound callback that would detect would be placed on the end of the queue after a sound had been playing when the play command popped off the queue your callback command would get fired and that could put a new sound play or a sound buffer command into the queue and also put another callback command onto the queue and so that would continually loop so that's pretty much all there is for playing a sound when you're using sounds there couple things that you need to be aware of and cognizant of and the first is that you need to make sure that you dispose of all your sound channels when you're done playing them you can do that by calling dispose cutey object on the sound Channel and if you like you can do that directly from a call back it's it's very important to do that as opposed to waiting for the garbage collector clean to clean you up because that can be a lot of native data additionally if you have any completion routines that you've specified and registered with the SPB device go ahead and remove those as well by calling remove completion proc and finally there are a couple of garbage collection issues you need to keep in mind if you have sound objects on the stack they can go out of scope so be aware of your use of local variables some manager doesn't get happy it isn't happy if buffers for the first sound that's supposed to be playing get get garbage collected on you also make sure that you dispose of any objects that you use within a callback before you dispose of the callback itself and keeping in mind those guidelines will make sure that your experience using audio is a sound one I know that was bad couldn't help it okay so now we're gonna look at a new area of quicktime for java 5 which is the presentation API and a bit of an overview first for those of you that haven't seen any of the previous QuickTime sessions there was a presentation section and that that showed the new API available with QuickTime for Java a QuickTime 5 that we implemented in QuickTime for Java as well this enables you to broadcast from any source that is sequence grabber compatible audio devices such as two turntables and a microphone or any DV audio source also video devices as well and you can specify that that broadcast is unicast or multicast going to a single machine or to a number of machines on the same network and the broadcast is also used or configurable via a settings dialog which we'll see in the demo to follow so let's look at how this works from a client side the broadcaster is a machine that has some sort of device such as a camera can did and it also specifies it has a you an SDP file which stands for stinky dead pigeon no actually it doesn't it's the stream data protocol and that's a standard in a standard for specifying how streaming will be sent across the network and so we use that standard as part of QuickTime since we are a standard space technology so once you specify the SDP file to configure your broadcast then those packets are going to go out onto the network and onto any machines which are also viewing the same SDP file and in this case the illustration shows that those machines are just using the Qt player to open the FTP file and that doesn't have to be a player it can be any application that is capable of opening a movie so let's look at the broadcaster in more detail now on that broadcast machine we have a video camera which is the source of the broadcast that goes through the sequence grabber into the sorcerer object we also have a presentation that encapsulates all these various units within the broadcaster and the presentation you can think of is kind of like the top level component or a movie that contains all these other objects within it that's configured by the SDP file which specifies whether there's audio whether there's video what the whether its unicast or multicast what the sample rate is what the form compression type of that broadcast is going to be once that is specified that's going to affect the packet Iser which is responsible from taking the data from the source or object and splitting up into little packets that it can then send out on the network in an efficient manner so that packet Iser is going to be affected greatly by the compression type that's being used by the sorcerer component for example there are packetize errs that are specific to Sorenson that know a lot more about its format and can more efficiently send out those packets and finally we have the streamer which is report which is required for actually sending the packets out on the wire so that's how the presentation works and how do we map this in a quick time for Java we have a presentation API that's been placed in the QuickTime streaming package and we represent that presentation or streaming session by a presentation object we the streaming session is configurable again via settings dialog which we'll show you in our demo coming up and we have a streamlined API available now and we'll be releasing additional features of the API in the future to allow you to do things other than just using the sequence grabber oops skip the slide so let's go over to the demo and we have a video camera here it's going to be digitizing all you happy people in the audience so what I'm going to do first is I'm running a QuickTime for Java applet and I'm selecting an FTP file which as I mentioned previously it's simply just a text file and at that point then the the settings dialog is going to come up let me move that onto the monitor so you can see it and in the on the top side you see the settings for the audio and including the component that that's coming from which is actually in this case coming from the sequence grabber I'm going to go ahead and edit the sound settings here too since I don't really care about audio I'm going to cut that down a little bit and then so that's the component responsible for compression and then on the right side you see the packet Iser that's going to use to send that out and I'm just gonna use the QuickTime packet Iser you'll note that it also is recognized that I'm sending an 8-bit sound so there's a special packet Iser for that however since my fdpp file specified that the packet Iser would be quicktime i need to make sure that I use the same packet Iser otherwise the client will be looking for a different packet Iser and then what's being broadcast and it won't pick that up and you can see that I'm using a DV video source and I'm going to go ahead and turn down the quality at a little bit that's fine and let's increase the keyframe frequency slightly so actually see some data and then I'm going to go ahead and hit okay and we'll look at the broadcast so once I click the start button you can see now that this is what we're digging from the camera and on the other machine we're going to go ahead now and open the same SDP file up in the QuickTime Player so you can see what's actually being broadcasted across the network and this is a multicast presentation and as such if more than one machine could go ahead and and receive that broadcast and as you can see we have a little lens flare going on there's somebody in the back waving fiendishly feverishly maybe fiendishly as well so there we go we're doing a live broadcast from a TV camera plugged in through a firewire report from a quicktime for java app being all on ten and being received on a you receiving that to John no use just waving okay anyway so that game people get so crazy when their video cameras on them alright so I'm going to go ahead and stop that now and go back to slides a live presentation on a Java machine can't do that without QuickTime and that's the beauty of QuickTime for Java it gives you a very elegant simplified interface that lets you to do some very powerful features that would take tons and tons and tons of code we're looking at the code now natively this would take thousands of lines of code but in QuickTime for Java and in the example sent out on the SDK you'll see that there's really only a couple of lines of code since we've taken care of a lot of the details for you you can specify advanced modes but you're not required to so let's look at the presentation API to create a presentation you can call presentation from file and specify an SDP file you can also specify an XML file if you like and then your presentation parameters which is an object that lets you specify the sound rate etc and data rate then if you like you need to show your settings dialog by calling the settings dialog and pass in your presentation object as the note says and as I previously mentioned I have to reiterate that you're the users responsible the broadcaster for choosing a setting that makes sense based on what the SDP file is specifying for the type of broadcast since the client that's using that SDP file is only gonna look for a specific format a packet Iser and if you choose a different one well the clients gonna say that's not the broadcast I'm looking for so it won't find it so make sure you do that correctly to prepare and start a presentation you simply pre-roll your presentation and then call start on it there's also a callback that you can receive a QuickTime for Java does support that will allow you to determine if the pre-roll has actually occurred and that can be important if you have a slow device that you're grabbing from that just isn't ready yet once it's ready you call start and to stop you call stop this as easy as it can get so oh but there's a little bit more sorry for God you do have to actually set up an idler you can create a new a thread that's gonna be responsible for calling presentation idle and that's the mechanism that will go ahead and keep the sequence grabber running and go ahead and actually do all the compression and packetization and we recommend that you do that in a test thread and you can specify on the task thread both a string name which will allow you to easily recognize it in a debugger and also a rate of which that thread is going to get serviced in this case we chose 20 milliseconds because that seems to be a good value and then when you override your task method you just call idle and that's really all you need to do to do a live broadcast from any source supported by the sequence grabber in QuickTime for Java again we encourage you to look at the SDK code later if you're interested and now I'm going to turn the presentation over to John summers again who's going to talk about transition enhancements thank you Michael transitions quick time for Java 5 now supports enhanced transitions to go back transitions are QuickTime effects cool time effects architecture has a large number of effects that you can apply to still images that is a single source and that this is a represented as a QuickTime filter a QT filter in QT for Java or can be applied between multiple sources a QuickTime transition the main enhancement has been to the parameter dialog in QT Java for we supported editing create sorry creation of a QuickTime parameter quick time quick time out of container which contains the data for a quick time effect and in QuickTime for Java 5 we've extended the parameter dialog so that now you can re-edit the parameters this is an important consideration for some of our developers and as well we have allowed you to customize the dialog by putting in optional preview pictures and another new feature of QuickTime for Java 5 is an enhancement to the atom container class specifically the insert child call we've extended the number of data types to cover all the data types found in quick time so we have all the simple data types of byte short int and float and as well object data types which we'll cover most of the all of the other data types that you'll need to actually create quick time out of containers for tween type atoms where the data is actually an array of two elements that is a start and end sample we have a new class between data which extends QT by objects so can be used directly with the insert child call for atom container and how we've constructed how we've implemented this is to overload the constructor so we take we take a start and end value and the types are short int fixed float double point fixed point etc which are all the types that you will need to create quick time between type atoms one of the things that we've done for a quick time done for Java in QuickTime for Java 5 is to change the implementation the semantics of some of the atom container calls you notice in the insert child we have a parent atom in some of the QuickTime out of container methods we have actually changed the semantics so can actually pass in null so that actually this will be recognized as being a synonym for atom 0 that is the container is the parent atom parent atom is the container and new QuickTime 5 features in QuickTime for Java 5 are support for the XML parser in QuickTime 5 we've implemented this with data classes which represent the parser the past document and elements and attributes and and XML content from the from the parsed XML stream you can get to these you can get to these elements by part bike by creating callbacks which will be called during the passing of XML so you can find out when the document parsing starts when you reach a particular element which will allow you to use the quick times XML parser for a pretty good XML parsing now I'd like to hand stage back to mark Hopkins for more new features we still have plenty of time okay additional new features in QuickTime 5 there's a brand new one that's pretty significant called drawing notification registration and what that allows you to do is register for notification when drawing and update operations occur on objects such as a compositor an effects presenter or a movie presenter and this actually allows you to do some pretty interesting things for example if you aren't really big on using time bases although that's and also an excellent API you could synchronize a framerate to the drawing by by registering as a listener for a component also if you need to do some some drawing yourself onto an off screen before you present that you could go ahead and get notification when drawing was completed and then do your additional drawing before that gets rendered to the screen so the way this works is the listener implements the drawing listener interface and they override the drawing complete method and they can put in any code in there that they wish you'll also notice that they receive the QT drawable object that generated the message within that call so you have access to determine it's time or what media it's presenting for example once you've overrated that interface you register your listener with a component by calling by creating a new listener and then adding that drawer listener to the object that you wish to register with and not shown on the slide but additionally important once you're done you can remove yourself by calling remove during listener so that's a powerful new feature that we've added but we're not done yet we've added an is sizing option in QT canvas a very strange named one called K initial size no resize and for those of you harass QT Java programmers you may think well there's already a K initial size a sizing option well that one allowed an object contained within a canvas within a window to grow smaller but not increase in size whereas this new sizing option absolutely specifies that that canvas will not grow or shrink regardless of what happens to its parent window additionally we have a new interface called standard QT constants v and oddly enough this represents newly defined constants in the QT 5 API and this supplements previous constants such as the standard QT constants 4 which represents QT for API and standard QT constants which is QT 3 and previous so anything that's in 5 is specifically going to be in that new standard constants 5 interface so hopefully at this point nobody is confused we've added a lot of new functionality in our product we have a brand new operating system that we're supporting in a very very high fashion and that's Mac OS 10 we've added new support for compositing a new support for for broadcasting new support for time base we work through a lot of new features that are part of the 5 API and as such you as a developer may have a lot of questions about this but there are good places to get answers the first of which is the public mailing list it's available for Qt Java developers you can go to list a palom and sign up for the Qt Java list and that's an excellent place for you to go out and get information or ask some questions if you're having difficulty when we highly encourage that because that's a very good community for a quick time for Java developers also I mentioned previously the Qt Java SDK we have five new examples and that s clay and that includes all of the things that we've covered today so you can get examples for that in that SDK so it's a developer.apple.com slash QuickTime slash Katy Java finally if you want to be part of our seed program I assume everybody's a registered developer here so if you want to get in on that and get access to pre releases of our software please send a mail to cutie job at apple.com and we'll get you on that and we really appreciate your feedback and find out what things are important to you and see how we're doing so additionally I would be shot dead if I didn't plug bills book there's an excellent book called call them QuickTime for Java programming well I'm sure all of you are aware of that it's an excellent book that has a great overview of some of the concepts that QuickTime for Java were built on as well as a reference in the back so again we recommend that so this build the publisher the publisher Morgan and Kaufman and you can find that on amazon.com even I believe ok so I know it's Thursday and a lot of you feel like WWDC is almost over but there's still a number of excellent sessions coming up we have the quick time feedback forum immediately after this over in j1 it's a good place to come bring your constructive criticism about things in QuickTime you'd like to see additionally immediately after the session john burke 'is going to give a killer java graphics demo and that's really important because there's quick time for java developers you will be interacting with things like swing in the Java API 2d API so those are some good things to do if you want to learn about some of those other ways of rendering in Java additionally we have some excellent audio services class in in j2 here at j2 at 5:00 where you can learn about the audio services on Mac OS 10 and there is as I mentioned a Java API for that as well so you can call that with Java and that's a great way if you're a 10 only developer to make use of some really advanced functionality additionally for those of you they're deploying applets please see Java security tomorrow at 9:00 and then of course the Java feedback forum tomorrow at 10:30 you