diff options
Diffstat (limited to 'plugins/KeyboardNotify/flash.cpp')
| -rw-r--r-- | plugins/KeyboardNotify/flash.cpp | 438 | 
1 files changed, 438 insertions, 0 deletions
diff --git a/plugins/KeyboardNotify/flash.cpp b/plugins/KeyboardNotify/flash.cpp new file mode 100644 index 0000000000..fd3815d0b1 --- /dev/null +++ b/plugins/KeyboardNotify/flash.cpp @@ -0,0 +1,438 @@ +/*
 +
 +This program is free software; you can redistribute it and/or
 +modify it under the terms of the GNU General Public License
 +as published by the Free Software Foundation; either version 2
 +of the License, or (at your option) any later version.
 +
 +This program is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with this program; if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +
 +*/
 +
 +#define WIN32_LEAN_AND_MEAN
 +
 +#include <windows.h>
 +#include "flash.h"
 +#include "keyboard.h"
 +#include "keypresses.h"
 +#include "utils.h"
 +#include "constants.h"
 +#include <newpluginapi.h>
 +#include <m_database.h>
 +
 +typedef struct {
 +	unsigned int size;
 +	unsigned int index;
 +	BYTE frame[MAX_PATH];
 +} FLASHING_SEQUENCE;
 +
 +
 +// Prototypes
 +FLASHING_SEQUENCE *getCustomSeq(void);
 +FLASHING_SEQUENCE *getPredefinedSeq(void);
 +FLASHING_SEQUENCE *getTrillianSeq(void);
 +void updateTrillianSeq(void);
 +static void TestThread(FLASHING_SEQUENCE *);
 +static void PreviewThread(void *);
 +FLASHING_SEQUENCE str2FS(TCHAR *);
 +BYTE KbdChar2Byte(char);
 +void countUnopenEvents(int *, int *, int *, int *);
 +
 +#define Leds2Flash	((BYTE)(bFlashLed[2] + (bFlashLed[0]<<1) + (bFlashLed[1]<<2)))
 +
 +// Flashing settings
 +FLASHING_SEQUENCE *pFS;
 +BOOL bTemporarilyUseExtern;
 +extern BYTE bFlashLed[3];
 +extern BYTE bFlashEffect; extern BYTE bSequenceOrder;
 +extern WORD wCustomTheme;
 +extern BYTE bTrillianLedsMsg; extern BYTE bTrillianLedsURL; extern BYTE bTrillianLedsFile; extern BYTE bTrillianLedsOther;
 +extern BYTE bEmulateKeypresses;
 +
 +
 +// TestThread/PreviewThread globals
 +extern int nWaitDelay; extern WORD wStartDelay;
 +BOOL bTestSemaphore, bPreviewSemaphore, bPreview;
 +
 +
 +void RestoreLEDState(void)
 +{
 +	if (bEmulateKeypresses)
 +		keypresses_RestoreLEDState();
 +	else
 +		ToggleKeyboardLights((BYTE)(LedState(VK_SCROLL) + (LedState(VK_NUMLOCK)<<1) + (LedState(VK_CAPITAL)<<2)));
 +}
 +
 +
 +BYTE getBlinkingLeds(void)
 +{
 +	if (!pFS->size)
 +		return (BYTE)(LedState(VK_SCROLL) + (LedState(VK_NUMLOCK)<<1) + (LedState(VK_CAPITAL)<<2));
 +
 +	pFS->index %= pFS->size;
 +	if (bFlashEffect == FLASH_TRILLIAN && !bTemporarilyUseExtern && !pFS->index)
 +		updateTrillianSeq();
 +	return pFS->frame[pFS->index++];
 +}
 +
 +
 +void setFlashingSequence(void)
 +{
 +	switch (bFlashEffect) {
 +		case FLASH_CUSTOM:
 +			pFS = getCustomSeq();
 +			break;
 +		case FLASH_TRILLIAN:
 +			pFS = getTrillianSeq();
 +			break;
 +		default:
 +			pFS = getPredefinedSeq();
 +	}
 +	bTemporarilyUseExtern = FALSE;
 +}
 +
 +
 +FLASHING_SEQUENCE *getCustomSeq(void)
 +{
 +	static FLASHING_SEQUENCE Custom = {0};
 +
 +	DBVARIANT dbv;
 +	TCHAR customStr[MAX_PATH+1];
 +
 +
 +	customStr[0] = _T('\0');
 +	if(!DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", wCustomTheme), &dbv)) {
 +		wcscpy(customStr, dbv.pwszVal);
 +		DBFreeVariant(&dbv);
 +	}
 +
 +	Custom = str2FS(customStr);
 +
 +	return &Custom;
 +}
 +
 +
 +FLASHING_SEQUENCE *getPredefinedSeq(void)
 +{
 +	static FLASHING_SEQUENCE Predefined = {0};
 +
 +	FLASHING_SEQUENCE *pAux;
 +	FLASHING_SEQUENCE SameTime = {2, 0, {7, 0}};
 +	FLASHING_SEQUENCE InTurn = {2, 0, {3, 4}};
 +	FLASHING_SEQUENCE InSeq = {3, 0, {2, 4, 1}};
 +	FLASHING_SEQUENCE InSeqRev = {3, 0, {1, 4, 2}};
 +	FLASHING_SEQUENCE InSeqKIT = {4, 0, {2, 4, 1, 4}};
 +
 +
 +	if (Leds2Flash < 3 || Leds2Flash == 4)
 +		pAux = &SameTime;
 +	else
 +		switch (bFlashEffect) {
 +			default:
 +			case FLASH_SAMETIME:
 +				pAux = &SameTime;
 +				break;
 +			case FLASH_INTURN:
 +				if (Leds2Flash == 3)	// 3 = Num+Scroll
 +					pAux = &InSeq;
 +				else
 +					pAux = &InTurn;
 +				break;
 +			case FLASH_INSEQUENCE:
 +				switch (bSequenceOrder) {
 +					default:
 +					case SEQ_LEFT2RIGHT:
 +						pAux = &InSeq;
 +						break;
 +					case SEQ_RIGHT2LEFT:
 +						pAux = &InSeqRev;
 +						break;
 +					case SEQ_LIKEKIT:
 +						if (Leds2Flash != 7)	// 7 = Num+Caps+Scroll
 +							pAux = &InSeq;
 +						else
 +							pAux = &InSeqKIT;
 +						break;
 +				}
 +				break;
 +		}
 +
 +	Predefined.size = Predefined.index = 0;
 +	for (pAux->index=0; pAux->index < pAux->size; pAux->index++)
 +		if (!pAux->frame[pAux->index] || (pAux->frame[pAux->index] & Leds2Flash)) {
 +			Predefined.size++;
 +			Predefined.frame[Predefined.size - 1] = pAux->frame[pAux->index] & Leds2Flash;
 +		}
 +
 +	return &Predefined;
 +}
 +
 +
 +FLASHING_SEQUENCE *getTrillianSeq(void)
 +{
 +	static FLASHING_SEQUENCE Trillian = {2, 0, {0, 0}};
 +
 +	Trillian.size = 2;
 +	Trillian.index = 0;
 +
 +	return &Trillian;
 +}
 +
 +
 +void updateTrillianSeq(void)
 +{
 +	int i, msgCount=0, fileCount=0, urlCount=0, otherCount=0;
 +
 +	pFS->size = 2;
 +	countUnopenEvents(&msgCount, &fileCount, &urlCount, &otherCount);
 +
 +	if ((bTrillianLedsMsg & Leds2Flash) && (pFS->size + 2 * msgCount) <= MAX_PATH)
 +		for (i=0; i < msgCount; i++) {
 +			pFS->frame[pFS->size++] = bTrillianLedsMsg & Leds2Flash;
 +			pFS->frame[pFS->size++] = 0;
 +		}
 +
 +	if ((bTrillianLedsFile & Leds2Flash) && (pFS->size + 2 * fileCount) <= MAX_PATH)
 +		for (i=0; i < fileCount; i++) {
 +			pFS->frame[pFS->size++] = bTrillianLedsFile & Leds2Flash;
 +			pFS->frame[pFS->size++] = 0;
 +		}
 +
 +	if ((bTrillianLedsURL & Leds2Flash) && (pFS->size + 2 * urlCount) <= MAX_PATH)
 +		for (i=0; i < urlCount; i++) {
 +			pFS->frame[pFS->size++] = bTrillianLedsURL & Leds2Flash;
 +			pFS->frame[pFS->size++] = 0;
 +		}
 +
 +	if ((bTrillianLedsOther & Leds2Flash) && (pFS->size + 2 * otherCount) <= MAX_PATH)
 +		for (i=0; i < otherCount; i++) {
 +			pFS->frame[pFS->size++] = bTrillianLedsOther & Leds2Flash;
 +			pFS->frame[pFS->size++] = 0;
 +		}
 +
 +}
 +
 +
 +void useExternSequence(TCHAR *extStr)
 +{
 +	static FLASHING_SEQUENCE Extern = {0};
 +
 +	TCHAR externStr[MAX_PATH+1];
 +
 +
 +	wcscpy(externStr, extStr);
 +
 +	Extern = str2FS(normalizeCustomString(externStr));
 +
 +	pFS = &Extern;
 +	bTemporarilyUseExtern = TRUE;
 +}
 +
 +
 +TCHAR *normalizeCustomString(TCHAR *customStr)
 +{
 +	int len=0, status=0;
 +	BOOL used[4];
 +	TCHAR strAux[MAX_PATH+1], *str;
 +
 +	for (wcscpy(str=strAux, customStr); *str; str++)
 +		switch (*str) {
 +			case _T('['):
 +				if (status == 0) {
 +					status = 1;
 +					customStr[len++] = *str;
 +					used[0] = used [1] = used[2] = used[3] = FALSE;
 +				}
 +				break;
 +			case _T(']'):
 +				if (status == 1) {
 +					status = 0;
 +					customStr[len++] = *str;
 +				}
 +				break;
 +			case _T('0'):
 +			case _T('1'):
 +			case _T('2'):
 +			case _T('3'):
 +				if (status == 0)
 +					customStr[len++] = *str;
 +				else
 +					if (!used[*str - _T('0')]) {
 +						customStr[len++] = *str;
 +						used[*str - _T('0')] = TRUE;
 +					}
 +				break;
 +		}
 +	if (status == 1)
 +		customStr[len++] = _T(']');
 +	customStr[len] = _T('\0');
 +
 +	return customStr;
 +}
 +
 +
 +TCHAR *getCurrentSequenceString(void)
 +{
 +	static TCHAR CurrentSeqString[MAX_PATH+1];
 +
 +	unsigned int i;
 +	TCHAR *str;
 +
 +
 +	for (i=0, str=CurrentSeqString; i < pFS->size; i++)
 +		switch (pFS->frame[i]) {
 +			case 0:
 +				*(str++) = _T('0');
 +				break;
 +			case 1:
 +				*(str++) = _T('3');
 +				break;
 +			case 2:
 +				*(str++) = _T('1');
 +				break;
 +			case 3:
 +				*(str++) = _T('[');
 +				*(str++) = _T('1');
 +				*(str++) = _T('3');
 +				*(str++) = _T(']');
 +				break;
 +			case 4:
 +				*(str++) = _T('2');
 +				break;
 +			case 5:
 +				*(str++) = _T('[');
 +				*(str++) = _T('2');
 +				*(str++) = _T('3');
 +				*(str++) = _T(']');
 +				break;
 +			case 6:
 +				*(str++) = _T('[');
 +				*(str++) = _T('1');
 +				*(str++) = _T('2');
 +				*(str++) = _T(']');
 +				break;
 +			case 7:
 +				*(str++) = _T('[');
 +				*(str++) = _T('1');
 +				*(str++) = _T('2');
 +				*(str++) = _T('3');
 +				*(str++) = _T(']');
 +		}
 +	*str = _T('\0');
 +
 +
 +	return CurrentSeqString;
 +}
 +
 +
 +void testSequence(TCHAR *testStr)
 +{
 +	static FLASHING_SEQUENCE Test = {0};
 +
 +	DWORD threadID = 0;
 +
 +
 +	if (bTestSemaphore) // we try to avoid concurrent test threads
 +		return;
 +	bTestSemaphore = TRUE;
 +
 +	Test = str2FS(testStr);
 +	
 +	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TestThread, &Test, 0, &threadID);
 +}
 +
 +
 +static void TestThread(FLASHING_SEQUENCE *pTest)
 +{
 +	unsigned int i;
 +	DWORD dwEndTest;
 +
 +	unsigned int testNum = (unsigned int)DBGetContactSettingByte(NULL, KEYBDMODULE, "testnum", DEF_SETTING_TESTNUM);
 +	unsigned int testSecs = (unsigned int)DBGetContactSettingByte(NULL, KEYBDMODULE, "testsecs", DEF_SETTING_TESTSECS);
 +
 +	for (i=0, dwEndTest=GetTickCount()+testSecs*1000; i < testNum || GetTickCount() < dwEndTest; i++)
 +		for (pTest->index=0; pTest->index < pTest->size; pTest->index++) {
 +			ToggleKeyboardLights(pTest->frame[pTest->index]);
 +			Sleep(nWaitDelay);
 +		}
 +
 +	RestoreLEDState();
 +
 +	bTestSemaphore = FALSE;	
 +}
 +
 +
 +void previewFlashing(BOOL buttonState)
 +{
 +	DWORD threadID = 0;
 +
 +	bPreview = buttonState;
 +
 +	if (!bPreview || bPreviewSemaphore) // turn off flashing or already running
 +		return;
 +
 +	bPreviewSemaphore = TRUE;
 +	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreviewThread, NULL, 0, &threadID);
 +}
 +
 +
 +static void PreviewThread(void *dummy)
 +{
 +	unsigned int i;
 +	BYTE unchangedLeds;
 +
 +	if (wStartDelay > 0)
 +		Sleep(wStartDelay * 1000);
 +
 +	unchangedLeds = (BYTE)(LedState(VK_SCROLL) * !bFlashLed[2] + ((LedState(VK_NUMLOCK) * !bFlashLed[0])<<1) + ((LedState(VK_CAPITAL) * !bFlashLed[1])<<2));
 +
 +	while (bPreview)
 +		for (i=0; bPreview && i < pFS->size; i++) {
 +			ToggleKeyboardLights((BYTE)(pFS->frame[i%pFS->size]|unchangedLeds));
 +			Sleep(nWaitDelay);				
 +		}
 +
 +	RestoreLEDState();
 +
 +	bPreviewSemaphore = FALSE;	
 +}
 +
 +
 +FLASHING_SEQUENCE str2FS(TCHAR *str)
 +{
 +	FLASHING_SEQUENCE Temp = {0};
 +
 +	for (Temp.size=Temp.index=0; *str; str++) {
 +		Temp.size++;
 +		if (*str == _T('[')) {
 +			Temp.frame[Temp.size - 1] = 0;
 +			for (str++; *str && *str != _T(']'); str++)
 +				Temp.frame[Temp.size - 1] += KbdChar2Byte(*str) & Leds2Flash;
 +			if (!*str) break;
 +		} else
 +			Temp.frame[Temp.size - 1] = KbdChar2Byte(*str) & Leds2Flash;
 +	}
 +
 +	return Temp;
 +}
 +
 +
 +BYTE KbdChar2Byte(char kbdChar)
 +{
 +	switch (kbdChar) {
 +		case '1': //NumLock
 +			return 2;
 +		case '2': //CapsLock
 +			return 4;
 +		case '3': //ScrollLock
 +			return 1;
 +	}
 +	return 0;
 +}
  | 
