diff options
author | pescuma <pescuma@c086bb3d-8645-0410-b8da-73a8550f86e7> | 2010-01-18 00:53:43 +0000 |
---|---|---|
committer | pescuma <pescuma@c086bb3d-8645-0410-b8da-73a8550f86e7> | 2010-01-18 00:53:43 +0000 |
commit | a36ca1b4d5d0c89b09382ac4215681b47865bea1 (patch) | |
tree | ec2c5372a53deb91169181c965f504b0f16912f0 | |
parent | 9bcf44d21b3a7588a267e98573396dbf2deceb12 (diff) |
sip_cli: Example plugin to use SIP client API
git-svn-id: http://pescuma.googlecode.com/svn/trunk/Miranda@210 c086bb3d-8645-0410-b8da-73a8550f86e7
-rw-r--r-- | Plugins/sip_cli/commons.h | 62 | ||||
-rw-r--r-- | Plugins/sip_cli/resource.h | 92 | ||||
-rw-r--r-- | Plugins/sip_cli/resource.rc | 118 | ||||
-rw-r--r-- | Plugins/sip_cli/sdk/m_sip.h | 98 | ||||
-rw-r--r-- | Plugins/sip_cli/sdk/m_voice.h | 180 | ||||
-rw-r--r-- | Plugins/sip_cli/sdk/m_voiceservice.h | 90 | ||||
-rw-r--r-- | Plugins/sip_cli/sip_cli.cpp | 285 | ||||
-rw-r--r-- | Plugins/sip_cli/sip_cli.dsp | 187 | ||||
-rw-r--r-- | Plugins/sip_cli/sip_cli.dsw | 29 |
9 files changed, 1141 insertions, 0 deletions
diff --git a/Plugins/sip_cli/commons.h b/Plugins/sip_cli/commons.h new file mode 100644 index 0000000..884ac10 --- /dev/null +++ b/Plugins/sip_cli/commons.h @@ -0,0 +1,62 @@ +/*
+Copyright (C) 2010 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __COMMONS_H__
+# define __COMMONS_H__
+
+
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+
+
+// Miranda headers
+#define MIRANDA_VER 0x0800
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_langpack.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_utils.h>
+
+#include "../utils/mir_memory.h"
+#include "../utils/mir_icons.h"
+
+#include "sdk/m_sip.h"
+#include "sdk/m_voice.h"
+#include "sdk/m_voiceservice.h"
+
+#include "resource.h"
+
+
+#define MODULE_NAME "SIP_CLI"
+
+
+// Global Variables
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+
+
+#endif // __COMMONS_H__
diff --git a/Plugins/sip_cli/resource.h b/Plugins/sip_cli/resource.h new file mode 100644 index 0000000..8b45235 --- /dev/null +++ b/Plugins/sip_cli/resource.h @@ -0,0 +1,92 @@ +//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDR_MENUS 101
+#define IDD_CALLS 102
+#define IDI_TALKING 102
+#define IDI_RINGING 103
+#define IDI_CALLING 104
+#define IDI_ON_HOLD 105
+#define IDI_ENDED 106
+#define IDI_BUSY 107
+#define IDD_DLG 107
+#define IDI_ACTION_CALL 108
+#define IDI_ACTION_ANSWER 109
+#define IDI_ACTION_HOLD 110
+#define IDI_ACTION_DROP 111
+#define IDI_MAIN 112
+#define IDI_DIALPAD 113
+#define IDD_NEW_CALL 113
+#define IDI_SECURE 114
+#define IDD_POPUPS 120
+#define IDI_SMALLDOT 211
+#define IDD_OPT_AUTO 215
+#define IDD_OPTS 216
+#define IDD_OPT_DEVICES 217
+#define IDC_CALLS 1000
+#define IDC_DELAY 1001
+#define IDC_TEXT 1001
+#define IDC_WINCOLORS 1002
+#define ID_ANSWER 1002
+#define IDC_DEFAULTCOLORS 1003
+#define ID_DROP 1003
+#define IDC_BGCOLOR 1004
+#define IDC_AUTO 1004
+#define IDC_TEXTCOLOR 1005
+#define IDC_FRAME_AUTOSIZE 1005
+#define IDC_PREV 1006
+#define IDC_NUMBER 1006
+#define IDC_DELAYFROMPU 1007
+#define IDC_CALL 1007
+#define IDC_DELAYCUSTOM 1008
+#define IDC_DIALPAD 1008
+#define IDC_DELAYPERMANENT 1009
+#define IDC_INPUT 1009
+#define IDC_OUTPUT 1010
+#define IDC_ECHO 1011
+#define IDC_MIC_BOOST 1012
+#define IDC_1 1012
+#define IDC_2 1013
+#define IDC_DATA 1013
+#define IDC_3 1014
+#define IDC_4 1015
+#define IDC_HOST 1015
+#define IDC_5 1016
+#define IDC_PORT 1016
+#define IDC_6 1017
+#define IDC_PROTOCOL 1017
+#define IDC_AST 1018
+#define IDC_0 1019
+#define IDC_SHARP 1020
+#define IDC_7 1021
+#define IDC_RIGHT_ACTION 1022
+#define IDC_8 1022
+#define IDC_LEFT_ACTION 1023
+#define IDC_9 1023
+#define IDC_POPUPS 1060
+#define IDC_DELAY_SPIN 1061
+#define IDC_COLOURS_G 1068
+#define IDC_BGCOLOR_L 1069
+#define IDC_TEXTCOLOR_L 1070
+#define IDC_DELAY_G 1071
+#define IDC_ACTIONS_G 1072
+#define IDC_RIGHT_ACTION_L 1073
+#define IDC_LEFT_ACTION_L 1074
+#define IDC_LIST 1079
+#define IDC_ANSWER 1204
+#define IDC_DROP 1205
+#define ID_FRAMEPOPUP_ANSWERCALL 40001
+#define ID_FRAMEPOPUP_DROPCALL 40002
+#define ID_FRAMEPOPUP_HOLDCALL 40003
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 116
+#define _APS_NEXT_COMMAND_VALUE 40004
+#define _APS_NEXT_CONTROL_VALUE 1019
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Plugins/sip_cli/resource.rc b/Plugins/sip_cli/resource.rc new file mode 100644 index 0000000..ab0c0b3 --- /dev/null +++ b/Plugins/sip_cli/resource.rc @@ -0,0 +1,118 @@ +//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DLG DIALOG DISCARDABLE 0, 0, 213, 139
+STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "SIP"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Host: %s\nUDP: %d\nTCP: %d\nTLS: %d",IDC_DATA,7,7,199,
+ 35
+ GROUPBOX "Contact",IDC_STATIC,7,45,199,87
+ LTEXT "Host:",IDC_STATIC,13,60,45,11
+ EDITTEXT IDC_HOST,63,58,137,13,ES_AUTOHSCROLL
+ LTEXT "Port:",IDC_STATIC,13,75,45,11
+ EDITTEXT IDC_PORT,63,73,137,13,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Protocol:",IDC_STATIC,14,90,45,11
+ COMBOBOX IDC_PROTOCOL,63,88,137,12,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ PUSHBUTTON "Call",IDC_CALL,80,112,52,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_DLG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 206
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 132
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Portuguese (Brazil) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PTB)
+#ifdef _WIN32
+LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Portuguese (Brazil) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Plugins/sip_cli/sdk/m_sip.h b/Plugins/sip_cli/sdk/m_sip.h new file mode 100644 index 0000000..360912b --- /dev/null +++ b/Plugins/sip_cli/sdk/m_sip.h @@ -0,0 +1,98 @@ +/*
+Copyright (C) 2010 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __M_SIP_H__
+# define __M_SIP_H__
+
+
+// state is a VOICE_STATE_*
+// flags are VOICE_*
+// host_port can be NULL
+typedef void (*SIPClientCallback)(void *param, int callId, int state, int flags, const TCHAR *host_port);
+
+struct SIP_REGISTRATION
+{
+ int cbSize;
+ const char *name; // Internal name of client
+ int udp_port; // UDP port to be used: 0 means random, -1 means don't want UDP
+ int tcp_port; // UDP port to be used: 0 means TCP, -1 means don't want TCP
+ int tls_port; // UDP port to be used: 0 means TLS, -1 means don't want TLS
+
+ HANDLE hNetlib; // To be used for logs. Can be 0
+
+ SIPClientCallback callback;
+ void *callback_param;
+};
+
+
+struct SIP_CLIENT
+{
+ void *data; // Do not touch
+ const TCHAR *host;
+ const int udp_port;
+ const int tcp_port;
+ const int tls_port;
+
+ // @param protocol 1 UDP, 2 TCP, 3 TLS
+ // @return callId or <0 on error
+ int (*Call)(SIP_CLIENT *sip, const TCHAR *host, int port, int protocol);
+
+ // @return 0 on success
+ int (*DropCall)(SIP_CLIENT *sip, int callId);
+
+ // @return 0 on success
+ int (*HoldCall)(SIP_CLIENT *sip, int callId);
+
+ // @return 0 on success
+ int (*AnswerCall)(SIP_CLIENT *sip, int callId);
+
+ // @return 0 on success
+ int (*SendDTMF)(SIP_CLIENT *sip, int callId, TCHAR dtmf);
+};
+
+
+/*
+Register a SIP client, allowing it to make calls
+
+wParam = SIP_REGISTRATION *
+lParam = 0
+return SIP_CLIENT * or NULL on error
+*/
+#define MS_SIP_REGISTER "SIP/Client/Register"
+
+
+/*
+Unregister a SIP client and free the internal structures.
+
+wParam = SIP_CLIENT *
+lParam = 0
+return 0 on success
+*/
+#define MS_SIP_UNREGISTER "SIP/Client/Unregister"
+
+
+
+
+
+
+
+
+
+#endif // __M_SIP_H__
diff --git a/Plugins/sip_cli/sdk/m_voice.h b/Plugins/sip_cli/sdk/m_voice.h new file mode 100644 index 0000000..e4ea883 --- /dev/null +++ b/Plugins/sip_cli/sdk/m_voice.h @@ -0,0 +1,180 @@ +/*
+Copyright (C) 2006-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __M_VOICE_H__
+# define __M_VOICE_H__
+
+
+#define EVENTTYPE_VOICE_CALL 8739
+
+
+#define VOICE_CAPS_VOICE (1<<0) // Voice is supported for this protocol. You need to set this one.
+#define VOICE_CAPS_CALL_CONTACT (1<<1) // Set if a call can be made to a hContact (PS_VOICE_CALL_CONTACT_VALID is used to validate the string)
+#define VOICE_CAPS_CALL_STRING (1<<3) // Set if a call can be made to some string (PS_VOICE_CALL_STRING_VALID is used to validate the string)
+/*
+Request to the protocol capabilities relative to voice.
+
+wParam: 0
+lParam: 0
+return: VOICE_CAPS_*
+*/
+#define PS_VOICE_CAPS "/Voice/Caps"
+
+
+
+#define VOICE_SECURE 0x00000001
+#define VOICE_UNICODE 0x80000000
+
+#ifdef UNICODE
+# define VOICE_TCHAR VOICE_UNICODE
+#else
+# define VOICE_TCHAR 0
+#endif
+
+#define VOICE_STATE_TALKING 0
+#define VOICE_STATE_RINGING 1
+#define VOICE_STATE_CALLING 2
+#define VOICE_STATE_ON_HOLD 3
+#define VOICE_STATE_ENDED 4
+#define VOICE_STATE_BUSY 5
+
+typedef struct {
+ int cbSize; // Struct size
+ const char *moduleName; // The name of the module (the same as VOICE_MODULE.name or the protocol szModule)
+ char *id; // Protocol especific ID for this call
+ int flags; // VOICE_UNICODE to say the string is unicode or 0. VOICE_SECURE to say this is a
+ // encrypted call
+
+ HANDLE hContact; // Contact associated with the call (can be NULL)
+
+ union { // Number to call (can be NULL)
+ const TCHAR *ptszNumber;// Or the contact or the number must be != NULL
+ const char *pszNumber; // If both are != NULL the call will be made to the number
+ const WCHAR *pwszNumber;// and will be associated with the contact
+ }; // This fields are only needed in first notification for a call id
+
+ union { // Name of the caller. This makes sense only on incoming calls,
+ const TCHAR *ptszName; // where no contact is associated and the caller has a name and a number.
+ const char *pszName;
+ const WCHAR *pwszName;
+ };
+
+
+ int state; // VOICE_STATE_*
+
+} VOICE_CALL;
+
+
+/*
+Notifies that a voice call changed state
+
+wParam: const VOICE_CALL *
+lParam: ignored
+return: 0 on success
+*/
+#define PE_VOICE_CALL_STATE "/Voice/State"
+
+
+
+/*
+Request the protocol to make a voice call
+
+wParam: (HANDLE) hContact
+lParam: (const TCHAR *) number
+return: 0 on success
+Or the contact or the number must be != NULL. If both are != NULL the call will be
+made to the number and will be associated with the contact.
+*/
+#define PS_VOICE_CALL "/Voice/Call"
+
+/*
+Service called to make the protocol answer a call or restore a hold call.
+It is an async call. If the call was answered, the PE_VOICE_CALL_STATE
+notification will be fired.
+
+wParam: (const char *) id
+lParam: ignored
+return: 0 on success
+*/
+#define PS_VOICE_ANSWERCALL "/Voice/AnswerCall"
+
+/*
+Service called to make the protocol answer a call. This can be called if the
+call is ringing or has started. If called any other time it should be ignored.
+It is an async call. If the call was droped, the PE_VOICE_CALL_STATE
+notification will be fired.
+
+wParam: (const char *) id
+lParam: ignored
+return: 0 on success
+*/
+#define PS_VOICE_DROPCALL "/Voice/DropCall"
+
+/*
+Service called to make the protocol hold a call. This means that the call should not
+be droped, but it should be muted and put in a hold, to allow other call to be answered.
+If the protocol can't hold a cal, it should be droped.
+
+This can be called if the call has started. If called any other time it should be ignored.
+It is an async call. If the call was droped, the PE_VOICE_CALL_STATE
+notification will be fired.
+
+wParam: (const char *) id
+lParam: ignored
+return: 0 on success
+*/
+#define PS_VOICE_HOLDCALL "/Voice/HoldCall"
+
+/*
+Send a DTMF (one digit text) to a talking call.
+
+wParam: (const char *) id
+lParam: (TCHAR) dtmf
+return: 0 on success
+*/
+#define PS_VOICE_SEND_DTMF "/Voice/SendDTMF"
+
+/*
+Used if protocol support VOICE_CALL_STRING. The call string is passed as
+wParam and the proto should validate it. If this service does not exist all numbers can be called.
+
+wParam: (const TCHAR *) call string
+lParam: ignored
+return: 0 if wrong, 1 if correct
+*/
+#define PS_VOICE_CALL_STRING_VALID "/Voice/CallStringValid"
+
+/*
+Used if protocol support VOICE_CALL_CONTACT.
+The hContact is passed as wParam and the proto should tell if this contact can be
+called. If this service does not exist all contacts can be called (or, if it is a protocol,
+all contacts from the protocol can be called).
+
+wParam: (HANDLE) hContact
+lParam: (BOOL) TRUE if it is a test for 'can call now?', FALSE if is a test for 'will be possible to call someday?'
+return: 0 if can't be called, 1 if can
+*/
+#define PS_VOICE_CALL_CONTACT_VALID "/Voice/CallContactValid"
+
+
+
+
+
+#endif // __M_VOICE_H__
diff --git a/Plugins/sip_cli/sdk/m_voiceservice.h b/Plugins/sip_cli/sdk/m_voiceservice.h new file mode 100644 index 0000000..2d55d9a --- /dev/null +++ b/Plugins/sip_cli/sdk/m_voiceservice.h @@ -0,0 +1,90 @@ +/*
+Copyright (C) 2007-2009 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __M_VOICESERVICE_H__
+# define __M_VOICESERVICE_H__
+
+
+#define MIID_VOICESERVICE { 0x7d64437, 0xef2e, 0x4f60, { 0xbb, 0x2d, 0x3c, 0x51, 0x8f, 0xe2, 0x4d, 0x63 } }
+
+
+/*
+This services are a mirror of the services/notifications in m_voice.h,
+with the difference that that ones are to be used by protocols, and this ones
+are to be used by plugins that can make calls to contacts in multiple protocols.
+
+To get the devices for input/output and some options, query the db directly:
+ VoiceService/EchoCancelation BYTE default: TRUE
+ VoiceService/MicBoost BYTE default: TRUE
+ VoiceService/Input TString default: windows default
+ VoiceService/Output TString default: windows default
+*/
+
+
+struct VOICE_MODULE
+{
+ int cbSize; // sizeof(VOICE_MODULE)
+ TCHAR *description; // The description of the voice provider. This is the name that will be shown
+ // to the user
+ char *name; // The internal name of the voice provider. All PS_* serivces
+ // defined in m_voide.h need to be created based in this name. For example,
+ // PS_VOICE_CALL (/Voice/Call) need to be created as <name>/Voice/Call
+ char *icon; // Icon to identify provider (from icolib)
+ int flags; // or of VOICE_CAPS_*. You don't need to send VOICE_CAPS_VOICE.
+};
+/*
+Register a new plugin that can make/receive voice calls (a voice provider).
+
+wParam: const VOICE_MODULE *
+lParam: ignored
+return: 0 on success
+*/
+#define MS_VOICESERVICE_REGISTER "VoiceService/Register"
+
+/*
+Unregister a plugin that can make/receive voice calls (a voice provider).
+
+wParam: (const char *) Provider name
+lParam: ignored
+return: 0 on success
+*/
+#define MS_VOICESERVICE_UNREGISTER "VoiceService/Unregister"
+
+/*
+Request a voice call to hContact.
+
+wParam: (HANDLE) hContact
+lParam: ignored
+return: the number of option calls for a contact. If > 0, it can be called
+*/
+#define MS_VOICESERVICE_CAN_CALL "VoiceService/CanCall"
+
+/*
+Request a voice call to hContact.
+
+wParam: (HANDLE) hContact
+lParam: (char *) Voice provider or NULL to use any provider avaiable
+return: 0 on success
+*/
+#define MS_VOICESERVICE_CALL "VoiceService/Call"
+
+
+
+#endif // __M_VOICESERVICE_H__
diff --git a/Plugins/sip_cli/sip_cli.cpp b/Plugins/sip_cli/sip_cli.cpp new file mode 100644 index 0000000..b017daf --- /dev/null +++ b/Plugins/sip_cli/sip_cli.cpp @@ -0,0 +1,285 @@ +/*
+Copyright (C) 2010 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "commons.h"
+
+
+// Prototypes ///////////////////////////////////////////////////////////////////////////
+
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+#ifdef UNICODE
+ "SIP Client Test (Unicode)",
+#else
+ "SIP Client Test (Ansi)",
+#endif
+ PLUGIN_MAKE_VERSION(0,1,0,0),
+ "SIP Client example",
+ "Ricardo Pescuma Domenecci",
+ "pescuma@miranda-im.org",
+ "© 2010 Ricardo Pescuma Domenecci",
+ "http://pescuma.org/miranda/sip",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#ifdef UNICODE
+ { 0xcfbcbfac, 0x7f26, 0x489f, { 0x91, 0x7e, 0xc6, 0x7f, 0xc2, 0x2e, 0x55, 0xfd } } // {CFBCBFAC-7F26-489f-917E-C67FC22E55FD}
+#else
+ { 0x97506685, 0x6de4, 0x47ef, { 0x84, 0x61, 0x5f, 0xbd, 0xcf, 0xd0, 0x8f, 0x0 } } // {97506685-6DE4-47ef-8461-5FBDCFD08F00}
+#endif
+};
+
+#define MIID_SIP_CLI { 0xa8a11cca, 0x5545, 0x43d2, { 0xb0, 0x5c, 0x55, 0x5a, 0xde, 0xe1, 0x11, 0x2f } }
+
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+MM_INTERFACE mmi;
+UTF8_INTERFACE utfi;
+
+static INT_PTR ModulesLoaded(WPARAM wParam, LPARAM lParam);
+static INT_PTR PreShutdown(WPARAM wParam, LPARAM lParam);
+
+static BOOL CALLBACK TestDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static INT_PTR Service_Call(WPARAM wParam, LPARAM lParam);
+static INT_PTR Service_Answer(WPARAM wParam, LPARAM lParam);
+static INT_PTR Service_Hold(WPARAM wParam, LPARAM lParam);
+static INT_PTR Service_Drop(WPARAM wParam, LPARAM lParam);
+static INT_PTR Service_SendDTMF(WPARAM wParam, LPARAM lParam);
+
+
+// Functions ////////////////////////////////////////////////////////////////////////////
+
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFO);
+ return (PLUGININFO*) &pluginInfo;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFOEX);
+ return &pluginInfo;
+}
+
+
+static const MUUID interfaces[] = { MIID_SIP_CLI, MIID_LAST };
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ CHECK_VERSION("SIP_CLI")
+
+ // TODO Assert results here
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown);
+
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
+
+
+
+SIP_CLIENT *cli;
+HANDLE hEvent;
+HWND hwnd;
+
+void Callback(void *param, int callId, int state, int flags, const TCHAR *host_port)
+{
+ char tmp[16];
+
+ VOICE_CALL vc = {0};
+ vc.cbSize = sizeof(vc);
+ vc.moduleName = MODULE_NAME;
+ vc.id = itoa(callId, tmp, 10);
+ vc.flags = flags;
+ vc.hContact = NULL;
+ //vc.ptszName = name;
+ vc.ptszNumber = host_port;
+ vc.state = state;
+
+ NotifyEventHooks(hEvent, (WPARAM) &vc, 0);
+
+}
+
+static INT_PTR Service_Call(WPARAM wParam, LPARAM lParam)
+{
+ // Not implemented yet
+ return -1;
+}
+
+static INT_PTR Service_Answer(WPARAM wParam, LPARAM lParam)
+{
+ const char *id = (const char *) wParam;
+ if (id == NULL)
+ return -1;
+
+ return cli->AnswerCall(cli, atoi(id));
+}
+
+static INT_PTR Service_Hold(WPARAM wParam, LPARAM lParam)
+{
+ const char *id = (const char *) wParam;
+ if (id == NULL)
+ return -1;
+
+ return cli->HoldCall(cli, atoi(id));
+}
+
+static INT_PTR Service_Drop(WPARAM wParam, LPARAM lParam)
+{
+ const char *id = (const char *) wParam;
+ if (id == NULL)
+ return -1;
+
+ return cli->DropCall(cli, atoi(id));
+}
+
+static INT_PTR Service_SendDTMF(WPARAM wParam, LPARAM lParam)
+{
+ const char *id = (const char *) wParam;
+ if (id == NULL)
+ return -1;
+
+ return cli->SendDTMF(cli, atoi(id), (TCHAR) lParam);
+}
+
+static INT_PTR ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ SIP_REGISTRATION reg = {0};
+ reg.cbSize = sizeof(SIP_REGISTRATION);
+ reg.name = MODULE_NAME;
+ reg.callback = Callback;
+
+ cli = (SIP_CLIENT *) CallService(MS_SIP_REGISTER, (WPARAM) ®, 0);
+ if (cli == NULL)
+ {
+ MessageBox(NULL, _T("Error registering with SIP"), _T("SIP_CLI"), MB_OK | MB_ICONERROR);
+ return 0;
+ }
+
+ char tmp[512];
+ mir_snprintf(tmp, MAX_REGS(tmp), "SIP_CLI%s", PE_VOICE_CALL_STATE);
+ hEvent = CreateHookableEvent(tmp);
+
+ mir_snprintf(tmp, MAX_REGS(tmp), "SIP_CLI%s", PS_VOICE_CALL);
+ CreateServiceFunction(tmp, &Service_Call);
+ mir_snprintf(tmp, MAX_REGS(tmp), "SIP_CLI%s", PS_VOICE_ANSWERCALL);
+ CreateServiceFunction(tmp, &Service_Answer);
+ mir_snprintf(tmp, MAX_REGS(tmp), "SIP_CLI%s", PS_VOICE_DROPCALL);
+ CreateServiceFunction(tmp, &Service_Drop);
+ mir_snprintf(tmp, MAX_REGS(tmp), "SIP_CLI%s", PS_VOICE_HOLDCALL);
+ CreateServiceFunction(tmp, &Service_Hold);
+ mir_snprintf(tmp, MAX_REGS(tmp), "SIP_CLI%s", PS_VOICE_SEND_DTMF);
+ CreateServiceFunction(tmp, &Service_SendDTMF);
+
+ VOICE_MODULE vm = {0};
+ vm.cbSize = sizeof(vm);
+ vm.description = _T("SIP Client Test");
+ vm.name = "SIP_CLI";
+ // TODO vm.icon
+ vm.flags = VOICE_CAPS_VOICE;
+ CallService(MS_VOICESERVICE_REGISTER, (WPARAM) &vm, 0);
+
+ hwnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_DLG), NULL, TestDlgProc);
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+
+ return 0;
+}
+
+
+static INT_PTR PreShutdown(WPARAM wParam, LPARAM lParam)
+{
+ if (cli)
+ CallService(MS_SIP_UNREGISTER, (WPARAM) cli, 0);
+
+ return 0;
+}
+
+
+static BOOL CALLBACK TestDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ TCHAR text[1024];
+ mir_sntprintf(text, MAX_REGS(text), TranslateT("Host: %s\nUDP: %d\nTCP: %d\nTLS: %d"),
+ cli->host, cli->udp_port, cli->tcp_port, cli->tls_port);
+ SendDlgItemMessage(hwndDlg, IDC_DATA, WM_SETTEXT, 0, (LPARAM) text);
+
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_ADDSTRING, 0, (LPARAM) _T("UDP"));
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_ADDSTRING, 0, (LPARAM) _T("TCP"));
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_ADDSTRING, 0, (LPARAM) _T("TLS"));
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_SETCURSEL, 0, 0);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch(wParam)
+ {
+ case IDC_CALL:
+ {
+ TCHAR host[512];
+ GetDlgItemText(hwndDlg, IDC_HOST, host, MAX_REGS(host));
+ int port = GetDlgItemInt(hwndDlg, IDC_PORT, NULL, TRUE);
+ int protocol = SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, CB_GETCURSEL, 0, 0) + 1;
+
+ int callId = cli->Call(cli, host, port, protocol);
+ if (callId < 0)
+ MessageBox(NULL, _T("Error making call"), _T("SIP_CLI"), MB_OK | MB_ICONERROR);
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/Plugins/sip_cli/sip_cli.dsp b/Plugins/sip_cli/sip_cli.dsp new file mode 100644 index 0000000..96eb22d --- /dev/null +++ b/Plugins/sip_cli/sip_cli.dsp @@ -0,0 +1,187 @@ +# Microsoft Developer Studio Project File - Name="sip_cli" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=sip_cli - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sip_cli.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sip_cli.mak" CFG="sip_cli - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sip_cli - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "sip_cli - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "sip_cli - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "sip_cli - Win32 Unicode Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sip_cli - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O1 /YX /FD /c
+# SUBTRACT BASE CPP /Fr
+# ADD CPP /nologo /G5 /MT /W3 /GX /O2 /Ob0 /I "../../include" /I "sdk" /I "lib/portaudio" /D "WIN32" /D "W32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 user32.lib shell32.lib wininet.lib gdi32.lib /nologo /base:"0x67100000" /dll /machine:I386 /filealign:0x200
+# SUBTRACT BASE LINK32 /pdb:none /map
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"" /dll /map /debug /debugtype:both /machine:I386 /out:"..\..\bin\release\Plugins\sip_cli.dll" /pdbtype:sept /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "sip_cli - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G4 /MT /W3 /GX /O2 /Ob0 /I "../../include" /FR /YX /FD /c
+# ADD CPP /nologo /G5 /MDd /W3 /GX /ZI /Od /I "../../include" /I "sdk" /I "lib/portaudio" /D "WIN32" /D "W32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..bin\release\Plugins\sip_cli.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug\Plugins\sip_cli.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "sip_cli - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "sip_cli___Win32_Unicode_Debug"
+# PROP BASE Intermediate_Dir "sip_cli___Win32_Unicode_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Debug"
+# PROP Intermediate_Dir "Unicode_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G4 /MTd /W3 /GX /ZI /Od /I "../../include" /FR /YX /FD /c
+# ADD CPP /nologo /G5 /MDd /W3 /GX /ZI /Od /I "../../include" /I "sdk" /I "lib/portaudio" /D "WIN32" /D "W32" /D "_DEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x32100000" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug\Plugins\sip_cli.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug unicode\Plugins\sip_cliW.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "sip_cli - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "sip_cli___Win32_Unicode_Release"
+# PROP BASE Intermediate_Dir "sip_cli___Win32_Unicode_Release"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Release"
+# PROP Intermediate_Dir "Unicode_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /G4 /MT /W3 /GX /O2 /Ob0 /I "../../include" /Fr /YX /FD /c
+# ADD CPP /nologo /G5 /MT /W3 /GX /O2 /Ob0 /I "../../include" /I "sdk" /I "lib/portaudio" /D "WIN32" /D "W32" /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "_USRDLL" /Fr /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x417 /d "NDEBUG"
+# ADD RSC /l 0x417 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x32100000" /dll /map /machine:I386 /out:"..\..\bin\release\Plugins\sip_cli.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 kernel32.lib user32.lib /nologo /base:"" /dll /map /debug /debugtype:both /machine:I386 /out:"..\..\bin\release\Plugins\sip_cliW.dll" /pdbtype:sept /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "sip_cli - Win32 Release"
+# Name "sip_cli - Win32 Debug"
+# Name "sip_cli - Win32 Unicode Debug"
+# Name "sip_cli - Win32 Unicode Release"
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\commons.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# End Group
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\sip_cli.cpp
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Plugins/sip_cli/sip_cli.dsw b/Plugins/sip_cli/sip_cli.dsw new file mode 100644 index 0000000..52b4862 --- /dev/null +++ b/Plugins/sip_cli/sip_cli.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sip_cli"=.\sip_cli.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
|