diff options
Diffstat (limited to 'Plugins/voiceservice')
50 files changed, 8252 insertions, 0 deletions
diff --git a/Plugins/voiceservice/Docs/langpack_voiceservice.txt b/Plugins/voiceservice/Docs/langpack_voiceservice.txt new file mode 100644 index 0000000..7d3a59c --- /dev/null +++ b/Plugins/voiceservice/Docs/langpack_voiceservice.txt @@ -0,0 +1,74 @@ +; Voice Service
+; Author: Pescuma
+
+[Voice Calls]
+
+; Dialog
+[New Voice Call]
+[%s wants to start a voice call with you. What you want to do?]
+[Answer]
+[Drop]
+[From now on, repeat this action for this contact]
+
+; Options
+[Background]
+
+[Popups]
+[Enable popups]
+[ Colours ]
+[Background colour]
+[Text colour]
+[Use Windows colours]
+[Use default colours]
+[ Delay ]
+[From popup plugin]
+[Custom]
+[Permanent]
+[ Actions ]
+[On right click:]
+[On left click:]
+[Do nothing]
+[Close popup]
+[Preview]
+
+[Auto actions]
+[ Automatic Actions ]
+[Auto accept this contact calls]
+[Auto drop this contacts calls]
+
+[ Frame ]
+[Auto-size frame]
+
+; Test popup
+[Test Contact]
+[Test description]
+
+; Status
+[Talking]
+[Calling]
+[Ended]
+[On Hold]
+[Ringing]
+
+; Actions
+[Voice Call]
+[Answer Voice Call]
+[Hold Voice Call]
+[Drop Voice Call]
+
+; Icons
+[Main]
+
+; Popups
+[Calling %s]
+[Ringing call from %s]
+[Voice call ended]
+[Call from %s started]
+[Voice call started]
+[Call from %s is on hold]
+[Voice call on hold]
+
+; Frame popup menu
+[Answer call]
+[Drop call]
+[Hold call]
diff --git a/Plugins/voiceservice/Docs/voiceservice_changelog.txt b/Plugins/voiceservice/Docs/voiceservice_changelog.txt new file mode 100644 index 0000000..861627a --- /dev/null +++ b/Plugins/voiceservice/Docs/voiceservice_changelog.txt @@ -0,0 +1,35 @@ +Voice Service
+
+Changelog:
+
+. 0.1.0.0
+ + Allow selection of input/output devices
+ + Dialpad
+ + USe history events
+ + Internal improviments and fixes
+ * Changed API (old plugins using it will no longer work)
+
+. 0.0.0.8
+ + Auto-size frame
+ * Fix for background color of list control
+
+. 0.0.0.7
+ + Added dialog on tray icon doubleclick
+ + Handle more than one notification per status
+
+. 0.0.0.6
+ + Added sound support
+
+. 0.0.0.5
+ + Added services for call a contact
+ + Added initial metacontact support
+
+. 0.0.0.4
+ + Added support for miranda 0.8
+ * Fixed some bugs
+
+. 0.0.0.2
+ + Added background color for frame
+
+. 0.0.0.1
+ + Initial version
\ No newline at end of file diff --git a/Plugins/voiceservice/Docs/voiceservice_readme.txt b/Plugins/voiceservice/Docs/voiceservice_readme.txt new file mode 100644 index 0000000..ec4b913 --- /dev/null +++ b/Plugins/voiceservice/Docs/voiceservice_readme.txt @@ -0,0 +1,18 @@ +Voice Service plugin
+--------------------
+
+CAUTION: THIS IS AN ALPHA STAGE PLUGIN. IT CAN DO VERY BAD THINGS. USE AT YOUR OWN RISK.
+
+This is a service to provide a common user interface for voice calls to protocols/plugins that support it.
+
+For it to work, protocols/plugins need to support it. By now, only a mod of MirandaComm2 and a mod of JGmail does that (to check it out, look at its thread in miranda forum).
+
+Many thanks to Angeli-Ka for creating the icons.
+
+To report bugs/make suggestions, go to the forum thread: http://forums.miranda-im.org/showthread.php?p=114862
+
+This plugin needs Miranda 0.9 to work.
+
+Todo:
+- Add meSpeak support
+- Handle more than one way to call a contact
\ No newline at end of file diff --git a/Plugins/voiceservice/Docs/voiceservice_version.txt b/Plugins/voiceservice/Docs/voiceservice_version.txt new file mode 100644 index 0000000..3a48c76 --- /dev/null +++ b/Plugins/voiceservice/Docs/voiceservice_version.txt @@ -0,0 +1 @@ +Voice Service 0.1.0.0
\ No newline at end of file diff --git a/Plugins/voiceservice/ZIP/doit.bat b/Plugins/voiceservice/ZIP/doit.bat new file mode 100644 index 0000000..e26ff60 --- /dev/null +++ b/Plugins/voiceservice/ZIP/doit.bat @@ -0,0 +1,82 @@ +@echo off
+
+rem Batch file to build and upload files
+rem
+rem TODO: Integration with FL
+
+set name=voiceservice
+
+rem To upload, this var must be set here or in other batch
+rem set ftp=ftp://<user>:<password>@<ftp>/<path>
+
+echo Building %name% ...
+
+msdev ..\%name%.dsp /MAKE "%name% - Win32 Release" /REBUILD
+msdev ..\%name%.dsp /MAKE "%name% - Win32 Unicode Release" /REBUILD
+
+echo Generating files for %name% ...
+
+del *.zip
+del *.dll
+copy ..\..\..\bin\release\Plugins\%name%.dll
+copy ..\..\..\bin\release\Plugins\%name%W.dll
+copy ..\Docs\%name%_changelog.txt
+copy ..\Docs\%name%_version.txt
+copy ..\Docs\%name%_readme.txt
+mkdir Docs
+cd Docs
+del /Q *.*
+copy ..\..\Docs\%name%_readme.txt
+copy ..\..\Docs\langpack_%name%.txt
+rem copy ..\..\Docs\helppack_%name%.txt
+copy ..\..\m_%name%.h
+copy ..\..\m_voice.h
+cd ..
+mkdir src
+cd src
+del /Q *.*
+copy ..\..\*.h
+copy ..\..\*.cpp
+copy ..\..\*.
+copy ..\..\*.rc
+copy ..\..\*.dsp
+copy ..\..\*.dsw
+mkdir Docs
+cd Docs
+del /Q *.*
+copy ..\..\..\Docs\*.*
+cd ..
+cd ..
+
+"C:\Program Files\Filzip\Filzip.exe" -a -rp %name%.zip %name%.dll Docs
+"C:\Program Files\Filzip\Filzip.exe" -a -rp %name%W.zip %name%W.dll Docs
+"C:\Program Files\Filzip\Filzip.exe" -a -rp %name%_src.zip src\*.*
+
+del *.dll
+cd Docs
+del /Q *.*
+cd ..
+rmdir Docs
+cd src
+del /Q *.*
+cd Docs
+del /Q *.*
+cd ..
+rmdir Docs
+cd ..
+rmdir src
+
+if "%ftp%"=="" GOTO END
+
+echo Going to upload files...
+pause
+
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%.zip %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%W.zip %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%_changelog.txt %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%_version.txt %ftp% -overwrite -close
+"C:\Program Files\FileZilla\FileZilla.exe" -u .\%name%_readme.txt %ftp% -overwrite -close
+
+:END
+
+echo Done.
diff --git a/Plugins/voiceservice/codepages.cpp b/Plugins/voiceservice/codepages.cpp new file mode 100644 index 0000000..6441cda --- /dev/null +++ b/Plugins/voiceservice/codepages.cpp @@ -0,0 +1,307 @@ +
+struct {
+ char *name;
+ UINT codepage;
+} codepages[] = {
+ { "ISO8859-1", 28591 },
+ { "UTF-7", CP_UTF7 },
+ { "UTF-8", CP_UTF8 },
+ { "UTF7", CP_UTF7 },
+ { "UTF8", CP_UTF8 },
+ { "ISO8859-2", 28592 },
+ { "ISO8859-3", 28593 },
+ { "ISO8859-4", 28594 },
+ { "ISO8859-5", 28595 },
+ { "ISO8859-6", 28596 },
+ { "ISO8859-7", 28597 },
+ { "ISO8859-8", 28598 },
+ { "ISO8859-9", 28599 },
+ { "ASMO-708", 708 },
+ { "DOS-720", 720 },
+ { "iso-8859-6", 28596 },
+ { "arabic", 28596 },
+ { "csISOLatinArabic", 28596 },
+ { "ECMA-114", 28596 },
+ { "ISO_8859-6", 28596 },
+ { "ISO_8859-6:1987", 28596 },
+ { "iso-ir-127", 28596 },
+ { "x-mac-arabic", 10004 },
+ { "windows-1256", 1256 },
+ { "cp1256", 1256 },
+ { "ibm775", 775 },
+ { "CP500", 775 },
+ { "iso-8859-4", 28594 },
+ { "csISOLatin4", 28594 },
+ { "ISO_8859-4", 28594 },
+ { "ISO_8859-4:1988", 28594 },
+ { "iso-ir-110", 28594 },
+ { "l4", 28594 },
+ { "latin4", 28594 },
+ { "windows-1257", 1257 },
+ { "ibm852", 852 },
+ { "cp852", 852 },
+ { "iso-8859-2", 28592 },
+ { "csISOLatin2", 28592 },
+ { "iso_8859-2", 28592 },
+ { "iso_8859-2:1987", 28592 },
+ { "iso-ir-101", 28592 },
+ { "l2", 28592 },
+ { "latin2", 28592 },
+ { "x-mac-ce", 10029 },
+ { "windows-1250", 1250 },
+ { "x-cp1250", 1250 },
+ { "EUC-CN", 51936 },
+ { "x-euc-cn", 51936 },
+ { "gb2312", 936 },
+ { "chinese", 936 },
+ { "CN-GB", 936 },
+ { "csGB2312", 936 },
+ { "csGB231280", 936 },
+ { "csISO58GB231280", 936 },
+ { "GB_2312-80", 936 },
+ { "GB231280", 936 },
+ { "GB2312-80", 936 },
+ { "GBK", 936 },
+ { "iso-ir-58", 936 },
+ { "hz-gb-2312", 52936 },
+ { "x-mac-chinesesimp", 10008 },
+ { "big5", 950 },
+ { "cn-big5", 950 },
+ { "csbig5", 950 },
+ { "x-x-big5", 950 },
+ { "x-Chinese-CNS", 20000 },
+ { "x-Chinese-Eten", 20002 },
+ { "x-mac-chinesetrad", 10002 },
+ { "cp866", 866 },
+ { "ibm866", 866 },
+ { "iso-8859-5", 28595 },
+ { "csISOLatin5", 28595 },
+ { "csISOLatinCyrillic", 28595 },
+ { "cyrillic", 28595 },
+ { "ISO_8859-5", 28595 },
+ { "ISO_8859-5:1988", 28595 },
+ { "iso-ir-144", 28595 },
+ { "l5", 28595 },
+ { "KOI8-R", 20866 },
+ { "csKOI8R", 20866 },
+ { "koi", 20866 },
+ { "koi8", 20866 },
+ { "koi8r", 20866 },
+ { "KOI8-U", 21866 },
+ { "koi8-ru", 21866 },
+ { "x-mac-cyrillic", 10007 },
+ { "windows-1251", 1251 },
+ { "Win1251", 1251 },
+ { "x-cp1251", 1251 },
+ { "x-Europa", 29001 },
+ { "x-IA5-German", 20106 },
+ { "ibm737", 737 },
+ { "iso-8859-7", 28597 },
+ { "csISOLatinGreek", 28597 },
+ { "ECMA-118", 28597 },
+ { "ELOT_928", 28597 },
+ { "greek", 28597 },
+ { "greek8", 28597 },
+ { "ISO_8859-7", 28597 },
+ { "ISO_8859-7:1987", 28597 },
+ { "iso-ir-126", 28597 },
+ { "x-mac-greek", 10006 },
+ { "windows-1253", 1253 },
+ { "ibm869", 869 },
+ { "DOS-862", 862 },
+ { "iso-8859-8-i", 38598 },
+ { "logical", 38598 },
+ { "iso-8859-8", 28598 },
+ { "csISOLatinHebrew", 28598 },
+ { "hebrew", 28598 },
+ { "ISO_8859-8", 28598 },
+ { "ISO_8859-8:1988", 28598 },
+ { "ISO-8859-8", 28598 },
+ { "iso-ir-138", 28598 },
+ { "visual", 28598 },
+ { "x-mac-hebrew", 10005 },
+ { "windows-1255", 1255 },
+ { "ISO_8859-8-I", 1255 },
+ { "ISO-8859-8", 1255 },
+ { "x-EBCDIC-Arabic", 20420 },
+ { "x-EBCDIC-CyrillicRussian", 20880 },
+ { "x-EBCDIC-CyrillicSerbianBulgarian", 21025 },
+ { "x-EBCDIC-DenmarkNorway", 20277 },
+ { "x-ebcdic-denmarknorway-euro", 1142 },
+ { "x-EBCDIC-FinlandSweden", 20278 },
+ { "x-ebcdic-finlandsweden-euro", 1143 },
+ { "X-EBCDIC-France", 1143 },
+ { "X-EBCDIC-France", 1143 },
+ { "x-ebcdic-france-euro", 1147 },
+ { "x-EBCDIC-Germany", 20273 },
+ { "x-ebcdic-germany-euro", 1141 },
+ { "x-EBCDIC-GreekModern", 875 },
+ { "x-EBCDIC-Greek", 20423 },
+ { "x-EBCDIC-Hebrew", 20424 },
+ { "x-EBCDIC-Icelandic", 20871 },
+ { "x-ebcdic-icelandic-euro", 1149 },
+ { "x-ebcdic-international-euro", 1148 },
+ { "x-EBCDIC-Italy", 20280 },
+ { "x-ebcdic-italy-euro", 1144 },
+ { "x-EBCDIC-JapaneseAndKana", 50930 },
+ { "x-EBCDIC-JapaneseAndJapaneseLatin", 50939 },
+ { "x-EBCDIC-JapaneseAndUSCanada", 50931 },
+ { "x-EBCDIC-JapaneseKatakana", 20290 },
+ { "x-EBCDIC-KoreanAndKoreanExtended", 50933 },
+ { "x-EBCDIC-KoreanExtended", 20833 },
+ { "CP870", 870 },
+ { "x-EBCDIC-SimplifiedChinese", 50935 },
+ { "X-EBCDIC-Spain", 20284 },
+ { "x-ebcdic-spain-euro", 1145 },
+ { "x-EBCDIC-Thai", 20838 },
+ { "x-EBCDIC-TraditionalChinese", 50937 },
+ { "CP1026", 1026 },
+ { "x-EBCDIC-Turkish", 20905 },
+ { "x-EBCDIC-UK", 20285 },
+ { "x-ebcdic-uk-euro", 1146 },
+ { "ebcdic-cp-us", 37 },
+ { "x-ebcdic-cp-us-euro", 1140 },
+ { "ibm861", 861 },
+ { "x-mac-icelandic", 10079 },
+ { "x-iscii-as", 57006 },
+ { "x-iscii-be", 57003 },
+ { "x-iscii-de", 57002 },
+ { "x-iscii-gu", 57010 },
+ { "x-iscii-ka", 57008 },
+ { "x-iscii-ma", 57009 },
+ { "x-iscii-or", 57007 },
+ { "x-iscii-pa", 57011 },
+ { "x-iscii-ta", 57004 },
+ { "x-iscii-te", 57005 },
+ { "euc-jp", 51932 },
+ { "csEUCPkdFmtJapanese", 51932 },
+ { "Extended_UNIX_Code_Packed_Format_for_Japanese", 51932 },
+ { "x-euc", 51932 },
+ { "x-euc-jp", 51932 },
+ { "iso-2022-jp", 50220 },
+ { "iso-2022-jp", 50222 },
+ { "_iso-2022-jp$SIO", 50222 },
+ { "csISO2022JP", 50221 },
+ { "_iso-2022-jp", 50221 },
+ { "x-mac-japanese", 10001 },
+ { "shift_jis", 932 },
+ { "csShiftJIS", 932 },
+ { "csWindows31J", 932 },
+ { "ms_Kanji", 932 },
+ { "shift-jis", 932 },
+ { "x-ms-cp932", 932 },
+ { "x-sjis", 932 },
+ { "ks_c_5601-1987", 949 },
+ { "csKSC56011987", 949 },
+ { "euc-kr", 949 },
+ { "iso-ir-149", 949 },
+ { "korean", 949 },
+ { "ks_c_5601", 949 },
+ { "ks_c_5601_1987", 949 },
+ { "ks_c_5601-1989", 949 },
+ { "KSC_5601", 949 },
+ { "KSC5601", 949 },
+ { "euc-kr", 51949 },
+ { "csEUCKR", 51949 },
+ { "iso-2022-kr", 50225 },
+ { "csISO2022KR", 50225 },
+ { "Johab", 1361 },
+ { "x-mac-korean", 10003 },
+ { "iso-8859-3", 28593 },
+ { "csISO", 28593 },
+ { "Latin3", 28593 },
+ { "ISO_8859-3", 28593 },
+ { "ISO_8859-3:1988", 28593 },
+ { "iso-ir-109", 28593 },
+ { "l3", 28593 },
+ { "latin3", 28593 },
+ { "iso-8859-15", 28605 },
+ { "csISO", 28605 },
+ { "Latin9", 28605 },
+ { "ISO_8859-15", 28605 },
+ { "l9", 28605 },
+ { "latin9", 28605 },
+ { "x-IA5-Norwegian", 20108 },
+ { "IBM437", 437 },
+ { "437", 437 },
+ { "cp437", 437 },
+ { "csPC8", 437 },
+ { "CodePage437", 437 },
+ { "x-IA5-Swedish", 20107 },
+ { "windows-874", 874 },
+ { "DOS-874", 874 },
+ { "iso-8859-11", 874 },
+ { "TIS-620", 874 },
+ { "ibm857", 857 },
+ { "iso-8859-9", 28599 },
+ { "csISO", 28599 },
+ { "Latin5", 28599 },
+ { "ISO_8859-9", 28599 },
+ { "ISO_8859-9:1989", 28599 },
+ { "iso-ir-148", 28599 },
+ { "l5", 28599 },
+ { "latin5", 28599 },
+ { "x-mac-turkish", 10081 },
+ { "windows-1254", 1254 },
+ { "ISO_8859-9", 1254 },
+ { "ISO_8859-9:1989", 1254 },
+ { "iso-8859-9", 1254 },
+ { "iso-ir-148", 1254 },
+ { "latin5", 1254 },
+ { "unicode", 1200 },
+ { "utf-16", 1200 },
+ { "unicodeFFFE", 1201 },
+ { "utf-7", 65000 },
+ { "csUnicode11UTF7", 65000 },
+ { "unicode-1-1-utf-7", 65000 },
+ { "x-unicode-2-0-utf-7", 65000 },
+ { "utf-8", 65001 },
+ { "unicode-1-1-utf-8", 65001 },
+ { "unicode-2-0-utf-8", 65001 },
+ { "x-unicode-2-0-utf-8", 65001 },
+ { "us-ascii", 20127 },
+ { "ANSI_X3.4-1968", 20127 },
+ { "ANSI_X3.4-1986", 20127 },
+ { "ascii", 20127 },
+ { "cp367", 20127 },
+ { "csASCII", 20127 },
+ { "IBM367", 20127 },
+ { "ISO_646.irv:1991", 20127 },
+ { "ISO646-US", 20127 },
+ { "iso-ir-6us", 20127 },
+ { "windows-1258", 1258 },
+ { "ibm850", 850 },
+ { "x-IA5", 20105 },
+ { "iso-8859-1", 28591 },
+ { "cp819", 28591 },
+ { "csISO", 28591 },
+ { "Latin1", 28591 },
+ { "ibm819", 28591 },
+ { "iso_8859-1", 28591 },
+ { "iso_8859-1:1987", 28591 },
+ { "iso-ir-100", 28591 },
+ { "l1", 28591 },
+ { "latin1", 28591 },
+ { "macintosh", 10000 },
+ { "Windows-1252", 1252 },
+ { "ANSI_X3.4-1968", 1252 },
+ { "ANSI_X3.4-1986", 1252 },
+ { "ascii", 1252 },
+ { "cp367", 1252 },
+ { "cp819", 1252 },
+ { "csASCII", 1252 },
+ { "IBM367", 1252 },
+ { "ibm819", 1252 },
+ { "ISO_646.irv:1991", 1252 },
+ { "iso_8859-1", 1252 },
+ { "iso_8859-1:1987", 1252 },
+ { "ISO646-US", 1252 },
+ { "iso-ir-100", 1252 },
+ { "iso-ir-6", 1252 },
+ { "latin1", 1252 },
+ { "us", 1252 },
+ { "us-ascii", 1252 },
+ { "x-ansi", 1252 },
+ { "microsoft-cp1251", 1251 }
+};
+
diff --git a/Plugins/voiceservice/commons.h b/Plugins/voiceservice/commons.h new file mode 100644 index 0000000..ffdb622 --- /dev/null +++ b/Plugins/voiceservice/commons.h @@ -0,0 +1,337 @@ +/*
+Copyright (C) 2006 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>
+#include <time.h>
+#include <commctrl.h>
+
+
+// Disable "...truncated to '255' characters in the debug information" warnings
+#pragma warning(disable: 4786)
+
+#include <vector>
+using namespace std;
+
+
+
+// Miranda headers
+#define MIRANDA_VER 0x0800
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_contacts.h>
+#include <m_langpack.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_utils.h>
+#include <m_button.h>
+#include <m_updater.h>
+#include <m_popup.h>
+#include <m_cluiframes.h>
+#include <m_icolib.h>
+#include <m_metacontacts.h>
+#include <m_fontservice.h>
+#include <m_skin.h>
+#include <m_historyevents.h>
+#include <portaudio.h>
+
+#include "../utils/mir_memory.h"
+#include "../utils/mir_icons.h"
+#include "../utils/mir_options.h"
+#include "../utils/mir_dbutils.h"
+#include "../utils/utf8_helpers.h"
+
+#include "m_voice.h"
+#include "m_voiceservice.h"
+
+#include "resource.h"
+#include "options.h"
+#include "frame.h"
+#include "popup.h"
+
+
+#define MODULE_NAME "VoiceService"
+
+
+// Global Variables
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+
+#define ACTION_CALL 0
+#define ACTION_ANSWER 1
+#define ACTION_HOLD 2
+#define ACTION_DROP 3
+
+#define NUM_STATES 6
+#define NUM_FONTS NUM_STATES
+
+#define AUTO_NOTHING 0
+#define AUTO_ACCEPT 1
+#define AUTO_DROP 2
+
+extern HFONT fonts[NUM_FONTS];
+extern COLORREF font_colors[NUM_FONTS];
+extern int font_max_height;
+extern COLORREF bkg_color;
+extern HBRUSH bk_brush;
+
+
+
+
+class VoiceProvider
+{
+public:
+ TCHAR description[256];
+ char name[256];
+ char icon[256];
+ int flags;
+ bool is_protocol;
+
+ VoiceProvider(const char *name, const TCHAR *description, int flags, const char *icon);
+ ~VoiceProvider();
+
+ bool CanCall(const TCHAR *number);
+ bool CanCall(HANDLE hContact, BOOL now = TRUE);
+ void Call(HANDLE hContact, const TCHAR *number);
+
+ bool CanHold();
+
+ bool CanSendDTMF();
+
+ HICON GetIcon();
+ void ReleaseIcon(HICON hIcon);
+
+private:
+ bool canHold;
+ HANDLE state_hook;
+};
+
+
+class VoiceCall
+{
+public:
+ VoiceProvider *module;
+ char *id; // Protocol especific ID for this call
+ HANDLE hContact;
+ TCHAR name[256];
+ TCHAR number[256];
+ TCHAR displayName[256];
+ int state;
+ DWORD end_time;
+ bool incoming;
+ bool secure;
+
+ VoiceCall(VoiceProvider *module, const char *id);
+ ~VoiceCall();
+
+ void AppendCallerID(HANDLE hContact, const TCHAR *name, const TCHAR *number);
+
+ void SetState(int state);
+
+ void Drop();
+ void Answer();
+ void Hold();
+
+ bool CanDrop();
+ bool CanAnswer();
+ bool CanHold();
+
+ bool CanSendDTMF();
+ void SendDTMF(TCHAR c);
+
+ bool IsFinished();
+
+ void Notify(bool history = true, bool popup = true, bool sound = true, bool clist = true);
+ void SetNewCallHWND(HWND hwnd);
+
+private:
+ HWND hwnd;
+ bool clistBlinking;
+
+ void RemoveNotifications();
+ void CreateDisplayName();
+
+};
+
+
+extern OBJLIST<VoiceProvider> modules;
+extern OBJLIST<VoiceCall> calls;
+
+void Answer(VoiceCall *call);
+bool CanCall(HANDLE hContact, BOOL now = TRUE);
+bool CanCall(const TCHAR *number);
+bool CanCallNumber();
+VoiceCall * GetTalkingCall();
+bool IsFinalState(int state);
+
+
+// See if a protocol service exists
+__inline static int ProtoServiceExists(const char *szModule,const char *szService)
+{
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, MAX_REGS(str), "%s%s", szModule, szService);
+ return ServiceExists(str);
+}
+
+
+static TCHAR *lstrtrim(TCHAR *str)
+{
+ int len = lstrlen(str);
+
+ int i;
+ for(i = len - 1; i >= 0 && (str[i] == ' ' || str[i] == '\t'); --i) ;
+ if (i < len - 1)
+ {
+ ++i;
+ str[i] = _T('\0');
+ len = i;
+ }
+
+ for(i = 0; i < len && (str[i] == ' ' || str[i] == '\t'); ++i) ;
+ if (i > 0)
+ memmove(str, &str[i], (len - i + 1) * sizeof(TCHAR));
+
+ return str;
+}
+
+
+static BOOL IsEmptyA(const char *str)
+{
+ return str == NULL || str[0] == 0;
+}
+
+static BOOL IsEmptyW(const WCHAR *str)
+{
+ return str == NULL || str[0] == 0;
+}
+
+#ifdef UNICODE
+# define IsEmpty IsEmptyW
+#else
+# define IsEmpty IsEmptyA
+#endif
+
+
+
+#define ICON_SIZE 16
+
+#define TIME_TO_SHOW_ENDED_CALL 5000 // ms
+
+
+#define MS_VOICESERVICE_CLIST_DBLCLK "VoiceService/CList/RingingDblClk"
+
+#define MS_VOICESERVICE_CM_CALL "VoiceService/ContactMenu/Call"
+#define MS_VOICESERVICE_CM_ANSWER "VoiceService/ContactMenu/Answer"
+#define MS_VOICESERVICE_CM_HOLD "VoiceService/ContactMenu/Hold"
+#define MS_VOICESERVICE_CM_DROP "VoiceService/ContactMenu/Drop"
+
+
+
+static struct {
+ char *name;
+ char *description;
+} sounds[] = {
+ { "voice_started", "Started talking"},
+ { "voice_ringing", "Ringing"},
+ { "voice_calling", "Calling a contact"},
+ { "voice_holded", "Put a call on Hold"},
+ { "voice_ended", "End of call"},
+ { "voice_busy", "Busy signal"},
+ { "voice_dialpad", "Dialpad press"},
+};
+
+static TCHAR *stateTexts[] = {
+ _T("Call from %s has started"),
+ _T("Call from %s is ringing"),
+ _T("Calling %s"),
+ _T("Call from %s is on hold"),
+ _T("Call from %s has ended"),
+ _T("%s is busy"),
+};
+
+static TCHAR *popupTitles[] = {
+ _T("Voice call started"),
+ _T("Voice call ringing"),
+ _T("Voice call"),
+ _T("Voice call on hold"),
+ _T("Voice call ended"),
+ _T("Voice call busy"),
+};
+
+static TCHAR *stateNames[] = {
+ _T("Talking"),
+ _T("Ringing"),
+ _T("Calling"),
+ _T("On Hold"),
+ _T("Ended"),
+ _T("Busy"),
+};
+
+static TCHAR *actionNames[] = {
+ _T("Make Voice Call"),
+ _T("Answer Voice Call"),
+ _T("Hold Voice Call"),
+ _T("Drop Voice Call"),
+};
+
+static char *stateIcons[] = {
+ "vc_talking",
+ "vc_ringing",
+ "vc_calling",
+ "vc_on_hold",
+ "vc_ended",
+ "vc_busy"
+};
+
+static char *actionIcons[] = {
+ "vca_call",
+ "vca_answer" ,
+ "vca_hold",
+ "vca_drop",
+ "vc_main",
+ "vc_dialpad"
+};
+
+static char *mainIcons[] = {
+ "vc_main",
+ "vc_dialpad",
+ "vc_secure"
+};
+
+
+
+
+#endif // __COMMONS_H__
diff --git a/Plugins/voiceservice/concepts/concepts.txt b/Plugins/voiceservice/concepts/concepts.txt new file mode 100644 index 0000000..6a4c497 --- /dev/null +++ b/Plugins/voiceservice/concepts/concepts.txt @@ -0,0 +1,42 @@ +General ideas about the plugin:
+
+- A voice provider can call contacts from varios protocols (even if it is a protocol). A voice provider is a plugin that registered itself with MS_VOICESERVICE_REGISTER. The voice provider can be an account or just a usual plugin. It is an account if the name send in MS_VOICESERVICE_REGISTER == and account name. Even if it is an account, it can call contacts from any protocol, not just its contacts. For example, iax will be a protocol that can call any contact that has a phone number.
+
+- A voice contact can call a contact with diferent means (by the contact and by number associated with the contact). A call can be made to an HContact (for example using MSN) or to a number associated with an hContact (for example its home phone). More than that, you may be able to call a contact from 3 means: MSN / contact ; SkypeOut / home number ; SkypeOut / work number ; IAX / home number
+
+- A voice provider is a protocol if it has the same name as an account
+
+- Each call can have one contact associated with it (or none)
+
+- More than one call can happen at the same time
+
+- my idea is that there are 3 types of calls:
+ 1. to an hContact. That is a call made thought a protocol, like MSN or skype, that uses the protocol "im network"
+ 2. a call to a number without an hContact. That is a phone call, or a SkypeOut call
+ 3. a call with a hContact and a number. That is almost like 2, but we have more info to show the GUI and were to blink icons. For example in incoming phone call where the call id is the same as a contact, or if we use a phone number stored in a contact
+ 2 and 3 are really "external" calls in the sense they are not using an im network, but instead are identified by a number that may be or may not be associated with a contact
+
+- It is voice service's responsability to handle the call switching/answering/droping logic
+
+- Voice provides should be as simple as possible (they are already complicated by the protocols itself)
+
+- As long as possible voice service should show the options to the user and the providers should only read it from the DB
+
+- All the GUI (as far as possible) is voice service's responsability
+
+
+
+
+Future:
+
+- Voice service will (with some luck) handle video in the future
+
+
- The dialpad will be skinnable + +
+
+- Some hookable way to fetch numbers from contacts
+
+- Number formaters
+
+- Record calls?
diff --git a/Plugins/voiceservice/concepts/frame.bmml b/Plugins/voiceservice/concepts/frame.bmml new file mode 100644 index 0000000..8ce94de --- /dev/null +++ b/Plugins/voiceservice/concepts/frame.bmml @@ -0,0 +1,212 @@ +<mockup version="1.0" skin="sketch" measuredW="999" measuredH="534" mockupW="936" mockupH="445"> + <controls> + <control controlID="0" controlTypeID="com.balsamiq.mockups::FieldSet" x="255" y="191" w="317" h="333" measuredW="200" measuredH="170" zOrder="0" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + </controlProperties> + </control> + <control controlID="2" controlTypeID="com.balsamiq.mockups::Icon" x="262" y="206" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="1" locked="false" isInGroup="-1"> + <controlProperties> + <icon>WirelessIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="3" controlTypeID="com.balsamiq.mockups::Label" x="314" y="206" w="-1" h="-1" measuredW="89" measuredH="25" zOrder="2" locked="false" isInGroup="-1"> + <controlProperties> + <text>Contact%20name</text> + </controlProperties> + </control> + <control controlID="4" controlTypeID="com.balsamiq.mockups::Icon" x="286" y="206" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="3" locked="false" isInGroup="-1"> + <controlProperties> + <icon>UserIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="5" controlTypeID="com.balsamiq.mockups::Icon" x="533" y="206" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="4" locked="false" isInGroup="-1"> + <controlProperties> + <icon>PauseIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="6" controlTypeID="com.balsamiq.mockups::Icon" x="509" y="206" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="5" locked="false" isInGroup="-1"> + <controlProperties> + <icon>TapeIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="7" controlTypeID="com.balsamiq.mockups::Icon" x="262" y="230" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="6" locked="false" isInGroup="-1"> + <controlProperties> + <icon>PauseIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="8" controlTypeID="com.balsamiq.mockups::Label" x="314" y="230" w="-1" h="-1" measuredW="176" measuredH="25" zOrder="7" locked="false" isInGroup="-1"> + <controlProperties> + <text>1234-5678%20%28Contact%20name%29</text> + </controlProperties> + </control> + <control controlID="9" controlTypeID="com.balsamiq.mockups::Icon" x="286" y="230" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="8" locked="false" isInGroup="-1"> + <controlProperties> + <icon>UserIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="10" controlTypeID="com.balsamiq.mockups::Icon" x="533" y="230" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="9" locked="false" isInGroup="-1"> + <controlProperties> + <icon>RightTriangleIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="12" controlTypeID="com.balsamiq.mockups::Arrow" x="247" y="105" w="29" h="94" measuredW="150" measuredH="100" zOrder="10" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <direction>top</direction> + <leftArrow>false</leftArrow> + </controlProperties> + </control> + <control controlID="13" controlTypeID="com.balsamiq.mockups::Label" x="178" y="80" w="-1" h="-1" measuredW="71" measuredH="25" zOrder="11" locked="false" isInGroup="-1"> + <controlProperties> + <text>Call%20status</text> + </controlProperties> + </control> + <control controlID="14" controlTypeID="com.balsamiq.mockups::Label" x="286" y="79" w="-1" h="-1" measuredW="235" measuredH="25" zOrder="12" locked="false" isInGroup="-1"> + <controlProperties> + <text>Voice%20provider%20%28not%20contact%20protocol%29</text> + </controlProperties> + </control> + <control controlID="15" controlTypeID="com.balsamiq.mockups::Arrow" x="299" y="105" w="83" h="95" measuredW="150" measuredH="100" zOrder="13" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <direction>bottom</direction> + <rightArrow>false</rightArrow> + </controlProperties> + </control> + <control controlID="16" controlTypeID="com.balsamiq.mockups::Arrow" x="397" y="123" w="93" h="79" measuredW="150" measuredH="100" zOrder="14" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <direction>bottom</direction> + <rightArrow>false</rightArrow> + </controlProperties> + </control> + <control controlID="17" controlTypeID="com.balsamiq.mockups::Label" x="490" y="114" w="-1" h="-1" measuredW="186" measuredH="25" zOrder="15" locked="false" isInGroup="-1"> + <controlProperties> + <text>Contact%20name%20and/or%20number</text> + </controlProperties> + </control> + <control controlID="18" controlTypeID="com.balsamiq.mockups::Arrow" x="536" y="154" w="93" h="46" measuredW="150" measuredH="100" zOrder="16" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <direction>bottom</direction> + <rightArrow>false</rightArrow> + </controlProperties> + </control> + <control controlID="19" controlTypeID="com.balsamiq.mockups::Label" x="629" y="149" w="-1" h="-1" measuredW="80" measuredH="25" zOrder="17" locked="false" isInGroup="-1"> + <controlProperties> + <text>Action%20icons</text> + </controlProperties> + </control> + <control controlID="20" controlTypeID="com.balsamiq.mockups::Icon" x="262" y="271" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="18" locked="false" isInGroup="-1"> + <controlProperties> + <icon>DownTriangleIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="23" controlTypeID="com.balsamiq.mockups::TextInput" x="291" y="268" w="230" h="-1" measuredW="79" measuredH="29" zOrder="19" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + </controlProperties> + </control> + <control controlID="24" controlTypeID="com.balsamiq.mockups::Button" x="521" y="267" w="-1" h="-1" measuredW="48" measuredH="32" zOrder="20" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <icon>TelephoneIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="27" controlTypeID="com.balsamiq.mockups::MultilineButton" x="262" y="301" w="72" h="52" measuredW="43" measuredH="60" zOrder="21" locked="false" isInGroup="-1"> + <controlProperties> + <text>1</text> + </controlProperties> + </control> + <control controlID="28" controlTypeID="com.balsamiq.mockups::MultilineButton" x="377" y="301" w="72" h="52" measuredW="43" measuredH="60" zOrder="22" locked="false" isInGroup="-1"> + <controlProperties> + <text>2</text> + </controlProperties> + </control> + <control controlID="29" controlTypeID="com.balsamiq.mockups::MultilineButton" x="485" y="301" w="72" h="52" measuredW="43" measuredH="60" zOrder="23" locked="false" isInGroup="-1"> + <controlProperties> + <text>3</text> + </controlProperties> + </control> + <control controlID="30" controlTypeID="com.balsamiq.mockups::MultilineButton" x="262" y="353" w="72" h="52" measuredW="43" measuredH="60" zOrder="24" locked="false" isInGroup="-1"> + <controlProperties> + <text>4</text> + </controlProperties> + </control> + <control controlID="31" controlTypeID="com.balsamiq.mockups::MultilineButton" x="377" y="353" w="72" h="52" measuredW="43" measuredH="60" zOrder="25" locked="false" isInGroup="-1"> + <controlProperties> + <text>5</text> + </controlProperties> + </control> + <control controlID="32" controlTypeID="com.balsamiq.mockups::MultilineButton" x="485" y="353" w="72" h="52" measuredW="43" measuredH="60" zOrder="26" locked="false" isInGroup="-1"> + <controlProperties> + <text>6</text> + </controlProperties> + </control> + <control controlID="33" controlTypeID="com.balsamiq.mockups::MultilineButton" x="262" y="405" w="72" h="52" measuredW="43" measuredH="60" zOrder="27" locked="false" isInGroup="-1"> + <controlProperties> + <text>7</text> + </controlProperties> + </control> + <control controlID="34" controlTypeID="com.balsamiq.mockups::MultilineButton" x="377" y="405" w="72" h="52" measuredW="43" measuredH="60" zOrder="28" locked="false" isInGroup="-1"> + <controlProperties> + <text>8</text> + </controlProperties> + </control> + <control controlID="35" controlTypeID="com.balsamiq.mockups::MultilineButton" x="485" y="405" w="72" h="52" measuredW="43" measuredH="60" zOrder="29" locked="false" isInGroup="-1"> + <controlProperties> + <text>9</text> + </controlProperties> + </control> + <control controlID="36" controlTypeID="com.balsamiq.mockups::MultilineButton" x="262" y="457" w="72" h="52" measuredW="42" measuredH="60" zOrder="30" locked="false" isInGroup="-1"> + <controlProperties> + <text>*</text> + </controlProperties> + </control> + <control controlID="37" controlTypeID="com.balsamiq.mockups::MultilineButton" x="377" y="457" w="72" h="52" measuredW="43" measuredH="60" zOrder="31" locked="false" isInGroup="-1"> + <controlProperties> + <text>0</text> + </controlProperties> + </control> + <control controlID="38" controlTypeID="com.balsamiq.mockups::MultilineButton" x="485" y="457" w="72" h="52" measuredW="47" measuredH="60" zOrder="32" locked="false" isInGroup="-1"> + <controlProperties> + <text>%23</text> + </controlProperties> + </control> + <control controlID="39" controlTypeID="com.balsamiq.mockups::VCurly" x="595" y="199" w="180" h="57" measuredW="180" measuredH="140" zOrder="33" locked="false" isInGroup="-1"> + <controlProperties> + <text>Active%20calls</text> + </controlProperties> + </control> + <control controlID="40" controlTypeID="com.balsamiq.mockups::VCurly" x="597" y="264" w="180" h="254" measuredW="180" measuredH="140" zOrder="34" locked="false" isInGroup="-1"> + <controlProperties> + <text>Make%20calls</text> + </controlProperties> + </control> + <control controlID="41" controlTypeID="com.balsamiq.mockups::Arrow" x="105" y="277" w="150" h="24" measuredW="150" measuredH="100" zOrder="35" locked="false" isInGroup="-1"> + <controlProperties> + <direction>bottom</direction> + <leftArrow>false</leftArrow> + </controlProperties> + </control> + <control controlID="42" controlTypeID="com.balsamiq.mockups::Label" x="53" y="301" w="-1" h="-1" measuredW="84" measuredH="25" zOrder="36" locked="false" isInGroup="-1"> + <controlProperties> + <text>Hide%20dialpad</text> + </controlProperties> + </control> + <control controlID="43" controlTypeID="com.balsamiq.mockups::Arrow" x="572" y="267" w="214" h="19" measuredW="150" measuredH="100" zOrder="37" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <curvature>0</curvature> + <direction>bottom</direction> + <rightArrow>false</rightArrow> + </controlProperties> + </control> + <control controlID="46" controlTypeID="com.balsamiq.mockups::Paragraph" x="789" y="247" w="-1" h="-1" measuredW="200" measuredH="140" zOrder="38" locked="false" isInGroup="-1"> + <controlProperties> + <text>Make%20call%0AIf%20more%20than%20one%20provider%20allowed%2C%20%0Ashow%20popup%20with%20provides.%0AChanges%20icon%20to%20X%20if%20no%20provide%20accepts%20that%20number</text> + </controlProperties> + </control> + </controls> +</mockup>
\ No newline at end of file diff --git a/Plugins/voiceservice/concepts/frame.png b/Plugins/voiceservice/concepts/frame.png Binary files differnew file mode 100644 index 0000000..8faa84b --- /dev/null +++ b/Plugins/voiceservice/concepts/frame.png diff --git a/Plugins/voiceservice/concepts/options.bmml b/Plugins/voiceservice/concepts/options.bmml new file mode 100644 index 0000000..a0368c6 --- /dev/null +++ b/Plugins/voiceservice/concepts/options.bmml @@ -0,0 +1,42 @@ +<mockup version="1.0" skin="sketch" measuredW="642" measuredH="420" mockupW="572" mockupH="400"> + <controls> + <control controlID="0" controlTypeID="com.balsamiq.mockups::TitleWindow" x="60" y="10" w="572" h="400" measuredW="450" measuredH="400" zOrder="0" locked="false" isInGroup="-1"> + <controlProperties> + <text>Option</text> + <topheight>26</topheight> + </controlProperties> + </control> + <control controlID="1" controlTypeID="com.balsamiq.mockups::Tree" x="75" y="39" w="146" h="342" measuredW="300" measuredH="225" zOrder="1" locked="false" isInGroup="-1"> + <controlProperties> + <text>v%20Voice%0A%3E%20Devices</text> + </controlProperties> + </control> + <control controlID="2" controlTypeID="com.balsamiq.mockups::FieldSet" x="236" y="39" w="379" h="147" measuredW="200" measuredH="170" zOrder="2" locked="false" isInGroup="-1"> + <controlProperties> + <text>Audio</text> + </controlProperties> + </control> + <control controlID="3" controlTypeID="com.balsamiq.mockups::Label" x="251" y="65" w="-1" h="-1" measuredW="46" measuredH="25" zOrder="3" locked="false" isInGroup="-1"> + <controlProperties> + <text>Input%3A</text> + </controlProperties> + </control> + <control controlID="4" controlTypeID="com.balsamiq.mockups::ComboBox" x="312" y="64" w="288" h="-1" measuredW="92" measuredH="25" zOrder="4" locked="false" isInGroup="-1"/> + <control controlID="5" controlTypeID="com.balsamiq.mockups::Label" x="251" y="97" w="-1" h="-1" measuredW="57" measuredH="25" zOrder="5" locked="false" isInGroup="-1"> + <controlProperties> + <text>Output%3A</text> + </controlProperties> + </control> + <control controlID="6" controlTypeID="com.balsamiq.mockups::ComboBox" x="312" y="98" w="288" h="-1" measuredW="92" measuredH="25" zOrder="6" locked="false" isInGroup="-1"/> + <control controlID="7" controlTypeID="com.balsamiq.mockups::CheckBox" x="251" y="129" w="348" h="20" measuredW="128" measuredH="22" zOrder="7" locked="false" isInGroup="-1"> + <controlProperties> + <text>Echo%20cancelation</text> + </controlProperties> + </control> + <control controlID="8" controlTypeID="com.balsamiq.mockups::CheckBox" x="251" y="151" w="348" h="20" measuredW="125" measuredH="22" zOrder="8" locked="false" isInGroup="-1"> + <controlProperties> + <text>Microfone%20boost</text> + </controlProperties> + </control> + </controls> +</mockup>
\ No newline at end of file diff --git a/Plugins/voiceservice/concepts/options.png b/Plugins/voiceservice/concepts/options.png Binary files differnew file mode 100644 index 0000000..cc1eb98 --- /dev/null +++ b/Plugins/voiceservice/concepts/options.png diff --git a/Plugins/voiceservice/concepts/popup.bmml b/Plugins/voiceservice/concepts/popup.bmml new file mode 100644 index 0000000..7bdee0b --- /dev/null +++ b/Plugins/voiceservice/concepts/popup.bmml @@ -0,0 +1,63 @@ +<mockup version="1.0" skin="sketch" measuredW="1117" measuredH="416" mockupW="1007" mockupH="388"> + <controls> + <control controlID="1" controlTypeID="com.balsamiq.mockups::List" x="397" y="43" w="296" h="363" measuredW="100" measuredH="231" zOrder="0" locked="false" isInGroup="-1"> + <controlProperties> + <text>...%0A...%0A...%0ACall%20with%20MSN%0ACall%201234-5678%0ACall%201234-5678%20with%20SkypeOut%0A...%0A...%0AAnswer%20call%20from%20MSN%0ADrop%20call%20from%201234-5678%20from%20SkypeOut%0A...</text> + </controlProperties> + </control> + <control controlID="3" controlTypeID="com.balsamiq.mockups::Icon" x="663" y="125" w="-1" h="-1" measuredW="24" measuredH="24" zOrder="1" locked="false" isInGroup="-1"> + <controlProperties> + <icon>RightFillTriangleIcon%7Csmall</icon> + </controlProperties> + </control> + <control controlID="4" controlTypeID="com.balsamiq.mockups::List" x="685" y="125" w="125" h="51" measuredW="100" measuredH="126" zOrder="2" locked="false" isInGroup="-1"> + <controlProperties> + <text>With%20IAX%0AWith%20SkypeOut</text> + </controlProperties> + </control> + <control controlID="5" controlTypeID="com.balsamiq.mockups::Arrow" x="247" y="31" w="150" h="79" measuredW="150" measuredH="100" zOrder="3" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <leftArrow>false</leftArrow> + </controlProperties> + </control> + <control controlID="6" controlTypeID="com.balsamiq.mockups::Label" x="100" y="18" w="-1" h="-1" measuredW="147" measuredH="25" zOrder="4" locked="false" isInGroup="-1"> + <controlProperties> + <text>Calls%20for%20the%20hContact</text> + </controlProperties> + </control> + <control controlID="7" controlTypeID="com.balsamiq.mockups::Arrow" x="247" y="133" w="150" h="10" measuredW="150" measuredH="100" zOrder="5" locked="false" isInGroup="-1"> + <controlProperties> + <curvature>0</curvature> + <leftArrow>false</leftArrow> + </controlProperties> + </control> + <control controlID="8" controlTypeID="com.balsamiq.mockups::Label" x="100" y="116" w="-1" h="-1" measuredW="234" measuredH="25" zOrder="6" locked="false" isInGroup="-1"> + <controlProperties> + <text>Calls%20from%20numbers%20from%20the%20contact</text> + </controlProperties> + </control> + <control controlID="9" controlTypeID="com.balsamiq.mockups::Arrow" x="794" y="138" w="86" h="26" measuredW="150" measuredH="100" zOrder="7" locked="false" isInGroup="-1"> + <controlProperties> + <text/> + <rightArrow>false</rightArrow> + </controlProperties> + </control> + <control controlID="10" controlTypeID="com.balsamiq.mockups::Paragraph" x="886" y="154" w="221" h="140" measuredW="200" measuredH="140" zOrder="8" locked="false" isInGroup="-1"> + <controlProperties> + <text>If%20an%20item%20%28contact%20or%20number%29%20can%20be%20called%20from%20more%20than%20one%20provider%2C%20show%20a%20popup%20menu%20with%20options.%0ABut%20show%20all%20contact/numbers%20in%20the%20initial%20popup</text> + </controlProperties> + </control> + <control controlID="11" controlTypeID="com.balsamiq.mockups::Arrow" x="247" y="227" w="150" h="10" measuredW="150" measuredH="100" zOrder="9" locked="false" isInGroup="-1"> + <controlProperties> + <curvature>0</curvature> + <leftArrow>false</leftArrow> + </controlProperties> + </control> + <control controlID="12" controlTypeID="com.balsamiq.mockups::Label" x="100" y="210" w="-1" h="-1" measuredW="287" measuredH="25" zOrder="10" locked="false" isInGroup="-1"> + <controlProperties> + <text>Current%20calls%20can%20be%20managed%20from%20popup%20too</text> + </controlProperties> + </control> + </controls> +</mockup>
\ No newline at end of file diff --git a/Plugins/voiceservice/concepts/popup.png b/Plugins/voiceservice/concepts/popup.png Binary files differnew file mode 100644 index 0000000..df1fca5 --- /dev/null +++ b/Plugins/voiceservice/concepts/popup.png diff --git a/Plugins/voiceservice/frame.cpp b/Plugins/voiceservice/frame.cpp new file mode 100644 index 0000000..6add8f3 --- /dev/null +++ b/Plugins/voiceservice/frame.cpp @@ -0,0 +1,829 @@ +/*
+Copyright (C) 2005 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 /////////////////////////////////////////////////////////////////////////////////////
+
+
+HWND hwnd_frame = NULL;
+HWND hwnd_container = NULL;
+
+int frame_id = -1;
+
+static LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+#define H_SPACE 2
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+void InitFrames()
+{
+ if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ {
+ hwnd_frame = CreateDialog(hInst, MAKEINTRESOURCE(IDD_CALLS),
+ (HWND) CallService(MS_CLUI_GETHWND, 0, 0), (DLGPROC) FrameWndProc);
+
+ CLISTFrame Frame = {0};
+ Frame.cbSize = sizeof(CLISTFrame);
+ Frame.tname = TranslateT("Voice Calls");
+ Frame.hWnd = hwnd_frame;
+ Frame.align = alBottom;
+ Frame.Flags = F_VISIBLE | F_NOBORDER | F_LOCKED | F_TCHAR;
+ Frame.height = 0;
+ Frame.hIcon = IcoLib_LoadIcon(mainIcons[0], TRUE);
+
+ frame_id = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0);
+ }
+}
+
+
+void DeInitFrames()
+{
+ if (ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME) && frame_id != -1)
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)frame_id, 0);
+
+ if (hwnd_frame != NULL)
+ DestroyWindow(hwnd_frame);
+}
+
+
+static int GetMaxLineHeight() {
+ return max(ICON_SIZE, font_max_height) + 1;
+}
+
+
+BOOL FrameIsFloating(int frame_id)
+{
+ if (frame_id == -1)
+ return TRUE; // no frames, always floating
+
+ return CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLOATING, frame_id), 0);
+}
+
+void ResizeFrame(int frame_id, HWND hwnd)
+{
+ int height = calls.getCount() * GetMaxLineHeight();
+ if (height > 0)
+ height += 2;
+
+ if (CanCallNumber())
+ {
+ height += 23 + 2;
+
+ if (SendMessage(GetDlgItem(hwnd, IDC_DIALPAD), BM_GETCHECK, 0, 0) == BST_CHECKED)
+ {
+ RECT first, last;
+ GetWindowRect(GetDlgItem(hwnd, IDC_1), &first);
+ GetWindowRect(GetDlgItem(hwnd, IDC_SHARP), &last);
+
+ height += last.bottom - first.top + 1;
+ }
+ }
+
+ if (FrameIsFloating(frame_id))
+ {
+ HWND parent = GetParent(hwnd);
+ if (parent == NULL)
+ return;
+
+ RECT r_client;
+ GetClientRect(hwnd, &r_client);
+
+ if (r_client.bottom - r_client.top == height)
+ return;
+
+ RECT parent_client, parent_window, r_window;
+ GetClientRect(parent, &parent_client);
+ GetWindowRect(parent, &parent_window);
+ GetWindowRect(hwnd, &r_window);
+
+ int diff = (parent_window.bottom - parent_window.top) - (parent_client.bottom - parent_client.top);
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ diff += (r_window.top - parent_window.top);
+
+ SetWindowPos(parent, 0, 0, 0, parent_window.right - parent_window.left, height + diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ }
+ else
+ {
+ int old_height = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, frame_id), 0);
+ if (old_height == height)
+ return;
+
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, frame_id), (LPARAM) height);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_TBREDRAW | FU_FMREDRAW | FU_FMPOS));
+ }
+}
+
+void ShowFrame(int frame_id, HWND hwnd, int show)
+{
+ BOOL is_visible = IsWindowVisible(hwnd);
+ if ((is_visible && show == SW_SHOW) || (!is_visible && show == SW_HIDE))
+ return;
+
+ if (ServiceExists(MS_CLIST_FRAMES_SHFRAME) && frame_id != -1)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)frame_id, 0);
+ else
+ ShowWindow(GetParent(hwnd), show);
+}
+
+
+static int dialCtrls[] = {
+ IDC_DIALPAD, IDC_NUMBER, IDC_CALL,
+ IDC_1, IDC_2, IDC_3,
+ IDC_4, IDC_5, IDC_6,
+ IDC_7, IDC_8, IDC_9,
+ IDC_AST, IDC_0, IDC_SHARP
+};
+
+
+
+static void InvalidateAll(HWND hwnd)
+{
+ InvalidateRect(GetDlgItem(hwnd, IDC_CALLS), NULL, FALSE);
+ for(int i = 0; i < MAX_REGS(dialCtrls); ++i)
+ InvalidateRect(GetDlgItem(hwnd, dialCtrls[i]), NULL, FALSE);
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ if (frame_id != -1)
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_FMREDRAW));
+}
+
+
+static void ShowHideDialpad(HWND hwnd)
+{
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ if (!CanCallNumber())
+ {
+ for(int i = 0; i < MAX_REGS(dialCtrls); ++i)
+ ShowWindow(GetDlgItem(hwnd, dialCtrls[i]), SW_HIDE);
+ }
+ else
+ {
+ int i;
+ for(i = 0; i < 3; ++i)
+ ShowWindow(GetDlgItem(hwnd, dialCtrls[i]), SW_SHOW);
+
+ bool showDialpad = (SendMessage(GetDlgItem(hwnd, IDC_DIALPAD), BM_GETCHECK, 0, 0) == BST_CHECKED);
+
+ for(i = 3; i < MAX_REGS(dialCtrls); ++i)
+ ShowWindow(GetDlgItem(hwnd, dialCtrls[i]), showDialpad ? SW_SHOW : SW_HIDE);
+
+ VoiceCall *talking = NULL;
+ bool ringing = false;
+ bool calling = false;
+ for(i = 0; i < calls.getCount(); i++)
+ {
+ VoiceCall *call = &calls[i];
+ if (call->state == VOICE_STATE_TALKING)
+ talking = call;
+ else if (call->state == VOICE_STATE_CALLING)
+ calling = true;
+ else if (call->state == VOICE_STATE_RINGING)
+ ringing = true;
+ }
+
+ TCHAR number[1024];
+ GetDlgItemText(hwnd, IDC_NUMBER, number, MAX_REGS(number));
+ lstrtrim(number);
+
+ if (ringing && number[0] != 0)
+ {
+ SetWindowText(GetDlgItem(hwnd, IDC_NUMBER), _T(""));
+ number[0] = 0;
+ }
+
+ if (ringing || calling)
+ {
+ for(i = 0; i < MAX_REGS(dialCtrls); ++i)
+ EnableWindow(GetDlgItem(hwnd, dialCtrls[i]), FALSE);
+ }
+ else if (talking)
+ {
+ if (!showDialpad || !talking->CanSendDTMF())
+ {
+ for(i = 0; i < MAX_REGS(dialCtrls); ++i)
+ EnableWindow(GetDlgItem(hwnd, dialCtrls[i]), FALSE);
+
+ EnableWindow(GetDlgItem(hwnd, IDC_DIALPAD), TRUE);
+ }
+ else
+ {
+ for(i = 0; i < MAX_REGS(dialCtrls); ++i)
+ EnableWindow(GetDlgItem(hwnd, dialCtrls[i]), TRUE);
+
+ EnableWindow(GetDlgItem(hwnd, IDC_NUMBER), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_CALL), FALSE);
+ }
+ }
+ else
+ {
+ for(i = 0; i < MAX_REGS(dialCtrls); ++i)
+ EnableWindow(GetDlgItem(hwnd, dialCtrls[i]), TRUE);
+
+ EnableWindow(GetDlgItem(hwnd, IDC_CALL), CanCall(number));
+ }
+ }
+
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+
+ InvalidateAll(hwnd);
+}
+
+
+static int sttCompareProvidesByDescription(const VoiceProvider *p1, const VoiceProvider *p2)
+{
+ return lstrcmp(p2->description, p1->description);
+}
+
+
+static void DrawIconLib(HDC hDC, const RECT &rc, const char *icon)
+{
+ HICON hIcon = IcoLib_LoadIcon(icon);
+ if (hIcon == NULL)
+ return;
+
+ DrawIconEx(hDC, rc.left, (rc.top + rc.bottom - ICON_SIZE)/2, hIcon, ICON_SIZE, ICON_SIZE, 0, NULL, DI_NORMAL);
+ IcoLib_ReleaseIcon(hIcon);
+}
+
+
+static LRESULT CALLBACK FrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch(msg)
+ {
+ case WM_CREATE:
+ case WM_INITDIALOG:
+ {
+ SendDlgItemMessage(hwnd, IDC_DIALPAD, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwnd, IDC_DIALPAD, BUTTONSETASPUSHBTN, TRUE, 0);
+ SendDlgItemMessageA(hwnd, IDC_DIALPAD, BUTTONADDTOOLTIP, (LPARAM) Translate("Show dialpad"), 0);
+ SendDlgItemMessage(hwnd, IDC_DIALPAD, BM_SETIMAGE, IMAGE_ICON, (LPARAM) IcoLib_LoadIcon("vc_dialpad", TRUE));
+
+ SendDlgItemMessage(hwnd, IDC_CALL, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessageA(hwnd, IDC_CALL, BUTTONADDTOOLTIP, (LPARAM) Translate("Make call"), 0);
+ SendDlgItemMessage(hwnd, IDC_CALL, BM_SETIMAGE, IMAGE_ICON, (LPARAM) IcoLib_LoadIcon("vca_call", TRUE));
+
+ PostMessage(hwnd, WMU_RESIZE_FRAME, 0, 1);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+
+ int width = rc.right - rc.left;
+ int height = rc.bottom - rc.top;
+
+ if (CanCallNumber())
+ {
+ bool showDialpad = (SendMessage(GetDlgItem(hwnd, IDC_DIALPAD), BM_GETCHECK, 0, 0) == BST_CHECKED);
+
+ RECT rc;
+ GetWindowRect(hwnd, &rc);
+
+ RECT first = {0}, last = {0};
+ GetWindowRect(GetDlgItem(hwnd, IDC_1), &first);
+ GetWindowRect(GetDlgItem(hwnd, IDC_SHARP), &last);
+
+ int dialpad_height = last.bottom - first.top;
+ int dialpad_width = last.right - first.left;
+
+
+ int call_height = 23;
+ int call_width = 25;
+ int top = height - call_height - 1;
+
+ if (showDialpad)
+ top -= dialpad_height + 1;
+
+ MoveWindow(GetDlgItem(hwnd, IDC_DIALPAD), 1, top, call_width -2, call_height, FALSE);
+ MoveWindow(GetDlgItem(hwnd, IDC_NUMBER), call_width, top, width - 2 * call_width, call_height, FALSE);
+ MoveWindow(GetDlgItem(hwnd, IDC_CALL), width - call_width, top, call_width, call_height +1, FALSE);
+
+
+ int dialpad_top = top + call_height + 1;
+ int dialpad_left = ((rc.right - rc.left) - dialpad_width) / 2;
+ int deltaX = dialpad_left - first.left;
+ int deltaY = dialpad_top - first.top;
+ for(int i = 3; i < MAX_REGS(dialCtrls); ++i)
+ {
+ GetWindowRect(GetDlgItem(hwnd, dialCtrls[i]), &rc);
+ MoveWindow(GetDlgItem(hwnd, dialCtrls[i]), rc.left + deltaX, rc.top + deltaY,
+ rc.right - rc.left, rc.bottom - rc.top, FALSE);
+ }
+
+
+ height -= call_height + 2;
+ if (showDialpad)
+ height -= dialpad_height + 1;
+ }
+
+ if (height <= 2)
+ {
+ ShowWindow(GetDlgItem(hwnd, IDC_CALLS), SW_HIDE);
+ }
+ else
+ {
+ MoveWindow(GetDlgItem(hwnd, IDC_CALLS), 1, 1, width-2, height-2, FALSE);
+ ShowWindow(GetDlgItem(hwnd, IDC_CALLS), SW_SHOW);
+ }
+
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+
+ InvalidateAll(hwnd);
+ break;
+ }
+
+ case WMU_REFRESH:
+ {
+ HWND list = GetDlgItem(hwnd, IDC_CALLS);
+
+ SendMessage(list, WM_SETREDRAW, FALSE, 0);
+ SendMessage(list, LB_RESETCONTENT, 0, 0);
+ for(int i = 0; i < calls.getCount(); i++)
+ {
+ VoiceCall *call = &calls[i];
+
+ TCHAR text[512];
+ mir_sntprintf(text, MAX_REGS(text), _T("%d %s"), call->state, call->displayName);
+
+ int pos = SendMessage(list, LB_ADDSTRING, 0, (LPARAM) text);
+ if (pos == LB_ERR)
+ // TODO Show error
+ continue;
+
+ SendMessage(list, LB_SETITEMDATA, pos, (LPARAM) call);
+ }
+ SendMessage(list, WM_SETREDRAW, TRUE, 0);
+
+ // Fall throught
+ }
+
+ case WMU_RESIZE_FRAME:
+ {
+ ShowHideDialpad(hwnd);
+
+ if (lParam)
+ SendMessage(hwnd, WM_SIZE, 0, 0);
+
+ if (opts.resize_frame)
+ {
+ if (calls.getCount() == 0 && !CanCallNumber())
+ {
+ ShowFrame(frame_id, hwnd, SW_HIDE);
+ }
+ else
+ {
+ ResizeFrame(frame_id, hwnd);
+ ShowFrame(frame_id, hwnd, SW_SHOW);
+ }
+ }
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDC_CALL:
+ {
+ TCHAR number[1024];
+ GetDlgItemText(hwnd, IDC_NUMBER, number, MAX_REGS(number));
+ lstrtrim(number);
+
+ LIST<VoiceProvider> candidates(10, &sttCompareProvidesByDescription);
+
+ for(int i = 0; i < modules.getCount(); i++)
+ {
+ if (!modules[i].CanCall(number))
+ continue;
+
+ candidates.insert(&modules[i]);
+ }
+
+ int selected;
+
+ if (candidates.getCount() < 1)
+ {
+ break;
+ }
+ else if (candidates.getCount() == 1)
+ {
+ selected = 0;
+ }
+ else
+ {
+ HMENU menu = CreatePopupMenu();
+
+ for (int i = 0; i < candidates.getCount(); ++i)
+ {
+ TCHAR text[1024];
+ mir_sntprintf(text, MAX_REGS(text), TranslateT("Call with %s"),
+ candidates[i]->description);
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = text;
+ mii.cch = lstrlen(text);
+ mii.wID = i + 1;
+
+ // TODO: Add icon to menu
+
+ InsertMenuItem(menu, 0, TRUE, &mii);
+ }
+
+ RECT rc;
+ GetWindowRect(GetDlgItem(hwnd, IDC_CALL), &rc);
+
+ POINT p;
+ p.x = rc.right;
+ p.y = rc.bottom+1;
+
+ selected = TrackPopupMenu(menu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD|TPM_RIGHTALIGN,
+ p.x, p.y, 0, hwnd, NULL);
+
+ DestroyMenu(menu);
+
+ if (selected == 0)
+ break;
+
+ selected--;
+ }
+
+ candidates[selected]->Call(NULL, number);
+
+ break;
+ }
+ case IDC_NUMBER:
+ {
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ ShowHideDialpad(hwnd);
+ }
+ break;
+ }
+ case IDC_DIALPAD:
+ {
+ ShowHideDialpad(hwnd);
+ SendMessage(hwnd, WMU_RESIZE_FRAME, 0, 0);
+ break;
+ }
+ case IDC_1:
+ case IDC_2:
+ case IDC_3:
+ case IDC_4:
+ case IDC_5:
+ case IDC_6:
+ case IDC_7:
+ case IDC_8:
+ case IDC_9:
+ case IDC_AST:
+ case IDC_0:
+ case IDC_SHARP:
+ {
+ TCHAR text[2];
+ switch(LOWORD(wParam))
+ {
+ case IDC_1: text[0] = _T('1'); break;
+ case IDC_2: text[0] = _T('2'); break;
+ case IDC_3: text[0] = _T('3'); break;
+ case IDC_4: text[0] = _T('4'); break;
+ case IDC_5: text[0] = _T('5'); break;
+ case IDC_6: text[0] = _T('6'); break;
+ case IDC_7: text[0] = _T('7'); break;
+ case IDC_8: text[0] = _T('8'); break;
+ case IDC_9: text[0] = _T('9'); break;
+ case IDC_AST: text[0] = _T('*'); break;
+ case IDC_0: text[0] = _T('0'); break;
+ case IDC_SHARP: text[0] = _T('#'); break;
+ }
+ text[1] = 0;
+
+ SkinPlaySound("voice_dialpad");
+
+ VoiceCall *call = GetTalkingCall();
+ if (call == NULL)
+ {
+ SendMessage(GetDlgItem(hwnd, IDC_NUMBER), EM_REPLACESEL, TRUE, (LPARAM) text);
+ }
+ else
+ {
+ TCHAR tmp[1024];
+
+ GetWindowText(GetDlgItem(hwnd, IDC_NUMBER), tmp, MAX_REGS(tmp));
+
+ tmp[MAX_REGS(tmp)-2] = 0;
+ lstrcat(tmp, text);
+
+ SetWindowText(GetDlgItem(hwnd, IDC_NUMBER), tmp);
+
+ call->SendDTMF(text[0]);
+ }
+ break;
+ }
+ case IDC_CALLS:
+ {
+ if (HIWORD(wParam) != LBN_SELCHANGE)
+ break;
+
+ HWND list = GetDlgItem(hwnd, IDC_CALLS);
+
+ int pos = SendMessage(list, LB_GETCURSEL, 0, 0);
+ if (pos == LB_ERR)
+ break;
+
+ POINT p;
+ GetCursorPos(&p);
+ ScreenToClient(list, &p);
+
+ int ret = SendMessage(list, LB_ITEMFROMPOINT, 0, MAKELONG(p.x, p.y));
+ if (HIWORD(ret))
+ break;
+ if (pos != LOWORD(ret))
+ break;
+
+ RECT rc;
+ SendMessage(list, LB_GETITEMRECT, pos, (LPARAM) &rc);
+ int x = rc.right - p.x;
+
+ int action;
+ if (x >= H_SPACE && x <= ICON_SIZE + H_SPACE)
+ action = 2;
+ else if (x >= ICON_SIZE + 2 * H_SPACE && x <= 2 * (ICON_SIZE + H_SPACE))
+ action = 1;
+ else
+ break;
+
+ VoiceCall *call = (VoiceCall *) SendMessage(list, LB_GETITEMDATA, pos, 0);
+ switch (call->state)
+ {
+ case VOICE_STATE_TALKING:
+ {
+ if (action == 1)
+ call->Hold();
+ else
+ call->Drop();
+ break;
+ }
+ case VOICE_STATE_RINGING:
+ case VOICE_STATE_ON_HOLD:
+ {
+ if (action == 1)
+ Answer(call);
+ else
+ call->Drop();
+ break;
+ }
+ case VOICE_STATE_CALLING:
+ {
+ if (action == 2)
+ call->Drop();
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ HWND list = GetDlgItem(hwnd, IDC_CALLS);
+ if ((HANDLE) wParam != list)
+ break;
+
+ POINT p;
+ p.x = LOWORD(lParam);
+ p.y = HIWORD(lParam);
+ ScreenToClient(list, &p);
+
+ int pos = SendMessage(list, LB_ITEMFROMPOINT, 0, MAKELONG(p.x, p.y));
+ if (HIWORD(pos))
+ break;
+ pos = LOWORD(pos);
+
+ if (pos >= calls.getCount())
+ break;
+
+ if (IsFinalState(calls[pos].state))
+ break;
+
+ // Just to get things strait
+ SendMessage(list, LB_SETCURSEL, pos, 0);
+
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENUS));
+ HMENU submenu = GetSubMenu(menu, 0);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM)submenu, 0);
+
+ switch (calls[pos].state)
+ {
+ case VOICE_STATE_CALLING:
+ {
+ DeleteMenu(menu, ID_FRAMEPOPUP_ANSWERCALL, MF_BYCOMMAND);
+ DeleteMenu(menu, ID_FRAMEPOPUP_HOLDCALL, MF_BYCOMMAND);
+ break;
+ }
+ case VOICE_STATE_TALKING:
+ {
+ DeleteMenu(menu, ID_FRAMEPOPUP_ANSWERCALL, MF_BYCOMMAND);
+ if (!calls[pos].module->CanHold())
+ DeleteMenu(menu, ID_FRAMEPOPUP_HOLDCALL, MF_BYCOMMAND);
+ break;
+ }
+ }
+
+ p.x = LOWORD(lParam);
+ p.y = HIWORD(lParam);
+ int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+
+ switch(ret)
+ {
+ case ID_FRAMEPOPUP_DROPCALL:
+ {
+ calls[pos].Drop();
+ break;
+ }
+ case ID_FRAMEPOPUP_ANSWERCALL:
+ {
+ Answer(&calls[pos]);
+ break;
+ }
+ case ID_FRAMEPOPUP_HOLDCALL:
+ {
+ calls[pos].Hold();
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT) lParam;
+ if (mis->CtlID != IDC_CALLS)
+ break;
+
+ mis->itemHeight = GetMaxLineHeight();
+
+ return TRUE;
+ }
+
+ case WM_CTLCOLORLISTBOX:
+ {
+ return (LRESULT) bk_brush;
+ }
+
+ case WM_DRAWITEM:
+ {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
+
+ if (dis->CtlID != IDC_CALLS || dis->itemID == -1)
+ break;
+
+ VoiceCall *call = (VoiceCall *) dis->itemData;
+ if (call == NULL)
+ break;
+
+ RECT rc = dis->rcItem;
+
+ FillRect(dis->hDC, &rc, bk_brush);
+
+ rc.left += H_SPACE;
+ rc.right -= H_SPACE;
+ rc.bottom --;
+
+ int old_bk_mode = SetBkMode(dis->hDC, TRANSPARENT);
+
+ // Draw status
+ DrawIconLib(dis->hDC, rc, stateIcons[call->state]);
+
+ if (call->secure)
+ DrawIconLib(dis->hDC, rc, "vc_secure");
+
+ // Draw voice provider icon
+ rc.left += ICON_SIZE + H_SPACE;
+
+ HICON hIcon = call->module->GetIcon();
+ if (hIcon != NULL)
+ {
+ DrawIconEx(dis->hDC, rc.left, (rc.top + rc.bottom - ICON_SIZE)/2, hIcon, ICON_SIZE, ICON_SIZE, 0, NULL, DI_NORMAL);
+ call->module->ReleaseIcon(hIcon);
+ }
+
+ // Draw contact
+ rc.left += ICON_SIZE + H_SPACE;
+
+ int numIcons = 0;
+ switch (call->state)
+ {
+ case VOICE_STATE_CALLING:
+ numIcons = 1;
+ break;
+ case VOICE_STATE_TALKING:
+ if (call->module->CanHold())
+ numIcons = 2;
+ else
+ numIcons = 1;
+ break;
+ case VOICE_STATE_RINGING:
+ case VOICE_STATE_ON_HOLD:
+ numIcons = 2;
+ break;
+ }
+
+ rc.right -= numIcons * (ICON_SIZE + H_SPACE);
+
+ HFONT old_font = (HFONT) SelectObject(dis->hDC, fonts[call->state]);
+ COLORREF old_color = SetTextColor(dis->hDC, font_colors[call->state]);
+
+ DrawText(dis->hDC, call->displayName, -1, &rc, DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS | DT_VCENTER);
+
+ SelectObject(dis->hDC, old_font);
+ SetTextColor(dis->hDC, old_color);
+
+ // Draw action icons
+ rc = dis->rcItem;
+ rc.right -= H_SPACE;
+ rc.bottom --;
+
+ switch (call->state)
+ {
+ case VOICE_STATE_CALLING:
+ {
+ rc.left = rc.right - ICON_SIZE;
+ DrawIconLib(dis->hDC, rc, actionIcons[ACTION_DROP]);
+ break;
+ }
+ case VOICE_STATE_TALKING:
+ {
+ rc.left = rc.right - ICON_SIZE;
+ DrawIconLib(dis->hDC, rc, actionIcons[ACTION_DROP]);
+
+ if (call->module->CanHold())
+ {
+ rc.right -= ICON_SIZE + H_SPACE;
+ rc.left = rc.right - ICON_SIZE;
+ DrawIconLib(dis->hDC, rc, actionIcons[ACTION_HOLD]);
+ }
+
+ break;
+ }
+ case VOICE_STATE_RINGING:
+ case VOICE_STATE_ON_HOLD:
+ {
+ rc.left = rc.right - ICON_SIZE;
+ DrawIconLib(dis->hDC, rc, actionIcons[ACTION_DROP]);
+
+ rc.right -= ICON_SIZE + H_SPACE;
+ rc.left = rc.right - ICON_SIZE;
+ DrawIconLib(dis->hDC, rc, actionIcons[ACTION_ANSWER]);
+
+ break;
+ }
+ }
+
+ SetBkMode(dis->hDC, old_bk_mode);
+ return TRUE;
+ }
+
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
diff --git a/Plugins/voiceservice/frame.h b/Plugins/voiceservice/frame.h new file mode 100644 index 0000000..c0221cd --- /dev/null +++ b/Plugins/voiceservice/frame.h @@ -0,0 +1,36 @@ +/*
+Copyright (C) 2006 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 __FRAME_H__
+# define __FRAME_H__
+
+
+void InitFrames();
+void DeInitFrames();
+
+
+extern HWND hwnd_frame;
+
+
+#define WMU_REFRESH (WM_USER + 25)
+#define WMU_RESIZE_FRAME (WM_USER + 26)
+
+
+#endif // __FRAME_H__
\ No newline at end of file diff --git a/Plugins/voiceservice/lib/portaudio/Debug/libportaudio.lib b/Plugins/voiceservice/lib/portaudio/Debug/libportaudio.lib Binary files differnew file mode 100644 index 0000000..461b78d --- /dev/null +++ b/Plugins/voiceservice/lib/portaudio/Debug/libportaudio.lib diff --git a/Plugins/voiceservice/lib/portaudio/LICENSE.txt b/Plugins/voiceservice/lib/portaudio/LICENSE.txt new file mode 100644 index 0000000..e0ac4e8 --- /dev/null +++ b/Plugins/voiceservice/lib/portaudio/LICENSE.txt @@ -0,0 +1,81 @@ +Portable header file to contain: +>>>>> +/* + * PortAudio Portable Real-Time Audio Library + * PortAudio API Header File + * Latest version available at: http://www.portaudio.com + * + * Copyright (c) 1999-2006 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ +<<<<< + + +Implementation files to contain: +>>>>> +/* + * PortAudio Portable Real-Time Audio Library + * Latest version at: http://www.portaudio.com + * <platform> Implementation + * Copyright (c) 1999-2000 <author(s)> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ +<<<<<
\ No newline at end of file diff --git a/Plugins/voiceservice/lib/portaudio/Release/libportaudio.lib b/Plugins/voiceservice/lib/portaudio/Release/libportaudio.lib Binary files differnew file mode 100644 index 0000000..88ccf54 --- /dev/null +++ b/Plugins/voiceservice/lib/portaudio/Release/libportaudio.lib diff --git a/Plugins/voiceservice/lib/portaudio/portaudio.h b/Plugins/voiceservice/lib/portaudio/portaudio.h new file mode 100644 index 0000000..89964ab --- /dev/null +++ b/Plugins/voiceservice/lib/portaudio/portaudio.h @@ -0,0 +1,1134 @@ +#ifndef PORTAUDIO_H +#define PORTAUDIO_H +/* + * $Id: portaudio.h 1337 2008-02-15 07:32:09Z rossb $ + * PortAudio Portable Real-Time Audio Library + * PortAudio API Header File + * Latest version available at: http://www.portaudio.com/ + * + * Copyright (c) 1999-2002 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however, + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the + * license above. + */ + +/** @file + @ingroup public_header + @brief The portable PortAudio API. +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +/** Retrieve the release number of the currently running PortAudio build, + eg 1900. +*/ +int Pa_GetVersion( void ); + + +/** Retrieve a textual description of the current PortAudio build, + eg "PortAudio V19-devel 13 October 2002". +*/ +const char* Pa_GetVersionText( void ); + + +/** Error codes returned by PortAudio functions. + Note that with the exception of paNoError, all PaErrorCodes are negative. +*/ + +typedef int PaError; +typedef enum PaErrorCode +{ + paNoError = 0, + + paNotInitialized = -10000, + paUnanticipatedHostError, + paInvalidChannelCount, + paInvalidSampleRate, + paInvalidDevice, + paInvalidFlag, + paSampleFormatNotSupported, + paBadIODeviceCombination, + paInsufficientMemory, + paBufferTooBig, + paBufferTooSmall, + paNullCallback, + paBadStreamPtr, + paTimedOut, + paInternalError, + paDeviceUnavailable, + paIncompatibleHostApiSpecificStreamInfo, + paStreamIsStopped, + paStreamIsNotStopped, + paInputOverflowed, + paOutputUnderflowed, + paHostApiNotFound, + paInvalidHostApi, + paCanNotReadFromACallbackStream, /**< @todo review error code name */ + paCanNotWriteToACallbackStream, /**< @todo review error code name */ + paCanNotReadFromAnOutputOnlyStream, /**< @todo review error code name */ + paCanNotWriteToAnInputOnlyStream, /**< @todo review error code name */ + paIncompatibleStreamHostApi, + paBadBufferPtr +} PaErrorCode; + + +/** Translate the supplied PortAudio error code into a human readable + message. +*/ +const char *Pa_GetErrorText( PaError errorCode ); + + +/** Library initialization function - call this before using PortAudio. + This function initialises internal data structures and prepares underlying + host APIs for use. With the exception of Pa_GetVersion(), Pa_GetVersionText(), + and Pa_GetErrorText(), this function MUST be called before using any other + PortAudio API functions. + + If Pa_Initialize() is called multiple times, each successful + call must be matched with a corresponding call to Pa_Terminate(). + Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not + required to be fully nested. + + Note that if Pa_Initialize() returns an error code, Pa_Terminate() should + NOT be called. + + @return paNoError if successful, otherwise an error code indicating the cause + of failure. + + @see Pa_Terminate +*/ +PaError Pa_Initialize( void ); + + +/** Library termination function - call this when finished using PortAudio. + This function deallocates all resources allocated by PortAudio since it was + initializied by a call to Pa_Initialize(). In cases where Pa_Initialise() has + been called multiple times, each call must be matched with a corresponding call + to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically + close any PortAudio streams that are still open. + + Pa_Terminate() MUST be called before exiting a program which uses PortAudio. + Failure to do so may result in serious resource leaks, such as audio devices + not being available until the next reboot. + + @return paNoError if successful, otherwise an error code indicating the cause + of failure. + + @see Pa_Initialize +*/ +PaError Pa_Terminate( void ); + + + +/** The type used to refer to audio devices. Values of this type usually + range from 0 to (Pa_GetDeviceCount()-1), and may also take on the PaNoDevice + and paUseHostApiSpecificDeviceSpecification values. + + @see Pa_GetDeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification +*/ +typedef int PaDeviceIndex; + + +/** A special PaDeviceIndex value indicating that no device is available, + or should be used. + + @see PaDeviceIndex +*/ +#define paNoDevice ((PaDeviceIndex)-1) + + +/** A special PaDeviceIndex value indicating that the device(s) to be used + are specified in the host api specific stream info structure. + + @see PaDeviceIndex +*/ +#define paUseHostApiSpecificDeviceSpecification ((PaDeviceIndex)-2) + + +/* Host API enumeration mechanism */ + +/** The type used to enumerate to host APIs at runtime. Values of this type + range from 0 to (Pa_GetHostApiCount()-1). + + @see Pa_GetHostApiCount +*/ +typedef int PaHostApiIndex; + + +/** Retrieve the number of available host APIs. Even if a host API is + available it may have no devices available. + + @return A non-negative value indicating the number of available host APIs + or, a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. + + @see PaHostApiIndex +*/ +PaHostApiIndex Pa_GetHostApiCount( void ); + + +/** Retrieve the index of the default host API. The default host API will be + the lowest common denominator host API on the current platform and is + unlikely to provide the best performance. + + @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1) + indicating the default host API index or, a PaErrorCode (which are always + negative) if PortAudio is not initialized or an error is encountered. +*/ +PaHostApiIndex Pa_GetDefaultHostApi( void ); + + +/** Unchanging unique identifiers for each supported host API. This type + is used in the PaHostApiInfo structure. The values are guaranteed to be + unique and to never change, thus allowing code to be written that + conditionally uses host API specific extensions. + + New type ids will be allocated when support for a host API reaches + "public alpha" status, prior to that developers should use the + paInDevelopment type id. + + @see PaHostApiInfo +*/ +typedef enum PaHostApiTypeId +{ + paInDevelopment=0, /* use while developing support for a new host API */ + paDirectSound=1, + paMME=2, + paASIO=3, + paSoundManager=4, + paCoreAudio=5, + paOSS=7, + paALSA=8, + paAL=9, + paBeOS=10, + paWDMKS=11, + paJACK=12, + paWASAPI=13, + paAudioScienceHPI=14 +} PaHostApiTypeId; + + +/** A structure containing information about a particular host API. */ + +typedef struct PaHostApiInfo +{ + /** this is struct version 1 */ + int structVersion; + /** The well known unique identifier of this host API @see PaHostApiTypeId */ + PaHostApiTypeId type; + /** A textual description of the host API for display on user interfaces. */ + const char *name; + + /** The number of devices belonging to this host API. This field may be + used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate + all devices for this host API. + @see Pa_HostApiDeviceIndexToDeviceIndex + */ + int deviceCount; + + /** The default input device for this host API. The value will be a + device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice + if no default input device is available. + */ + PaDeviceIndex defaultInputDevice; + + /** The default output device for this host API. The value will be a + device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice + if no default output device is available. + */ + PaDeviceIndex defaultOutputDevice; + +} PaHostApiInfo; + + +/** Retrieve a pointer to a structure containing information about a specific + host Api. + + @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1) + + @return A pointer to an immutable PaHostApiInfo structure describing + a specific host API. If the hostApi parameter is out of range or an error + is encountered, the function returns NULL. + + The returned structure is owned by the PortAudio implementation and must not + be manipulated or freed. The pointer is only guaranteed to be valid between + calls to Pa_Initialize() and Pa_Terminate(). +*/ +const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi ); + + +/** Convert a static host API unique identifier, into a runtime + host API index. + + @param type A unique host API identifier belonging to the PaHostApiTypeId + enumeration. + + @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or, + a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. + + The paHostApiNotFound error code indicates that the host API specified by the + type parameter is not available. + + @see PaHostApiTypeId +*/ +PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type ); + + +/** Convert a host-API-specific device index to standard PortAudio device index. + This function may be used in conjunction with the deviceCount field of + PaHostApiInfo to enumerate all devices for the specified host API. + + @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1) + + @param hostApiDeviceIndex A valid per-host device index in the range + 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1) + + @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1) + or, a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. + + A paInvalidHostApi error code indicates that the host API index specified by + the hostApi parameter is out of range. + + A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter + is out of range. + + @see PaHostApiInfo +*/ +PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, + int hostApiDeviceIndex ); + + + +/** Structure used to return information about a host error condition. +*/ +typedef struct PaHostErrorInfo{ + PaHostApiTypeId hostApiType; /**< the host API which returned the error code */ + long errorCode; /**< the error code returned */ + const char *errorText; /**< a textual description of the error if available, otherwise a zero-length string */ +}PaHostErrorInfo; + + +/** Return information about the last host error encountered. The error + information returned by Pa_GetLastHostErrorInfo() will never be modified + asyncronously by errors occurring in other PortAudio owned threads + (such as the thread that manages the stream callback.) + + This function is provided as a last resort, primarily to enhance debugging + by providing clients with access to all available error information. + + @return A pointer to an immutable structure constaining information about + the host error. The values in this structure will only be valid if a + PortAudio function has previously returned the paUnanticipatedHostError + error code. +*/ +const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void ); + + + +/* Device enumeration and capabilities */ + +/** Retrieve the number of available devices. The number of available devices + may be zero. + + @return A non-negative value indicating the number of available devices or, + a PaErrorCode (which are always negative) if PortAudio is not initialized + or an error is encountered. +*/ +PaDeviceIndex Pa_GetDeviceCount( void ); + + +/** Retrieve the index of the default input device. The result can be + used in the inputDevice parameter to Pa_OpenStream(). + + @return The default input device index for the default host API, or paNoDevice + if no default input device is available or an error was encountered. +*/ +PaDeviceIndex Pa_GetDefaultInputDevice( void ); + + +/** Retrieve the index of the default output device. The result can be + used in the outputDevice parameter to Pa_OpenStream(). + + @return The default output device index for the defualt host API, or paNoDevice + if no default output device is available or an error was encountered. + + @note + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. +<pre> + set PA_RECOMMENDED_OUTPUT_DEVICE=1 +</pre> + The user should first determine the available device ids by using + the supplied application "pa_devs". +*/ +PaDeviceIndex Pa_GetDefaultOutputDevice( void ); + + +/** The type used to represent monotonic time in seconds that can be used + for syncronisation. The type is used for the outTime argument to the + PaStreamCallback and as the result of Pa_GetStreamTime(). + + @see PaStreamCallback, Pa_GetStreamTime +*/ +typedef double PaTime; + + +/** A type used to specify one or more sample formats. Each value indicates + a possible format for sound data passed to and from the stream callback, + Pa_ReadStream and Pa_WriteStream. + + The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8 + and aUInt8 are usually implemented by all implementations. + + The floating point representation (paFloat32) uses +1.0 and -1.0 as the + maximum and minimum respectively. + + paUInt8 is an unsigned 8 bit format where 128 is considered "ground" + + The paNonInterleaved flag indicates that a multichannel buffer is passed + as a set of non-interleaved pointers. + + @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo + @see paFloat32, paInt16, paInt32, paInt24, paInt8 + @see paUInt8, paCustomFormat, paNonInterleaved +*/ +typedef unsigned long PaSampleFormat; + + +#define paFloat32 ((PaSampleFormat) 0x00000001) /**< @see PaSampleFormat */ +#define paInt32 ((PaSampleFormat) 0x00000002) /**< @see PaSampleFormat */ +#define paInt24 ((PaSampleFormat) 0x00000004) /**< Packed 24 bit format. @see PaSampleFormat */ +#define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */ +#define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */ +#define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */ +#define paCustomFormat ((PaSampleFormat) 0x00010000)/**< @see PaSampleFormat */ + +#define paNonInterleaved ((PaSampleFormat) 0x80000000) + +/** A structure providing information and capabilities of PortAudio devices. + Devices may support input, output or both input and output. +*/ +typedef struct PaDeviceInfo +{ + int structVersion; /* this is struct version 2 */ + const char *name; + PaHostApiIndex hostApi; /* note this is a host API index, not a type id*/ + + int maxInputChannels; + int maxOutputChannels; + + /* Default latency values for interactive performance. */ + PaTime defaultLowInputLatency; + PaTime defaultLowOutputLatency; + /* Default latency values for robust non-interactive applications (eg. playing sound files). */ + PaTime defaultHighInputLatency; + PaTime defaultHighOutputLatency; + + double defaultSampleRate; +} PaDeviceInfo; + + +/** Retrieve a pointer to a PaDeviceInfo structure containing information + about the specified device. + @return A pointer to an immutable PaDeviceInfo structure. If the device + parameter is out of range the function returns NULL. + + @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1) + + @note PortAudio manages the memory referenced by the returned pointer, + the client must not manipulate or free the memory. The pointer is only + guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate(). + + @see PaDeviceInfo, PaDeviceIndex +*/ +const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device ); + + +/** Parameters for one direction (input or output) of a stream. +*/ +typedef struct PaStreamParameters +{ + /** A valid device index in the range 0 to (Pa_GetDeviceCount()-1) + specifying the device to be used or the special constant + paUseHostApiSpecificDeviceSpecification which indicates that the actual + device(s) to use are specified in hostApiSpecificStreamInfo. + This field must not be set to paNoDevice. + */ + PaDeviceIndex device; + + /** The number of channels of sound to be delivered to the + stream callback or accessed by Pa_ReadStream() or Pa_WriteStream(). + It can range from 1 to the value of maxInputChannels in the + PaDeviceInfo record for the device specified by the device parameter. + */ + int channelCount; + + /** The sample format of the buffer provided to the stream callback, + a_ReadStream() or Pa_WriteStream(). It may be any of the formats described + by the PaSampleFormat enumeration. + */ + PaSampleFormat sampleFormat; + + /** The desired latency in seconds. Where practical, implementations should + configure their latency based on these parameters, otherwise they may + choose the closest viable latency instead. Unless the suggested latency + is greater than the absolute upper limit for the device implementations + should round the suggestedLatency up to the next practial value - ie to + provide an equal or higher latency than suggestedLatency wherever possibe. + Actual latency values for an open stream may be retrieved using the + inputLatency and outputLatency fields of the PaStreamInfo structure + returned by Pa_GetStreamInfo(). + @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo + */ + PaTime suggestedLatency; + + /** An optional pointer to a host api specific data structure + containing additional information for device setup and/or stream processing. + hostApiSpecificStreamInfo is never required for correct operation, + if not used it should be set to NULL. + */ + void *hostApiSpecificStreamInfo; + +} PaStreamParameters; + + +/** Return code for Pa_IsFormatSupported indicating success. */ +#define paFormatIsSupported (0) + +/** Determine whether it would be possible to open a stream with the specified + parameters. + + @param inputParameters A structure that describes the input parameters used to + open a stream. The suggestedLatency field is ignored. See PaStreamParameters + for a description of these parameters. inputParameters must be NULL for + output-only streams. + + @param outputParameters A structure that describes the output parameters used + to open a stream. The suggestedLatency field is ignored. See PaStreamParameters + for a description of these parameters. outputParameters must be NULL for + input-only streams. + + @param sampleRate The required sampleRate. For full-duplex streams it is the + sample rate for both input and output + + @return Returns 0 if the format is supported, and an error code indicating why + the format is not supported otherwise. The constant paFormatIsSupported is + provided to compare with the return value for success. + + @see paFormatIsSupported, PaStreamParameters +*/ +PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate ); + + + +/* Streaming types and functions */ + + +/** + A single PaStream can provide multiple channels of real-time + streaming audio input and output to a client application. A stream + provides access to audio hardware represented by one or more + PaDevices. Depending on the underlying Host API, it may be possible + to open multiple streams using the same device, however this behavior + is implementation defined. Portable applications should assume that + a PaDevice may be simultaneously used by at most one PaStream. + + Pointers to PaStream objects are passed between PortAudio functions that + operate on streams. + + @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream, + Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive, + Pa_GetStreamTime, Pa_GetStreamCpuLoad + +*/ +typedef void PaStream; + + +/** Can be passed as the framesPerBuffer parameter to Pa_OpenStream() + or Pa_OpenDefaultStream() to indicate that the stream callback will + accept buffers of any size. +*/ +#define paFramesPerBufferUnspecified (0) + + +/** Flags used to control the behavior of a stream. They are passed as + parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be + ORed together. + + @see Pa_OpenStream, Pa_OpenDefaultStream + @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput, + paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags +*/ +typedef unsigned long PaStreamFlags; + +/** @see PaStreamFlags */ +#define paNoFlag ((PaStreamFlags) 0) + +/** Disable default clipping of out of range samples. + @see PaStreamFlags +*/ +#define paClipOff ((PaStreamFlags) 0x00000001) + +/** Disable default dithering. + @see PaStreamFlags +*/ +#define paDitherOff ((PaStreamFlags) 0x00000002) + +/** Flag requests that where possible a full duplex stream will not discard + overflowed input samples without calling the stream callback. This flag is + only valid for full duplex callback streams and only when used in combination + with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using + this flag incorrectly results in a paInvalidFlag error being returned from + Pa_OpenStream and Pa_OpenDefaultStream. + + @see PaStreamFlags, paFramesPerBufferUnspecified +*/ +#define paNeverDropInput ((PaStreamFlags) 0x00000004) + +/** Call the stream callback to fill initial output buffers, rather than the + default behavior of priming the buffers with zeros (silence). This flag has + no effect for input-only and blocking read/write streams. + + @see PaStreamFlags +*/ +#define paPrimeOutputBuffersUsingStreamCallback ((PaStreamFlags) 0x00000008) + +/** A mask specifying the platform specific bits. + @see PaStreamFlags +*/ +#define paPlatformSpecificFlags ((PaStreamFlags)0xFFFF0000) + +/** + Timing information for the buffers passed to the stream callback. +*/ +typedef struct PaStreamCallbackTimeInfo{ + PaTime inputBufferAdcTime; + PaTime currentTime; + PaTime outputBufferDacTime; +} PaStreamCallbackTimeInfo; + + +/** + Flag bit constants for the statusFlags to PaStreamCallback. + + @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow, + paPrimingOutput +*/ +typedef unsigned long PaStreamCallbackFlags; + +/** In a stream opened with paFramesPerBufferUnspecified, indicates that + input data is all silence (zeros) because no real data is available. In a + stream opened without paFramesPerBufferUnspecified, it indicates that one or + more zero samples have been inserted into the input buffer to compensate + for an input underflow. + @see PaStreamCallbackFlags +*/ +#define paInputUnderflow ((PaStreamCallbackFlags) 0x00000001) + +/** In a stream opened with paFramesPerBufferUnspecified, indicates that data + prior to the first sample of the input buffer was discarded due to an + overflow, possibly because the stream callback is using too much CPU time. + Otherwise indicates that data prior to one or more samples in the + input buffer was discarded. + @see PaStreamCallbackFlags +*/ +#define paInputOverflow ((PaStreamCallbackFlags) 0x00000002) + +/** Indicates that output data (or a gap) was inserted, possibly because the + stream callback is using too much CPU time. + @see PaStreamCallbackFlags +*/ +#define paOutputUnderflow ((PaStreamCallbackFlags) 0x00000004) + +/** Indicates that output data will be discarded because no room is available. + @see PaStreamCallbackFlags +*/ +#define paOutputOverflow ((PaStreamCallbackFlags) 0x00000008) + +/** Some of all of the output data will be used to prime the stream, input + data may be zero. + @see PaStreamCallbackFlags +*/ +#define paPrimingOutput ((PaStreamCallbackFlags) 0x00000010) + +/** + Allowable return values for the PaStreamCallback. + @see PaStreamCallback +*/ +typedef enum PaStreamCallbackResult +{ + paContinue=0, + paComplete=1, + paAbort=2 +} PaStreamCallbackResult; + + +/** + Functions of type PaStreamCallback are implemented by PortAudio clients. + They consume, process or generate audio in response to requests from an + active PortAudio stream. + + @param input and @param output are arrays of interleaved samples, + the format, packing and number of channels used by the buffers are + determined by parameters to Pa_OpenStream(). + + @param frameCount The number of sample frames to be processed by + the stream callback. + + @param timeInfo The time in seconds when the first sample of the input + buffer was received at the audio input, the time in seconds when the first + sample of the output buffer will begin being played at the audio output, and + the time in seconds when the stream callback was called. + See also Pa_GetStreamTime() + + @param statusFlags Flags indicating whether input and/or output buffers + have been inserted or will be dropped to overcome underflow or overflow + conditions. + + @param userData The value of a user supplied pointer passed to + Pa_OpenStream() intended for storing synthesis data etc. + + @return + The stream callback should return one of the values in the + PaStreamCallbackResult enumeration. To ensure that the callback continues + to be called, it should return paContinue (0). Either paComplete or paAbort + can be returned to finish stream processing, after either of these values is + returned the callback will not be called again. If paAbort is returned the + stream will finish as soon as possible. If paComplete is returned, the stream + will continue until all buffers generated by the callback have been played. + This may be useful in applications such as soundfile players where a specific + duration of output is required. However, it is not necessary to utilise this + mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also + be used to stop the stream. The callback must always fill the entire output + buffer irrespective of its return value. + + @see Pa_OpenStream, Pa_OpenDefaultStream + + @note With the exception of Pa_GetStreamCpuLoad() it is not permissable to call + PortAudio API functions from within the stream callback. +*/ +typedef int PaStreamCallback( + const void *input, void *output, + unsigned long frameCount, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData ); + + +/** Opens a stream for either input, output or both. + + @param stream The address of a PaStream pointer which will receive + a pointer to the newly opened stream. + + @param inputParameters A structure that describes the input parameters used by + the opened stream. See PaStreamParameters for a description of these parameters. + inputParameters must be NULL for output-only streams. + + @param outputParameters A structure that describes the output parameters used by + the opened stream. See PaStreamParameters for a description of these parameters. + outputParameters must be NULL for input-only streams. + + @param sampleRate The desired sampleRate. For full-duplex streams it is the + sample rate for both input and output + + @param framesPerBuffer The number of frames passed to the stream callback + function, or the preferred block granularity for a blocking read/write stream. + The special value paFramesPerBufferUnspecified (0) may be used to request that + the stream callback will recieve an optimal (and possibly varying) number of + frames based on host requirements and the requested latency settings. + Note: With some host APIs, the use of non-zero framesPerBuffer for a callback + stream may introduce an additional layer of buffering which could introduce + additional latency. PortAudio guarantees that the additional latency + will be kept to the theoretical minimum however, it is strongly recommended + that a non-zero framesPerBuffer value only be used when your algorithm + requires a fixed number of frames per stream callback. + + @param streamFlags Flags which modify the behaviour of the streaming process. + This parameter may contain a combination of flags ORed together. Some flags may + only be relevant to certain buffer formats. + + @param streamCallback A pointer to a client supplied function that is responsible + for processing and filling input and output buffers. If this parameter is NULL + the stream will be opened in 'blocking read/write' mode. In blocking mode, + the client can receive sample data using Pa_ReadStream and write sample data + using Pa_WriteStream, the number of samples that may be read or written + without blocking is returned by Pa_GetStreamReadAvailable and + Pa_GetStreamWriteAvailable respectively. + + @param userData A client supplied pointer which is passed to the stream callback + function. It could for example, contain a pointer to instance data necessary + for processing the audio buffers. This parameter is ignored if streamCallback + is NULL. + + @return + Upon success Pa_OpenStream() returns paNoError and places a pointer to a + valid PaStream in the stream argument. The stream is inactive (stopped). + If a call to Pa_OpenStream() fails, a non-zero error code is returned (see + PaError for possible error codes) and the value of stream is invalid. + + @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream, + Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable +*/ +PaError Pa_OpenStream( PaStream** stream, + const PaStreamParameters *inputParameters, + const PaStreamParameters *outputParameters, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamFlags streamFlags, + PaStreamCallback *streamCallback, + void *userData ); + + +/** A simplified version of Pa_OpenStream() that opens the default input + and/or output devices. + + @param stream The address of a PaStream pointer which will receive + a pointer to the newly opened stream. + + @param numInputChannels The number of channels of sound that will be supplied + to the stream callback or returned by Pa_ReadStream. It can range from 1 to + the value of maxInputChannels in the PaDeviceInfo record for the default input + device. If 0 the stream is opened as an output-only stream. + + @param numOutputChannels The number of channels of sound to be delivered to the + stream callback or passed to Pa_WriteStream. It can range from 1 to the value + of maxOutputChannels in the PaDeviceInfo record for the default output dvice. + If 0 the stream is opened as an output-only stream. + + @param sampleFormat The sample format of both the input and output buffers + provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream. + sampleFormat may be any of the formats described by the PaSampleFormat + enumeration. + + @param sampleRate Same as Pa_OpenStream parameter of the same name. + @param framesPerBuffer Same as Pa_OpenStream parameter of the same name. + @param streamCallback Same as Pa_OpenStream parameter of the same name. + @param userData Same as Pa_OpenStream parameter of the same name. + + @return As for Pa_OpenStream + + @see Pa_OpenStream, PaStreamCallback +*/ +PaError Pa_OpenDefaultStream( PaStream** stream, + int numInputChannels, + int numOutputChannels, + PaSampleFormat sampleFormat, + double sampleRate, + unsigned long framesPerBuffer, + PaStreamCallback *streamCallback, + void *userData ); + + +/** Closes an audio stream. If the audio stream is active it + discards any pending buffers as if Pa_AbortStream() had been called. +*/ +PaError Pa_CloseStream( PaStream *stream ); + + +/** Functions of type PaStreamFinishedCallback are implemented by PortAudio + clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback + function. Once registered they are called when the stream becomes inactive + (ie once a call to Pa_StopStream() will not block). + A stream will become inactive after the stream callback returns non-zero, + or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio + output, if the stream callback returns paComplete, or Pa_StopStream is called, + the stream finished callback will not be called until all generated sample data + has been played. + + @param userData The userData parameter supplied to Pa_OpenStream() + + @see Pa_SetStreamFinishedCallback +*/ +typedef void PaStreamFinishedCallback( void *userData ); + + +/** Register a stream finished callback function which will be called when the + stream becomes inactive. See the description of PaStreamFinishedCallback for + further details about when the callback will be called. + + @param stream a pointer to a PaStream that is in the stopped state - if the + stream is not stopped, the stream's finished callback will remain unchanged + and an error code will be returned. + + @param streamFinishedCallback a pointer to a function with the same signature + as PaStreamFinishedCallback, that will be called when the stream becomes + inactive. Passing NULL for this parameter will un-register a previously + registered stream finished callback function. + + @return on success returns paNoError, otherwise an error code indicating the cause + of the error. + + @see PaStreamFinishedCallback +*/ +PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback ); + + +/** Commences audio processing. +*/ +PaError Pa_StartStream( PaStream *stream ); + + +/** Terminates audio processing. It waits until all pending + audio buffers have been played before it returns. +*/ +PaError Pa_StopStream( PaStream *stream ); + + +/** Terminates audio processing immediately without waiting for pending + buffers to complete. +*/ +PaError Pa_AbortStream( PaStream *stream ); + + +/** Determine whether the stream is stopped. + A stream is considered to be stopped prior to a successful call to + Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream. + If a stream callback returns a value other than paContinue the stream is NOT + considered to be stopped. + + @return Returns one (1) when the stream is stopped, zero (0) when + the stream is running or, a PaErrorCode (which are always negative) if + PortAudio is not initialized or an error is encountered. + + @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive +*/ +PaError Pa_IsStreamStopped( PaStream *stream ); + + +/** Determine whether the stream is active. + A stream is active after a successful call to Pa_StartStream(), until it + becomes inactive either as a result of a call to Pa_StopStream() or + Pa_AbortStream(), or as a result of a return value other than paContinue from + the stream callback. In the latter case, the stream is considered inactive + after the last buffer has finished playing. + + @return Returns one (1) when the stream is active (ie playing or recording + audio), zero (0) when not playing or, a PaErrorCode (which are always negative) + if PortAudio is not initialized or an error is encountered. + + @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped +*/ +PaError Pa_IsStreamActive( PaStream *stream ); + + + +/** A structure containing unchanging information about an open stream. + @see Pa_GetStreamInfo +*/ + +typedef struct PaStreamInfo +{ + /** this is struct version 1 */ + int structVersion; + + /** The input latency of the stream in seconds. This value provides the most + accurate estimate of input latency available to the implementation. It may + differ significantly from the suggestedLatency value passed to Pa_OpenStream(). + The value of this field will be zero (0.) for output-only streams. + @see PaTime + */ + PaTime inputLatency; + + /** The output latency of the stream in seconds. This value provides the most + accurate estimate of output latency available to the implementation. It may + differ significantly from the suggestedLatency value passed to Pa_OpenStream(). + The value of this field will be zero (0.) for input-only streams. + @see PaTime + */ + PaTime outputLatency; + + /** The sample rate of the stream in Hertz (samples per second). In cases + where the hardware sample rate is inaccurate and PortAudio is aware of it, + the value of this field may be different from the sampleRate parameter + passed to Pa_OpenStream(). If information about the actual hardware sample + rate is not available, this field will have the same value as the sampleRate + parameter passed to Pa_OpenStream(). + */ + double sampleRate; + +} PaStreamInfo; + + +/** Retrieve a pointer to a PaStreamInfo structure containing information + about the specified stream. + @return A pointer to an immutable PaStreamInfo structure. If the stream + parameter invalid, or an error is encountered, the function returns NULL. + + @param stream A pointer to an open stream previously created with Pa_OpenStream. + + @note PortAudio manages the memory referenced by the returned pointer, + the client must not manipulate or free the memory. The pointer is only + guaranteed to be valid until the specified stream is closed. + + @see PaStreamInfo +*/ +const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream ); + + +/** Determine the current time for the stream according to the same clock used + to generate buffer timestamps. This time may be used for syncronising other + events to the audio stream, for example synchronizing audio to MIDI. + + @return The stream's current time in seconds, or 0 if an error occurred. + + @see PaTime, PaStreamCallback +*/ +PaTime Pa_GetStreamTime( PaStream *stream ); + + +/** Retrieve CPU usage information for the specified stream. + The "CPU Load" is a fraction of total CPU time consumed by a callback stream's + audio processing routines including, but not limited to the client supplied + stream callback. This function does not work with blocking read/write streams. + + This function may be called from the stream callback function or the + application. + + @return + A floating point value, typically between 0.0 and 1.0, where 1.0 indicates + that the stream callback is consuming the maximum number of CPU cycles possible + to maintain real-time operation. A value of 0.5 would imply that PortAudio and + the stream callback was consuming roughly 50% of the available CPU time. The + return value may exceed 1.0. A value of 0.0 will always be returned for a + blocking read/write stream, or if an error occurrs. +*/ +double Pa_GetStreamCpuLoad( PaStream* stream ); + + +/** Read samples from an input stream. The function doesn't return until + the entire buffer has been filled - this may involve waiting for the operating + system to supply the data. + + @param stream A pointer to an open stream previously created with Pa_OpenStream. + + @param buffer A pointer to a buffer of sample frames. The buffer contains + samples in the format specified by the inputParameters->sampleFormat field + used to open the stream, and the number of channels specified by + inputParameters->numChannels. If non-interleaved samples were requested, + buffer is a pointer to the first element of an array of non-interleaved + buffer pointers, one for each channel. + + @param frames The number of frames to be read into buffer. This parameter + is not constrained to a specific range, however high performance applications + will want to match this parameter to the framesPerBuffer parameter used + when opening the stream. + + @return On success PaNoError will be returned, or PaInputOverflowed if input + data was discarded by PortAudio after the previous call and before this call. +*/ +PaError Pa_ReadStream( PaStream* stream, + void *buffer, + unsigned long frames ); + + +/** Write samples to an output stream. This function doesn't return until the + entire buffer has been consumed - this may involve waiting for the operating + system to consume the data. + + @param stream A pointer to an open stream previously created with Pa_OpenStream. + + @param buffer A pointer to a buffer of sample frames. The buffer contains + samples in the format specified by the outputParameters->sampleFormat field + used to open the stream, and the number of channels specified by + outputParameters->numChannels. If non-interleaved samples were requested, + buffer is a pointer to the first element of an array of non-interleaved + buffer pointers, one for each channel. + + @param frames The number of frames to be written from buffer. This parameter + is not constrained to a specific range, however high performance applications + will want to match this parameter to the framesPerBuffer parameter used + when opening the stream. + + @return On success PaNoError will be returned, or paOutputUnderflowed if + additional output data was inserted after the previous call and before this + call. +*/ +PaError Pa_WriteStream( PaStream* stream, + const void *buffer, + unsigned long frames ); + + +/** Retrieve the number of frames that can be read from the stream without + waiting. + + @return Returns a non-negative value representing the maximum number of frames + that can be read from the stream without blocking or busy waiting or, a + PaErrorCode (which are always negative) if PortAudio is not initialized or an + error is encountered. +*/ +signed long Pa_GetStreamReadAvailable( PaStream* stream ); + + +/** Retrieve the number of frames that can be written to the stream without + waiting. + + @return Returns a non-negative value representing the maximum number of frames + that can be written to the stream without blocking or busy waiting or, a + PaErrorCode (which are always negative) if PortAudio is not initialized or an + error is encountered. +*/ +signed long Pa_GetStreamWriteAvailable( PaStream* stream ); + + +/* Miscellaneous utilities */ + + +/** Retrieve the size of a given sample format in bytes. + + @return The size in bytes of a single sample in the specified format, + or paSampleFormatNotSupported if the format is not supported. +*/ +PaError Pa_GetSampleSize( PaSampleFormat format ); + + +/** Put the caller to sleep for at least 'msec' milliseconds. This function is + provided only as a convenience for authors of portable code (such as the tests + and examples in the PortAudio distribution.) + + The function may sleep longer than requested so don't rely on this for accurate + musical timing. +*/ +void Pa_Sleep( long msec ); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* PORTAUDIO_H */ diff --git a/Plugins/voiceservice/m_voice.h b/Plugins/voiceservice/m_voice.h new file mode 100644 index 0000000..e4ea883 --- /dev/null +++ b/Plugins/voiceservice/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/voiceservice/m_voiceservice.h b/Plugins/voiceservice/m_voiceservice.h new file mode 100644 index 0000000..2d55d9a --- /dev/null +++ b/Plugins/voiceservice/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/voiceservice/options.cpp b/Plugins/voiceservice/options.cpp new file mode 100644 index 0000000..78f2de7 --- /dev/null +++ b/Plugins/voiceservice/options.cpp @@ -0,0 +1,616 @@ +/*
+Copyright (C) 2006 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"
+
+#include "options.h"
+
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+
+HANDLE hOptHook = NULL;
+
+Options opts;
+
+
+static BOOL CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK DevicesDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK PopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK AutoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+static OptPageControl optionsControls[] = {
+ { &opts.resize_frame, CONTROL_CHECKBOX, IDC_FRAME_AUTOSIZE, "FrameAutoSize", TRUE }
+};
+
+static OptPageControl devicesControls[] = {
+ { NULL, CONTROL_CHECKBOX, IDC_ECHO, "EchoCancelation", TRUE },
+ { NULL, CONTROL_CHECKBOX, IDC_MIC_BOOST, "MicBoost", TRUE },
+};
+
+static OptPageControl popupsControls[] = {
+ { &opts.popup_enable, CONTROL_CHECKBOX, IDC_POPUPS, "PopupsEnable", FALSE },
+ { &opts.popup_bkg_color, CONTROL_COLOR, IDC_BGCOLOR, "PopupsBgColor", RGB(255,255,255) },
+ { &opts.popup_text_color, CONTROL_COLOR, IDC_TEXTCOLOR, "PopupsTextColor", RGB(0,0,0) },
+ { &opts.popup_use_win_colors, CONTROL_CHECKBOX, IDC_WINCOLORS, "PopupsWinColors", FALSE },
+ { &opts.popup_use_default_colors, CONTROL_CHECKBOX, IDC_DEFAULTCOLORS, "PopupsDefaultColors", FALSE },
+ { &opts.popup_delay_type, CONTROL_RADIO, IDC_DELAYFROMPU, "PopupsDelayType", POPUP_DELAY_DEFAULT, POPUP_DELAY_DEFAULT },
+ { NULL, CONTROL_RADIO, IDC_DELAYCUSTOM, "PopupsDelayType", POPUP_DELAY_DEFAULT, POPUP_DELAY_CUSTOM },
+ { NULL, CONTROL_RADIO, IDC_DELAYPERMANENT, "PopupsDelayType", POPUP_DELAY_DEFAULT, POPUP_DELAY_PERMANENT },
+ { &opts.popup_timeout, CONTROL_SPIN, IDC_DELAY, "PopupsTimeout", 10, IDC_DELAY_SPIN, (WORD) 1, (WORD) 255 },
+ { &opts.popup_right_click_action, CONTROL_COMBO, IDC_RIGHT_ACTION, "PopupsRightClick", POPUP_ACTION_CLOSEPOPUP },
+ { &opts.popup_left_click_action, CONTROL_COMBO, IDC_LEFT_ACTION, "PopupsLeftClick", POPUP_ACTION_CLOSEPOPUP }
+};
+
+static UINT popupsExpertControls[] = {
+ IDC_COLOURS_G, IDC_BGCOLOR, IDC_BGCOLOR_L, IDC_TEXTCOLOR, IDC_TEXTCOLOR_L, IDC_WINCOLORS, IDC_DEFAULTCOLORS,
+ IDC_DELAY_G, IDC_DELAYFROMPU, IDC_DELAYCUSTOM, IDC_DELAYPERMANENT, IDC_DELAY, IDC_DELAY_SPIN,
+ IDC_ACTIONS_G, IDC_RIGHT_ACTION_L, IDC_RIGHT_ACTION, IDC_LEFT_ACTION_L, IDC_LEFT_ACTION,
+ IDC_PREV
+};
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+int InitOptionsCallback(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ if(ServiceExists(MS_POPUP_ADDPOPUPEX)
+#ifdef UNICODE
+ || ServiceExists(MS_POPUP_ADDPOPUPW)
+#endif
+ )
+ {
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.ptszGroup = LPGENT("Popups");
+ odp.ptszTitle = LPGENT("Voice Calls");
+ odp.pfnDlgProc = PopupsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_POPUPS);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.expertOnlyControls = popupsExpertControls;
+ odp.nExpertOnlyControls = MAX_REGS(popupsExpertControls);
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp);
+ }
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.ptszTitle = LPGENT("Voice Calls");
+ odp.pfnDlgProc = OptionsDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTS);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.ptszGroup = LPGENT("Voice Calls");
+ odp.ptszTitle = LPGENT("Auto actions");
+ odp.pfnDlgProc = AutoDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_AUTO);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.ptszGroup = LPGENT("Voice Calls");
+ odp.ptszTitle = LPGENT("Devices");
+ odp.pfnDlgProc = DevicesDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_DEVICES);
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp);
+
+ return 0;
+}
+
+
+void InitOptions()
+{
+ LoadOptions();
+
+ hOptHook = HookEvent(ME_OPT_INITIALISE, InitOptionsCallback);
+}
+
+
+void DeInitOptions()
+{
+ UnhookEvent(hOptHook);
+}
+
+
+void LoadOptions()
+{
+ LoadOpts(optionsControls, MAX_REGS(optionsControls), MODULE_NAME);
+ LoadOpts(popupsControls, MAX_REGS(popupsControls), MODULE_NAME);
+}
+
+
+static BOOL CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return SaveOptsDlgProc(optionsControls, MAX_REGS(optionsControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+}
+
+
+static BOOL CALLBACK DevicesDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ int defaultInput = Pa_GetDefaultInputDevice();
+ const char *defaultInputName = NULL;
+
+ int defaultOutput = Pa_GetDefaultOutputDevice();
+ const char *defaultOutputName = NULL;
+
+ int devices = Pa_GetDeviceCount();
+ for(int i = 0; i < devices; i++)
+ {
+ const PaDeviceInfo *device = Pa_GetDeviceInfo(i);
+
+ if (device->maxInputChannels > 0)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_INPUT, CB_ADDSTRING, 0, (WPARAM) CharToTchar(device->name).get());
+ if (i == defaultInput)
+ defaultInputName = device->name;
+ }
+
+ if (device->maxOutputChannels > 0)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_OUTPUT, CB_ADDSTRING, 0, (WPARAM) CharToTchar(device->name).get());
+ if (i == defaultOutput)
+ defaultOutputName = device->name;
+ }
+ }
+
+ DBVARIANT dbvInput = {0};
+ if (DBGetContactSettingString(NULL, MODULE_NAME, "Input", &dbvInput) == 0 && dbvInput.ptszVal != NULL && dbvInput.ptszVal[0] != 0)
+ defaultInputName = dbvInput.pszVal;
+
+ DBVARIANT dbvOutput = {0};
+ if (DBGetContactSettingString(NULL, MODULE_NAME, "Output", &dbvOutput) == 0 && dbvOutput.ptszVal != NULL && dbvOutput.ptszVal[0] != 0)
+ defaultOutputName = dbvOutput.pszVal;
+
+ if (defaultInputName != NULL)
+ SendDlgItemMessageA(hwndDlg, IDC_INPUT, CB_SELECTSTRING, -1, (WPARAM) defaultInputName);
+
+ if (defaultOutputName != NULL)
+ SendDlgItemMessageA(hwndDlg, IDC_OUTPUT, CB_SELECTSTRING, -1, (WPARAM) defaultOutputName);
+
+ DBFreeVariant(&dbvOutput);
+ DBFreeVariant(&dbvInput);
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam) == IDC_INPUT || LOWORD(wParam) == IDC_OUTPUT)
+ {
+ if (HIWORD(wParam) != CBN_SELCHANGE || (HWND)lParam != GetFocus())
+ return 0;
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR lpnmhdr = (LPNMHDR)lParam;
+
+ if (lpnmhdr->idFrom == 0 && lpnmhdr->code == PSN_APPLY)
+ {
+ TCHAR tmp[1024];
+
+ GetWindowText(GetDlgItem(hwndDlg, IDC_INPUT), tmp, MAX_REGS(tmp));
+ DBWriteContactSettingTString(NULL, MODULE_NAME, "Input", tmp);
+
+ GetWindowText(GetDlgItem(hwndDlg, IDC_OUTPUT), tmp, MAX_REGS(tmp));
+ DBWriteContactSettingTString(NULL, MODULE_NAME, "Output", tmp);
+ }
+ break;
+ }
+ }
+
+ return SaveOptsDlgProc(devicesControls, MAX_REGS(devicesControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+}
+
+
+static void PopupsEnableDisableCtrls(HWND hwndDlg)
+{
+ BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_POPUPS);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COLOURS_G), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY_G), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYFROMPU), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYCUSTOM), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAYPERMANENT), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ACTIONS_G), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHT_ACTION_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHT_ACTION), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LEFT_ACTION_L), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LEFT_ACTION), enabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREV), enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BGCOLOR), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS) &&
+ !IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TEXTCOLOR), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS) &&
+ !IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DEFAULTCOLORS), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WINCOLORS), enabled &&
+ !IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DELAY), enabled &&
+ IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM));
+}
+
+
+static BOOL CALLBACK PopupsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ SendDlgItemMessage(hwndDlg, IDC_RIGHT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Do nothing"));
+ SendDlgItemMessage(hwndDlg, IDC_RIGHT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Close popup"));
+
+ SendDlgItemMessage(hwndDlg, IDC_LEFT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Do nothing"));
+ SendDlgItemMessage(hwndDlg, IDC_LEFT_ACTION, CB_ADDSTRING, 0, (LONG) TranslateT("Close popup"));
+
+ // Needs to be called here in this case
+ BOOL ret = SaveOptsDlgProc(popupsControls, MAX_REGS(popupsControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+
+ PopupsEnableDisableCtrls(hwndDlg);
+
+ return ret;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_POPUPS:
+ case IDC_WINCOLORS:
+ case IDC_DEFAULTCOLORS:
+ case IDC_DELAYFROMPU:
+ case IDC_DELAYPERMANENT:
+ case IDC_DELAYCUSTOM:
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ PopupsEnableDisableCtrls(hwndDlg);
+
+ break;
+ }
+ case IDC_PREV:
+ {
+ Options op = opts;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_DELAYFROMPU))
+ op.popup_delay_type = POPUP_DELAY_DEFAULT;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYCUSTOM))
+ op.popup_delay_type = POPUP_DELAY_CUSTOM;
+ else if (IsDlgButtonChecked(hwndDlg, IDC_DELAYPERMANENT))
+ op.popup_delay_type = POPUP_DELAY_PERMANENT;
+
+ op.popup_timeout = GetDlgItemInt(hwndDlg,IDC_DELAY, NULL, FALSE);
+ op.popup_bkg_color = SendDlgItemMessage(hwndDlg,IDC_BGCOLOR,CPM_GETCOLOUR,0,0);
+ op.popup_text_color = SendDlgItemMessage(hwndDlg,IDC_TEXTCOLOR,CPM_GETCOLOUR,0,0);
+ op.popup_use_win_colors = IsDlgButtonChecked(hwndDlg, IDC_WINCOLORS) != 0;
+ op.popup_use_default_colors = IsDlgButtonChecked(hwndDlg, IDC_DEFAULTCOLORS) != 0;
+
+ ShowTestPopup(TranslateT("Test Contact"), TranslateT("Test description"), &op);
+
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return SaveOptsDlgProc(popupsControls, MAX_REGS(popupsControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+}
+
+
+static void SetAllContactIcons(HWND hwndList)
+{
+ HANDLE hContact,hItem;
+
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ do
+ {
+ hItem=(HANDLE)SendMessage(hwndList,CLM_FINDCONTACT,(WPARAM)hContact,0);
+ if(hItem)
+ {
+ // Some Module can handle it?
+ if (!CanCall(hContact, FALSE))
+ {
+ SendMessage(hwndList,CLM_DELETEITEM,(WPARAM)hItem,0);
+ }
+ else
+ {
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0,
+ DBGetContactSettingWord(hContact, MODULE_NAME, "AutoAccept", AUTO_NOTHING) == AUTO_ACCEPT ? 1 : 0));
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(1,
+ DBGetContactSettingWord(hContact, MODULE_NAME, "AutoAccept", AUTO_NOTHING) == AUTO_DROP ? 2 : 0));
+ }
+ }
+ } while(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0));
+}
+
+
+static void SetListGroupIcons(HWND hwndList,HANDLE hFirstItem,HANDLE hParentItem,int *groupChildCount)
+{
+ int typeOfFirst;
+ int iconOn[2]={1,1};
+ int childCount[2]={0,0},i;
+ int iImage;
+ HANDLE hItem,hChildItem;
+
+ typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0);
+ //check groups
+ if(typeOfFirst==CLCIT_GROUP) hItem=hFirstItem;
+ else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem);
+ while(hItem) {
+ hChildItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if(hChildItem) SetListGroupIcons(hwndList,hChildItem,hItem,childCount);
+ for( i=0; i < MAX_REGS(iconOn); i++)
+ if(iconOn[i] && SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,i)==0) iconOn[i]=0;
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ //check contacts
+ if(typeOfFirst==CLCIT_CONTACT) hItem=hFirstItem;
+ else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem);
+ while(hItem) {
+ for ( i=0; i < MAX_REGS(iconOn); i++) {
+ iImage=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,i);
+ if(iconOn[i] && iImage==0) iconOn[i]=0;
+ if(iImage!=0xFF) childCount[i]++;
+ }
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem);
+ }
+ //set icons
+ if (hParentItem != NULL) {
+ for( i=0; i < MAX_REGS(iconOn); i++) {
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hParentItem,MAKELPARAM(i,childCount[i]?(iconOn[i]?i+1:0):0xFF));
+ if(groupChildCount) groupChildCount[i]+=childCount[i];
+ }
+ }
+}
+
+
+static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage)
+{
+ int typeOfFirst,iOldIcon;
+ HANDLE hItem,hChildItem;
+
+ typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0);
+ //check groups
+ if(typeOfFirst==CLCIT_GROUP) hItem=hFirstItem;
+ else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem);
+ while(hItem) {
+ hChildItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if(hChildItem) SetAllChildIcons(hwndList,hChildItem,iColumn,iImage);
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ //check contacts
+ if(typeOfFirst==CLCIT_CONTACT) hItem=hFirstItem;
+ else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem);
+ while(hItem) {
+ iOldIcon=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if(iOldIcon!=0xFF && iOldIcon!=iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem);
+ }
+}
+
+
+static void ResetListOptions(HWND hwndList)
+{
+ SendMessage(hwndList,CLM_SETBKBITMAP, 0, 0);
+ SendMessage(hwndList,CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(hwndList,CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(hwndList,CLM_SETLEFTMARGIN, 2, 0);
+ SendMessage(hwndList,CLM_SETINDENT, 10, 0);
+
+ for(int i=0;i<=FONTID_MAX;i++)
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+
+// SetWindowLong(hwndList,GWL_STYLE,GetWindowLong(hwndList,GWL_STYLE)|CLS_SHOWHIDDEN|CLS_NOHIDEOFFLINE|CLS_GREYALTERNATE);
+}
+
+
+int ImageList_AddIcon_NotShared(HIMAGELIST hIml, HINSTANCE hInstance, LPCTSTR szResource)
+{
+ HICON hIcon = LoadIcon(hInstance, szResource);
+ int res = ImageList_AddIcon(hIml, hIcon);
+ DestroyIcon(hIcon);
+ return res;
+}
+
+
+int ImageList_AddIcon_NotShared(HIMAGELIST hIml, char *iconName)
+{
+ HICON hIcon = IcoLib_LoadIcon(iconName);
+ int res = ImageList_AddIcon(hIml, hIcon);
+ IcoLib_ReleaseIcon(hIcon);
+ return res;
+}
+
+
+static BOOL CALLBACK AutoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HICON hAnswerIcon, hDropIcon;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ {
+ HIMAGELIST hIml = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),
+ (IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,3,3);
+
+ ImageList_AddIcon_NotShared(hIml, GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SMALLDOT));
+ ImageList_AddIcon_NotShared(hIml, actionIcons[ACTION_ANSWER]);
+ ImageList_AddIcon_NotShared(hIml, actionIcons[ACTION_DROP]);
+ SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_SETEXTRAIMAGELIST,0,(LPARAM)hIml);
+
+ hAnswerIcon=ImageList_GetIcon(hIml,1,ILD_NORMAL);
+ SendDlgItemMessage(hwndDlg,IDC_ANSWER,STM_SETICON,(WPARAM)hAnswerIcon,0);
+
+ hDropIcon=ImageList_GetIcon(hIml,2,ILD_NORMAL);
+ SendDlgItemMessage(hwndDlg,IDC_DROP,STM_SETICON,(WPARAM)hDropIcon,0);
+ }
+
+ ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST));
+ SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_SETEXTRACOLUMNS,2,0);
+
+ SetAllContactIcons(GetDlgItem(hwndDlg,IDC_LIST));
+ SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),NULL,NULL);
+ return TRUE;
+ }
+ case WM_SETFOCUS:
+ SetFocus(GetDlgItem(hwndDlg,IDC_LIST));
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_LIST:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ SetAllContactIcons(GetDlgItem(hwndDlg,IDC_LIST));
+ //fall through
+
+ case CLN_CONTACTMOVED:
+ SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),NULL,NULL);
+ break;
+
+ case CLN_OPTIONSCHANGED:
+ ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST));
+ break;
+
+ case NM_CLICK:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam;
+ DWORD hitFlags;
+ int iImage;
+ int itemType;
+
+ // Make sure we have an extra column
+ if (nm->iColumn == -1)
+ break;
+
+ // Find clicked item
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x,nm->pt.y));
+ // Nothing was clicked
+ if (hItem == NULL) break;
+ // It was not a visbility icon
+ if (!(hitFlags & CLCHT_ONITEMEXTRA)) break;
+
+ // Get image in clicked column (0=none, 1=visible, 2=invisible)
+ iImage = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, 0));
+ if (iImage == 0)
+ iImage=nm->iColumn + 1;
+ else
+ if (iImage == 1 || iImage == 2)
+ iImage = 0;
+
+ // Get item type (contact, group, etc...)
+ itemType = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE, (WPARAM)hItem, 0);
+
+ // Update list, making sure that the options are mutually exclusive
+ if (itemType == CLCIT_CONTACT) { // A contact
+ SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, iImage));
+ if (iImage && SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn?0:1,0))!=0xFF)
+ SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn?0:1, 0));
+ }
+ else if (itemType == CLCIT_GROUP) { // A group
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if (hItem) {
+ SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn, iImage);
+ if (iImage)
+ SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn?0:1, 0);
+ }
+ }
+ // Update the all/none icons
+ SetListGroupIcons(GetDlgItem(hwndDlg, IDC_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), NULL, NULL);
+
+ // Activate Apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ HANDLE hContact,hItem;
+ int set,i,iImage;
+
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ do {
+ hItem=(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_FINDCONTACT,(WPARAM)hContact,0);
+ if(hItem)
+ {
+ set=0;
+ for(i=0;i<2;i++) {
+ iImage=SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(i,0));
+ if(iImage==i+1) {
+ DBWriteContactSettingWord(hContact, MODULE_NAME, "AutoAccept", iImage==1 ? AUTO_ACCEPT : AUTO_DROP);
+ set=1;
+ break;
+ }
+ }
+ if(!set) DBWriteContactSettingWord(hContact, MODULE_NAME, "AutoAccept", AUTO_NOTHING);
+ }
+ } while(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0));
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ case WM_DESTROY:
+ DestroyIcon(hAnswerIcon);
+ DestroyIcon(hDropIcon);
+ {
+ HIMAGELIST hIml=(HIMAGELIST)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETEXTRAIMAGELIST,0,0);
+ ImageList_Destroy(hIml);
+ }
+ break;
+ }
+ return FALSE;
+
+}
\ No newline at end of file diff --git a/Plugins/voiceservice/options.h b/Plugins/voiceservice/options.h new file mode 100644 index 0000000..ff5d649 --- /dev/null +++ b/Plugins/voiceservice/options.h @@ -0,0 +1,67 @@ +/*
+Copyright (C) 2006 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 __OPTIONS_H__
+# define __OPTIONS_H__
+
+
+#include <windows.h>
+
+#define POPUP_ACTION_DONOTHING 0
+#define POPUP_ACTION_CLOSEPOPUP 1
+
+#define POPUP_DELAY_DEFAULT 0
+#define POPUP_DELAY_CUSTOM 1
+#define POPUP_DELAY_PERMANENT 2
+
+
+struct Options {
+ // Popup
+ BYTE popup_enable;
+ WORD popup_delay_type;
+ WORD popup_timeout;
+ BYTE popup_use_win_colors;
+ BYTE popup_use_default_colors;
+ COLORREF popup_bkg_color;
+ COLORREF popup_text_color;
+ WORD popup_left_click_action;
+ WORD popup_right_click_action;
+
+ // Frame
+ BOOL resize_frame;
+};
+
+extern Options opts;
+
+
+// Initializations needed by options
+void InitOptions();
+
+// Deinitializations needed by options
+void DeInitOptions();
+
+
+// Loads the options from DB
+// It don't need to be called, except in some rare cases
+void LoadOptions();
+
+
+
+#endif // __OPTIONS_H__
diff --git a/Plugins/voiceservice/popup.cpp b/Plugins/voiceservice/popup.cpp new file mode 100644 index 0000000..45d06f6 --- /dev/null +++ b/Plugins/voiceservice/popup.cpp @@ -0,0 +1,340 @@ +/*
+Copyright (C) 2005 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"
+
+#include <stdarg.h>
+
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+#define WMU_ACTION (WM_USER + 1)
+
+
+LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+HWND hPopupWindow = NULL;
+
+
+static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+
+// Initializations needed by popups
+void InitPopups()
+{
+ // window needed for popup commands
+ hPopupWindow = CreateWindowEx(WS_EX_TOOLWINDOW, _T("static"), _T(MODULE_NAME) _T("_PopupWindow"),
+ 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP,
+ NULL, hInst, NULL);
+ SetWindowLong(hPopupWindow, GWL_WNDPROC, (LONG)(WNDPROC)PopupWndProc);
+}
+
+
+// Deinitializations needed by popups
+void DeInitPopups()
+{
+}
+
+
+// Show an error popup
+void ShowErrPopup(const TCHAR *description, const TCHAR *title)
+{
+ ShowPopupEx(NULL, title == NULL ? _T(MODULE_NAME) _T(" Error") : title, description,
+ NULL, POPUP_TYPE_ERROR, NULL);
+}
+
+
+void ShowTestPopup(const TCHAR *title, const TCHAR *description, const Options *op)
+{
+ ShowPopupEx(NULL, title, description, NULL, POPUP_TYPE_TEST, op);
+}
+
+
+void ShowPopup(HANDLE hContact, const TCHAR *title, const TCHAR *description, ...)
+{
+ if (!opts.popup_enable)
+ return;
+
+ TCHAR text[1024];
+
+ va_list va;
+ va_start(va, description);
+ _vsntprintf(text, MAX_REGS(text), description, va);
+ va_end(va);
+
+
+ ShowPopupEx(hContact, title, text, hContact, POPUP_TYPE_NORMAL, &opts);
+}
+
+
+// Show an popup
+void ShowPopupEx(HANDLE hContact, const TCHAR *title, const TCHAR *description,
+ void *plugin_data, int type, const Options *op)
+{
+#ifdef UNICODE
+ if(ServiceExists(MS_POPUP_ADDPOPUPW))
+ {
+ // Make popup
+ POPUPDATAW ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = hContact;
+ ppd.lchIcon = (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(174),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
+
+ if (title != NULL)
+ lstrcpyn(ppd.lpwzContactName, title, MAX_REGS(ppd.lpwzContactName));
+ else if (hContact != NULL)
+ lstrcpyn(ppd.lpwzContactName, (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR),
+ MAX_REGS(ppd.lpwzContactName));
+
+ if (description != NULL)
+ lstrcpyn(ppd.lpwzText, description, MAX_REGS(ppd.lpwzText));
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ if (op->popup_use_default_colors)
+ {
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ }
+ else if (op->popup_use_win_colors)
+ {
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ else
+ {
+ ppd.colorBack = op->popup_bkg_color;
+ ppd.colorText = op->popup_text_color;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.colorBack = RGB(200,0,0);
+ ppd.colorText = RGB(255,255,255);
+ }
+
+ if (type == POPUP_TYPE_NORMAL)
+ {
+ ppd.PluginWindowProc = PopupDlgProc;
+ ppd.PluginData = plugin_data;
+ }
+ else // if (type == POPUP_TYPE_TEST || type == POPUP_TYPE_ERROR)
+ {
+ ppd.PluginWindowProc = DumbPopupDlgProc;
+ }
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ switch (op->popup_delay_type)
+ {
+ case POPUP_DELAY_CUSTOM:
+ ppd.iSeconds = opts.popup_timeout;
+ break;
+
+ case POPUP_DELAY_PERMANENT:
+ ppd.iSeconds = -1;
+ break;
+
+ //case POPUP_DELAY_DEFAULT:
+ default:
+ ppd.iSeconds = 0;
+ break;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.iSeconds = 0;
+ }
+
+ // Now that every field has been filled, we want to see the popup.
+ CallService(MS_POPUP_ADDPOPUPW, (WPARAM)&ppd,0);
+ }
+ else
+#endif
+ if(ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ // Make popup
+ POPUPDATAEX ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = hContact;
+ ppd.lchIcon = (HICON) LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(174),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
+
+ if (title != NULL)
+#ifdef UNICODE
+ mir_snprintf(ppd.lpzContactName, MAX_REGS(ppd.lpzContactName), "%S", title);
+#else
+ lstrcpynA(ppd.lpzContactName, title, MAX_REGS(ppd.lpzContactName));
+#endif
+ else
+ lstrcpynA(ppd.lpzContactName, (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0),
+ MAX_REGS(ppd.lpzContactName));
+
+ if (description != NULL)
+#ifdef UNICODE
+ mir_snprintf(ppd.lpzText, MAX_REGS(ppd.lpzText), "%S", description);
+#else
+ lstrcpynA(ppd.lpzText, description, MAX_REGS(ppd.lpzText));
+#endif
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ if (op->popup_use_default_colors)
+ {
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ }
+ else if (op->popup_use_win_colors)
+ {
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);
+ ppd.colorText = GetSysColor(COLOR_WINDOWTEXT);
+ }
+ else
+ {
+ ppd.colorBack = op->popup_bkg_color;
+ ppd.colorText = op->popup_text_color;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.colorBack = RGB(200,0,0);
+ ppd.colorText = RGB(255,255,255);
+ }
+
+ if (type == POPUP_TYPE_NORMAL)
+ {
+ ppd.PluginWindowProc = PopupDlgProc;
+ ppd.PluginData = plugin_data;
+ }
+ else // if (type == POPUP_TYPE_TEST || type == POPUP_TYPE_ERROR)
+ {
+ ppd.PluginWindowProc = DumbPopupDlgProc;
+ }
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ switch (op->popup_delay_type)
+ {
+ case POPUP_DELAY_CUSTOM:
+ ppd.iSeconds = opts.popup_timeout;
+ break;
+
+ case POPUP_DELAY_PERMANENT:
+ ppd.iSeconds = -1;
+ break;
+
+ case POPUP_DELAY_DEFAULT:
+ default:
+ ppd.iSeconds = 0;
+ break;
+ }
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.iSeconds = 0;
+ }
+
+ // Now that every field has been filled, we want to see the popup.
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd,0);
+ }
+}
+
+
+// Handle to the hidden windows to handle actions for popup clicks
+// wParam has the number of MOTD in case of WMU_SHOW_MOTD_DETAILS
+LRESULT CALLBACK PopupWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WMU_ACTION)
+ {
+// if (lParam == POPUP_ACTION_OPENHISTORY)
+// {
+// CallService(MS_HISTORY_SHOWCONTACTHISTORY, wParam, 0);
+// }
+ }
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+}
+
+
+// Handle to popup events
+static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ {
+ SendMessage(hPopupWindow, WMU_ACTION, (WPARAM)PUGetPluginData(hWnd), opts.popup_left_click_action);
+
+ if (opts.popup_left_click_action != POPUP_ACTION_DONOTHING)
+ PUDeletePopUp(hWnd);
+
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ SendMessage(hPopupWindow, WMU_ACTION, (WPARAM)PUGetPluginData(hWnd), opts.popup_right_click_action);
+
+ if (opts.popup_right_click_action != POPUP_ACTION_DONOTHING)
+ PUDeletePopUp(hWnd);
+
+ return TRUE;
+ }
+
+ case UM_FREEPLUGINDATA:
+ {
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+
+// Handle to popup events
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ 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);
+}
+
diff --git a/Plugins/voiceservice/popup.h b/Plugins/voiceservice/popup.h new file mode 100644 index 0000000..91de52a --- /dev/null +++ b/Plugins/voiceservice/popup.h @@ -0,0 +1,49 @@ +/*
+Copyright (C) 2005 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 __POPUP_H__
+# define __POPUP_H__
+
+// Initializations needed by popups
+void InitPopups();
+
+// Deinitializations needed by popups
+void DeInitPopups();
+
+
+#define POPUP_TYPE_NORMAL 0
+#define POPUP_TYPE_TEST 1
+#define POPUP_TYPE_ERROR 2
+
+// Show an popup
+void ShowPopup(HANDLE hContact, const TCHAR *title, const TCHAR *description, ...);
+
+// Show an test
+void ShowTestPopup(const TCHAR *title, const TCHAR *description, const Options *op);
+
+// Show an error popup
+void ShowErrPopup(const char *description, const char *title = NULL);
+
+void ShowPopupEx(HANDLE hContact, const TCHAR *title, const TCHAR *description,
+ void *plugin_data, int type, const Options *op);
+
+
+
+#endif // __POPUP_H__
diff --git a/Plugins/voiceservice/res/Answer.ico b/Plugins/voiceservice/res/Answer.ico Binary files differnew file mode 100644 index 0000000..1f1c4ee --- /dev/null +++ b/Plugins/voiceservice/res/Answer.ico diff --git a/Plugins/voiceservice/res/Busy.ico b/Plugins/voiceservice/res/Busy.ico Binary files differnew file mode 100644 index 0000000..397ecb2 --- /dev/null +++ b/Plugins/voiceservice/res/Busy.ico diff --git a/Plugins/voiceservice/res/Call.ico b/Plugins/voiceservice/res/Call.ico Binary files differnew file mode 100644 index 0000000..6559874 --- /dev/null +++ b/Plugins/voiceservice/res/Call.ico diff --git a/Plugins/voiceservice/res/Calling.ico b/Plugins/voiceservice/res/Calling.ico Binary files differnew file mode 100644 index 0000000..6559874 --- /dev/null +++ b/Plugins/voiceservice/res/Calling.ico diff --git a/Plugins/voiceservice/res/Drop.ico b/Plugins/voiceservice/res/Drop.ico Binary files differnew file mode 100644 index 0000000..48cfa14 --- /dev/null +++ b/Plugins/voiceservice/res/Drop.ico diff --git a/Plugins/voiceservice/res/Hold.ico b/Plugins/voiceservice/res/Hold.ico Binary files differnew file mode 100644 index 0000000..b789a7b --- /dev/null +++ b/Plugins/voiceservice/res/Hold.ico diff --git a/Plugins/voiceservice/res/Main.ico b/Plugins/voiceservice/res/Main.ico Binary files differnew file mode 100644 index 0000000..952d87e --- /dev/null +++ b/Plugins/voiceservice/res/Main.ico diff --git a/Plugins/voiceservice/res/On hold.ico b/Plugins/voiceservice/res/On hold.ico Binary files differnew file mode 100644 index 0000000..357bf07 --- /dev/null +++ b/Plugins/voiceservice/res/On hold.ico diff --git a/Plugins/voiceservice/res/Rinning.ico b/Plugins/voiceservice/res/Rinning.ico Binary files differnew file mode 100644 index 0000000..0f2a5b5 --- /dev/null +++ b/Plugins/voiceservice/res/Rinning.ico diff --git a/Plugins/voiceservice/res/Talking.ico b/Plugins/voiceservice/res/Talking.ico Binary files differnew file mode 100644 index 0000000..b73bc5d --- /dev/null +++ b/Plugins/voiceservice/res/Talking.ico diff --git a/Plugins/voiceservice/res/dialpad.ico b/Plugins/voiceservice/res/dialpad.ico Binary files differnew file mode 100644 index 0000000..45258ed --- /dev/null +++ b/Plugins/voiceservice/res/dialpad.ico diff --git a/Plugins/voiceservice/res/ended.ico b/Plugins/voiceservice/res/ended.ico Binary files differnew file mode 100644 index 0000000..397ecb2 --- /dev/null +++ b/Plugins/voiceservice/res/ended.ico diff --git a/Plugins/voiceservice/res/secure.ico b/Plugins/voiceservice/res/secure.ico Binary files differnew file mode 100644 index 0000000..7386501 --- /dev/null +++ b/Plugins/voiceservice/res/secure.ico diff --git a/Plugins/voiceservice/res/smalldot.ico b/Plugins/voiceservice/res/smalldot.ico Binary files differnew file mode 100644 index 0000000..47f0556 --- /dev/null +++ b/Plugins/voiceservice/res/smalldot.ico diff --git a/Plugins/voiceservice/resource.h b/Plugins/voiceservice/resource.h new file mode 100644 index 0000000..cfdbccb --- /dev/null +++ b/Plugins/voiceservice/resource.h @@ -0,0 +1,87 @@ +//{{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 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_3 1014
+#define IDC_4 1015
+#define IDC_5 1016
+#define IDC_6 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 115
+#define _APS_NEXT_COMMAND_VALUE 40004
+#define _APS_NEXT_CONTROL_VALUE 1013
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Plugins/voiceservice/resource.rc b/Plugins/voiceservice/resource.rc new file mode 100644 index 0000000..83f3435 --- /dev/null +++ b/Plugins/voiceservice/resource.rc @@ -0,0 +1,290 @@ +//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_CALLS DIALOGEX 0, 0, 195, 225
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LISTBOX IDC_CALLS,0,0,195,126,LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | NOT
+ WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_DIALPAD,"MButtonClass",0x0,0,126,20,14,
+ 0x18000000L
+ EDITTEXT IDC_NUMBER,20,126,155,14,ES_AUTOHSCROLL
+ CONTROL "",IDC_CALL,"MButtonClass",0x0,175,126,20,14,0x18000000L
+ PUSHBUTTON "1",IDC_1,67,143,18,18
+ PUSHBUTTON "2",IDC_2,87,143,18,18
+ PUSHBUTTON "3",IDC_3,107,143,18,18
+ PUSHBUTTON "4",IDC_4,67,163,18,18
+ PUSHBUTTON "5",IDC_5,87,163,18,18
+ PUSHBUTTON "6",IDC_6,107,163,18,18
+ PUSHBUTTON "7",IDC_7,67,183,18,18
+ PUSHBUTTON "8",IDC_8,87,183,18,18
+ PUSHBUTTON "9",IDC_9,107,183,18,18
+ PUSHBUTTON "*",IDC_AST,67,203,18,18
+ PUSHBUTTON "0",IDC_0,87,203,18,18
+ PUSHBUTTON "#",IDC_SHARP,107,203,18,18
+END
+
+IDD_POPUPS DIALOGEX 0, 0, 314, 240
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Enable popups",IDC_POPUPS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,3,3,308,12
+ GROUPBOX " Colours ",IDC_COLOURS_G,3,25,158,75
+ CONTROL "",IDC_BGCOLOR,"ColourPicker",WS_TABSTOP,11,37,35,14
+ LTEXT "Background colour",IDC_BGCOLOR_L,55,41,66,8
+ CONTROL "",IDC_TEXTCOLOR,"ColourPicker",WS_TABSTOP,11,55,35,14
+ LTEXT "Text colour",IDC_TEXTCOLOR_L,55,59,66,8
+ CONTROL "Use Windows colours",IDC_WINCOLORS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,11,74,108,10
+ CONTROL "Use default colours",IDC_DEFAULTCOLORS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,11,84,107,10
+ GROUPBOX " Delay ",IDC_DELAY_G,166,25,145,75
+ CONTROL "From popup plugin",IDC_DELAYFROMPU,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,175,38,122,10
+ CONTROL "Custom",IDC_DELAYCUSTOM,"Button",BS_AUTORADIOBUTTON,175,
+ 52,54,10
+ CONTROL "Permanent",IDC_DELAYPERMANENT,"Button",
+ BS_AUTORADIOBUTTON,175,66,122,10
+ EDITTEXT IDC_DELAY,233,50,31,14,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_DELAY_SPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS |
+ UDS_HOTTRACK,268,51,11,11
+ GROUPBOX " Actions ",IDC_ACTIONS_G,3,103,308,47
+ RTEXT "On right click:",IDC_RIGHT_ACTION_L,13,118,62,9
+ COMBOBOX IDC_RIGHT_ACTION,83,116,156,60,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ RTEXT "On left click:",IDC_LEFT_ACTION_L,13,132,62,9
+ COMBOBOX IDC_LEFT_ACTION,83,132,156,60,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Preview",IDC_PREV,131,161,50,14
+END
+
+IDD_NEW_CALL DIALOG DISCARDABLE 0, 0, 229, 87
+STYLE DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "New Voice Call"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CTEXT "%s wants to start a voice call with you. What you want to do?\n\nIf you answer the call, the current call will be put on hold.",
+ IDC_TEXT,7,7,215,36
+ DEFPUSHBUTTON "Answer",ID_ANSWER,58,47,50,14
+ PUSHBUTTON "Drop",ID_DROP,121,47,50,14
+ CONTROL "From now on, repeat this action for this contact",
+ IDC_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,67,215,
+ 12
+END
+
+IDD_OPTS DIALOGEX 0, 0, 233, 41
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Frame",IDC_STATIC,3,3,227,30
+ CONTROL "Auto-size frame",IDC_FRAME_AUTOSIZE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,11,15,214,12
+END
+
+IDD_OPT_AUTO DIALOGEX 0, 0, 313, 240
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Automatic Actions",IDC_STATIC,0,0,313,240
+ CONTROL "",IDC_LIST,"CListControl",WS_TABSTOP | 0x1f0,8,14,297,
+ 183,WS_EX_CLIENTEDGE
+ ICON IDI_ACTION_ANSWER,IDC_ANSWER,8,204,20,20
+ LTEXT "Auto accept this contact calls",IDC_STATIC,26,205,279,8,
+ SS_NOPREFIX | SS_CENTERIMAGE
+ ICON IDI_ACTION_DROP,IDC_DROP,8,219,20,20
+ LTEXT "Auto drop this contacts calls",IDC_STATIC,26,220,279,8,
+ SS_NOPREFIX | SS_CENTERIMAGE
+END
+
+IDD_OPT_DEVICES DIALOGEX 0, 0, 295, 221
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Audio",IDC_STATIC,3,3,289,78
+ LTEXT "Input:",IDC_STATIC,11,16,42,12
+ COMBOBOX IDC_INPUT,58,15,228,13,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Output:",IDC_STATIC,11,33,42,12
+ COMBOBOX IDC_OUTPUT,58,32,228,13,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ CONTROL "Echo cancelation",IDC_ECHO,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,11,49,275,12
+ CONTROL "Microphone boost",IDC_MIC_BOOST,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,11,64,275,12
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_POPUPS, DIALOG
+ BEGIN
+ LEFTMARGIN, 3
+ RIGHTMARGIN, 311
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 237
+ END
+
+ IDD_NEW_CALL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 222
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 80
+ END
+
+ IDD_OPTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 3
+ RIGHTMARGIN, 230
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 38
+ END
+
+ IDD_OPT_AUTO, DIALOG
+ BEGIN
+ VERTGUIDE, 8
+ VERTGUIDE, 305
+ END
+
+ IDD_OPT_DEVICES, DIALOG
+ BEGIN
+ LEFTMARGIN, 3
+ RIGHTMARGIN, 292
+ TOPMARGIN, 3
+ BOTTOMMARGIN, 218
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENUS MENU DISCARDABLE
+BEGIN
+ POPUP "Frame Popup"
+ BEGIN
+ MENUITEM "Answer call", ID_FRAMEPOPUP_ANSWERCALL
+ MENUITEM "Drop call", ID_FRAMEPOPUP_DROPCALL
+ MENUITEM "Hold call", ID_FRAMEPOPUP_HOLDCALL
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_TALKING ICON DISCARDABLE "res\\Talking.ico"
+IDI_RINGING ICON DISCARDABLE "res\\Rinning.ico"
+IDI_ENDED ICON DISCARDABLE "res\\ended.ico"
+IDI_BUSY ICON DISCARDABLE "res\\Busy.ico"
+IDI_ON_HOLD ICON DISCARDABLE "res\\On hold.ico"
+IDI_ACTION_CALL ICON DISCARDABLE "res\\Call.ico"
+IDI_ACTION_ANSWER ICON DISCARDABLE "res\\Answer.ico"
+IDI_ACTION_HOLD ICON DISCARDABLE "res\\Hold.ico"
+IDI_ACTION_DROP ICON DISCARDABLE "res\\Drop.ico"
+IDI_MAIN ICON DISCARDABLE "res\\Main.ico"
+IDI_CALLING ICON DISCARDABLE "res\\Calling.ico"
+IDI_DIALPAD ICON DISCARDABLE "res\\dialpad.ico"
+IDI_SMALLDOT ICON DISCARDABLE "res/smalldot.ico"
+IDI_SECURE ICON DISCARDABLE "res\\secure.ico"
+#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/voiceservice/sdk/m_cluiframes.h b/Plugins/voiceservice/sdk/m_cluiframes.h new file mode 100644 index 0000000..1d6cd4b --- /dev/null +++ b/Plugins/voiceservice/sdk/m_cluiframes.h @@ -0,0 +1,254 @@ +/*
+Miranda ICQ: the free icq client for MS Windows
+Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+///#include "commonheaders.h"
+//#pragma hdrstop
+
+////////////////////////////////////
+//Extra Image Column Support +0.5.0.0
+
+//Extra columns type.
+//column arranged in this way
+//
+// [statusicon] ContactName [WEB][ADV1][ADV2][SMS][EMAIL][PROTO][CLIENT]
+//
+#define EXTRA_ICON_EMAIL 1
+#define EXTRA_ICON_PROTO 2
+#define EXTRA_ICON_SMS 3
+#define EXTRA_ICON_ADV1 4
+#define EXTRA_ICON_ADV2 5
+#define EXTRA_ICON_WEB 6
+#define EXTRA_ICON_CLIENT 7
+#define EXTRA_ICON_VISMODE 8
+#define EXTRA_ICON_ADV3 9
+#define EXTRA_ICON_ADV4 10
+
+#define EXTRA_ICON_COUNT 10
+
+typedef struct
+{
+int cbSize; //must be sizeof(IconExtraColumn)
+int ColumnType;
+HANDLE hImage; //return value from MS_CLIST_EXTRA_ADD_ICON
+}IconExtraColumn,*pIconExtraColumn;
+
+
+//Set icon for contact at needed column
+//wparam=hContact
+//lparam=pIconExtraColumn
+//return 0 on success,-1 on failure
+//
+//See above for supported columns
+#define MS_CLIST_EXTRA_SET_ICON "CListFrames/SetIconForExraColumn"
+
+//Adding icon to extra image list.
+//Call this in ME_CLIST_EXTRA_LIST_REBUILD event
+//
+//wparam=hIcon
+//lparam=0
+//return hImage on success,-1 on failure
+#define MS_CLIST_EXTRA_ADD_ICON "CListFrames/AddIconToExtraImageList"
+
+
+
+#define ME_CLIST_EXTRA_LIST_REBUILD "CListFrames/OnExtraListRebuild"
+
+//called with wparam=hContact
+#define ME_CLIST_EXTRA_IMAGE_APPLY "CListFrames/OnExtraImageApply"
+
+
+///////////////////////////////////
+
+
+
+
+//
+//want show tooltip for statusbar
+//wparam=(char *)protocolname
+//lparam=0
+#define ME_CLIST_FRAMES_SB_SHOW_TOOLTIP "CListFrames/StatusBarShowToolTip"
+
+
+//want hide tooltip for statusbar
+//wparam=lparam=0
+
+#define ME_CLIST_FRAMES_SB_HIDE_TOOLTIP "CListFrames/StatusBarHideToolTip"
+
+//
+
+
+
+//adds a frame window
+//wParam=(CLISTFrame*)
+//lParam=0
+//returns an integer, the frame id.
+typedef struct tagCLISTFrame {
+ DWORD cbSize;
+ HWND hWnd ;
+ HICON hIcon;
+ int align; //al flags below
+ int height;
+ int Flags; //F_flags below
+ char *name; //frame window name,will be shown in menu
+ char *TBname; //titlebar caption
+ //COLORREF TBBackColour; //titlebar background colour
+} CLISTFrame;
+#define F_VISIBLE 1 //Frame visible
+#define F_SHOWTB 2 //Show TitleBar
+#define F_UNCOLLAPSED 4 //UnCollapse frame
+#define F_LOCKED 8 //Lock Frame
+#define F_NOBORDER 16 //Dont apply WS_BORDER style for window
+#define F_SHOWTBTIP 32 //Show titlebar tooltip
+#define F_NO_SUBCONTAINER 1024 //Support skining no subcontainer needed
+
+
+// frame alignment
+#define alTop 0x00000001
+#define alBottom 0x00000002
+#define alClient 0x00000004 //only one alClient frame
+#define MS_CLIST_FRAMES_ADDFRAME "CListFrames/AddFrame"
+
+#define MS_CLIST_FRAMES_REMOVEFRAME "CListFrames/RemoveFrame"
+
+//shows all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHOWALLFRAMES "CListFrames/ShowALLFrames"
+
+//shows the titlebars of all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHOWALLFRAMESTB "CListFrames/ShowALLFramesTB"
+
+//hides the titlebars of all frames
+//wParam=lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_HIDEALLFRAMESTB "CListFrames/HideALLFramesTB"
+
+//shows the frame if it is hidden,
+//hides the frame if it is shown
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHFRAME "CListFrames/SHFrame"
+
+//shows the frame titlebar if it is hidden,
+//hides the frame titlebar if it is shown
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SHFRAMETITLEBAR "CListFrame/SHFrameTitleBar"
+
+//locks the frame if it is unlocked,
+//unlock the frame if it is locked
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_ULFRAME "CListFrame/ULFrame"
+
+//collapses the frame if it is uncollapsed,
+//uncollapses the frame if it is collapsed
+//wParam=FrameId
+//lParam=0
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_UCOLLFRAME "CListFrame/UCOLLFrame"
+
+//trigger border flags
+//wparam=frameid
+//lparam=0
+#define MS_CLIST_FRAMES_SETUNBORDER "CListFrame/SetUnBorder"
+
+//redraws the frame
+//wParam=FrameId, -1 for all frames
+//lparam=FU_flags
+//returns a pointer to option, -1 on failure
+#define FU_TBREDRAW 1 //redraw titlebar
+#define FU_FMREDRAW 2 //redraw Frame
+#define FU_FMPOS 4 //update Frame position
+#define MS_CLIST_FRAMES_UPDATEFRAME "CListFrame/UpdateFrame"
+
+//gets the frame options
+//(HIWORD)wParam=FrameId
+//(LOWORD)wParam=FO_flag
+//lParam=0
+//returns a pointer to option, -1 on failure
+#define FO_FLAGS 0x0001 //return set of F_VISIBLE,F_SHOWTB,F_UNCOLLAPSED,F_LOCKED,F_NOBORDER,F_SHOWTBTIP
+#define FO_NAME 0x0002 //Change name
+#define FO_TBNAME 0x0003 //Change TB caption
+#define FO_TBSTYLE 0x0004 //Change TB style
+#define FO_TBEXSTYLE 0x0005 //Change TB exstyle
+#define FO_ICON 0x0006 //Change icon
+#define FO_HEIGHT 0x0007 //Change height
+#define FO_ALIGN 0x0008 //Change align
+#define FO_TBTIPNAME 0x0009 //Change TB tooltip
+#define FO_FLOATING 0x000a //Change floating mode
+
+#define MS_CLIST_FRAMES_GETFRAMEOPTIONS "CListFrame/GetFrameOptions"
+
+//sets the frame options
+//(HIWORLD)wParam=FrameId
+//(LOWORD)wParam=FO_flag
+//lParam=value
+//returns 0 on success, -1 on failure
+#define MS_CLIST_FRAMES_SETFRAMEOPTIONS "CListFrame/SetFrameOptions"
+
+
+//menu stuff
+
+//add a new item to the context frame menu
+//wParam=0
+//lParam=(LPARAM)(CLISTMENUITEM*)&mi
+//returns a handle to the new item
+//popupposition=frameid
+//contactowner=advanced parameter
+#define MS_CLIST_ADDCONTEXTFRAMEMENUITEM "CList/AddContextFrameMenuItem"
+
+//remove a item from context frame menu
+//wParam=hMenuItem returned by MS_CLIST_ADDCONTACTMENUITEM
+//lParam=0
+//returns 0 on success, nonzero on failure
+#define MS_CLIST_REMOVECONTEXTFRAMEMENUITEM "CList/RemoveContextFrameMenuItem"
+
+//builds the context menu for a frame
+//wparam=frameid
+//lParam=0
+//returns a HMENU on success, or NULL on failure
+#define MS_CLIST_MENUBUILDFRAMECONTEXT "CList/BuildContextFrameMenu"
+
+/*
+//the frame menu is about to be built
+wparam=frameid
+lparam=
+-1 for build from titlebar,
+ use
+ MS_CLIST_ADDCONTEXTFRAMEMENUITEM
+ MS_CLIST_REMOVECONTEXTFRAMEMENUITEM
+
+>0 for build in main menu,
+must be popupname=lparam to place your items in right popup of main menu.
+ use
+ MS_CLIST_ADDMAINMENUITEM
+ MS_CLIST_REMOVEMAINMENUITEM
+
+*/
+#define ME_CLIST_PREBUILDFRAMEMENU "CList/PreBuildFrameMenu"
+
+//needed by cluiframes module to add frames menu to main menu.
+//it just calls NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,lParam);
+#define MS_CLIST_FRAMEMENUNOTIFY "CList/ContextFrameMenuNotify"
diff --git a/Plugins/voiceservice/sdk/m_folders.h b/Plugins/voiceservice/sdk/m_folders.h new file mode 100644 index 0000000..c232410 --- /dev/null +++ b/Plugins/voiceservice/sdk/m_folders.h @@ -0,0 +1,205 @@ +/*
+Custom profile folders plugin for Miranda IM
+
+Copyright © 2005 Cristian Libotean
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_CUSTOM_FOLDERS_H
+#define M_CUSTOM_FOLDERS_H
+
+#define FOLDERS_API 501 //dunno why it's here but it is :)
+
+#define PROFILE_PATH "%profile_path%"
+#define CURRENT_PROFILE "%current_profile%"
+#define MIRANDA_PATH "%miranda_path%"
+#define PLUGINS_PATH "%miranda_path%" "\\plugins"
+
+#define TO_WIDE(x) L ## x
+
+#define PROFILE_PATHW L"%profile_path%"
+#define CURRENT_PROFILEW L"%current_profile%"
+#define MIRANDA_PATHW L"%miranda_path%"
+
+#define FOLDER_AVATARS PROFILE_PATH "\\" CURRENT_PROFILE "\\avatars"
+#define FOLDER_VCARDS PROFILE_PATH "\\" CURRENT_PROFILE "\\vcards"
+#define FOLDER_LOGS PROFILE_PATH "\\" CURRENT_PROFILE "\\logs"
+#define FOLDER_RECEIVED_FILES PROFILE_PATH "\\" CURRENT_PROFILE "\\received files"
+#define FOLDER_DOCS MIRANDA_PATH "\\" "docs"
+
+#define FOLDER_CONFIG PLUGINS_PATH "\\" "config"
+
+#define FOLDER_SCRIPTS MIRANDA_PATH "\\" "scripts"
+
+#define FOLDER_UPDATES MIRANDA_PATH "\\" "updates"
+
+#define FOLDER_CUSTOMIZE MIRANDA_PATH "\\" "customize"
+#define FOLDER_CUSTOMIZE_SOUNDS FOLDER_CUSTOMIZE "\\sounds"
+#define FOLDER_CUSTOMIZE_ICONS FOLDER_CUSTOMIZE "\\icons"
+#define FOLDER_CUSTOMIZE_SMILEYS FOLDER_CUSTOMIZE "\\smileys"
+#define FOLDER_CUSTOMIZE_SKINS FOLDER_CUSTOMIZE "\\skins"
+#define FOLDER_CUSTOMIZE_THEMES FOLDER_CUSTOMIZE "\\themes"
+
+
+#define FOLDERS_NAME_MAX_SIZE 64 //maximum name and section size
+
+#define FF_UNICODE 0x00000001
+
+typedef struct{
+ int cbSize; //size of struct
+ char szSection[FOLDERS_NAME_MAX_SIZE]; //section name, if it doesn't exist it will be created otherwise it will just add this entry to it
+ char szName[FOLDERS_NAME_MAX_SIZE]; //entry name - will be shown in options
+ union{
+ const char *szFormat; //default string format. Fallback string in case there's no entry in the database for this folder. This should be the initial value for the path, users will be able to change it later.
+ const wchar_t *szFormatW; //String is dup()'d so you can free it later. If you set the unicode string don't forget to set the flag accordingly.
+ const TCHAR *szFormatT;
+ };
+ DWORD flags; //FF_* flags
+} FOLDERSDATA;
+
+/*Folders/Register/Path service
+ wParam - not used, must be 0
+ lParam - (LPARAM) (const FOLDERDATA *) - Data structure filled with
+ the necessary information.
+ Returns a handle to the registered path or 0 on error.
+ You need to use this to call the other services.
+*/
+#define MS_FOLDERS_REGISTER_PATH "Folders/Register/Path"
+
+/*Folders/Get/PathSize service
+ wParam - (WPARAM) (int) - handle to registered path
+ lParam - (LPARAM) (int *) - pointer to the variable that receives the size of the path
+ string (not including the null character). Depending on the flags set when creating the path
+ it will either call strlen() or wcslen() to get the length of the string.
+ Returns the size of the buffer.
+*/
+#define MS_FOLDERS_GET_SIZE "Folders/Get/PathSize"
+
+typedef struct{
+ int cbSize;
+ int nMaxPathSize; //maximum size of buffer. This represents the number of characters that can be copied to it (so for unicode strings you don't send the number of bytes but the length of the string).
+ union{
+ char *szPath; //pointer to the buffer that receives the path without the last "\\"
+ wchar_t *szPathW; //unicode version of the buffer.
+ TCHAR *szPathT;
+ };
+} FOLDERSGETDATA;
+
+/*Folders/Get/Path service
+ wParam - (WPARAM) (int) - handle to registered path
+ lParam - (LPARAM) (FOLDERSGETDATA *) pointer to a FOLDERSGETDATA that has all the relevant fields filled.
+ Should return 0 on success, or nonzero otherwise.
+*/
+#define MS_FOLDERS_GET_PATH "Folders/Get/Path"
+
+typedef struct{
+ int cbSize;
+ union{
+ char **szPath; //address of a string variable (char *) or (wchar_t*) where the path should be stored (the last \ won't be copied).
+ wchar_t **szPathW; //unicode version of string.
+ TCHAR **szPathT;
+ };
+} FOLDERSGETALLOCDATA;
+
+/*Folders/GetRelativePath/Alloc service
+ wParam - (WPARAM) (int) - Handle to registered path
+ lParam - (LPARAM) (FOLDERSALLOCDATA *) data
+ This service is the same as MS_FOLDERS_GET_PATH with the difference that this service
+ allocates the needed space for the buffer. It uses miranda's memory functions for that and you need
+ to use those to free the resulting buffer.
+ Should return 0 on success, or nonzero otherwise. Currently it only returns 0.
+*/
+#define MS_FOLDERS_GET_PATH_ALLOC "Folders/Get/Path/Alloc"
+
+
+/*Folders/On/Path/Changed
+ wParam - (WPARAM) 0
+ lParam - (LPARAM) 0
+ Triggered when the folders change, you should reget the paths you registered.
+*/
+#define ME_FOLDERS_PATH_CHANGED "Folders/On/Path/Changed"
+
+#ifndef FOLDERS_NO_HELPER_FUNCTIONS
+//#include "../../../include/newpluginapi.h"
+
+__inline static int FoldersRegisterCustomPath(const char *section, const char *name, const char *defaultPath)
+{
+ FOLDERSDATA fd = {0};
+ if (!ServiceExists(MS_FOLDERS_REGISTER_PATH)) return 1;
+ fd.cbSize = sizeof(FOLDERSDATA);
+ strncpy(fd.szSection, section, FOLDERS_NAME_MAX_SIZE);
+ fd.szSection[FOLDERS_NAME_MAX_SIZE - 1] = '\0';
+ strncpy(fd.szName, name, FOLDERS_NAME_MAX_SIZE);
+ fd.szName[FOLDERS_NAME_MAX_SIZE - 1] = '\0';
+ fd.szFormat = defaultPath;
+ return CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd);
+}
+
+__inline static int FoldersRegisterCustomPathW(const char *section, const char *name, const wchar_t *defaultPathW)
+{
+ FOLDERSDATA fd = {0};
+ if (!ServiceExists(MS_FOLDERS_REGISTER_PATH)) return 1;
+ fd.cbSize = sizeof(FOLDERSDATA);
+ strncpy(fd.szSection, section, FOLDERS_NAME_MAX_SIZE);
+ fd.szSection[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; //make sure it's NULL terminated
+ strncpy(fd.szName, name, FOLDERS_NAME_MAX_SIZE);
+ fd.szName[FOLDERS_NAME_MAX_SIZE - 1] = '\0'; //make sure it's NULL terminated
+ fd.szFormatW = defaultPathW;
+ fd.flags = FF_UNICODE;
+ return CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd);
+}
+
+__inline static int FoldersGetCustomPath(HANDLE hFolderEntry, char *path, const int size, char *notFound)
+{
+ FOLDERSGETDATA fgd = {0};
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = size;
+ fgd.szPath = path;
+ int res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd);
+ if (res)
+ {
+ strncpy(path, notFound, size);
+ path[size - 1] = '\0'; //make sure it's NULL terminated
+ }
+ return res;
+}
+
+__inline static int FoldersGetCustomPathW(HANDLE hFolderEntry, wchar_t *pathW, const int count, wchar_t *notFoundW)
+{
+ FOLDERSGETDATA fgd = {0};
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = count;
+ fgd.szPathW = pathW;
+ int res = CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolderEntry, (LPARAM) &fgd);
+ if (res)
+ {
+ wcsncpy(pathW, notFoundW, count);
+ pathW[count - 1] = '\0';
+ }
+ return res;
+}
+
+# ifdef _UNICODE
+# define FoldersGetCustomPathT FoldersGetCustomPathW
+# define FoldersRegisterCustomPathT FoldersRegisterCustomPathW
+#else
+# define FoldersGetCustomPathT FoldersGetCustomPath
+# define FoldersRegisterCustomPathT FoldersRegisterCustomPath
+#endif
+
+#endif
+
+#endif //M_CUSTOM_FOLDERS_H
\ No newline at end of file diff --git a/Plugins/voiceservice/sdk/m_historyevents.h b/Plugins/voiceservice/sdk/m_historyevents.h new file mode 100644 index 0000000..f31f31e --- /dev/null +++ b/Plugins/voiceservice/sdk/m_historyevents.h @@ -0,0 +1,459 @@ +/*
+Copyright (C) 2006 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_HISTORYEVENTS_H__
+# define __M_HISTORYEVENTS_H__
+
+
+#define MIID_HISTORYEVENTS { 0xc8be8543, 0x6618, 0x4030, { 0x85, 0xcf, 0x90, 0x82, 0xc7, 0xde, 0x7f, 0xf7 } }
+
+
+#define HISTORYEVENTS_FORMAT_CHAR 1
+#define HISTORYEVENTS_FORMAT_WCHAR 2
+#define HISTORYEVENTS_FORMAT_RICH_TEXT 4
+#define HISTORYEVENTS_FORMAT_HTML 8
+
+#ifdef UNICODE
+# define HISTORYEVENTS_FORMAT_TCHAR HISTORYEVENTS_FORMAT_WCHAR
+#else
+# define HISTORYEVENTS_FORMAT_TCHAR HISTORYEVENTS_FORMAT_CHAR
+#endif
+
+#define HISTORYEVENTS_FLAG_DEFAULT (1 << 0) // Is a miranda core event type
+#define HISTORYEVENTS_FLAG_SHOW_IM_SRMM (1 << 1) // If this event has to be shown in srmm dialog
+#define HISTORYEVENTS_FLAG_USE_SENT_FLAG (1 << 2) // Means that it can be a sent or received and uses DBEF_SENT to mark that
+#define HISTORYEVENTS_FLAG_EXPECT_CONTACT_NAME_BEFORE (1 << 3) // Means that who is drawing this should draw the contact name before the text
+#define HISTORYEVENTS_FLAG_ONLY_LOG_IF_SRMM_OPEN (1 << 4) // If this event will be logged only if the message window is open
+#define HISTORYEVENTS_FLAG_FLASH_MSG_WINDOW (1 << 5) // If this event will trigger the openning/flashing of the message window
+#define HISTORYEVENTS_REGISTERED_IN_ICOLIB (9 << 16) // If the icon is a name already registered in icolib
+#define HISTORYEVENTS_FLAG_KEEP_ONE_YEAR (1 << 8) // By default store in db for 1 year
+#define HISTORYEVENTS_FLAG_KEEP_SIX_MONTHS (2 << 8) // By default store in db for 6 months
+#define HISTORYEVENTS_FLAG_KEEP_ONE_MONTH (3 << 8) // By default store in db for 1 month
+#define HISTORYEVENTS_FLAG_KEEP_ONE_WEEK (4 << 8) // By default store in db for 1 week
+#define HISTORYEVENTS_FLAG_KEEP_ONE_DAY (5 << 8) // By default store in db for 1 day
+#define HISTORYEVENTS_FLAG_KEEP_FOR_SRMM (6 << 8) // By default store in db only enought for message log
+#define HISTORYEVENTS_FLAG_KEEP_MAX_TEN (7 << 8) // By default store in db max 10 entries
+#define HISTORYEVENTS_FLAG_KEEP_MAX_HUNDRED (8 << 8) // By default store in db for 100 entries
+#define HISTORYEVENTS_FLAG_KEEP_DONT (9 << 8) // By default don't store in db (aka ignore it)
+
+
+// This function must be implemented by subscribers. It must return a pointer or NULL
+// to say it can't handle the text
+typedef void * (*fGetHistoryEventText)(HANDLE hContact, HANDLE hDbEvent, DBEVENTINFO *dbe, int format);
+
+typedef struct {
+ int cbSize;
+ char *module;
+ char *name; // Internal event name
+ char *description; // Will be translated. When retrieving it is already translated
+ WORD eventType; // The event type it can handle
+ union {
+ HICON defaultIcon;
+ char * defaultIconName; // if HISTORYEVENTS_REGISTERED_IN_ICOLIB is set. Always use this one when retrieving
+ };
+ int supports; // What kind of return is supported - or of HISTORYEVENTS_FORMAT_*
+ int flags; // or of HISTORYEVENTS_FLAG_*
+ fGetHistoryEventText pfGetHistoryEventText; // NULL to use default get text (similar to message, without extra format)
+
+ // Aditional data if wants to use add to history services
+ char **templates; // Each entry is: "Name\nDefault\n%var%\tDescription\n%var%\tDescription\n%var%\tDescription"
+ int numTemplates;
+
+} HISTORY_EVENT_HANDLER;
+
+
+/*
+Get the number of registered events
+
+wParam: ignored
+lParam: ignored
+Return: The number of events registered with the plugin
+*/
+#define MS_HISTORYEVENTS_GET_COUNT "HistoryEvents/GetCount"
+
+
+/*
+Get an event by number or by type.
+To retrieve by number, pass -1 as type. To retrieve by type, pass -1 as number.
+
+wParam: (int) event number
+lParam: (int) event type
+Return: (const HISTORY_EVENT_HANDLER *) if the event exists, NULL otherwise. Don't change the
+ returned strunc: it is a pointer to the internall struct.
+*/
+#define MS_HISTORYEVENTS_GET_EVENT "HistoryEvents/GetEvent"
+
+
+/*
+Register a plugin that can handle an event type. This must be called during the call to the
+Load function of the plugin. In ModulesLoaded callback all plugins have to be already registered,
+so srmm and history modules can query then.
+
+wParam: HISTORY_EVENT_HANDLER *
+lParam: ignored
+Return: 0 for success
+*/
+#define MS_HISTORYEVENTS_REGISTER "HistoryEvents/Register"
+
+
+typedef struct {
+ int cbSize;
+ HANDLE hDbEvent;
+ DBEVENTINFO *dbe; // Optional
+ int format; // one of HISTORYEVENTS_FORMAT_*
+
+} HISTORY_EVENT_PARAM;
+
+/*
+Check if an event can be handled by any subscribers
+
+wParam: WORD - event type
+lParam: ignored
+Return: BOOL
+*/
+#define MS_HISTORYEVENTS_CAN_HANDLE "HistoryEvents/CanHandle"
+
+/*
+Get the icon for a history event type
+
+wParam: WORD - event type
+lParam: BOOL - TRUE to copy the icon (should be released with DestroyObject),
+ FALSE to use icolib one (should be released with MS_HISTORYEVENTS_RELEASE_ICON)
+Return: HICON
+*/
+#define MS_HISTORYEVENTS_GET_ICON "HistoryEvents/GetIcon"
+
+/*
+Get the flags for a history event type
+
+wParam: WORD - event type
+lParam: ignored
+Return: int - or of HISTORYEVENTS_FLAG_* or -1 if error
+*/
+#define MS_HISTORYEVENTS_GET_FLAGS "HistoryEvents/GetFlags"
+
+/*
+Release the icon for a history event type. This is really just a forward to icolib
+
+wParam: HICON
+lParam: ignored
+*/
+#define MS_HISTORYEVENTS_RELEASE_ICON "Skin2/Icons/ReleaseIcon"
+
+/*
+Get the text for a history event type
+
+wParam: HISTORY_EVENT_PARAM *
+lParam: ignored
+Return: char * or wchar * depending on sent flags. Free with mir_free or MS_HISTORYEVENTS_RELEASE_TEXT
+*/
+#define MS_HISTORYEVENTS_GET_TEXT "HistoryEvents/GetText"
+
+/*
+Release the text for a history event type. Internally is just a call to mir_free
+
+wParam: char * or wchar *
+lParam: ignored
+*/
+#define MS_HISTORYEVENTS_RELEASE_TEXT "HistoryEvents/ReleaseText"
+
+
+
+typedef struct {
+ int cbSize;
+ HANDLE hContact;
+ WORD eventType;
+ int templateNum;
+ TCHAR **variables;
+ int numVariables;
+ PBYTE additionalData;
+ int additionalDataSize;
+ int flags; // Flags for the event type
+ DWORD timestamp; // 0 for now
+ BOOL addToMetaToo;
+} HISTORY_EVENT_ADD;
+
+/*
+Add an registered event to the history. This is a helper service
+
+wParam: HISTORY_EVENT_ADD
+lParam: ignored
+Return: HANDLE to the db event
+*/
+#define MS_HISTORYEVENTS_ADD_TO_HISTORY "HistoryEvents/AddToHistory"
+
+/*
+Check if a template is enabled
+
+wParam: event type
+lParam: template num
+Return: TRUE or FALSE
+*/
+#define MS_HISTORYEVENTS_IS_ENABLED_TEMPLATE "HistoryEvents/IsEnabledTemplate"
+
+
+
+// Helper functions //////////////////////////////////////////////////////////////////////////////
+
+
+
+
+static int HistoryEvents_Register(char *module, char *name, char *description, int eventType, HICON defaultIcon,
+ int supports, int flags, fGetHistoryEventText pfGetHistoryEventText)
+{
+ HISTORY_EVENT_HANDLER heh = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_REGISTER))
+ return 1;
+
+ heh.cbSize = sizeof(heh);
+ heh.module = module;
+ heh.name = name;
+ heh.description = description;
+ heh.eventType = eventType;
+ heh.defaultIcon = defaultIcon;
+ heh.supports = supports;
+ heh.flags = flags;
+ heh.pfGetHistoryEventText = pfGetHistoryEventText;
+ return CallService(MS_HISTORYEVENTS_REGISTER, (WPARAM) &heh, 0);
+}
+
+static int HistoryEvents_RegisterWithTemplates(char *module, char *name, char *description, int eventType, HICON defaultIcon,
+ int supports, int flags, fGetHistoryEventText pfGetHistoryEventText,
+ char **templates, int numTemplates)
+{
+ HISTORY_EVENT_HANDLER heh = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_REGISTER))
+ return 1;
+
+ heh.cbSize = sizeof(heh);
+ heh.module = module;
+ heh.name = name;
+ heh.description = description;
+ heh.eventType = eventType;
+ heh.defaultIcon = defaultIcon;
+ heh.supports = supports;
+ heh.flags = flags;
+ heh.pfGetHistoryEventText = pfGetHistoryEventText;
+ heh.templates = templates;
+ heh.numTemplates = numTemplates;
+ return CallService(MS_HISTORYEVENTS_REGISTER, (WPARAM) &heh, 0);
+}
+
+static int HistoryEvents_RegisterMessageStyle(char *module, char *name, char *description, int eventType, HICON defaultIcon,
+ int flags, char **templates, int numTemplates)
+{
+ HISTORY_EVENT_HANDLER heh = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_REGISTER))
+ return 1;
+
+ heh.cbSize = sizeof(heh);
+ heh.module = module;
+ heh.name = name;
+ heh.description = description;
+ heh.eventType = eventType;
+ heh.defaultIcon = defaultIcon;
+ heh.flags = flags;
+ heh.templates = templates;
+ heh.numTemplates = numTemplates;
+ return CallService(MS_HISTORYEVENTS_REGISTER, (WPARAM) &heh, 0);
+}
+
+static BOOL HistoryEvents_CanHandle(WORD eventType)
+{
+ if (!ServiceExists(MS_HISTORYEVENTS_CAN_HANDLE))
+ return FALSE;
+
+ return (BOOL) CallService(MS_HISTORYEVENTS_CAN_HANDLE, (WPARAM) eventType, 0);
+}
+
+static HICON HistoryEvents_GetIcon(WORD eventType)
+{
+ if (!ServiceExists(MS_HISTORYEVENTS_GET_ICON))
+ return NULL;
+
+ return (HICON) CallService(MS_HISTORYEVENTS_GET_ICON, (WPARAM) eventType, 0);
+}
+
+static int HistoryEvents_GetFlags(WORD eventType)
+{
+ if (!ServiceExists(MS_HISTORYEVENTS_GET_FLAGS))
+ return -1;
+
+ return (int) CallService(MS_HISTORYEVENTS_GET_FLAGS, (WPARAM) eventType, 0);
+}
+
+static void HistoryEvents_ReleaseIcon(HICON icon)
+{
+ CallService(MS_HISTORYEVENTS_RELEASE_ICON, (WPARAM) icon, 0);
+}
+
+static char * HistoryEvents_GetTextA(HANDLE hDbEvent, DBEVENTINFO *dbe)
+{
+ HISTORY_EVENT_PARAM hep = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_GET_TEXT))
+ return NULL;
+
+ hep.cbSize = sizeof(hep);
+ hep.hDbEvent = hDbEvent;
+ hep.dbe = dbe;
+ hep.format = HISTORYEVENTS_FORMAT_CHAR;
+ return (char *) CallService(MS_HISTORYEVENTS_GET_TEXT, (WPARAM) &hep, 0);
+}
+
+static wchar_t * HistoryEvents_GetTextW(HANDLE hDbEvent, DBEVENTINFO *dbe)
+{
+ HISTORY_EVENT_PARAM hep = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_GET_TEXT))
+ return NULL;
+
+ hep.cbSize = sizeof(hep);
+ hep.hDbEvent = hDbEvent;
+ hep.dbe = dbe;
+ hep.format = HISTORYEVENTS_FORMAT_WCHAR;
+ return (wchar_t *) CallService(MS_HISTORYEVENTS_GET_TEXT, (WPARAM) &hep, 0);
+}
+
+static char * HistoryEvents_GetRichText(HANDLE hDbEvent, DBEVENTINFO *dbe)
+{
+ HISTORY_EVENT_PARAM hep = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_GET_TEXT))
+ return NULL;
+
+ hep.cbSize = sizeof(hep);
+ hep.hDbEvent = hDbEvent;
+ hep.dbe = dbe;
+ hep.format = HISTORYEVENTS_FORMAT_RICH_TEXT;
+ return (char *) CallService(MS_HISTORYEVENTS_GET_TEXT, (WPARAM) &hep, 0);
+}
+
+#define HistoryEvents_ReleaseText mir_free
+//static void HistoryEvents_ReleaseText(void *str)
+//{
+// if (!ServiceExists(MS_HISTORYEVENTS_RELEASE_TEXT))
+// return;
+//
+// CallService(MS_HISTORYEVENTS_RELEASE_TEXT, (WPARAM) str, 0);
+//}
+
+
+#ifdef __cplusplus
+static HANDLE HistoryEvents_AddToHistoryEx(HANDLE hContact, WORD eventType, int templateNum,
+ TCHAR **variables, int numVariables,
+ PBYTE additionalData, int additionalDataSize,
+ int flags = 0, DWORD timestamp = 0, BOOL addToMetaToo = FALSE)
+#else
+static HANDLE HistoryEvents_AddToHistoryEx(HANDLE hContact, WORD eventType, int templateNum,
+ TCHAR **variables, int numVariables,
+ PBYTE additionalData, int additionalDataSize,
+ int flags, DWORD timestamp, BOOL addToMetaToo)
+#endif
+{
+ HISTORY_EVENT_ADD hea = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_ADD_TO_HISTORY))
+ return NULL;
+
+ hea.cbSize = sizeof(hea);
+ hea.hContact = hContact;
+ hea.eventType = eventType;
+ hea.templateNum = templateNum;
+ hea.numVariables = numVariables;
+ hea.variables = variables;
+ hea.additionalData = additionalData;
+ hea.additionalDataSize = additionalDataSize;
+ hea.flags = flags;
+ hea.timestamp = timestamp;
+ hea.addToMetaToo = addToMetaToo;
+
+ return (HANDLE) CallService(MS_HISTORYEVENTS_ADD_TO_HISTORY, (WPARAM) &hea, 0);
+}
+
+#ifdef __cplusplus
+static HANDLE HistoryEvents_AddToHistoryVars(HANDLE hContact, WORD eventType, int templateNum,
+ TCHAR **variables, int numVariables,
+ int flags = 0, DWORD timestamp = 0, BOOL addToMetaToo = FALSE)
+#else
+static HANDLE HistoryEvents_AddToHistoryVars(HANDLE hContact, WORD eventType, int templateNum,
+ TCHAR **variables, int numVariables,
+ int flags, DWORD timestamp, BOOL addToMetaToo)
+#endif
+{
+ HISTORY_EVENT_ADD hea = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_ADD_TO_HISTORY))
+ return NULL;
+
+ hea.cbSize = sizeof(hea);
+ hea.hContact = hContact;
+ hea.eventType = eventType;
+ hea.templateNum = templateNum;
+ hea.numVariables = numVariables;
+ hea.variables = variables;
+ hea.flags = flags;
+ hea.timestamp = timestamp;
+ hea.addToMetaToo = addToMetaToo;
+
+ return (HANDLE) CallService(MS_HISTORYEVENTS_ADD_TO_HISTORY, (WPARAM) &hea, 0);
+}
+
+#ifdef __cplusplus
+static HANDLE HistoryEvents_AddToHistorySimple(HANDLE hContact, WORD eventType, int templateNum,
+ int flags = 0, DWORD timestamp = 0, BOOL addToMetaToo = FALSE)
+#else
+static HANDLE HistoryEvents_AddToHistorySimple(HANDLE hContact, WORD eventType, int templateNum,
+ int flags, DWORD timestamp, BOOL addToMetaToo)
+#endif
+{
+ HISTORY_EVENT_ADD hea = {0};
+
+ if (!ServiceExists(MS_HISTORYEVENTS_ADD_TO_HISTORY))
+ return NULL;
+
+ hea.cbSize = sizeof(hea);
+ hea.hContact = hContact;
+ hea.eventType = eventType;
+ hea.templateNum = templateNum;
+ hea.flags = flags;
+ hea.timestamp = timestamp;
+ hea.addToMetaToo = addToMetaToo;
+
+ return (HANDLE) CallService(MS_HISTORYEVENTS_ADD_TO_HISTORY, (WPARAM) &hea, 0);
+}
+
+static BOOL HistoryEvents_IsEnabledTemplate(WORD eventType, int templateNum)
+{
+ return (BOOL) CallService(MS_HISTORYEVENTS_IS_ENABLED_TEMPLATE, eventType, templateNum);
+}
+
+#ifdef UNICODE
+# define HistoryEvents_GetTextT HistoryEvents_GetTextW
+#else
+# define HistoryEvents_GetTextT HistoryEvents_GetTextA
+#endif
+
+
+
+#endif // __M_HISTORYEVENTS_H__
diff --git a/Plugins/voiceservice/sdk/m_metacontacts.h b/Plugins/voiceservice/sdk/m_metacontacts.h new file mode 100644 index 0000000..1da12b9 --- /dev/null +++ b/Plugins/voiceservice/sdk/m_metacontacts.h @@ -0,0 +1,162 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright © 2004 Universite Louis PASTEUR, STRASBOURG.
+Copyright © 2004 Scott Ellis (www.scottellis.com.au mail@scottellis.com.au)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_METACONTACTS_H__
+#define M_METACONTACTS_H__ 1
+
+//get the handle for a contact's parent metacontact
+//wParam=(HANDLE)hSubContact
+//lParam=0
+//returns a handle to the parent metacontact, or null if this contact is not a subcontact
+#define MS_MC_GETMETACONTACT "MetaContacts/GetMeta"
+
+//gets the handle for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the default contact, or null on failure
+#define MS_MC_GETDEFAULTCONTACT "MetaContacts/GetDefault"
+
+//gets the contact number for the default contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD contact number, or -1 on failure
+#define MS_MC_GETDEFAULTCONTACTNUM "MetaContacts/GetDefaultNum"
+
+//gets the handle for the 'most online' contact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a handle to the 'most online' contact
+#define MS_MC_GETMOSTONLINECONTACT "MetaContacts/GetMostOnline"
+
+//gets the number of subcontacts for a metacontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns a DWORD representing the number of subcontacts for the given metacontact
+#define MS_MC_GETNUMCONTACTS "MetaContacts/GetNumContacts"
+
+//gets the handle of a subcontact, using the subcontact's number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns a handle to the specified subcontact
+#define MS_MC_GETSUBCONTACT "MetaContacts/GetSubContact"
+
+//sets the default contact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACTNUM "MetaContacts/SetDefault"
+
+//sets the default contact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success
+#define MS_MC_SETDEFAULTCONTACT "MetaContacts/SetDefaultByHandle"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's contact number
+//wParam=(HANDLE)hMetaContact
+//lParam=(DWORD)contact number
+//returns 0 on success
+#define MS_MC_FORCESENDCONTACTNUM "MetaContacts/ForceSendContact"
+
+//forces the metacontact to send using a specific subcontact, using the subcontact's handle
+//wParam=(HANDLE)hMetaContact
+//lParam=(HANDLE)hSubcontact
+//returns 0 on success (will fail if 'force default' is in effect)
+#define MS_MC_FORCESENDCONTACT "MetaContacts/ForceSendContactByHandle"
+
+//'unforces' the metacontact to send using a specific subcontact
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 0 on success (will fail if 'force default' is in effect)
+#define MS_MC_UNFORCESENDCONTACT "MetaContacts/UnforceSendContact"
+
+//'forces' or 'unforces' (i.e. toggles) the metacontact to send using it's default contact
+// overrides (and clears) 'force send' above, and will even force use of offline contacts
+// will send ME_MC_FORCESEND or ME_MC_UNFORCESEND event
+//wParam=(HANDLE)hMetaContact
+//lParam=0
+//returns 1(true) or 0(false) representing new state of 'force default'
+#define MS_MC_FORCEDEFAULT "MetaContacts/ForceSendDefault"
+
+// method to get state of 'force' for a metacontact
+// wParam=(HANDLE)hMetaContact
+// lParam= (DWORD)&contact_number or NULL
+//
+// if lparam supplied, the contact_number of the contatct 'in force' will be copied to the address it points to,
+// or if none is in force, the value (DWORD)-1 will be copied
+// (v0.8.0.8+ returns 1 if 'force default' is true with *lParam == default contact number, else returns 0 with *lParam as above)
+#define MS_MC_GETFORCESTATE "MetaContacts/GetForceState"
+
+// fired when a metacontact's default contact changes (fired upon creation of metacontact also, when default is initially set)
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hDefaultContact
+#define ME_MC_DEFAULTTCHANGED "MetaContacts/DefaultChanged"
+
+// fired when a metacontact's subcontacts change (fired upon creation of metacontact, when contacts are added or removed, and when
+// contacts are reordered) - a signal to re-read metacontact data
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_SUBCONTACTSCHANGED "MetaContacts/SubcontactsChanged"
+
+// fired when a metacontact is forced to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=(HANDLE)hForceContact
+#define ME_MC_FORCESEND "MetaContacts/ForceSend"
+
+// fired when a metacontact is 'unforced' to send using a specific subcontact
+// wParam=(HANDLE)hMetaContact
+// lParam=0
+#define ME_MC_UNFORCESEND "MetaContacts/UnforceSend"
+
+// method to get protocol name - used to be sure you're dealing with a "real" metacontacts plugin :)
+// wParam=lParam=0
+#define MS_MC_GETPROTOCOLNAME "MetaContacts/GetProtoName"
+
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=0
+// convert a given contact into a metacontact
+#define MS_MC_CONVERTTOMETA "MetaContacts/ConvertToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=(HANDLE)hContact
+// lParam=(HANDLE)hMeta
+// add an existing contact to a metacontact
+#define MS_MC_ADDTOMETA "MetaContacts/AddToMetacontact"
+
+// added 0.9.5.0 (22/3/05)
+// wParam=0
+// lParam=(HANDLE)hContact
+// remove a contact from a metacontact
+#define MS_MC_REMOVEFROMMETA "MetaContacts/RemoveFromMetacontact"
+
+
+// added 0.9.13.2 (6/10/05)
+// wParam=(BOOL)disable
+// lParam=0
+// enable/disable the 'hidden group hack' - for clists that support subcontact hiding using 'IsSubcontact' setting
+// should be called once in the clist 'onmodulesloaded' event handler (which, since it's loaded after the db, will be called
+// before the metacontact onmodulesloaded handler where the subcontact hiding is usually done)
+#define MS_MC_DISABLEHIDDENGROUP "MetaContacts/DisableHiddenGroup"
+
+#endif
diff --git a/Plugins/voiceservice/sdk/m_updater.h b/Plugins/voiceservice/sdk/m_updater.h new file mode 100644 index 0000000..371b743 --- /dev/null +++ b/Plugins/voiceservice/sdk/m_updater.h @@ -0,0 +1,146 @@ +#ifndef _M_UPDATER_H
+#define _M_UPDATER_H
+
+// NOTES:
+// - For langpack updates, include a string of the following format in the langpack text file:
+// ";FLID: <file listing name> <version>"
+// version must be four numbers seperated by '.', in the range 0-255 inclusive
+// - Updater will disable plugins that are downloaded but were not active prior to the update (this is so that, if an archive contains e.g. ansi and
+// unicode versions, the correct plugin will be the only one active after the new version is installed)...so if you add a support plugin, you may need
+// to install an ini file to make the plugin activate when miranda restarts after the update
+// - Updater will replace all dlls that have the same internal shortName as a downloaded update dll (this is so that msn1.dll and msn2.dll, for example,
+// will both be updated) - so if you have a unicode and a non-unicode version of a plugin in your archive, you should make the internal names different (which will break automatic
+// updates from the file listing if there is only one file listing entry for both versions, unless you use the 'MS_UPDATE_REGISTER' service below)
+// - Updater will install all files in the root of the archive into the plugins folder, except for langpack files that contain the FLID string which go into the root folder (same
+// folder as miranda32.exe)...all folders in the archive will also be copied to miranda's root folder, and their contents transferred into the new folders. The only exception is a
+// special folder called 'root_files' - if there is a folder by that name in the archive, it's contents will also be copied into miranda's root folder - this is intended to be used
+// to install additional dlls etc that a plugin may require)
+
+// if you set Update.szUpdateURL to the following value when registering, as well as setting your beta site and version data,
+// Updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data.
+// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case)
+#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER"
+// Updater will also use the backend xml data if you provide URL's that reference the miranda file listing for updates (so you can use that method
+// if e.g. your plugin shortName does not match the file listing) - it will grab the file listing id from the end of these URLs
+
+typedef struct Update_tag {
+ int cbSize;
+ char *szComponentName; // component name as it will appear in the UI (will be translated before displaying)
+
+ char *szVersionURL; // URL where the current version can be found (NULL to disable)
+ BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ // (note that this URL could point at a binary file - dunno why, but it could :)
+ int cpbVersionPrefix; // number of bytes pointed to by pbVersionPrefix
+ char *szUpdateURL; // URL where dll/zip is located
+ // set to UPDATER_AUTOREGISTER if you want Updater to find the file listing URLs (ensure plugin shortName matches file listing!)
+
+ char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas)
+ BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data
+ int cpbBetaVersionPrefix; // number of bytes pointed to by pbVersionPrefix
+ char *szBetaUpdateURL; // URL where dll/zip is located
+
+ BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL
+ int cpbVersion; // number of bytes pointed to by pbVersion
+
+ char *szBetaChangelogURL; // url for displaying changelog for beta versions
+} Update;
+
+// register a comonent with Updater
+//
+// wparam = 0
+// lparam = (LPARAM)&Update
+#define MS_UPDATE_REGISTER "Update/Register"
+
+// utility functions to create a version string from a DWORD or from pluginInfo
+// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter
+//
+__inline static char *CreateVersionString(DWORD version, char *buf) {
+ mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF);
+ return buf;
+}
+
+__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) {
+ return CreateVersionString(pluginInfo->version, buf);
+}
+
+
+// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing
+// NOTE: the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1,
+// four numbers between 0 and 255 inclusivem, so no letters, brackets, etc.)
+//
+// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link)
+// lParam = (PLUGININFO*)&pluginInfo
+#define MS_UPDATE_REGISTERFL "Update/RegisterFL"
+
+// this function can be used to 'unregister' components - useful for plugins that register non-plugin/langpack components and
+// may need to change those components on the fly
+// lParam = (char *)szComponentName
+#define MS_UPDATE_UNREGISTER "Update/Unregister"
+
+// this event is fired when the startup process is complete, but NOT if a restart is imminent
+// it is designed for status managment plugins to use as a trigger for beggining their own startup process
+// wParam = lParam = 0 (unused)
+// (added in version 0.1.6.0)
+#define ME_UPDATE_STARTUPDONE "Update/StartupDone"
+
+// this service can be used to enable/disable Updater's global status control
+// it can be called from the StartupDone event handler
+// wParam = (BOOL)enable
+// lParam = 0
+// (added in version 0.1.6.0)
+#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl"
+
+// An description of usage of the above service and event:
+// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler.
+// In order to make yourself 'Updater compatible', you would move the status control code from ModulesLoaded to another function,
+// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service.
+// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may
+// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature.
+
+// this service can be used to determine whether updates are possible for a component with the given name
+// wParam = 0
+// lParam = (char *)szComponentName
+// returns TRUE if updates are supported, FALSE otherwise
+#define MS_UPDATE_ISUPDATESUPPORTED "Update/IsUpdateSupported"
+
+#endif
+
+
+/////////////// Usage Example ///////////////
+
+#ifdef EXAMPLE_CODE
+
+// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function...
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+
+ Update update = {0}; // for c you'd use memset or ZeroMemory...
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ // 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.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip";
+ update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html";
+ update.pbVersionPrefix = (BYTE *)"Updater version ";
+
+ update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix);
+
+ // do the same for the beta versions of the above struct members if you wish to allow beta updates from another URL
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+
+ // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing...
+ // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo);
+
+ return 0;
+}
+
+#endif
diff --git a/Plugins/voiceservice/voiceservice.cpp b/Plugins/voiceservice/voiceservice.cpp new file mode 100644 index 0000000..1b43795 --- /dev/null +++ b/Plugins/voiceservice/voiceservice.cpp @@ -0,0 +1,1666 @@ +/*
+Copyright (C) 2006 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
+ "Voice Service (Unicode)",
+#else
+ "Voice Service",
+#endif
+ PLUGIN_MAKE_VERSION(0,1,2,0),
+ "Provide services for protocols that support voice calls",
+ "Ricardo Pescuma Domenecci",
+ "pescuma@miranda-im.org",
+ "© 2007-2009 Ricardo Pescuma Domenecci",
+ "http://pescuma.org/miranda/voiceservice",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#ifdef UNICODE
+ { 0x1bfc449d, 0x8f6f, 0x4080, { 0x8f, 0x35, 0xf9, 0x40, 0xb3, 0xde, 0x12, 0x84 } } // {1BFC449D-8F6F-4080-8F35-F940B3DE1284}
+#else
+ { 0x1bbe5b21, 0x238d, 0x4cbc, { 0xaf, 0xb8, 0xe, 0xef, 0xab, 0x1b, 0xf2, 0x69 } } // {1BBE5B21-238D-4cbc-AFB8-0EEFAB1BF269}
+#endif
+};
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+MM_INTERFACE mmi;
+UTF8_INTERFACE utfi;
+LIST_INTERFACE li;
+
+static vector<HANDLE> hHooks;
+
+static vector<HANDLE> hCMCalls;
+static HANDLE hCMCall = NULL;
+static HANDLE hCMAnswer = NULL;
+static HANDLE hCMDrop = NULL;
+static HANDLE hCMHold = NULL;
+
+char *metacontacts_proto = NULL;
+
+
+static INT_PTR ModulesLoaded(WPARAM wParam, LPARAM lParam);
+static INT_PTR PreShutdown(WPARAM wParam, LPARAM lParam);
+static INT_PTR ProtoAck(WPARAM wParam, LPARAM lParam);
+static INT_PTR PreBuildContactMenu(WPARAM wParam, LPARAM lParam);
+static INT_PTR AccListChanged(WPARAM wParam, LPARAM lParam);
+
+static INT_PTR VoiceRegister(WPARAM wParam, LPARAM lParam);
+static INT_PTR VoiceUnregister(WPARAM wParam, LPARAM lParam);
+static INT_PTR VoiceState(WPARAM wParam, LPARAM lParam);
+
+VoiceProvider * FindModule(const char *szModule);
+VoiceCall * FindVoiceCall(const char *szModule, const char *id, BOOL add);
+VoiceCall * FindVoiceCall(HANDLE hContact);
+
+
+template<class TYPE>
+static int sttCompare(const TYPE *p1, const TYPE *p2)
+{
+ return (int) p1 - (int) p2;
+}
+OBJLIST<VoiceProvider> modules(1, &sttCompare<VoiceProvider>);
+OBJLIST<VoiceCall> calls(1, &sttCompare<VoiceCall>);
+
+HFONT fonts[NUM_FONTS] = {0};
+COLORREF font_colors[NUM_FONTS] = {0};
+int font_max_height;
+
+COLORREF bkg_color = {0};
+HBRUSH bk_brush = NULL;
+
+
+
+static INT_PTR CListDblClick(WPARAM wParam, LPARAM lParam);
+
+static INT_PTR Service_CanCall(WPARAM wParam, LPARAM lParam);
+static INT_PTR Service_Call(WPARAM wParam, LPARAM lParam);
+static INT_PTR CMAnswer(WPARAM wParam, LPARAM lParam);
+static INT_PTR CMHold(WPARAM wParam, LPARAM lParam);
+static INT_PTR CMDrop(WPARAM wParam, LPARAM lParam);
+
+static INT_PTR IconsChanged(WPARAM wParam, LPARAM lParam);
+static INT_PTR ReloadFont(WPARAM wParam, LPARAM lParam);
+static INT_PTR ReloadColor(WPARAM wParam, LPARAM lParam);
+static VOID CALLBACK ClearOldVoiceCalls(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+
+static BOOL CALLBACK DlgProcNewCall(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+
+class CallingMethod
+{
+public:
+ VoiceProvider *provider;
+ HANDLE hContact;
+ TCHAR number[128];
+
+ CallingMethod(VoiceProvider *provider, HANDLE hContact, const TCHAR *number = NULL)
+ : provider(provider), hContact(hContact)
+ {
+ if (number == NULL)
+ this->number[0] = 0;
+ else
+ lstrcpyn(this->number, number, MAX_REGS(this->number));
+ }
+
+ void Call()
+ {
+ provider->Call(hContact, number);
+ }
+};
+
+
+static int sttCompareCallingMethods(const CallingMethod *p1, const CallingMethod *p2)
+{
+ if (p1->hContact != p2->hContact)
+ return (int)p2->hContact - (int)p1->hContact;
+
+ BOOL noNum1 = (IsEmpty(p1->number) ? 1 : 0);
+ BOOL noNum2 = (IsEmpty(p2->number) ? 1 : 0);
+ if (noNum1 != noNum2)
+ return noNum2 - noNum1;
+
+ if (!noNum1)
+ {
+ int numDif = lstrcmp(p1->number, p2->number);
+ if (numDif != 0)
+ return numDif;
+ }
+
+ BOOL isProto1 = (CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM) p1->hContact, (LPARAM) p1->provider->name) ? 1 : 0);
+ BOOL isProto2 = (CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM) p2->hContact, (LPARAM) p2->provider->name) ? 1 : 0);
+ if (isProto1 != isProto2)
+ return isProto2 - isProto1;
+
+ return lstrcmp(p1->provider->description, p2->provider->description);
+}
+
+
+static void AddMethodsFrom(OBJLIST<CallingMethod> *list, HANDLE hContact)
+{
+ for(int i = 0; i < modules.getCount(); i++)
+ {
+ VoiceProvider *provider = &modules[i];
+ if (provider->CanCall(hContact))
+ list->insert(new CallingMethod(provider, hContact));
+ }
+}
+
+static void AddMethodsFrom(OBJLIST<CallingMethod> *list, HANDLE hContact, const TCHAR *number)
+{
+ for(int i = 0; i < modules.getCount(); i++)
+ {
+ VoiceProvider *provider = &modules[i];
+ if (provider->CanCall(number))
+ list->insert(new CallingMethod(provider, hContact, number));
+ }
+}
+
+static void BuildCallingMethodsList(OBJLIST<CallingMethod> *list, HANDLE hContact)
+{
+ AddMethodsFrom(list, hContact);
+
+ // Fetch contact number
+ char *proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+
+ DBTString protoNumber(hContact, proto, "Number");
+ if (protoNumber != NULL)
+ AddMethodsFrom(list, hContact, protoNumber);
+
+ for(int i = 0; ;i++)
+ {
+ char tmp[128];
+ mir_snprintf(tmp, MAX_REGS(tmp), "MyPhone%d", i);
+
+ DBTString number(hContact, "UserInfo", tmp);
+ if (number != NULL)
+ AddMethodsFrom(list, hContact, number);
+
+ if (number == NULL && i >= 4)
+ break;
+ }
+}
+
+
+// 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_VOICESERVICE, MIID_LAST };
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ CHECK_VERSION("Voice Service")
+
+ if (Pa_Initialize() != paNoError)
+ MessageBox(NULL, TranslateT("Error initializing portaudio."), TranslateT("Voice Service"), MB_OK | MB_ICONERROR);
+
+ // TODO Assert results here
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+ mir_getLI(&li);
+
+ CreateServiceFunction(MS_VOICESERVICE_CLIST_DBLCLK, CListDblClick);
+ CreateServiceFunction(MS_VOICESERVICE_REGISTER, VoiceRegister);
+ CreateServiceFunction(MS_VOICESERVICE_UNREGISTER, VoiceUnregister);
+
+ // Hooks
+ hHooks.push_back( HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded) );
+ hHooks.push_back( HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown) );
+ hHooks.push_back( HookEvent(ME_PROTO_ACK, ProtoAck) );
+
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ if (bk_brush != NULL)
+ DeleteObject(bk_brush);
+
+ Pa_Terminate();
+
+ return 0;
+}
+
+
+static void AddAccount(PROTOACCOUNT *acc)
+{
+ if (!IsAccountEnabled(acc))
+ return;
+ if (IsEmptyA(acc->szModuleName))
+ return;
+ if (!ProtoServiceExists(acc->szModuleName, PS_VOICE_CAPS))
+ return;
+
+ int flags = CallProtoService(acc->szModuleName, PS_VOICE_CAPS, 0, 0);
+
+ if ((flags & VOICE_CAPS_VOICE) == 0)
+ return;
+
+ VOICE_MODULE vm = {0};
+ vm.cbSize = sizeof(vm);
+ vm.name = acc->szModuleName;
+ vm.description = acc->tszAccountName;
+ vm.flags = flags;
+ VoiceRegister((WPARAM) &vm, 0);
+}
+
+
+// Called when all the modules are loaded
+static INT_PTR ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ // add our modules to the KnownModules list
+ CallService("DBEditorpp/RegisterSingleModule", (WPARAM) MODULE_NAME, 0);
+
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ metacontacts_proto = (char *) CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ // updater plugin support
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update upd = {0};
+ char szCurrentVersion[30];
+
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = pluginInfo.shortName;
+
+ upd.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ upd.szBetaVersionURL = "http://pescuma.org/miranda/voiceservice_version.txt";
+ upd.szBetaChangelogURL = "http://pescuma.org/miranda/voiceservice#Changelog";
+ upd.pbBetaVersionPrefix = (BYTE *)"Voice Service ";
+ upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix);
+#ifdef UNICODE
+ upd.szBetaUpdateURL = "http://pescuma.org/miranda/voiceserviceW.zip";
+#else
+ upd.szBetaUpdateURL = "http://pescuma.org/miranda/voiceservice.zip";
+#endif
+
+ upd.pbVersion = (BYTE *)CreateVersionStringPlugin((PLUGININFO*) &pluginInfo, szCurrentVersion);
+ upd.cpbVersion = strlen((char *)upd.pbVersion);
+
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+ }
+
+ // Init icons
+ {
+ IcoLib_Register(mainIcons[0], _T("Voice Calls"), _T("Main"), IDI_MAIN);
+ IcoLib_Register(mainIcons[1], _T("Voice Calls"), _T("Dialpad"), IDI_DIALPAD);
+ IcoLib_Register(mainIcons[2], _T("Voice Calls"), _T("Secure Overlay"), IDI_SECURE);
+
+ int i;
+ for(i = 0; i < MAX_REGS(stateNames); i++)
+ IcoLib_Register(stateIcons[i], _T("Voice Calls"), stateNames[i], IDI_TALKING + i);
+
+ for(i = 0; i < MAX_REGS(actionNames); i++)
+ IcoLib_Register(actionIcons[i], _T("Voice Calls"), actionNames[i], IDI_ACTION_CALL + i);
+
+ hHooks.push_back( HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged) );
+ }
+
+ // Init fonts
+ {
+ FontIDT fi = {0};
+ fi.cbSize = sizeof(fi);
+ lstrcpyn(fi.group, TranslateT("Voice Calls"), MAX_REGS(fi.group));
+ strncpy(fi.dbSettingsGroup, MODULE_NAME, MAX_REGS(fi.dbSettingsGroup));
+
+ for (int i = 0; i < NUM_FONTS; i++)
+ {
+ fi.order = i;
+ lstrcpyn(fi.name, stateNames[i], MAX_REGS(fi.name));
+ strncpy(fi.prefix, stateIcons[i], MAX_REGS(fi.prefix));
+
+ CallService(MS_FONT_REGISTERT, (WPARAM) &fi, 0);
+ }
+
+ ReloadFont(0,0);
+ hHooks.push_back( HookEvent(ME_FONT_RELOAD, ReloadFont) );
+ }
+
+ // Init bkg color
+ {
+ ColourIDT ci = {0};
+ ci.cbSize = sizeof(ci);
+ lstrcpyn(ci.group, TranslateT("Voice Calls"), MAX_REGS(ci.group));
+ lstrcpyn(ci.name, TranslateT("Background"), MAX_REGS(ci.name));
+ strncpy(ci.dbSettingsGroup, MODULE_NAME, MAX_REGS(ci.dbSettingsGroup));
+ strncpy(ci.setting, "BkgColor", MAX_REGS(ci.setting));
+ ci.defcolour = GetSysColor(COLOR_BTNFACE);
+
+ CallService(MS_COLOUR_REGISTERT, (WPARAM) &ci, 0);
+
+ ReloadColor(0,0);
+ hHooks.push_back( HookEvent(ME_COLOUR_RELOAD, ReloadColor) );
+ }
+
+ // Init history
+ if (ServiceExists(MS_HISTORYEVENTS_REGISTER))
+ {
+ char *templates[] = {
+ "Talking\nCall from %number% has started\n%number%\tOther side of the call",
+ "Ringing\nCall from %number% is ringing\n%number%\tOther side of the call",
+ "Calling\nCalling %number%\n%number%\tOther side of the call",
+ "On Hold\nCall from %number% is on hold\n%number%\tOther side of the call",
+ "Ended\nCall from %number% has ended\n%number%\tOther side of the call",
+ "Busy\n%number% is busy\n%number%\tOther side of the call",
+ };
+
+ HISTORY_EVENT_HANDLER heh = {0};
+ heh.cbSize = sizeof(heh);
+ heh.module = MODULE_NAME;
+ heh.name = "VoiceCall";
+ heh.description = "Voice calls";
+ heh.eventType = EVENTTYPE_VOICE_CALL;
+ heh.defaultIconName = "vca_call";
+ heh.supports = HISTORYEVENTS_FORMAT_TCHAR;
+ heh.flags = HISTORYEVENTS_FLAG_SHOW_IM_SRMM
+ | HISTORYEVENTS_FLAG_USE_SENT_FLAG
+ | HISTORYEVENTS_REGISTERED_IN_ICOLIB;
+ heh.templates = templates;
+ heh.numTemplates = MAX_REGS(templates);
+ CallService(MS_HISTORYEVENTS_REGISTER, (WPARAM) &heh, 0);
+ }
+
+ InitOptions();
+ InitFrames();
+
+ // Add menu items
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000020000;
+ mi.flags = CMIF_TCHAR;
+
+ HICON icons[MAX_REGS(actionIcons)];
+ for(int i = 0; i < MAX_REGS(actionIcons); ++i)
+ icons[i] = IcoLib_LoadIcon(actionIcons[i]);
+
+ CreateServiceFunction(MS_VOICESERVICE_CM_CALL, Service_Call);
+ mi.ptszName = actionNames[ACTION_CALL];
+ mi.hIcon = icons[ACTION_CALL];
+ mi.pszService = MS_VOICESERVICE_CM_CALL;
+ hCMCall = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ CreateServiceFunction(MS_VOICESERVICE_CM_ANSWER, CMAnswer);
+ mi.position++;
+ mi.ptszName = actionNames[ACTION_ANSWER];
+ mi.hIcon = icons[ACTION_ANSWER];
+ mi.pszService = MS_VOICESERVICE_CM_ANSWER;
+ hCMAnswer = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ CreateServiceFunction(MS_VOICESERVICE_CM_HOLD, CMHold);
+ mi.position++;
+ mi.position++;
+ mi.ptszName = actionNames[ACTION_HOLD];
+ mi.hIcon = icons[ACTION_HOLD];
+ mi.pszService = MS_VOICESERVICE_CM_HOLD;
+ hCMHold = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ CreateServiceFunction(MS_VOICESERVICE_CM_DROP, CMDrop);
+ mi.position++;
+ mi.ptszName = actionNames[ACTION_DROP];
+ mi.hIcon = icons[ACTION_DROP];
+ mi.pszService = MS_VOICESERVICE_CM_DROP;
+ hCMDrop = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ for(i = 0; i < MAX_REGS(actionIcons); ++i)
+ IcoLib_ReleaseIcon(icons[i]);
+
+ hHooks.push_back( HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PreBuildContactMenu) );
+
+ // Util services
+ CreateServiceFunction(MS_VOICESERVICE_CALL, Service_Call);
+ CreateServiceFunction(MS_VOICESERVICE_CAN_CALL, Service_CanCall);
+
+ // Sounds
+ SKINSOUNDDESCEX ssd = {0};
+ ssd.cbSize = sizeof(ssd);
+ ssd.pszSection = "Voice Calls";
+
+ {
+ for(int i = 0; i < MAX_REGS(sounds); ++i)
+ {
+ ssd.pszName = sounds[i].name;
+ ssd.pszDescription = sounds[i].description;
+ CallService(MS_SKIN_ADDNEWSOUND, 0, (LPARAM)&ssd);
+ }
+ }
+
+ SetTimer(NULL, 0, 1000, ClearOldVoiceCalls);
+
+ // Accounts
+ int numAccounts;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&numAccounts, &accounts);
+ for(i = 0; i < numAccounts; ++i)
+ AddAccount(accounts[i]);
+
+ hHooks.push_back( HookEvent(ME_PROTO_ACCLISTCHANGED, AccListChanged) );
+
+ return 0;
+}
+
+
+static INT_PTR AccListChanged(WPARAM wParam, LPARAM lParam)
+{
+ PROTOACCOUNT *acc = (PROTOACCOUNT *) lParam;
+ if (acc == NULL)
+ return 0;
+
+ VoiceProvider *provider = FindModule(acc->szModuleName);
+
+ switch(wParam)
+ {
+ case PRAC_ADDED:
+ {
+ AddAccount(acc);
+ break;
+ }
+ case PRAC_CHANGED:
+ {
+ if (provider != NULL)
+ lstrcpyn(provider->description, acc->tszAccountName, MAX_REGS(provider->description));
+ break;
+ }
+ case PRAC_CHECKED:
+ {
+ BOOL enabled = IsAccountEnabled(acc);
+
+ if (!enabled)
+ {
+ if (provider != NULL)
+ VoiceUnregister((WPARAM) acc->szModuleName, 0);
+ }
+ else
+ {
+ if (provider == NULL)
+ AddAccount(acc);
+ }
+ break;
+ }
+ case PRAC_REMOVED:
+ {
+ if (provider != NULL)
+ VoiceUnregister((WPARAM) acc->szModuleName, 0);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+static INT_PTR PreShutdown(WPARAM wParam, LPARAM lParam)
+{
+ DeInitFrames();
+ DeInitOptions();
+
+ for(unsigned int i = 0; i < hHooks.size(); ++i)
+ UnhookEvent(hHooks[i]);
+ hHooks.clear();
+
+ return 0;
+}
+
+
+static INT_PTR ProtoAck(WPARAM wParam, LPARAM lParam)
+{
+ ACKDATA *ack = (ACKDATA*)lParam;
+
+ if (ack->type == ACKTYPE_STATUS)
+ {
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+ }
+
+ return 0;
+}
+
+
+HANDLE ConvertMetacontact(HANDLE hContact)
+{
+ if (ServiceExists(MS_MC_GETMOSTONLINECONTACT))
+ {
+ HANDLE hTmp = (HANDLE) CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM) hContact, NULL);
+ if (hTmp != NULL)
+ return hTmp;
+ }
+ return hContact;
+}
+
+
+VoiceProvider * FindModule(const char *szModule)
+{
+ for(int i = 0; i < modules.getCount(); i++)
+ if (strcmp(modules[i].name, szModule) == 0)
+ return &modules[i];
+
+ return NULL;
+}
+
+
+static bool IsCall(VoiceCall *call, const char *szModule, const char *id)
+{
+ return strcmp(call->module->name, szModule) == 0
+ && call->id != NULL && strcmp(call->id, id) == 0;
+}
+
+
+VoiceCall * FindVoiceCall(const char *szModule, const char *id, bool add)
+{
+ for(int i = 0; i < calls.getCount(); i++)
+ {
+ if (IsCall(&calls[i], szModule, id))
+ {
+ return &calls[i];
+ }
+ }
+
+ if (add)
+ {
+ VoiceProvider *module = FindModule(szModule);
+ if (module == NULL)
+ return NULL;
+
+ VoiceCall *tmp = new VoiceCall(module, id);
+ calls.insert(tmp);
+ return tmp;
+ }
+
+ return NULL;
+}
+
+
+VoiceCall * FindVoiceCall(HANDLE hContact)
+{
+ for(int i = 0; i < calls.getCount(); i++)
+ {
+ if (calls[i].state != VOICE_STATE_ENDED && calls[i].hContact == hContact)
+ {
+ return &calls[i];
+ }
+ }
+
+ return NULL;
+}
+
+
+static void RemoveVoiceCall(const char *szModule, const char *id)
+{
+ for(int i = calls.getCount() - 1; i >= 0; --i)
+ {
+ if (IsCall(&calls[i], szModule, id))
+ calls.remove(i);
+ }
+}
+
+
+static VOID CALLBACK ClearOldVoiceCalls(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ DWORD now = GetTickCount();
+ BOOL refresh = FALSE;
+ for(int i = calls.getCount() - 1; i >= 0; --i)
+ {
+ VoiceCall *call = &calls[i];
+
+ if (call->state == VOICE_STATE_ENDED && call->end_time + TIME_TO_SHOW_ENDED_CALL < now)
+ {
+ calls.remove(i);
+ refresh = TRUE;
+ }
+ }
+
+ if (refresh && hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+}
+
+
+
+static bool IsProtocol(const char *module)
+{
+ PROTOACCOUNT **protos;
+ int count;
+
+ BOOL hasAccounts = ServiceExists(MS_PROTO_ENUMACCOUNTS);
+
+ if (hasAccounts)
+ CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&protos);
+ else
+ CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&count, (LPARAM)&protos);
+
+ for (int i = 0; i < count; i++)
+ {
+ if (protos[i]->type != PROTOTYPE_PROTOCOL)
+ continue;
+
+ if (protos[i]->szModuleName == NULL || protos[i]->szModuleName[0] == '\0')
+ continue;
+
+ if (strcmp(module, protos[i]->szModuleName) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+
+static INT_PTR VoiceRegister(WPARAM wParam, LPARAM lParam)
+{
+ VOICE_MODULE *in = (VOICE_MODULE *) wParam;
+ if (in == NULL || in->cbSize < sizeof(VOICE_MODULE) || in->name == NULL || in->description == NULL)
+ return -1;
+
+ if (FindModule(in->name) != NULL)
+ return -2;
+
+ if (!ProtoServiceExists(in->name, PS_VOICE_CALL)
+ || !ProtoServiceExists(in->name, PS_VOICE_ANSWERCALL)
+ || !ProtoServiceExists(in->name, PS_VOICE_DROPCALL))
+ return -3;
+
+ modules.insert(new VoiceProvider(in->name, in->description, in->flags, in->icon));
+
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+
+ return 0;
+}
+
+
+static INT_PTR VoiceUnregister(WPARAM wParam, LPARAM lParam)
+{
+ char *moduleName = (char *) wParam;
+ if (moduleName == NULL || moduleName[0] == 0)
+ return -1;
+
+ VoiceProvider *module = FindModule(moduleName);
+ if (module == NULL)
+ return -2;
+
+ for(int i = calls.getCount() - 1; i >= 0; --i)
+ {
+ VoiceCall *call = &calls[i];
+
+ if (call->module == module)
+ {
+ call->Drop();
+ call->SetState(VOICE_STATE_ENDED);
+
+ calls.remove(i);
+ }
+ }
+
+ modules.remove(module);
+
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+
+ return 0;
+}
+
+
+bool CanCall(HANDLE hContact, BOOL now)
+{
+ for(int i = 0; i < modules.getCount(); i++)
+ {
+ if (modules[i].CanCall(hContact, now))
+ return true;
+ }
+
+ return false;
+}
+
+
+bool CanCall(const TCHAR *number)
+{
+ for(int i = 0; i < modules.getCount(); i++)
+ {
+ if (modules[i].CanCall(number))
+ return true;
+ }
+
+ return false;
+}
+
+
+bool CanCallNumber()
+{
+ for(int i = 0; i < modules.getCount(); i++)
+ {
+ if (modules[i].flags & VOICE_CAPS_CALL_STRING)
+ return true;
+ }
+
+ return false;
+}
+
+
+bool IsFinalState(int state)
+{
+ return state == VOICE_STATE_ENDED || state == VOICE_STATE_BUSY;
+}
+
+
+VoiceCall * GetTalkingCall()
+{
+ for(int i = 0; i < calls.getCount(); ++i)
+ {
+ VoiceCall *call = &calls[i];
+
+ if (call->state == VOICE_STATE_TALKING)
+ return call;
+ }
+
+ return NULL;
+}
+
+
+static void HoldOtherCalls(VoiceCall *call)
+{
+ for(int i = 0; i < calls.getCount(); ++i)
+ {
+ VoiceCall *other = &calls[i];
+
+ if (other == call || other->state != VOICE_STATE_TALKING)
+ continue;
+
+ if (other->CanHold())
+ other->Hold();
+ else
+ other->Drop();
+ }
+}
+
+
+void Answer(VoiceCall *call)
+{
+ if (!call->CanAnswer())
+ return;
+
+ HoldOtherCalls(call);
+
+ // Now annswer it
+ call->Answer();
+}
+
+
+static INT_PTR VoiceState(WPARAM wParam, LPARAM lParam)
+{
+ VOICE_CALL *in = (VOICE_CALL *) wParam;
+ if (in == NULL || in->cbSize < sizeof(VOICE_CALL) || in->moduleName == NULL || in->id == NULL)
+ return 0;
+
+ // Check if the call is aready in list
+ VoiceCall *call = FindVoiceCall(in->moduleName, in->id, !IsFinalState(in->state));
+ if (call == NULL)
+ return 0;
+
+ call->AppendCallerID(in->hContact,
+ (in->flags & VOICE_UNICODE) ? WcharToTchar(in->pwszName).get() : CharToTchar(in->pszName).get(),
+ (in->flags & VOICE_UNICODE) ? WcharToTchar(in->pwszNumber).get() : CharToTchar(in->pszNumber).get());
+ call->secure = (in->flags & VOICE_SECURE) != 0;
+
+ if (in->state == VOICE_STATE_RINGING && call->hContact != NULL)
+ {
+ int aut = DBGetContactSettingWord(call->hContact, MODULE_NAME, "AutoAccept", AUTO_NOTHING);
+ if (aut == AUTO_ACCEPT || aut == AUTO_DROP)
+ {
+ call->state = VOICE_STATE_RINGING;
+ call->Notify(true, false, false, false);
+
+ if (aut == AUTO_ACCEPT)
+ Answer(call);
+ else
+ call->Drop();
+
+ return 0;
+ }
+ }
+
+ if (in->state == VOICE_STATE_TALKING)
+ HoldOtherCalls(call);
+
+ call->SetState(in->state);
+
+ return 0;
+}
+
+
+static INT_PTR IconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+
+ return 0;
+}
+
+
+static INT_PTR ReloadFont(WPARAM wParam, LPARAM lParam)
+{
+ FontIDT fi = {0};
+ fi.cbSize = sizeof(fi);
+ lstrcpyn(fi.group, TranslateT("Voice Calls"), MAX_REGS(fi.group));
+
+ font_max_height = 0;
+ for (int i = 0; i < NUM_FONTS; i++)
+ {
+ if (fonts[i] != 0) DeleteObject(fonts[i]);
+
+ lstrcpyn(fi.name, stateNames[i], MAX_REGS(fi.name));
+
+ LOGFONT log_font = {0};
+ font_colors[i] = CallService(MS_FONT_GETT, (WPARAM) &fi, (LPARAM) &log_font);
+ fonts[i] = CreateFontIndirect(&log_font);
+
+ font_max_height = max(font_max_height, log_font.lfHeight);
+ }
+
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+
+ return 0;
+}
+
+
+static INT_PTR ReloadColor(WPARAM wParam, LPARAM lParam)
+{
+ ColourIDT ci = {0};
+ ci.cbSize = sizeof(ci);
+ lstrcpyn(ci.group, TranslateT("Voice Calls"), MAX_REGS(ci.group));
+ lstrcpyn(ci.name, TranslateT("Background"), MAX_REGS(ci.name));
+
+ bkg_color = CallService(MS_COLOUR_GETT, (WPARAM) &ci, 0);
+
+ if (bk_brush != NULL)
+ DeleteObject(bk_brush);
+ bk_brush = CreateSolidBrush(bkg_color);
+
+ if (hwnd_frame != NULL)
+ InvalidateRect(hwnd_frame, NULL, TRUE);
+
+ return 0;
+}
+
+
+static INT_PTR CListDblClick(WPARAM wParam, LPARAM lParam)
+{
+ CLISTEVENT *ce = (CLISTEVENT *) lParam;
+
+ VoiceCall *call = (VoiceCall *) ce->lParam;
+
+ HWND hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_NEW_CALL), NULL, DlgProcNewCall, (LPARAM) call);
+
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+
+ call->SetNewCallHWND(hwnd);
+
+ return 0;
+}
+
+
+static INT_PTR Service_CanCall(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ return CanCall(hContact) ? 1 : 0;
+}
+
+
+static INT_PTR Service_Call(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ OBJLIST<CallingMethod> methods(10, sttCompareCallingMethods);
+ BuildCallingMethodsList(&methods, hContact);
+
+ if (methods.getCount() < 1)
+ return -2;
+
+ CallingMethod *method = &methods[0];
+ if (!IsEmpty(method->number))
+ return -2;
+
+ method->Call();
+
+ return 0;
+}
+
+
+static INT_PTR Service_CallItem(WPARAM wParam, LPARAM lParam, LPARAM param)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ int index = (int) param;
+
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ OBJLIST<CallingMethod> methods(10, sttCompareCallingMethods);
+ BuildCallingMethodsList(&methods, hContact);
+
+ if (index < 0 || index >= methods.getCount())
+ return -2;
+
+ methods[index].Call();
+
+ return 0;
+}
+
+
+static INT_PTR CMAnswer(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ VoiceCall *call = FindVoiceCall(hContact);
+ if (call != NULL)
+ Answer(call);
+
+ return 0;
+}
+
+
+static INT_PTR CMHold(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ VoiceCall *call = FindVoiceCall(hContact);
+ if (call != NULL)
+ call->Hold();
+
+ return 0;
+}
+
+
+static INT_PTR CMDrop(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ VoiceCall *call = FindVoiceCall(hContact);
+ if (call != NULL)
+ call->Drop();
+
+ return 0;
+}
+
+
+static void HideMenuItem(HANDLE hMenu)
+{
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN | CMIF_TCHAR;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hMenu, (LPARAM) &mi);
+}
+
+
+static void ShowMenuItem(HANDLE hMenu)
+{
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_TCHAR;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hMenu, (LPARAM) &mi);
+}
+
+
+static INT_PTR PreBuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ HideMenuItem(hCMCall);
+ HideMenuItem(hCMAnswer);
+ HideMenuItem(hCMHold);
+ HideMenuItem(hCMDrop);
+ for(unsigned int i = 0; i < hCMCalls.size(); ++i)
+ HideMenuItem(hCMCalls[i]);
+
+ HANDLE hContact = (HANDLE) wParam;
+ if (hContact == NULL)
+ return -1;
+
+ hContact = ConvertMetacontact(hContact);
+
+ // There is a current call already?
+ VoiceCall *call = FindVoiceCall(hContact);
+ if (call == NULL)
+ {
+ OBJLIST<CallingMethod> methods(10, sttCompareCallingMethods);
+ BuildCallingMethodsList(&methods, hContact);
+
+ if (methods.getCount() == 1)
+ {
+ CallingMethod *method = &methods[0];
+
+ TCHAR name[128];
+ if (!IsEmpty(method->number))
+ mir_sntprintf(name, MAX_REGS(name), TranslateT("Call %s with %s"),
+ method->number, method->provider->description);
+ else
+ mir_sntprintf(name, MAX_REGS(name), TranslateT("Call with %s"),
+ method->provider->description);
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_TCHAR | CMIM_NAME;
+ mi.ptszName = name;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hCMCall, (LPARAM) &mi);
+ }
+ else if (methods.getCount() > 1)
+ {
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_TCHAR | CMIM_NAME;
+ mi.ptszName = _T("Call");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hCMCall, (LPARAM) &mi);
+
+ for(int i = 0; i < methods.getCount(); ++i)
+ {
+ CallingMethod *method = &methods[i];
+
+ HICON hIcon = method->provider->GetIcon();
+
+ TCHAR name[128];
+ if (!IsEmpty(method->number))
+ mir_sntprintf(name, MAX_REGS(name), TranslateT("%s with %s"),
+ method->number, method->provider->description);
+ else
+ mir_sntprintf(name, MAX_REGS(name), TranslateT("with %s"),
+ method->provider->description);
+
+ char service[128];
+ mir_snprintf(service, MAX_REGS(service), "VoiceService/ContactMenu/Call_%d", i);
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.position = i;
+ mi.flags = CMIF_TCHAR | CMIF_ROOTHANDLE;
+ mi.ptszName = name;
+ mi.hIcon = hIcon;
+ mi.pszService = service;
+ mi.hParentMenu = (HGENMENU) hCMCall;
+
+ if (i == hCMCalls.size())
+ {
+ CreateServiceFunctionParam(service, Service_CallItem, i);
+
+ HANDLE hMenu = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ hCMCalls.push_back(hMenu);
+ }
+ else
+ {
+ HANDLE hMenu = hCMCalls[i];
+
+ mi.flags = mi.flags | CMIM_ALL;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hMenu, (LPARAM) &mi);
+ }
+
+ method->provider->ReleaseIcon(hIcon);
+ }
+ }
+ }
+ else
+ {
+ switch (call->state)
+ {
+ case VOICE_STATE_CALLING:
+ {
+ ShowMenuItem(hCMDrop);
+ break;
+ }
+ case VOICE_STATE_TALKING:
+ {
+ if (call->module->CanHold())
+ ShowMenuItem(hCMHold);
+ ShowMenuItem(hCMDrop);
+ break;
+ }
+ case VOICE_STATE_RINGING:
+ case VOICE_STATE_ON_HOLD:
+ {
+ ShowMenuItem(hCMAnswer);
+ ShowMenuItem(hCMDrop);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+static BOOL CALLBACK DlgProcNewCall(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ VoiceCall *call = (VoiceCall *) lParam;
+
+ TranslateDialogDefault(hwndDlg);
+
+ TCHAR text[1024];
+
+ VoiceCall *currentCall = GetTalkingCall();
+ if (currentCall == NULL)
+ {
+ mir_sntprintf(text, MAX_REGS(text), TranslateT("%s wants to start a voice call with you. What you want to do?"),
+ call->displayName);
+ }
+ else if (currentCall->CanHold())
+ {
+ mir_sntprintf(text, MAX_REGS(text), TranslateT("%s wants to start a voice call with you. What you want to do?\n\nIf you answer the call, the current call will be put on hold."),
+ call->displayName);
+ }
+ else
+ {
+ mir_sntprintf(text, MAX_REGS(text), TranslateT("%s wants to start a voice call with you. What you want to do?\n\nIf you answer the call, the current call will be dropped."),
+ call->displayName);
+ }
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_TEXT), WM_SETTEXT, 0, (LPARAM) text);
+
+ HICON hIcon = IcoLib_LoadIcon(stateIcons[VOICE_STATE_RINGING]);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
+ IcoLib_ReleaseIcon(hIcon);
+
+ if (call->hContact == NULL)
+ ShowWindow(GetDlgItem(hwndDlg, IDC_AUTO), SW_HIDE);
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) call);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch(wParam)
+ {
+ case ID_ANSWER:
+ {
+ VoiceCall *call = (VoiceCall *) GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (call->hContact != NULL && IsDlgButtonChecked(hwndDlg, IDC_AUTO))
+ DBWriteContactSettingWord(call->hContact, MODULE_NAME, "AutoAccept", AUTO_ACCEPT);
+
+ Answer(call);
+
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ case ID_DROP:
+ {
+ VoiceCall *call = (VoiceCall *) GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (call->hContact != NULL && IsDlgButtonChecked(hwndDlg, IDC_AUTO))
+ DBWriteContactSettingWord(call->hContact, MODULE_NAME, "AutoAccept", AUTO_DROP);
+
+ call->Drop();
+
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ VoiceCall *call = (VoiceCall *) GetWindowLong(hwndDlg, GWL_USERDATA);
+ call->Notify(false, false, false, true);
+
+ DestroyWindow(hwndDlg);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ VoiceCall *call = (VoiceCall *) GetWindowLong(hwndDlg, GWL_USERDATA);
+ call->SetNewCallHWND(NULL);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+VoiceProvider::VoiceProvider(const char *name, const TCHAR *description, int flags, const char *icon)
+{
+ strncpy(this->name, name, MAX_REGS(this->name));
+ this->name[MAX_REGS(this->name)-1] = 0;
+
+ lstrcpyn(this->description, description, MAX_REGS(this->description));
+
+ if (icon == NULL)
+ this->icon[0] = 0;
+ else
+ lstrcpynA(this->icon, icon, MAX_REGS(this->icon));
+
+ this->flags = flags;
+ is_protocol = IsProtocol(name);
+ canHold = (ProtoServiceExists(name, PS_VOICE_HOLDCALL) != 0);
+
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, MAX_REGS(str), "%s%s", name, PE_VOICE_CALL_STATE);
+ state_hook = HookEvent(str, VoiceState);
+}
+
+
+VoiceProvider::~VoiceProvider()
+{
+ UnhookEvent(state_hook);
+ state_hook = NULL;
+}
+
+
+bool VoiceProvider::CanCall(HANDLE hContact, BOOL now)
+{
+ if (hContact == NULL)
+ return false;
+
+ if ((flags & VOICE_CAPS_CALL_CONTACT) == 0)
+ return false;
+
+ if (ProtoServiceExists(name, PS_VOICE_CALL_CONTACT_VALID))
+ return CallProtoService(name, PS_VOICE_CALL_CONTACT_VALID, (WPARAM) hContact, now) != FALSE;
+
+ if (is_protocol)
+ {
+ if (now && CallProtoService(name, PS_GETSTATUS, 0, 0) <= ID_STATUS_OFFLINE)
+ return false;
+
+ if (!CallService(MS_PROTO_ISPROTOONCONTACT, (WPARAM) hContact, (LPARAM) name))
+ return false;
+
+ return DBGetContactSettingWord(hContact, name, "Status", ID_STATUS_OFFLINE) > ID_STATUS_OFFLINE;
+ }
+
+ return true;
+}
+
+bool VoiceProvider::CanCall(const TCHAR *number)
+{
+ if (number == NULL || number[0] == 0)
+ return false;
+
+ if ((flags & VOICE_CAPS_CALL_STRING) == 0)
+ return false;
+
+ if (ProtoServiceExists(name, PS_VOICE_CALL_STRING_VALID))
+ return CallProtoService(name, PS_VOICE_CALL_STRING_VALID, (WPARAM) number, 0) != FALSE;
+
+ if (is_protocol)
+ {
+ return CallProtoService(name, PS_GETSTATUS, 0, 0) > ID_STATUS_OFFLINE;
+ }
+
+ return true;
+}
+
+bool VoiceProvider::CanHold()
+{
+ return canHold;
+}
+
+bool VoiceProvider::CanSendDTMF()
+{
+ return ProtoServiceExists(name, PS_VOICE_SEND_DTMF) != FALSE;
+}
+
+void VoiceProvider::Call(HANDLE hContact, const TCHAR *number)
+{
+ CallProtoService(name, PS_VOICE_CALL, (WPARAM) hContact, (LPARAM) number);
+}
+
+HICON VoiceProvider::GetIcon()
+{
+ if (!IsEmptyA(icon))
+ {
+ return IcoLib_LoadIcon(icon);
+ }
+ else if (is_protocol)
+ {
+ return LoadSkinnedProtoIcon(name, ID_STATUS_ONLINE);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void VoiceProvider::ReleaseIcon(HICON hIcon)
+{
+ if (hIcon == NULL)
+ return;
+
+ if (!IsEmptyA(icon))
+ IcoLib_ReleaseIcon(hIcon);
+}
+
+
+
+
+VoiceCall::VoiceCall(VoiceProvider *module, const char *id)
+ : module(module), id(mir_strdup(id))
+{
+ hContact = NULL;
+ name[0] = 0;
+ number[0] = 0;
+ displayName[0] = 0;
+ state = -1;
+ end_time = 0;
+ clistBlinking = false;
+ incoming = false;
+ secure = false;
+ hwnd = NULL;
+ CreateDisplayName();
+}
+
+VoiceCall::~VoiceCall()
+{
+ RemoveNotifications();
+ mir_free(id);
+ id = NULL;
+}
+
+void VoiceCall::AppendCallerID(HANDLE aHContact, const TCHAR *aName, const TCHAR *aNumber)
+{
+ bool changed = false;
+
+ if (aHContact != NULL)
+ {
+ hContact = aHContact;
+ changed = true;
+ }
+
+ if (!IsEmpty(aName))
+ {
+ lstrcpyn(name, aName, MAX_REGS(name));
+ changed = true;
+ }
+
+ if (!IsEmpty(aNumber))
+ {
+ lstrcpyn(number, aNumber, MAX_REGS(number));
+ changed = true;
+ }
+
+ if (changed)
+ CreateDisplayName();
+}
+
+void VoiceCall::CreateDisplayName()
+{
+ TCHAR *contact = NULL;
+ if (hContact != NULL)
+ contact = (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR);
+
+ TCHAR *nameTmp = NULL;
+ if (lstrcmp(name, number) != 0)
+ nameTmp = name;
+
+ if (contact != NULL)
+ {
+ if (!IsEmpty(number))
+ mir_sntprintf(displayName, MAX_REGS(displayName), _T("%s <%s>"), contact, number);
+ else
+ lstrcpyn(displayName, contact, MAX_REGS(displayName));
+ }
+ else if (!IsEmpty(nameTmp) && !IsEmpty(number))
+ {
+ mir_sntprintf(displayName, MAX_REGS(displayName), _T("%s <%s>"), name, number);
+ }
+ else if (!IsEmpty(nameTmp))
+ {
+ lstrcpyn(displayName, name, MAX_REGS(displayName));
+ }
+ else if (!IsEmpty(number))
+ {
+ lstrcpyn(displayName, number, MAX_REGS(displayName));
+ }
+ else
+ {
+ lstrcpyn(displayName, TranslateT("Unknown number"), MAX_REGS(displayName));
+ }
+}
+
+void VoiceCall::RemoveNotifications()
+{
+ if (hwnd != NULL)
+ {
+ DestroyWindow(hwnd);
+ hwnd = NULL;
+ }
+
+ if (clistBlinking)
+ {
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM) hContact, (LPARAM) this);
+ clistBlinking = false;
+ }
+}
+
+void VoiceCall::SetState(int aState)
+{
+ if (state == aState)
+ return;
+
+ if (aState == VOICE_STATE_RINGING)
+ incoming = true;
+ else if (aState == VOICE_STATE_CALLING)
+ incoming = false;
+
+ RemoveNotifications();
+
+ state = aState;
+
+ if (IsFinished())
+ {
+ if (end_time == 0)
+ end_time = GetTickCount();
+
+ // Remove id because providers can re-use them
+ mir_free(id);
+ id = NULL;
+ }
+
+ Notify();
+}
+
+
+void VoiceCall::Notify(bool history, bool popup, bool sound, bool clist)
+{
+ if (history)
+ {
+ TCHAR *variables[] = {
+ _T("number"), displayName
+ };
+ HistoryEvents_AddToHistoryVars(hContact, EVENTTYPE_VOICE_CALL, state, variables, MAX_REGS(variables),
+ DBEF_READ | (incoming ? 0 : DBEF_SENT));
+ }
+
+ if (popup)
+ {
+ TCHAR text[512];
+ mir_sntprintf(text, MAX_REGS(text), TranslateTS(stateTexts[state]), displayName);
+
+ ShowPopup(NULL, TranslateTS(popupTitles[state]), text);
+ }
+
+ if (sound)
+ SkinPlaySound(sounds[state].name);
+
+ if (clist && state == VOICE_STATE_RINGING)
+ {
+ HICON hIcon = IcoLib_LoadIcon(stateIcons[VOICE_STATE_RINGING]);
+
+ CLISTEVENT ce = {0};
+ ce.cbSize = sizeof(ce);
+ ce.hContact = hContact;
+ ce.hIcon = hIcon;
+ ce.hDbEvent = (HANDLE) this;
+ ce.pszService = MS_VOICESERVICE_CLIST_DBLCLK;
+ ce.lParam = (LPARAM) this;
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) &ce);
+
+ IcoLib_ReleaseIcon(hIcon);
+
+ clistBlinking = true;
+ }
+
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, WMU_REFRESH, 0, 0);
+}
+
+
+bool VoiceCall::IsFinished()
+{
+ return IsFinalState(state);
+}
+
+
+bool VoiceCall::CanDrop()
+{
+ return !IsFinished();
+}
+
+void VoiceCall::Drop()
+{
+ if (!CanDrop())
+ return;
+
+ RemoveNotifications();
+
+ CallProtoService(module->name, PS_VOICE_DROPCALL, (WPARAM) id, 0);
+}
+
+
+bool VoiceCall::CanAnswer()
+{
+ return state == -1 || state == VOICE_STATE_RINGING || state == VOICE_STATE_ON_HOLD;
+}
+
+void VoiceCall::Answer()
+{
+ if (!CanAnswer())
+ return;
+
+ RemoveNotifications();
+
+ CallProtoService(module->name, PS_VOICE_ANSWERCALL, (WPARAM) id, 0);
+}
+
+
+bool VoiceCall::CanHold()
+{
+ return module->CanHold() && (state == -1 || state == VOICE_STATE_TALKING);
+}
+
+void VoiceCall::Hold()
+{
+ if (!CanHold())
+ return;
+
+ RemoveNotifications();
+
+ CallProtoService(module->name, PS_VOICE_HOLDCALL, (WPARAM) id, 0);
+}
+
+bool VoiceCall::CanSendDTMF()
+{
+ return module->CanSendDTMF() && state == VOICE_STATE_TALKING;
+}
+
+void VoiceCall::SendDTMF(TCHAR c)
+{
+ if (!CanSendDTMF())
+ return;
+
+ CallProtoService(module->name, PS_VOICE_SEND_DTMF, (WPARAM) id, (LPARAM) c);
+}
+
+
+
+void VoiceCall::SetNewCallHWND(HWND hwnd)
+{
+ if (hwnd != NULL)
+ RemoveNotifications();
+
+ this->hwnd = hwnd;
+}
\ No newline at end of file diff --git a/Plugins/voiceservice/voiceservice.dsp b/Plugins/voiceservice/voiceservice.dsp new file mode 100644 index 0000000..ba34588 --- /dev/null +++ b/Plugins/voiceservice/voiceservice.dsp @@ -0,0 +1,319 @@ +# Microsoft Developer Studio Project File - Name="voiceservice" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=voiceservice - 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 "voiceservice.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 "voiceservice.mak" CFG="voiceservice - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "voiceservice - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "voiceservice - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "voiceservice - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "voiceservice - 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)" == "voiceservice - 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 libportaudio.lib kernel32.lib user32.lib gdi32.lib comctl32.lib /nologo /base:"0x3EC40000" /dll /map /debug /debugtype:both /machine:I386 /out:"..\..\bin\release\Plugins\voiceservice.dll" /pdbtype:sept /libpath:"lib\portaudio\Release" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "voiceservice - 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\voiceservice.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 libportaudio.lib kernel32.lib user32.lib gdi32.lib comctl32.lib /nologo /base:"0x3EC40000" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug\Plugins\voiceservice.dll" /libpath:"lib\portaudio\Debug" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "voiceservice - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "voiceservice___Win32_Unicode_Debug"
+# PROP BASE Intermediate_Dir "voiceservice___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\voiceservice.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 libportaudio.lib kernel32.lib user32.lib gdi32.lib comctl32.lib /nologo /base:"0x3EC40000" /dll /incremental:yes /debug /machine:I386 /out:"..\..\bin\debug unicode\Plugins\voiceserviceW.dll" /libpath:"lib\portaudio\Debug" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ELSEIF "$(CFG)" == "voiceservice - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "voiceservice___Win32_Unicode_Release"
+# PROP BASE Intermediate_Dir "voiceservice___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\voiceservice.dll" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT BASE LINK32 /profile /pdb:none
+# ADD LINK32 libportaudio.lib kernel32.lib user32.lib gdi32.lib comctl32.lib /nologo /base:"0x3EC40000" /dll /map /debug /debugtype:both /machine:I386 /out:"..\..\bin\release\Plugins\voiceserviceW.dll" /pdbtype:sept /libpath:"lib\portaudio\Release" /filealign:0x200 /ALIGN:4096 /ignore:4108
+# SUBTRACT LINK32 /profile /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "voiceservice - Win32 Release"
+# Name "voiceservice - Win32 Debug"
+# Name "voiceservice - Win32 Unicode Debug"
+# Name "voiceservice - 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=.\frame.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_voice.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\m_voiceservice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_dbutils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_icons.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_memory.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_options.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\popup.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=.\res\Answer.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Busy.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Call.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Calling.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\dialpad.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Drop.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\ended.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Hold.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Main.ico
+# End Source File
+# Begin Source File
+
+SOURCE=".\res\On hold.ico"
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Rinning.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\secure.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\smalldot.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Talking.ico
+# 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=.\frame.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_icons.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\utils\mir_options.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\popup.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\voiceservice.cpp
+# End Source File
+# End Group
+# Begin Group "Docs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\Docs\langpack_voiceservice.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\voiceservice_changelog.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\voiceservice_readme.txt
+# End Source File
+# Begin Source File
+
+SOURCE=.\Docs\voiceservice_version.txt
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/Plugins/voiceservice/voiceservice.dsw b/Plugins/voiceservice/voiceservice.dsw new file mode 100644 index 0000000..593eba5 --- /dev/null +++ b/Plugins/voiceservice/voiceservice.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "voiceservice"=.\voiceservice.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
|