Symbian3/PDK/Source/GUID-21E26B07-7E4D-50E0-97BE-C05CCD88B89F.dita
changeset 1 25a17d01db0c
child 3 46218c8b8afa
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-21E26B07-7E4D-50E0-97BE-C05CCD88B89F" xml:lang="en"><title>Creating
       
    13 a Sink Plugin</title><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>A data sink plugin needs to implement the pure virtual (and where appropriate
       
    15 override the virtual) base class mixin functions. This section describes how
       
    16 to implement the <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> base class.</p>
       
    17 <p>Note that it is possible for a single source/sink plugin to be both a source
       
    18 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>
       
    19 <p>See <xref href="GUID-B998B8FC-3DC3-57B5-A4E6-C4D903B4ACF9.dita">Creating a Source
       
    20 Plugin</xref> for information on source/sink negotiation and data transfer.</p>
       
    21 
       
    22 
       
    23 <p><b> Sink Plugin Instantiation</b> </p>
       
    24 <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,
       
    25 passing in the UID of the sink as one of the parameters. The controller framework
       
    26 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
       
    27 rather than the more conventional <codeph>NewL()</codeph> method. This is
       
    28 because, in some cases, a plugin can be both a sink and a sink of multimedia
       
    29 data in which case the instantiation methods for sinks and sinks need to be
       
    30 distinct. The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> base class instantiation methods
       
    31 are described below followed by how to write the instantiation methods in
       
    32 the derived class. </p>
       
    33 <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
       
    34 instantiation. The constructor of a data sink plugin needs to specify what
       
    35 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>
       
    36 <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,
       
    37 then a further layer of instantiation is required. For example, suppose <codeph>CAcmeDataSink</codeph> had
       
    38 some extra methods that were not part of the base class then an additional
       
    39 mxin interface for this class is required. For example:</p>
       
    40 <codeblock id="GUID-D81EF01A-7C6C-5EBF-BCC9-3A45378C0466" xml:space="preserve">class MAcmeDataSink : public MDataSink
       
    41     {
       
    42 public:
       
    43     inline static MAcmeDataSink* NewAcmeDataSinkL(TUid aImplemetationUid, const TDesC8&amp; aInitData);
       
    44     //This allows dynamic linkage to the Class:
       
    45     }
       
    46 </codeblock>
       
    47 <p>The <codeph>NewAcmeDataSinkL</codeph> should be implemented as follows:</p>
       
    48 <codeblock id="GUID-CDA802E2-20C6-5FEF-9429-0ED3B45322C8" xml:space="preserve">MAcmeDataSink* retPtr = static_cast&lt;MAcmeDataSink*&gt;(MDataSink::NewSinkL(aImplementationUid, aInitData));</codeblock>
       
    49 <p>The class should derive from the <codeph>MAcmeDataSink</codeph> rather
       
    50 than <codeph>MDataSink</codeph> as follows:</p>
       
    51 <codeblock id="GUID-C06D0D2C-C24A-59B6-9775-0521509C8F5B" xml:space="preserve">class CAcmeDataSink: public CBase, public MAcmeDataSink
       
    52     {
       
    53 public:
       
    54  MDataSink* NewSinkL();
       
    55 </codeblock>
       
    56 
       
    57 
       
    58 <p><b>Sink Plugin Buffer Creation</b> </p>
       
    59 <p>Buffers are required to transfer data between a source and a sink. These
       
    60 buffers may be created by the source and/or sink. The methods below are for
       
    61 the sink buffer creation.</p>
       
    62 <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
       
    63 implemented by the data sink plugin. Most sinks should be capable of creating
       
    64 their own buffer and so would return <codeph>ETrue</codeph>. Note that just
       
    65 because a sink can create a buffer, this does not guarantee that the framework
       
    66 will actually use the buffer created by the sink. Which buffer is used depends
       
    67 on factors such as whether a null codec is used and whether the source is
       
    68 the reference buffer, in either of these cases the sink buffer will not be
       
    69 used.</p>
       
    70 <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
       
    71 by the framework to create a buffer from the sink. This method should create
       
    72 a buffer of length 0 bytes and a maximum length of an appropriate size for
       
    73 the sink. The meaning of 'appropriate' in this context depends on sink specifics,
       
    74 such as whether the sink data ultimately comes from hardware that supplies
       
    75 buffers of a certain size. Generally a larger buffer size means a smaller
       
    76 number data transfers between the sink and sink are required. The returned
       
    77 buffer must derive from <xref href="GUID-9A7A83ED-592B-3A0C-BABB-3B90099BCF7C.dita"><apiname>CMMFBuffer</apiname></xref> but will be a derived
       
    78 buffer eg <xref href="GUID-AE26E6A4-C1AD-3B35-B5F7-CE0AB60169BB.dita"><apiname>CMMFDataBuffer</apiname></xref> or a video frame buffer.</p>
       
    79 <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,
       
    80 which has an additional <codeph>aSinkBuffer</codeph> parameter, is optional.
       
    81 The default implementation is identical to the standard <codeph>CreateSinkBufferL</codeph> above.
       
    82 This overloaded version is used where the nature of the sink buffer may impact
       
    83 the created sink buffer. This method should only be overridden if the size
       
    84 and/or type of the sink buffer can influence the size and/or type of the created
       
    85 sink buffer.</p>
       
    86 
       
    87 
       
    88 <p><b>Sink State Methods</b> </p>
       
    89 <p>The <xref href="GUID-708A7583-5C55-3FE1-8238-974C8821588D.dita"><apiname>MDataSink</apiname></xref> mixin provides a number of state-related
       
    90 functions used to inform a source/sink that the data path (via the controller)
       
    91 has made a transition to a particular state. These state transition methods
       
    92 are usually called on the source/sink from the datapath and so will be called
       
    93 on the data source/sink plugin. These methods are not pure virtual and so
       
    94 it is not compulsory to implement them. </p>
       
    95 <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
       
    96 the sink that it can perform any thread specific initialisation. This is so
       
    97 that the thread in which the data sink is instantiated is not necessarily
       
    98 the same thread in which the actual transfer of data between the source and
       
    99 the sink takes place. Any thread-specific sink initialisation cannot take
       
   100 place in the <codeph>NewSinkL()</codeph> method and must instead be performed
       
   101 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
       
   102 called in the thread in which the data transfer between sink and sink is to
       
   103 take place.</p>
       
   104 <p>The <xref href="GUID-8512F793-107A-3166-A62F-750696D942CE.dita"><apiname>MAsyncEventHandler</apiname></xref> must also be passed into the
       
   105 sink in the same thread in which the sink is to transfer data. If the sink
       
   106 can generate events during a data transfer, then it must keep the reference
       
   107 to event handler.</p>
       
   108 <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
       
   109 the sink has thread specific initialisation and/or can generate events during
       
   110 data transfer.</p>
       
   111 <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
       
   112 are called when a controller performs a transition to the corresponding state.
       
   113 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
       
   114 called.</p>
       
   115 <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
       
   116 is optional. This method is called when the controller has finished with the
       
   117 data sink and is called in the same thread as the data transfer. This allows
       
   118 the data sink to perform any thread specific destruction such as the closure
       
   119 of handles. </p>
       
   120 
       
   121 
       
   122 <p><b>Sink Data Types</b> </p>
       
   123 <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
       
   124 by the data sink. It should return the data type of the sink for the specified
       
   125 media ID. Some data sinks may need their data type to be explicitly set, via
       
   126 the <codeph>SetSinkDataTypeCode</codeph> method or via negotiation with a
       
   127 data sink, in which case this function should either return a default <codeph>FourCC</codeph> code,
       
   128 or a <codeph>NULL</codeph> code, to indicate that the data type is not yet
       
   129 known.</p>
       
   130 <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
       
   131 is optional. It should be implemented where the sink can support multiple
       
   132 data types.</p>
       
   133 
       
   134 
       
   135 <p><b>Sink Custom Commands</b> </p>
       
   136 <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
       
   137 the use of custom commands. An example implementation is shown below:</p>
       
   138 <codeblock id="GUID-C04BBBD3-9991-5478-9920-E7FFE28DB166" xml:space="preserve">void CAcmeDataSink::SinkCustomCommand(TMMFMessage&amp; aMessage)
       
   139     {
       
   140     // First, check we can handle message by checking its interface id
       
   141     if (aMessage.InterfaceId() != KUidAcmeDatasinkCustomCommandInterface)
       
   142         {
       
   143         aMessage.Complete(KErrNotSupported);
       
   144         return;
       
   145         }
       
   146 
       
   147     // Next, dispatch the command to the appropriate method.
       
   148     TInt error = KErrNone;
       
   149     switch (aMessage.Function())
       
   150         {
       
   151     case EAcmeDatasinkCustomCommandOne:
       
   152        error = HandleCustomCommandOne(aMessage);
       
   153        break;
       
   154     case EAcmeDataSinkCustomCommandTwo:
       
   155        error = HandleCustomCommandTwo(aMessage);
       
   156        break;
       
   157     default:
       
   158        error = KErrNotSupported;
       
   159        break;
       
   160        }
       
   161     aMessage.Complete(error);
       
   162     }
       
   163 </codeblock>
       
   164 <p>Use of the custom command mechanism is preferable to adding extra methods
       
   165 as it avoids extra casting.</p>
       
   166 
       
   167 
       
   168 <p><b>Sink Priority Settings</b> </p>
       
   169 <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.
       
   170 It is used to provide a mechanism to determine which sink should have priority
       
   171 in cases where more than one client wishes to use the same physical sink.
       
   172 An example might be an audio output, although several audio output sinks can
       
   173 be created, the actual hardware may only have one physical speaker. Therefore,
       
   174 if one audio output is being used to play music, and another is being used
       
   175 to play a ring tone due to an incoming call, then the latter needs to take
       
   176 precedence. <xref href="GUID-AA73C7C3-5874-34D1-8879-597B0900E9F3.dita"><apiname>TMMFPrioritySettings</apiname></xref> contains an <codeph>iPriority
       
   177 TInt</codeph> data member, where 100 is maximum priority, 0 is normal and
       
   178 -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.
       
   179 These specify whether the priority applies to recording or playing.</p>
       
   180 </conbody></concept>