ansphoneengine.h

来自「series60 应用程序开发的源代码 series60 应用程序开发的源代码」· C头文件 代码 · 共 231 行

H
231
字号
#ifndef __ANSPHONEENGINE_H__
#define __ANSPHONEENGINE_H__

#include <MdaAudioSampleEditor.h>
#include <mda\common\base.h>
#include "AnsPhoneTimer.h"
#include "AnsPhoneCallWatcher.h"
#include "AnsPhoneCallMaker.h"
#include "AnsPhoneCallLog.h"
#include "AnsPhonePhone.h"

class CAnsPhoneMessageHolder;

_LIT(KAnsPhoneEngine, "CAnsPhoneEngine");
const TInt KNumberMaxLength = 20;


class MAnsPhoneEngineObserver
{
    public:
        virtual void HandlePlayMessageOverL() = 0;
        virtual void HandleCallChangeL(const RCall::TStatus& aStatus) = 0;
        virtual void HandleNewMessageL() = 0;
};

/**
*
* @class    CAnsPhoneEngine AnsPhoneEngine.h
* @brief    This can record & play messages
*
*    When recording there is a difference between local messages which is the
*    users voice message and non-local messages which are messages that are being
*    recorded over the telephony line
*
*    When playing there is a difference between local messages which are
*    on the phone and playing to the user and non-local messages which are messages that
*    are being played over the telephony line
*    There is one further difference when playing, in that the message can be either
*    the user's voice message or a message that has been recorded by the answering phone.
*
*    In order to play a message PlayMessageL() is called and the parameters determine if
*    the message is local or non-local, the user's or not and the index into the messages list,
*    if one of those is to be played.
*    In order to record a message RecordMessageL() is called and the parameter determines
*    if the message is local or non-local.
*
*    In order to play/record, a CMdaAudioRecorderUtility object is used.
*    This allows recording to and playing of files, using RecordL() and PlayL().
*
*    There are several stages in recording/playing.
*    The file is opened 1st, when this state is set to either ERecordInit or EPlayInit,
*    using one of the OpenL() functions. This call is asynchronous and when complete
*    MoscoStateChangeEvent() is called. Depending upon the state, the playing/recording
*    is then begun, using either RecordL() or PlayL().
*
*
*    Notes:
*
*    It will be noted that the CMdaAudioRecorderUtility allows playing of files,
*    which would be adequate for playing the user's message locally.
*    However, this class does not also contain any ability to notify an observer
*    when the file stops playing.
*    This is an answering phone and so must know when the file has stopped playing,
*    so that recording can take place.
*    Therefore, we could use a CMdaAudioPlayerUtility to play messages, which takes an observer
*    that would be notified once the file has finished playing.
*
*    Unfortunately, CMdaAudioPlayerUtility does not allow playing to the telephony line,
*    so we're going to stick with the CMdaAudioRecorderUtility and have a timer that will run
*    for the duration of the sound file. When it has finished, this class' TimerCompleteL()
*    function will be called by the timer's RunL(). The recording can then be started.
*
*
*    How the engine stores messages:
*
*    Messages are stored in files.
*    In order to display a message, there are 2 things that need to be known:
*    ->    the number of the person that left the message;
*        this is handled by naming the file the message is stored under as the phone number
*    ->    the time the message was left
*        this is handled by the time the message file was created
*
*    The engine stores a list of TMessage objects; it constructs this and populates it
*    from the files that are in the "messages" folder, when this object is constructed.
*
*    Because the name of the file is the phone number, if there are multiple messages by the same
*    phone number, there has to be a way to differentiate them. This is done by appending a number to the
*    end of the file, e.g. "07779238045" could become "07779238045 1.wav" or "07779238045 11.wav"
*    depending upon the highest index of the files there. Thus, if there is a "1", "3" and "5", the file
*    would have an index of "6"
*
*
*    How the engine handles telephony
*
*    The engine uses a connection to the telephony server, RTelServer, in order to get handles on
*    lines, phones and calls for accessing calls made using the telephony server. It stores a handle
*    to a voice line, RLine, so that it can pass this to the other call objects that will need it for
*    obtaining RCall handles.
*
*    There are two principle functions that are addressed:
*    ->    Answer phone calls
*        This is handled by the CAnsPhoneCallWatcher object. It asks the line to notify it when an
*        call comes in. It alerts the engine (its observer) so that the voice message can be started and then
*        recording begun. Meanwhile the call watcher watches the call until it is hung up, at which
*        point it alerts the engine. It then restarts its line notify so that it waits for another incoming
*        call.
*        When the call is hung up, the CAnsPhoneCallLog object is asked to get the number of the
*        call that just came in. When it completes the message that was just recorded is renamed using
*        the phone number to compose the file name. The request for the phone number completes very
*        quickly and there is no danger that if the user selects the messages list, they will see the
*        messages before the file name has been updated.
*
*    ->    Make phone calls
*        This is handled by the CAnsPhoneCallMaker object. It dials a number and waits for that
*        call to be hung up. When it has, it tells the engine (its observer).
*
* Copyright (c) EMCC Software Ltd 2003
* @version    1.0
*
*/

