Factory Implementation

Describes how to implement a factory.

The Sound Driver PDD must provide a factory class to create channels. All PDD factory classes are derived from DPhysicalDevice. The template PDD factory class TemplateSoundScPddFactory creates the appropriate PDD object when a driver channel is opened on the device. As well as the configurations supporting both record and playback, this class implements control of those aspects of the audio hardware device that are shared between the two channels.

DTemplateSoundScPddFactory is defined as:

class DTemplateSoundScPddFactory : public DPhysicalDevice
    {
public:
    DTemplateSoundScPddFactory();
    ~DTemplateSoundScPddFactory();
    virtual TInt Install();
    virtual void GetCaps(TDes8& aDes) const;
    virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
    virtual TInt Validate(TInt aUnit, const TDesC8* aInfo, const TVersion& aVer);
private:
    /** The DFC queue (used also by the LDD). */ 
    TDynamicDfcQue* iDfcQ;
    friend class DTemplateSoundScTxPdd;
    friend class DTemplateSoundScRxPdd; 
    };

The PDD factory class provided by the template Sound Driver creates a new DFC queue and associated kernel thread, iDfcQ, for exclusive use by this pair of Sound Driver channels. This is created within the second stage constructor function Install(). A pointer to the DFC queue is returned by the PDD function DfcQ(). See the PDD class constructor section.

The class DTemplateSoundScPddFactory contains four virtual functions, including the constructor, that must be implemented by the PDD for both driver channels. The template Sound Driver contains default implementations together with a constructor and destructor and, typically, need little or no modification:

DTemplateSoundScPddFactory constructor

Ensure that the inherited data member iUnitsMask is setup correctly according to the unit numbers to be supported. The default version enables the PDD to open both the first playback driver channel number KSoundScTxUnit0 and the first record driver channel number KSoundScRxUnit0:

// Support units KSoundScTxUnit0 & KSoundScRxUnit0
iUnitsMask=(1<<KSoundScRxUnit0)|(1<<KSoundScTxUnit0);

Install()

This is the second stage constructor for the PDD factory class. The template version creates the DFC queue and sets the driver name.

_LIT(KSoundScPddName,"SoundSc.Template");

// Definitions for the kernel thread created for this sound driver.
_LIT(KSoundScDriverThreadName,"SoundDriverThread");
const TInt KSoundScDriverThreadPriority=26; // One less than DFC thread 0

TInt DTemplateSoundScPddFactory::Install()
{
    TInt r=KErrNone;
    if (iDfcQ==NULL)
        {
        // Create a new sound driver DFC queue (and associated kernel thread). 
        r=Kern::DynamicDfcQCreate(iDfcQ, KSoundScDriverThreadPriority, KSoundScDriverThreadName);
        }
    
    if (r==KErrNone)
        {
        r=SetName(&KSoundScPddName); // Set the name of the driver object
        }
    return(r);
    }

The physical device is identified by the driver name, alter this to reflect your device. The driver name is the same as the LDD name, but followed by a dot and a short string to represent the physical device. For example, the name used for template is "SoundSc.Template ".

Validate()

This function is called by the kernel device driver framework to see whether this PDD is suitable for use with a particular driver channel. Ensure that the unit number checking code is correct for the unit numbers that are to be supported. The default version enables the PDD to open both the first playback driver channel number KSoundScTxUnit0 and the first record driver channel number KSoundScRxUnit0.

// Check the unit number is compatible
if (aUnit!=KSoundScTxUnit0 && aUnit!=KSoundScRxUnit0)
    return(KErrNotSupported);

Create()

This function is called by the kernel device driver framework to create a PDD object. Ensure that the unit number checking code is correct for the unit numbers that are to be supported. For configurations supporting both playback and record, it must be capable of creating either a playback or record PDD object according to the channel number specified. The template version is implemented as follows:

TInt DTemplateSoundScPddFactory::Create(DBase*& aChannel, 
                                        TInt aUnit,
                                        const TDesC8* /*anInfo*/, 
                                        const TVersion& /*aVer*/)
    {
    // Create the appropriate PDD channel object.
    TInt r=KErrNoMemory;
    if (aUnit==KSoundScRxUnit0)
        {
        // Create a record PDD channel object
        DTemplateSoundScRxPdd* pD=new DTemplateSoundScRxPdd;
        aChannel=pD;
        if (pD)
            {
            pD->iPhysicalDevice=this;
            r=pD->DoCreate();
            }
        }
       else
        {
        // Create a playback PDD channel object
        DTemplateSoundScTxPdd* pD=new DTemplateSoundScTxPdd;
        aChannel=pD;
        if (pD)
            {
            pD->iPhysicalDevice=this;
            r=pD->DoCreate();
            }
        }
    return(r);
    }