/*++ Copyright (c) 2000 Microsoft Corporation Module Name: phone.h Abstract: Declaration of the CPhone class Notes: Revision History: --*/ #ifndef __PHONE_H_ #define __PHONE_H_ #include "resource.h" // main symbols #include "address.h" #include "ObjectSafeImpl.h" class CTAPI; extern CHashTable * gpPhoneHashTable; ///////////////////////////////////////////////////////////////// // Intermediate classes used for DISPID encoding template class ITPhoneVtbl : public ITPhone { DECLARE_TRACELOG_CLASS(ITPhoneVtbl) }; template class ITAutomatedPhoneControlVtbl : public ITAutomatedPhoneControl { DECLARE_TRACELOG_CLASS(ITAutomatedPhoneControlVtbl) }; ///////////////////////////////////////////////////////////////// // Constants defining default values for certain properties. const DWORD APC_DEFAULT_AEONT = 3000; const DWORD APC_DEFAULT_AKTMD = 100; const DWORD APC_DEFAULT_VCS = 4096; const DWORD APC_DEFAULT_VCRD = 500; const DWORD APC_DEFAULT_VCRP = 100; const DWORD APC_MAX_NUMBERS_GATHERED = 100; ///////////////////////////////////////////////////////////////// // Types typedef enum AUTOMATED_PHONE_STATE { APS_ONHOOK_IDLE, APS_OFFHOOK_DIALTONE, APS_OFFHOOK_WARNING, APS_ONHOOK_RINGING_IN, APS_OFFHOOK_DIALING, APS_OFFHOOK_DEAD_LINE, APS_OFFHOOK_CALL_INIT, APS_OFFHOOK_CONNECTED, APS_ONHOOK_CONNECTED, APS_OFFHOOK_BUSY_TONE, APS_OFFHOOK_RINGING_OUT, APS_ONHOOK_RINGING_OUT } AUTOMATED_PHONE_STATE; ///////////////////////////////////////////////////////////////////////////// // CPhone class CPhone : public CTAPIComObjectRoot, public IDispatchImpl, &IID_ITPhone, &LIBID_TAPI3Lib>, public IDispatchImpl, &IID_ITAutomatedPhoneControl, &LIBID_TAPI3Lib>, public CObjectSafeImpl { public: CPhone() : m_pTAPI(NULL), m_hPhoneApp(NULL), m_dwAPIVersion(0), m_dwDeviceID(0), m_hPhone(NULL), m_dwPrivilege(0), m_pPhoneCaps(NULL), m_pdwLineDeviceIDs(NULL), m_dwNumLineDeviceIDs(0), m_Tone(PT_SILENCE), m_fRinger(FALSE), m_fPhoneHandlingEnabled(FALSE), m_dwAutoEndOfNumberTimeout(APC_DEFAULT_AEONT), m_fAutoDialtone(TRUE), m_fAutoStopTonesOnOnHook(TRUE), m_fAutoStopRingOnOffHook(TRUE), m_fAutoKeypadTones(TRUE), m_dwAutoKeypadTonesMinimumDuration(APC_DEFAULT_AKTMD), m_pCall(NULL), m_hTimerQueue(NULL), m_hTimerEvent(NULL), m_hToneTimer(NULL), m_hDTMFTimer(NULL), m_hRingTimer(NULL), m_hVolumeTimer(NULL), m_hAutoEndOfNumberTimer(NULL), m_fUseWaveForRinger(FALSE), m_wszNumbersGathered(NULL), m_AutomatedPhoneState(APS_ONHOOK_IDLE), m_fAutoVolumeControl(TRUE), m_dwAutoVolumeControlStep(APC_DEFAULT_VCS), m_dwAutoVolumeControlRepeatDelay(APC_DEFAULT_VCRD), m_dwAutoVolumeControlRepeatPeriod(APC_DEFAULT_VCRP), m_dwOffHookCount(0), m_fInitialized(FALSE) { LOG((TL_TRACE, "CPhone[%p] - enter", this )); LOG((TL_TRACE, "CPhone - finished" )); } ~CPhone() { LOG((TL_TRACE, "~CPhone[%p] - enter", this )); LOG((TL_TRACE, "~CPhone - finished" )); } DECLARE_DEBUG_ADDREF_RELEASE(CPhone) DECLARE_QI() DECLARE_MARSHALQI(CPhone) DECLARE_TRACELOG_CLASS(CPhone) BEGIN_COM_MAP(CPhone) COM_INTERFACE_ENTRY2(IDispatch, ITPhone) COM_INTERFACE_ENTRY(ITPhone) // ITAutomatedPhoneControlQI will fall thru on SUCCESS, so we need to keep COM_INTERFACE_ENTRY(ITAutomatedPhoneControl) COM_INTERFACE_ENTRY_FUNC(IID_ITAutomatedPhoneControl, 0, CPhone::ITAutomatedPhoneControlQI) COM_INTERFACE_ENTRY(ITAutomatedPhoneControl) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP() void FinalRelease(); private: ITTAPI * m_pTAPI; HPHONEAPP m_hPhoneApp; DWORD m_dwAPIVersion; DWORD m_dwDeviceID; HPHONE m_hPhone; DWORD m_dwPrivilege; LPPHONECAPS m_pPhoneCaps; DWORD * m_pdwLineDeviceIDs; DWORD m_dwNumLineDeviceIDs; BOOL m_fInitialized; // AutomatedPhoneControl Variables CWavePlayer m_WavePlayer; BOOL m_fUseWaveForRinger; BOOL m_fRinger; BOOL m_fPhoneHandlingEnabled; DWORD m_dwAutoEndOfNumberTimeout; BOOL m_fAutoDialtone; BOOL m_fAutoStopTonesOnOnHook; BOOL m_fAutoStopRingOnOffHook; BOOL m_fAutoKeypadTones; DWORD m_dwAutoKeypadTonesMinimumDuration; BOOL m_fAutoVolumeControl; DWORD m_dwAutoVolumeControlStep; DWORD m_dwAutoVolumeControlRepeatDelay; DWORD m_dwAutoVolumeControlRepeatPeriod; DWORD m_dwOffHookCount; ITCallInfo * m_pCall; LPWSTR m_wszNumbersGathered; PHONE_TONE m_Tone; DWORD m_dwToneDuration; DWORD m_dwTonePeriodOn; DWORD m_dwTonePeriodOff; PHONE_TONE m_DTMF; DWORD m_dwDTMFStart; DWORD m_dwRingDuration; DWORD m_dwRingPeriod; BOOL m_fVolumeUp; AUTOMATED_PHONE_STATE m_AutomatedPhoneState; BOOL m_fDefaultTerminalsSelected; // Timer Handles HANDLE m_hTimerQueue; HANDLE m_hTimerEvent; HANDLE m_hToneTimer; HANDLE m_hDTMFTimer; HANDLE m_hRingTimer; HANDLE m_hVolumeTimer; HANDLE m_hAutoEndOfNumberTimer; // Critical Sections CRITICAL_SECTION m_csAutomatedPhoneState; CRITICAL_SECTION m_csToneTimer; CRITICAL_SECTION m_csRingTimer; public: static HRESULT WINAPI ITAutomatedPhoneControlQI(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw); DWORD GetDeviceID(){ return m_dwDeviceID; } DWORD GetAPIVersion(){ return m_dwAPIVersion; } HPHONEAPP GetHPhoneApp(){ return m_hPhoneApp; } HRESULT Initialize( ITTAPI * pTAPI, HPHONEAPP hPhoneApp, DWORD dwAPIVersion, DWORD dwDeviceID ); void SetPhoneCapBuffer( LPVOID pBuf ); HRESULT UpdatePhoneCaps(); HRESULT InvalidatePhoneCaps(); BOOL IsPhoneOnAddress(ITAddress * pAddress); BOOL IsPhoneOnPreferredAddress(ITAddress *pAddress); BOOL IsPhoneUsingWaveID(DWORD dwWaveID, TERMINAL_DIRECTION nDir); CTAPI * GetTapi(); void ForceClose(); void Automation_CallState( ITCallInfo * pCall, CALL_STATE cs, CALL_STATE_EVENT_CAUSE cause ); void Automation_ButtonDown( DWORD dwButtonId ); void Automation_ButtonUp( DWORD dwButtonId ); void Automation_OnHook( PHONE_HOOK_SWITCH_DEVICE phsd ); void Automation_OffHook( PHONE_HOOK_SWITCH_DEVICE phsd ); void Automation_EndOfNumberTimeout(); // // IDispatch // STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid ); STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr ); STDMETHOD_(ULONG, InternalAddRef)(); STDMETHOD_(ULONG, InternalRelease)(); // // ITPhone // STDMETHOD(Open)( IN PHONE_PRIVILEGE Privilege ); STDMETHOD(Close)(); STDMETHOD(get_Addresses)( OUT VARIANT * pAddresses ); STDMETHOD(EnumerateAddresses)( OUT IEnumAddress ** ppEnumAddress ); STDMETHOD(get_PreferredAddresses)( OUT VARIANT * pAddresses ); STDMETHOD(EnumeratePreferredAddresses)( OUT IEnumAddress ** ppEnumAddress ); STDMETHOD(get_PhoneCapsLong)( IN PHONECAPS_LONG pclCap, OUT long * plCapability ); STDMETHOD(get_PhoneCapsString)( IN PHONECAPS_STRING pcsCap, OUT BSTR * ppCapability ); STDMETHOD(GetPhoneCapsBuffer)( IN PHONECAPS_BUFFER pcbCaps, OUT DWORD *pdwSize, OUT BYTE **ppPhoneCapsBuffer ); STDMETHOD(get_PhoneCapsBuffer)( IN PHONECAPS_BUFFER pcbCaps, OUT VARIANT *pVarBuffer ); STDMETHOD(get_Terminals)( IN ITAddress * pAddress, OUT VARIANT * pTerminals ); STDMETHOD(EnumerateTerminals)( IN ITAddress * pAddress, OUT IEnumTerminal ** ppEnumTerminal ); STDMETHOD(get_ButtonMode)( IN long lButtonID, OUT PHONE_BUTTON_MODE * pButtonMode ); STDMETHOD(put_ButtonMode)( IN long lButtonID, IN PHONE_BUTTON_MODE ButtonMode ); STDMETHOD(get_LampMode)( IN long lLampID, OUT PHONE_LAMP_MODE* pLampMode ); STDMETHOD(put_LampMode)( IN long lLampID, IN PHONE_LAMP_MODE pLampMode ); STDMETHOD(get_ButtonFunction)( IN long lButtonID, OUT PHONE_BUTTON_FUNCTION * pButtonFunction ); STDMETHOD(put_ButtonFunction)( IN long lButtonID, IN PHONE_BUTTON_FUNCTION ButtonFunction ); STDMETHOD(get_ButtonText)( IN long lButtonID, OUT BSTR * ppButtonText ); STDMETHOD(put_ButtonText)( IN long lButtonID, IN BSTR bstrButtonText ); STDMETHOD(get_ButtonState)( IN long lButtonID, OUT PHONE_BUTTON_STATE * pButtonState ); STDMETHOD(get_HookSwitchState)( IN PHONE_HOOK_SWITCH_DEVICE HookSwitchDevice, OUT PHONE_HOOK_SWITCH_STATE * pHookSwitchState ); STDMETHOD(put_HookSwitchState)( IN PHONE_HOOK_SWITCH_DEVICE HookSwitchDevice, OUT PHONE_HOOK_SWITCH_STATE HookSwitchState ); STDMETHOD(put_RingMode)( IN long lRingMode ); STDMETHOD(get_RingMode)( OUT long * plRingMode ); STDMETHOD(put_RingVolume)( IN long lRingVolume ); STDMETHOD(get_RingVolume)( OUT long * plRingVolume ); STDMETHOD(get_Privilege)( OUT PHONE_PRIVILEGE * pPrivilege ); STDMETHOD(get_Display)( BSTR *pbstrDisplay ); // // put display string at a specified location // STDMETHOD(SetDisplay)( IN long lRow, IN long lColumn, IN BSTR bstrDisplay ); STDMETHOD(DeviceSpecific)( IN BYTE *pParams, IN DWORD dwSize ); STDMETHOD(DeviceSpecificVariant)( IN VARIANT varDevSpecificByteArray ); STDMETHOD(NegotiateExtVersion)( IN long lLowVersion, IN long lHighVersion, IN long *plExtVersion ); // // ITAutomatedPhoneControl // public: STDMETHOD (StartTone)( IN PHONE_TONE Tone, IN long lDuration ); STDMETHOD (StopTone)(); STDMETHOD (get_Tone)( OUT PHONE_TONE * pTone ); STDMETHOD (StartRinger)( IN long lRingMode, IN long lDuration ); STDMETHOD (StopRinger)(); STDMETHOD (get_Ringer)( OUT VARIANT_BOOL * pfRinging ); STDMETHOD (put_PhoneHandlingEnabled)( IN VARIANT_BOOL fEnabled ); STDMETHOD (get_PhoneHandlingEnabled)( OUT VARIANT_BOOL * pfEnabled ); STDMETHOD (put_AutoEndOfNumberTimeout)( IN long lTimeout ); STDMETHOD (get_AutoEndOfNumberTimeout)( OUT long * plTimeout ); STDMETHOD (put_AutoDialtone)( IN VARIANT_BOOL fEnabled ); STDMETHOD (get_AutoDialtone)( OUT VARIANT_BOOL * pfEnabled ); STDMETHOD (put_AutoStopTonesOnOnHook)( IN VARIANT_BOOL fEnabled ); STDMETHOD (get_AutoStopTonesOnOnHook)( OUT VARIANT_BOOL * pfEnabled ); STDMETHOD (put_AutoStopRingOnOffHook)( IN VARIANT_BOOL fEnabled ); STDMETHOD (get_AutoStopRingOnOffHook)( OUT VARIANT_BOOL * pfEnabled ); STDMETHOD (put_AutoKeypadTones)( IN VARIANT_BOOL fEnabled ); STDMETHOD (get_AutoKeypadTones)( OUT VARIANT_BOOL * pfEnabled ); STDMETHOD (put_AutoKeypadTonesMinimumDuration)( IN long lDuration ); STDMETHOD (get_AutoKeypadTonesMinimumDuration)( OUT long * plDuration ); STDMETHOD (put_AutoVolumeControl)( IN VARIANT_BOOL fEnabled ); STDMETHOD (get_AutoVolumeControl)( OUT VARIANT_BOOL * pfEnabled ); STDMETHOD (put_AutoVolumeControlStep)( IN long lStepSize ); STDMETHOD (get_AutoVolumeControlStep)( OUT long * plStepSize ); STDMETHOD (put_AutoVolumeControlRepeatDelay)( IN long lDelay ); STDMETHOD (get_AutoVolumeControlRepeatDelay)( OUT long * plDelay ); STDMETHOD (put_AutoVolumeControlRepeatPeriod)( IN long lPeriod ); STDMETHOD (get_AutoVolumeControlRepeatPeriod)( OUT long * plPeriod ); STDMETHOD (SelectCall)( IN ITCallInfo * pCall, IN VARIANT_BOOL fSelectDefaultTerminals ); STDMETHOD (UnselectCall)( IN ITCallInfo * pCall ); STDMETHOD (EnumerateSelectedCalls)( OUT IEnumCall ** ppCallEnum ); STDMETHOD (get_SelectedCalls)( OUT VARIANT * pVariant ); // Private helper methods for ITAutomatedPhoneControl implementation private: void UnselectAllPreviouslySelectedTerminals( IN ITBasicCallControl2 * pCall, IN ITTerminal * pTerminalThatFailed, IN IEnumTerminal * pEnum ); HRESULT InternalUnselectCall( IN ITCallInfo * pCall ); HRESULT SelectDefaultTerminalsOnCall( IN ITCallInfo * pCall ); HRESULT UnselectDefaultTerminalsOnCall( IN ITCallInfo * pCall ); HRESULT GetPhoneWaveRenderID( IN DWORD * pdwWaveID ); void OpenWaveDevice( ); void CloseWaveDevice( ); static VOID CALLBACK ToneTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ); static VOID CALLBACK DTMFTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ); static VOID CALLBACK RingTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ); static VOID CALLBACK VolumeTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ); static VOID CALLBACK AutoEndOfNumberTimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired ); }; class CPhoneEvent : public CTAPIComObjectRoot, // no need to have a cs public CComDualImpl, public CObjectSafeImpl { public: DECLARE_MARSHALQI(CPhoneEvent) DECLARE_TRACELOG_CLASS(CPhoneEvent) BEGIN_COM_MAP(CPhoneEvent) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITPhoneEvent) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP() static HRESULT FireEvent( CPhone * pCPhone, PHONE_EVENT Event, PHONE_BUTTON_STATE ButtonState, PHONE_HOOK_SWITCH_STATE HookSwitchState, PHONE_HOOK_SWITCH_DEVICE HookSwitchDevice, DWORD dwRingMode, DWORD dwButtonLampId, PWSTR pNumber, ITCallInfo * pCallInfo ); void FinalRelease(); protected: ITPhone * m_pPhone; PHONE_EVENT m_Event; PHONE_BUTTON_STATE m_ButtonState; PHONE_HOOK_SWITCH_STATE m_HookSwitchState; PHONE_HOOK_SWITCH_DEVICE m_HookSwitchDevice; DWORD m_dwRingMode; DWORD m_dwButtonLampId; BSTR m_pNumber; ITCallInfo * m_pCallInfo; #if DBG PWSTR m_pDebug; #endif public: STDMETHOD(get_Phone)( ITPhone ** ppPhone ); STDMETHOD(get_Event)( PHONE_EVENT * pEvent ); STDMETHOD(get_ButtonState)( PHONE_BUTTON_STATE * pState ); STDMETHOD(get_HookSwitchState)( PHONE_HOOK_SWITCH_STATE * pState ); STDMETHOD(get_HookSwitchDevice)( PHONE_HOOK_SWITCH_DEVICE * pDevice ); STDMETHOD(get_RingMode)( long * plRingMode ); STDMETHOD(get_ButtonLampId)( LONG * plButtonLampId ); STDMETHOD(get_NumberGathered)( BSTR * ppNumber ); STDMETHOD(get_Call)( ITCallInfo ** ppCallInfo ); }; class CPhoneDevSpecificEvent : public CTAPIComObjectRoot, // no need to have a cs public CComDualImpl, public CObjectSafeImpl { public: DECLARE_MARSHALQI(CPhoneDevSpecificEvent) DECLARE_TRACELOG_CLASS(CPhoneDevSpecificEvent) BEGIN_COM_MAP(CPhoneDevSpecificEvent) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITPhoneDeviceSpecificEvent) COM_INTERFACE_ENTRY(IObjectSafety) COM_INTERFACE_ENTRY_FUNC(IID_IMarshal, 0, IMarshalQI) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP() static HRESULT FireEvent( CPhone *pPhone, long lParam1, long lParam2, long lParam3 ); void FinalRelease(); CPhoneDevSpecificEvent(); protected: // // phone for which the event was fired // ITPhone *m_pPhone; // // data received from the TSP // long m_l1; long m_l2; long m_l3; #if DBG PWSTR m_pDebug; #endif public: STDMETHOD(get_Phone)( ITPhone **ppPhone ); STDMETHOD(get_lParam1)( long *plParam1 ); STDMETHOD(get_lParam2)( long *plParam2 ); STDMETHOD(get_lParam3)( long *plParam3 ); }; #endif //__PHONE_H_