diff -r 43e37759235e -r 51a74ef9ed63 Symbian3/SDK/Source/GUID-528BDE53-327A-5D34-B4BF-CB2421BE43C8.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/SDK/Source/GUID-528BDE53-327A-5D34-B4BF-CB2421BE43C8.dita Wed Mar 31 11:11:55 2010 +0100 @@ -0,0 +1,639 @@ + + + + + +Writing +a controller plugin +

This document explains how to write a controller plugin.

+
Purpose

A +controller plugin is the main type of multimedia framework (MMF) plugin. A +controller plugin typically supports playing or recording one or more multimedia +formats, mp3 or avi for example. A controller +plugin is able to read data from one or more sources, apply any required data +transformations and write the data to the appropriate sink.

Required +Background

You need to be familiar with the Symbian platform Plugin +Framework.

+
Using the Controller +Plugin

The following tasks will be covered in this tutorial:

    +
  • Implementing the core controller plugin interface

  • +
  • Implementing the standard custom command interfaces

  • +
  • Interaction with MMF Base Classes and other plugins

  • +
  • Integrating the controller into the ECom plugin framework

  • +
  • Testing

  • +

Basic +Procedure

The basic steps for writing a controller plugin are +shown here:

    +
  1. Implementing the core controller plugin interface

  2. +
  3. Implementing the standard custom command interfaces

  4. +
  5. Interaction with MMF Base Classes and other plugins

  6. +
  7. Integrating the controller into the ECom plugin framework

  8. +
  9. Testing

  10. +
+
Implementing +the core controller plugin interface

The controller plugin API +is defined by the controller framework element of the MMF. All controller +plugin implementations must derive from the abstract class CMMFController and +implement its pure virtual methods.

As well as providing the controller +API, the CMMFController base class also provides functionality +such as instantiation of controller plugins via the ECom plugin +framework, inter-thread message decoding and parameter unpacking, an object +reference counting mechanism and a few utility methods for use by controller +plugins.

The following sections describe how to implement the controller +API.

Sources and sinks

Sources and sinks are themselves ECom plugins and provide +an interface that allows the controller to read and write raw data buffers. +The type of source or sink, along with any source- specific or sink-specific +initialisation parameters (for example, the file name for a file source), +is specified by the client. The source or sink is then created and owned by +the controller framework. It is then passed into the controller plugin via +a call to CMMFController::AddDataSourceL() or CMMFController::AddDataSinkL() for +a data source or a data sink respectively.

Note : The ownership +of a source or sink always remains with the controller framework and not with +the controller plugin, and that a controller plugin should never delete a +source or sink. If the controller plugin leaves during the call to CMMFController::AddDataSourceL() or CMMFController::AddDataSinkL(), the source or sink will be destroyed by the controller framework.

There +is no limit on the number of sources or sinks that can be added to a particular +controller plugin, other than the limit provided by the plugin itself. For +example, an audio controller would have one source and one sink. A video playing +controller would have one source and two sinks (display and speaker).

Sources +and sinks can also be removed from the controller plugin by the client. The +reference of the particular source or sink being removed is passed into either +the CMMFController::RemoveDataSourceL() or CMMFController::RemoveDataSinkL() method +to remove a data source or a data sink respectively. The controller plugin +should remove any reference that it has to the source or sink; the source +or sink will then be deleted by the controller framework.

Note: If +the controller plugin leaves during these calls (for example, if it does not +support the removal of sources or sinks), the controller framework will not +delete the source or sink.

Controller states

The Controller plugin states, along with +the commands to transition the plugin between the states, are:

    +
  • Open, +this is the current state of the controller, after it has been created. Once +the controller has been configured, it moves to the Stopped state. +This transition typically involves adding the source(s) and sink(s) and configuring +any utility objects or other plugins owned by the controller.

  • +
  • Stopped, +in this state the controller should not have any resources or buffers allocated, +and the position should be zero.

  • +
  • Primed, +in moving to the primed state, the controller should allocate any buffers +and resources that will be required to perform playback. The playback or recording +position should also be stored when the controllere is in the primed state. +Controllers should only be moved into this state just before play, otherwise +unnecessary memory and resources will be used.

  • +
  • Playing, +when in this state, the controller plugin should be transferring data between +source(s) and sink(s).

  • +

