summaryrefslogtreecommitdiff
path: root/plugins/WinterSpeak/src
diff options
context:
space:
mode:
authorPhilip Schell <github.com@blubbfish.net>2013-10-19 13:05:02 +0000
committerPhilip Schell <github.com@blubbfish.net>2013-10-19 13:05:02 +0000
commit397e25f2b71347c7c83495fe5b25496ff3b02b75 (patch)
tree71f6ad2ef525218541a7a35cc659b4fb7bf047d6 /plugins/WinterSpeak/src
parent9e786b686fae94e71279a797047a91ffdc4b0443 (diff)
WinterSpeak: ticket:269 WinterSpeak now rewritten
git-svn-id: http://svn.miranda-ng.org/main/trunk@6532 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/WinterSpeak/src')
-rw-r--r--plugins/WinterSpeak/src/AnnounceDatabase.cpp82
-rw-r--r--plugins/WinterSpeak/src/AnnounceDatabase.h64
-rw-r--r--plugins/WinterSpeak/src/AnnounceDialog.cpp149
-rw-r--r--plugins/WinterSpeak/src/AnnounceDialog.h30
-rw-r--r--plugins/WinterSpeak/src/Common.h41
-rw-r--r--plugins/WinterSpeak/src/ConfigDatabase.cpp146
-rw-r--r--plugins/WinterSpeak/src/ConfigDatabase.h79
-rw-r--r--plugins/WinterSpeak/src/DialogConfigActive.cpp376
-rw-r--r--plugins/WinterSpeak/src/DialogConfigActive.h49
-rw-r--r--plugins/WinterSpeak/src/DialogConfigEngine.cpp229
-rw-r--r--plugins/WinterSpeak/src/DialogConfigEngine.h41
-rw-r--r--plugins/WinterSpeak/src/EventInformation.cpp85
-rw-r--r--plugins/WinterSpeak/src/EventInformation.h53
-rw-r--r--plugins/WinterSpeak/src/MirandaDialog.cpp38
-rw-r--r--plugins/WinterSpeak/src/MirandaDialog.h12
-rw-r--r--plugins/WinterSpeak/src/Observer.cpp6
-rw-r--r--plugins/WinterSpeak/src/Observer.h17
-rw-r--r--plugins/WinterSpeak/src/ProtocolInformation.cpp78
-rw-r--r--plugins/WinterSpeak/src/ProtocolInformation.h25
-rw-r--r--plugins/WinterSpeak/src/SpeakAnnounce.cpp206
-rw-r--r--plugins/WinterSpeak/src/SpeakAnnounce.h54
-rw-r--r--plugins/WinterSpeak/src/SpeakConfig.cpp107
-rw-r--r--plugins/WinterSpeak/src/SpeakConfig.h41
-rw-r--r--plugins/WinterSpeak/src/SpeechApi51.cpp253
-rw-r--r--plugins/WinterSpeak/src/SpeechApi51.h83
-rw-r--r--plugins/WinterSpeak/src/SpeechApi51Lexicon.cpp75
-rw-r--r--plugins/WinterSpeak/src/SpeechApi51Lexicon.h35
-rw-r--r--plugins/WinterSpeak/src/SpeechInterface.cpp68
-rw-r--r--plugins/WinterSpeak/src/SpeechInterface.h32
-rw-r--r--plugins/WinterSpeak/src/Subject.cpp55
-rw-r--r--plugins/WinterSpeak/src/Subject.h38
-rw-r--r--plugins/WinterSpeak/src/TextToSpeech.cpp14
-rw-r--r--plugins/WinterSpeak/src/TextToSpeech.h74
-rw-r--r--plugins/WinterSpeak/src/UserInformation.cpp78
-rw-r--r--plugins/WinterSpeak/src/UserInformation.h53
-rw-r--r--plugins/WinterSpeak/src/Version.h14
-rw-r--r--plugins/WinterSpeak/src/m_speak.h4
-rw-r--r--plugins/WinterSpeak/src/main.cpp172
-rw-r--r--plugins/WinterSpeak/src/resource.h71
-rw-r--r--plugins/WinterSpeak/src/stdafx.cpp18
-rw-r--r--plugins/WinterSpeak/src/voice_desc.h10
41 files changed, 3155 insertions, 0 deletions
diff --git a/plugins/WinterSpeak/src/AnnounceDatabase.cpp b/plugins/WinterSpeak/src/AnnounceDatabase.cpp
new file mode 100644
index 0000000000..526d057058
--- /dev/null
+++ b/plugins/WinterSpeak/src/AnnounceDatabase.cpp
@@ -0,0 +1,82 @@
+#include "Common.h"
+#include "AnnounceDatabase.h"
+
+
+//------------------------------------------------------------------------------
+namespace
+{
+ const char *SPEAK = "speak_announce";
+ const char *STATUS_FLAGS = "status_flags";
+ const char *EVENT_FLAGS = "event_flags";
+ const char *MAX_MSG_SIZE = "max_msg_size";
+}
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+AnnounceDatabase::AnnounceDatabase() : m_status_flags(0), m_event_flags(0), m_max_msg(0)
+{
+ load();
+}
+
+//------------------------------------------------------------------------------
+AnnounceDatabase::~AnnounceDatabase()
+{
+}
+
+//------------------------------------------------------------------------------
+bool AnnounceDatabase::getStatusFlag(StatusFlag flag) const
+{
+ return ((m_status_flags & (1 << flag)) != 0);
+}
+
+//------------------------------------------------------------------------------
+void AnnounceDatabase::setStatusFlag(StatusFlag flag, bool state)
+{
+ if (state)
+ {
+ m_status_flags |= (1 << flag);
+ }
+ else
+ {
+ m_status_flags &= ~(1 << flag);
+ }
+}
+
+//------------------------------------------------------------------------------
+bool AnnounceDatabase::getEventFlag(EventFlag flag) const
+{
+ return ((m_event_flags & (1 << flag)) != 0);
+}
+
+//------------------------------------------------------------------------------
+void AnnounceDatabase::setEventFlag(EventFlag flag, bool state)
+{
+ if (state)
+ {
+ m_event_flags |= (1 << flag);
+ }
+ else
+ {
+ m_event_flags &= ~(1 << flag);
+ }
+}
+
+//------------------------------------------------------------------------------
+void AnnounceDatabase::load()
+{
+ m_status_flags = db_get_dw(NULL, SPEAK, STATUS_FLAGS, 0xffff);
+ m_event_flags = db_get_dw(NULL, SPEAK, EVENT_FLAGS, 0xffff);
+ m_max_msg = db_get_dw(NULL, SPEAK, MAX_MSG_SIZE, 50);
+}
+
+//------------------------------------------------------------------------------
+void
+AnnounceDatabase::save()
+{
+ db_set_dw(NULL, SPEAK, STATUS_FLAGS, m_status_flags);
+ db_set_dw(NULL, SPEAK, EVENT_FLAGS, m_event_flags);
+ db_set_dw(NULL, SPEAK, MAX_MSG_SIZE, m_max_msg);
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/AnnounceDatabase.h b/plugins/WinterSpeak/src/AnnounceDatabase.h
new file mode 100644
index 0000000000..06014843ac
--- /dev/null
+++ b/plugins/WinterSpeak/src/AnnounceDatabase.h
@@ -0,0 +1,64 @@
+#pragma once
+
+class AnnounceDatabase
+{
+ public:
+ AnnounceDatabase();
+ ~AnnounceDatabase();
+
+ enum StatusFlag
+ {
+ StatusFlag_Offline = 0,
+ StatusFlag_Online,
+ StatusFlag_Away,
+ StatusFlag_Dnd,
+ StatusFlag_Na,
+ StatusFlag_Occupied,
+ StatusFlag_FreeForChat,
+ StatusFlag_Invisible,
+ StatusFlag_SpeakStatusMsg,
+ StatusFlag_SuppressConnect,
+ };
+
+ enum EventFlag
+ {
+ EventFlag_Message = 0,
+ EventFlag_Url,
+ EventFlag_Added,
+ EventFlag_AuthRequest,
+ EventFlag_File,
+ EventFlag_ReadMsgLength,
+ EventFlag_DialogOpen,
+ EventFlag_DialogFocused,
+ };
+
+ //--------------------------------------------------------------------------
+ // Description : get/set a status flags
+ //--------------------------------------------------------------------------
+ bool getStatusFlag(StatusFlag flag) const;
+ void setStatusFlag(StatusFlag flag, bool state);
+
+ //--------------------------------------------------------------------------
+ // Description : get/set an event flags
+ //--------------------------------------------------------------------------
+ bool getEventFlag(EventFlag flag) const;
+ void setEventFlag(EventFlag flag, bool state);
+
+ //--------------------------------------------------------------------------
+ // Description : get/set an event flags
+ //--------------------------------------------------------------------------
+ unsigned int getMaxMsgSize() const { return m_max_msg; }
+ void setMaxMsgSize(unsigned int size) { m_max_msg = size; }
+
+ //--------------------------------------------------------------------------
+ // Description : load/save the settings from the miranda database
+ //--------------------------------------------------------------------------
+ void load();
+ void save();
+
+ private:
+ unsigned int m_status_flags;
+ unsigned int m_event_flags;
+
+ unsigned int m_max_msg;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/AnnounceDialog.cpp b/plugins/WinterSpeak/src/AnnounceDialog.cpp
new file mode 100644
index 0000000000..11b917b287
--- /dev/null
+++ b/plugins/WinterSpeak/src/AnnounceDialog.cpp
@@ -0,0 +1,149 @@
+#include "Common.h"
+#include "AnnounceDialog.h"
+
+
+AnnounceDialog *AnnounceDialog::m_instance = 0;
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+AnnounceDialog::AnnounceDialog(AnnounceDatabase &db) : m_db(db)
+{
+ m_instance = this;
+}
+
+//------------------------------------------------------------------------------
+AnnounceDialog::~AnnounceDialog()
+{
+ m_instance = 0;
+}
+
+//------------------------------------------------------------------------------
+// private:
+//------------------------------------------------------------------------------
+INT_PTR CALLBACK AnnounceDialog::process(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (!m_instance)
+ {
+ return 1;
+ }
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ m_instance->load(window);
+ break;
+
+ case WM_COMMAND:
+ m_instance->command(window, wparam);
+ break;
+
+ case WM_NOTIFY:
+ if (PSN_APPLY == LPNMHDR(lparam)->code)
+ {
+ m_instance->save(window);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+void AnnounceDialog::command(HWND window, int control)
+{
+ switch (LOWORD(control))
+ {
+ case IDC_STATUS_OFFLINE:
+ case IDC_STATUS_ONLINE:
+ case IDC_STATUS_AWAY:
+ case IDC_STATUS_DND:
+ case IDC_STATUS_NA:
+ case IDC_STATUS_OCCUPIED:
+ case IDC_STATUS_FREEFORCHAT:
+ case IDC_STATUS_INVISIBLE:
+ case IDC_SPEAK_STATUS_MSG:
+ case IDC_SUPPRESS_CONNECT:
+ case IDC_EVENT_MESSAGE:
+ case IDC_EVENT_URL:
+ case IDC_EVENT_FILE:
+ case IDC_EVENT_AUTHREQUEST:
+ case IDC_EVENT_ADDED:
+ case IDC_READ_MSG_LENGTH:
+ case IDC_DIALOG_OPEN:
+ case IDC_DIALOG_FOCUSED:
+
+ changed(window);
+ break;
+
+ case IDC_MAX_MSG:
+ if (EN_CHANGE == HIWORD(control))
+ {
+ changed(window);
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+void
+AnnounceDialog::load(HWND window)
+{
+ TranslateDialogDefault(window);
+
+ // initialise the checkboxes
+ CheckDlgButton(window, IDC_STATUS_OFFLINE, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Offline));
+ CheckDlgButton(window, IDC_STATUS_ONLINE, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Online));
+ CheckDlgButton(window, IDC_STATUS_AWAY, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Away));
+ CheckDlgButton(window, IDC_STATUS_DND, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Dnd));
+ CheckDlgButton(window, IDC_STATUS_NA, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Na));
+ CheckDlgButton(window, IDC_STATUS_OCCUPIED, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Occupied));
+ CheckDlgButton(window, IDC_STATUS_FREEFORCHAT, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_FreeForChat));
+ CheckDlgButton(window, IDC_STATUS_INVISIBLE, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Invisible));
+ CheckDlgButton(window, IDC_SPEAK_STATUS_MSG, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_SpeakStatusMsg));
+ CheckDlgButton(window, IDC_SUPPRESS_CONNECT, m_db.getStatusFlag(AnnounceDatabase::StatusFlag_SuppressConnect));
+
+ CheckDlgButton(window, IDC_EVENT_MESSAGE, m_db.getEventFlag(AnnounceDatabase::EventFlag_Message));
+ CheckDlgButton(window, IDC_EVENT_URL, m_db.getEventFlag(AnnounceDatabase::EventFlag_Url));
+ CheckDlgButton(window, IDC_EVENT_FILE, m_db.getEventFlag(AnnounceDatabase::EventFlag_File));
+ CheckDlgButton(window, IDC_EVENT_AUTHREQUEST, m_db.getEventFlag(AnnounceDatabase::EventFlag_AuthRequest));
+ CheckDlgButton(window, IDC_EVENT_ADDED, m_db.getEventFlag(AnnounceDatabase::EventFlag_Added));
+ CheckDlgButton(window, IDC_READ_MSG_LENGTH, m_db.getEventFlag(AnnounceDatabase::EventFlag_ReadMsgLength));
+ CheckDlgButton(window, IDC_DIALOG_OPEN, m_db.getEventFlag(AnnounceDatabase::EventFlag_DialogOpen));
+ CheckDlgButton(window, IDC_DIALOG_FOCUSED, m_db.getEventFlag(AnnounceDatabase::EventFlag_DialogFocused));
+
+ // initialise the welcome message box
+ SetDlgItemInt(window, IDC_MAX_MSG, m_db.getMaxMsgSize(), 0);
+}
+
+//------------------------------------------------------------------------------
+void
+AnnounceDialog::save(HWND window)
+{
+ // store the checkboxes
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Offline, (IsDlgButtonChecked(window, IDC_STATUS_OFFLINE) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Online, (IsDlgButtonChecked(window, IDC_STATUS_ONLINE) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Away, (IsDlgButtonChecked(window, IDC_STATUS_AWAY) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Dnd, (IsDlgButtonChecked(window, IDC_STATUS_DND) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Na, (IsDlgButtonChecked(window, IDC_STATUS_NA) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Occupied, (IsDlgButtonChecked(window, IDC_STATUS_OCCUPIED) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_FreeForChat, (IsDlgButtonChecked(window, IDC_STATUS_FREEFORCHAT) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_Invisible, (IsDlgButtonChecked(window, IDC_STATUS_INVISIBLE) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_SpeakStatusMsg, (IsDlgButtonChecked(window, IDC_SPEAK_STATUS_MSG) != 0));
+ m_db.setStatusFlag(AnnounceDatabase::StatusFlag_SuppressConnect, (IsDlgButtonChecked(window, IDC_SUPPRESS_CONNECT) != 0));
+
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_Message, (IsDlgButtonChecked(window, IDC_EVENT_MESSAGE) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_Url, (IsDlgButtonChecked(window, IDC_EVENT_URL) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_File, (IsDlgButtonChecked(window, IDC_EVENT_FILE) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_AuthRequest, (IsDlgButtonChecked(window, IDC_EVENT_AUTHREQUEST) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_Added, (IsDlgButtonChecked(window, IDC_EVENT_ADDED) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_ReadMsgLength, (IsDlgButtonChecked(window, IDC_READ_MSG_LENGTH) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_DialogOpen, (IsDlgButtonChecked(window, IDC_DIALOG_OPEN) != 0));
+ m_db.setEventFlag(AnnounceDatabase::EventFlag_DialogFocused, (IsDlgButtonChecked(window, IDC_DIALOG_FOCUSED) != 0));
+
+ m_db.setMaxMsgSize(GetDlgItemInt(window, IDC_MAX_MSG, NULL, 0));
+
+ m_instance->m_db.save();
+}
+
+//============================================================================== \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/AnnounceDialog.h b/plugins/WinterSpeak/src/AnnounceDialog.h
new file mode 100644
index 0000000000..3a3da28f9a
--- /dev/null
+++ b/plugins/WinterSpeak/src/AnnounceDialog.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "mirandadialog.h"
+#include "AnnounceDatabase.h"
+
+class AnnounceDialog : public MirandaDialog
+{
+ public:
+ AnnounceDialog(AnnounceDatabase &db);
+ ~AnnounceDialog();
+
+ //--------------------------------------------------------------------------
+ // Description : process a dialog message
+ // Return : true - update the systems configuration
+ // false - do nothing
+ //--------------------------------------------------------------------------
+ static INT_PTR CALLBACK process(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
+
+ private:
+ void command(HWND window, int control);
+
+ //--------------------------------------------------------------------------
+ // Description : load/save settings to the miranda database
+ //--------------------------------------------------------------------------
+ void load(HWND window);
+ void save(HWND window);
+
+ static AnnounceDialog *m_instance;
+ AnnounceDatabase &m_db;
+};
+
diff --git a/plugins/WinterSpeak/src/Common.h b/plugins/WinterSpeak/src/Common.h
new file mode 100644
index 0000000000..cff8761c21
--- /dev/null
+++ b/plugins/WinterSpeak/src/Common.h
@@ -0,0 +1,41 @@
+#define _CRT_SECURE_NO_WARNINGS
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <Winsock2.h>
+
+#include <CommCtrl.h>
+#include <newpluginapi.h>
+#include <m_langpack.h>
+#include <m_genmenu.h>
+#include <m_utils.h>
+#include <win2k.h>
+#include <m_options.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_clistint.h>
+#include <m_skin.h>
+#include <m_icolib.h>
+#include <m_netlib.h>
+#include <m_extraicons.h>
+
+
+#include "resource.h"
+#include "Version.h"
+#include "m_speak.h"
+
+#include "DialogConfigEngine.h"
+#include "DialogConfigActive.h"
+
+#include "AnnounceDialog.h"
+#include "AnnounceDatabase.h"
+#include "SpeakAnnounce.h"
+
+#include "ConfigDatabase.h"
+#include "MirandaDialog.h"
+#include "Subject.h"
+#include "SpeechInterface.h"
+#include "SpeakConfig.h"
+#include "UserInformation.h"
+#include "EventInformation.h"
+#include "ProtocolInformation.h" \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/ConfigDatabase.cpp b/plugins/WinterSpeak/src/ConfigDatabase.cpp
new file mode 100644
index 0000000000..64af1e35f4
--- /dev/null
+++ b/plugins/WinterSpeak/src/ConfigDatabase.cpp
@@ -0,0 +1,146 @@
+#include "Common.h"
+#include "ConfigDatabase.h"
+
+
+namespace
+{
+ const char *SPEAK = "speak_config";
+ const char *ACTIVE_FLAGS = "active_flags";
+ const char *ACTIVE_STATE = "active_state";
+ const char *ACTIVE_MSG = "active_msg";
+ const char *WELCOME_MSG = "welcome_msg";
+ const char *ENGINE = "engine";
+ const char *VOICE = "voice";
+ const char *VOLUME = "volume";
+ const char *RATE = "rate";
+ const char *PITCH = "pitch";
+}
+
+ConfigDatabase::ConfigDatabase() : m_voice_desc(), m_active_flags(0), m_welcome_msg(L""), m_active_users()
+{
+ // load the database from miranda
+ load();
+}
+
+
+ConfigDatabase::~ConfigDatabase(void)
+{
+}
+
+
+bool ConfigDatabase::getActiveFlag(ActiveFlag flag) const
+{
+ return ((m_active_flags & (1 << flag)) != 0);
+}
+
+//------------------------------------------------------------------------------
+void ConfigDatabase::setActiveFlag(ActiveFlag flag, bool state)
+{
+ if (state)
+ {
+ m_active_flags |= (1 << flag);
+ }
+ else
+ {
+ m_active_flags &= ~(1 << flag);
+ }
+}
+
+//------------------------------------------------------------------------------
+ConfigDatabase::act ConfigDatabase::getActiveUser(HANDLE user) const
+{
+ ActiveUsersMap::const_iterator iter = m_active_users.find(user);
+
+ if (iter == m_active_users.end())
+ {
+ // get the unknown user status
+ iter = m_active_users.find(0);
+
+ if (iter == m_active_users.end())
+ {
+ ConfigDatabase::act ret;
+ ret.message = false;
+ ret.status = false;
+ return ret;
+ }
+ }
+
+ return iter->second;
+}
+
+//------------------------------------------------------------------------------
+void ConfigDatabase::setActiveUser(HANDLE user, act state)
+{
+ m_active_users[user].status = state.status;
+ m_active_users[user].message = state.message;
+}
+
+//------------------------------------------------------------------------------
+void ConfigDatabase::load()
+{
+ m_voice_desc.engine = DBGetContactSettingString(SPEAK, ENGINE, L"");
+ m_voice_desc.voice = DBGetContactSettingString(SPEAK, VOICE, L"");
+ m_voice_desc.volume = db_get_dw(NULL, SPEAK, VOLUME, 50);
+ m_voice_desc.pitch = db_get_dw(NULL, SPEAK, PITCH, 50);
+ m_voice_desc.rate = db_get_dw(NULL, SPEAK, RATE, 50);
+
+ m_active_flags = db_get_dw(NULL, SPEAK, ACTIVE_FLAGS, 0xffff);
+
+ m_welcome_msg = DBGetContactSettingString(SPEAK, WELCOME_MSG, L"Welcome to Miranda");
+
+ // iterate through all the users and add them to the list if active
+ HANDLE contact = db_find_first();
+
+ while (NULL != contact)
+ {
+ m_active_users[contact].status = (db_get_b(contact, SPEAK, ACTIVE_STATE, true) != 0);
+ m_active_users[contact].message = (db_get_b(contact, SPEAK, ACTIVE_MSG, true) != 0);
+
+ contact = db_find_next(contact);
+ }
+
+ // load unknown users setting
+ m_active_users[0].status = (db_get_b(NULL, SPEAK, ACTIVE_STATE, true) != 0);
+ m_active_users[0].message = (db_get_b(NULL, SPEAK, ACTIVE_MSG, true) != 0);
+}
+
+//------------------------------------------------------------------------------
+void ConfigDatabase::save()
+{
+ db_set_ts(NULL, SPEAK, ENGINE, m_voice_desc.engine.c_str());
+ db_set_ts(NULL, SPEAK, VOICE, m_voice_desc.voice.c_str());
+ db_set_dw(NULL, SPEAK, VOLUME, m_voice_desc.volume);
+ db_set_dw(NULL, SPEAK, PITCH, m_voice_desc.pitch);
+ db_set_dw(NULL, SPEAK, RATE, m_voice_desc.rate);
+
+ db_set_dw(NULL, SPEAK, ACTIVE_FLAGS, m_active_flags);
+
+ db_set_ts(NULL, SPEAK, WELCOME_MSG, m_welcome_msg.c_str());
+
+ for (ActiveUsersMap::iterator i = m_active_users.begin(); i != m_active_users.end(); ++i)
+ {
+ db_set_b(i->first, SPEAK, ACTIVE_STATE, i->second.status);
+ db_set_b(i->first, SPEAK, ACTIVE_MSG, i->second.message);
+ }
+
+ // notify the subjects that things have changed
+ notify();
+}
+
+//------------------------------------------------------------------------------
+// private:
+//------------------------------------------------------------------------------
+std::wstring ConfigDatabase::DBGetContactSettingString(const char *szModule, const char *szSetting, const WCHAR *def)
+{
+ std::wstring ret = def;
+ DBVARIANT dbv;
+
+ if (!db_get_ts(NULL, szModule, szSetting, &dbv))
+ {
+ ret = dbv.pwszVal;
+ }
+
+ return ret;
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/ConfigDatabase.h b/plugins/WinterSpeak/src/ConfigDatabase.h
new file mode 100644
index 0000000000..5682abf0f0
--- /dev/null
+++ b/plugins/WinterSpeak/src/ConfigDatabase.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <map>
+#include "voice_desc.h"
+#include "Subject.h"
+
+class ConfigDatabase : public Subject
+{
+public:
+ ConfigDatabase(void);
+ ~ConfigDatabase(void);
+
+ enum ActiveFlag
+ {
+ ActiveFlag_Online = 1,
+ ActiveFlag_Away,
+ ActiveFlag_Dnd,
+ ActiveFlag_Na,
+ ActiveFlag_Occupied,
+ ActiveFlag_FreeForChat,
+ ActiveFlag_Invisible
+ };
+
+ struct act {
+ bool status;
+ bool message;
+ };
+
+ typedef std::map<HANDLE, act> ActiveUsersMap;
+
+ //--------------------------------------------------------------------------
+ // Description : get/set the voice description
+ //--------------------------------------------------------------------------
+ VoiceDesc getVoiceDesc() const { return m_voice_desc; }
+ void setVoiceDesc(const VoiceDesc &desc) { m_voice_desc = desc; }
+
+ //--------------------------------------------------------------------------
+ // Description : get/set the welcome message
+ //--------------------------------------------------------------------------
+ const std::wstring & getWelcomeMessage() const { return m_welcome_msg; }
+ void setWelcomeMessage(const std::wstring &msg) { m_welcome_msg = msg; }
+
+ //--------------------------------------------------------------------------
+ // Description : get/set an status flags
+ //--------------------------------------------------------------------------
+ bool getActiveFlag(ActiveFlag flag) const;
+ void setActiveFlag(ActiveFlag flag, bool state);
+
+ //--------------------------------------------------------------------------
+ // Description : get/set the user active flag
+ //--------------------------------------------------------------------------
+ act getActiveUser(HANDLE user) const;
+ void setActiveUser(HANDLE user, act state);
+ ActiveUsersMap getActiveUsers() const { return m_active_users; }
+
+ //--------------------------------------------------------------------------
+ // Description : load/save the settings from the miranda database
+ //--------------------------------------------------------------------------
+ void load();
+ void save();
+
+ private:
+ //--------------------------------------------------------------------------
+ // Description : For some reason this isn't implemented in miranda yet
+ // Just get a string from the db
+ // Parameters : szModule - the entrys' module
+ // szSetting - the entrys' setting
+ // def - default string if entry doesn't exist
+ //--------------------------------------------------------------------------
+ static std::wstring DBGetContactSettingString(const char *szModule,
+ const char *szSetting, const WCHAR *def);
+
+ VoiceDesc m_voice_desc;
+ unsigned int m_active_flags;
+ std::wstring m_welcome_msg;
+ //std::string m_welcome_msg;
+ ActiveUsersMap m_active_users;
+};
+
diff --git a/plugins/WinterSpeak/src/DialogConfigActive.cpp b/plugins/WinterSpeak/src/DialogConfigActive.cpp
new file mode 100644
index 0000000000..8caea38e8b
--- /dev/null
+++ b/plugins/WinterSpeak/src/DialogConfigActive.cpp
@@ -0,0 +1,376 @@
+#include "Common.h"
+#include "DialogConfigActive.h"
+
+//------------------------------------------------------------------------------
+DialogConfigActive *DialogConfigActive::m_instance = 0;
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+DialogConfigActive::DialogConfigActive(ConfigDatabase &db) : m_db(db)
+{
+ m_instance = this;
+}
+
+//------------------------------------------------------------------------------
+DialogConfigActive::~DialogConfigActive()
+{
+ m_instance = 0;
+}
+
+//------------------------------------------------------------------------------
+int CALLBACK DialogConfigActive::process(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (!m_instance)
+ {
+ return 1;
+ }
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ m_instance->load(window);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lparam)->idFrom) {
+ case IDC_ACTIVE_USERS: {
+ m_instance->notify(window, lparam);
+
+ } break;
+ case 0: {
+ switch (reinterpret_cast<LPNMHDR>(lparam)->code)
+ {
+ case PSN_APPLY:
+ m_instance->save(window);
+ break;
+
+ case LVN_ITEMCHANGED:
+ m_instance->changed(window);
+ break;
+ } break;
+ } break;
+ } break;
+ case WM_COMMAND:
+ switch (LOWORD(wparam))
+ {
+ case IDC_ACTIVE_OFFLINE:
+ case IDC_ACTIVE_ONLINE:
+ case IDC_ACTIVE_AWAY:
+ case IDC_ACTIVE_DND:
+ case IDC_ACTIVE_NA:
+ case IDC_ACTIVE_OCCUPIED:
+ case IDC_ACTIVE_FREEFORCHAT:
+ case IDC_ACTIVE_INVISIBLE:
+ m_instance->changed(window);
+ break;
+
+ /*case IDC_ACTIVE_ALL:
+ m_instance->selectAllUsers(window, true);
+ break;*/
+
+ /*case IDC_ACTIVE_NONE:
+ m_instance->selectAllUsers(window, false);
+ break;*/
+
+ case IDC_ACTIVE_USERS:
+ m_instance->changed(window);
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+//------------------------------------------------------------------------------
+// private:
+//------------------------------------------------------------------------------
+void DialogConfigActive::notify(HWND hwndDlg, LPARAM lParam) {
+ switch (((LPNMHDR)lParam)->code) {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ SetAllContactIcons( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS), hwndDlg);
+ //fall through
+ case CLN_CONTACTMOVED:
+ SetListGroupIcons( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS), (HANDLE)SendDlgItemMessage(hwndDlg, IDC_ACTIVE_USERS, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+
+ ResetListOptions( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS));
+ break;
+ case CLN_CHECKCHANGED:
+ m_instance->changed(hwndDlg);
+ break;
+ case NM_CLICK:
+ {
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ if (nm->iColumn == -1)
+ break;
+
+ DWORD hitFlags;
+ HANDLE hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_ACTIVE_USERS, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x, nm->pt.y));
+ if (hItem == NULL || !(hitFlags & CLCHT_ONITEMEXTRA))
+ break;
+
+ if (nm->iColumn == 2) { // ignore all
+ for (int iImage = 0;iImage<2;iImage++)
+ SetIconsForColumn( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS), hItem, hItemAll, iImage, iImage+3);
+ }
+ else if (nm->iColumn == 3) { // ignore none
+ for (int iImage = 0;iImage<2;iImage++)
+ SetIconsForColumn( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS), hItem, hItemAll, iImage, 0);
+ }
+ else {
+ int iImage = SendDlgItemMessage(hwndDlg, IDC_ACTIVE_USERS, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, 0));
+ if (iImage == 0)
+ iImage = nm->iColumn+3;
+ else if (iImage != EMPTY_EXTRA_ICON)
+ iImage = 0;
+ SetIconsForColumn( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS), hItem, hItemAll, nm->iColumn, iImage);
+ }
+ SetListGroupIcons( GetDlgItem(hwndDlg, IDC_ACTIVE_USERS), (HANDLE)SendDlgItemMessage(hwndDlg, IDC_ACTIVE_USERS, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+ m_instance->changed(hwndDlg);
+ }
+ break;
+ }
+}
+
+void DialogConfigActive::load(HWND window)
+{
+ TranslateDialogDefault(window);
+
+ // initialise the checkboxes
+ CheckDlgButton(window, IDC_ACTIVE_ONLINE, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Online));
+ CheckDlgButton(window, IDC_ACTIVE_AWAY, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Away));
+ CheckDlgButton(window, IDC_ACTIVE_DND, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Dnd));
+ CheckDlgButton(window, IDC_ACTIVE_NA, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Na));
+ CheckDlgButton(window, IDC_ACTIVE_OCCUPIED, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Occupied));
+ CheckDlgButton(window, IDC_ACTIVE_FREEFORCHAT, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_FreeForChat));
+ CheckDlgButton(window, IDC_ACTIVE_INVISIBLE, m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Invisible));
+
+ HWND listview = GetDlgItem(window, IDC_ACTIVE_USERS);
+
+ HIMAGELIST hIml = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 3, 3);
+ ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_SMALLDOT);
+ ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_FILLEDBLOB);
+ ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_EMPTYBLOB);
+ ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_EVENT_MESSAGE);
+ ImageList_AddIcon_IconLibLoaded(hIml, SKINICON_OTHER_USERONLINE);
+
+ SendDlgItemMessage(window, IDC_ACTIVE_USERS, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)hIml);
+ for (int i=0; i < SIZEOF(hIcons); i++)
+ hIcons[i] = ImageList_GetIcon(hIml, 1+i, ILD_NORMAL);
+
+ SendDlgItemMessage(window, IDC_ALLICON, STM_SETICON, (WPARAM)hIcons[0], 0);
+ SendDlgItemMessage(window, IDC_NONEICON, STM_SETICON, (WPARAM)hIcons[1], 0);
+ SendDlgItemMessage(window, IDC_MSGICON, STM_SETICON, (WPARAM)hIcons[2], 0);
+ SendDlgItemMessage(window, IDC_ONLINEICON, STM_SETICON, (WPARAM)hIcons[3], 0);
+
+ this->ResetListOptions(listview);
+
+ SendDlgItemMessage(window, IDC_ACTIVE_USERS, CLM_SETEXTRACOLUMNS, 4, 0);
+ {
+ CLCINFOITEM cii = {0};
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT;
+ cii.pszText = TranslateT("** All contacts **");
+ hItemAll = (HANDLE)SendDlgItemMessage(window, IDC_ACTIVE_USERS, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+
+ cii.pszText = TranslateT("** Unknown contacts **");
+ hItemUnknown = (HANDLE)SendDlgItemMessage(window, IDC_ACTIVE_USERS, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ ConfigDatabase::ActiveUsersMap active_users = m_db.getActiveUsers();
+ this->InitialiseItem(listview, hItemUnknown, active_users[0].message, active_users[0].status);
+ }
+ this->SetAllContactIcons(listview, window);
+ this->SetListGroupIcons(GetDlgItem(window, IDC_ACTIVE_USERS), (HANDLE)SendDlgItemMessage(window, IDC_ACTIVE_USERS, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL);
+
+}
+
+void DialogConfigActive::SetAllChildIcons(HWND hwndList, HANDLE hFirstItem, int iColumn, int iImage)
+{
+ HANDLE hItem;
+
+ int 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) {
+ HANDLE 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) {
+ int iOldIcon = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, iColumn);
+ if (iOldIcon != EMPTY_EXTRA_ICON && iOldIcon != iImage)
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+}
+
+void DialogConfigActive::SetIconsForColumn(HWND hwndList, HANDLE hItem, HANDLE hItemAll, int iColumn, int iImage) {
+ switch ( SendMessage(hwndList, CLM_GETITEMTYPE, (WPARAM)hItem, 0)) {
+ case CLCIT_CONTACT:
+ {
+ int oldiImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, iColumn);
+ if (oldiImage != EMPTY_EXTRA_ICON && oldiImage != iImage)
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage));
+ }
+ break;
+ case CLCIT_INFO:
+ if (hItem == hItemAll)
+ SetAllChildIcons(hwndList, hItem, iColumn, iImage);
+ else
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(iColumn, iImage)); //hItemUnknown
+ break;
+
+ case CLCIT_GROUP:
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
+ if (hItem)
+ SetAllChildIcons(hwndList, hItem, iColumn, iImage);
+ }
+}
+
+void DialogConfigActive::InitialiseItem(HWND hwndList, HANDLE hItem, bool message, bool status) {
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(0, (message)?0:3)); //Message
+
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(1, (status)?0:4)); //Online
+
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(2, 1));
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(3, 2));
+}
+
+void DialogConfigActive::SetAllContactIcons(HWND hwndList, HWND window) {
+ ConfigDatabase::ActiveUsersMap active_users = m_db.getActiveUsers();
+ ConfigDatabase::ActiveUsersMap::const_iterator iter;
+ for (iter = active_users.begin(); iter != active_users.end(); ++iter)
+ {
+ HANDLE hContact = iter->first;
+ if(hContact == 0) {
+
+ } else {
+ HANDLE hItem = (HANDLE)SendMessage(hwndList, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem && SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(1, 0)) == EMPTY_EXTRA_ICON) {
+ this->InitialiseItem(hwndList, hItem, iter->second.message, iter->second.status);
+ }
+ }
+ }
+}
+
+void DialogConfigActive::ResetListOptions(HWND listview) {
+ SendMessage(listview, CLM_SETBKBITMAP, 0, (LPARAM)(HBITMAP)NULL);
+ SendMessage(listview, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendMessage(listview, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendMessage(listview, CLM_SETLEFTMARGIN, 2, 0);
+ SendMessage(listview, CLM_SETINDENT, 10, 0);
+ SendMessage(listview, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+
+ for (int i=0; i <= FONTID_MAX; i++)
+ SendMessage(listview, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+
+ SetWindowLong(listview, GWL_STYLE, GetWindowLong(listview, GWL_STYLE) | CLS_SHOWHIDDEN);
+}
+
+void DialogConfigActive::SetListGroupIcons(HWND hwndList, HANDLE hFirstItem, HANDLE hParentItem, int *groupChildCount) {
+ int iconOn[2] = {1, 1};
+ int childCount[2] = {0, 0}, i;
+ int iImage;
+ HANDLE hItem, hChildItem;
+
+ int 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 < SIZEOF(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 < SIZEOF(iconOn); i++) {
+ iImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i);
+ if (iconOn[i] && iImage == 0) iconOn[i] = 0;
+ if (iImage != EMPTY_EXTRA_ICON)
+ childCount[i]++;
+ }
+ hItem = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_NEXTCONTACT, (LPARAM)hItem);
+ }
+ //set icons
+ for (i=0; i < SIZEOF(iconOn); i++) {
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(i, childCount[i]?(iconOn[i]?i+3:0) : EMPTY_EXTRA_ICON));
+ if (groupChildCount) groupChildCount[i]+=childCount[i];
+ }
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(2, 1));
+ SendMessage(hwndList, CLM_SETEXTRAIMAGE, (WPARAM)hParentItem, MAKELPARAM(3, 2));
+}
+
+//------------------------------------------------------------------------------
+void DialogConfigActive::save(HWND window)
+{
+ // store the checkboxes
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_Online, (IsDlgButtonChecked(window, IDC_ACTIVE_ONLINE) != 0));
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_Away, (IsDlgButtonChecked(window, IDC_ACTIVE_AWAY) != 0));
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_Dnd, (IsDlgButtonChecked(window, IDC_ACTIVE_DND) != 0));
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_Na, (IsDlgButtonChecked(window, IDC_ACTIVE_NA) != 0));
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_Occupied, (IsDlgButtonChecked(window, IDC_ACTIVE_OCCUPIED) != 0));
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_FreeForChat, (IsDlgButtonChecked(window, IDC_ACTIVE_FREEFORCHAT) != 0));
+ m_db.setActiveFlag(ConfigDatabase::ActiveFlag_Invisible, (IsDlgButtonChecked(window, IDC_ACTIVE_INVISIBLE) != 0));
+
+ for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
+ HANDLE hItem = (HANDLE)SendDlgItemMessage(window, IDC_ACTIVE_USERS, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SaveItemMask(GetDlgItem(window, IDC_ACTIVE_USERS), hContact, hItem);
+ }
+
+ SaveItemMask( GetDlgItem(window, IDC_ACTIVE_USERS), NULL, hItemUnknown);
+
+ m_db.save();
+}
+
+void DialogConfigActive::SaveItemMask(HWND hwndList, HANDLE hContact, HANDLE hItem) {
+ ConfigDatabase::act mask;
+ mask.message = true;
+ mask.status = true;
+ for (int i=0; i < 2; i++) {
+ int iImage = SendMessage(hwndList, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(i, 0));
+ if (iImage && iImage != EMPTY_EXTRA_ICON) {
+ if(i == 1) { //Online
+ mask.status = false;
+ }
+ if(i == 0) { //message
+ mask.message = false;
+ }
+ }
+ }
+ m_db.setActiveUser(hContact, mask);
+}
+
+//------------------------------------------------------------------------------
+void DialogConfigActive::selectAllUsers(HWND window, bool state)
+{
+ HWND listview = GetDlgItem(window, IDC_ACTIVE_USERS);
+
+ for (int i = 0; i < ListView_GetItemCount(listview); ++i)
+ {
+ ListView_SetCheckState(listview, i, state);
+ }
+
+ changed(window);
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/DialogConfigActive.h b/plugins/WinterSpeak/src/DialogConfigActive.h
new file mode 100644
index 0000000000..8dbbbd43a9
--- /dev/null
+++ b/plugins/WinterSpeak/src/DialogConfigActive.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "mirandadialog.h"
+
+class DialogConfigActive : public MirandaDialog
+{
+ public:
+ //--------------------------------------------------------------------------
+ // Description : Initialise
+ // Parameters : db - reference to the database to initalise and save
+ // control to and from
+ //--------------------------------------------------------------------------
+ DialogConfigActive(ConfigDatabase &db);
+ virtual ~DialogConfigActive();
+
+ //--------------------------------------------------------------------------
+ // Description : process a dialog message
+ // Return : 0 - process ok
+ // 1 - error
+ //--------------------------------------------------------------------------
+ static INT_PTR CALLBACK process(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
+
+ private:
+ //--------------------------------------------------------------------------
+ // Description : load/save setting to the miranda database
+ //--------------------------------------------------------------------------
+ void load(HWND window);
+ void save(HWND window);
+ void notify(HWND window, LPARAM lparam);
+
+ //--------------------------------------------------------------------------
+ // Description : select/unselect all the active status checkboxes
+ // Parameters : state - the state to apply to the checkboxes
+ //--------------------------------------------------------------------------
+ void selectAllUsers(HWND window, bool state);
+ void ResetListOptions(HWND listview);
+ void InitialiseItem(HWND hwndList, HANDLE hItem, bool message, bool status);
+ void SetAllContactIcons(HWND listview, HWND window);
+ void SetIconsForColumn(HWND hwndList, HANDLE hItem, HANDLE hItemAll, int iColumn, int iImage);
+ void SetAllChildIcons(HWND hwndList, HANDLE hFirstItem, int iColumn, int iImage);
+ void SetListGroupIcons(HWND hwndList, HANDLE hFirstItem, HANDLE hParentItem, int *groupChildCount);
+ void SaveItemMask(HWND hwndList, HANDLE hContact, HANDLE hItem);
+
+ static DialogConfigActive *m_instance;
+ ConfigDatabase &m_db;
+ HICON hIcons[4];
+ HANDLE hItemUnknown;
+ HANDLE hItemAll;
+};
+
diff --git a/plugins/WinterSpeak/src/DialogConfigEngine.cpp b/plugins/WinterSpeak/src/DialogConfigEngine.cpp
new file mode 100644
index 0000000000..2375dedcc7
--- /dev/null
+++ b/plugins/WinterSpeak/src/DialogConfigEngine.cpp
@@ -0,0 +1,229 @@
+#include "Common.h"
+#include "DialogConfigEngine.h"
+
+DialogConfigEngine *DialogConfigEngine::m_instance = 0;
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+DialogConfigEngine::DialogConfigEngine(ConfigDatabase &db) : m_db(db), m_test_tts(0)
+{
+ m_instance = this;
+}
+
+//------------------------------------------------------------------------------
+DialogConfigEngine::~DialogConfigEngine()
+{
+ m_instance = 0;
+}
+
+//------------------------------------------------------------------------------
+INT_PTR CALLBACK DialogConfigEngine::process(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (!m_instance)
+ {
+ return 1;
+ }
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ m_instance->load(window);
+ break;
+
+ case WM_NOTIFY:
+ if (PSN_APPLY == reinterpret_cast<LPNMHDR>(lparam)->code)
+ {
+ m_instance->save(window);
+ m_instance->m_db.save();
+ }
+ break;
+
+ case WM_HSCROLL:
+ m_instance->changed(window);
+ break;
+
+ case WM_COMMAND:
+ m_instance->command(window, wparam);
+ break;
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+// private:
+//------------------------------------------------------------------------------
+void DialogConfigEngine::command(HWND window, int control)
+{
+ switch (LOWORD(control))
+ {
+ case IDC_WELCOME_MSG:
+ if (EN_CHANGE == HIWORD(control))
+ {
+ changed(window);
+ }
+ break;
+
+ case IDC_SELECT_VOICE:
+ if (CBN_SELCHANGE == HIWORD(control))
+ {
+ changed(window);
+ }
+ break;
+
+ case IDC_SELECT_ENGINE:
+ if (CBN_SELCHANGE == HIWORD(control))
+ {
+ updateVoices(window);
+ changed(window);
+ }
+ break;
+
+ case IDC_CONFIG_LEXICON:
+ if (createTts(window))
+ {
+ if (!m_test_tts->lexiconDialog(window))
+ {
+ MessageBox(window, L"Lexicon for this engine is not supported", L"Speak", MB_OK | MB_ICONEXCLAMATION);
+ }
+ }
+ break;
+
+ case IDC_BUTTON_TEST:
+ if (createTts(window))
+ {
+ m_test_tts->say(TranslateW(L"testing testing 1 2 3"));
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+void DialogConfigEngine::load(HWND window)
+{
+ TranslateDialogDefault(window);
+
+ // add the available engines to the combo box
+ SpeechInterface si;
+ std::vector<std::wstring> engines = si.getAvailableEngines();
+ for (unsigned int i = 0; i < engines.size(); ++i)
+ {
+ SendDlgItemMessage(window, IDC_SELECT_ENGINE, CB_ADDSTRING, 0, (long)(engines[i].c_str()));
+ }
+
+ VoiceDesc desc = m_db.getVoiceDesc();
+
+ // initialise the sliders
+ SendDlgItemMessage(window, IDC_SLIDER_VOLUME, TBM_SETPOS, TRUE, desc.volume);
+ SendDlgItemMessage(window, IDC_SLIDER_PITCH, TBM_SETPOS, TRUE, desc.pitch);
+ SendDlgItemMessage(window, IDC_SLIDER_RATE, TBM_SETPOS, TRUE, desc.rate);
+
+ // select the speech engine
+ SendDlgItemMessage(window, IDC_SELECT_ENGINE, CB_SELECTSTRING, 0, reinterpret_cast<long>(desc.engine.c_str()));
+
+ // initialise the welcome message box
+ SetDlgItemText(window, IDC_WELCOME_MSG, m_db.getWelcomeMessage().c_str());
+
+ updateVoices(window);
+}
+
+//------------------------------------------------------------------------------
+void DialogConfigEngine::save(HWND window)
+{
+ VoiceDesc desc;
+ getVoiceDesc(window, desc);
+ m_db.setVoiceDesc(desc);
+
+ // store the welcome message
+ WCHAR *text = Hlp_GetDlgItemText(window, IDC_WELCOME_MSG);
+ m_db.setWelcomeMessage(text);
+}
+
+//------------------------------------------------------------------------------
+void DialogConfigEngine::updateVoices(HWND window)
+{
+ SpeechInterface si;
+ m_test_tts = std::auto_ptr<TextToSpeech>(si.createTts(getEngine(window)));
+
+ if (!m_test_tts.get())
+ {
+ return;
+ }
+
+ // add the voices onto the list
+ std::vector<std::wstring> voices = m_test_tts->getVoices();
+
+ SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_RESETCONTENT, 0, 0);
+ for (unsigned int i = 0; i < voices.size(); ++i)
+ {
+ SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_ADDSTRING, 0,
+ (long)voices[i].c_str());
+ }
+
+ // get the voice saved in the database
+ std::wstring voice = m_db.getVoiceDesc().voice;
+
+ if (FAILED(SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_FINDSTRINGEXACT, 0, (long)voice.c_str())))
+ {
+ // select the first one
+ SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_SETCURSEL , 0, 0);
+ }
+ else
+ {
+ // select the saved voice
+ SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_SELECTSTRING, 0, (long)voice.c_str());
+ }
+}
+
+//------------------------------------------------------------------------------
+void DialogConfigEngine::getVoiceDesc(HWND window, VoiceDesc &desc)
+{
+ // get the engine
+ WCHAR *text = Hlp_GetDlgItemText(window, IDC_SELECT_ENGINE);
+ desc.engine = text;
+
+ // get the voice
+ WCHAR *voice = Hlp_GetDlgItemText(window, IDC_SELECT_VOICE);
+ desc.voice = voice;
+ /*std::auto_ptr<char> voice(new char[50]);
+ SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_GETLBTEXT,
+ SendDlgItemMessage(window, IDC_SELECT_VOICE, CB_GETCURSEL, 0, 0),
+ reinterpret_cast<long>(voice.get()));
+ desc.voice = voice.get();*/
+
+ // get the voice setting sliders
+ desc.volume = SendDlgItemMessage(window, IDC_SLIDER_VOLUME, TBM_GETPOS, 0, 0);
+ desc.pitch = SendDlgItemMessage(window, IDC_SLIDER_PITCH, TBM_GETPOS, 0, 0);
+ desc.rate = SendDlgItemMessage(window, IDC_SLIDER_RATE, TBM_GETPOS, 0, 0);
+}
+
+//------------------------------------------------------------------------------
+std::wstring DialogConfigEngine::getEngine(HWND window)
+{
+ WCHAR *text = Hlp_GetDlgItemText(window, IDC_SELECT_ENGINE);
+ /*char text[100];
+ GetDlgItemText(window, IDC_SELECT_ENGINE, mir_a2u(text), sizeof(text));*/
+
+ return text;
+}
+
+//------------------------------------------------------------------------------
+bool DialogConfigEngine::createTts(HWND window)
+{
+ VoiceDesc desc;
+ getVoiceDesc(window, desc);
+
+ SpeechInterface si;
+ m_test_tts = std::auto_ptr<TextToSpeech>(si.createTts(desc.engine));
+
+ if (!m_test_tts.get())
+ {
+ return false;
+ }
+
+ si.configureTts(m_test_tts.get(), desc);
+ return true;
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/DialogConfigEngine.h b/plugins/WinterSpeak/src/DialogConfigEngine.h
new file mode 100644
index 0000000000..b72037288f
--- /dev/null
+++ b/plugins/WinterSpeak/src/DialogConfigEngine.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "MirandaDialog.h"
+#include "ConfigDatabase.h"
+
+class TextToSpeech;
+
+class DialogConfigEngine : public MirandaDialog
+{
+ public:
+ DialogConfigEngine(ConfigDatabase &db);
+ virtual ~DialogConfigEngine();
+
+ //--------------------------------------------------------------------------
+ // Description : process a dialog message
+ // Return : 0 - process ok
+ // 1 - error
+ //--------------------------------------------------------------------------
+ static INT_PTR CALLBACK process(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
+
+ private:
+ void command(HWND window, int control);
+
+ //--------------------------------------------------------------------------
+ // Description : load/save setting to the miranda database
+ //--------------------------------------------------------------------------
+ void load(HWND window);
+ void save(HWND window);
+
+ //--------------------------------------------------------------------------
+ // Description : update the voices combo box
+ //--------------------------------------------------------------------------
+ void updateVoices(HWND window);
+ void getVoiceDesc(HWND window, VoiceDesc &desc);
+ std::wstring getEngine(HWND window);
+ bool createTts(HWND window);
+
+ static DialogConfigEngine *m_instance;
+ ConfigDatabase &m_db;
+ std::auto_ptr<TextToSpeech> m_test_tts;
+};
diff --git a/plugins/WinterSpeak/src/EventInformation.cpp b/plugins/WinterSpeak/src/EventInformation.cpp
new file mode 100644
index 0000000000..69437a71ea
--- /dev/null
+++ b/plugins/WinterSpeak/src/EventInformation.cpp
@@ -0,0 +1,85 @@
+#include "Common.h"
+#include "EventInformation.h"
+
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+EventInformation::EventInformation() : m_event_strings(), m_event_info()
+{
+ // insert the event strings into a map for easy access
+ m_event_strings[EVENTTYPE_MESSAGE] = TranslateW(L"incoming message from %u");
+ m_event_strings[EVENTTYPE_URL] = TranslateW(L"incoming U R L from %u");
+ m_event_strings[EVENTTYPE_ADDED] = TranslateW(L"you have been added to %u's contact list");
+ m_event_strings[EVENTTYPE_AUTHREQUEST] = TranslateW(L"%u requests your authorization");
+ m_event_strings[EVENTTYPE_FILE] = TranslateW(L"there is an incoming file from %u");
+
+ ZeroMemory(&m_event_info, sizeof(m_event_info));
+}
+
+//------------------------------------------------------------------------------
+EventInformation::~EventInformation()
+{
+}
+
+//------------------------------------------------------------------------------
+bool EventInformation::isValidEvent(HANDLE event)
+{
+ // clean up the old event
+ if (m_event_info.pBlob)
+ {
+ delete m_event_info.pBlob;
+ }
+ ZeroMemory(&m_event_info, sizeof(m_event_info));
+
+ // find out and assign the space we need for the new event
+ m_event_info.cbSize = sizeof(m_event_info);
+ m_event_info.cbBlob = db_event_getBlobSize(event);// CallService(MS_DB_EVENT_GETBLOBSIZE, reinterpret_cast<LPARAM>(event), 0);
+
+ if (-1 == m_event_info.cbBlob)
+ {
+ return false;
+ }
+ m_event_info.pBlob = new unsigned char[m_event_info.cbBlob];
+
+ // get the event info
+ db_event_get(event, &m_event_info);
+ //CallService(MS_DB_EVENT_GET, reinterpret_cast<LPARAM>(event), reinterpret_cast<LPARAM>(&m_event_info));
+
+ // if the event has already been read or was sent by me then exit
+ if (m_event_info.flags & (DBEF_SENT | DBEF_READ))
+ {
+ return false;
+ }
+
+ // if the event string doesn't exist in our list then exit
+ if (m_event_strings.find(m_event_info.eventType) == m_event_strings.end())
+ {
+ return false;
+ }
+
+ // event was good
+ return true;
+}
+
+//------------------------------------------------------------------------------
+std::wstring EventInformation::getMessage()
+{
+ const std::wstring intro = TranslateW(L"%u says");
+
+ return intro + L" " + mir_a2t_cp((char*)m_event_info.pBlob,CP_UTF8);
+}
+
+//------------------------------------------------------------------------------
+unsigned int EventInformation::getMessageSize()
+{
+ return std::wstring((WCHAR *)m_event_info.pBlob).size();
+}
+
+//------------------------------------------------------------------------------
+std::wstring EventInformation::eventString()
+{
+ return m_event_strings[m_event_info.eventType];
+}
+
+//============================================================================== \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/EventInformation.h b/plugins/WinterSpeak/src/EventInformation.h
new file mode 100644
index 0000000000..2715dee7f9
--- /dev/null
+++ b/plugins/WinterSpeak/src/EventInformation.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <map>
+#include <string>
+
+class EventInformation
+{
+ public:
+ EventInformation();
+ ~EventInformation();
+
+ //--------------------------------------------------------------------------
+ // Description : is the event valid?
+ // Return : true = the event is valid
+ //--------------------------------------------------------------------------
+ bool isValidEvent(HANDLE event);
+
+ //--------------------------------------------------------------------------
+ // Description : get the last event received
+ // Return : the last event or 0 if none yet received
+ //--------------------------------------------------------------------------
+ unsigned short getLastEvent() { return m_event_info.eventType; }
+
+ //--------------------------------------------------------------------------
+ // Description : was the last event a messsage event?
+ // Return : true - yes it was
+ // false - no it wasn't
+ //--------------------------------------------------------------------------
+// bool isMessageEvent()
+// { return (m_event_info.eventType == EVENTTYPE_MESSAGE); }
+
+ //--------------------------------------------------------------------------
+ // Description : get the message from the last event
+ // Return : the last message
+ //--------------------------------------------------------------------------
+ std::wstring getMessage();
+
+ //--------------------------------------------------------------------------
+ // Description : get the size of the message from the last event
+ // Return : the size of the message
+ //--------------------------------------------------------------------------
+ unsigned int getMessageSize();
+
+ //--------------------------------------------------------------------------
+ // Description : get the event string
+ //--------------------------------------------------------------------------
+ std::wstring eventString();
+
+ private:
+ std::map<unsigned short, std::wstring> m_event_strings;
+
+ DBEVENTINFO m_event_info;
+};
diff --git a/plugins/WinterSpeak/src/MirandaDialog.cpp b/plugins/WinterSpeak/src/MirandaDialog.cpp
new file mode 100644
index 0000000000..fad87285f6
--- /dev/null
+++ b/plugins/WinterSpeak/src/MirandaDialog.cpp
@@ -0,0 +1,38 @@
+#include "Common.h"
+#include "MirandaDialog.h"
+
+
+MirandaDialog::MirandaDialog(void)
+{
+}
+
+
+MirandaDialog::~MirandaDialog(void)
+{
+}
+
+void MirandaDialog::changed(HWND window)
+{
+ SendMessage(GetParent(window), PSM_CHANGED, 0, 0);
+}
+
+WCHAR *MirandaDialog::Hlp_GetDlgItemText(HWND hwndDlg, int nIDDlgItem) {
+
+ int len = SendDlgItemMessage(hwndDlg, nIDDlgItem, WM_GETTEXTLENGTH, 0, 0);
+ if (len < 0)
+ return NULL;
+
+ WCHAR *res = (WCHAR*)mir_alloc((len+1)*sizeof(WCHAR));
+ ZeroMemory(res, (len+1)*sizeof(WCHAR));
+ GetDlgItemText(hwndDlg, nIDDlgItem, res, len+1);
+
+ return res;
+}
+
+int MirandaDialog::ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId)
+{
+ HICON hIcon = LoadSkinnedIcon(iconId);
+ int res = ImageList_AddIcon(hIml, hIcon);
+ Skin_ReleaseIcon(hIcon);
+ return res;
+} \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/MirandaDialog.h b/plugins/WinterSpeak/src/MirandaDialog.h
new file mode 100644
index 0000000000..bd9e2c91a0
--- /dev/null
+++ b/plugins/WinterSpeak/src/MirandaDialog.h
@@ -0,0 +1,12 @@
+#pragma once
+class MirandaDialog
+{
+public:
+ MirandaDialog(void);
+ virtual ~MirandaDialog(void);
+ static WCHAR *MirandaDialog::Hlp_GetDlgItemText(HWND hwndDlg, int nIDDlgItem);
+ static int ImageList_AddIcon_IconLibLoaded(HIMAGELIST hIml, int iconId);
+protected:
+ void changed(HWND window);
+};
+
diff --git a/plugins/WinterSpeak/src/Observer.cpp b/plugins/WinterSpeak/src/Observer.cpp
new file mode 100644
index 0000000000..b2bc38be5c
--- /dev/null
+++ b/plugins/WinterSpeak/src/Observer.cpp
@@ -0,0 +1,6 @@
+#include "Common.h"
+#include "Observer.h"
+
+Observer::~Observer(void)
+{
+}
diff --git a/plugins/WinterSpeak/src/Observer.h b/plugins/WinterSpeak/src/Observer.h
new file mode 100644
index 0000000000..ec52b2c4d3
--- /dev/null
+++ b/plugins/WinterSpeak/src/Observer.h
@@ -0,0 +1,17 @@
+#pragma once
+
+
+class Subject;
+
+class Observer
+{
+ public:
+ virtual ~Observer();
+
+ //--------------------------------------------------------------------------
+ // Description : Called by a subject that this observer is observing
+ // to signify a change in state
+ // Parameters : subject - the subject that changed
+ //--------------------------------------------------------------------------
+ virtual void update(Subject &subject) = 0;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/ProtocolInformation.cpp b/plugins/WinterSpeak/src/ProtocolInformation.cpp
new file mode 100644
index 0000000000..d04f485a9b
--- /dev/null
+++ b/plugins/WinterSpeak/src/ProtocolInformation.cpp
@@ -0,0 +1,78 @@
+#include "Common.h"
+#include "ProtocolInformation.h"
+
+
+//------------------------------------------------------------------------------
+ProtocolInformation *ProtocolInformation::m_instance = 0;
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+ProtocolInformation::ProtocolInformation() : m_protocol_timeout()
+{
+ m_instance = this;
+}
+
+//------------------------------------------------------------------------------
+ProtocolInformation::~ProtocolInformation()
+{
+ m_instance = 0;
+
+ // kill all the timers
+ for (ProtocolTimeoutQueue::const_iterator iter = m_protocol_timeout.begin();
+ iter != m_protocol_timeout.end();
+ ++iter)
+ {
+ KillTimer(NULL, (*iter).second);
+ }
+}
+
+//------------------------------------------------------------------------------
+void ProtocolInformation::disable(const char *protocol)
+{
+ if (NULL == protocol)
+ {
+ return;
+ }
+
+ const unsigned int TIMEOUT = 10000;
+
+ unsigned int t = SetTimer(NULL, NULL, TIMEOUT, ProtocolInformation::timeout);
+ m_protocol_timeout.push_back(std::make_pair(protocol, t));
+}
+
+//------------------------------------------------------------------------------
+bool ProtocolInformation::isDisabled(const char *protocol) const
+{
+ if (NULL == protocol)
+ {
+ return false;
+ }
+
+ // iterate through the list and see if the protocol has a timer callback
+ for (ProtocolTimeoutQueue::const_iterator iter = m_protocol_timeout.begin();
+ iter != m_protocol_timeout.end();
+ ++iter)
+ {
+ if (0 == (*iter).first.compare(protocol))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//------------------------------------------------------------------------------
+// private:
+//------------------------------------------------------------------------------
+void CALLBACK ProtocolInformation::timeout(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
+{
+ ProtocolTimeout pt = m_instance->m_protocol_timeout.front();
+
+ KillTimer(NULL, pt.second);
+
+ m_instance->m_protocol_timeout.pop_front();
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/ProtocolInformation.h b/plugins/WinterSpeak/src/ProtocolInformation.h
new file mode 100644
index 0000000000..dcfb6eca18
--- /dev/null
+++ b/plugins/WinterSpeak/src/ProtocolInformation.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <deque>
+#include <utility>
+
+class ProtocolInformation
+{
+ public:
+ ProtocolInformation();
+ ~ProtocolInformation();
+
+ void disable(const char *protocol);
+ bool isDisabled(const char *protocol) const;
+
+ private:
+ typedef std::pair<std::string, unsigned int> ProtocolTimeout;
+ typedef std::deque<ProtocolTimeout> ProtocolTimeoutQueue;
+
+ static void CALLBACK timeout(HWND hwnd, UINT uMsg, UINT idEvent,
+ DWORD dwTime);
+
+ static ProtocolInformation *m_instance;
+
+ ProtocolTimeoutQueue m_protocol_timeout;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeakAnnounce.cpp b/plugins/WinterSpeak/src/SpeakAnnounce.cpp
new file mode 100644
index 0000000000..c95550b4af
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeakAnnounce.cpp
@@ -0,0 +1,206 @@
+#include "Common.h"
+#include "SpeakAnnounce.h"
+
+
+SpeakAnnounce::SpeakAnnounce(HINSTANCE instance) : m_instance(instance), m_db(), m_dialog(m_db), m_user_info(), m_event_info(), m_protocol_info()
+{
+}
+
+//------------------------------------------------------------------------------
+SpeakAnnounce::~SpeakAnnounce()
+{
+}
+
+//------------------------------------------------------------------------------
+void SpeakAnnounce::statusChange(DBCONTACTWRITESETTING *write_setting, HANDLE user)
+{
+ const std::string STATUS = "Status";
+
+ // if the user is myself (NULL) then return
+ // if it's not a status change then return
+ // check and update the user's status, if status didn't change the return
+ if ((NULL == user)
+ || (STATUS != write_setting->szSetting)
+ || (!m_user_info.updateStatus(user, write_setting->value.wVal)))
+ {
+ return;
+ }
+
+ // check if we just connected, and want to suppress status changes
+ if (!m_db.getStatusFlag(AnnounceDatabase::StatusFlag_SuppressConnect)
+ && m_protocol_info.isDisabled(
+ (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)user, 0)))
+ {
+ return;
+ }
+
+ bool speak = false;
+
+ switch (write_setting->value.wVal)
+ {
+ case ID_STATUS_OFFLINE:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Offline);
+ break;
+ case ID_STATUS_ONLINE:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Online);
+ break;
+ case ID_STATUS_AWAY:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Away);
+ break;
+ case ID_STATUS_DND:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Dnd);
+ break;
+ case ID_STATUS_NA:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Na);
+ break;
+ case ID_STATUS_OCCUPIED:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Occupied);
+ break;
+ case ID_STATUS_FREECHAT:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_FreeForChat);
+ break;
+ case ID_STATUS_INVISIBLE:
+ speak = m_db.getStatusFlag(AnnounceDatabase::StatusFlag_Invisible);
+ break;
+ }
+
+ if (!speak)
+ {
+ return;
+ }
+
+ // translate, insert name then speak
+ std::wstring status_str = TranslateW(m_user_info.statusString(user).c_str());
+ m_user_info.insertName(status_str, user);
+ status(status_str, user);
+}
+
+//------------------------------------------------------------------------------
+void SpeakAnnounce::incomingEvent(HANDLE user, HANDLE event)
+{
+ if (m_event_info.isValidEvent(event))
+ {
+ bool speak = false;
+ switch (m_event_info.getLastEvent())
+ {
+ case EVENTTYPE_MESSAGE:
+ speak = m_db.getEventFlag(AnnounceDatabase::EventFlag_Message);
+ break;
+
+ case EVENTTYPE_URL:
+ speak = m_db.getEventFlag(AnnounceDatabase::EventFlag_Url);
+ break;
+
+ case EVENTTYPE_ADDED:
+ speak = m_db.getEventFlag(AnnounceDatabase::EventFlag_Added);
+ break;
+
+ case EVENTTYPE_AUTHREQUEST:
+ speak = m_db.getEventFlag(AnnounceDatabase::EventFlag_AuthRequest);
+ break;
+
+ case EVENTTYPE_FILE:
+ speak = m_db.getEventFlag(AnnounceDatabase::EventFlag_File);
+ break;
+
+ }
+
+ if (!speak)
+ {
+ return;
+ }
+ std::wstring event_str = L"";
+
+ if (EVENTTYPE_MESSAGE == m_event_info.getLastEvent())
+ {
+ if (!readMessage(user))
+ {
+ return; // message dialog is open so just leave without saying anything
+ }
+ if ((m_db.getEventFlag(AnnounceDatabase::EventFlag_ReadMsgLength)) && (m_event_info.getMessageSize() <= m_db.getMaxMsgSize()))
+ {
+ event_str = m_event_info.getMessage(); // conditions met to read the message
+ }
+ else
+ {
+ event_str = m_event_info.eventString();
+ }
+ }
+ else
+ {
+ event_str = m_event_info.eventString();
+ }
+ m_user_info.insertName(event_str, user); // translate the string, insert the name, then speak it
+ message(event_str, user);
+ }
+}
+
+//------------------------------------------------------------------------------
+void SpeakAnnounce::protocolAck(ACKDATA *ack)
+{
+ if (ACKTYPE_STATUS != ack->type)
+ {
+ return;
+ }
+
+ if (ID_STATUS_CONNECTING != (int)ack->hProcess)
+ {
+ return;
+ }
+
+ m_protocol_info.disable((char *)ack->szModule);
+}
+
+//------------------------------------------------------------------------------
+void SpeakAnnounce::message(const std::wstring &sentence, HANDLE user)
+{
+ CallService(ME_SPEAK_MESSAGE, reinterpret_cast<LPARAM>(user), reinterpret_cast<WPARAM>(sentence.c_str()));
+}
+void SpeakAnnounce::status(const std::wstring &sentence, HANDLE user)
+{
+ CallService(ME_SPEAK_STATUS, reinterpret_cast<LPARAM>(user), reinterpret_cast<WPARAM>(sentence.c_str()));
+}
+
+//------------------------------------------------------------------------------
+bool SpeakAnnounce::readMessage(HANDLE contact)
+{
+ std::wstring title = m_user_info.nameString(contact) + L" (" + m_user_info.statusModeString(contact) + L"): ";
+
+ HWND window = NULL;
+
+ window = FindWindow(L"#32770", (title + TranslateW(L"Message Session")).c_str());
+ if (window)
+ {
+ // check if we dont want to read message if dialog is open
+ if (m_db.getEventFlag(AnnounceDatabase::EventFlag_DialogOpen))
+ {
+ return false;
+ }
+
+ // check if we dont want to read message if dialog if focused
+ if ((window == GetForegroundWindow()) && m_db.getEventFlag(AnnounceDatabase::EventFlag_DialogFocused))
+ {
+ return false;
+ }
+ }
+
+ window = FindWindow(L"#32770", (title + TranslateW(L"Message Received")).c_str());
+ if (window)
+ {
+ // check if we dont want to read message if dialog is open
+ if (m_db.getEventFlag(AnnounceDatabase::EventFlag_DialogOpen))
+ {
+ return false;
+ }
+
+ // check if we dont want to read message if dialog if focused
+ if ((window == GetForegroundWindow()) && m_db.getEventFlag(AnnounceDatabase::EventFlag_DialogFocused))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/SpeakAnnounce.h b/plugins/WinterSpeak/src/SpeakAnnounce.h
new file mode 100644
index 0000000000..ff681e6fdb
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeakAnnounce.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "Common.h"
+#include <m_database.h>
+
+class SpeakAnnounce
+{
+ public:
+ SpeakAnnounce(HINSTANCE instance);
+ ~SpeakAnnounce();
+
+ //--------------------------------------------------------------------------
+ // Description : handle a status change
+ //--------------------------------------------------------------------------
+ void statusChange(DBCONTACTWRITESETTING *write_setting, HANDLE user);
+
+ //--------------------------------------------------------------------------
+ // Description : handle an event
+ //--------------------------------------------------------------------------
+ void incomingEvent(HANDLE user, HANDLE event);
+
+ //--------------------------------------------------------------------------
+ // Description : handle a protocol state change
+ //--------------------------------------------------------------------------
+ void protocolAck(ACKDATA *ack);
+
+ //--------------------------------------------------------------------------
+ // Description : speak a sentence
+ // Parameters : sentence - the sentence to speak
+ // user - the user who is speaking, or NULL for no user
+ // Returns : true - speak successful
+ // false - speak failed
+ //--------------------------------------------------------------------------
+ void message(const std::wstring &sentence, HANDLE user);
+ void status(const std::wstring &sentence, HANDLE user);
+
+ private:
+ //--------------------------------------------------------------------------
+ // Description : check if the users message window is open and focused
+ // Parameters : contact - the user to check for
+ // Returns : true = message window is open
+ // false = message window not open
+ //--------------------------------------------------------------------------
+ bool readMessage(HANDLE contact);
+
+ HINSTANCE m_instance;
+
+ AnnounceDatabase m_db;
+ AnnounceDialog m_dialog;
+ UserInformation m_user_info;
+ EventInformation m_event_info;
+ ProtocolInformation m_protocol_info;
+};
+
diff --git a/plugins/WinterSpeak/src/SpeakConfig.cpp b/plugins/WinterSpeak/src/SpeakConfig.cpp
new file mode 100644
index 0000000000..40c9d48dbe
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeakConfig.cpp
@@ -0,0 +1,107 @@
+#include "Common.h"
+#include "SpeakConfig.h"
+
+
+SpeakConfig::SpeakConfig(HINSTANCE instance) : m_instance(instance), m_db(), m_tts(0), m_dialog_engine(m_db), m_dialog_active(m_db)
+{
+ // create and configure the tts
+ SpeechInterface si;
+ VoiceDesc desc = m_db.getVoiceDesc();
+ m_tts = std::auto_ptr<TextToSpeech>(si.createTts(desc.engine));
+ si.configureTts(m_tts.get(), desc);
+
+ // observer the database for changes
+ m_db.attach(*this);
+
+ message(m_db.getWelcomeMessage());
+}
+
+//------------------------------------------------------------------------------
+SpeakConfig::~SpeakConfig()
+{
+}
+
+//------------------------------------------------------------------------------
+void SpeakConfig::update(Subject &subject)
+{
+ ConfigDatabase &db = static_cast<ConfigDatabase &>(subject);
+
+ SpeechInterface si;
+ VoiceDesc desc = db.getVoiceDesc();
+ m_tts = std::auto_ptr<TextToSpeech>(si.createTts(desc.engine));
+ si.configureTts(m_tts.get(), desc);
+}
+
+//------------------------------------------------------------------------------
+bool SpeakConfig::status(const std::wstring &sentence, HANDLE user) {
+ return say(sentence, user, false);
+}
+bool SpeakConfig::message(const std::wstring &sentence, HANDLE user) {
+ return say(sentence, user, true);
+}
+bool SpeakConfig::say(const std::wstring &sentence, HANDLE user, bool message)
+{
+ if (!m_tts.get()){
+ return false;
+ }
+
+ bool active = true;
+
+ if (NULL != user)
+ {
+ // get the status of the protocol of this user
+ const char *protocol = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)user, 0);
+
+ switch (CallProtoService(protocol, PS_GETSTATUS, 0, 0))
+ {
+ case ID_STATUS_ONLINE:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Online);
+ break;
+ case ID_STATUS_AWAY:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Away);
+ break;
+ case ID_STATUS_DND:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Dnd);
+ break;
+ case ID_STATUS_NA:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Na);
+ break;
+ case ID_STATUS_OCCUPIED:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Occupied);
+ break;
+ case ID_STATUS_FREECHAT:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_FreeForChat);
+ break;
+ case ID_STATUS_INVISIBLE:
+ active = m_db.getActiveFlag(ConfigDatabase::ActiveFlag_Invisible);
+ break;
+ case ID_STATUS_OFFLINE:
+ // if we are offline for this protocol, then don't speak the
+ // sentence this is so we don't announce users offline status if
+ // we are disconnected.
+ active = false;
+ break;
+ default:
+ active = false;
+ break;
+ }
+
+ // if its a user say, then check the users status
+ if (active)
+ {
+ if(message) {
+ active = m_db.getActiveUser(user).message;
+ } else {
+ active = m_db.getActiveUser(user).status;
+ }
+ }
+ }
+
+ if (!active)
+ {
+ return false;
+ }
+
+ bool ret = m_tts->say(sentence);
+ return ret;
+}
diff --git a/plugins/WinterSpeak/src/SpeakConfig.h b/plugins/WinterSpeak/src/SpeakConfig.h
new file mode 100644
index 0000000000..e1a4cb421a
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeakConfig.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "Common.h"
+#include "ConfigDatabase.h"
+#include "TextToSpeech.h"
+
+class TextToSpeech;
+
+class SpeakConfig : public Observer
+{
+ public:
+ SpeakConfig(HINSTANCE instance);
+ virtual ~SpeakConfig();
+
+ //--------------------------------------------------------------------------
+ // Description : Called by a subject that this observer is observing
+ // to signify a change in state
+ // Parameters : subject - the subject that changed
+ //--------------------------------------------------------------------------
+ virtual void update(Subject &subject);
+
+ //--------------------------------------------------------------------------
+ // Description : speak a sentence
+ // Parameters : sentence - the sentence to speak
+ // user - the user to associate the say with
+ // NULL = ignore user
+ // Returns : true - speak successful
+ // false - speak failed
+ //--------------------------------------------------------------------------
+ bool status(const std::wstring &sentence, HANDLE user = NULL);
+ bool message(const std::wstring &sentence, HANDLE user = NULL);
+ bool say(const std::wstring &sentence, HANDLE user, bool message);
+
+ private:
+ HINSTANCE m_instance;
+
+ ConfigDatabase m_db;
+ std::auto_ptr<TextToSpeech> m_tts;
+ DialogConfigEngine m_dialog_engine;
+ DialogConfigActive m_dialog_active;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechApi51.cpp b/plugins/WinterSpeak/src/SpeechApi51.cpp
new file mode 100644
index 0000000000..194a867172
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi51.cpp
@@ -0,0 +1,253 @@
+#include "Common.h"
+#include "SpeechApi51.h"
+#include "SpeechApi51Lexicon.h"
+
+#include <sapi.h>
+#include <sphelper.h>
+
+#include <sstream>
+#include <memory>
+
+namespace
+{
+
+//------------------------------------------------------------------------------
+// Description : implement callback
+//------------------------------------------------------------------------------
+/*class Sapi51Callback : public ISpNotifyCallback
+{
+ public:
+ Sapi51Callback();
+
+ virtual STDMETHODIMP NotifyCallback(WPARAM wParam, LPARAM lParam)
+ {
+
+ return S_OK;
+ }
+};*/
+
+}
+
+//------------------------------------------------------------------------------
+SpeechApi51::SpeechApi51() : m_sapi(0), m_state(TextToSpeech::State_Unloaded), m_voice(L""), m_volume(50), m_pitch(50), m_rate(50)
+{
+}
+
+//------------------------------------------------------------------------------
+SpeechApi51::~SpeechApi51()
+{
+ unload();
+
+ CoUninitialize();
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::isAvailable()
+{
+ CoInitialize(NULL);
+
+ ISpVoice *sapi;
+ bool ret = true;
+
+ if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, reinterpret_cast<void **>(&sapi))))
+ {
+ ret = false;
+ }
+ else
+ {
+ sapi->Release();
+ }
+
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::load()
+{
+ if (isLoaded())
+ {
+ return true;
+ }
+
+ CoInitialize(NULL);
+
+ if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, reinterpret_cast<void **>(&m_sapi))))
+ {
+ return false;
+ }
+
+ m_state = TextToSpeech::State_Loaded;
+
+ // adjust the volume and rate settings
+ setVoice(m_voice);
+ setVolume(m_volume);
+ setRate(m_rate);
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::unload()
+{
+ if (isLoaded())
+ {
+ m_sapi->Release();
+ m_sapi = 0;
+ }
+
+ m_state = TextToSpeech::State_Unloaded;
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::isLoaded() const
+{
+ return (TextToSpeech::State_Loaded == m_state);
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::say(const std::wstring &sentence)
+{
+ if (!isLoaded())
+ {
+ return false;
+ }
+
+ // prepend the pitch setting
+ std::wstringstream output;
+ output << "<pitch middle='" << m_pitch << "'/> " << sentence;
+
+ const std::wstring& wstr = output.str(); // extends lifetime of temporary
+ const LPCWSTR p = wstr.c_str();
+ //std::auto_ptr<wchar_t> sapi_sentence(new wchar_t[output.str().size() + 1]);
+ //mbstowcs(sapi_sentence.get(), output.str().c_str(), output.str().size() + 1);
+
+ // speak the sentence
+ if (FAILED(m_sapi->Speak(p, SPF_IS_XML | SPF_ASYNC, NULL)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::setVolume(int volume)
+{
+ m_volume = volume;
+
+ if (isLoaded() && FAILED(m_sapi->SetVolume(volume)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::setPitch(int pitch)
+{
+ m_pitch = (pitch / 5) - 10;
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::setRate(int rate)
+{
+ m_rate = rate;
+
+ // convert it to the range -10 to 10
+ if (isLoaded() && FAILED(m_sapi->SetRate((rate / 5.0) - 10)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::setVoice(const std::wstring &voice)
+{
+ m_voice = voice;
+
+ if (!isLoaded())
+ {
+ return true;
+ }
+
+ // get a voice enumerator
+ CComPtr<IEnumSpObjectTokens> cpEnum;
+ if (FAILED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum)))
+ {
+ return false;
+ }
+
+ // iterate through the list till we find a matching voice
+ ISpObjectToken *voice_token;
+ while (S_OK == cpEnum->Next(1, &voice_token, NULL))
+ {
+ CSpDynamicString voice_str;
+
+ if (SUCCEEDED(SpGetDescription(voice_token, &voice_str))
+ && (voice == voice_str.Copy()))
+ {
+ m_sapi->SetVoice(voice_token);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//------------------------------------------------------------------------------
+std::vector<std::wstring> SpeechApi51::getVoices() const
+{
+ std::vector<std::wstring> ret;
+
+ CoInitialize(NULL);
+
+ // get a voice enumerator
+ CComPtr<IEnumSpObjectTokens> cpEnum;
+ if (S_OK != SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum))
+ {
+ return ret;
+ }
+
+ // iterate through the voices and add them to the string vector
+ ISpObjectToken *voice_token;
+ while (S_OK == cpEnum->Next(1, &voice_token, NULL))
+ {
+ CSpDynamicString voice_str;
+
+ if (SUCCEEDED(SpGetDescription(voice_token, &voice_str)))
+ {
+ ret.push_back(voice_str.Copy());
+ }
+ }
+
+ return ret;
+}
+
+
+//------------------------------------------------------------------------------
+bool SpeechApi51::lexiconDialog(HWND window)
+{
+ // open the dialog
+ SpeechApi51Lexicon dialog(window);
+
+ if (!dialog.display())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+std::wstring SpeechApi51::getDescription()
+{
+ return L"Microsoft SAPI v5.1";
+}
+
+//------------------------------------------------------------------------------ \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechApi51.h b/plugins/WinterSpeak/src/SpeechApi51.h
new file mode 100644
index 0000000000..b7505e1410
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi51.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "TextToSpeech.h"
+
+struct ISpVoice;
+class Sapi51Callback;
+
+class SpeechApi51 : public TextToSpeech
+{
+ public:
+ SpeechApi51();
+ virtual ~SpeechApi51();
+
+ //--------------------------------------------------------------------------
+ // Description : is the api available for use
+ // Return : true - it is available
+ // false - it is not available
+ //--------------------------------------------------------------------------
+ virtual bool isAvailable();
+
+ //--------------------------------------------------------------------------
+ // Description : load/unload/reload the speech api
+ // Return : true - the action succeeded
+ // false - the action failed
+ //--------------------------------------------------------------------------
+ virtual bool load();
+ virtual bool unload();
+
+ //--------------------------------------------------------------------------
+ // Description : check if the speech api is loaded
+ // Return : true - the speech_api is loaded
+ // false - its not loaded
+ //--------------------------------------------------------------------------
+ virtual bool isLoaded() const;
+
+ //--------------------------------------------------------------------------
+ // Description : speak a sentence
+ // Parameters : sentence - the sentence to speak
+ // Returns : true - speak successful
+ // false - speak failed
+ //--------------------------------------------------------------------------
+ virtual bool say(const std::wstring &sentence);
+
+ //--------------------------------------------------------------------------
+ // Description : set the voice settings
+ // Parameters : range from 0 to 100
+ //--------------------------------------------------------------------------
+ virtual bool setVolume(int volume);
+ virtual bool setPitch(int pitch);
+ virtual bool setRate(int rate);
+
+ //--------------------------------------------------------------------------
+ // Description : set the voice
+ //--------------------------------------------------------------------------
+ virtual bool setVoice(const std::wstring &voice);
+
+ //--------------------------------------------------------------------------
+ // Description : get the available voices
+ //--------------------------------------------------------------------------
+ virtual std::vector<std::wstring> getVoices() const;
+
+ //--------------------------------------------------------------------------
+ // Description : open the lexicon dialog for this engine
+ // Parameters : window - handle to the parent window
+ // Return : true - dialog completely successfully
+ // false - dialog failed
+ //--------------------------------------------------------------------------
+ virtual bool lexiconDialog(HWND window);
+
+ //--------------------------------------------------------------------------
+ // Description : get the description of the tts engine
+ //--------------------------------------------------------------------------
+ static std::wstring getDescription();
+
+ private:
+ ISpVoice *m_sapi;
+
+ TextToSpeech::State m_state;
+ std::wstring m_voice;
+ int m_volume;
+ int m_pitch;
+ int m_rate;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechApi51Lexicon.cpp b/plugins/WinterSpeak/src/SpeechApi51Lexicon.cpp
new file mode 100644
index 0000000000..2a64b0fb6a
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi51Lexicon.cpp
@@ -0,0 +1,75 @@
+#include "Common.h"
+#include "SpeechApi51Lexicon.h"
+#include "SpeechApi51.h"
+
+
+extern HINSTANCE g_hInst;
+
+//------------------------------------------------------------------------------
+SpeechApi51Lexicon::SpeechApi51Lexicon(HWND window) : m_parent_window(window), m_window(0)
+{
+}
+
+//------------------------------------------------------------------------------
+SpeechApi51Lexicon::~SpeechApi51Lexicon()
+{
+}
+
+//------------------------------------------------------------------------------
+bool SpeechApi51Lexicon::display()
+{
+ m_window = CreateDialog(
+ g_hInst,
+ MAKEINTRESOURCE(IDD_TTS_LEXICON),
+ m_parent_window,
+ dialogEvent);
+
+ if (!m_window)
+ {
+ return false;
+ }
+
+ ShowWindow(m_window, SW_SHOW);
+
+/* WNDCLASS wc;
+
+ wc.style = 0;
+! wc.lpfnWndProc = (WNDPROC)MainWndProc; // Window procedure for this class.
+ wc.cbClsExtra = 0; // No per-class extra data.
+! wc.cbWndExtra = 0; // No per-window extra data.
+ wc.hInstance = hInstance; // Application that owns the class.
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "Comdlg32WClass"; // Name used in call to CreateWindow.
+
+ return (RegisterClass(&wc));*/
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+INT_PTR CALLBACK SpeechApi51Lexicon::dialogEvent(HWND hwndDlg, UINT uMsg, WPARAM wParam,
+ LPARAM lParam)
+{
+
+ return TRUE;
+}
+
+//------------------------------------------------------------------------------
+void SpeechApi51Lexicon::addLexicon()
+{
+}
+
+//------------------------------------------------------------------------------
+void SpeechApi51Lexicon::deleteLexicon()
+{
+}
+
+//------------------------------------------------------------------------------
+void SpeechApi51Lexicon::displayLexicon()
+{
+}
+
+//------------------------------------------------------------------------------ \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechApi51Lexicon.h b/plugins/WinterSpeak/src/SpeechApi51Lexicon.h
new file mode 100644
index 0000000000..85dd2230fe
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechApi51Lexicon.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <wtypes.h>
+
+class SpeechApi51;
+
+class SpeechApi51Lexicon
+{
+ public:
+ //--------------------------------------------------------------------------
+ // Description : Constuctor
+ // Parameters : window - handle to the parent window
+ //--------------------------------------------------------------------------
+ SpeechApi51Lexicon(HWND window);
+
+ ~SpeechApi51Lexicon();
+
+ //--------------------------------------------------------------------------
+ // Description : display the lexicon dialog
+ // Return : true - display ok
+ // false - display failed
+ //--------------------------------------------------------------------------
+ bool display();
+
+ private:
+ static INT_PTR CALLBACK dialogEvent(HWND hwndDlg, UINT uMsg,
+ WPARAM wParam, LPARAM lParam);
+
+ void addLexicon();
+ void deleteLexicon();
+ void displayLexicon();
+
+ HWND m_parent_window;
+ HWND m_window;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/SpeechInterface.cpp b/plugins/WinterSpeak/src/SpeechInterface.cpp
new file mode 100644
index 0000000000..500165f356
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechInterface.cpp
@@ -0,0 +1,68 @@
+#include "Common.h"
+#include "SpeechInterface.h"
+#include "SpeechApi51.h"
+
+
+SpeechInterface::SpeechInterface()
+{
+}
+
+//------------------------------------------------------------------------------
+SpeechInterface::~SpeechInterface()
+{
+}
+
+//------------------------------------------------------------------------------
+TextToSpeech * SpeechInterface::createTts(std::wstring &engine) const
+{
+ TextToSpeech *tts = 0;
+
+ /*if (SpeechApi40a::getDescription() == engine)
+ {
+ tts = new SpeechApi40a();
+ }
+ else*/
+ if (SpeechApi51::getDescription() == engine)
+ {
+ tts = new SpeechApi51();
+ }
+
+ return tts;
+}
+
+//------------------------------------------------------------------------------
+void SpeechInterface::configureTts(TextToSpeech *tts, const VoiceDesc &desc) const
+{
+ if (!tts)
+ {
+ return;
+ }
+
+ tts->setVoice(desc.voice);
+ tts->setVolume(desc.volume);
+ tts->setRate(desc.rate);
+ tts->setPitch(desc.pitch);
+ tts->load();
+}
+
+//------------------------------------------------------------------------------
+std::vector<std::wstring> SpeechInterface::getAvailableEngines()
+{
+ std::vector<std::wstring> engines;
+
+ /*SpeechApi40a sapi40a;
+ if (sapi40a.isAvailable())
+ {
+ engines.push_back(SpeechApi40a::getDescription());
+ }*/
+
+ SpeechApi51 sapi51;
+ if (sapi51.isAvailable())
+ {
+ engines.push_back(SpeechApi51::getDescription());
+ }
+
+ return engines;
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/SpeechInterface.h b/plugins/WinterSpeak/src/SpeechInterface.h
new file mode 100644
index 0000000000..eec7eae4f0
--- /dev/null
+++ b/plugins/WinterSpeak/src/SpeechInterface.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <vector>
+
+class TextToSpeech;
+
+class SpeechInterface
+{
+ public:
+ SpeechInterface();
+ ~SpeechInterface();
+
+ //--------------------------------------------------------------------------
+ // Description : create the text to speech object
+ // Parameters : engine - the name of the engine to create
+ // Returns : an instance of the text to speech engine
+ //--------------------------------------------------------------------------
+ TextToSpeech * createTts(std::wstring &engine) const;
+
+ //--------------------------------------------------------------------------
+ // Description : configure the tts object
+ // Parameters : tts - the tts object to configure
+ // desc - the description of the voice
+ //--------------------------------------------------------------------------
+ void configureTts(TextToSpeech *tts, const VoiceDesc &desc) const;
+
+ //--------------------------------------------------------------------------
+ // Description : create a vector of available engines
+ //--------------------------------------------------------------------------
+ std::vector<std::wstring> getAvailableEngines();
+};
+
diff --git a/plugins/WinterSpeak/src/Subject.cpp b/plugins/WinterSpeak/src/Subject.cpp
new file mode 100644
index 0000000000..b502aac4fb
--- /dev/null
+++ b/plugins/WinterSpeak/src/Subject.cpp
@@ -0,0 +1,55 @@
+#include "Common.h"
+#include "Subject.h"
+#include "Observer.h"
+
+
+//------------------------------------------------------------------------------
+// public:
+//------------------------------------------------------------------------------
+Subject::Subject() : m_observer_list()
+{
+}
+
+//------------------------------------------------------------------------------
+Subject::~Subject()
+{
+}
+
+//------------------------------------------------------------------------------
+void Subject::notify()
+{
+ // call update for all observers in the list
+ for (std::list<Observer *>::iterator iter = m_observer_list.begin(); iter != m_observer_list.end(); ++iter)
+ {
+ (*iter)->update(*this);
+ }
+}
+
+//------------------------------------------------------------------------------
+void Subject::attach(Observer &observer)
+{
+ for (std::list<Observer *>::iterator iter = m_observer_list.begin(); iter != m_observer_list.end(); ++iter)
+ {
+ if (*iter == &observer)
+ {
+ return;
+ }
+ }
+ m_observer_list.push_back(&observer);
+}
+
+//------------------------------------------------------------------------------
+void Subject::detach(const Observer &observer)
+{
+ for (std::list<Observer *>::iterator iter = m_observer_list.begin(); iter != m_observer_list.end(); ++iter)
+ {
+ if (*iter == &observer)
+ {
+ m_observer_list.erase(iter);
+ }
+ }
+}
+
+//==============================================================================
+
+
diff --git a/plugins/WinterSpeak/src/Subject.h b/plugins/WinterSpeak/src/Subject.h
new file mode 100644
index 0000000000..f4bba3b075
--- /dev/null
+++ b/plugins/WinterSpeak/src/Subject.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "Observer.h"
+
+#include <list>
+class Subject
+{
+public:
+ Subject();
+ virtual ~Subject();
+
+ //--------------------------------------------------------------------------
+ // Description : Notify all observers of a state change
+ //--------------------------------------------------------------------------
+ void notify();
+
+ //--------------------------------------------------------------------------
+ // Description : Attach an observer to the subject
+ // Parameters : observer - the observer
+ //--------------------------------------------------------------------------
+ void attach(Observer &observer);
+
+ //--------------------------------------------------------------------------
+ // Description : Detach an observer from the subject
+ // Parameters : observer - the observer
+ //--------------------------------------------------------------------------
+ void detach(const Observer &observer);
+
+ private:
+ //--------------------------------------------------------------------------
+ // Description : Disallow assignment operator and copy constructor
+ //--------------------------------------------------------------------------
+ Subject(const Subject &rhs);
+ const Subject & operator=(const Subject &rhs);
+
+ std::list<Observer *> m_observer_list;
+};
+
diff --git a/plugins/WinterSpeak/src/TextToSpeech.cpp b/plugins/WinterSpeak/src/TextToSpeech.cpp
new file mode 100644
index 0000000000..ddb1185225
--- /dev/null
+++ b/plugins/WinterSpeak/src/TextToSpeech.cpp
@@ -0,0 +1,14 @@
+#include "Common.h"
+#include "TextToSpeech.h"
+
+//------------------------------------------------------------------------------
+TextToSpeech::TextToSpeech()
+{
+}
+
+//------------------------------------------------------------------------------
+TextToSpeech::~TextToSpeech()
+{
+}
+
+//------------------------------------------------------------------------------ \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/TextToSpeech.h b/plugins/WinterSpeak/src/TextToSpeech.h
new file mode 100644
index 0000000000..f426c43e87
--- /dev/null
+++ b/plugins/WinterSpeak/src/TextToSpeech.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "Common.h"
+#include <string>
+#include <vector>
+
+class TextToSpeech
+{
+ public:
+ enum State
+ {
+ State_Loaded,
+ State_Unloaded,
+ };
+
+ TextToSpeech();
+ virtual ~TextToSpeech();
+
+ //--------------------------------------------------------------------------
+ // Description : is the api available for use
+ // Return : true - it is available
+ // false - it is not available
+ //--------------------------------------------------------------------------
+ virtual bool isAvailable() = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : load/unload/reload the speech api
+ // Return : true - the action succeeded
+ // false - the action failed
+ //--------------------------------------------------------------------------
+ virtual bool load() = 0;
+ virtual bool unload() = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : check if the speech api is loaded
+ // Return : true - the speech_api is loaded
+ // false - its not loaded
+ //--------------------------------------------------------------------------
+ virtual bool isLoaded() const = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : speak a sentence
+ // Parameters : sentence - the sentence to speak
+ // Returns : true - speak successful
+ // false - speak failed
+ //--------------------------------------------------------------------------
+ virtual bool say(const std::wstring &sentence) = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : set the voice settings
+ // Parameters : range from 0 to 100
+ //--------------------------------------------------------------------------
+ virtual bool setVolume(int volume) = 0;
+ virtual bool setPitch(int pitch) = 0;
+ virtual bool setRate(int rate) = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : set the voice
+ //--------------------------------------------------------------------------
+ virtual bool setVoice(const std::wstring &voice) = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : get the available voices
+ //--------------------------------------------------------------------------
+ virtual std::vector<std::wstring> getVoices() const = 0;
+
+ //--------------------------------------------------------------------------
+ // Description : open the lexicon dialog for this engine
+ // Parameters : window - handle to the parent window
+ // Return : true - dialog completely successfully
+ // false - dialog failed
+ //--------------------------------------------------------------------------
+ virtual bool lexiconDialog(HWND window) = 0;
+}; \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/UserInformation.cpp b/plugins/WinterSpeak/src/UserInformation.cpp
new file mode 100644
index 0000000000..fa5db0b0e5
--- /dev/null
+++ b/plugins/WinterSpeak/src/UserInformation.cpp
@@ -0,0 +1,78 @@
+#include "Common.h"
+#include "UserInformation.h"
+
+
+UserInformation::UserInformation() : m_status_info(), m_status_strings() {
+ // insert the status strings into a map for easy access
+ m_status_strings[ID_STATUS_OFFLINE] = L"%u is now offline";
+ m_status_strings[ID_STATUS_ONLINE] = L"%u is now online";
+ m_status_strings[ID_STATUS_AWAY] = L"%u is away";
+ m_status_strings[ID_STATUS_INVISIBLE] = L"%u is invisible";
+ m_status_strings[ID_STATUS_NA] = L"%u is not available";
+ m_status_strings[ID_STATUS_DND] = L"%u does not want to be disturbed";
+ m_status_strings[ID_STATUS_OCCUPIED] = L"%u is occupied";
+ m_status_strings[ID_STATUS_FREECHAT] = L"%u is free for chat";
+}
+
+//------------------------------------------------------------------------------
+UserInformation::~UserInformation()
+{
+}
+
+//------------------------------------------------------------------------------
+bool UserInformation::updateStatus(HANDLE user, int status)
+{
+ bool ret = false;
+
+ // if the user exists and their status hasn't changed, then return false
+ if ((m_status_info.find(user) != m_status_info.end())
+ && (m_status_info[user] != status))
+ {
+ ret = true;
+ }
+
+ // update the status
+ m_status_info[user] = status;
+
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+std::wstring UserInformation::statusString(HANDLE user)
+{
+ return m_status_strings[m_status_info[user]];
+}
+
+//------------------------------------------------------------------------------
+std::wstring UserInformation::statusModeString(HANDLE user)
+{
+ int status = CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, m_status_info[user], 0);
+
+ if (NULL == status)
+ {
+ return L"";
+ }
+
+ return reinterpret_cast<WCHAR *>(status);
+}
+
+//------------------------------------------------------------------------------
+void UserInformation::insertName(std::wstring &str, HANDLE user) const
+{
+ // insert the user's name into the string
+ str.replace(str.find(L"%u"), 2, nameString(user));
+}
+
+//------------------------------------------------------------------------------
+std::wstring UserInformation::nameString(HANDLE user) const
+{
+ //WCHAR *ret = reinterpret_cast<WCHAR *>(CallService(MS_CLIST_GETCONTACTDISPLAYNAME, reinterpret_cast<unsigned int>(user), 0));
+ char* ret = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, WPARAM(user), 0);
+ if (0 == ret)
+ {
+ return L"";
+ }
+ return TranslateW(mir_a2t(ret));
+}
+
+//==============================================================================
diff --git a/plugins/WinterSpeak/src/UserInformation.h b/plugins/WinterSpeak/src/UserInformation.h
new file mode 100644
index 0000000000..a9d972d96d
--- /dev/null
+++ b/plugins/WinterSpeak/src/UserInformation.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <map>
+#include <string>
+
+class UserInformation
+{
+ public:
+ UserInformation();
+ ~UserInformation();
+
+ //--------------------------------------------------------------------------
+ // Description : update the users status
+ // Parameters : user - the current user
+ // status - the users status
+ // Returns : true - the status changed
+ // false - the status stayed the same
+ //--------------------------------------------------------------------------
+ bool updateStatus(HANDLE user, int status);
+
+ //--------------------------------------------------------------------------
+ // Description : get a string containing the users current status string
+ // Parameters : user - the current user
+ // Returns : the string containing the users status
+ //--------------------------------------------------------------------------
+ std::wstring statusString(HANDLE user);
+
+ //--------------------------------------------------------------------------
+ // Description : return the status mode of the user
+ // Parameters : user - the current user
+ // Returns : the string containing the users status mode
+ //--------------------------------------------------------------------------
+ std::wstring statusModeString(HANDLE user);
+
+ //--------------------------------------------------------------------------
+ // Description : insert the name into the string at the %u location
+ // Parameters : str - the string to have the username inserted into
+ // user - the current user
+ //--------------------------------------------------------------------------
+ void insertName(std::wstring &str, HANDLE user) const;
+
+ //--------------------------------------------------------------------------
+ // Description : get the name string for the user
+ // Parameters : user - the current user
+ // Returns : a string containing the user's name
+ //--------------------------------------------------------------------------
+ std::wstring nameString(HANDLE user) const;
+
+ private:
+ std::map<HANDLE, int> m_status_info;
+ std::map<int, std::wstring> m_status_strings;
+};
+
diff --git a/plugins/WinterSpeak/src/Version.h b/plugins/WinterSpeak/src/Version.h
new file mode 100644
index 0000000000..6dcfc0d27f
--- /dev/null
+++ b/plugins/WinterSpeak/src/Version.h
@@ -0,0 +1,14 @@
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 9
+#define __RELEASE_NUM 8
+#define __BUILD_NUM 0
+
+#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+
+#define __PLUGIN_NAME "Speak"
+#define __FILENAME "speak.dll"
+#define __DESCRIPTION "Miranda interface to the Microsoft Speech API"
+#define __AUTHOR "Ryan Winter, BlubbFish"
+#define __AUTHOREMAIL "miranda@blubbfish.net"
+#define __AUTHORWEB "http://miranda-ng.org/p/WinterSpeak/"
+#define __COPYRIGHT "© 2002 Ryan Winter, © 2013 BlubbFish"
diff --git a/plugins/WinterSpeak/src/m_speak.h b/plugins/WinterSpeak/src/m_speak.h
new file mode 100644
index 0000000000..d044b29595
--- /dev/null
+++ b/plugins/WinterSpeak/src/m_speak.h
@@ -0,0 +1,4 @@
+
+
+#define ME_SPEAK_STATUS "Speak/Status"
+#define ME_SPEAK_MESSAGE "Speak/Message" \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/main.cpp b/plugins/WinterSpeak/src/main.cpp
new file mode 100644
index 0000000000..debe87cf29
--- /dev/null
+++ b/plugins/WinterSpeak/src/main.cpp
@@ -0,0 +1,172 @@
+#include "Common.h"
+
+
+HINSTANCE g_hInst;
+int hLangpack;
+DWORD g_mirandaVersion;
+
+SpeakConfig *g_speak_config = 0;
+SpeakAnnounce *g_speak_announce = 0;
+HANDLE g_dialog_options_initialise;
+HANDLE g_event_status_change;
+HANDLE g_event_message_added;
+HANDLE g_protocol_ack;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {81E189DC-C251-45F6-9EDF-A0F3A05C4248}
+ { 0x81e189dc, 0xc251, 0x45f6, { 0x9e, 0xdf, 0xa0, 0xf3, 0xa0, 0x5c, 0x42, 0x48 } }
+};
+
+//-----------------------------------------------------------------------------
+// Description : External hook
+//-----------------------------------------------------------------------------
+int status(WPARAM wParam, LPARAM lParam)
+{
+ return g_speak_config->status(reinterpret_cast<WCHAR *>(lParam), reinterpret_cast<HANDLE>(wParam));
+}
+int message(WPARAM wParam, LPARAM lParam)
+{
+ return g_speak_config->message(reinterpret_cast<WCHAR *>(lParam), reinterpret_cast<HANDLE>(wParam));
+}
+
+//-----------------------------------------------------------------------------
+// Description : an status change event occured
+//-----------------------------------------------------------------------------
+int eventStatusChange(WPARAM wParam, LPARAM lParam)
+{
+ g_speak_announce->statusChange(
+ reinterpret_cast<DBCONTACTWRITESETTING *>(lParam),
+ reinterpret_cast<HANDLE>(wParam));
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Description : a message event occured
+//-----------------------------------------------------------------------------
+int eventMessageAdded(WPARAM wParam, LPARAM lParam)
+{
+ g_speak_announce->incomingEvent(reinterpret_cast<HANDLE>(wParam), reinterpret_cast<HANDLE>(lParam));
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Description : a messaging protocol changed state
+//-----------------------------------------------------------------------------
+int protocolAck(WPARAM wParam, LPARAM lParam)
+{
+ g_speak_announce->protocolAck(reinterpret_cast<ACKDATA *>(lParam));
+
+ return 0;
+}
+
+int dialogOptionsInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { sizeof(odp) };
+
+ odp.hInstance = g_hInst;
+ odp.ptszGroup = LPGENT("Speak");
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+
+ if (g_speak_config)
+ {
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_CONFIG);
+ odp.ptszTitle = LPGENT("Engine/Voice");
+ odp.pfnDlgProc = DialogConfigEngine::process;
+ Options_AddPage(wParam, &odp);
+
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_ACTIVEMODES);
+ odp.ptszTitle = LPGENT("Active Modes");
+ odp.pfnDlgProc = DialogConfigActive::process;
+ Options_AddPage(wParam, &odp);
+ }
+
+ if (g_speak_announce)
+ {
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_ANNOUNCE);
+ odp.ptszTitle = LPGENT("Announce");
+ odp.pfnDlgProc = AnnounceDialog::process;
+ Options_AddPage(wParam, &odp);
+ }
+ return 0;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ g_mirandaVersion = mirandaVersion;
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) int Load(void)
+{
+ mir_getLP( &pluginInfo );
+ //pluginLink = link;
+
+ if (!g_speak_config)
+ {
+ g_speak_config = new SpeakConfig(g_hInst);
+
+ // expose to allow miranda + plugins to access my speak routines
+ CreateServiceFunction(ME_SPEAK_STATUS, status);
+ CreateServiceFunction(ME_SPEAK_MESSAGE, message);
+ }
+
+ if (!g_speak_announce)
+ {
+ g_speak_announce = new SpeakAnnounce(g_hInst);
+
+ // tap into contact setting change event
+ g_event_status_change = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, eventStatusChange);
+
+ // a new message event has occured
+ g_event_message_added = HookEvent(ME_DB_EVENT_ADDED, eventMessageAdded);
+
+ // a messaging protocol changed state
+ g_protocol_ack = HookEvent(ME_PROTO_ACK, protocolAck);
+
+ }
+
+ // a option dialog box request has occured
+ g_dialog_options_initialise = HookEvent(ME_OPT_INITIALISE, dialogOptionsInitialise);
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ UnhookEvent(g_dialog_options_initialise);
+
+ if (g_speak_config)
+ {
+ delete g_speak_config;
+ g_speak_config = 0;
+ }
+
+ if (g_speak_announce)
+ {
+ UnhookEvent(g_event_status_change);
+ UnhookEvent(g_event_message_added);
+ UnhookEvent(g_protocol_ack);
+
+ delete g_speak_announce;
+ g_speak_announce = 0;
+ }
+
+ return 0;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ DisableThreadLibraryCalls(hinstDLL);
+ g_hInst = hinstDLL;
+ return TRUE;
+} \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/resource.h b/plugins/WinterSpeak/src/resource.h
new file mode 100644
index 0000000000..6775f8d314
--- /dev/null
+++ b/plugins/WinterSpeak/src/resource.h
@@ -0,0 +1,71 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Restart.rc
+//
+#define IDD_CONFIG 101
+#define IDD_ANNOUNCE 102
+#define IDD_ACTIVEMODES 103
+#define IDI_RECVMSG 136
+#define IDI_USERONLINE 201
+#define IDI_FILLEDBLOB 212
+#define IDI_EMPTYBLOB 213
+#define IDC_SELECT_ENGINE 1001
+#define IDC_SELECT_VOICE 1002
+#define IDC_SLIDER_RATE 1003
+#define IDC_SLIDER_VOLUME 1004
+#define IDC_SLIDER_PITCH 1005
+#define IDC_LOAD_SAPI 1006
+#define IDC_WELCOME_MSG 1007
+#define IDC_ACTIVE_OFFLINE 1008
+#define IDC_ACTIVE_ONLINE 1009
+#define IDC_ACTIVE_AWAY 1010
+#define IDC_ACTIVE_DND 1011
+#define IDC_ACTIVE_NA 1012
+#define IDC_ACTIVE_OCCUPIED 1013
+#define IDC_ACTIVE_FREEFORCHAT 1014
+#define IDC_ACTIVE_INVISIBLE 1015
+#define IDC_BUTTON_TEST 1016
+#define IDC_STATUS_OFFLINE 1100
+#define IDC_STATUS_ONLINE 1101
+#define IDC_STATUS_AWAY 1102
+#define IDC_STATUS_DND 1103
+#define IDC_STATUS_NA 1104
+#define IDC_STATUS_OCCUPIED 1105
+#define IDC_STATUS_FREEFORCHAT 1106
+#define IDC_STATUS_INVISIBLE 1107
+#define IDC_SPEAK_STATUS_MSG 1108
+#define IDC_EVENT_MESSAGE 1109
+#define IDC_EVENT_URL 1110
+#define IDC_EVENT_FILE 1111
+#define IDC_EVENT_AUTHREQUEST 1112
+#define IDC_EVENT_ADDED 1113
+#define IDC_READ_MSG_LENGTH 1114
+#define IDC_MAX_MSG 1115
+#define IDC_DIALOG_OPEN 1116
+#define IDC_DIALOG_FOCUSED 1117
+#define IDC_ACTIVE_USERS 1118
+#define IDC_ONLINEICON 1207
+#define IDC_MSGICON 1375
+#define IDC_ALLICON 1208
+#define IDC_NONEICON 1209
+#define IDC_SUPPRESS_CONNECT 1121
+#define IDC_CONFIG_LEXICON 1122
+
+#define IDD_TTS_LEXICON 201
+#define IDC_TTS_LEXICON_LIST 2001
+#define IDC_TTS_LEXICON_ORIGINAL 2002
+#define IDC_TTS_LEXICON_FINAL 2003
+#define IDC_TTS_LEXICON_ADD 2004
+#define IDC_TTS_LEXICON_REMOVE 2005
+#define IDC_TTS_LEXICON_TEST 2006
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/WinterSpeak/src/stdafx.cpp b/plugins/WinterSpeak/src/stdafx.cpp
new file mode 100644
index 0000000000..1976d867da
--- /dev/null
+++ b/plugins/WinterSpeak/src/stdafx.cpp
@@ -0,0 +1,18 @@
+/*
+Copyright (C) 2012-13 Miranda NG Project (http://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h" \ No newline at end of file
diff --git a/plugins/WinterSpeak/src/voice_desc.h b/plugins/WinterSpeak/src/voice_desc.h
new file mode 100644
index 0000000000..37ae72b0e9
--- /dev/null
+++ b/plugins/WinterSpeak/src/voice_desc.h
@@ -0,0 +1,10 @@
+#include <string>
+
+struct VoiceDesc
+{
+ std::wstring engine;
+ std::wstring voice;
+ int volume;
+ int pitch;
+ int rate;
+}; \ No newline at end of file