diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-15FDDEED-89F1-5BE5-97AD-8DFD3640369A.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-15FDDEED-89F1-5BE5-97AD-8DFD3640369A.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,101 @@ + + + + + +Playback +operationDescribes the operation of the Sound Driver for sound playback. +
Normal operation

The client calls RSoundSc::PlayData() to +issue an audio request.

The LDD breaks the audio request into manageable +fragments and transfers them to the PDD by calling DSoundScPdd::TransferData().

When +the PDD has transmitted the fragment it calls DSoundScLdd::PlayCallback() to +signal to the LDD that it has finished transfer of a fragment. When the client +request has been completed, the LDD calls DSoundScPdd::StopTransfer() to +stop the PDD transmitting data and to release any transfer specific resources.

To +ensure uninterrupted playback, a client must have multiple play requests pending +on the driver. As soon as one request completes, the client issues a further +request until the end of the track. Typically, a client issues a series of +calls to RSoundSc::PlayData() to play an audio track.

Each RSoundSc::PlayData() request +is handled in the context of the driver's Deferred Function Call (DFC) thread. +Assuming that the driver is not already in the process of playing data when +the first request is received, the LDD checks whether the client has specified +or supplied a shared +chunk to the Driver +channel and also whether the audio configuration and volume have both +been set. If the chunk configuration has not been specified, then the driver +cannot proceed and returns KErrNotReady. However, if the +audio configuration or volume has not been specified, then the LDD simply +applies default settings to the audio hardware device. These values are returned +by the PDD functions DSoundScPdd::SetConfig() and DSoundScPdd::SetVolume() when +called by the LDD.

The LDD may need to break the play request down +into fragments to support the maximum amount of data that the PDD can handle +in a single transfer. The function DSoundScPdd::MaxTransferLen() returns +this maximum value. The LDD queues as many transfer fragments on the PDD as +it can accept with a call to DSoundScPdd::TransferData() for +each fragment.

To support uninterrupted transfer of audio data, the +PDD must be able to accept at least two transfer fragments simultaneously: +the first being actively transferred by the audio hardware device, the other +being queued for transfer on the same device. Therefore, as long as the LDD +has transfer fragments still to queue, it continues to call DSoundScPdd::TransferData() on +the PDD until this signals that it has temporarily reached its capacity, by +returning KErrNotReady.

If the PDD accepts all the +fragments for this initial play request then the LDD moves on to process the +subsequent requests from the client. These are also fragmented until either +the PDD reaches its capacity or all pending play requests are queued.

Each +time the PDD completes the transfer of a fragment from a play buffer, it must +signal this event back to the LDD by calling the function DSoundScLdd::PlayCallback(). +This must always be called in the context of the driver DFC thread so there +are no synchronisation problems. For example, where transfer completion interrupts +the processing of new play requests from the client.

In executing DSoundScLdd::PlayCallback(), +the LDD checks whether the entire transfer for the current request is now +complete. If so, it signals completion back to the client. Also within the DSoundScLdd::PlayCallback() function, +the LDD will attempt to queue further fragments on the PDD, by calling DSoundScPdd::TransferData(), +as the PDD should now have the capability to accept more transfers. The PDD +must be written to handle calls to DSoundScPdd::TransferData() within +its callback to DSoundScLdd::PlayCallBack().

If, +on completing a request from the client, the LDD discovers that there are +no further play requests pending from the client, then this is treated as +an underflow situation and KErrUnderflow is returned to the +client. If however, the client specified KSndFlagLastSample as +the aFlag argument of the RSoundSc::PlayData() function +then an underflow is expected after this request completes.

When the +audio request has been completed the LDD calls DSoundScPdd::StopTransfer() on +the PDD. This allows the PDD to release any resources necessary for transfer.

+
Pausing and resuming audio playback

The client +may temporarily halt the progress of audio playback at any time by issuing DSoundScLdd::Pause(). +In order to configure the audio hardware device to halt playback, the LDD +calls DSoundScPdd::PauseTransfer() on the PDD. Ideally, +playback should be suspended in such a way that it can be resumed later, starting +from next sample following the one last played.

The client +requests resumption of playback by calling DSoundScLdd::Resume() on +the LDD. The LDD, in turn tells the PDD to re-commence playback by calling DSoundScPdd::ResumeTransfer()

Since +access to the hardware is required in both cases, pause and resume are handled +in the context of the driver DFC thread.

+
Error handling during playback

If the PDD reports +an error when setting up the audio device for playback then the LDD immediately +completes the first play request back to the client returning the error value +as the result. For example, if the PDD returns a value other than KErrNone from +a call to the function DSoundScPdd::StartTransfer(). The +LDD attempts to re-start playback data transfer when it processes any further +play requests from the client.

If the PDD reports an error when commencing +transfer or as the result of the transfer of a playback fragment, then the +LDD ceases transfer of the associated request and instead immediately completes +the request back to the client returning the error value as the result.

Unexpected +errors from the PDD are returned to the LDD via the functions DSoundScPdd::TransferData() and DSoundScLdd::PlayCallback(). The DSoundScPdd::TransferData() function signals that +an error has occurred when setting up the transfer of a playback fragment +by returning an error value other than KErrNone or KErrNotReady. +The DSoundScLdd::PlayCallback() function called by the +PDD at the end of a transfer, signals an error to the LDD if the value passed +is not equal to KErrNone.

The LDD does not cancel +the transfer of other fragments for the same request which are already queued +on the PDD, but it ignores their outcome. However, the LDD does try to carry +on with the transfer of subsequent play requests queued by the client.

In +any of the above situations, the client may choose to terminate playback operation +by cancelling all outstanding play requests when it detects a playback error.

+
\ No newline at end of file