Calling CMMFController::ResetL() on the controller +plugin should cause it to revert back to the Open state. +This will involve stopping playback, deleting any allocated resources, and +removing any references to sources and sinks.

Position and Duration

Position and duration can be set by +deriving from the pure virtual methods CMMFController::PositionL(), CMMFController::SetPositionL() and CMMFController::DurationL().

Note: The position has +meaning only in the Primed and Playing states. +The controller plugin should leave with KErrNotReady if an +attempt is made to set or get the position when the controller is in any other +state. However, it should be possible to query the duration as soon as the +data source or data sink has been added.

Custom Commands

Custom commands allow controller plugin writers +to extend the basic controller API. They sends messages from the client through +the controller framework to the controller plugin.

The CMMFController::CustomCommand() method +can be implemented in the controller plugin to support custom commands. The +default implementation provided by the base class is to complete the message +with KErrNotSupported.

Note: It is imperative +that the message is always completed by this method and that this method cannot +leave. Any error that occurs must be passed back to the client by completing +the message with the error code.

Each TMMFMessage has +an associated interface UID which should be checked before handling any message +to make sure that the command is supported.

The following code illustrates +a typical custom command implementation.

void CMyController::CustomCommand(TMMFMessage& aMessage) + { + // First, check we can handle message by checking its interface id + if (aMessage.InterfaceId() != KUidMyControllerCustomCommandInterface) + { + aMessage.Complete(KErrNotSupported); + return; + } + + // Next, dispatch the command to the appropriate method. + TInt error = KErrNone; + switch (aMessage.Function()) + { + case EMyCustomCommandOne: + error = HandleCustomCommandOne(aMessage); + break; + case EMyCustomCommandTwo: + error = HandleCustomCommandTwo(aMessage); + break; + default: + error = KErrNotSupported; +break; + } + aMessage.Complete(error); + } + +

The above example shows synchronous command handling. If the +plugin needs to do some task that requires a long time, the aMessage parameter +should be copied, stored and completed later when processing has finished.

The +methods HandleCustomCommandOne and HandleCustomCommandTwo above, +copy any data to and from the client. This can be done using the appropriate TMMFMessage methods.

Asynchronous Error Reporting

The CMMFController::DoSendEventToClient() utility +method allows a controller plugin to send an event to its client.

The +multimedia client utilities listen for specific event types and error codes. +If the controller plugin is accessed by clients that are using the multimedia +client utility APIs (which will usually be the case) then those event types +and error codes should be used. The event types and error codes for which +the multimedia client utilities listen are listed below:

+ + + +

Client utility

+

Event type

+

Error code

+

Meaning

+
+ +

Audio Player Utility (CMdaAudioPlayerUtility)

+

Any

+

KErrOverflow

+

Playback complete, the end of the data was reached.

+
+ +

+

Any

+

KErrEof

+

Playback complete, the end of the data was reached.

+
+ +

Audio Recorder Utility (CMdaAudioRecorderUtility)

+

Any

+

KErrOverflow

+

Playback complete, the end of the data was reached.

+
+ +

+

Any

+

KErrUnderflow

+

Recording complete, no more source data from microphone.

+
+ +

+

Any

+

KErrEof

+

Playback or recording complete, end of data reached.

+
+ +

Audio Converter Utility (CMdaAudioConvertUtility)

+

Any

+

KErrOverflow

+

Conversion complete, end of data reached.

+
+ +

+

Any

+

KErrEof

+

Conversion complete, end of data reached.

+
+ +

Video Player Utility (CVideoPlayerUtility)

+

Any

+

KErrOverflow

+

Playback complete, end of data reached.

+
+ +

+

Any

+

KErrEof

+

Playback complete, end of data reached.

+
+ +

+

KMMFEventCategory VideoOpenComplete

+

Any

+

Open complete. Must be used otherwise clients will not be notified +when the clip has been opened. This is used because video clips can take a +long time to process on opening. The error code is passed back to the client.

+
+ +

+

KMMFEventCategory PlaybackComplete

+

Any

+

Playback complete. Can be used instead of KErrOverflow or KErrEof. +The error code is passed back to the client.

+
+ +

+

KMMFEventCategory VideoRebufferStarted

+

Any

+

Re-buffering has begun. Client will be notified so it can update +its UI.

+
+ +

+

KMMFEventCategory VideoRebufferComplete

+

Any

+

Re-buffering has finished. Client will be notified so it can update +its UI.

+
+ + +

MMF Objects

The controller framework contains an object referencing +mechanism that allows a client to send messages to arbitrary objects in the +controller thread without having to go via the controller plugin itself. In +order to achieve this, the arbitrary object must be derived from CMMFObject and +added to the object container. The object container can be accessed via the CMMFController::MMFObjectContainerL() method.

Sources and sinks have a CMMFObject wrapper placed around +them by the controller framework, and can receive messages from the client. +This mechanism is also used to reference source(s) and sink(s), so the client +can specify exactly the source or sink when calling the CMMFController::RemoveDataSourceL() or CMMFController::RemoveDataSinkL() methods.

Note: The objects added to the CMMFObjectContainer are +owned by the CMMFObjectContainer.

Each object added +to the CMMFObjectContainer is assigned a handle. This handle +must be passed back to the client in order for the client to be able to send +messages directly to the object.

The client should use this handle +to set the handle of the TMMFMessageDestination parameter +in the RMMFController::CustomCommandAsync() or RMMFController::CustomCommandSync() method +for asynchronous or synchronous operation respectively. The custom command +will then be routed directly to the CMMFObject by the controller +framework.

+
Implementing +the standard custom command interfaces

The core controller plugin +API provides only basic support for controlling the flow of data. The application-level +multimedia utility APIs (for example, CMdaAudioPlayerUtility ) +contain much richer functionality. The application-level multimedia utility +APIs provide clients with a concrete API to access extended controller functionality, +and to give controller plugins a concrete mixin API to implement.

Several +sets of standard custom command APIs have been defined. The following table +shows which of these classes must be implemented to allow the controller plugin +to be used properly from each of the application-level utility APIs.

+ + + +

Application-level Utility API

+

Required Custom Command APIs

+
+ +

CmdaAudioPlayerUtility

+

MMMFAudioPlayDeviceCustomCommandImplementor

MMMFAudioPlayControllerCustomCommandImplementor

+
+ +

CmdaAudioRecorderUtility

+

MMMFAudioPlayDeviceCustomCommandImplementor

MMMFAudioRecordDeviceCustomCommandImplementor

MMMFAudioPlayControllerCustomCommandImplementor

MMMFAudioRecordControllerCustomCommandImplementor

MMMFAudioControllerCustomCommandImplementor

+
+ +

CmdaAudioConvertUtility

+

MMMFAudioPlayControllerCustomCommandImplementor

MMMFAudioRecordControllerCustomCommandImplementor

MMMFAudioControllerCustomCommandImplementor

+
+ +

CvideoPlayerUtility

+

MMMFVideoControllerCustomCommandImplementor

MMMFVideoPlayControllerCustomCommandImplementor

MMMFAudioPlayDeviceCustomCommandImplementor

+
+ +

CvideoRecorderUtility

+

MMMFVideoControllerCustomCommandImplementor

MMMFVideoRecordControllerCustomCommandImplementor

MMMFAudioRecordDeviceCustomCommandImplementor

+
+ + +

In order to implement the required custom command APIs, the controller +plugin should derive from the mixins shown in the table above, and use the CMMFController::AddCustomCommandParserL() method +to register itself as being able to handle that API.

The CMMFCustomCommandParserBase derived +object decodes the custom command on behalf of the controller plugin and calls +the concrete API via the mixin interface. The following table shows which CMMFCustomCommandParserBase object +should be used with each mixin class.

+ + + +

Mixin Interface

+

Custom Command Parser

+
+ +

MMMFAudioControllerCustomCommandImplementor

+

CMMFAudioControllerCustomCommandParser

+
+ +

MMMFAudioPlayControllerCustomCommandImplementor

+

CMMFAudioPlayControllerCustomCommandParser

+
+ +

MMMFAudioRecordControllerCustomCommandImplementor

+

CMMFAudioRecordControllerCustomCommandParser

+
+ +

MMMFVideoControllerCustomCommandImplementor

+

CMMFVideoControllerCustomCommandParser

+
+ +

MMMFVideoPlayControllerCustomCommandImplementor

+

CMMFVideoPlayControllerCustomCommandParser

+
+ +

MMMFVideoRecordControllerCustomCommandImplementor

+

CMMFVideoRecordControllerCustomCommandParser

+
+ +

MMMFAudioPlayDeviceCustomCommandImplementor

+

CMMFAudioPlayDeviceCustomCommandParser

+
+ +

MMMFAudioRecordDeviceCustomCommandImplementor

+

CMMFAudioRecordDeviceCustomCommandParser

+
+ + +

The following example code shows how the controller should register +itself with the controller framework to receive standard custom commands.

class CMyControllerPlugin : public CMMFController, + MMMFAudioControllerCustomCommandImplementor, + MMMFAudioPlayDeviceCustomCommandImplementor + { +... +private: + void ConstructL(); + }; + +void CMyControllerPlugin::ConstructL() + { +... + // Construct custom command parsers + + CMMFAudioControllerCustomCommandParser* audConParser = + CMMFAudioControllerCustomCommandParser::NewL(*this); + CleanupStack::PushL(audParser); + AddCustomCommandParserL(*audConParser); //parser now owned by controller framework + CleanupStack::Pop(audConParser); + + CMMFAudioPlayDeviceCustomCommandParser* audPlayDevParser = + CMMFAudioPlayDeviceCustomCommandParser::NewL(*this); + CleanupStack::PushL(audPlayDevParser); + AddCustomCommandParserL(*audPlayDevParser); //parser now owned by controller framework + CleanupStack::Pop();//audPlayDevParser + + + } +

It is also possible for controller plugins to define their +own standard custom command classes. This might be useful if a group of plugins +have the same API (for example, a group of MIDI controller +plugins). Clients would then be able to access equivalent functionality in +each plugin using the same API.

+
Interaction +with MMF Base Classes and other Plugins

The MMF provides a set +of utility classes and other types of plugins to aid with writing controller +plugins. All utility classes are provided in the library MMFServerBaseClasses.DLL. +A brief description of each of the classes follows.

Note: The +use of data sources, data sinks and buffers is mandatory. The use of the other +classes is optional.

    +
  • Data Sources and Sinks

  • +
  • Buffers

  • +
  • Datapath

  • +
  • Codecs

  • +
  • Formats

  • +

Data Sources and Sinks

Data sources and sinks are ECom plugins, +and are derived from the base class MDataSource or MDataSink respectively. +The currently available data sources and sinks are listed below:

    +
  • CMMFFile

  • +
  • CMMFDescriptor

  • +
  • CMMFAudioInput

  • +
  • CMMFAudioOutput CMMFAudioInput

  • +

They are created by the controller framework and passed into the +controller plugin by reference using the CMMFController::AddDataSourceL() or CMMFController::AddDataSinkL() method.

Some sources and sinks have extended APIs that allow the controller plugin +to perform actions, such as setting the volume. The type of the source or +sink can be checked by the controller plugin using the methods MDataSource::DataSourceType() and MDataSink::DataSinkType(). These methods return a UID which can be checked against known UIDs to identify +the extended API of the source or sink. For example, the following code would +be used to set the volume of a speaker sink.

MMMFAudioOutput* audioOutput = static_cast(MMMFAudioOutput*,(iDataSink)); +audioOutput->SoundDevice().SetVolume(14); +

It is possible dynamically to add new data sources and sinks +to the system, see writing +a Source/Sink plugin for information.

Buffers

Buffers are used to contain data as it is being transferred +from a source to a sink. There are several buffer types all derived from a +common base class CMMFBuffer: CMMFDataBuffer, CMMFDescriptorBuffer and CMMFTransferBuffer.

Datapath

The datapath is a utility class that transfers data +from a single source to a single sink, via a codec plugin if the source and +sink data types differ. The API of the datapath is very similar to that of +the basic controller plugin API, and much of the complexity of controller +plugins can be avoided by using the datapath.

The datapath can be +used either through:

    +
  • CMMFDataPath, +in which case the data will be transferred from the source to the sink in +the main thread of the controller plugin.

  • +
  • RMMFDataPath, +in which case a new thread will be launched to transfer the data from the +source to the sink. This is useful if a controller has multiple sources and +sinks (a video controller for example). The multiple datapaths can each be +executed in their own thread to improve performance.

  • +

If the source and sink data types are the same then no codec is required +and the datapath will use a null codec and the buffers will +be transferred straight from the source to the sink without being copied in +between.

Codecs

Codec plugins are derived from CMMFCodec and +can be used by controller plugins to convert data from one data type to another. +Codec plugins are designed to be used by different controller plugins, for +example both an audio controller and a video controller might want to make +use of a PCM8 to PCM16 codec.

See writing a codec plugin for +details of how to implement codec plugins.

Formats

Controller plugin writers may wish to implement their +format support by writing format plugins. While format plugins can only be +used by one controller plugin, this does make it much easier to dynamically +extend the formats supported by the controller plugin without providing a +whole new controller plugin. See writing +a format plugin for details of how to implement format plugins.

+
Integrating +the Controller into the ECom Plugin Framework

This section describes +how to write the ECom plugin registry file. See ECom for +generic instructions on how to write an ECom plugin.

The controller +plugin resolver is decides which controller plugin should be used to provide +support for a particular format. Controller plugins provide information in +their ECom resource file which allows the controller framework +(and ultimately the client application) to determine:

    +
  • The display name and +supplier of the controller plugin.

  • +
  • The media types supported +by the controller plugin (e.g. audio or video).

  • +
  • The formats the controller +plugin can play and record.

  • +

For each format supported, for both playing and recording, the information +below is provided:

    +
  • Display Name of the +format.

  • +
  • Supplier of the format +(in case support for this format was provided by a different party to the +controller plugin).

  • +
  • The Media Types supported +by the format.

  • +
  • The MIME types applicable +to the format.

  • +
  • The file extensions +that identify files that can be handled by the format.

  • +
  • Any header data segments +that could be matched to the first few bytes of multimedia data to identify +that the data could be handled using this format.

  • +

Most of the information outlined above is provided by the plugin +in the opaque_data field of the ECom resource file. This +field takes an 8-bit string and is limited to 127 characters in length. A +tagged data scheme is used to separate the different types of data. The tags +are all three characters in length, and the scheme only uses opening tags +(i.e. no end tags) to reduce overhead and complexity. The tags available are:

+ + + +

Tag

+

Usage

+

Description

+
+ +

<s>

+

Controller, Format

+

The supplier of the plugin.

+
+ +

<i>

+

Controller, Format

+

A media ID supported by this plugin. Multiple entries can be included.

+
+ +

<p>

+

Controller

+

The UID of the play format collection for this controller (see below).

+
+ +

<r>

+

Controller

+

The UID of the record format collection for this controller (see +below).

+
+ +

<m>

+

Format

+

A mime type that describes the format. Multiple entries with this +tag can be included.

+
+ +

<e>

+

Format

+

A file extension supported by this format. Multiple entries with +this tag can be included.

+
+ +

<h>

+

Format

+

A segment of header data that can be matched against the first few +bytes of a clip to check whether this format is capable of handling the clip. +Multiple entries with this tag can be included.

+
+ + +

Formats can be supported by controller plugins either:

    +
  • Internally: In +this case, the controller is able to read or write the format by itself. Controller +plugins can specify the formats they support internally with extra entries +in their plugin resource file. They define two new ECom plugin +interface uids (one for play formats, the other for record formats) in their opaque_data field +using the tags <p> and <r>. The play +formats they support are then listed as ECom plugin implementations +of the play format interface UID, and likewise with the record formats. These +interface UIDs and implementations do not correspond to any real plugins. +They are simply a way of letting the controller framework know exactly which +formats the controller supports in a scalable manner. The implementation UIDs +of each format should be known to the controller so that a client can specify +the format that a controller should use by using this UID.

  • +
  • By using format +plugins: The MMFServerBaseClasses component defines +base classes for both encoding and decoding format plugins. By using format +plugins, the formats supported by a controller plugin can be extended dynamically +without having to change the controller plugin itself. The ECom plugin +resource file of each format plugin contains the UID of the controller plugin +that it extends, allowing the controller framework to build up an accurate +picture of the formats supported by each controller.

  • +

The following is an example of a resource file for an audio controller +plugin that supports playing WAV and AU, +and recording AU.

RESOURCE REGISTRY_INFO theInfo + { + dll_uid = 0x101F1234; + interfaces = + { + INTERFACE_INFO // Controller Plugin Description + { + interface_uid = KMmfUidPluginInterfaceController ; + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x101F1235 ; + version_no = 1; + display_name = "Symbian Audio controller"; + default_data = "?"; + opaque_data = + “<s>Symbian<i>0x101F5D07<p>0x101F0001<r>0x101F0002"; + // SUPPLIER = Symbian + // MEDIA ID = uid for audio media type + // PLAY FORMATS = look at interface uid 0x101f0001 + // RECORD FORMATS = look at interface uid 0x101f0002 + } + }; + }, + INTERFACE_INFO // Play Formats Description + { + interface_uid = 0x101F0001 ; + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x101F1236 ; + version_no = 1; + display_name = "WAV Play Format"; + default_data = "?"; + opaque_data = + “<s>Symbian<i>0x101f5d07<e>.wav<h>RIFF????WAVE<m>Audio/Wave"; + // SUPPLIER = Symbian + // MEDIA ID = uid for audio media type + // FILE EXTENSION = .wav + // HEADER DATA = look for RIFF????WAVE in header data. The’?’s + // indicate a single character wildcard. + // MIME TYPE = Audio/Wave + }, + IMPLEMENTATION_INFO + { + implementation_uid = 0x101F1237 ; + version_no = 1; + display_name = "AU Play Format"; + default_data = "?"; + opaque_data = + “<s>Symbian<i>0x101f5d07<e>.au<h>.snd"; + // SUPPLIER = Symbian + // MEDIA ID = uid for audio media type + // FILE EXTENSION = .au + // HEADER DATA = look for .snd in header data. + // MIME TYPE = No mime type + } + }; + }, + INTERFACE_INFO // Record Formats Description + { + interface_uid = 0x101F0002 ; + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x101F1238 ; + version_no = 1; + display_name = "WAV Record Format"; + default_data = "?"; + opaque_data = + “<s>Symbian<i>0x101f5d07<e>.wav<h>RIFF????WAVE<m>Audio/Wave"; + // SUPPLIER = Symbian + // MEDIA ID = uid for audio media type + // FILE EXTENSION = .wav + // HEADER DATA = look for RIFF????WAVE in header data. The’?’s + // indicate a single character wildcard. + // MIME TYPE = Audio/Wave + } + }; + } + }; + } + +

Note: The default_data field is not +used by the controller framework. A UTF8 to unicode conversion +is performed on the Supplier. All other data is left in ascii.

+
Testing

The +controller plugin should be tested by exercising any application-level utility +APIs that are meant to be supported by the plugin. For example, a video player +controller would be tested using the CVideoPlayer API.

+
+Multimedia +APIs and Frameworks +
\ No newline at end of file