symba (779893), страница 45
Текст из файла (страница 45)
If you’ve already called theAPPARC server, for example to distinguish audio from video, then itdoes little harm to use the MIME type.The final approach may sound counter-intuitive. If MMF or ICL can’twork out the format, how can the application architecture server? APPARCrecognition can use different algorithms – rather than just looking formagic numbers, it can look for internal information about the files. It canbe worth a go.If none of these work, it is probably safest to flag a clip as unsupported,using whatever manner your application would normally use. However,there are times when this is not sufficient and, at this point, you are mostlikely going to have to guess at the MIME type.Should you really bother about this problem? We’d suggest not, unlessit comes up as a usability problem in tests or you know you are goingto play clips from descriptors that might fall under the ‘can’t detect’category.8.5 Don’t Use CMdaAudioOutputStream for NetworkStreamingIt is a common misconception, which is understandable given the nameof the class, however, CMdaAudioOutputStream is not suitable forstreamed data, in the sense of streaming audio over a network.214BEST PRACTICEThe name of the class goes back to the days of the Media Server onSymbian OS v7.0 (see Section 1.5.1).
Its reasoning is largely lost now,but its intended use case was for playing unwrapped, raw-encoded data,to be fed into a DevSound codec. If you receive this sort of data over thenetwork, this may be a valid approach. However, it is more likely thatthe streamed data is actually formatted data, requiring use of the MMFclient utility classes and you should use the OpenUrlL()3 method of theappropriate API class.How to tell? Well if the data stream just contains continuous audio data,then CMdaAudioOutputStream might be valid.
Otherwise, look at thekind of data being transferred: ‘wrapped’ data, such as AAC or WAV files,requires a controller. You could write code that talks to the appropriatenetwork source, strips out the extra data such as headers and networkinfo, and uses CMdaAudioOutputStream to supply the encoded datato the codec. What you’d effectively be doing is writing a networkingengine in parallel with the MMF client layer itself. The feasibility of doingthis depends on the formats.
Formats such as MP3 can be supportedthis way: on many devices, the codecs skip the extra data, but noton all platforms. Using OpenUrlL() on the client utilities is arguablymore portable. Continuous PCM data can definitely be supported usingCMdaAudioOutputStream.One area where CMdaAudioOutputStream is useful is when yourapplication generates the audio data. Perhaps it decodes audio dataor generates the audio samples directly (for example, it may generate harmonic tones). You could use CMMFDevSound instead, butCMdaAudioOutputStream is generally considered easier to use. WithCMdaAudioOutputStream, your client code pushes the generatedaudio using WriteL() and you can write several chunks of data withoutwaiting for each buffer to be played by using additional chunks. CMMFDevSound works differently: it pulls data from the client code using theBufferToBeFilled() callback, which the calling code must handlein ‘good time’ or the audio may break up.
Most people find CMdaAudioOutputStream easier to use, although in theory CMMFDevSoundshould be more memory efficient.As an extra word of warning, the adaptations on particular devicesmay have more requirements over the calling sequence, particularly forthe more complex formats. They may expect additional setup calls andconstraints, such as only supplying whole frames in each WriteL(). Ingeneral, we advise that you try it to see what happens, but if you do hitproblems that might be the reason.
You’d have to seek advice on theparticular smartphone concerned.3 Note that, on S60, CVideoPlayerUtility is more likely to support your audiostream than CMdaAudioPlayerUtility, contradicting some of the advice above! Ofcourse the exact behavior depends on the controller plug-ins present on the device inquestion.USE CMdaAudioPlayerUtility TO PLAY CLIPS2158.6 Use CMdaAudioPlayerUtility to Play ToneSequence FilesAt face value, the way to play a tone sequence file is to use CMdaAudioToneUtility. However, it is also possible to play such files usingCMdaAudioPlayerUtility – device configurations include controllers to play these files, so you can play them like any other audio file.In general, using CMdaAudioPlayerUtility is preferred to CMdaAudioToneUtility.
Although it uses more runtime resources – anextra thread and several plug-ins to support controllers – the sameCMdaAudioPlayerUtility code can play not only simple tonesequence files, but also music files, recorded data, MIDI files and soon. Most of what end users think of as ‘ringtones’ are normal audio files.There is a more subtle reason for preferring CMdaAudioPlayerUtility: the format of the files supported by CMdaAudioToneUtility varies from one smartphone to another.
Although it is usually the same for devices produced by any particular manufacturer, it isprobably safer to use CMdaAudioPlayerUtility. Formats supportedentirely via a controller plug-in are not accessible by CMdaAudioToneUtility. What is supported by the DevSound of one device mightbe implemented using a controller on another. Use CMdaAudioPlayerUtility and this need not concern you.So why use CMdaAudioToneUtility? If you want to play simpletones, DTMF tones or sequences, it is still probably the simplest API touse.
If you already require a CMdaAudioToneUtility object for thispurpose, then maybe it can be doubled up to cover files too. However,this is a stretch and consistently using CMdaAudioPlayerUtility willalmost certainly require you to write less code, and it will be moreflexible.8.7 Use CMdaAudioPlayerUtility to Play ClipsThis is a generalization of the previous guideline.
You may notice thatthere are several client-facing audio APIs capable of playing differentsorts of audio file: as well as the general CMdaAudioPlayerUtility,you can use CMdaAudioRecorderUtility, there is a dedicated APIfor MIDI files and a tone utility capable of playing sequence files. Itmay be assumed that if you have a MIDI file you have to use the MIDIutility, and if you have a tone sequence file you have to use the toneutility.
As stated in Section 8.6, this is not true for tone files and it isnot true for any type of file. Even MIDI files can be played via thestandard CMdaAudioPlayerUtility interface – you only need to usethe special MIDI client utility if you want to set special, MIDI-specificparameters.216BEST PRACTICEThat does lead to the question of when to use the play facilities fromCMdaAudioRecorderUtility.
The key use case for using the recorderutility to play audio is when playing back a recording that has just beenmade.If you just want to play a file, then it is best to use CMdaAudioPlayerUtility. The plug-in scheme associated with this API playssequences or MIDI files if required, with reasonable default settingswhere applicable.
You can use virtually any file with the same code.Having said that, the recorder utility does give more progress information – the callback should tell you when playing or recording starts,while the play utility callback just tells you when playing finishes. Someapplication writers think this feature is worth the extra overheads – itallows you to delay updating your client API until it is confirmed thatplay has started.8.8 Don’t Hardwire Controller UIDs in Portable CodeSome of the MMF Open() methods have the ability to select a controllerby its UID. It is tempting to use this, but it should be avoided at all costs4since it leads to non-portable code. The controllers vary from device todevice and the same format may be supported by different controllers ondifferent devices, even those that are closely related.Rather than stating explicitly which controller to use for a givenscenario, use the default KNullUid value for the controller – it tellsMMF to go and find a suitable controller.Just because you know the correct controller for device A does notmean it is valid for device B.
Far better to be flexible and let MMF workit out – MMF looks at the data and works out what to open.There is an occasional case when you need to tell MMF the formatbecause it can’t work it out. Again resist the temptation to state thecontroller UID. The most portable solution is to state the MIME type, forexample:_LIT(KVideo3gpp, "video/3gpp");iVideoPlayer->OpenUrlL(aUrl, KUseDefaultIap, KVideo3gpp);This example is for video streaming, but the same goes for other APIstoo. By not being specific, the MMF can find the most suitable controllerfor the data.So why, you may be wondering, does this API feature exist? The straightanswer is for testing purposes.
If you are testing plug-ins, it is useful to4 For video recording, the controller UID is a required parameter but a dynamic plug-inquery and selection mechanism is provided. See Section 4.4 for details.SET CONTROLLER THREAD PRIORITIES BEFORE PLAYING OR RECORDING 217know which controller you are using. There are additional cases whereengineers writing code for a particular device wish to be very specificabout the controller to use, or perhaps engineers working for the companywho wrote a specific controller wish to ensure their applications use thecompany’s controller. Perhaps the controller has extra features they wishto exploit. If you want to write portable code that works independentlyof the specific controllers, don’t do this.There is a trick for audio recording to a file that allows you to avoidUIDs altogether; the format can be selected by choosing the appropriatefile suffix.