class CAnsPhoneEngine    :    public CBase,
                            public MMdaObjectStateChangeObserver,
                            public MAnsPhoneTimerObserver,
                            public MAnsPhoneCallWatcherObserver,
                            public MAnsPhoneCallMakerObserver,
                            public MAnsPhoneCallLogObserver
{
    public:
        enum TState    { ENoState, ERecordInit, ERecord, EPlayInit, EPlay };

    public:
        class TMessage
        {
            public:
                TMessage(){ iNumber.Zero(); }
            public:
                TBuf<KNumberMaxLength>    iNumber;    // this includes index, e.g. "07779238045 5"
                TTime                    iTime;
        };

    public:
        static CAnsPhoneEngine* NewL(MAnsPhoneEngineObserver& aObserver);
        ~CAnsPhoneEngine();

    public:                    // MMdaObjectStateChangeObserver
        virtual void MoscoStateChangeEvent(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode);

    public:                    // MAnsPhoneTimerObserver
        virtual void TimerCompleteL();

    public:                    // MAnsPhoneCallWatcherObserver
        virtual void HandleCallInChangeL(const RCall::TStatus& aStatus);

    public:                    // MAnsPhoneCallMakerObserver
        virtual void HandleCallHungUpL();

    public:                    // MAnsPhoneCallLogObserver
        virtual void HandlePhoneNumberL(const TDesC& aNumber);

    public:
        void PlayMessageL(TBool aIsLocal, TInt aIndex, TBool aIsUsers);
        void RecordMessageL(TBool aIsLocal);
        void Stop();
        void DeleteMessage(TInt aIndex);

        void AnsweringStartL();
        void AnsweringStop();

        void DialNumberL(TInt aIndex);

    public:
        void TrimIndex(const TDesC& aBuffer, TDes& aNumber, TInt& aIndex);

    public:
        inline const TState& State() const;
        inline const CArrayFixSeg<TMessage>& MessageList() const;

    private:
        CAnsPhoneEngine(MAnsPhoneEngineObserver& aObserver);
        void ConstructL();

    private:
        void MoscoStateChangeEventL(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode);

        void TelStartL();
        void SoundCleanup();
        void TelephonyCleanup();
        void GetNextMessageFileName(TDes& aFileName, const TDesC& aNumber);


    private:
        enum TPanicCode { EWrongState, ERecordInitError, EPlayInitError, EPlayError };
        inline void Panic(TPanicCode aReason) const;

    private:
        MAnsPhoneEngineObserver&    iObserver;
        CMdaAudioRecorderUtility*    iSound;
        TState                        iState;
        TBool                        iIsLocal;

        // recording message settings
        TMdaFileClipLocation    iMessageLocation;
        TMdaAudioDataSettings    iMessageSettings;
        TMdaWavClipFormat        iMessageFormat;
        TMdaPcmWavCodec            iMessageCodec;

        CAnsPhoneTimer*            iTimer;

        // telephony
        RTelServer                    iSession;
        RLine                        iLine;
        RAnsPhonePhone                iPhone;
        CAnsPhoneCallWatcher*        iCallWatcher;
        CAnsPhoneCallMaker*            iCallMaker;
        CAnsPhoneCallLog*            iCallLog;


        CArrayFixSeg<TMessage>*        iMessageList;

        RFs                         iFs;
};

// inline functions
const CAnsPhoneEngine::TState& CAnsPhoneEngine::State() const                    { return iState; }
const CArrayFixSeg<CAnsPhoneEngine::TMessage>& CAnsPhoneEngine::MessageList() const{ return *iMessageList; }

void CAnsPhoneEngine::Panic(TPanicCode aReason) const                            { User::Panic(KAnsPhoneEngine, aReason); };

#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?