From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- kbdnotify/flash.c | 438 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 kbdnotify/flash.c (limited to 'kbdnotify/flash.c') diff --git a/kbdnotify/flash.c b/kbdnotify/flash.c new file mode 100644 index 0000000..5450be9 --- /dev/null +++ b/kbdnotify/flash.c @@ -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 +#include "flash.h" +#include "keyboard.h" +#include "keypresses.h" +#include "utils.h" +#include "constants.h" +#include "../headers_c/newpluginapi.h" +#include "../headers_c/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(char *); +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; + char customStr[MAX_PATH+1]; + + + customStr[0] = '\0'; + if(!DBGetContactSetting(NULL, KEYBDMODULE, fmtDBSettingName("custom%d", wCustomTheme), &dbv)) { + strcpy(customStr, dbv.pszVal); + 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) +{ + unsigned 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(char *extStr) +{ + static FLASHING_SEQUENCE Extern = {0}; + + char externStr[MAX_PATH+1]; + + + strcpy(externStr, extStr); + + Extern = str2FS(normalizeCustomString(externStr)); + + pFS = &Extern; + bTemporarilyUseExtern = TRUE; +} + + +char *normalizeCustomString(char *customStr) +{ + int len=0, status=0; + BOOL used[4]; + char strAux[MAX_PATH+1], *str; + + for (strcpy(str=strAux, customStr); *str; str++) + switch (*str) { + case '[': + if (status == 0) { + status = 1; + customStr[len++] = *str; + used[0] = used [1] = used[2] = used[3] = FALSE; + } + break; + case ']': + if (status == 1) { + status = 0; + customStr[len++] = *str; + } + break; + case '0': + case '1': + case '2': + case '3': + if (status == 0) + customStr[len++] = *str; + else + if (!used[*str - '0']) { + customStr[len++] = *str; + used[*str - '0'] = TRUE; + } + break; + } + if (status == 1) + customStr[len++] = ']'; + customStr[len] = '\0'; + + return customStr; +} + + +char *getCurrentSequenceString(void) +{ + static char CurrentSeqString[MAX_PATH+1]; + + unsigned int i; + char *str; + + + for (i=0, str=CurrentSeqString; i < pFS->size; i++) + switch (pFS->frame[i]) { + case 0: + *(str++) = '0'; + break; + case 1: + *(str++) = '3'; + break; + case 2: + *(str++) = '1'; + break; + case 3: + *(str++) = '['; + *(str++) = '1'; + *(str++) = '3'; + *(str++) = ']'; + break; + case 4: + *(str++) = '2'; + break; + case 5: + *(str++) = '['; + *(str++) = '2'; + *(str++) = '3'; + *(str++) = ']'; + break; + case 6: + *(str++) = '['; + *(str++) = '1'; + *(str++) = '2'; + *(str++) = ']'; + break; + case 7: + *(str++) = '['; + *(str++) = '1'; + *(str++) = '2'; + *(str++) = '3'; + *(str++) = ']'; + } + *str = '\0'; + + + return CurrentSeqString; +} + + +void testSequence(char *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(char *str) +{ + FLASHING_SEQUENCE Temp = {0}; + + for (Temp.size=Temp.index=0; *str; str++) { + Temp.size++; + if (*str == '[') { + Temp.frame[Temp.size - 1] = 0; + for (str++; *str && *str != ']'; 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; +} -- cgit v1.2.3