Programming Java 2 Micro Edition for Symbian OS 2004 (779882), страница 33
Текст из файла (страница 33)
Thedetails are specified using the well-documented BNF syntax (AugmentedBackus–Naur Format). We’ll look at some practical examples below.In the context of MMAPI on Symbian OS, the only such communicationprotocol supported is HTTP (http://) but MMAPI also introduces anumber of other protocol options, in particular:• capture://This is used, as the name suggests, to capture live media from hardware such as an onboard camera (capture://video), microphone(capture://audio) or radio (capture://radio).• device://This allows players to be configured for tone sequences (device://tone) or MIDI data (device://midi). These are defined as static160MIDP 2.0 AND THE JTWIString members of the Manager class, denoted by TONE_DEVICE_LOCATOR and MIDI_DEVICE_LOCATOR.
The latter is not currentlysupported on Symbian OS phones.• rtp://The Real Time Protocol (RTP) allows for streaming media: playbackbegins without having to wait for all the media content to be downloaded/buffered. This is not currently supported for any media type inthe context of Symbian OS.In summary, the following set of media locator formats are currentlysupported on (at least some) Symbian OS phones:• capture://audio• capture://video• device://midi• device://tone• http://Specifying a URI is not the only way to create a Player. A secondvariant of the Manager.createPlayer() method takes as argumentsan InputStream and a String representing a MIME type:public static Player createPlayer(InputStream stream, String type)This would be used, for example, to read a byte stream from the recordmanagement system (RMS) as follows:RecordStore rs;int recordID;... // code to set up the recordstore.try {InputStream is = newByteArrayInputStream(rs.getRecord(recordID));Player p = Manager.createPlayer(is, "audio/X-wav");p.start();} catch (IOException ioe) {} catch (MediaException me) { }A final variant of the Manager.createPlayer() method takes asargument a custom data source deriving from the abstract DataSourceclass and is used to handle proprietary or application-defined protocols:Player p = Manager.createPlayer(customDataSource);OPTIONAL J2ME APIS IN THE JTWI161Note that all variants of createPlayer throw a MediaExceptionif it is not possible to create a player of the correct type (perhaps due tothat media type being unsupported).
They also throw an IOExceptionif there is a problem connecting to or reading from the source or stream.We note in passing that an IOException would be expected tooccur, if at all, only in the process of connecting to a DataSource,rather than in instantiating it. The connection is performed explicitly inclient code only in the case of a custom DataSource, before it is passedas an argument to the createPlayer() method.3.4.1.3 Playing Media ContentBecause of the complexity of what a Player does, there are necessarilyseveral stages (or states) it has to go through before it can do its playing.As we have just seen, the first stage is the creation of a Player objectvia the Manager factory class.This involves the creation of a DataSource object, which providesa standard interface to the media content.
The content is ultimatelypresented as a SourceStream, although this detail will not affect youunless you are designing a custom DataSource. The DataSourceis created implicitly on your behalf when you instantiate the Player.However, if you are working with a custom DataSource, you willinstantiate your DataSource explicitly.Creating the Player object does not initialize the data transfer,which begins at the next stage. On creation, the Player will be inthe UNREALIZED state.
Its subsequent lifecycle is described in the statediagram in Figure 3.23.Calling the realize() method causes the Player to initiate datatransfer, e.g. communicating with a server or a file system. Peer classesto marshal the data on the native side will typically be instantiated atthis point. When this method returns, the player is in the REALIZEDstate.
Calling prefetch() causes the Player to acquire the scarceand exclusive resources it needs to play the media, such as access tothe phone’s audio device. It may have to wait for another applicationto release these resources before it can move to the PREFETCHED state.Once in this state, the Player is ready to start. A call to its start()method initiates playing and moves it on to the STARTED state. In orderto interrogate the state of the Player the getState() method of thePlayer class is provided.In many cases, of course, clients of MMAPI will not be interested inthe fine distinctions of which resources are acquired by which methods.The good news is that you are free to ignore them if you wish: a callto start() on a Player in any state other than CLOSED will resultin any intermediate calls needed to realize() or prefetch() beingmade implicitly on your behalf. Of course, the price you pay will be lessfine-grained control of exception handling.162MIDP 2.0 AND THE JTWIUNREALIZEDclose()realize()REALIZEDdeallocate()close()CLOSEDprefetch()PREFETCHEDclose()stop()start()STARTEDclose()Figure 3.23 Lifecycle of a Player object.The matching methods to stop the Player are close(), deallocate() and stop().
As with the start() method, the close()method encompasses the other two, so they need not be invoked ona Player directly. You should be aware, however, that reaching theend of the media results in the Player returning to the PREFETCHEDstate, as though the stop() method had been called. The good thingabout this is that you can then conveniently replay the media by callingstart() again.However, you must ultimately call the close() method explicitly torecover all the resources associated with ‘‘realization’’ and ‘‘prefetching’’and to set to null all references to your Player so the garbage collectorcan dispose of it. (You do want to dispose of it, since a closed Playercannot be reused!)In playing media content it is often useful to work with one or moreControl objects.
These allow you to control media processing and areobtained from an implementer of the Controllable interface, in mostcases a Player, using one of the following methods:Control getControl(String controlType);Control[] getControls();DataSource also implements Controllable, thus providing custom DataSources with the flexibility to make available new ways toOPTIONAL J2ME APIS IN THE JTWI163control playback. This approach to adding controls is necessary as thereis no application-level API for making the availability of new controlsknown to the system-defined Players.A media player of a given type may support a variety of Controls.The String passed in determines the name of the interface implementedby the Control returned, which will typically be one of the pre-definedtypes in the javax.microedition.media.control subpackage:• FramePositioningControl• GUIControl• MetaDataControl• MIDIControl• PitchControl• RateControl• TempoControl• RecordControl• StopTimeControl• ToneControl• VideoControl• VolumeControl.If the type of Control you want is not available you will be returned anull value (which you should always check for!).
You will also need tocast the Control appropriately before using it:VolumeControl volC = (VolumeControl)player.getControl(“VolumeControl”);if (volC != null)volC.setVolume(50);Of these 12 controls, only the last five are currently supported onSymbian OS phones. The availability of support for the others dependson a number of factors, such as the media type and the phone model.Only ToneControl and Volumecontrol are available as part of theMIDP 2.0 audio subset. The remainder are specific to MMAPI.An alternative approach to controls is the getControls() method,which returns an array containing all available controls.
You can then useinstanceof to ascertain whether the Control you want is available:Control[] controls = player.getControls();for (int i = 0; i < controls.length; i++){164MIDP 2.0 AND THE JTWIif (controls[i] instanceof VolumeControl) {VolumeControl volC = (VolumeControl) controls[i]volC.setVolume(50);}if (controls[i] instanceof VideoControl) {VideoControl vidC = (VideoControl) controls[i]vidC.setDisplayFullScreen(true);}}// allow controls to be garbage collectedcontrols = null;Note that getControl() and getControls() cannot be invokedon a Player in the UNREALIZED or CLOSED states; doing so will causean IllegalStateException to be thrown.Aside from the use of Players, there is a further option to play simpletones or tone sequences directly using the static Manager.playTone()method.