From cbfe48a482e80dd513308d90d500f7c34c33b068 Mon Sep 17 00:00:00 2001 From: sje Date: Fri, 3 Nov 2006 13:33:30 +0000 Subject: git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@35 4f64403b-2f21-0410-a795-97e2b3489a10 --- iax/IcoLib.h | 37 +++ iax/README_building.txt | 13 + iax/common.h | 37 +++ iax/dial_dlg.cpp | 343 ++++++++++++++++++++++++++ iax/dial_dlg.h | 14 ++ iax/dllmain.cpp | 121 ++++++++++ iax/docs/licence_iax.txt | 8 + iax/iax.rc | 229 ++++++++++++++++++ iax/iax_8.sln | 29 +++ iax/iax_8.vcproj | 334 ++++++++++++++++++++++++++ iax/iax_interface.cpp | 325 +++++++++++++++++++++++++ iax/iax_interface.h | 26 ++ iax/iaxclient_patch.patch | 597 ++++++++++++++++++++++++++++++++++++++++++++++ iax/icon1.ico | Bin 0 -> 766 bytes iax/icons.cpp | 50 ++++ iax/icons.h | 9 + iax/menu.cpp | 151 ++++++++++++ iax/menu.h | 10 + iax/options.cpp | 306 ++++++++++++++++++++++++ iax/options.h | 21 ++ iax/private.h | 24 ++ iax/private.rc | 35 +++ iax/resource.h | 70 ++++++ iax/resource.rc | 2 + iax/services.cpp | 292 +++++++++++++++++++++++ iax/services.h | 14 ++ iax/utils.cpp | 126 ++++++++++ iax/utils.h | 10 + 28 files changed, 3233 insertions(+) create mode 100644 iax/IcoLib.h create mode 100644 iax/README_building.txt create mode 100644 iax/common.h create mode 100644 iax/dial_dlg.cpp create mode 100644 iax/dial_dlg.h create mode 100644 iax/dllmain.cpp create mode 100644 iax/docs/licence_iax.txt create mode 100644 iax/iax.rc create mode 100644 iax/iax_8.sln create mode 100644 iax/iax_8.vcproj create mode 100644 iax/iax_interface.cpp create mode 100644 iax/iax_interface.h create mode 100644 iax/iaxclient_patch.patch create mode 100644 iax/icon1.ico create mode 100644 iax/icons.cpp create mode 100644 iax/icons.h create mode 100644 iax/menu.cpp create mode 100644 iax/menu.h create mode 100644 iax/options.cpp create mode 100644 iax/options.h create mode 100644 iax/private.h create mode 100644 iax/private.rc create mode 100644 iax/resource.h create mode 100644 iax/resource.rc create mode 100644 iax/services.cpp create mode 100644 iax/services.h create mode 100644 iax/utils.cpp create mode 100644 iax/utils.h diff --git a/iax/IcoLib.h b/iax/IcoLib.h new file mode 100644 index 0000000..1817df6 --- /dev/null +++ b/iax/IcoLib.h @@ -0,0 +1,37 @@ +typedef struct { + int cbSize; + char *pszSection; //section name used to group icons + char *pszDescription; //description for options dialog + char *pszName; //name to refer to icon when playing and in db + //this name is miranda-wide. so use prefixes of your plugin + //e.g: "isee_connect", "clist_delete", etc + char *pszDefaultFile; //default icon file to use + int iDefaultIndex; +} SKINICONDESC; + +typedef struct { + int cbSize; + char *pszSection; + char *pszDescription; + char *pszName; + char *pszDefaultFile; + int iDefaultIndex; + HICON hDefaultIcon; +} SKINICONDESC2; + +// +// Add a icon into options UI +// +// wParam = (WPARAM)0 +// lParam = (LPARAM)(SKINICONDESC*)sid; +// +#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon" +// +// Retrieve HICON with name specified in lParam +// Returned HICON SHOULDN'T be destroyed, it managed by IcoLib +// +#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon" +// +// Icons change notification +// +#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged" diff --git a/iax/README_building.txt b/iax/README_building.txt new file mode 100644 index 0000000..9d33c13 --- /dev/null +++ b/iax/README_building.txt @@ -0,0 +1,13 @@ +notes on building: +------------------ + +get iaxclient + +i managed to get the vs2005 static library to build, but had to remove the cpp file which doesn't exist and replace it with the c file which does, and then +set vc to build that file as c++ code...also had to change the calling convention in that project (was set to stdcall instead of cdecl) so that the exports worked + +optionally get the ilbc codec (instructions on building in the ilbc codec are in the readme for iaxclient) - add codec_ilibc.cpp and header file to iaxclient lib project, +and #define CODEC_ILBC in BOTH the iaxclient lib project and the iax plugin project + +that should be it + diff --git a/iax/common.h b/iax/common.h new file mode 100644 index 0000000..a20064c --- /dev/null +++ b/iax/common.h @@ -0,0 +1,37 @@ +#ifndef _COMMON_INC +#define _COMMON_INC + +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0500 + +#define MIRANDA_VER 0x0600 + +#include +#include +#include "win2k.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "IcoLib.h" + +#define MODULE "IAX" + +extern HINSTANCE hInst; + +#endif diff --git a/iax/dial_dlg.cpp b/iax/dial_dlg.cpp new file mode 100644 index 0000000..29fcf66 --- /dev/null +++ b/iax/dial_dlg.cpp @@ -0,0 +1,343 @@ +#include "common.h" +#include "dial_dlg.h" +#include "resource.h" +#include "utils.h" +#include "options.h" +#include "iax_interface.h" + +HWND hWnd = 0; +ATOM hkid; + +#define WMU_REFRESHLINEINFO (WM_USER + 0x10) +#define WMU_SETLEVELS (WM_USER + 0x11) + +bool first_show = true; + +HBRUSH hBrushActive, hBrushFree, hBrushActiveSelect, hBrushFreeSelect, hBrushRingIn, hBrushRingOut, hBrushRingInSelect, hBrushRingOutSelect; + +struct CallHist { + char num[256]; + char name[256]; + CallHist *next; +}; + +CallHist *hist = 0; + +void list_insert(char *buff, char *name_buff) { + bool in_list = false; + CallHist *node = hist; + while(node && !in_list) { + if(strcmp(node->num, buff) == 0) { + in_list = true; + break; + } + node = node->next; + } + if(!in_list) { + node = (CallHist *)malloc(sizeof(CallHist)); + node->next = hist; + strncpy(node->num, buff, 256); + strncpy(node->name, name_buff, 256); + hist = node; + } else { + if(name_buff[0]) + strncpy(node->name, name_buff, 256); + } +} + +static BOOL CALLBACK DlgProcDial(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + switch ( msg ) { + case WM_INITDIALOG: + hWnd = hwndDlg; + + TranslateDialogDefault( hwndDlg ); + { + CallHist *node = hist; + while(node) { + SendDlgItemMessage(hwndDlg, IDC_CMB_NUM, CB_ADDSTRING, 0, (LPARAM)node->num); + node = node->next; + } + } + SendMessage(hwndDlg, WMU_REFRESHLINEINFO, 0, 0); + SendMessage(hwndDlg, WMU_SETLEVELS, 0, 0); + + SendDlgItemMessage(hwndDlg, IDC_SLD_IN, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(int)(iaxc_input_level_get() * 100)); + SendDlgItemMessage(hwndDlg, IDC_SLD_OUT, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(int)(iaxc_output_level_get() * 100)); + + ResetDlgHotkey(); + + SetFocus(GetDlgItem(hwndDlg, IDC_CMB_NUM)); + return TRUE; + + case WM_DRAWITEM: + { + bool active, select, ringing, outgoing; + int line_no = 0; + if(wParam == IDC_L1) line_no = 0; + else if(wParam == IDC_L2) line_no = 1; + else if(wParam == IDC_L3) line_no = 2; + else break; + + ringing = (GetLineState(line_no) & IAXC_CALL_STATE_RINGING) != 0; + outgoing = (GetLineState(line_no) & IAXC_CALL_STATE_OUTGOING) != 0; + active = (GetLineState(line_no) & IAXC_CALL_STATE_ACTIVE) != 0; + select = (GetLineNo() == line_no); + + HBRUSH bgBrush = 0; + if(ringing) { + if(outgoing) { + if(select) bgBrush = hBrushRingOutSelect; + else bgBrush = hBrushRingOut; + } else { + if(select) bgBrush = hBrushRingInSelect; + else bgBrush = hBrushRingIn; + } + } else { + if(active) { + if(select) bgBrush = hBrushActiveSelect; + else bgBrush = hBrushActive; + } else { + if(select) bgBrush = hBrushFreeSelect; + else bgBrush = hBrushFree; + } + } + + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; + //FillRect(dis->hDC, &dis->rcItem, bgBrush); + HBRUSH oldBrush = (HBRUSH)SelectObject(dis->hDC, bgBrush); + RoundRect(dis->hDC, dis->rcItem.left, dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom, 3, 3); + SelectObject(dis->hDC, oldBrush); + + char buff[2]; + GetWindowText(GetDlgItem(hwndDlg, wParam), buff, 2); + SetBkMode(dis->hDC, TRANSPARENT); + DrawText(dis->hDC, buff, 1, &dis->rcItem, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_NOPREFIX); + + return TRUE; + + } + break; + + case WM_SHOWWINDOW: + if(wParam && first_show) { + first_show = false; + + SAVEWINDOWPOS swp; + swp.hwnd=hwndDlg; swp.hContact=0; swp.szModule=MODULE; swp.szNamePrefix="CallWindow"; + CallService(MS_UTILS_RESTOREWINDOWPOSITION, RWPF_NOSIZE | RWPF_NOACTIVATE, (LPARAM)&swp); + } + break; + + case WM_HOTKEY: + if(IsWindowVisible(hwndDlg)) + ShowWindow(hwndDlg, SW_HIDE); + else { + ShowWindow(hwndDlg, SW_SHOW); + SetForegroundWindow(hWnd); + } + return TRUE; + case WM_HSCROLL: + //if (LOWORD(wParam) == TB_PAGEUP || LOWORD(wParam) == TB_PAGEDOWN) + { + int input = SendDlgItemMessage(hwndDlg, IDC_SLD_IN, TBM_GETPOS, 0, 0), + output = SendDlgItemMessage(hwndDlg, IDC_SLD_OUT, TBM_GETPOS, 0, 0); + + iaxc_input_level_set(input / 100.0); + iaxc_output_level_set(output / 100.0); + } + break; + case WM_COMMAND: + if ( HIWORD( wParam ) == CBN_SELCHANGE) { + SetDlgItemText(hwndDlg, IDC_ED_NAME, ""); + } else if ( HIWORD( wParam ) == BN_CLICKED ) { + char c = 0; + switch( LOWORD( wParam )) { + case IDC_BTN_CALL: + { + char buff[256]; + GetDlgItemText(hwndDlg, IDC_CMB_NUM, buff, 256); + if(buff[0]) { + Call(buff); + SetFocus(GetDlgItem(hwndDlg, IDC_CMB_NUM)); + } + } + return TRUE; + + case IDC_BTN_HANGUP: + { + HangUp(); + SetFocus(GetDlgItem(hwndDlg, IDC_CMB_NUM)); + } + return TRUE; + + case IDC_BTN_ANSWER: + { + AnswerCall(GetLineNo()); + SetFocus(GetDlgItem(hwndDlg, IDC_CMB_NUM)); + } + return TRUE; + + case IDC_L1: SelectLine(0); return TRUE; + case IDC_L2: SelectLine(1); return TRUE; + case IDC_L3: SelectLine(2); return TRUE; + + case IDC_B0: c = '0'; break; + case IDC_B1: c = '1'; break; + case IDC_B2: c = '2'; break; + case IDC_B3: c = '3'; break; + case IDC_B4: c = '4'; break; + case IDC_B5: c = '5'; break; + case IDC_B6: c = '6'; break; + case IDC_B7: c = '7'; break; + case IDC_B8: c = '8'; break; + case IDC_B9: c = '9'; break; + case IDC_BSTAR: c = '*'; break; + case IDC_BHASH: c = '#'; break; + } + + SkinPlaySound("iax_keypad"); + + char buff[512]; + GetDlgItemText(hwndDlg, IDC_CMB_NUM, buff, 512); + if(strlen(buff) < 511) { + strncat(buff, &c, 1); + SetDlgItemText(hwndDlg, IDC_CMB_NUM, buff); + } + + SendDTMF(c); + } + break; + case WMU_REFRESHLINEINFO: + { + char *num = GetLineCIDNum(GetLineNo()), *name = GetLineCIDName(GetLineNo()); + // trim prefix from name if present + char prefix[512]; + mir_snprintf(prefix, 512, "%s:%s@%s", options.username, options.password, options.host); + int prefix_len = strlen(prefix); + if(strncmp(name, prefix, prefix_len) == 0) + name += prefix_len + 1; + SetDlgItemText(hwndDlg, IDC_CMB_NUM, num); + SetDlgItemText(hwndDlg, IDC_ED_NAME, name); + bool active = (GetLineState(GetLineNo()) & IAXC_CALL_STATE_ACTIVE) != 0; + + if(active && num[0]) list_insert(num, name); + + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_CALL), !active); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_HANGUP), active); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_ANSWER), (GetLineState(GetLineNo()) & IAXC_CALL_STATE_RINGING) && !(GetLineState(GetLineNo()) & IAXC_CALL_STATE_OUTGOING)); + InvalidateRect(hwndDlg, 0, FALSE); + } + return TRUE; + case WMU_SETLEVELS: + { + int in = wParam, out = lParam; + SendDlgItemMessage(hwndDlg, IDC_PRG_IN, PBM_SETPOS, in, 0); + SendDlgItemMessage(hwndDlg, IDC_PRG_OUT, PBM_SETPOS, out, 0); + } + return TRUE; + case WM_CLOSE: + ShowWindow(hwndDlg, SW_HIDE); + return TRUE; + case WM_DESTROY: + Utils_SaveWindowPosition(hwndDlg,0,MODULE,"CallWindow"); + hWnd = 0; + break; + } + + return 0; +} + +void ShowDialDialog(bool activate) { + ShowWindow(hWnd, SW_SHOWNORMAL); + if(activate) SetForegroundWindow(hWnd); +} + +void SetLevels(float in, float out) { + if(!hWnd) return; + + PostMessage(hWnd, WMU_SETLEVELS, (WPARAM)(int)(99 + in), (LPARAM)(int)(99 + out)); +} + +void RefreshLineInfo() { + if(hWnd) PostMessage(hWnd, WMU_REFRESHLINEINFO, 0, 0); +} + +void ResetDlgHotkey() { + //PostMessage(hWnd, WM_SETHOTKEY, options.dlgHotkey, 0); + WORD vk = LOBYTE(options.dlgHotkey); + WORD hotkey_f = HIBYTE(options.dlgHotkey), + mod = 0; + + if(hotkey_f & HOTKEYF_ALT) mod |= MOD_ALT; + if(hotkey_f & HOTKEYF_CONTROL) mod |= MOD_CONTROL; + if(hotkey_f & HOTKEYF_EXT) mod |= MOD_WIN; + if(hotkey_f & HOTKEYF_SHIFT) mod |= MOD_SHIFT; + + UnregisterHotKey(hWnd, hkid); + if(!RegisterHotKey(hWnd, hkid, mod, vk)) { + ShowWarning("Failed to register hotkey"); + } +} + +void InitDialDialog() { + char buff[256]; + DBVARIANT dbv, dbv2; + for(int i = 0; i < 10; i++) { + mir_snprintf(buff, 256, "SavedNum%d", i); + if(!DBGetContactSettingTString(0, MODULE, buff, &dbv)) { + mir_snprintf(buff, 256, "SavedName%d", i); + if(!DBGetContactSettingTString(0, MODULE, buff, &dbv2)) { + list_insert(dbv.pszVal, dbv2.pszVal); + DBFreeVariant(&dbv2); + }else + list_insert(dbv.pszVal, ""); + DBFreeVariant(&dbv); + } + } + + hBrushActive = CreateSolidBrush(RGB(0, 0xff, 0)); + hBrushFree = CreateSolidBrush(RGB(0xD0, 0xD0, 0xD0)); + hBrushActiveSelect = CreateSolidBrush(RGB(0x80, 0xff, 0x80)); + hBrushFreeSelect = CreateSolidBrush(RGB(0xff, 0xff, 0xff)); + + hBrushRingIn = CreateSolidBrush(RGB(0xff, 0, 0xff)); + hBrushRingOut = CreateSolidBrush(RGB(0, 0, 0xff)); + hBrushRingInSelect = CreateSolidBrush(RGB(0xff, 0x80, 0xff)); + hBrushRingOutSelect = CreateSolidBrush(RGB(0x80, 0x80, 0xff)); + + hkid = GlobalAddAtom("IAX plugin hk id"); + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIAL), 0, DlgProcDial, 0); +} + +void DeinitDialDialog() { + UnregisterHotKey(hWnd, hkid); + GlobalDeleteAtom(hkid); + DestroyWindow(hWnd); + + CallHist *node; + int i = 0; + char buff[256]; + while(hist) { + + node = hist; + if(i < 10) { + mir_snprintf(buff, 256, "SavedNum%d", i); + DBWriteContactSettingTString(0, MODULE, buff, node->num); + mir_snprintf(buff, 256, "SavedName%d", i); + DBWriteContactSettingTString(0, MODULE, buff, node->name); + } + hist = hist->next; + free(node); + i++; + } + + DeleteObject(hBrushActive); + DeleteObject(hBrushFree); + DeleteObject(hBrushActiveSelect); + DeleteObject(hBrushFreeSelect); + + DeleteObject(hBrushRingIn); + DeleteObject(hBrushRingOut); + DeleteObject(hBrushRingInSelect); + DeleteObject(hBrushRingOutSelect); +} \ No newline at end of file diff --git a/iax/dial_dlg.h b/iax/dial_dlg.h new file mode 100644 index 0000000..d19887a --- /dev/null +++ b/iax/dial_dlg.h @@ -0,0 +1,14 @@ +#ifndef _DIAL_DLG_INC +#define _DIAL_DLG_INC + +void ResetDlgHotkey(); + +void ShowDialDialog(bool activate); +void SetLevels(float in, float out); + +void RefreshLineInfo(); + +void InitDialDialog(); +void DeinitDialDialog(); + +#endif \ No newline at end of file diff --git a/iax/dllmain.cpp b/iax/dllmain.cpp new file mode 100644 index 0000000..a96ab4c --- /dev/null +++ b/iax/dllmain.cpp @@ -0,0 +1,121 @@ +/* Replace "dll.h" with the name of your header */ +#include "common.h" +#include "private.h" +#include "resource.h" +#include "icons.h" +#include "options.h" +#include "services.h" +#include "iax_interface.h" +#include "menu.h" + +/////////////////////////////////////////////// +// Common Plugin Stuff +/////////////////////////////////////////////// +HINSTANCE hInst; +PLUGINLINK *pluginLink; + +// plugin stuff +PLUGININFO pluginInfo={ + sizeof(PLUGININFO), + MODULE, + PLUGIN_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_RELEASE, VER_BUILD), + DESC_STRING, + "Scott Ellis", + "mail@scottellis.com.au", + "© 2005 Scott Ellis", + "http://www.scottellis.com.au/", + 0, //not transient + 0 //doesn't replace anything built-in +}; + +extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { + hInst=hinstDLL; + return TRUE; +} + +extern "C" __declspec (dllexport) PLUGININFO* __cdecl MirandaPluginInfo(DWORD mirandaVersion) { + return &pluginInfo; +} + +int ModulesLoaded(WPARAM wParam, LPARAM lParam) { + if(ServiceExists(MS_UPDATE_REGISTER)) { + // register with updater + Update update = {0}; + char szVersion[16]; + + update.cbSize = sizeof(Update); + + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); + + update.szUpdateURL = UPDATER_AUTOREGISTER; + + // these are the three lines that matter - the archive, the page containing the version string, and the text (or data) + // before the version that we use to locate it on the page + // (note that if the update URL and the version URL point to standard file listing entries, the backend xml + // data will be used to check for updates rather than the actual web page - this is not true for beta urls) + update.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/iax.zip"; + update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_iax.html"; + update.pbBetaVersionPrefix = (BYTE *)"IAX, version "; + + update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix); + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + } + + InitIcons(); + InitMenu(); + + return 0; +} + +HANDLE hModulesLoaded; +extern "C" __declspec (dllexport) int __cdecl Load(PLUGINLINK *link) { + pluginLink=link; + + PreInitOptions(); + + if(!InitIAXInterface()) { + MessageBox(0, Translate("Failed to initialize IAX Client library. Plugin disabled."), Translate("IAX Plugin error"), MB_OK | MB_ICONERROR); + return 1; + } + + if(ServiceExists(MS_DB_SETSETTINGRESIDENT)) { // 0.6+ + CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/Status")); + CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (LPARAM)(MODULE "/LineNo")); + } + + INITCOMMONCONTROLSEX icex; + + // Ensure that the common control DLL is loaded (for listview) + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_LISTVIEW_CLASSES; + InitCommonControlsEx(&icex); + + InitServices(); + + PROTOCOLDESCRIPTOR pd = {0}; + pd.cbSize = sizeof(pd); + pd.szName = MODULE; + pd.type = PROTOTYPE_PROTOCOL; + CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd); + + // since we can call people when not registered... + SetContactStatus(ID_STATUS_ONLINE); + + InitOptions(); + + // hook modules loaded + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + return 0; +} + +extern "C" __declspec (dllexport) int __cdecl Unload(void) { + DeinitOptions(); + DeinitServices(); + DeinitMenu(); + DeinitIcons(); + DeinitIAXInterface(); + return 0; +} diff --git a/iax/docs/licence_iax.txt b/iax/docs/licence_iax.txt new file mode 100644 index 0000000..a23a323 --- /dev/null +++ b/iax/docs/licence_iax.txt @@ -0,0 +1,8 @@ +The IAX plugin for Miranda-IM is Copyright (c) 2006 Scott Ellis (mail@scottellis.com.au) + +http://www.scottellis.com.au + +It is released under the General Public Licence (GPL), available here: +http://www.gnu.org/copyleft/gpl.html + +This plugin uses IAXClient library, covered by the LGPL. \ No newline at end of file diff --git a/iax/iax.rc b/iax/iax.rc new file mode 100644 index 0000000..092d1b9 --- /dev/null +++ b/iax/iax.rc @@ -0,0 +1,229 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (Australia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT DIALOGEX 0, 0, 308, 203 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + RTEXT "Username:",IDC_STATIC,11,15,42,8 + RTEXT "Password:",IDC_STATIC,158,15,47,8 + RTEXT "Host:",IDC_STATIC,21,32,32,8 + EDITTEXT IDC_ED_UNAME,57,12,96,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_PW,212,12,78,12,ES_PASSWORD | ES_AUTOHSCROLL + EDITTEXT IDC_ED_HOST,57,29,96,12,ES_AUTOHSCROLL + GROUPBOX "Login",IDC_STATIC,7,1,293,60 + RTEXT "Name:",IDC_STATIC,11,79,42,8 + RTEXT "Number:",IDC_STATIC,158,79,47,8 + EDITTEXT IDC_ED_CIDNAME,57,76,96,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_CIDNUM,212,76,78,12,ES_AUTOHSCROLL + GROUPBOX "Caller ID",IDC_STATIC,7,64,293,34 + COMBOBOX IDC_CMB_DEVIN,68,112,147,77,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Devices",IDC_STATIC,7,100,293,49 + RTEXT "Input:",IDC_STATIC,20,116,39,8 + RTEXT "Output:",IDC_STATIC,20,133,39,8 + COMBOBOX IDC_CMB_DEVOUT,68,129,147,77,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + RTEXT "*Source port:",IDC_STATIC,158,32,47,8 + EDITTEXT IDC_ED_PORT,212,29,41,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + CTEXT "(*Changes will take effect after restart)",IDC_STATIC,75,47,158,8 + GROUPBOX "Call Window",IDC_STATIC,7,152,293,45 + CONTROL "",IDC_HK_DLG,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,57,169,80,14 + RTEXT "Hotkey:",IDC_STATIC,11,172,42,8 + CONTROL "Popup on incoming call",IDC_CHK_POPDIALIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,165,114,10 + CONTROL "Popup on outgoing call",IDC_CHK_POPDIALOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,157,178,114,10 + CONTROL "Mic boost",IDC_CHK_MICBOOST,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,226,120,68,10 +END + +IDD_DIAL DIALOGEX 0, 0, 195, 153 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Dial" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + COMBOBOX IDC_CMB_NUM,7,21,181,122,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "1",IDC_B1,49,77,19,14 + PUSHBUTTON "2",IDC_B2,72,77,19,14 + PUSHBUTTON "4",IDC_B4,49,93,19,14 + PUSHBUTTON "5",IDC_B5,72,93,19,14 + PUSHBUTTON "3",IDC_B3,94,77,19,14 + PUSHBUTTON "7",IDC_B7,49,109,19,14 + PUSHBUTTON "6",IDC_B6,94,93,19,14 + PUSHBUTTON "8",IDC_B8,72,109,19,14 + PUSHBUTTON "*",IDC_BSTAR,49,125,19,14 + PUSHBUTTON "9",IDC_B9,94,109,19,14 + PUSHBUTTON "0",IDC_B0,72,125,19,14 + PUSHBUTTON "#",IDC_BHASH,94,125,19,14 + DEFPUSHBUTTON "Call",IDC_BTN_CALL,132,77,50,14 + PUSHBUTTON "Hang Up",IDC_BTN_HANGUP,132,97,50,14 + PUSHBUTTON "Answer",IDC_BTN_ANSWER,132,118,50,14 + EDITTEXT IDC_ED_NAME,46,7,142,12,ES_AUTOHSCROLL | ES_READONLY + RTEXT "Name:",IDC_STATIC,11,9,27,8 + CONTROL "1",IDC_L1,"Button",BS_OWNERDRAW | WS_TABSTOP,11,78,19,14 + CONTROL "2",IDC_L2,"Button",BS_OWNERDRAW | WS_TABSTOP,11,98,19,14 + CONTROL "3",IDC_L3,"Button",BS_OWNERDRAW | WS_TABSTOP,11,119,19,14 + GROUPBOX "Line",IDC_STATIC,7,63,28,83 + GROUPBOX "Keypad",IDC_STATIC,40,63,80,83 + GROUPBOX "Function",IDC_STATIC,125,63,63,83 + CONTROL "",IDC_SLD_IN,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,0,41,98,12 + CONTROL "",IDC_SLD_OUT,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,96,41,97,12 + CONTROL "",IDC_PRG_IN,"msctls_progress32",WS_BORDER,7,54,86,6 + CONTROL "",IDC_PRG_OUT,"msctls_progress32",WS_BORDER,102,54,86,6 + LTEXT "Input",IDC_STATIC,16,35,44,8 + LTEXT "Output",IDC_STATIC,116,35,44,8 +END + +IDD_OPT_CODEC DIALOGEX 0, 0, 268, 153 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_CHK_ULAW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,37,10,10 + CONTROL "",IDC_CHK_ALAW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,49,10,10 + CONTROL "",IDC_CHK_GSM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,61,10,10 + CONTROL "",IDC_CHK_SPEEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,73,10,10 + CONTROL "",IDC_CHK_ILBC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,85,10,10 + CTEXT "Changes will take effect after restart",IDC_STATIC,48,117,171,8 + RTEXT "ULAW",IDC_STATIC,65,39,32,8 + RTEXT "ALAW",IDC_STATIC,65,51,32,8 + RTEXT "GSM",IDC_STATIC,65,63,32,8 + RTEXT "Speex",IDC_STATIC,65,75,32,8 + RTEXT "iLBC",IDC_STATIC,65,87,32,8 + CTEXT "Allowed",IDC_STATIC,122,18,35,8 + CTEXT "Preferred",IDC_STATIC,166,18,35,8 + GROUPBOX "",IDC_STATIC,7,7,254,139 + CONTROL "",IDC_CHK_ULAW_P,"Button",BS_AUTORADIOBUTTON,179,37,10,10 + CONTROL "",IDC_CHK_ALAW_P,"Button",BS_AUTORADIOBUTTON,179,49,10,10 + CONTROL "",IDC_CHK_GSM_P,"Button",BS_AUTORADIOBUTTON,179,61,10,10 + CONTROL "",IDC_CHK_SPEEX_P,"Button",BS_AUTORADIOBUTTON,179,73,10,10 + CONTROL "",IDC_CHK_ILBC_P,"Button",BS_AUTORADIOBUTTON,179,85,10,10 +END + +IDD_ADDCONTACT DIALOGEX 0, 0, 186, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "New IAX Contact" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,40,55,50,14 + PUSHBUTTON "Cancel",IDCANCEL,95,55,50,14 + RTEXT "Name:",IDC_STATIC,21,13,42,8 + RTEXT "Number:",IDC_STATIC,16,35,47,8 + EDITTEXT IDC_ED_NAME,73,11,96,12,ES_AUTOHSCROLL + EDITTEXT IDC_ED_NUM,73,33,96,12,ES_AUTOHSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 301 + TOPMARGIN, 1 + BOTTOMMARGIN, 197 + END + + IDD_DIAL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 188 + TOPMARGIN, 7 + BOTTOMMARGIN, 146 + END + + IDD_OPT_CODEC, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 261 + TOPMARGIN, 7 + BOTTOMMARGIN, 146 + END + + IDD_ADDCONTACT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 69 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_PROTO ICON "icon1.ico" +#endif // English (Australia) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/iax/iax_8.sln b/iax/iax_8.sln new file mode 100644 index 0000000..4bf639d --- /dev/null +++ b/iax/iax_8.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iax", "iax.vcproj", "{7C89CA7D-D98A-43E6-9772-385681506ABF}" + ProjectSection(ProjectDependencies) = postProject + {4AF56BD0-9FB7-435B-99F2-8582FEAC8137} = {4AF56BD0-9FB7-435B-99F2-8582FEAC8137} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iaxclient_lib", "iaxclient\lib\win\vs2005\iaxclient_lib.vcproj", "{4AF56BD0-9FB7-435B-99F2-8582FEAC8137}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7C89CA7D-D98A-43E6-9772-385681506ABF}.Debug|Win32.ActiveCfg = Debug|Win32 + {7C89CA7D-D98A-43E6-9772-385681506ABF}.Debug|Win32.Build.0 = Debug|Win32 + {7C89CA7D-D98A-43E6-9772-385681506ABF}.Release|Win32.ActiveCfg = Release|Win32 + {7C89CA7D-D98A-43E6-9772-385681506ABF}.Release|Win32.Build.0 = Release|Win32 + {4AF56BD0-9FB7-435B-99F2-8582FEAC8137}.Debug|Win32.ActiveCfg = Debug|Win32 + {4AF56BD0-9FB7-435B-99F2-8582FEAC8137}.Debug|Win32.Build.0 = Debug|Win32 + {4AF56BD0-9FB7-435B-99F2-8582FEAC8137}.Release|Win32.ActiveCfg = Release|Win32 + {4AF56BD0-9FB7-435B-99F2-8582FEAC8137}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/iax/iax_8.vcproj b/iax/iax_8.vcproj new file mode 100644 index 0000000..e7e39f0 --- /dev/null +++ b/iax/iax_8.vcproj @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iax/iax_interface.cpp b/iax/iax_interface.cpp new file mode 100644 index 0000000..8004ca0 --- /dev/null +++ b/iax/iax_interface.cpp @@ -0,0 +1,325 @@ +#include "common.h" +#include "iax_interface.h" +#include "options.h" +#include "services.h" +#include "utils.h" +#include "resource.h" +#include "dial_dlg.h" +#include "icons.h" + +#include +#include + +#define NUM_LINES 3 + +typedef struct { + HWND hwndPopup; + bool ring_thread; + int state; + char cid_name[256]; + char cid_num[256]; +} LineInfo; + +LineInfo line_info[NUM_LINES] = {0}; + +int reg_id = 0; +double silence_threshold = -99; +//double silence_threshold = 0; + +void SendDTMF(char c) { + iaxc_send_dtmf(c); +} + +void Call(char *number) { + char buff[512]; + mir_snprintf(buff, 512, "%s:%s@%s/%s", options.username, options.password, options.host, number); + iaxc_call(buff); +} + +void HangUp() { + iaxc_reject_call(); +} + +void SelectLine(int line) { + iaxc_select_call(line); +} + +void SetLineNo(int line) { + iaxc_select_call(line); +} + +int GetLineNo() { + return iaxc_selected_call(); +} + +int GetLineState(int line) { + return line_info[line].state; +} + +void AnswerCall(int callNo) { + WMPPause(); + iaxc_answer_call(callNo); +} + +char *GetLineCIDNum(int callNo) { + return line_info[callNo].cid_num; +} + +char *GetLineCIDName(int callNo) { + return line_info[callNo].cid_name; +} + +int text_event_callback(iaxc_ev_text text) { + switch(text.type) { + case IAXC_TEXT_TYPE_STATUS: + //ShowInfo(Translate("Status: %s"), Translate(text.message)); + break; + case IAXC_TEXT_TYPE_NOTICE: + ShowInfo(Translate("Notice: %s"), Translate(text.message)); + break; + case IAXC_TEXT_TYPE_ERROR: + ShowError(Translate(text.message)); + break; + case IAXC_TEXT_TYPE_FATALERROR: + ShowError(Translate("Fatal: %s"), Translate(text.message)); + break; + case IAXC_TEXT_TYPE_IAX: + ShowInfo(Translate("Text: %s"), text.message); + break; + } + return 0; +} + +LRESULT CALLBACK CallPopupWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { + switch( message ) { + case UM_INITPOPUP: + { + int callNo = CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,0); + line_info[callNo].hwndPopup = hWnd; + } + return 0; + case WM_COMMAND: + { + int callNo = CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,0); + iaxc_answer_call(callNo); + } + PUDeletePopUp( hWnd ); + return TRUE; + + case WM_CONTEXTMENU: + { + int callNo = CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,0); + iaxc_reject_call_number(callNo); + } + PUDeletePopUp( hWnd ); + return TRUE; + + case UM_FREEPLUGINDATA: + { + } + return TRUE; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +unsigned int CALLBACK RingThread(void *param) { + int callNo = (int)param; + while((GetLineState(callNo) & IAXC_CALL_STATE_RINGING) && !Miranda_Terminated()) { + if(GetLineState(callNo) & IAXC_CALL_STATE_OUTGOING) + SkinPlaySound("iax_ring_out"); + else + SkinPlaySound("iax_ring_in"); + Sleep(3000); + } + line_info[callNo].ring_thread = false; + return 0; +} + +void AddClistIcon(HANDLE hContact, int line_no) { + CLISTEVENT cli = {0}; + cli.cbSize = sizeof(CLISTEVENT); + cli.flags = CLEF_URGENT; + cli.hContact = hContact; + cli.hDbEvent = (HANDLE)line_no; + cli.hIcon = hIconRing; + cli.pszService = MODULE "/ClistIconClick"; + cli.pszTooltip = (line_info[line_no].state & IAXC_CALL_STATE_OUTGOING) ? Translate("Ringing (OUT)") : Translate("Ringing (IN)"); + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cli); +} + +int ClistIconClick(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + CLISTEVENT *cli = (CLISTEVENT *)lParam; + int line_no = (int)cli->hDbEvent; + + if(!(line_info[line_no].state & IAXC_CALL_STATE_RINGING)) + return 0; + /* + if(line_info[line_no].state & IAXC_CALL_STATE_OUTGOING) { + // ask if user wants to hang up or leave it ringing + } else { + // ask if user wants to answer call or reject call or leave it ringing + } + */ + + ShowDialDialog(true); + //AddClistIcon(hContact, line_no); + //CallServiceSync(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContact, 0); + return 0; +} + +int state_event_callback(iaxc_ev_call_state call){ + + //ShowInfo("Line %d, name = %s", call.callNo, call.remote_name); + + line_info[call.callNo].state = call.state; + if(call.remote_name) strncpy(line_info[call.callNo].cid_name, call.remote_name, 256); + else line_info[call.callNo].cid_name[0] = 0; + if(call.remote) strncpy(line_info[call.callNo].cid_num, call.remote, 256); + else line_info[call.callNo].cid_num[0] = 0; + + HANDLE hContact = FindContact(call.remote); + + RefreshLineInfo(); + + bool active = (call.state & IAXC_CALL_STATE_ACTIVE) != 0; + bool ringing = (call.state & IAXC_CALL_STATE_RINGING) != 0; + bool outgoing = (call.state & IAXC_CALL_STATE_OUTGOING) != 0; + + if(ringing) { + + if(!line_info[call.callNo].ring_thread) { + CloseHandle((HANDLE)_beginthreadex(0, 0, RingThread, (void *)call.callNo, 0, 0)); + line_info[call.callNo].ring_thread = true; + } + + if(!hContact) hContact = CreateContact(call.remote, call.remote, true); //call.remote_name); + DBWriteContactSettingByte(hContact, MODULE, "LineNo", call.callNo); + if(outgoing) { + DBWriteContactSettingWord(hContact, MODULE, "Status", ID_STATUS_NA); + if(options.pop_dial_out) ShowDialDialog(false); + } else { + DBWriteContactSettingWord(hContact, MODULE, "Status", ID_STATUS_FREECHAT); + if(options.pop_dial_in) ShowDialDialog(false); + } + + } else if(hContact) { + if(active) { + DBWriteContactSettingWord(hContact, MODULE, "Status", ID_STATUS_ONTHEPHONE); + DBWriteContactSettingDword(hContact, MODULE, "LastCall", (DWORD)time(0)); + DBWriteContactSettingByte(hContact, MODULE, "LineNo", call.callNo); + } else { + DBWriteContactSettingWord(hContact, MODULE, "Status", ID_STATUS_ONLINE); + DWORD current_time = (DWORD)time(0), last_call = DBGetContactSettingDword(hContact, MODULE, "LastCall", current_time); + if(current_time - last_call > 0) { + DBWriteContactSettingDword(hContact, MODULE, "LastCallDuration", current_time - last_call); + } + DBWriteContactSettingByte(hContact, MODULE, "LineNo", 0xff); + } + } + + + return 0; +} + +int registration_event_callback(iaxc_ev_registration reg) { + if(reg.reply == IAXC_REGISTRATION_REPLY_ACK) { + SetStatusAndACK(ID_STATUS_ONLINE); + if(reg.msgcount > 0) ShowInfo(Translate("You have %d messages."), reg.msgcount); + SetLineNo(0); + SetContactStatus(ID_STATUS_ONLINE); + } else if(reg.reply == IAXC_REGISTRATION_REPLY_REJ) { + if(reg_id) ShowError(Translate("Registration rejected")); + Disconnect(); + SetStatusAndACK(ID_STATUS_OFFLINE); + } else if(reg.reply == IAXC_REGISTRATION_REPLY_TIMEOUT) { + if(reg_id) ShowError(Translate("Registration timeout")); + Disconnect(); + SetStatusAndACK(ID_STATUS_OFFLINE); + } + return 0; +} + +int levels_callback(float input, float output) { + SetLevels(input, output); + return 0; +} + +int iaxc_callback(iaxc_event e) +{ + switch(e.type) { + case IAXC_EVENT_LEVELS: + return levels_callback(e.ev.levels.input, e.ev.levels.output); + case IAXC_EVENT_NETSTAT: + //return netstat_callback(e.ev.netstats); + return 0; + case IAXC_EVENT_TEXT: + return text_event_callback(e.ev.text); + case IAXC_EVENT_STATE: + return state_event_callback(e.ev.call); + case IAXC_EVENT_REGISTRATION: + return registration_event_callback(e.ev.reg); + default: + return 0; // not handled + } +} + + +void Connect() { + if(reg_id) Disconnect(); + + if(options.username && options.password && options.host) { + if(options.cid_name) + iaxc_set_callerid(options.cid_name, options.cid_number); + reg_id = iaxc_register(options.username, options.password, options.host); + SetStatusAndACK(ID_STATUS_CONNECTING); + } else + SetStatusAndACK(ID_STATUS_OFFLINE); +} + +void Disconnect() { + if(reg_id) { + iaxc_unregister(reg_id); + reg_id = 0; + Sleep(500); + } +} + +HANDLE hServiceIconClist; +bool InitIAXInterface() { + SkinAddNewSoundEx("iax_ring_in", Translate("IAX"), Translate("Ring (Inbound)")); + SkinAddNewSoundEx("iax_ring_out", Translate("IAX"), Translate("Ring (Outbound)")); + SkinAddNewSoundEx("iax_keypad", Translate("IAX"), Translate("Key Press")); + + hServiceIconClist = CreateServiceFunction(MODULE "/ClistIconClick", ClistIconClick); + + iaxc_set_preferred_source_udp_port(DBGetContactSettingDword(0, MODULE, "Port", 4569)); + if(iaxc_initialize(AUDIO_INTERNAL_PA, NUM_LINES)) return false; + + iaxc_set_formats(options.codecs_preferred, options.codecs_allowed); + + //iaxc_set_filters(IAXC_FILTER_CN); + + iaxc_set_speex_settings(1,-1,-1,0,8000,3); + + iaxc_set_silence_threshold(silence_threshold); + + iaxc_set_event_callback(iaxc_callback); + + iaxc_start_processing_thread(); + + return true; +} + +void DeinitIAXInterface() { + DestroyServiceFunction(hServiceIconClist); + + iaxc_dump_call(); + iaxc_millisleep(1000); + if (reg_id) iaxc_unregister(reg_id); + iaxc_stop_processing_thread(); + iaxc_shutdown(); +} + + diff --git a/iax/iax_interface.h b/iax/iax_interface.h new file mode 100644 index 0000000..e2a5f9d --- /dev/null +++ b/iax/iax_interface.h @@ -0,0 +1,26 @@ +#ifndef _IAX_INTERFACE_INC +#define _IAX_INTERFACE_INC + +#include "iaxclient/lib/iaxclient.h" + + +void SendDTMF(char c); +void Call(char *number); +void HangUp(); +void SelectLine(int line); +void AnswerCall(int callNo); +void SetLineNo(int line); +int GetLineNo(); + +int GetLineState(int line); + +char *GetLineCIDNum(int callNo); +char *GetLineCIDName(int callNo); + +void Connect(); +void Disconnect(); + +bool InitIAXInterface(); +void DeinitIAXInterface(); + +#endif \ No newline at end of file diff --git a/iax/iaxclient_patch.patch b/iax/iaxclient_patch.patch new file mode 100644 index 0000000..f746225 --- /dev/null +++ b/iax/iaxclient_patch.patch @@ -0,0 +1,597 @@ +Index: lib/iaxclient_lib.c +=================================================================== +--- lib/iaxclient_lib.c (revision 666) ++++ lib/iaxclient_lib.c (working copy) +@@ -386,6 +386,7 @@ + vsnprintf(buf, 1024, fmt, args); + va_end(args); + ++ printf("jb_errf!\n"); + iaxc_usermsg(IAXC_ERROR, buf); + } + +Index: lib/libiax2/src/iax.c +=================================================================== +--- lib/libiax2/src/iax.c (revision 666) ++++ lib/libiax2/src/iax.c (working copy) +@@ -839,7 +839,7 @@ + { + /* Send the frame raw */ + #ifdef DEBUG_SUPPORT +- if (ntohs(h->scallno) & IAX_FLAG_FULL) ++ if (ntohs(f->callno) & IAX_FLAG_FULL) + iax_showframe(f, NULL, 0, f->transfer ? + &(f->session->transfer) : + &(f->session->peeraddr), f->datalen - sizeof(struct ast_iax2_full_hdr)); +@@ -1995,7 +1995,8 @@ + /* Setup host connection */ + hp = gethostbyname(hostname); + if (!hp) { +- snprintf(iax_errstr, sizeof(iax_errstr), "Invalid hostname: %s", hostname); ++ IAXERROR "Invalid hostname: %s", hostname); ++ DEBU(G "Invalid hostname: %s", hostname); + return -1; + } + memcpy(&session->peeraddr.sin_addr, hp->h_addr, sizeof(session->peeraddr.sin_addr)); +Index: lib/Makefile +=================================================================== +--- lib/Makefile (revision 666) ++++ lib/Makefile (working copy) +@@ -382,14 +382,14 @@ + ar rs $(MSLIB) $(OBJS) + + +-#shared: CFLAGS := $(CFLAGS) $(DYNCFLAGS) ++shared: CFLAGS := $(CFLAGS) $(DYNCFLAGS) + #shared: clean libiaxclient.a +-#shared: libiaxclient.a +-#ifeq ($(OSTYPE),MACOSX) +-# $(CC) -single_module -dylib -dynamiclib -o $(DYNLIB) $(OBJS) $(DYNLDFLAGS) -framework CoreAudio -framework AudioToolbox -framework System -framework Carbon -framework AudioUnit portaudio/lib/libportaudio.a +-#else +-# $(CC) -shared -o $(DYNLIB) $(OBJS) $(DYNLDFLAGS) +-#endif ++shared: libiaxclient.a ++ifeq ($(OSTYPE),MACOSX) ++ $(CC) -single_module -dylib -dynamiclib -o $(DYNLIB) $(OBJS) $(DYNLDFLAGS) -framework CoreAudio -framework AudioToolbox -framework System -framework Carbon -framework AudioUnit portaudio/lib/libportaudio.a ++else ++ $(CC) -shared -o $(DYNLIB) $(OBJS) $(DYNLDFLAGS) ++endif + + + +Index: lib/win/vs2005/iaxclient_dll.vcproj +=================================================================== +--- lib/win/vs2005/iaxclient_dll.vcproj (revision 666) ++++ lib/win/vs2005/iaxclient_dll.vcproj (working copy) +@@ -46,7 +46,7 @@ + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_WINDLL;_USRDLL;BUILDING_DLL;PA_NO_DS;PA_NO_ASIO;SPEEX_PREPROCESS=1;NEWJB;LIBIAX;SPEEX_EC=1;inline=__inline;strncasecmp=strnicmp;vsnprintf=_vsnprintf" + MinimalRebuild="true" + BasicRuntimeChecks="3" +- RuntimeLibrary="3" ++ RuntimeLibrary="1" + RuntimeTypeInfo="false" + PrecompiledHeaderFile="" + AssemblerListingLocation="$(IntDir)/" +@@ -143,7 +143,7 @@ + Optimization="4" + AdditionalIncludeDirectories="..\..,..\..\gsm\inc,..\..\portaudio\include,..\..\portaudio\src\common,..\..\portaudio\pablio,..\..\portmixer\px_common,..\..\libspeex\include,..\..\libiax2\src,..\..\wince" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_WINDLL;_USRDLL;BUILDING_DLL;PA_NO_DS;PA_NO_ASIO;SPEEX_PREPROCESS=1;NEWJB;LIBIAX;SPEEX_EC=1;inline=__inline;strncasecmp=strnicmp;vsnprintf=_vsnprintf" +- RuntimeLibrary="2" ++ RuntimeLibrary="0" + PrecompiledHeaderFile="" + AssemblerListingLocation="$(IntDir)/" + ObjectFile="$(IntDir)/" +@@ -237,6 +237,10 @@ + > + + ++ ++ + +@@ -302,6 +306,10 @@ + > + + ++ ++ + +@@ -594,7 +602,7 @@ + Filter="cpp;h" + > + + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +Index: lib/win/vs2005/iaxclient_lib.vcproj +=================================================================== +--- lib/win/vs2005/iaxclient_lib.vcproj (revision 666) ++++ lib/win/vs2005/iaxclient_lib.vcproj (working copy) +@@ -43,10 +43,10 @@ + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..,..\..\gsm\inc,..\..\portaudio\include,..\..\portaudio\src\common,..\..\portaudio\pablio,..\..\portmixer\px_common,..\..\libspeex\include,..\..\libiax2\src,..\..\wince" +- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_LIB;PA_NO_DS;PA_NO_ASIO;SPEEX_PREPROCESS=1;NEWJB;LIBIAX;SPEEX_EC=1;inline=__inline;strncasecmp=strnicmp;vsnprintf=_vsnprintf" ++ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_LIB;PA_NO_DS;PA_NO_ASIO;SPEEX_PREPROCESS=1;NEWJB;LIBIAX;SPEEX_EC=1;inline=__inline;strncasecmp=strnicmp;vsnprintf=_vsnprintf;DEBUG_SUPPORT" + MinimalRebuild="true" + BasicRuntimeChecks="3" +- RuntimeLibrary="3" ++ RuntimeLibrary="1" + RuntimeTypeInfo="false" + PrecompiledHeaderFile="" + AssemblerListingLocation="$(IntDir)/" +@@ -57,7 +57,6 @@ + SuppressStartupBanner="true" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="3" +- CallingConvention="2" + CompileAs="1" + /> + + + + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +Index: lib/winfuncs.c +=================================================================== +--- lib/winfuncs.c (revision 666) ++++ lib/winfuncs.c (working copy) +@@ -85,7 +85,9 @@ + } + + int iaxc_prioboostend() { +- /* TODO */ ++ if ( !SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL) ) { ++ fprintf(stderr, "SetThreadPriority failed: %ld.\n", GetLastError()); ++ } + return 0; + } + diff --git a/iax/icon1.ico b/iax/icon1.ico new file mode 100644 index 0000000..927413d Binary files /dev/null and b/iax/icon1.ico differ diff --git a/iax/icons.cpp b/iax/icons.cpp new file mode 100644 index 0000000..dd7298e --- /dev/null +++ b/iax/icons.cpp @@ -0,0 +1,50 @@ +#include "common.h" +#include "icons.h" +#include "resource.h" + +HICON hIconProto, hIconRing; +HANDLE hIcoLibIconsChanged = 0; + +int ReloadIcons(WPARAM wParam, LPARAM lParam) { + hIconProto = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)MODULE "_proto"); + hIconRing = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)MODULE "_ring"); + + return 0; +} + +void InitIcons() { + if(ServiceExists(MS_SKIN2_ADDICON)) { + SKINICONDESC2 sid = {0}; + sid.cbSize = sizeof(SKINICONDESC2); + + sid.pszSection = MODULE; + +#define AddIcon(x,y,z) \ + sid.pszDescription = Translate(x); \ + sid.pszName = y; \ + sid.pszDefaultFile = MODULE ".dll"; \ + sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(z), IMAGE_ICON, 0, 0, 0); \ + CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); \ + sid.iDefaultIndex++; + + AddIcon("Protocol", MODULE "_proto", IDI_PROTO); + AddIcon("Ring", MODULE "_ring", IDI_PROTO); + +#undef AddIcon + + ReloadIcons(0, 0); + + hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, ReloadIcons); + } else { + hIconProto = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_PROTO), IMAGE_ICON, 0, 0, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS ); + hIconRing = hIconProto; + } + +} + +void DeinitIcons() { + if(hIcoLibIconsChanged) UnhookEvent(hIcoLibIconsChanged); + else { + DestroyIcon(hIconProto); + } +} diff --git a/iax/icons.h b/iax/icons.h new file mode 100644 index 0000000..854aae5 --- /dev/null +++ b/iax/icons.h @@ -0,0 +1,9 @@ +#ifndef _ICONS_INC +#define _ICONS_INC + +extern HICON hIconProto, hIconRing; + +void InitIcons(); +void DeinitIcons(); + +#endif diff --git a/iax/menu.cpp b/iax/menu.cpp new file mode 100644 index 0000000..99cc536 --- /dev/null +++ b/iax/menu.cpp @@ -0,0 +1,151 @@ +#include "common.h" +#include "menu.h" +#include "icons.h" +#include "iax_interface.h" +#include "resource.h" +#include "utils.h" +#include "services.h" +#include "dial_dlg.h" + +HANDLE hMenuAnswer, hMenuDial, hMenuCall, hMenuAddContact, hServiceAnswer, hServiceDial, hServiceCall, hServiceAddContact; + +void EnableMainMenuItem(bool enable, HANDLE hMenu) { + CLISTMENUITEM menu; + ZeroMemory(&menu,sizeof(menu)); + menu.cbSize=sizeof(menu); + + menu.flags = CMIM_FLAGS | (enable ? 0 : CMIF_GRAYED); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenu, (LPARAM)&menu); +} + +void SetAnswerEnable(bool enable) { + EnableMainMenuItem(enable, hMenuAnswer); +} + +void SetDialEnable(bool enable) { + EnableMainMenuItem(enable, hMenuDial); +} + +int AnswerCallService(WPARAM wParam, LPARAM lParam) { + AnswerCall(0); + return 0; +} + +int ShowDialWindowService(WPARAM wParam, LPARAM lParam) { + ShowDialDialog(true); + return 0; +} + +int CallContactService(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + + DBVARIANT dbv; + if(!DBGetContactSettingTString(hContact, MODULE, "Number", &dbv)) { + Call(dbv.pszVal); + DBFreeVariant(&dbv); + } + + return 0; +} + +static BOOL CALLBACK AddContactDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + SetFocus(GetDlgItem(hwndDlg, IDC_ED_NAME)); + return FALSE; + case WM_COMMAND: + if ( HIWORD( wParam ) == BN_CLICKED) { + switch(LOWORD(wParam)) { + case IDOK: + { + char name[256], number[256]; + if(GetDlgItemText(hwndDlg, IDC_ED_NAME, name, 256) && GetDlgItemText(hwndDlg, IDC_ED_NUM, number, 256)) + CreateContact(number, name, false); + else { + MessageBox(hwndDlg, Translate("You must enter a number and a name."), Translate("IAX Input Error"), MB_OK | MB_ICONWARNING); + return TRUE; + } + } + // drop through + case IDCANCEL: + SendMessage(hwndDlg, WM_CLOSE, 0, 0); + return TRUE; + } + } + break; + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + } + + return 0; +} +int AddContactService(WPARAM wParam, LPARAM lParam) { + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ADDCONTACT), 0, AddContactDialogProc, 0); + return 0; +} + +void InitMenu() { + InitDialDialog(); + hServiceAnswer = CreateServiceFunction(MODULE "/AnswerCall", AnswerCallService); + hServiceDial = CreateServiceFunction(MODULE "/DialNumber", ShowDialWindowService); + hServiceCall = CreateServiceFunction(MODULE "/CallContact", CallContactService); + hServiceAddContact = CreateServiceFunction(MODULE "/AddContact", AddContactService); + + CLISTMENUITEM menu; + ZeroMemory(&menu,sizeof(menu)); + menu.cbSize=sizeof(menu); + + // main menu + menu.flags = 0; + menu.popupPosition = 500099900; + menu.pszPopupName = Translate( MODULE ); + menu.cbSize = sizeof( menu ); + menu.position = 2000060000; + menu.hIcon = hIconProto; + menu.pszName = Translate( "Answer Call" ); + menu.pszService = MODULE "/AnswerCall"; + hMenuAnswer = (HANDLE)CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu ); + + menu.flags = 0; + menu.popupPosition = 500299901; + menu.pszPopupName = Translate( MODULE ); + menu.cbSize = sizeof( menu ); + menu.position = 2000060001; + menu.popupPosition = 0; + menu.hIcon = hIconProto; + menu.pszName = Translate( "Dial Number" ); + menu.pszService = MODULE "/DialNumber"; + hMenuDial = (HANDLE)CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu ); + + menu.flags = 0; + menu.popupPosition = 500299901; + menu.pszPopupName = Translate( MODULE ); + menu.cbSize = sizeof( menu ); + menu.position = 2000060001; + menu.popupPosition = 0; + menu.hIcon = hIconProto; + menu.pszName = Translate( "Add Contact" ); + menu.pszService = MODULE "/AddContact"; + hMenuAddContact = (HANDLE)CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu ); + + // contact menu + menu.flags = CMIF_NOTOFFLINE; + menu.popupPosition = 0; + menu.cbSize = sizeof( menu ); + menu.position = 0; + menu.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + menu.pszName = Translate( "Call" ); + menu.pszService = MODULE "/CallContact"; + menu.pszContactOwner = MODULE; + hMenuCall = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu ); +} + +void DeinitMenu() { + DeinitDialDialog(); + DestroyServiceFunction(hServiceAnswer); + DestroyServiceFunction(hServiceDial); + DestroyServiceFunction(hServiceCall); + DestroyServiceFunction(hServiceAddContact); +} diff --git a/iax/menu.h b/iax/menu.h new file mode 100644 index 0000000..5270edb --- /dev/null +++ b/iax/menu.h @@ -0,0 +1,10 @@ +#ifndef _MENU_INC +#define _MENU_INC + +void SetAnswerEnable(bool enable); +void SetDialEnable(bool enable); + +void InitMenu(); +void DeinitMenu(); + +#endif \ No newline at end of file diff --git a/iax/options.cpp b/iax/options.cpp new file mode 100644 index 0000000..8c9176b --- /dev/null +++ b/iax/options.cpp @@ -0,0 +1,306 @@ +#include "common.h" +#include "options.h" +#include "resource.h" +#include "icons.h" +#include "dial_dlg.h" +#include "iaxclient/lib/iaxclient.h" + +Options options = {0}; + +static BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + SetDlgItemText(hwndDlg, IDC_ED_UNAME, options.username); + SetDlgItemText(hwndDlg, IDC_ED_PW, options.password); + SetDlgItemText(hwndDlg, IDC_ED_HOST, options.host); + SetDlgItemText(hwndDlg, IDC_ED_CIDNAME, options.cid_name); + SetDlgItemText(hwndDlg, IDC_ED_CIDNUM, options.cid_number); + SetDlgItemInt(hwndDlg, IDC_ED_PORT, options.port, FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_POPDIALIN, options.pop_dial_in ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_POPDIALOUT, options.pop_dial_out ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_MICBOOST, options.mic_boost ? TRUE : FALSE); + + { + iaxc_audio_device *dev; + int nDevs, in, out, ring, ind; + iaxc_audio_devices_get(&dev, &nDevs, &in, &out, &ring); + for(int i = 0; i < nDevs; i++) { + if(dev[i].capabilities & IAXC_AD_INPUT) { + ind = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVIN, CB_ADDSTRING, 0, (LPARAM)dev[i].name); + SendDlgItemMessage(hwndDlg, IDC_CMB_DEVIN, CB_SETITEMDATA, ind, i); + if(i == in) SendDlgItemMessage(hwndDlg, IDC_CMB_DEVIN, CB_SETCURSEL, ind, 0); + } + if(dev[i].capabilities & IAXC_AD_OUTPUT) { + ind = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVOUT, CB_ADDSTRING, 0, (LPARAM)dev[i].name); + SendDlgItemMessage(hwndDlg, IDC_CMB_DEVOUT, CB_SETITEMDATA, ind, i); + if(i == out) SendDlgItemMessage(hwndDlg, IDC_CMB_DEVOUT, CB_SETCURSEL, ind, 0); + } + /* + if(dev[i].capabilities & IAXC_AD_RING) { + ind = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVRING, CB_ADDSTRING, 0, (LPARAM)dev[i].name); + SendDlgItemMessage(hwndDlg, IDC_CMB_DEVRING, CB_SETITEMDATA, ind, i); + if(i == ring) SendDlgItemMessage(hwndDlg, IDC_CMB_DEVRING, CB_SETCURSEL, ind, 0); + } + */ + } + } + SendDlgItemMessage(hwndDlg, IDC_HK_DLG, HKM_SETHOTKEY, options.dlgHotkey, 0); + + return FALSE; + case WM_COMMAND: + if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + if ( HIWORD( wParam ) == CBN_SELCHANGE) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + if ( HIWORD( wParam ) == BN_CLICKED) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + char buffer[512]; + + GetDlgItemText(hwndDlg, IDC_ED_UNAME, buffer, 512); + if(options.username) free(options.username); + options.username = strdup(buffer); + + GetDlgItemText(hwndDlg, IDC_ED_PW, buffer, 512); + if(options.password) free(options.password); + options.password = strdup(buffer); + + GetDlgItemText(hwndDlg, IDC_ED_HOST, buffer, 512); + if(options.host) free(options.host); + options.host = strdup(buffer); + + GetDlgItemText(hwndDlg, IDC_ED_CIDNAME, buffer, 512); + if(options.cid_name) free(options.cid_name); + options.cid_name = strdup(buffer); + + GetDlgItemText(hwndDlg, IDC_ED_CIDNUM, buffer, 512); + if(options.cid_number) free(options.cid_number); + options.cid_number = strdup(buffer); + + DBWriteContactSettingTString(0, MODULE, "Host", options.host); + DBWriteContactSettingTString(0, MODULE, "Username", options.username); + DBWriteContactSettingTString(0, MODULE, "Password", options.password); + DBWriteContactSettingTString(0, MODULE, "CIDName", options.cid_name); + DBWriteContactSettingTString(0, MODULE, "CIDNumber", options.cid_number); + + iaxc_audio_device *dev; + int nDevs, in, out, ring, ind; + iaxc_audio_devices_get(&dev, &nDevs, &in, &out, &ring); + + ind = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVIN, CB_GETCURSEL, 0, 0); + in = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVIN, CB_GETITEMDATA, ind, 0); + ind = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVOUT, CB_GETCURSEL, 0, 0); + out = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVOUT, CB_GETITEMDATA, ind, 0); + //ind = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVRING, CB_GETCURSEL, 0, 0); + //ring = SendDlgItemMessage(hwndDlg, IDC_CMB_DEVRING, CB_GETITEMDATA, ind, 0); + + DBWriteContactSettingTString(0, MODULE, "DeviceIn", dev[in].name); + DBWriteContactSettingTString(0, MODULE, "DeviceOut", dev[out].name); + //DBWriteContactSettingTString(0, MODULE, "DeviceRing", dev[ring].name); + + BOOL trans; + int port = GetDlgItemInt(hwndDlg, IDC_ED_PORT, &trans, FALSE); + if(trans) options.port = port; + DBWriteContactSettingDword(0, MODULE, "Port", options.port); + + iaxc_audio_devices_set(in, out, ring); + + options.dlgHotkey = (WORD)SendDlgItemMessage(hwndDlg, IDC_HK_DLG, HKM_GETHOTKEY, 0, 0); + DBWriteContactSettingWord(0, MODULE, "DlgHotkey", options.dlgHotkey); + ResetDlgHotkey(); + + options.pop_dial_in = IsDlgButtonChecked(hwndDlg, IDC_CHK_POPDIALIN) ? true : false; + options.pop_dial_out = IsDlgButtonChecked(hwndDlg, IDC_CHK_POPDIALOUT) ? true : false; + DBWriteContactSettingByte(0, MODULE, "PopupDial", options.pop_dial_in ? 1 : 0); + DBWriteContactSettingByte(0, MODULE, "PopupDialOut", options.pop_dial_out ? 1 : 0); + + options.mic_boost = IsDlgButtonChecked(hwndDlg, IDC_CHK_MICBOOST) ? true : false; + DBWriteContactSettingByte(0, MODULE, "MicBoost", options.mic_boost ? 1 : 0); + iaxc_mic_boost_set(options.mic_boost ? 1 : 0); + } + + return TRUE; + } + break; + } + + return 0; +} + +static BOOL CALLBACK DlgProcOptsCodec(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + + CheckDlgButton(hwndDlg, IDC_CHK_ULAW_P, options.codecs_preferred & IAXC_FORMAT_ULAW ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_ALAW_P, options.codecs_preferred & IAXC_FORMAT_ALAW ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_GSM_P, options.codecs_preferred & IAXC_FORMAT_GSM ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_SPEEX_P, options.codecs_preferred & IAXC_FORMAT_SPEEX ? TRUE : FALSE); + + CheckDlgButton(hwndDlg, IDC_CHK_ULAW, options.codecs_allowed & IAXC_FORMAT_ULAW ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_ALAW, options.codecs_allowed & IAXC_FORMAT_ALAW ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_GSM, options.codecs_allowed & IAXC_FORMAT_GSM ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_SPEEX, options.codecs_allowed & IAXC_FORMAT_SPEEX ? TRUE : FALSE); + +#ifdef CODEC_ILBC + CheckDlgButton(hwndDlg, IDC_CHK_ILBC_P, options.codecs_preferred & IAXC_FORMAT_ILBC ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_CHK_ILBC, options.codecs_allowed & IAXC_FORMAT_ILBC ? TRUE : FALSE); +#else + { + HWND hw = GetDlgItem(hwndDlg, IDC_CHK_ILBC); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_CHK_ILBC_P); + EnableWindow(hw, FALSE); + } +#endif + return FALSE; + case WM_COMMAND: + if ( HIWORD( wParam ) == BN_CLICKED) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { + options.codecs_preferred = options.codecs_allowed = 0; + + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ULAW_P)) options.codecs_preferred |= IAXC_FORMAT_ULAW; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ALAW_P)) options.codecs_preferred |= IAXC_FORMAT_ALAW; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_GSM_P)) options.codecs_preferred |= IAXC_FORMAT_GSM; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_SPEEX_P)) options.codecs_preferred |= IAXC_FORMAT_SPEEX; + + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ULAW)) options.codecs_allowed |= IAXC_FORMAT_ULAW; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ALAW)) options.codecs_allowed |= IAXC_FORMAT_ALAW; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_GSM)) options.codecs_allowed |= IAXC_FORMAT_GSM; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_SPEEX)) options.codecs_allowed |= IAXC_FORMAT_SPEEX; + +#ifdef CODEC_ILBC + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ILBC_P)) options.codecs_preferred |= IAXC_FORMAT_ILBC; + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ILBC)) options.codecs_allowed |= IAXC_FORMAT_ILBC; +#endif + + DBWriteContactSettingDword(0, MODULE, "CodecsPreferred", options.codecs_preferred); + DBWriteContactSettingDword(0, MODULE, "CodecsAllowed", options.codecs_allowed); + + iaxc_set_formats(options.codecs_preferred, options.codecs_allowed); + } + return TRUE; + } + break; + } + + return 0; +} + +int OptInit(WPARAM wParam, LPARAM lParam) { + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.flags = ODPF_BOLDGROUPS; + //odp.flags |= ODPF_UNICODE; + odp.position = -790000000; + odp.hInstance = hInst; + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT); + odp.pszTitle = Translate("IAX"); + odp.pszGroup = Translate("Network"); + odp.nIDBottomSimpleControl = 0; + odp.pfnDlgProc = DlgProcOpts; + odp.pszTab = Translate("Configuration"); + CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp ); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CODEC); + odp.pszTitle = Translate("IAX"); + odp.pszGroup = Translate("Network"); + odp.nIDBottomSimpleControl = 0; + odp.pfnDlgProc = DlgProcOptsCodec; + odp.pszTab = Translate("Codecs"); + CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp ); + + return 0; +} + +void PreInitOptions() { + options.codecs_preferred = DBGetContactSettingDword(0, MODULE, "CodecsPreferred", IAXC_FORMAT_SPEEX); + options.codecs_allowed = DBGetContactSettingDword(0, MODULE, "CodecsAllowed", IAXC_FORMAT_ILBC | IAXC_FORMAT_ULAW | IAXC_FORMAT_ALAW | IAXC_FORMAT_GSM | IAXC_FORMAT_SPEEX); +} + +HANDLE hEventOptInit; +void InitOptions() { + hEventOptInit = HookEvent(ME_OPT_INITIALISE, OptInit); + DBVARIANT dbv; + if(!DBGetContactSettingTString(0, MODULE, "Host", &dbv)) { + options.host = strdup(dbv.pszVal); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(0, MODULE, "Username", &dbv)) { + options.username = strdup(dbv.pszVal); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(0, MODULE, "Password", &dbv)) { + options.password = strdup(dbv.pszVal); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(0, MODULE, "CIDName", &dbv)) { + options.cid_name = strdup(dbv.pszVal); + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(0, MODULE, "CIDNumber", &dbv)) { + options.cid_number = strdup(dbv.pszVal); + DBFreeVariant(&dbv); + } + + iaxc_audio_device *dev; + int nDevs, in, out, ring; + iaxc_audio_devices_get(&dev, &nDevs, &in, &out, &ring); + if(!DBGetContactSettingTString(0, MODULE, "DeviceIn", &dbv)) { + for(int i = 0; i < nDevs; i++) { + if((dev[i].capabilities & IAXC_AD_INPUT) && strcmp(dbv.pszVal, dev[i].name) == 0) in = i; + } + DBFreeVariant(&dbv); + } + if(!DBGetContactSettingTString(0, MODULE, "DeviceOut", &dbv)) { + for(int i = 0; i < nDevs; i++) { + if((dev[i].capabilities & IAXC_AD_OUTPUT) && strcmp(dbv.pszVal, dev[i].name) == 0) out = i; + } + DBFreeVariant(&dbv); + } + /* + if(!DBGetContactSettingTString(0, MODULE, "DeviceRing", &dbv)) { + for(int i = 0; i < nDevs; i++) { + if((dev[i].capabilities & IAXC_AD_RING) && strcmp(dbv.pszVal, dev[i].name) == 0) ring = i; + } + DBFreeVariant(&dbv); + } + */ + + options.port = DBGetContactSettingDword(0, MODULE, "Port", 4569); + iaxc_audio_devices_set(in, out, ring); + + options.dlgHotkey = DBGetContactSettingWord(0, MODULE, "DlgHotkey", 0); + options.pop_dial_in = (DBGetContactSettingByte(0, MODULE, "PopupDial", 1) == 1); + options.pop_dial_out = (DBGetContactSettingByte(0, MODULE, "PopupDialOut", 0) == 1); + + options.mic_boost = (DBGetContactSettingByte(0, MODULE, "MicBoost", 0) == 1); + iaxc_mic_boost_set(options.mic_boost ? 1 : 0); + //options.mic_boost = (iaxc_mic_boost_get() != 0); +} + +void DeinitOptions() { + UnhookEvent(hEventOptInit); + if(options.host) free(options.host); + if(options.password) free(options.password); + if(options.username) free(options.username); + if(options.cid_name) free(options.cid_name); + if(options.cid_number) free(options.cid_number); +} diff --git a/iax/options.h b/iax/options.h new file mode 100644 index 0000000..8631344 --- /dev/null +++ b/iax/options.h @@ -0,0 +1,21 @@ +#ifndef _OPTIONS_INC +#define _OPTIONS_INC + +typedef struct { + char *username, *password, *host; + int port; + bool auto_answer; + char *cid_name, *cid_number; + WORD dlgHotkey; + bool pop_dial_in, pop_dial_out; + DWORD codecs_preferred, codecs_allowed; + bool mic_boost; +} Options; + +extern Options options; + +void PreInitOptions(); +void InitOptions(); +void DeinitOptions(); + +#endif diff --git a/iax/private.h b/iax/private.h new file mode 100644 index 0000000..2a1a603 --- /dev/null +++ b/iax/private.h @@ -0,0 +1,24 @@ +#ifndef _PRIVATE_H +#define _PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_MAJOR 0 +#define VER_MINOR 0 +#define VER_RELEASE 2 +#define VER_BUILD 0 + +#define __STRINGIZE(x) #x +#define VER_STRING __STRINGIZE( VER_MAJOR.VER_MINOR.VER_RELEASE.VER_BUILD ) + +#define DESC_STRING "IAX telephony client" +#define COMPANY_NAME "" +#define FILE_VERSION VER_STRING +#define FILE_DESCRIPTION DESC_STRING +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "© Scott Ellis 2005" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "iax.dll" +#define PRODUCT_NAME DESC_STRING +#define PRODUCT_VERSION VER_STRING + +#endif /*OTR_PRIVATE_H*/ diff --git a/iax/private.rc b/iax/private.rc new file mode 100644 index 0000000..47bca39 --- /dev/null +++ b/iax/private.rc @@ -0,0 +1,35 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "private.h" +#include "afxres.h" +// +// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS... +// +1 VERSIONINFO +FILEVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD +PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD +FILETYPE VFT_DLL +{ + BLOCK "StringFileInfo" + { + BLOCK "0C0904E4" + { + VALUE "CompanyName", COMPANY_NAME + VALUE "FileVersion", FILE_VERSION + VALUE "FileDescription", FILE_DESCRIPTION + VALUE "InternalName", INTERNAL_NAME + VALUE "LegalCopyright", LEGAL_COPYRIGHT + VALUE "LegalTrademarks", LEGAL_TRADEMARKS + VALUE "OriginalFilename", ORIGINAL_FILENAME + VALUE "ProductName", PRODUCT_NAME + VALUE "ProductVersion", PRODUCT_VERSION + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0C09, 1252 + } +} + + diff --git a/iax/resource.h b/iax/resource.h new file mode 100644 index 0000000..42fb630 --- /dev/null +++ b/iax/resource.h @@ -0,0 +1,70 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by iax.rc +// +#define IDD_OPT 103 +#define IDI_PROTO 104 +#define IDD_DIAL 105 +#define IDD_OPT_CODEC 106 +#define IDD_ADDCONTACT 107 +#define IDC_ED_UNAME 1004 +#define IDC_ED_PW 1005 +#define IDC_ED_HOST 1006 +#define IDC_ED_CIDNAME 1007 +#define IDC_ED_CIDNUM 1008 +#define IDC_ED_PORT 1009 +#define IDC_B0 1010 +#define IDC_B1 1011 +#define IDC_B2 1012 +#define IDC_B3 1013 +#define IDC_B4 1014 +#define IDC_B5 1015 +#define IDC_B6 1016 +#define IDC_B7 1017 +#define IDC_B8 1018 +#define IDC_B9 1019 +#define IDC_BSTAR 1020 +#define IDC_BHASH 1021 +#define IDC_CMB_NUM 1022 +#define IDC_L1 1023 +#define IDC_BTN_CALL 1025 +#define IDC_CMB_DEVIN 1026 +#define IDC_BTN_HANGUP 1026 +#define IDC_CMB_DEVOUT 1027 +#define IDC_L2 1027 +#define IDC_HK_DLG 1028 +#define IDC_L3 1028 +#define IDC_BTN_ANSWER 1029 +#define IDC_ED_NAME 1030 +#define IDC_CHK_POPDIAL 1031 +#define IDC_CHK_POPDIALIN 1031 +#define IDC_CHK_POPDIALOUT 1032 +#define IDC_SLD_IN 1033 +#define IDC_CHK_POPDIALIN2 1033 +#define IDC_CHK_MICBOOST 1033 +#define IDC_SLD_OUT 1034 +#define IDC_PRG_IN 1035 +#define IDC_PRG_OUT 1036 +#define IDC_CHK_ULAW_P 1036 +#define IDC_CHK_ULAW 1037 +#define IDC_CHK_ALAW 1038 +#define IDC_ST_OUT 1038 +#define IDC_ED_NUM 1038 +#define IDC_CHK_GSM 1039 +#define IDC_CHK_SPEEX 1040 +#define IDC_CHK_ILBC 1041 +#define IDC_CHK_ALAW_P 1042 +#define IDC_CHK_GSM_P 1043 +#define IDC_CHK_SPEEX_P 1044 +#define IDC_CHK_ILBC_P 1045 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1039 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/iax/resource.rc b/iax/resource.rc new file mode 100644 index 0000000..3080141 --- /dev/null +++ b/iax/resource.rc @@ -0,0 +1,2 @@ +#include "iax.rc" +#include "private.rc" diff --git a/iax/services.cpp b/iax/services.cpp new file mode 100644 index 0000000..7cf8986 --- /dev/null +++ b/iax/services.cpp @@ -0,0 +1,292 @@ +#include "common.h" +#include "services.h" +#include "resource.h" +#include "iax_interface.h" + +#define NUM_SERVICES 6 +HANDLE hServices[NUM_SERVICES]; + +int current_status = ID_STATUS_OFFLINE; + +HANDLE FindContact(char *num) { + char *proto; + DBVARIANT dbv; + HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ), ret = 0; + while ( hContact != NULL ) + { + proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 ); + if ( proto && !strcmp( MODULE, proto)) { + if(!DBGetContactSetting(hContact, MODULE, "Number", &dbv)) { + if(strcmp(num, dbv.pszVal) == 0) { + DBFreeVariant(&dbv); + return hContact; + } + DBFreeVariant(&dbv); + } + } + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } + + return 0; +} + +int ClistDblClick(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + char *proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 ); + if ( proto && !strcmp( MODULE, proto)) { + // if contact has active line + BYTE line_no = DBGetContactSettingByte(hContact, MODULE, "LineNo", 0xff); + if(line_no != 0xff) { + + // if ringing + if(GetLineState(line_no) & IAXC_CALL_STATE_RINGING) { + SelectLine(line_no); // calling this could change result of GetLineState call above + // if outgoing, hang up + if(GetLineState(line_no) & IAXC_CALL_STATE_OUTGOING) { + HangUp(); + } else { + // if incoming, answer + AnswerCall(line_no); + } + } else { + SelectLine(line_no); + // else + // hang up + HangUp(); + } + } else { + // else + // call number + DBVARIANT dbv; + if(!DBGetContactSettingTString(hContact, MODULE, "Number", &dbv)) { + Call(dbv.pszVal); + DBFreeVariant(&dbv); + } + } + } + + return 0; +} + +HANDLE CreateContact(char *num, char *name, bool temp) { + HANDLE hContact = FindContact(num); + if(!hContact) { + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + DBWriteContactSettingTString(hContact, MODULE, "Number", num); + CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)MODULE); + DBWriteContactSettingTString(hContact, MODULE, "Nick", name); + if(temp) DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + DBWriteContactSettingWord(hContact, MODULE, "Status", ID_STATUS_ONLINE); + CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE); + } else { + if(name && name[0]) DBWriteContactSettingTString(hContact, MODULE, "Nick", name); + if(DBGetContactSettingByte(hContact, "CList", "Hidden", 0)) + DBWriteContactSettingByte(hContact, "CList", "Hidden", 0); + } + return hContact; +} + +void SetContactStatus(int status) { + char *proto; + HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + while ( hContact != NULL ) + { + proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 ); + if ( proto && !strcmp( MODULE, proto)) { + if(!DBGetContactSettingByte(hContact, MODULE, "ChatRoom", 0)) { + DBWriteContactSettingWord( hContact, MODULE, "Status", status); + if(status == ID_STATUS_OFFLINE) { + DBWriteContactSettingDword(hContact, MODULE, "IdleTS", 0); + DBDeleteContactSetting(hContact, MODULE, "LineNo"); + } + } + } + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } +} + + +// protocol related services +int GetCaps(WPARAM wParam,LPARAM lParam) +{ + int ret = 0; + switch (wParam) { + case PFLAGNUM_1: + ret = 0; + break; + case PFLAGNUM_2: + ret = PF2_ONLINE | PF2_FREECHAT | PF2_LONGAWAY | PF2_ONTHEPHONE; + break; + case PFLAGNUM_3: + break; + case PFLAGNUM_4: + ret = 0; + break; + case PFLAGNUM_5: + // states contacts can have but we can't + ret = + PF2_FREECHAT // incomming call + | PF2_LONGAWAY // outgoing call + | PF2_ONTHEPHONE; // active call; + break; + case PFLAG_UNIQUEIDTEXT: + ret = (int) Translate("Ph#"); + break; + case PFLAG_MAXLENOFMESSAGE: + ret = 0; + break; + case PFLAG_UNIQUEIDSETTING: + ret = (int) "Number"; + break; + } + return ret; +} + +/** Copy the name of the protocole into lParam +* @param wParam : max size of the name +* @param lParam : reference to a char *, which will hold the name +*/ +int GetName(WPARAM wParam,LPARAM lParam) +{ + char *name = (char *)Translate(MODULE); + if(strncpy((char *)lParam,name,wParam)==NULL) + return 1; + ((char *)lParam)[wParam-1]='\0'; + return 0; +} + +/** Loads the icon corresponding to the status +* Called by the CList when the status changes. +* @param wParam : one of the following values : \n + PLI_PROTOCOL | PLI_ONLINE | PLI_OFFLINE +* @return an \c HICON in which the icon has been loaded. +*/ +int LoadIcon(WPARAM wParam,LPARAM lParam) +{ + + UINT id; + switch (wParam & 0xFFFF) + { + case PLI_PROTOCOL: + id = IDI_PROTO; + break; + case PLI_ONLINE: + id = IDI_PROTO; + break; + case PLI_OFFLINE: + id = IDI_PROTO; + break; + default: + return (int) (HICON) NULL; + } + + return (int) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, + GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON), + GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0); + return 0; +} + + +/** Changes the status and notifies everybody +* @param wParam : The new mode +* @param lParam : Allways set to 0. +*/ + +void SetStatusAndACK(int new_status) { + int prev_status = current_status; + current_status = new_status; + + ProtoBroadcastAck(MODULE,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS, (HANDLE)prev_status, current_status); +} + +int SetStatusService(WPARAM wParam,LPARAM lParam) +{ + int new_status = (int)wParam; + + if(new_status == current_status) return 0; + + if(current_status == ID_STATUS_OFFLINE && new_status != ID_STATUS_OFFLINE) { + Connect(); + } else { + if(new_status == ID_STATUS_OFFLINE && current_status != ID_STATUS_OFFLINE) { + Disconnect(); + //SetContactStatus(ID_STATUS_OFFLINE); + } + + SetStatusAndACK(new_status); + } + + return 0; +} + +void SetStatus(int new_status) { + SetStatusService((WPARAM)new_status, 0); +} + +/** Returns the current status +*/ +int GetStatus(WPARAM wParam,LPARAM lParam) +{ + return current_status; +} + +typedef struct tag_TFakeAckParams +{ + HANDLE hEvent; + HANDLE hContact; + LPARAM lParam; +} TFakeAckParams; + +static DWORD CALLBACK sttFakeAckInfoSuccess( LPVOID param ) +{ + TFakeAckParams *tParam = ( TFakeAckParams* )param; + WaitForSingleObject( tParam->hEvent, INFINITE ); + + Sleep( 100 ); + ProtoBroadcastAck(MODULE, tParam->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, ( HANDLE )1, 0 ); + + CloseHandle( tParam->hEvent ); + free(tParam); + return 0; +} + +int GetInfo(WPARAM wParam, LPARAM lParam) { + CCSDATA *ccs = (CCSDATA *) lParam; + DWORD dwThreadId; + HANDLE hEvent; + TFakeAckParams *tfap; + + hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + + tfap = (TFakeAckParams *)malloc(sizeof(TFakeAckParams)); + tfap->hContact = ccs->hContact; + tfap->hEvent = hEvent; + + CloseHandle( CreateThread( NULL, 0, sttFakeAckInfoSuccess, tfap, 0, &dwThreadId )); + SetEvent( hEvent ); + + return 0; +} + + +HANDLE hEventClistDblClick; + +void InitServices() { + int i = 0; + // protocol + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETCAPS, (MIRANDASERVICE)GetCaps); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETNAME, (MIRANDASERVICE)GetName); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_SETSTATUS, (MIRANDASERVICE)SetStatusService); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETSTATUS, (MIRANDASERVICE)GetStatus); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_LOADICON, (MIRANDASERVICE)LoadIcon); + hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_GETINFO, (MIRANDASERVICE)GetInfo); + + hEventClistDblClick = HookEvent(ME_CLIST_DOUBLECLICKED, ClistDblClick); +} + +void DeinitServices() { + UnhookEvent(hEventClistDblClick); + + for(int i = 0; i < NUM_SERVICES; i++) + if(hServices[i]) DestroyServiceFunction(hServices[i]); +} \ No newline at end of file diff --git a/iax/services.h b/iax/services.h new file mode 100644 index 0000000..24e0a32 --- /dev/null +++ b/iax/services.h @@ -0,0 +1,14 @@ +#ifndef _SERVICES_INC +#define _SERVICES_INC + +void SetStatusAndACK(int new_status); +void SetContactStatus(int status); + +HANDLE FindContact(char *num); +HANDLE CreateContact(char *num, char *name, bool temp); + +void InitServices(); +void DeinitServices(); + + +#endif diff --git a/iax/utils.cpp b/iax/utils.cpp new file mode 100644 index 0000000..f34ddf8 --- /dev/null +++ b/iax/utils.cpp @@ -0,0 +1,126 @@ +#include "common.h" +#include "utils.h" + +LRESULT CALLBACK NullWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { + switch( message ) { + case UM_INITPOPUP: + { + } + return 0; + case WM_COMMAND: + PUDeletePopUp( hWnd ); + return TRUE; + + case WM_CONTEXTMENU: + PUDeletePopUp( hWnd ); + return TRUE; + + case UM_FREEPLUGINDATA: + { + } + return TRUE; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + + +void ShowError(char *fmt, ...) { + va_list args; + char buff[MAX_SECONDLINE]; + va_start(args, fmt); + _vsnprintf(buff, MAX_SECONDLINE - 1, fmt, args); + va_end(args); + buff[MAX_SECONDLINE - 1] = 0; + + if(ServiceExists(MS_POPUP_ADDPOPUPEX)) { + POPUPDATAEX pd = {0}; + pd.colorBack = RGB(0xff, 0x00, 0x00); + pd.colorText = RGB(0xff, 0xff, 0xff); + pd.lchIcon = LoadIcon(0, IDI_ERROR); + strncpy(pd.lptzContactName, Translate(MODULE " Error"), MAX_CONTACTNAME); + strncpy(pd.lptzText, buff, MAX_SECONDLINE); + pd.iSeconds = -1; + pd.PluginWindowProc = NullWindowProc; + PUAddPopUpEx(&pd); + } else { + MIRANDASYSTRAYNOTIFY stn = {0}; + stn.cbSize = sizeof(stn); + stn.dwInfoFlags = NIIF_ERROR; // NIIF_INFO, NIIF_WARNING, NIIF_ERROR + stn.szInfo = buff; + stn.szInfoTitle = Translate(MODULE " Error"); + stn.szProto = MODULE; + stn.uTimeout = 10; + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&stn); + } +} + +void ShowWarning(char *fmt, ...) { + va_list args; + char buff[MAX_SECONDLINE]; + va_start(args, fmt); + _vsnprintf(buff, MAX_SECONDLINE - 1, fmt, args); + va_end(args); + buff[MAX_SECONDLINE - 1] = 0; + + if(ServiceExists(MS_POPUP_ADDPOPUPEX)) { + POPUPDATAEX pd = {0}; + pd.colorBack = RGB(0xff, 0xff, 0x00); + pd.colorText = 0; + pd.lchIcon = LoadIcon(0, IDI_WARNING); + strncpy(pd.lptzContactName, Translate(MODULE " Warning"), MAX_CONTACTNAME); + strncpy(pd.lptzText, buff, MAX_SECONDLINE); + pd.iSeconds = -1; + pd.PluginWindowProc = NullWindowProc; + PUAddPopUpEx(&pd); + } else { + MIRANDASYSTRAYNOTIFY stn = {0}; + stn.cbSize = sizeof(stn); + stn.dwInfoFlags = NIIF_WARNING; // NIIF_INFO, NIIF_WARNING, NIIF_ERROR + stn.szInfo = buff; + stn.szInfoTitle = Translate(MODULE" Warning"); + stn.szProto = MODULE; + stn.uTimeout = 10; + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&stn); + } +} + +void ShowInfo(char *fmt, ...) { + va_list args; + char buff[MAX_SECONDLINE]; + va_start(args, fmt); + _vsnprintf(buff, MAX_SECONDLINE - 1, fmt, args); + va_end(args); + buff[MAX_SECONDLINE - 1] = 0; + + if(ServiceExists(MS_POPUP_ADDPOPUPEX)) { + POPUPDATAEX pd = {0}; + pd.colorBack = RGB(0xff, 0xff, 0xff); + pd.colorText = 0; + pd.lchIcon = LoadIcon(0, IDI_INFORMATION); + strncpy(pd.lptzContactName, Translate(MODULE " Information"), MAX_CONTACTNAME); + strncpy(pd.lptzText, buff, MAX_SECONDLINE); + pd.iSeconds = 10; + pd.PluginWindowProc = NullWindowProc; + PUAddPopUpEx(&pd); + } else { + MIRANDASYSTRAYNOTIFY stn = {0}; + stn.cbSize = sizeof(stn); + stn.dwInfoFlags = NIIF_INFO; // NIIF_INFO, NIIF_WARNING, NIIF_ERROR + stn.szInfo = buff; + stn.szInfoTitle = Translate(MODULE " Information"); + stn.szProto = MODULE; + stn.uTimeout = 10; + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&stn); + } +} + +#define WMP_PAUSE 0x8028 //32808 +#define WMP_NEXT 0x497B //18811 + +void WMPPause() { + HWND hWnd = FindWindow(0, "Windows Media Player"); + if(hWnd) + PostMessage(hWnd, WM_COMMAND, WMP_PAUSE, 0); +} + diff --git a/iax/utils.h b/iax/utils.h new file mode 100644 index 0000000..01483a5 --- /dev/null +++ b/iax/utils.h @@ -0,0 +1,10 @@ +#ifndef _UTILS_INC +#define _UTILS_INC + +void ShowError(char *fmt, ...); +void ShowWarning(char *fmt, ...); +void ShowInfo(char *fmt, ...); + +void WMPPause(); + +#endif \ No newline at end of file -- cgit v1.2.3