Symbian3/SDK/Source/GUID-21E26B07-7E4D-50E0-97BE-C05CCD88B89F.dita
changeset 0 89d6a7a84779
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-21E26B07-7E4D-50E0-97BE-C05CCD88B89F.dita	Thu Jan 21 18:18:20 2010 +0000
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-21E26B07-7E4D-50E0-97BE-C05CCD88B89F" xml:lang="en"><title>Creating
+a Sink Plugin</title><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>A data sink plugin needs to implement the pure virtual (and where appropriate
+override the virtual) base class mixin functions. This section describes how
+to implement the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> base class.</p>
+<p>Note that it is possible for a single source/sink plugin to be both a source
+and a sink, i.e. derive from both <xref href="GUID-2230F976-A798-30EB-ABA6-09C86716A4B5.dita"><apiname>MDataSource</apiname></xref> and <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref>. </p>
+<p>See <xref href="GUID-B998B8FC-3DC3-57B5-A4E6-C4D903B4ACF9.dita">Creating a Source
+Plugin</xref> for information on source/sink negotiation and data transfer.</p>
+
+
+<p><b> Sink Plugin Instantiation</b> </p>
+<p>A client application instantiates a sink plugin using the <xref href="GUID-9DEDFB0F-C963-3FB7-9237-DDDB276C8841.dita#GUID-9DEDFB0F-C963-3FB7-9237-DDDB276C8841/GUID-2D177C9B-51F7-30EE-862E-F282E28B3633"><apiname>RMMFController::AddDataSink()</apiname></xref> method,
+passing in the UID of the sink as one of the parameters. The controller framework
+instantiates a sink via the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-04B8016D-E8A3-3F00-8367-6D20C407A240"><apiname>MDataSink::NewSinkL()</apiname></xref> method
+rather than the more conventional <codeph>NewL()</codeph> method. This is
+because, in some cases, a plugin can be both a sink and a sink of multimedia
+data in which case the instantiation methods for sinks and sinks need to be
+distinct. The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> base class instantiation methods
+are described below followed by how to write the instantiation methods in
+the derived class. </p>
+<p>The derived data sink needs to implement <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-04B8016D-E8A3-3F00-8367-6D20C407A240"><apiname>MDataSink::NewSinkL()</apiname></xref> and <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-AEC3FEB6-ED46-3E73-85D6-FD298CE1DE6C"><apiname>MDataSink::ConstructSinkL()</apiname></xref> for
+instantiation. The constructor of a data sink plugin needs to specify what
+type of data sink it is. This is achieved by passing a type UID into the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> constructor. </p>
+<p>If the sink has additional methods, that are not part of the base <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> class,
+then a further layer of instantiation is required. For example, suppose <codeph>CAcmeDataSink</codeph> had
+some extra methods that were not part of the base class then an additional
+mxin interface for this class is required. For example:</p>
+<codeblock id="GUID-D81EF01A-7C6C-5EBF-BCC9-3A45378C0466" xml:space="preserve">class MAcmeDataSink : public MDataSink
+    {
+public:
+    inline static MAcmeDataSink* NewAcmeDataSinkL(TUid aImplemetationUid, const TDesC8&amp; aInitData);
+    //This allows dynamic linkage to the Class:
+    }
+</codeblock>
+<p>The <codeph>NewAcmeDataSinkL</codeph> should be implemented as follows:</p>
+<codeblock id="GUID-CDA802E2-20C6-5FEF-9429-0ED3B45322C8" xml:space="preserve">MAcmeDataSink* retPtr = static_cast&lt;MAcmeDataSink*&gt;(MDataSink::NewSinkL(aImplementationUid, aInitData));</codeblock>
+<p>The class should derive from the <codeph>MAcmeDataSink</codeph> rather
+than <codeph>MDataSink</codeph> as follows:</p>
+<codeblock id="GUID-C06D0D2C-C24A-59B6-9775-0521509C8F5B" xml:space="preserve">class CAcmeDataSink: public CBase, public MAcmeDataSink
+    {
+public:
+ MDataSink* NewSinkL();
+</codeblock>
+
+
+<p><b>Sink Plugin Buffer Creation</b> </p>
+<p>Buffers are required to transfer data between a source and a sink. These
+buffers may be created by the source and/or sink. The methods below are for
+the sink buffer creation.</p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-774C8837-30F7-39C5-ACC9-0AEC1757070C"><apiname>MDataSink::CanCreateSinkBuffer()</apiname></xref> method must be
+implemented by the data sink plugin. Most sinks should be capable of creating
+their own buffer and so would return <codeph>ETrue</codeph>. Note that just
+because a sink can create a buffer, this does not guarantee that the framework
+will actually use the buffer created by the sink. Which buffer is used depends
+on factors such as whether a null codec is used and whether the source is
+the reference buffer, in either of these cases the sink buffer will not be
+used.</p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-8D998E91-9AF2-3734-A11A-985BD15E324C"><apiname>MDataSink::CreateSinkBufferL()</apiname></xref> method is called
+by the framework to create a buffer from the sink. This method should create
+a buffer of length 0 bytes and a maximum length of an appropriate size for
+the sink. The meaning of 'appropriate' in this context depends on sink specifics,
+such as whether the sink data ultimately comes from hardware that supplies
+buffers of a certain size. Generally a larger buffer size means a smaller
+number data transfers between the sink and sink are required. The returned
+buffer must derive from <xref href="GUID-9A7A83ED-592B-3A0C-BABB-3B90099BCF7C.dita"><apiname>CMMFBuffer</apiname></xref> but will be a derived
+buffer eg <xref href="GUID-AE26E6A4-C1AD-3B35-B5F7-CE0AB60169BB.dita"><apiname>CMMFDataBuffer</apiname></xref> or a video frame buffer.</p>
+<p>The overloaded <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-8D998E91-9AF2-3734-A11A-985BD15E324C"><apiname>MDataSink::CreateSinkBufferL()</apiname></xref> method,
+which has an additional <codeph>aSinkBuffer</codeph> parameter, is optional.
+The default implementation is identical to the standard <codeph>CreateSinkBufferL</codeph> above.
+This overloaded version is used where the nature of the sink buffer may impact
+the created sink buffer. This method should only be overridden if the size
+and/or type of the sink buffer can influence the size and/or type of the created
+sink buffer.</p>
+
+
+<p><b>Sink State Methods</b> </p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> mixin provides a number of state-related
+functions used to inform a source/sink that the data path (via the controller)
+has made a transition to a particular state. These state transition methods
+are usually called on the source/sink from the datapath and so will be called
+on the data source/sink plugin. These methods are not pure virtual and so
+it is not compulsory to implement them. </p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-A6CD1868-BAF7-332E-8C35-BE3F494E3D2D"><apiname>MDataSink::SinkThreadLogon()</apiname></xref> method indicates to
+the sink that it can perform any thread specific initialisation. This is so
+that the thread in which the data sink is instantiated is not necessarily
+the same thread in which the actual transfer of data between the source and
+the sink takes place. Any thread-specific sink initialisation cannot take
+place in the <codeph>NewSinkL()</codeph> method and must instead be performed
+in the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-A6CD1868-BAF7-332E-8C35-BE3F494E3D2D"><apiname>MDataSink::SinkThreadLogon()</apiname></xref> method which is always
+called in the thread in which the data transfer between sink and sink is to
+take place.</p>
+<p>The <xref href="GUID-8512F793-107A-3166-A62F-750696D942CE.dita"><apiname>MAsyncEventHandler</apiname></xref> must also be passed into the
+sink in the same thread in which the sink is to transfer data. If the sink
+can generate events during a data transfer, then it must keep the reference
+to event handler.</p>
+<p>It is only necessary to provide an implementation of <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-A6CD1868-BAF7-332E-8C35-BE3F494E3D2D"><apiname>MDataSink::SinkThreadLogon()</apiname></xref> if
+the sink has thread specific initialisation and/or can generate events during
+data transfer.</p>
+<p>Implementation of the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-17E785C1-D177-317F-82D1-D9727CE56399"><apiname>MDataSink::SinkPrimeL()</apiname></xref>, <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-63057BF2-4730-3042-AA32-1D06F455AE17"><apiname>MDataSink::SinkPlayL()</apiname></xref>, <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-5E0447D4-A48D-35B3-AEDF-758EB249FAE2"><apiname>MDataSink::SinkPauseL()</apiname></xref> and <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-E8627DBE-5709-388E-ABB1-0FC2DB8683D2"><apiname>MDataSink::SinkStopL()</apiname></xref> methods is optional. They
+are called when a controller performs a transition to the corresponding state.
+For example, if the controller starts, or resumes, playing then <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-63057BF2-4730-3042-AA32-1D06F455AE17"><apiname>MDataSink::SinkPlayL()</apiname></xref> is
+called.</p>
+<p>Implementation of the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-67D5D509-E5C1-3A93-B4E8-E6083E16E7A5"><apiname>MDataSink::SouceThreadLogoff()</apiname></xref> method
+is optional. This method is called when the controller has finished with the
+data sink and is called in the same thread as the data transfer. This allows
+the data sink to perform any thread specific destruction such as the closure
+of handles. </p>
+
+
+<p><b>Sink Data Types</b> </p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-04666F46-042D-311C-828D-A85B65DE992E"><apiname>MDataSink::SinkDataTypeCode()</apiname></xref> method must be implemented
+by the data sink. It should return the data type of the sink for the specified
+media ID. Some data sinks may need their data type to be explicitly set, via
+the <codeph>SetSinkDataTypeCode</codeph> method or via negotiation with a
+data sink, in which case this function should either return a default <codeph>FourCC</codeph> code,
+or a <codeph>NULL</codeph> code, to indicate that the data type is not yet
+known.</p>
+<p>Implementation of the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-BB031D9F-2345-3519-88D0-D6EE0CBFEE57"><apiname>MDataSink::SetSinkDataTypeCode()</apiname></xref> method
+is optional. It should be implemented where the sink can support multiple
+data types.</p>
+
+
+<p><b>Sink Custom Commands</b> </p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-EBF981DD-9C18-3417-BAC6-57DA837D4CEA"><apiname>MDataSink::SinkCustomCommand()</apiname></xref> method facilitates
+the use of custom commands. An example implementation is shown below:</p>
+<codeblock id="GUID-C04BBBD3-9991-5478-9920-E7FFE28DB166" xml:space="preserve">void CAcmeDataSink::SinkCustomCommand(TMMFMessage&amp; aMessage)
+    {
+    // First, check we can handle message by checking its interface id
+    if (aMessage.InterfaceId() != KUidAcmeDatasinkCustomCommandInterface)
+        {
+        aMessage.Complete(KErrNotSupported);
+        return;
+        }
+
+    // Next, dispatch the command to the appropriate method.
+    TInt error = KErrNone;
+    switch (aMessage.Function())
+        {
+    case EAcmeDatasinkCustomCommandOne:
+       error = HandleCustomCommandOne(aMessage);
+       break;
+    case EAcmeDataSinkCustomCommandTwo:
+       error = HandleCustomCommandTwo(aMessage);
+       break;
+    default:
+       error = KErrNotSupported;
+       break;
+       }
+    aMessage.Complete(error);
+    }
+</codeblock>
+<p>Use of the custom command mechanism is preferable to adding extra methods
+as it avoids extra casting.</p>
+
+
+<p><b>Sink Priority Settings</b> </p>
+<p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita#GUID-708A7583-5C55-3FE1-8238-974C8821588D/GUID-B045F6E3-7D43-3EB0-8AA7-1DF58AC7AFF5"><apiname>MDataSink::SetSinkPrioritySettings()</apiname></xref> method is optional.
+It is used to provide a mechanism to determine which sink should have priority
+in cases where more than one client wishes to use the same physical sink.
+An example might be an audio output, although several audio output sinks can
+be created, the actual hardware may only have one physical speaker. Therefore,
+if one audio output is being used to play music, and another is being used
+to play a ring tone due to an incoming call, then the latter needs to take
+precedence. <xref href="GUID-AA73C7C3-5874-34D1-8879-597B0900E9F3.dita"><apiname>TMMFPrioritySettings</apiname></xref> contains an <codeph>iPriority
+TInt</codeph> data member, where 100 is maximum priority, 0 is normal and
+-100 is minimum priority. The <xref href="GUID-AA73C7C3-5874-34D1-8879-597B0900E9F3.dita#GUID-AA73C7C3-5874-34D1-8879-597B0900E9F3/GUID-3B14D763-139C-3A4E-9640-CABBC3427D6E"><apiname>TMMFPrioritySettings::TMdaPriorityPreference</apiname></xref> and <xref href="GUID-AA73C7C3-5874-34D1-8879-597B0900E9F3.dita#GUID-AA73C7C3-5874-34D1-8879-597B0900E9F3/GUID-A2E1FCFD-2058-3E1D-9FEF-C562F613C65D"><apiname>TMMFPrioritySettings::TMMFStateA</apiname></xref> data members provide further information which may be used if required.
+These specify whether the priority applies to recording or playing.</p>
+</conbody></concept>
\ No newline at end of file