From 67c6f233d7e60ad59918e734fe565f5f5dfd28d5 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sun, 20 May 2012 18:33:39 +0000 Subject: projects renames and fixes git-svn-id: http://svn.miranda-ng.org/main/trunk@105 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/AVS/CHANGELOG.AVS | 182 ++ plugins/AVS/README | 94 + plugins/AVS/README.SOURCE | 25 + plugins/AVS/acc.cpp | 908 +++++++ plugins/AVS/acc.h | 44 + plugins/AVS/avs.rc | 251 ++ plugins/AVS/avs_10.vcxproj | 290 +++ plugins/AVS/avs_10.vcxproj.filters | 70 + plugins/AVS/commonheaders.h | 119 + plugins/AVS/image_utils.cpp | 757 ++++++ plugins/AVS/image_utils.h | 58 + plugins/AVS/license.txt | 340 +++ plugins/AVS/main.cpp | 2684 ++++++++++++++++++++ plugins/AVS/mir_thread.cpp | 50 + plugins/AVS/mir_thread.h | 49 + plugins/AVS/options.cpp | 1147 +++++++++ plugins/AVS/poll.cpp | 319 +++ plugins/AVS/poll.h | 36 + plugins/AVS/res/avatar.ico | Bin 0 -> 2550 bytes plugins/AVS/resource.h | 60 + plugins/AVS/vc6.rc | 2 + plugins/AVS/version.h | 5 + plugins/AVS/version.rc | 113 + plugins/Avs/CHANGELOG.AVS | 182 -- plugins/Avs/README | 94 - plugins/Avs/README.SOURCE | 25 - plugins/Avs/acc.cpp | 908 ------- plugins/Avs/acc.h | 44 - plugins/Avs/avs.rc | 251 -- plugins/Avs/avs_10.vcxproj | 290 --- plugins/Avs/avs_10.vcxproj.filters | 70 - plugins/Avs/commonheaders.h | 119 - plugins/Avs/image_utils.cpp | 757 ------ plugins/Avs/image_utils.h | 58 - plugins/Avs/license.txt | 340 --- plugins/Avs/main.cpp | 2684 -------------------- plugins/Avs/mir_thread.cpp | 50 - plugins/Avs/mir_thread.h | 49 - plugins/Avs/options.cpp | 1147 --------- plugins/Avs/poll.cpp | 319 --- plugins/Avs/poll.h | 36 - plugins/Avs/res/avatar.ico | Bin 2550 -> 0 bytes plugins/Avs/resource.h | 60 - plugins/Avs/vc6.rc | 2 - plugins/Avs/version.h | 5 - plugins/Avs/version.rc | 113 - plugins/BASS_interface/Bass.h | 920 +++++++ plugins/BASS_interface/Bass.rc | 109 + plugins/BASS_interface/Bass_interface.h | 46 + plugins/BASS_interface/Bass_interface.sln | 26 + plugins/BASS_interface/Bass_interface.vcxproj | 203 ++ .../BASS_interface/Bass_interface.vcxproj.filters | 44 + plugins/BASS_interface/Main.cpp | 513 ++++ plugins/BASS_interface/Resource.h | 31 + plugins/BASS_interface/Version.h | 28 + plugins/BASS_interface/Version.rc | 38 + plugins/BASS_interface/res/BASSSoundOnOffDown.ico | Bin 0 -> 1150 bytes plugins/BASS_interface/res/BASSSoundOnOffUp.ico | Bin 0 -> 1150 bytes plugins/Bass_interface/Bass.h | 920 ------- plugins/Bass_interface/Bass.rc | 109 - plugins/Bass_interface/Bass_interface.h | 46 - plugins/Bass_interface/Bass_interface.sln | 26 - plugins/Bass_interface/Bass_interface.vcxproj | 203 -- .../Bass_interface/Bass_interface.vcxproj.filters | 44 - plugins/Bass_interface/Main.cpp | 513 ---- plugins/Bass_interface/Resource.h | 31 - plugins/Bass_interface/Version.h | 28 - plugins/Bass_interface/Version.rc | 38 - plugins/Bass_interface/res/BASSSoundOnOffDown.ico | Bin 1150 -> 0 bytes plugins/Bass_interface/res/BASSSoundOnOffUp.ico | Bin 1150 -> 0 bytes plugins/BossKeyPlus/BossKey_10.vcxproj | 87 +- 71 files changed, 9581 insertions(+), 9628 deletions(-) create mode 100644 plugins/AVS/CHANGELOG.AVS create mode 100644 plugins/AVS/README create mode 100644 plugins/AVS/README.SOURCE create mode 100644 plugins/AVS/acc.cpp create mode 100644 plugins/AVS/acc.h create mode 100644 plugins/AVS/avs.rc create mode 100644 plugins/AVS/avs_10.vcxproj create mode 100644 plugins/AVS/avs_10.vcxproj.filters create mode 100644 plugins/AVS/commonheaders.h create mode 100644 plugins/AVS/image_utils.cpp create mode 100644 plugins/AVS/image_utils.h create mode 100644 plugins/AVS/license.txt create mode 100644 plugins/AVS/main.cpp create mode 100644 plugins/AVS/mir_thread.cpp create mode 100644 plugins/AVS/mir_thread.h create mode 100644 plugins/AVS/options.cpp create mode 100644 plugins/AVS/poll.cpp create mode 100644 plugins/AVS/poll.h create mode 100644 plugins/AVS/res/avatar.ico create mode 100644 plugins/AVS/resource.h create mode 100644 plugins/AVS/vc6.rc create mode 100644 plugins/AVS/version.h create mode 100644 plugins/AVS/version.rc delete mode 100644 plugins/Avs/CHANGELOG.AVS delete mode 100644 plugins/Avs/README delete mode 100644 plugins/Avs/README.SOURCE delete mode 100644 plugins/Avs/acc.cpp delete mode 100644 plugins/Avs/acc.h delete mode 100644 plugins/Avs/avs.rc delete mode 100644 plugins/Avs/avs_10.vcxproj delete mode 100644 plugins/Avs/avs_10.vcxproj.filters delete mode 100644 plugins/Avs/commonheaders.h delete mode 100644 plugins/Avs/image_utils.cpp delete mode 100644 plugins/Avs/image_utils.h delete mode 100644 plugins/Avs/license.txt delete mode 100644 plugins/Avs/main.cpp delete mode 100644 plugins/Avs/mir_thread.cpp delete mode 100644 plugins/Avs/mir_thread.h delete mode 100644 plugins/Avs/options.cpp delete mode 100644 plugins/Avs/poll.cpp delete mode 100644 plugins/Avs/poll.h delete mode 100644 plugins/Avs/res/avatar.ico delete mode 100644 plugins/Avs/resource.h delete mode 100644 plugins/Avs/vc6.rc delete mode 100644 plugins/Avs/version.h delete mode 100644 plugins/Avs/version.rc create mode 100644 plugins/BASS_interface/Bass.h create mode 100644 plugins/BASS_interface/Bass.rc create mode 100644 plugins/BASS_interface/Bass_interface.h create mode 100644 plugins/BASS_interface/Bass_interface.sln create mode 100644 plugins/BASS_interface/Bass_interface.vcxproj create mode 100644 plugins/BASS_interface/Bass_interface.vcxproj.filters create mode 100644 plugins/BASS_interface/Main.cpp create mode 100644 plugins/BASS_interface/Resource.h create mode 100644 plugins/BASS_interface/Version.h create mode 100644 plugins/BASS_interface/Version.rc create mode 100644 plugins/BASS_interface/res/BASSSoundOnOffDown.ico create mode 100644 plugins/BASS_interface/res/BASSSoundOnOffUp.ico delete mode 100644 plugins/Bass_interface/Bass.h delete mode 100644 plugins/Bass_interface/Bass.rc delete mode 100644 plugins/Bass_interface/Bass_interface.h delete mode 100644 plugins/Bass_interface/Bass_interface.sln delete mode 100644 plugins/Bass_interface/Bass_interface.vcxproj delete mode 100644 plugins/Bass_interface/Bass_interface.vcxproj.filters delete mode 100644 plugins/Bass_interface/Main.cpp delete mode 100644 plugins/Bass_interface/Resource.h delete mode 100644 plugins/Bass_interface/Version.h delete mode 100644 plugins/Bass_interface/Version.rc delete mode 100644 plugins/Bass_interface/res/BASSSoundOnOffDown.ico delete mode 100644 plugins/Bass_interface/res/BASSSoundOnOffUp.ico (limited to 'plugins') diff --git a/plugins/AVS/CHANGELOG.AVS b/plugins/AVS/CHANGELOG.AVS new file mode 100644 index 0000000000..a673bdff73 --- /dev/null +++ b/plugins/AVS/CHANGELOG.AVS @@ -0,0 +1,182 @@ + + Version history: + +0.0.2.6 - 2006/08/03 + + * added file hashing (pescuma) + * rewrote the picture loading code. It is now running in a background thread + at low priority. The loader thread is the only instance which actually writes + to the cache entries. It does this with a small delay and notifies the hook + subscribers when a picture has been loaded. While it is not fully loaded, + the fallback protocol picture may be used. This makes connecting or + loading the clist with lots of avatars significantly faster at the cost + of delayed picture appearance. + It may also help with the sporadic lockups since the part of the code which + runs in the callers thread context is now much simpler. + +0.0.2.5 - 2006/07/30 + + * fixed updater support + * moved InitPolls() to ModulesLoaded() to avoid a problem with missing + core services. + * fixed keyboard navigation glitch in the Customize->Contact pictures dialog. + +0.0.2.4 - 2006/07/30 + + * bugfix (missing protocol avatars after migrating to new relpath) + * added proper version info resource record (showing ansi/unicode) + * added project files for Visual C++ 6 (source code release only) + +0.0.2.3 - 2006/07/11 + + * should now work better with metacontacts. Subcontact avatar changes are + "forwarded" to the master contact. + + * relative path names are now relative to the DATABASE directory, not + Mirandas root directory. + + * missing picture files and/or invalid database entries will now result + in a refresh request. + +0.0.2.0 introduced big internal changes. New request queue system (written by Pescuma) + loadavatars no longer depends on imgdecoder.dll, but needs a recent png2dib + plugin (supplied with Miranda 0.4.3.x nightly builds) + +0.0.1.12 - 0.0.2.2 - released via nightlys (see SVN changelog) + +0.0.1.11 - 2005/11/10 + + + added patch by pescuma for making normal avatars transparent (or semi- + transparent). + There are global (under Customize->Contact pictures) and per contact settings + (contact menu -> Contact picture...). In order to get good results, you will need + to tweak the settings a bit - it works for most avatar pictures with a uni-color + background, but it really depends on the image. + + + built with Visual Studio 2005 (Visual C++ 8.0). The DLL is now statically + linked, so they are somewhat bigger, but it avoids error messages because of the + new VC++ 8 runtime which is not installed on most PCs. + + + added unicode version (loadavatarsW.dll) which will display unicode nicknames in + the "per user" contact picture dialog. + + + added services and events to manage own avatar pictures. See m_avatars.h for more + information. Also, the drawing service was enhanced to allow drawing your own + avatars. + +0.0.1.10 - 2005/10/19 + + ! added support for jabber avatar updates. + + + better cleanup on Unload() + +0.0.1.9 - 2005/10/18 + + * accept .dat as valid image extension (sometimes, icq avatars are saved as .dat + files, even if they are actually JPG images (reason unknown, but we can load + them anyway. MS_UTILS_LOADBITMAP will return an error when the file is not + really a valid image - the extension doesn't matter). + +0.0.1.8 - 2005/10/17 + + ! fix. Don't show tray warning messages about invalid avatar file size when + the option "Show warning messages" on Customize->Contact pictures is unchecked. + + * changed way how protocols are enabled/disabled. After protocols have been added + or removed, "new" protocols are automatically enabled, so you don't have to do + that manually any more. + + * you can completely disable the size limit check by setting the size limit on + Customize->Contact List to 0 (zero). + +0.0.1.7 - 2005/10/16 + + * bugfix: check filenames more aggressivly. + + * bugfix: premultiply was broken (thanks FYR) + + + added a service to draw a contacts picture to a target device context. + See m_avatars.h for description on how to use that service. + + + added file size limitation to the picture loader. The default are 70Kbytes, + should be enough for most avatar pictures (they have to be small images). + The limit can be increased on the option page (Customize->contact pictures). + +0.0.1.5 - 2005/09/15 + + + added updater support + + * moved option page to Customize->Contact pictures + +0.0.1.4 - 2005/08/31 + + * cache reallocs will now send avatar change notifies (realloc() may move the + cache in memory, so pointers to avatar cache entries may become invalid). + + ! bugfix - badly written protocols which load themself too late are now + skipped and won't cause troubles because of the protocol list reallocation. + +0.0.1.3 - 2005/08/30 + + + ability to lock the avatar (protect from automatic updates). Useful, if you + have set a local contact picture and don't want it to be overwritten. + Actually, the feature does not really lock the avatar updating - it will + only save the picture from being overwritten. + + + added UI to set/change/lock avatar. DEVELOPERS please check m_avatars.h on how + to use the service from your own plugins. There are now services to lock and/or + set the avatar, either by providing a valid image filename or by using a file + selection dialog. Also, there is a service to call the avatar dialog for a + hContact. + + * struct avatarCacheEntry has changed too. It now provides szFilename which + will contain the full image filename of the current avatar in use. + + * added a menu item to the contact menu which allows to set avatar options (local + picture, locked avatar, and a "hidden" attribute). + The hidden attribute is set in the struct avatarCacheEntry + + + added support for PNG images (imgdecoder.dll needs to be present in either the + main miranda directory or the \Plugins subfolder. Transparent PNG images are + supported and the avatar service will perform the premultiplication of alpha + values so that the image can (and should) be rendered with the AlphaBlend() + API. + +0.0.1.2 - 2005/08/20 + + + the service now creates and uses relative filenames for all contact pictures, + including protocol avatars, if possible. + + * for protocols which are in "invisible" status, no active avatar fetching + is performed. This is to avoid problems with MSN and privacy issues for + other protocols (if you're invisible, then the protocol should not initiate + any outbound communications which may require direct p2p connections). + + * an option page has been added. Currently, you can: + + + select, for which protocols the service should ACTIVELY fetch avatars. + If you set a protocols to "inactive" (uncheck it), already existing + avatars for contacts of that protocol will continue to work, but the + service will no longer actively refresh avatars. + + + set protocol pictures (pseudo avatars). You can select local pictures + for each installed protocol. These will be used as a fallback then, if + no avatar is available for a contact. You can also remove these pictures. + + * don't fetch avatars for contacts which are either blocked or set on the + invisibility list (ApparentMode == ID_STATUS_OFFLINE). Reason: No active + outbound communications w/o user intervention should be initiated for blocked + contacts. + + + added support for the updater plugin. + +0.0.1.1 - 2005/08/06 + + * changed API. Don't return HBITMAP directly, but instead, it returns + a pointer to a struct avatarCacheEntry which can be used to obtain + the bitmap handle. + +0.0.1.0 - 2005/08/05 + + * initial release, cvs import. + diff --git a/plugins/AVS/README b/plugins/AVS/README new file mode 100644 index 0000000000..d82d1d7fec --- /dev/null +++ b/plugins/AVS/README @@ -0,0 +1,94 @@ + + Load avatars 0.0.1.0 + -------------------- + +This is a SERVICE plugin, which means, it doesn't provide anything useful +on its own except for a few service(s) and event(s) which can be used by +other plugins. + +What it does? +------------- + +It loads avatars on demand and maintains an internal cache of avatar +bitmap handles. It also handles avatar changes transparently and can +notify event subscribers about avatar changes. + +How it works? +------------- + +The service MS_AV_GETAVATARBITMAP returns a pointer to a cache entry, if an +avatar is present for that contact. The service MAY return 0, in which +case, there is no valid avatar yet. However, that doesn't mean there +isn't ANY avatar, just that the avatar is not yet ready for use. When +someone calls the service requesting an avatar, the plugin will try +to get the avatar (if possible) and notify all subscribers via a +hookable event as soon as the avatar is ready. If the avatar is +already in the cache, it simply returns the cached entry. + +Whenever an avatar changes, the plugin fires an event, passing the +contacts handle in wParam and a data structure with the avatar information +in lParam. Plugins which use the bitmap handles returned by +MS_AV_GETAVATARBITMAP MUST subscribe to ME_AV_AVATARCHANGED, because the +original bitmap handle may become invalid when the avatar changes. + +Fetching avatars is done in a separate thread with reasonable delays to +avoid getting into troubles with flood protection(s). Avatars are cached +"in memory". + + +The included clist_nicer_plus.dll is a demonstration of how the avatar +service works and can be used by developers. Having a central instance +which maintains avatars saves resources and increases performance. + + +// example, how to use it (FOR DEVS only) + +#include "m_avatars.h" + +struct avatarCacheEntry *ace = 0; +HBITMAP hbmAvatar = 0; + +ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0); + +/* + now, check the return value. if it is 0, then the avatar is not yet ready or unavailble + for that contact. if it was only "not ready", your plugin will be notified by the + hookable event ME_AV_AVATARCHANGED + + if the return value is != 0, then it is a valid bitmap handle. DON'T DESTROY IT IN YOUR CODE +*/ + + +/* + * event function + * initialise with: + * HANDLE hEvent = HookEvent(ME_AV_AVATARCHANGED, AvatarChanged); + */ + +static int AvatarChanged(WPARAM wParam, LPARAM lParam) +{ + struct avatarCacheEntry *ace = (struct avatarCacheEntry *)lParam; + HANDLE hContact = (HANDLE)wParam; + + if(ace == NULL) + return 0; + if(ace->cbSize != sizeof(struct avatarCacheEntry)) + return 0; // safety check(s) + + HBITMAP hbmAvatar = ace->hbmPic; + ... + ... +} + + +TODO: maybe more intelligent cache managment, including auto-expire of avatars which + have not been used for a while. + + +Copyright and license: +---------------------- + +This plugin is released under the terms of the GNU general public license V2 or any later +version. + +Written, 2005 by Nightwish, silvercircle@gmail.com diff --git a/plugins/AVS/README.SOURCE b/plugins/AVS/README.SOURCE new file mode 100644 index 0000000000..5f87280afe --- /dev/null +++ b/plugins/AVS/README.SOURCE @@ -0,0 +1,25 @@ + +Source code for the loadavatars (avatar service plugin) is available via +anonymous SVN at: + +http://svn.berlios.de/svnroot/repos/mimplugins/trunk/avs/ + +You need a SVN client to access this, I recommend TortoiseSVN for Windows which +is easy to use and provides a good UI. + +To compile, you need a complete checkout of Mirandas main source repository and +Visual C++ 6 with service pack 6 + the latest platform SDK installed. + +Project files are provided for Visual C++ 6 and Visual Studio 2005 (aka Visual +C++ 8). The sources may compile with Mingw32/GCC, but this is not supported at +this time. + +This plugin for the Miranda Instant messenger is licensed under the GNU +General Public License Version 2. + +The code was written by: + +Nightwish (silvercircle@gmail.com) (original idea and implementation) +Pescuma (major rewrite for version 0.0.2.0 with new request/poll code and most of + the image manipulation utilities). + diff --git a/plugins/AVS/acc.cpp b/plugins/AVS/acc.cpp new file mode 100644 index 0000000000..f62009b43d --- /dev/null +++ b/plugins/AVS/acc.cpp @@ -0,0 +1,908 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +extern FI_INTERFACE *fei; + +int GetImageFormat(TCHAR *filename); +INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam); +INT_PTR GetAvatarBitmap(WPARAM wParam, LPARAM lParam); +INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam); +void InternalDrawAvatar(AVATARDRAWREQUEST *r, HBITMAP hbm, LONG bmWidth, LONG bmHeight, DWORD dwFlags); + + +#define DM_AVATARCHANGED (WM_USER + 20) +#define DM_MYAVATARCHANGED (WM_USER + 21) + +#define GIF_DISPOSAL_UNSPECIFIED 0 +#define GIF_DISPOSAL_LEAVE 1 +#define GIF_DISPOSAL_BACKGROUND 2 +#define GIF_DISPOSAL_PREVIOUS 3 + +typedef struct +{ + HANDLE hContact; + char proto[64]; + HANDLE hHook; + HANDLE hHookMy; + HFONT hFont; // font + COLORREF borderColor; + COLORREF bkgColor; + COLORREF avatarBorderColor; + int avatarRoundCornerRadius; + TCHAR noAvatarText[128]; + BOOL respectHidden; + BOOL showingFlash; + BOOL resizeIfSmaller; + BOOL fAero; + BOOL showingAnimatedGif; + + struct { + HBITMAP *hbms; + int *times; + + FIMULTIBITMAP *multi; + FIBITMAP *dib; + int frameCount; + int logicalWidth; + int logicalHeight; + BOOL loop; + RGBQUAD background; + BOOL started; + + struct { + int num; + int top; + int left; + int width; + int height; + int disposal_method; + } frame; + } ag; + +} ACCData; + + +void ResizeFlash(HWND hwnd, ACCData* data) +{ + if ((data->hContact != NULL || data->proto[0] != '\0') + && ServiceExists(MS_FAVATAR_RESIZE)) + { + RECT rc; + GetClientRect(hwnd, &rc); + + if (data->borderColor != -1 || data->avatarBorderColor != -1) + { + rc.left ++; + rc.right -= 2; + rc.top ++; + rc.bottom -= 2; + } + + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_RESIZE, (WPARAM)&fa, (LPARAM)&rc); + CallService(MS_FAVATAR_SETPOS, (WPARAM)&fa, (LPARAM)&rc); + } +} + +void SetBkgFlash(HWND hwnd, ACCData* data) +{ + if ((data->hContact != NULL || data->proto[0] != '\0') + && ServiceExists(MS_FAVATAR_SETBKCOLOR)) + { + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + + if (data->bkgColor != -1) + CallService(MS_FAVATAR_SETBKCOLOR, (WPARAM)&fa, (LPARAM)data->bkgColor); + else + CallService(MS_FAVATAR_SETBKCOLOR, (WPARAM)&fa, (LPARAM)RGB(255,255,255)); + } +} + +void DestroyFlash(HWND hwnd, ACCData* data) +{ + if (!data->showingFlash) + return; + + if ((data->hContact != NULL || data->proto[0] != '\0') + && ServiceExists(MS_FAVATAR_DESTROY)) + { + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_DESTROY, (WPARAM)&fa, 0); + } + + data->showingFlash = FALSE; +} + +void StartFlash(HWND hwnd, ACCData* data) +{ + if (!ServiceExists(MS_FAVATAR_MAKE)) + return; + + int format; + if (data->hContact != NULL) + { + format = DBGetContactSettingWord(data->hContact, "ContactPhoto", "Format", 0); + } + else if (data->proto[0] != '\0') + { + protoPicCacheEntry *ace = NULL; + for(int i = 0; i < g_MyAvatars.getCount(); i++) + { + if (!lstrcmpA(data->proto, g_MyAvatars[i].szProtoname)) + { + ace = &g_MyAvatars[i]; + break; + } + } + + if (ace != NULL && ace->szFilename != NULL) + format = GetImageFormat(ace->szFilename); + else + format = 0; + } + else + return; + + if (format != PA_FORMAT_XML && format != PA_FORMAT_SWF) + return; + + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0); + + if (fa.hWindow == NULL) + return; + + data->showingFlash = TRUE; + ResizeFlash(hwnd, data); + SetBkgFlash(hwnd, data); +} + +BOOL AnimatedGifGetData(ACCData* data) +{ + FIBITMAP *page = fei->FI_LockPage(data->ag.multi, 0); + if (page == NULL) + return FALSE; + + // Get info + FITAG *tag = NULL; + if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalWidth", &tag)) + goto ERR; + data->ag.logicalWidth = *(WORD *)fei->FI_GetTagValue(tag); + + if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalHeight", &tag)) + goto ERR; + data->ag.logicalHeight = *(WORD *)fei->FI_GetTagValue(tag); + + if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "Loop", &tag)) + goto ERR; + data->ag.loop = (*(LONG *)fei->FI_GetTagValue(tag) > 0); + + if (fei->FI_HasBackgroundColor(page)) + fei->FI_GetBackgroundColor(page, &data->ag.background); + + fei->FI_UnlockPage(data->ag.multi, page, FALSE); + return TRUE; + +ERR: + fei->FI_UnlockPage(data->ag.multi, page, FALSE); + return FALSE; +} + +void AnimatedGifDispodeFrame(ACCData* data) +{ + if (data->ag.frame.disposal_method == GIF_DISPOSAL_PREVIOUS) + { + // TODO + } + else if (data->ag.frame.disposal_method == GIF_DISPOSAL_BACKGROUND) + { + for (int y = 0; y < data->ag.frame.height; y++) + { + RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(data->ag.dib, + data->ag.logicalHeight - (y + data->ag.frame.top) - 1) + data->ag.frame.left; + for (int x = 0; x < data->ag.frame.width; x++) + *scanline++ = data->ag.background; + } + } +} + +void AnimatedGifMountFrame(ACCData* data, int page) +{ + data->ag.frame.num = page; + + if (data->ag.hbms[page] != NULL) + { + data->ag.frame.disposal_method = GIF_DISPOSAL_LEAVE; + return; + } + + FIBITMAP *dib = fei->FI_LockPage(data->ag.multi, data->ag.frame.num); + if (dib == NULL) + return; + + FITAG *tag = NULL; + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameLeft", &tag)) + data->ag.frame.left = *(WORD *)fei->FI_GetTagValue(tag); + else + data->ag.frame.left = 0; + + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTop", &tag)) + data->ag.frame.top = *(WORD *)fei->FI_GetTagValue(tag); + else + data->ag.frame.top = 0; + + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTime", &tag)) + data->ag.times[page] = *(LONG *)fei->FI_GetTagValue(tag); + else + data->ag.times[page] = 0; + + if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "DisposalMethod", &tag)) + data->ag.frame.disposal_method = *(BYTE *)fei->FI_GetTagValue(tag); + else + data->ag.frame.disposal_method = 0; + + data->ag.frame.width = fei->FI_GetWidth(dib); + data->ag.frame.height = fei->FI_GetHeight(dib); + + + //decode page + int palSize = fei->FI_GetColorsUsed(dib); + RGBQUAD *pal = fei->FI_GetPalette(dib); + bool have_transparent = false; + int transparent_color = -1; + if( fei->FI_IsTransparent(dib) ) { + int count = fei->FI_GetTransparencyCount(dib); + BYTE *table = fei->FI_GetTransparencyTable(dib); + for( int i = 0; i < count; i++ ) { + if( table[i] == 0 ) { + have_transparent = true; + transparent_color = i; + break; + } + } + } + + //copy page data into logical buffer, with full alpha opaqueness + for( int y = 0; y < data->ag.frame.height; y++ ) { + RGBQUAD *scanline = (RGBQUAD *)fei->FI_GetScanLine(data->ag.dib, data->ag.logicalHeight - (y + data->ag.frame.top) - 1) + data->ag.frame.left; + BYTE *pageline = fei->FI_GetScanLine(dib, data->ag.frame.height - y - 1); + for( int x = 0; x < data->ag.frame.width; x++ ) { + if( !have_transparent || *pageline != transparent_color ) { + *scanline = pal[*pageline]; + scanline->rgbReserved = 255; + } + scanline++; + pageline++; + } + } + + data->ag.hbms[page] = fei->FI_CreateHBITMAPFromDIB(data->ag.dib); + + fei->FI_UnlockPage(data->ag.multi, dib, FALSE); +} + +void AnimatedGifDeleteTmpValues(ACCData* data) +{ + if (data->ag.multi != NULL) + { + fei->FI_CloseMultiBitmap(data->ag.multi, 0); + data->ag.multi = NULL; + } + + if (data->ag.dib != NULL) + { + fei->FI_Unload(data->ag.dib); + data->ag.dib = NULL; + } +} + +void DestroyAnimatedGif(HWND hwnd, ACCData* data) +{ + if (!data->showingAnimatedGif) + return; + + AnimatedGifDeleteTmpValues(data); + + if (data->ag.hbms != NULL) + { + for (int i = 0; i < data->ag.frameCount; i++) + if (data->ag.hbms[i] != NULL) + DeleteObject(data->ag.hbms[i]); + + free(data->ag.hbms); + data->ag.hbms = NULL; + } + + if (data->ag.times != NULL) + { + free(data->ag.times); + data->ag.times = NULL; + } + + data->showingAnimatedGif = FALSE; +} + +void StartAnimatedGif(HWND hwnd, ACCData* data) +{ + if (fei == NULL) + return; + + int x, y; + AVATARCACHEENTRY *ace = NULL; + + if (data->hContact != NULL) + ace = (AVATARCACHEENTRY *) GetAvatarBitmap((WPARAM) data->hContact, 0); + else + ace = (AVATARCACHEENTRY *) GetMyAvatar(0, (LPARAM) data->proto); + + if (ace == NULL) + return; + + int format = GetImageFormat(ace->szFilename); + if (format != PA_FORMAT_GIF) + return; + + FREE_IMAGE_FORMAT fif = fei->FI_GetFileTypeT(ace->szFilename, 0); + if(fif == FIF_UNKNOWN) + fif = fei->FI_GetFIFFromFilenameT(ace->szFilename); + + data->ag.multi = fei->FI_OpenMultiBitmapT(fif, ace->szFilename, FALSE, TRUE, FALSE, GIF_LOAD256); + if (data->ag.multi == NULL) + return; + + data->ag.frameCount = fei->FI_GetPageCount(data->ag.multi); + if (data->ag.frameCount <= 1) + goto ERR; + + if (!AnimatedGifGetData(data)) + goto ERR; + + //allocate entire logical area + data->ag.dib = fei->FI_Allocate(data->ag.logicalWidth, data->ag.logicalHeight, 32, 0, 0, 0); + if (data->ag.dib == NULL) + goto ERR; + + //fill with background color to start + for (y = 0; y < data->ag.logicalHeight; y++) + { + RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(data->ag.dib, y); + for (x = 0; x < data->ag.logicalWidth; x++) + *scanline++ = data->ag.background; + } + + data->ag.hbms = (HBITMAP *) malloc(sizeof(HBITMAP) * data->ag.frameCount); + memset(data->ag.hbms, 0, sizeof(HBITMAP) * data->ag.frameCount); + + data->ag.times = (int *) malloc(sizeof(int) * data->ag.frameCount); + memset(data->ag.times, 0, sizeof(int) * data->ag.frameCount); + + AnimatedGifMountFrame(data, 0); + + data->showingAnimatedGif = TRUE; + + return; +ERR: + fei->FI_CloseMultiBitmap(data->ag.multi, 0); + data->ag.multi = NULL; +} + +void DestroyAnimation(HWND hwnd, ACCData* data) +{ + DestroyFlash(hwnd, data); + DestroyAnimatedGif(hwnd, data); +} + +void StartAnimation(HWND hwnd, ACCData* data) +{ + StartFlash(hwnd, data); + + if (!data->showingFlash) + StartAnimatedGif(hwnd, data); +} + +BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) +{ + BOOL ret; + + POINT pt; + + pt.x = lpRect->left; + pt.y = lpRect->top; + + ret = ScreenToClient(hWnd, &pt); + + if (!ret) return ret; + + lpRect->left = pt.x; + lpRect->top = pt.y; + + + pt.x = lpRect->right; + pt.y = lpRect->bottom; + + ret = ScreenToClient(hWnd, &pt); + + lpRect->right = pt.x; + lpRect->bottom = pt.y; + + return ret; +} + +static void Invalidate(HWND hwnd) +{ + ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); + if (data->bkgColor == -1) + { + HWND parent = GetParent(hwnd); + RECT rc; + GetWindowRect(hwnd, &rc); + ScreenToClient(parent, &rc); + InvalidateRect(parent, &rc, TRUE); + } + InvalidateRect(hwnd, NULL, TRUE); +} + +static void NotifyAvatarChange(HWND hwnd) +{ + PSHNOTIFY pshn = {0}; + pshn.hdr.idFrom = GetDlgCtrlID(hwnd); + pshn.hdr.hwndFrom = hwnd; + pshn.hdr.code = NM_AVATAR_CHANGED; + pshn.lParam = 0; + SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &pshn); +} + +static void DrawText(HDC hdc, HFONT hFont, const RECT &rc, const TCHAR *text) +{ + HGDIOBJ oldFont = SelectObject(hdc, hFont); + + // Get text rectangle + RECT tr = rc; + tr.top += 10; + tr.bottom -= 10; + tr.left += 10; + tr.right -= 10; + + // Calc text size + RECT tr_ret = tr; + DrawText(hdc, text, -1, &tr_ret, + DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT); + + // Calc needed size + tr.top += ((tr.bottom - tr.top) - (tr_ret.bottom - tr_ret.top)) / 2; + tr.bottom = tr.top + (tr_ret.bottom - tr_ret.top); + DrawText(hdc, text, -1, &tr, + DT_WORDBREAK | DT_NOPREFIX | DT_CENTER); + + SelectObject(hdc, oldFont); +} + +static LRESULT CALLBACK ACCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); + switch(msg) + { + case WM_NCCREATE: + { + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_OWNERDRAW); + SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT); + + data = (ACCData*) mir_alloc(sizeof(ACCData)); + if (data == NULL) + return FALSE; + SetWindowLongPtr(hwnd, 0, (LONG_PTR)data); + + ZeroMemory(data, sizeof(ACCData)); + data->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwnd, DM_AVATARCHANGED); + data->hHookMy = HookEventMessage(ME_AV_MYAVATARCHANGED, hwnd, DM_MYAVATARCHANGED); + data->hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); + data->borderColor = -1; + data->bkgColor = -1; + data->avatarBorderColor = -1; + data->respectHidden = TRUE; + data->showingFlash = FALSE; + data->resizeIfSmaller = TRUE; + data->showingAnimatedGif = FALSE; + data->fAero = FALSE; + + return TRUE; + } + case WM_NCDESTROY: + { + DestroyAnimation(hwnd, data); + if (data) + { + UnhookEvent(data->hHook); + UnhookEvent(data->hHookMy); + mir_free(data); + } + SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); + break; + } + case WM_SETFONT: + { + data->hFont = (HFONT)wParam; + Invalidate(hwnd); + break; + } + case AVATAR_SETCONTACT: + { + DestroyAnimation(hwnd, data); + + data->hContact = (HANDLE) lParam; + lstrcpynA(data->proto, (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)data->hContact, 0), sizeof(data->proto)); + + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETPROTOCOL: + { + DestroyAnimation(hwnd, data); + + data->hContact = NULL; + if (lParam == NULL) + data->proto[0] = '\0'; + else + lstrcpynA(data->proto, (char *) lParam, sizeof(data->proto)); + + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETBKGCOLOR: + { + data->bkgColor = (COLORREF) lParam; + if (data->showingFlash) + SetBkgFlash(hwnd, data); + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETBORDERCOLOR: + { + data->borderColor = (COLORREF) lParam; + if (data->showingFlash) + ResizeFlash(hwnd, data); + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETAVATARBORDERCOLOR: + { + data->avatarBorderColor = (COLORREF) lParam; + if (data->showingFlash) + ResizeFlash(hwnd, data); + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETAVATARROUNDCORNERRADIUS: + { + data->avatarRoundCornerRadius = (int) lParam; + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETNOAVATARTEXT: + { + lstrcpyn(data->noAvatarText, TranslateTS((TCHAR*) lParam), SIZEOF(data->noAvatarText)); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_RESPECTHIDDEN: + { + data->respectHidden = (BOOL) lParam; + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + case AVATAR_SETRESIZEIFSMALLER: + { + data->resizeIfSmaller = (BOOL) lParam; + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + return TRUE; + } + + case AVATAR_SETAEROCOMPATDRAWING: + data->fAero = lParam; + return(TRUE); + + case AVATAR_GETUSEDSPACE: + { + int *width = (int *)wParam; + int *height = (int *)lParam; + + RECT rc; + GetClientRect(hwnd, &rc); + + // Get avatar + if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO)) + { + FLASHAVATAR fa = {0}; + fa.hContact = data->hContact; + fa.cProto = data->proto; + fa.hParentWindow = hwnd; + fa.id = 1675; + CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0); + if (fa.hWindow != NULL) + { + *width = rc.right - rc.left; + *height = rc.bottom - rc.top; + return TRUE; + } + } + + avatarCacheEntry *ace; + if (data->hContact == NULL) + ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) data->proto); + else + ace = (avatarCacheEntry *) CallService(MS_AV_GETAVATARBITMAP, (WPARAM) data->hContact, 0); + + if (ace == NULL || ace->bmHeight == 0 || ace->bmWidth == 0 + || (data->respectHidden && (ace->dwFlags & AVS_HIDEONCLIST))) + { + *width = 0; + *height = 0; + return TRUE; + } + + // Get its size + int targetWidth = rc.right - rc.left; + int targetHeight = rc.bottom - rc.top; + + if (!data->resizeIfSmaller && ace->bmHeight <= targetHeight && ace->bmWidth <= targetWidth) + { + *height = ace->bmHeight; + *width = ace->bmWidth; + } + else if (ace->bmHeight > ace->bmWidth) + { + float dScale = targetHeight / (float)ace->bmHeight; + *height = targetHeight; + *width = (int) (ace->bmWidth * dScale); + } + else + { + float dScale = targetWidth / (float)ace->bmWidth; + *height = (int) (ace->bmHeight * dScale); + *width = targetWidth; + } + + return TRUE; + } + case DM_AVATARCHANGED: + { + if (data->hContact == (HANDLE) wParam) + { + DestroyAnimation(hwnd, data); + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + } + break; + } + case DM_MYAVATARCHANGED: + { + if (data->hContact == NULL && strcmp(data->proto, (char*) wParam) == 0) + { + DestroyAnimation(hwnd, data); + StartAnimation(hwnd, data); + + NotifyAvatarChange(hwnd); + Invalidate(hwnd); + } + break; + } + case WM_NCPAINT: + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + if (hdc == NULL) + break; + + int oldBkMode = SetBkMode(hdc, TRANSPARENT); + SetStretchBltMode(hdc, HALFTONE); + + RECT rc; + GetClientRect(hwnd, &rc); + + // Draw background + if (data->bkgColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->bkgColor); + FillRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + if (data->hContact == NULL && data->proto[0] == '\0' + && DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) + { + DrawText(hdc, data->hFont, rc, TranslateT("Protocols have different avatars")); + } + + // Has a flash avatar + else if (data->showingFlash) + { + // Don't draw + + // Draw control border if needed + if (data->borderColor == -1 && data->avatarBorderColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->avatarBorderColor); + FrameRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + } + + // Has an animated gif + // Has a "normal" image + else + { + // Draw avatar + AVATARDRAWREQUEST avdrq = {0}; + avdrq.cbSize = sizeof(avdrq); + avdrq.rcDraw = rc; + avdrq.hContact = data->hContact; + avdrq.szProto = data->proto; + avdrq.hTargetDC = hdc; + avdrq.dwFlags = AVDRQ_HIDEBORDERONTRANSPARENCY + | (data->respectHidden ? AVDRQ_RESPECTHIDDEN : 0) + | (data->hContact != NULL ? 0 : AVDRQ_OWNPIC) + | (data->avatarBorderColor == -1 ? 0 : AVDRQ_DRAWBORDER) + | (data->avatarRoundCornerRadius <= 0 ? 0 : AVDRQ_ROUNDEDCORNER) + | (data->fAero ? AVDRQ_AERO : 0) + | (data->resizeIfSmaller ? 0 : AVDRQ_DONTRESIZEIFSMALLER); + avdrq.clrBorder = data->avatarBorderColor; + avdrq.radius = data->avatarRoundCornerRadius; + + INT_PTR ret; + if (data->showingAnimatedGif) + { + InternalDrawAvatar(&avdrq, data->ag.hbms[data->ag.frame.num], data->ag.logicalWidth, data->ag.logicalHeight, 0); + ret = 1; + + if (!data->ag.started) + { + SetTimer(hwnd, 0, data->ag.times[data->ag.frame.num], NULL); + data->ag.started = TRUE; + } + } + else + ret = DrawAvatarPicture(0, (LPARAM)&avdrq); + + if (ret == 0) + DrawText(hdc, data->hFont, rc, data->noAvatarText); + } + + // Draw control border + if (data->borderColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->borderColor); + FrameRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + SetBkMode(hdc, oldBkMode); + + EndPaint(hwnd, &ps); + return TRUE; + } + case WM_ERASEBKGND: + { + HDC hdc = (HDC) wParam; + RECT rc; + GetClientRect(hwnd, &rc); + + // Draw background + if (data->bkgColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->bkgColor); + FillRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + // Draw control border + if (data->borderColor != -1) + { + HBRUSH hbrush = CreateSolidBrush(data->borderColor); + FrameRect(hdc, &rc, hbrush); + DeleteObject(hbrush); + } + + return TRUE; + } + case WM_SIZE: + { + if (data->showingFlash) + ResizeFlash(hwnd, data); + InvalidateRect(hwnd, NULL, TRUE); + break; + } + case WM_TIMER: + { + if (wParam != 0) + break; + KillTimer(hwnd, 0); + + if (!data->showingAnimatedGif) + break; + + AnimatedGifDispodeFrame(data); + + int frame = data->ag.frame.num + 1; + if (frame >= data->ag.frameCount) + { + // Don't need fi data no more + AnimatedGifDeleteTmpValues(data); + frame = 0; + } + AnimatedGifMountFrame(data, frame); + + data->ag.started = FALSE; + InvalidateRect(hwnd, NULL, FALSE); + + break; + } + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} + + +int LoadACC() +{ + WNDCLASSEX wc = {0}; + wc.cbSize = sizeof(wc); + wc.lpszClassName = AVATAR_CONTROL_CLASS; + wc.lpfnWndProc = ACCWndProc; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.cbWndExtra = sizeof(ACCData*); + wc.hbrBackground = 0; + wc.style = CS_GLOBALCLASS; + RegisterClassEx(&wc); + return 0; +} diff --git a/plugins/AVS/acc.h b/plugins/AVS/acc.h new file mode 100644 index 0000000000..11b235adc0 --- /dev/null +++ b/plugins/AVS/acc.h @@ -0,0 +1,44 @@ +/* +Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __ACC_H__ +# define __ACC_H__ + +class A2T +{ + TCHAR* buf; + +public: + A2T( const char* s ) : buf( mir_a2t( s )) {} + A2T( const char* s, int cp ) : buf( mir_a2t_cp( s, cp )) {} + ~A2T() { mir_free(buf); } + + __forceinline operator TCHAR*() const + { return buf; + } +}; + +INT_PTR avSetAvatar( HANDLE hContact, TCHAR* tszPath ); +INT_PTR avSetMyAvatar( char* szProto, TCHAR* tszPath ); + +int LoadACC(); + + +#endif // __ACC_H__ diff --git a/plugins/AVS/avs.rc b/plugins/AVS/avs.rc new file mode 100644 index 0000000000..e1818ede8d --- /dev/null +++ b/plugins/AVS/avs.rc @@ -0,0 +1,251 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPTIONS_PICTS DIALOGEX 0, 0, 299, 214 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CTEXT "The pictures you can set here are used as default avatars\nfor contacts that don't have their own.\nUse the checkboxes to enable/disable showing avatars for the protocols.",IDC_STATIC,0,13,294,27 + CONTROL "",IDC_PROTOCOLS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,19,83,150,85 + PUSHBUTTON "Set default picture",IDC_SETPROTOPIC,176,83,106,14 + PUSHBUTTON "Delete default picture",IDC_REMOVEPROTOPIC,176,99,106,14 + CONTROL "",IDC_PROTOPIC,"Button",BS_OWNERDRAW,197,118,56,50 + EDITTEXT IDC_PROTOAVATARNAME,18,176,264,30,ES_MULTILINE | ES_READONLY,WS_EX_CLIENTEDGE + CTEXT "CAUTION: These pictures are NOT your own avatars.\nTo set your own Avatar goto Main Menu | View/Change My Details | Avatars",IDC_STATIC,0,53,294,18 +END + +IDD_OPTIONS_AVATARS DIALOGEX 0, 0, 302, 189 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Try to draw avatar background transparent (for images without transparency)",IDC_MAKE_TRANSPARENT_BKG, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,17,278,12 + LTEXT "Num of points to define bkg:",IDC_BKG_NUM_POINTS_L,33,31,135,11 + EDITTEXT IDC_BKG_NUM_POINTS,173,30,36,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_BKG_NUM_POINTS_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,209,30,11,12 + LTEXT "Color difference allowed:",IDC_BKG_COLOR_DIFFERENCE_L,33,44,135,11 + EDITTEXT IDC_BKG_COLOR_DIFFERENCE,173,43,36,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_BKG_COLOR_DIFFERENCE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,209,42,11,12 + CONTROL "Make transparency proportional to color diff",IDC_MAKE_TRANSP_PROPORTIONAL, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,57,247,10 + CONTROL "Draw avatars grayscale",IDC_MAKE_GRAYSCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,72,269,13 + CONTROL "Show warning messages",IDC_SHOWWARNINGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,87,269,13 +END + +IDD_OPTIONS_OWN DIALOGEX 0, 0, 302, 75 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "When setting avatars, always make them square",IDC_SET_MAKE_SQUARE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,17,281,11 + CONTROL "Try to draw own avatar background transparent (for images without transparency)",IDC_MAKE_MY_AVATARS_TRANSP, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,30,289,16 + LTEXT "This uses the same additional options as in ""Contact Avatars"" tab",IDC_STATIC,17,50,257,13 +END + +IDD_OPENSUBCLASS DIALOGEX 0, 0, 246, 18 +STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Protect the picture and prevent automatic avatars from overwriting it",IDC_PROTECTAVATAR, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,237,8 +END + +IDD_SET_OWN_SUBCLASS DIALOG 0, 0, 323, 31 +STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Make the avatar square",IDC_MAKE_SQUARE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,0,237,8 + CONTROL "Resize the avatar to fit max allowed protocol size",IDC_GROW, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,12,237,8 +END + +IDD_AVATAROPTIONS DIALOGEX 0, 0, 213, 212 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Contact picture",IDC_STATIC,5,5,202,96 + CONTROL "",IDC_PROTOPIC,"Button",BS_OWNERDRAW,12,16,56,50 + PUSHBUTTON "Change",IDC_CHANGE,138,15,61,14 + PUSHBUTTON "Delete",IDC_DELETE,138,32,61,14 + PUSHBUTTON "Reset",IDC_RESET,138,49,61,14 + EDITTEXT IDC_AVATARNAME,12,68,187,29,ES_MULTILINE | ES_READONLY,WS_EX_CLIENTEDGE + GROUPBOX "Picture options",IDC_STATIC,5,102,202,92 + CONTROL "Protect the picture",IDC_PROTECTAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,112,186,8 + CONTROL "Set as hidden",IDC_HIDEAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,122,186,11 + CONTROL "Try to make picture background transparent",IDC_MAKETRANSPBKG, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,133,186,11 + LTEXT "Num of points to define bkg:",IDC_BKG_NUM_POINTS_L,23,148,118,11 + EDITTEXT IDC_BKG_NUM_POINTS,145,146,42,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_BKG_NUM_POINTS_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,187,147,11,12 + LTEXT "Color difference allowed:",IDC_BKG_COLOR_DIFFERENCE_L,23,162,118,11 + EDITTEXT IDC_BKG_COLOR_DIFFERENCE,145,160,42,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_BKG_COLOR_DIFFERENCE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,188,160,11,12 + DEFPUSHBUTTON "Use defaults",ID_USE_DEFAULTS,11,177,63,12 + DEFPUSHBUTTON "OK",IDOK,93,197,50,14 + DEFPUSHBUTTON "Cancel",IDCANCEL,151,197,50,14 +END + +IDD_USER_AVATAR DIALOGEX 0, 0, 222, 152 +STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_PROTOPIC,"MAvatarControlClass",0x0,3,4,96,89 + PUSHBUTTON "Change",IDC_CHANGE,3,102,96,14 + PUSHBUTTON "Delete",IDC_DELETE,3,118,96,14 + PUSHBUTTON "Reset",IDC_RESET,3,134,96,14 + GROUPBOX " Options ",IDC_STATIC,107,3,111,50 + CONTROL "Protect the picture",IDC_PROTECTAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,18,93,8 + CONTROL "Set as hidden",IDC_HIDEAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,34,93,11 + GROUPBOX " Background ",IDC_STATIC,107,59,111,89 + CONTROL "Transparent",IDC_MAKETRANSPBKG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,74,93,11 + LTEXT "Points:",IDC_BKG_NUM_POINTS_L,129,91,38,11 + EDITTEXT IDC_BKG_NUM_POINTS,169,89,42,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_BKG_NUM_POINTS_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,199,80,11,12 + LTEXT "Color diff:",IDC_BKG_COLOR_DIFFERENCE_L,129,108,38,11 + EDITTEXT IDC_BKG_COLOR_DIFFERENCE,169,106,42,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_BKG_COLOR_DIFFERENCE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,199,117,11,12 + PUSHBUTTON "Use defaults",ID_USE_DEFAULTS,118,130,63,12 +END + +IDD_PROTO_AVATARS DIALOGEX 0, 0, 222, 152 +STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_PROTOCOLS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,3,4,101,126 + CONTROL "",IDC_PROTOPIC,"MAvatarControlClass",0x0,114,4,96,89 + PUSHBUTTON "Set",IDC_CHANGE,114,100,96,14 + PUSHBUTTON "Delete",IDC_DELETE,114,116,96,14 + CONTROL "Use per protocol avatars",IDC_PER_PROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,137,215,11 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPTIONS_PICTS, DIALOG + BEGIN + RIGHTMARGIN, 294 + END + + IDD_OPENSUBCLASS, DIALOG + BEGIN + RIGHTMARGIN, 208 + TOPMARGIN, 7 + END + + IDD_AVATAROPTIONS, DIALOG + BEGIN + RIGHTMARGIN, 207 + BOTTOMMARGIN, 211 + END + + IDD_USER_AVATAR, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 218 + TOPMARGIN, 4 + BOTTOMMARGIN, 148 + END + + IDD_PROTO_AVATARS, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 218 + TOPMARGIN, 4 + BOTTOMMARGIN, 148 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_AVATAR ICON "res/avatar.ico" +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/AVS/avs_10.vcxproj b/plugins/AVS/avs_10.vcxproj new file mode 100644 index 0000000000..c512086a8d --- /dev/null +++ b/plugins/AVS/avs_10.vcxproj @@ -0,0 +1,290 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + AVS + {7711F563-6473-4ABD-B5E3-477CE8384AD6} + avs + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + false + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + true + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + true + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug_Unicode/avatars.tlb + + + + + Disabled + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + commonheaders.h + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + + + _DEBUG;UNICODE;%(PreprocessorDefinitions) + ../../include/msapi + + + comctl32.lib;msimg32.lib;%(AdditionalDependencies) + true + false + $(IntDir)$(TargetName).lib + Windows + 0x5130000 + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug_Unicode/avatars.tlb + + + + + Disabled + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + false + Use + commonheaders.h + Level3 + ProgramDatabase + 4996;%(DisableSpecificWarnings) + + + _DEBUG;UNICODE;%(PreprocessorDefinitions) + 0x0809 + ../../include/msapi + + + comctl32.lib;msimg32.lib;%(AdditionalDependencies) + true + type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies) + true + $(TargetDir)$(TargetName).pdb + false + $(IntDir)$(TargetName).lib + MachineX64 + 0x5130000 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release_Unicode/avatars.tlb + + + + + Full + OnlyExplicitInline + Size + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) + true + false + MultiThreadedDLL + false + true + Fast + Use + commonheaders.h + Level3 + 4996;%(DisableSpecificWarnings) + + + NDEBUG;UNICODE;%(PreprocessorDefinitions) + ../../include/msapi + + + /IGNORE:4089 /filealign:512 %(AdditionalOptions) + comctl32.lib;msimg32.lib;%(AdditionalDependencies) + true + true + true + 0x5130000 + false + $(IntDir)$(TargetName).lib + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release_Unicode/avatars.tlb + + + + + Full + OnlyExplicitInline + Size + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) + true + false + MultiThreadedDLL + false + true + Fast + Use + commonheaders.h + Level3 + 4996;%(DisableSpecificWarnings) + + + NDEBUG;UNICODE;%(PreprocessorDefinitions) + ../../include/msapi + + + /IGNORE:4089 /filealign:512 %(AdditionalOptions) + comctl32.lib;msimg32.lib;%(AdditionalDependencies) + type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies) + true + true + true + 0x5130000 + false + $(IntDir)$(TargetName).lib + Windows + + + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/AVS/avs_10.vcxproj.filters b/plugins/AVS/avs_10.vcxproj.filters new file mode 100644 index 0000000000..6f6d39f743 --- /dev/null +++ b/plugins/AVS/avs_10.vcxproj.filters @@ -0,0 +1,70 @@ + + + + + {8803e79e-1c62-4fcc-8daf-35634ce5e990} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {533b0c62-6839-47b0-bf0d-03e20a1a4e06} + h;hpp;hxx;hm;inl + + + {214ac298-955e-4931-a01c-3516a7206928} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Source Files + + + \ No newline at end of file diff --git a/plugins/AVS/commonheaders.h b/plugins/AVS/commonheaders.h new file mode 100644 index 0000000000..70b0c88fae --- /dev/null +++ b/plugins/AVS/commonheaders.h @@ -0,0 +1,119 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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 MIRANDA_VER 0x0A00 +#define _WIN32_WINNT 0x0501 + +#include "m_stdhdr.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "m_folders.h" + +#include +#include +#include +#include "m_metacontacts.h" +#include "m_avatarhistory.h" + +#include "resource.h" +#include "m_updater.h" +#include "m_flash.h" +#include "image_utils.h" +#include "mir_thread.h" +#include "poll.h" +#include "m_acc.h" +#include "acc.h" + + +// shared vars +//extern HINSTANCE g_hInst; + +/* most free()'s are invalid when the code is executed from a dll, so this changes + all the bad free()'s to good ones, however it's still incorrect code. The reasons for not + changing them include: + + * DBFreeVariant has a CallService() lookup + * free() is executed in some large loops to do with clist creation of group data + * easy search and replace + +*/ + +// The same fields as avatarCacheEntry + proto name +struct protoPicCacheEntry : public avatarCacheEntry +{ + __inline void* operator new( size_t size ) { return mir_alloc( size ); } + __inline void operator delete( void* p ) { mir_free( p ); } + + protoPicCacheEntry() { memset(this, 0, sizeof(*this)); }; + ~protoPicCacheEntry(); + + void clear(); + + char* szProtoname; + TCHAR* tszAccName; +}; + +extern OBJLIST g_ProtoPictures, g_MyAvatars; + + +int SetAvatarAttribute(HANDLE hContact, DWORD attrib, int mode); + +#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) ) + + +#define GAIR_FAILED 1000 + +#define AVS_IGNORENOTIFY 0x1000 + +#define AVS_DEFAULT "Global avatar" diff --git a/plugins/AVS/image_utils.cpp b/plugins/AVS/image_utils.cpp new file mode 100644 index 0000000000..f6b6c7a98b --- /dev/null +++ b/plugins/AVS/image_utils.cpp @@ -0,0 +1,757 @@ +#include "commonheaders.h" +#include "image_utils.h" + +#include +#include + +/* +Theese are the ones needed +#include +#include +#include +#include +#include +#include +*/ + +extern int _DebugTrace(const char *fmt, ...); +extern int _DebugTrace(HANDLE hContact, const char *fmt, ...); + + +#define GET_PIXEL(__P__, __X__, __Y__) ( __P__ + width * 4 * (__Y__) + 4 * (__X__) ) + + +extern FI_INTERFACE *fei; + +// Make a bitmap all transparent, but only if it is a 32bpp +void MakeBmpTransparent(HBITMAP hBitmap) +{ + BITMAP bmp; + DWORD dwLen; + BYTE *p; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + if (bmp.bmBitsPixel != 32) + return; + + dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); + p = (BYTE *)malloc(dwLen); + if (p == NULL) + return; + + memset(p, 0, dwLen); + SetBitmapBits(hBitmap, dwLen, p); + + free(p); +} + +// Resize ///////////////////////////////////////////////////////////////////////////////////////// + + +// Returns a copy of the bitmap with the size especified +// wParam = ResizeBitmap * +// lParam = NULL +INT_PTR BmpFilterResizeBitmap(WPARAM wParam,LPARAM lParam) +{ + // Call freeiamge service (is here only for backward compatibility) + return CallService(MS_IMG_RESIZE, wParam, lParam); +} + +HBITMAP CopyBitmapTo32(HBITMAP hBitmap) +{ + BITMAPINFO RGB32BitsBITMAPINFO; + BYTE * ptPixels; + HBITMAP hDirectBitmap; + + BITMAP bmp; + DWORD dwLen; + BYTE *p; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + dwLen = bmp.bmWidth * bmp.bmHeight * 4; + p = (BYTE *)malloc(dwLen); + if (p == NULL) + return NULL; + + // Create bitmap + ZeroMemory(&RGB32BitsBITMAPINFO, sizeof(BITMAPINFO)); + RGB32BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + RGB32BitsBITMAPINFO.bmiHeader.biWidth = bmp.bmWidth; + RGB32BitsBITMAPINFO.bmiHeader.biHeight = bmp.bmHeight; + RGB32BitsBITMAPINFO.bmiHeader.biPlanes = 1; + RGB32BitsBITMAPINFO.bmiHeader.biBitCount = 32; + + hDirectBitmap = CreateDIBSection(NULL, + (BITMAPINFO *)&RGB32BitsBITMAPINFO, + DIB_RGB_COLORS, + (void **)&ptPixels, + NULL, 0); + + // Copy data + if (bmp.bmBitsPixel != 32) + { + HDC hdcOrig, hdcDest; + HBITMAP oldOrig, oldDest; + + hdcOrig = CreateCompatibleDC(NULL); + oldOrig = (HBITMAP) SelectObject(hdcOrig, hBitmap); + + hdcDest = CreateCompatibleDC(NULL); + oldDest = (HBITMAP) SelectObject(hdcDest, hDirectBitmap); + + BitBlt(hdcDest, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOrig, 0, 0, SRCCOPY); + + SelectObject(hdcDest, oldDest); + DeleteObject(hdcDest); + SelectObject(hdcOrig, oldOrig); + DeleteObject(hdcOrig); + + // Set alpha + fei->FI_CorrectBitmap32Alpha(hDirectBitmap, FALSE); + } + else + { + GetBitmapBits(hBitmap, dwLen, p); + SetBitmapBits(hDirectBitmap, dwLen, p); + } + + free(p); + + return hDirectBitmap; +} + +HBITMAP CreateBitmap32(int cx, int cy) +{ + BITMAPINFO RGB32BitsBITMAPINFO; + UINT * ptPixels; + HBITMAP DirectBitmap; + + ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); + RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth; + RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight; + RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; + RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; + + DirectBitmap = CreateDIBSection(NULL, + (BITMAPINFO *)&RGB32BitsBITMAPINFO, + DIB_RGB_COLORS, + (void **)&ptPixels, + NULL, 0); + return DirectBitmap; +} + +// Set the color of points that are transparent +void SetTranspBkgColor(HBITMAP hBitmap, COLORREF color) +{ + BITMAP bmp; + DWORD dwLen; + BYTE *p; + int x, y; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + if (bmp.bmBitsPixel != 32) + return; + + dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); + p = (BYTE *)malloc(dwLen); + if (p == NULL) + return; + memset(p, 0, dwLen); + + GetBitmapBits(hBitmap, dwLen, p); + + bool changed = false; + for (y = 0; y < bmp.bmHeight; ++y) { + BYTE *px = p + bmp.bmWidth * 4 * y; + + for (x = 0; x < bmp.bmWidth; ++x) + { + if (px[3] == 0) + { + px[0] = GetBValue(color); + px[1] = GetGValue(color); + px[2] = GetRValue(color); + changed = true; + } + px += 4; + } + } + + if (changed) + SetBitmapBits(hBitmap, dwLen, p); + + free(p); +} + + +#define HIMETRIC_INCH 2540 // HIMETRIC units per inch + +void SetHIMETRICtoDP(HDC hdc, SIZE* sz) +{ + POINT pt; + int nMapMode = GetMapMode(hdc); + if ( nMapMode < MM_ISOTROPIC && nMapMode != MM_TEXT ) + { + // when using a constrained map mode, map against physical inch + SetMapMode(hdc,MM_HIMETRIC); + pt.x = sz->cx; + pt.y = sz->cy; + LPtoDP(hdc,&pt,1); + sz->cx = pt.x; + sz->cy = pt.y; + SetMapMode(hdc, nMapMode); + } + else + { + // map against logical inch for non-constrained mapping modes + int cxPerInch, cyPerInch; + cxPerInch = GetDeviceCaps(hdc,LOGPIXELSX); + cyPerInch = GetDeviceCaps(hdc,LOGPIXELSY); + sz->cx = MulDiv(sz->cx, cxPerInch, HIMETRIC_INCH); + sz->cy = MulDiv(sz->cy, cyPerInch, HIMETRIC_INCH); + } + + pt.x = sz->cx; + pt.y = sz->cy; + DPtoLP(hdc,&pt,1); + sz->cx = pt.x; + sz->cy = pt.y; +} + +INT_PTR BmpFilterLoadBitmap32(WPARAM wParam,LPARAM lParam) +{ + FIBITMAP *dib32 = NULL; + + if(fei == NULL) + return 0; + + FIBITMAP *dib = (FIBITMAP *)CallService(MS_IMG_LOAD, lParam, IMGL_RETURNDIB|IMGL_TCHAR); + + if(dib == NULL) + return 0; + + if(fei->FI_GetBPP(dib) != 32) { + dib32 = fei->FI_ConvertTo32Bits(dib); + fei->FI_Unload(dib); + } + else + dib32 = dib; + + if(dib32) { + if(fei->FI_IsTransparent(dib32)) { + if(wParam) { + DWORD *dwTrans = (DWORD *)wParam; + *dwTrans = 1; + } + } + if(fei->FI_GetWidth(dib32) > 128 || fei->FI_GetHeight(dib32) > 128) { + FIBITMAP *dib_new = fei->FI_MakeThumbnail(dib32, 128, FALSE); + fei->FI_Unload(dib32); + if(dib_new == NULL) + return 0; + dib32 = dib_new; + } + + HBITMAP bitmap = fei->FI_CreateHBITMAPFromDIB(dib32); + + fei->FI_Unload(dib32); + fei->FI_CorrectBitmap32Alpha(bitmap, FALSE); + return (INT_PTR)bitmap; + } + return 0; +} + +static HWND hwndClui = 0; + +// +// Save /////////////////////////////////////////////////////////////////////////////////////////// +// PNG and BMP will be saved as 32bit images, jpg as 24bit with default quality (75) +// returns 1 on success, 0 on failure + +int BmpFilterSaveBitmap(HBITMAP hBmp, char *szFile, int flags) +{ + IMGSRVC_INFO i = {0}; + i.cbSize = sizeof(IMGSRVC_INFO); + i.szName = szFile; + i.hbm = hBmp; + i.dwMask = IMGI_HBITMAP; + i.fif = FIF_UNKNOWN; + + return !CallService(MS_IMG_SAVE, (WPARAM) &i, MAKELONG(0, flags)); +} + + +int BmpFilterSaveBitmapW(HBITMAP hBmp, wchar_t *wszFile, int flags) +{ + IMGSRVC_INFO i = {0}; + i.cbSize = sizeof(IMGSRVC_INFO); + i.wszName = wszFile; + i.hbm = hBmp; + i.dwMask = IMGI_HBITMAP; + i.fif = FIF_UNKNOWN; + + return !CallService(MS_IMG_SAVE, (WPARAM) &i, MAKELONG(IMGL_WCHAR, flags)); +} + +// Save an HBITMAP to an image +// wParam = HBITMAP +// lParam = filename +INT_PTR BmpFilterSaveBitmap(WPARAM wParam,LPARAM lParam) +{ + if ( fei == NULL ) + return -1; + + const char *szFile = (const char*)lParam; + char szFilename[MAX_PATH]; + if ( !CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szFile, (LPARAM)szFilename)) + mir_snprintf(szFilename, SIZEOF(szFilename), "%s", szFile); + + int filenameLen = lstrlenA( szFilename ); + if ( filenameLen > 4 ) + return BmpFilterSaveBitmap(( HBITMAP )wParam, szFilename, 0); + + return -1; +} + +#if defined(_UNICODE) +INT_PTR BmpFilterSaveBitmapW(WPARAM wParam,LPARAM lParam) +{ + if ( fei == NULL ) + return -1; + + const wchar_t *wszFile = (const wchar_t *)lParam; + wchar_t wszFilename[MAX_PATH]; + if ( !CallService(MS_UTILS_PATHTOABSOLUTEW, (WPARAM)wszFile, (LPARAM)wszFilename)) + mir_sntprintf(wszFilename, SIZEOF(wszFilename), _T("%s"), wszFile); + + int filenameLen = lstrlenW( wszFilename ); + if ( filenameLen > 4 ) + return BmpFilterSaveBitmapW(( HBITMAP )wParam, wszFilename, 0 ); + + return -1; +} +#endif + +// Returns != 0 if can save that type of image, = 0 if cant +// wParam = 0 +// lParam = PA_FORMAT_* // image format +// kept for compatibilty - with freeimage we can save all common formats + +INT_PTR BmpFilterCanSaveBitmap(WPARAM wParam,LPARAM lParam) +{ + return 1; +} + + +// Other utilities //////////////////////////////////////////////////////////////////////////////// + + +static BOOL ColorsAreTheSame(int colorDiff, BYTE *px1, BYTE *px2) +{ + return abs(px1[0] - px2[0]) <= colorDiff + && abs(px1[1] - px2[1]) <= colorDiff + && abs(px1[2] - px2[2]) <= colorDiff; +} + + +void AddToStack(int *stack, int *topPos, int x, int y) +{ + int i; + + // Already is in stack? + for(i = 0 ; i < *topPos ; i += 2) + { + if (stack[i] == x && stack[i+1] == y) + return; + } + + stack[*topPos] = x; + (*topPos)++; + + stack[*topPos] = y; + (*topPos)++; +} + + +BOOL GetColorForPoint(int colorDiff, BYTE *p, int width, int height, + int x0, int y0, int x1, int y1, int x2, int y2, BOOL *foundBkg, BYTE colors[][3]) +{ + BYTE *px1, *px2, *px3; + + px1 = GET_PIXEL(p, x0,y0); + px2 = GET_PIXEL(p, x1,y1); + px3 = GET_PIXEL(p, x2,y2); + + // If any of the corners have transparency, forget about it + // Not using != 255 because some MSN bmps have 254 in some positions + if (px1[3] < 253 || px2[3] < 253 || px3[3] < 253) + return FALSE; + + // See if is the same color + if (ColorsAreTheSame(colorDiff, px1, px2) && ColorsAreTheSame(colorDiff, px3, px2)) + { + *foundBkg = TRUE; + memmove(colors, px1, 3); + } + else + { + *foundBkg = FALSE; + } + + return TRUE; +} + + +DWORD GetImgHash(HBITMAP hBitmap) +{ + BITMAP bmp; + DWORD dwLen; + WORD *p; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); + p = (WORD *)malloc(dwLen); + if (p == NULL) + return 0; + memset(p, 0, dwLen); + + GetBitmapBits(hBitmap, dwLen, p); + + DWORD ret = 0; + for (DWORD i = 0 ; i < dwLen/2 ; i++) + ret += p[i]; + + free(p); + + return ret; +} + +/* + * Changes the handle to a grayscale image + */ +HBITMAP MakeGrayscale(HANDLE hContact, HBITMAP hBitmap) +{ + if(hBitmap) { + FIBITMAP *dib = fei->FI_CreateDIBFromHBITMAP(hBitmap); + + if(dib) { + FIBITMAP *dib_new = fei->FI_ConvertToGreyscale(dib); + fei->FI_Unload(dib); + if(dib_new) { + DeleteObject(hBitmap); + HBITMAP hbm_new = fei->FI_CreateHBITMAPFromDIB(dib_new); + fei->FI_Unload(dib_new); + return hbm_new; + } + } + } + return hBitmap; +} + +/* + * See if finds a transparent background in image, and set its transparency + * Return TRUE if found a transparent background + */ +BOOL MakeTransparentBkg(HANDLE hContact, HBITMAP *hBitmap) +{ + BYTE *p = NULL; + DWORD dwLen; + int width, height, i, j; + BITMAP bmp; + BYTE colors[8][3]; + BOOL foundBkg[8]; + BYTE *px1; + int count, maxCount, selectedColor; + HBITMAP hBmpTmp; + int colorDiff; + + GetObject(*hBitmap, sizeof(bmp), &bmp); + width = bmp.bmWidth; + height = bmp.bmHeight; + colorDiff = DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgColorDiff", + DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10)); + + // Min 5x5 to easy things in loop + if (width <= 4 || height <= 4) + return FALSE; + + dwLen = width * height * 4; + p = (BYTE *)malloc(dwLen); + if (p == NULL) + { + return FALSE; + } + + if (bmp.bmBitsPixel == 32) + { + hBmpTmp = *hBitmap; + } + else + { + // Convert to 32 bpp + hBmpTmp = CopyBitmapTo32(*hBitmap); + } + + GetBitmapBits(hBmpTmp, dwLen, p); + + // **** Get corner colors + + // Top left + if (!GetColorForPoint(colorDiff, p, width, height, + 0, 0, 0, 1, 1, 0, &foundBkg[0], &colors[0])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Top center + if (!GetColorForPoint(colorDiff, p, width, height, + width/2, 0, width/2-1, 0, width/2+1, 0, &foundBkg[1], &colors[1])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Top Right + if (!GetColorForPoint(colorDiff, p, width, height, + width-1, 0, width-1, 1, width-2, 0, &foundBkg[2], &colors[2])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Center left + if (!GetColorForPoint(colorDiff, p, width, height, + 0, height/2, 0, height/2-1, 0, height/2+1, &foundBkg[3], &colors[3])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Center left + if (!GetColorForPoint(colorDiff, p, width, height, + width-1, height/2, width-1, height/2-1, width-1, height/2+1, &foundBkg[4], &colors[4])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Bottom left + if (!GetColorForPoint(colorDiff, p, width, height, + 0, height-1, 0, height-2, 1, height-1, &foundBkg[5], &colors[5])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Bottom center + if (!GetColorForPoint(colorDiff, p, width, height, + width/2, height-1, width/2-1, height-1, width/2+1, height-1, &foundBkg[6], &colors[6])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Bottom Right + if (!GetColorForPoint(colorDiff, p, width, height, + width-1, height-1, width-1, height-2, width-2, height-1, &foundBkg[7], &colors[7])) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // **** X corners have to have the same color + + count = 0; + for (i = 0 ; i < 8 ; i++) + { + if (foundBkg[i]) + count++; + } + + if (count < DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", + DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5))) + { + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Ok, X corners at least have a color, lets compare then + maxCount = 0; + for (i = 0 ; i < 8 ; i++) + { + if (foundBkg[i]) + { + count = 0; + + for (j = 0 ; j < 8 ; j++) + { + if (foundBkg[j] && ColorsAreTheSame(colorDiff, (BYTE *) &colors[i], (BYTE *) &colors[j])) + count++; + } + + if (count > maxCount) + { + maxCount = count; + selectedColor = i; + } + } + } + + if (maxCount < DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", + DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5))) + { + // Not enought corners with the same color + if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); + free(p); + return FALSE; + } + + // Get bkg color as mean of colors + { + int bkgColor[3]; + + bkgColor[0] = 0; + bkgColor[1] = 0; + bkgColor[2] = 0; + for (i = 0 ; i < 8 ; i++) + { + if (foundBkg[i] && ColorsAreTheSame(colorDiff, (BYTE *) &colors[i], (BYTE *) &colors[selectedColor])) + { + bkgColor[0] += colors[i][0]; + bkgColor[1] += colors[i][1]; + bkgColor[2] += colors[i][2]; + } + } + bkgColor[0] /= maxCount; + bkgColor[1] /= maxCount; + bkgColor[2] /= maxCount; + + colors[selectedColor][0] = bkgColor[0]; + colors[selectedColor][1] = bkgColor[1]; + colors[selectedColor][2] = bkgColor[2]; + } + + // **** Set alpha for the background color, from the borders + + if (hBmpTmp != *hBitmap) + { + DeleteObject(*hBitmap); + + *hBitmap = hBmpTmp; + + GetObject(*hBitmap, sizeof(bmp), &bmp); + GetBitmapBits(*hBitmap, dwLen, p); + } + + { + // Set alpha from borders + int x, y; + int topPos = 0; + int curPos = 0; + int *stack = (int *)malloc(width * height * 2 * sizeof(int)); + bool transpProportional = (DBGetContactSettingByte(NULL, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", 0) != 0); + + if (stack == NULL) + { + free(p); + return FALSE; + } + + // Put four corners + AddToStack(stack, &topPos, 0, 0); + AddToStack(stack, &topPos, width/2, 0); + AddToStack(stack, &topPos, width-1, 0); + AddToStack(stack, &topPos, 0, height/2); + AddToStack(stack, &topPos, width-1, height/2); + AddToStack(stack, &topPos, 0, height-1); + AddToStack(stack, &topPos, width/2, height-1); + AddToStack(stack, &topPos, width-1, height-1); + + while(curPos < topPos) + { + // Get pos + x = stack[curPos]; curPos++; + y = stack[curPos]; curPos++; + + // Get pixel + px1 = GET_PIXEL(p, x, y); + + // It won't change the transparency if one exists + // (This avoid an endless loop too) + // Not using == 255 because some MSN bmps have 254 in some positions + if (px1[3] >= 253) + { + if (ColorsAreTheSame(colorDiff, px1, (BYTE *) &colors[selectedColor])) + { + if (transpProportional) + { + px1[3] = min(252, + (abs(px1[0] - colors[selectedColor][0]) + + abs(px1[1] - colors[selectedColor][1]) + + abs(px1[2] - colors[selectedColor][2])) / 3); + } + else + { + px1[3] = 0; + } + + // Add 4 neighbours + + if (x + 1 < width) + AddToStack(stack, &topPos, x + 1, y); + + if (x - 1 >= 0) + AddToStack(stack, &topPos, x - 1, y); + + if (y + 1 < height) + AddToStack(stack, &topPos, x, y + 1); + + if (y - 1 >= 0) + AddToStack(stack, &topPos, x, y - 1); + } + } + } + + free(stack); + } + + dwLen = SetBitmapBits(*hBitmap, dwLen, p); + free(p); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Other utils + +int SaveAvatar( const char* protocol, const TCHAR* tszFileName ) +{ + int result = CallProtoService(protocol, PS_SETMYAVATART, 0, ( LPARAM )tszFileName); + #if defined( _UNICODE ) + if ( result == CALLSERVICE_NOTFOUND ) { + if ( tszFileName != NULL ) { + char szFileName[ MAX_PATH ]; + WideCharToMultiByte( CP_ACP, 0, tszFileName, -1, szFileName, SIZEOF(szFileName), 0, 0 ); + result = CallProtoService(protocol, PS_SETMYAVATAR, 0, ( LPARAM )szFileName); + } + else result = CallProtoService(protocol, PS_SETMYAVATAR, 0, 0); + } + #endif + + return result; +} diff --git a/plugins/AVS/image_utils.h b/plugins/AVS/image_utils.h new file mode 100644 index 0000000000..2dd75d8211 --- /dev/null +++ b/plugins/AVS/image_utils.h @@ -0,0 +1,58 @@ +#ifndef __IMAGE_UTILS_H__ +# define __IMAGE_UTILS_H__ + +#define _WIN32_WINNT 0x0501 +#include + +#include + + +// Load an image +// wParam = NULL +// lParam = filename +INT_PTR BmpFilterLoadBitmap32(WPARAM wParam,LPARAM lParam); + +// Save an HBITMAP to an image +// wParam = HBITMAP +// lParam = full path of filename +INT_PTR BmpFilterSaveBitmap(WPARAM wParam,LPARAM lParam); +#if defined(_UNICODE) + INT_PTR BmpFilterSaveBitmapW(WPARAM wParam,LPARAM lParam); + #define BmpFilterSaveBitmapT BmpFilterSaveBitmapW +#else + #define BmpFilterSaveBitmapT BmpFilterSaveBitmap +#endif + +// Returns != 0 if can save that type of image, = 0 if cant +// wParam = 0 +// lParam = PA_FORMAT_* // image format +INT_PTR BmpFilterCanSaveBitmap(WPARAM wParam,LPARAM lParam); + +// Returns a copy of the bitmap with the size especified or the original bitmap if nothing has to be changed +// wParam = ResizeBitmap * +// lParam = NULL +INT_PTR BmpFilterResizeBitmap(WPARAM wParam,LPARAM lParam); + + +int BmpFilterSaveBitmap(HBITMAP hBmp, char *szFile, int flags); +#if defined(_UNICODE) + int BmpFilterSaveBitmapW(HBITMAP hBmp, wchar_t *wszFile, int flags); + #define BmpFilterSaveBitmapT BmpFilterSaveBitmapW +#else + #define BmpFilterSaveBitmapT BmpFilterSaveBitmap +#endif + +HBITMAP CopyBitmapTo32(HBITMAP hBitmap); + +BOOL PreMultiply(HBITMAP hBitmap); +BOOL MakeTransparentBkg(HANDLE hContact, HBITMAP *hBitmap); +HBITMAP MakeGrayscale(HANDLE hContact, HBITMAP hBitmap); +DWORD GetImgHash(HBITMAP hBitmap); + +int AVS_pathIsAbsolute(const TCHAR *path); +size_t AVS_pathToRelative(const TCHAR *sPrc, TCHAR *pOut); +size_t AVS_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut); + +int SaveAvatar( const char* protocol, const TCHAR* tszFileName ); + +#endif // __IMAGE_UTILS_H__ diff --git a/plugins/AVS/license.txt b/plugins/AVS/license.txt new file mode 100644 index 0000000000..7f1161073d --- /dev/null +++ b/plugins/AVS/license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/plugins/AVS/main.cpp b/plugins/AVS/main.cpp new file mode 100644 index 0000000000..bb4ebc236f --- /dev/null +++ b/plugins/AVS/main.cpp @@ -0,0 +1,2684 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" +#include "version.h" + +HINSTANCE g_hInst = 0; +PLUGINLINK *pluginLink; +MM_INTERFACE mmi; +LIST_INTERFACE li; +int hLangpack; + +static TCHAR g_szDataPath[MAX_PATH]; // user datae path (read at startup only) +static BOOL g_MetaAvail = FALSE; +BOOL g_AvatarHistoryAvail = FALSE; +static long hwndSetMyAvatar = 0; + +static HANDLE hMyAvatarsFolder = 0; +static HANDLE hGlobalAvatarFolder = 0; +static HANDLE hLoaderEvent = 0; +static HANDLE hLoaderThread = 0; + +static HANDLE hOptInit = 0; +static HANDLE hModulesLoaded = 0; +static HANDLE hPresutdown = 0; +static HANDLE hOkToExit = 0; +static HANDLE hAccChanged = 0; + +HANDLE hProtoAckHook = 0, hContactSettingChanged = 0, hEventChanged = 0, hEventContactAvatarChanged = 0, + hMyAvatarChanged = 0, hEventDeleted = 0, hUserInfoInitHook = 0; +HICON g_hIcon = 0; + +BOOL (WINAPI *AvsAlphaBlend)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION) = NULL; + +static struct CacheNode *g_Cache = 0; +static CRITICAL_SECTION cachecs, alloccs; + +static int ComparePicture( const protoPicCacheEntry* p1, const protoPicCacheEntry* p2 ) +{ + if ((lstrcmpA(p1->szProtoname, "Global avatar") == 0) || strstr(p1->szProtoname, "Global avatar")) + return -1; + if ((lstrcmpA(p2->szProtoname, "Global avatar") == 0) || strstr(p1->szProtoname, "Global avatar")) + return 1; + return lstrcmpA( p1->szProtoname, p2->szProtoname ); +} + +OBJLIST + g_ProtoPictures( 10, ComparePicture ), + g_MyAvatars( 10, ComparePicture ); + +char* g_szMetaName = NULL; + +#ifndef SHVIEW_THUMBNAIL +#define SHVIEW_THUMBNAIL 0x702D +#endif + +// Stores the id of the dialog + +int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist = FALSE, int pa_format = 0); +static int ShutdownProc(WPARAM wParam, LPARAM lParam); +static int OkToExitProc(WPARAM wParam, LPARAM lParam); +static int OnDetailsInit(WPARAM wParam, LPARAM lParam); +static int GetFileHash(TCHAR* filename); +static DWORD GetFileSize(TCHAR *szFilename); + +void ProcessAvatarInfo(HANDLE hContact, int type, PROTO_AVATAR_INFORMATIONT *pai, const char *szProto); +int FetchAvatarFor(HANDLE hContact, char *szProto = NULL); +static INT_PTR ReportMyAvatarChanged(WPARAM wParam, LPARAM lParam); + +BOOL Proto_IsAvatarsEnabled(const char *proto); +BOOL Proto_IsAvatarFormatSupported(const char *proto, int format); +void Proto_GetAvatarMaxSize(const char *proto, int *width, int *height); +int Proto_AvatarImageProportion(const char *proto); +BOOL Proto_NeedDelaysForAvatars(const char *proto); +int Proto_GetAvatarMaxFileSize(const char *proto); +int Proto_GetDelayAfterFail(const char *proto); + +FI_INTERFACE *fei = 0; + +PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), +#if defined(_UNICODE) + "Avatar service (Unicode)", +#else + "Avatar service", +#endif + __VERSION_DWORD, + "Load and manage contact pictures for other plugins.", + "Nightwish, Pescuma", + "", + "Copyright 2000-2012 Miranda-IM project", + "http://www.miranda-im.org", + UNICODE_AWARE, + 0, +#if defined(_UNICODE) +// {E00F1643-263C-4599-B84B-053E5C511D29} + { 0xe00f1643, 0x263c, 0x4599, { 0xb8, 0x4b, 0x5, 0x3e, 0x5c, 0x51, 0x1d, 0x29 } } +#else +// {C9E01EB0-A119-42d2-B340-E8678F5FEAD8} + { 0xc9e01eb0, 0xa119, 0x42d2, { 0xb3, 0x40, 0xe8, 0x67, 0x8f, 0x5f, 0xea, 0xd8 } } +#endif +}; + +extern INT_PTR CALLBACK DlgProcOptionsAvatars(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcOptionsProtos(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcOptionsOwn(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcAvatarOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcAvatarUserInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +extern INT_PTR CALLBACK DlgProcAvatarProtoInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + + +static int SetProtoMyAvatar(char *protocol, HBITMAP hBmp, TCHAR *originalFilename, int format, BOOL square, BOOL grow); + +// See if a protocol service exists +int ProtoServiceExists(const char *szModule,const char *szService) +{ + char str[MAXMODULELABELLENGTH * 2]; + strcpy(str,szModule); + strcat(str,szService); + return ServiceExists(str); +} + + +/* + * output a notification message. + * may accept a hContact to include the contacts nickname in the notification message... + * the actual message is using printf() rules for formatting and passing the arguments... + * + * can display the message either as systray notification (baloon popup) or using the + * popup plugin. + */ + +#ifdef _DEBUG + +int _DebugTrace(const char *fmt, ...) +{ + char debug[2048]; + int ibsize = 2047; + va_list va; + va_start(va, fmt); + + mir_snprintf(debug, SIZEOF(debug) - 10, " ***** AVS [%08d] [ID:%04x]: ", GetTickCount(), GetCurrentThreadId()); + OutputDebugStringA(debug); + _vsnprintf(debug, ibsize, fmt, va); + OutputDebugStringA(debug); + OutputDebugStringA(" ***** \n"); + + return 0; +} + +int _DebugTrace(HANDLE hContact, const char *fmt, ...) +{ + char text[1024]; + size_t len; + va_list va; + + char *name = NULL; + char *proto = NULL; + if (hContact != NULL) + { + name = (char*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0); + proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + } + + mir_snprintf(text, SIZEOF(text) - 10, " ***** AVS [%08d] [ID:%04x]: [%08d - %s - %s] ", + GetTickCount(), GetCurrentThreadId(), hContact, proto == NULL ? "" : proto, name == NULL ? "" : name); + len = strlen(text); + + va_start(va, fmt); + mir_vsnprintf(&text[len], SIZEOF(text) - len, fmt, va); + va_end(va); + + OutputDebugStringA(text); + OutputDebugStringA(" ***** \n"); + + return 0; +} + +#endif + +/* + * path utilities (make avatar paths relative to *PROFILE* directory, not miranda directory. + * taken and modified from core services + */ + +int AVS_pathIsAbsolute(const TCHAR *path) +{ + if (!path || !(lstrlen(path) > 2)) + return 0; + if ((path[1]==':'&&path[2]=='\\')||(path[0]=='\\'&&path[1]=='\\')) return 1; + return 0; +} + +size_t AVS_pathToRelative(const TCHAR *pSrc, TCHAR *pOut) +{ + if (!pSrc || !*pSrc || _tcslen(pSrc) > MAX_PATH) return 0; + if (!AVS_pathIsAbsolute( pSrc )) + lstrcpyn(pOut, pSrc, MAX_PATH); + else { + TCHAR szTmp[MAX_PATH]; + mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc); + _tcslwr(szTmp); + if (_tcsstr(szTmp, g_szDataPath)) + lstrcpyn(pOut, pSrc + _tcslen(g_szDataPath) + 1, MAX_PATH); + else + lstrcpyn(pOut, pSrc, MAX_PATH); + } + return _tcslen(pOut); +} + +size_t AVS_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut) +{ + if (!pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH) + return 0; + + if (AVS_pathIsAbsolute(pSrc) || !_istalnum(pSrc[0])) + lstrcpyn(pOut, pSrc, MAX_PATH); + else + mir_sntprintf(pOut, MAX_PATH, _T("%s\\%s"), g_szDataPath, pSrc, MAX_PATH); + return lstrlen(pOut); +} + +static void NotifyMetaAware(HANDLE hContact, struct CacheNode *node = NULL, AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)-1) +{ + if (ace == (AVATARCACHEENTRY *)-1) + ace = &node->ace; + + NotifyEventHooks(hEventChanged, (WPARAM)hContact, (LPARAM)ace); + + if (g_MetaAvail && (node->dwFlags & MC_ISSUBCONTACT) && DBGetContactSettingByte(NULL, g_szMetaName, "Enabled", 0)) { + HANDLE hMasterContact = (HANDLE)DBGetContactSettingDword(hContact, g_szMetaName, "Handle", 0); + + if (hMasterContact && (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hMasterContact, 0) == hContact && + !DBGetContactSettingByte(hMasterContact, "ContactPhoto", "Locked", 0)) + NotifyEventHooks(hEventChanged, (WPARAM)hMasterContact, (LPARAM)ace); + } + if (node->dwFlags & AVH_MUSTNOTIFY) { + // Fire the event for avatar history + node->dwFlags &= ~AVH_MUSTNOTIFY; + if (node->ace.szFilename[0] != '\0') { + CONTACTAVATARCHANGEDNOTIFICATION cacn = {0}; + cacn.cbSize = sizeof(CONTACTAVATARCHANGEDNOTIFICATION); + cacn.hContact = hContact; + cacn.format = node->pa_format; + _tcsncpy(cacn.filename, node->ace.szFilename, MAX_PATH); + cacn.filename[MAX_PATH - 1] = 0; + + // Get hash + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto != NULL) { + DBVARIANT dbv = {0}; + if (!DBGetContactSetting(hContact, szProto, "AvatarHash", &dbv)) { + if (dbv.type == DBVT_TCHAR) { + _tcsncpy(cacn.hash, dbv.ptszVal, SIZEOF(cacn.hash)); + } else if (dbv.type == DBVT_BLOB) { + // Lets use base64 encode + char *tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + int i; + for(i = 0; i < dbv.cpbVal / 3 && i*4+3 < sizeof(cacn.hash)-1; i++) { + BYTE a = dbv.pbVal[i*3]; + BYTE b = i*3 + 1 < dbv.cpbVal ? dbv.pbVal[i*3 + 1] : 0; + BYTE c = i*3 + 2 < dbv.cpbVal ? dbv.pbVal[i*3 + 2] : 0; + + cacn.hash[i*4] = tab[(a & 0xFC) >> 2]; + cacn.hash[i*4+1] = tab[((a & 0x3) << 4) + ((b & 0xF0) >> 4)]; + cacn.hash[i*4+2] = tab[((b & 0xF) << 2) + ((c & 0xC0) >> 6)]; + cacn.hash[i*4+3] = tab[c & 0x3F]; + } + if (dbv.cpbVal % 3 != 0 && i*4+3 < sizeof(cacn.hash)-1) { + BYTE a = dbv.pbVal[i*3]; + BYTE b = i*3 + 1 < dbv.cpbVal ? dbv.pbVal[i*3 + 1] : 0; + + cacn.hash[i*4] = tab[(a & 0xFC) >> 2]; + cacn.hash[i*4+1] = tab[((a & 0x3) << 4) + ((b & 0xF0) >> 4)]; + if (i + 1 < dbv.cpbVal) + cacn.hash[i*4+2] = tab[((b & 0xF) << 4)]; + else + cacn.hash[i*4+2] = '='; + cacn.hash[i*4+3] = '='; + } + } + DBFreeVariant(&dbv); + } + } + + // Default value + if (cacn.hash[0] == '\0') + mir_sntprintf(cacn.hash, SIZEOF(cacn.hash), _T("AVS-HASH-%x"), GetFileHash(cacn.filename)); + + NotifyEventHooks(hEventContactAvatarChanged, (WPARAM)cacn.hContact, (LPARAM)&cacn); + } + else + NotifyEventHooks(hEventContactAvatarChanged, (WPARAM)hContact, NULL); + } +} + +static int g_maxBlock = 0, g_curBlock = 0; +static struct CacheNode **g_cacheBlocks = NULL; + +/* + * allocate a cache block and add it to the list of blocks + * does not link the new block with the old block(s) - caller needs to do this + */ + +static struct CacheNode *AllocCacheBlock() +{ + struct CacheNode *allocedBlock = NULL; + + allocedBlock = (struct CacheNode *)malloc(CACHE_BLOCKSIZE * sizeof(struct CacheNode)); + ZeroMemory((void *)allocedBlock, sizeof(struct CacheNode) * CACHE_BLOCKSIZE); + + for(int i = 0; i < CACHE_BLOCKSIZE - 1; i++) + { + //InitializeCriticalSection(&allocedBlock[i].cs); + allocedBlock[i].pNextNode = &allocedBlock[i + 1]; // pre-link the alloced block + } + //InitializeCriticalSection(&allocedBlock[CACHE_BLOCKSIZE - 1].cs); + + if (g_Cache == NULL) // first time only... + g_Cache = allocedBlock; + + // add it to the list of blocks + + if (g_curBlock == g_maxBlock) { + g_maxBlock += 10; + g_cacheBlocks = (struct CacheNode **)realloc(g_cacheBlocks, g_maxBlock * sizeof(struct CacheNode *)); + } + g_cacheBlocks[g_curBlock++] = allocedBlock; + + return(allocedBlock); +} + +int SetAvatarAttribute(HANDLE hContact, DWORD attrib, int mode) +{ + struct CacheNode *cacheNode = g_Cache; + + while(cacheNode) { + if (cacheNode->ace.hContact == hContact) { + DWORD dwFlags = cacheNode->ace.dwFlags; + + cacheNode->ace.dwFlags = mode ? cacheNode->ace.dwFlags | attrib : cacheNode->ace.dwFlags & ~attrib; + if (cacheNode->ace.dwFlags != dwFlags) + NotifyMetaAware(hContact, cacheNode); + break; + } + cacheNode = cacheNode->pNextNode; + } + return 0; +} + +/* + * convert the avatar image path to a relative one... + * given: contact handle, path to image + */ +void MakePathRelative(HANDLE hContact, TCHAR *path) +{ + TCHAR szFinalPath[MAX_PATH]; + szFinalPath[0] = '\0'; + + size_t result = AVS_pathToRelative(path, szFinalPath); + if (result && lstrlen(szFinalPath) > 0) { + DBWriteContactSettingTString(hContact, "ContactPhoto", "RFile", szFinalPath); + if (!DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0)) + DBWriteContactSettingTString(hContact, "ContactPhoto", "Backup", szFinalPath); + } +} + +/* + * convert the avatar image path to a relative one... + * given: contact handle + */ + +static void MakePathRelative(HANDLE hContact) +{ + DBVARIANT dbv = {0}; + + if (!DBGetContactSetting(hContact, "ContactPhoto", "File", &dbv)) { + if (dbv.type == DBVT_TCHAR) { + MakePathRelative(hContact, dbv.ptszVal); + } + DBFreeVariant(&dbv); + } +} + +static void ResetTranspSettings(HANDLE hContact) +{ + DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); +} + +static TCHAR *getJGMailID(char *szProto) +{ + static TCHAR szJID[MAX_PATH+1]; + DBVARIANT dbva={0}, dbvb={0}; + + szJID[0] = '\0'; + if (DBGetContactSettingTString(NULL, szProto, "LoginName", &dbva)) + return szJID; + if (DBGetContactSettingTString(NULL, szProto, "LoginServer", &dbvb)) { + DBFreeVariant(&dbva); + return szJID; + } + + mir_sntprintf(szJID, SIZEOF(szJID), _T("%s@%s"), dbva.ptszVal, dbvb.ptszVal); + DBFreeVariant(&dbva); + DBFreeVariant(&dbvb); + return szJID; +} + +// create the avatar in cache +// returns 0 if not created (no avatar), iIndex otherwise, -2 if has to request avatar, -3 if avatar too big +int CreateAvatarInCache(HANDLE hContact, avatarCacheEntry *ace, char *szProto) +{ + DBVARIANT dbv = {0}; + char *szExt = NULL; + TCHAR tszFilename[MAX_PATH]; + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD dwFileSizeHigh = 0, dwFileSize = 0, sizeLimit = 0; + + tszFilename[0] = 0; + + ace->hbmPic = 0; + ace->dwFlags = 0; + ace->bmHeight = 0; + ace->bmWidth = 0; + ace->lpDIBSection = NULL; + ace->szFilename[0] = 0; + + if (szProto == NULL) { + char *proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (proto == NULL || !DBGetContactSettingByte(NULL, AVS_MODULE, proto, 1)) { + return -1; + } + + if (DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) + && !DBGetContactSettingTString(hContact, "ContactPhoto", "Backup", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "RFile", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + else { + return -2; + } + } + else { + if (hContact == 0) { // create a protocol picture in the proto picture cache + if (!DBGetContactSettingTString(NULL, PPICT_MODULE, szProto, &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + else { + if (lstrcmpA(szProto, AVS_DEFAULT)) { + if (!DBGetContactSettingTString(NULL, PPICT_MODULE, AVS_DEFAULT, &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + + if (!strstr(szProto, "Global avatar for")) { + PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)szProto); + if (pdescr == NULL) + return -1; + char key[MAX_PATH]; + mir_snprintf(key, SIZEOF(key), "Global avatar for %s accounts", pdescr->szProtoName); + if (!DBGetContactSettingTString(NULL, PPICT_MODULE, key, &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + } + } + } + } + else if (hContact == (HANDLE)-1) { // create own picture - note, own avatars are not on demand, they are loaded once at + // startup and everytime they are changed. + if (szProto[0] == '\0') { + // Global avatar + if ( DBGetContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) + return -10; + + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + else if (ProtoServiceExists(szProto, PS_GETMYAVATART)) { + if (CallProtoService(szProto, PS_GETMYAVATART, (WPARAM)tszFilename, (LPARAM)MAX_PATH)) + tszFilename[0] = '\0'; + } +#if defined( _UNICODE ) + else if (ProtoServiceExists(szProto, PS_GETMYAVATAR)) { + char szFileName[ MAX_PATH ]; + if (CallProtoService(szProto, PS_GETMYAVATAR, (WPARAM)szFileName, (LPARAM)MAX_PATH)) + tszFilename[0] = '\0'; + else + MultiByteToWideChar( CP_ACP, 0, szFileName, -1, tszFilename, SIZEOF( tszFilename )); + } +#endif + else if (!DBGetContactSettingTString(NULL, szProto, "AvatarFile", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, tszFilename); + DBFreeVariant(&dbv); + } + else return -1; + } + } + + if ( lstrlen(tszFilename) < 4 ) + return -1; + + TCHAR* tmpPath = Utils_ReplaceVarsT(tszFilename); + mir_sntprintf(tszFilename, SIZEOF(tszFilename), _T("%s"), tmpPath); + mir_free(tmpPath); + + if ((hFile = CreateFile(tszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) + return -2; + + CloseHandle(hFile); + WPARAM isTransparentImage = 0; + + ace->hbmPic = (HBITMAP) BmpFilterLoadBitmap32((WPARAM)&isTransparentImage, (LPARAM)tszFilename); + ace->dwFlags = 0; + ace->bmHeight = 0; + ace->bmWidth = 0; + ace->lpDIBSection = NULL; + _tcsncpy(ace->szFilename, tszFilename, MAX_PATH); + ace->szFilename[MAX_PATH - 1] = 0; + if (ace->hbmPic != 0) { + BITMAP bminfo; + + GetObject(ace->hbmPic, sizeof(bminfo), &bminfo); + + ace->cbSize = sizeof(avatarCacheEntry); + ace->dwFlags = AVS_BITMAP_VALID; + if (hContact != NULL && DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0)) + ace->dwFlags |= AVS_HIDEONCLIST; + ace->hContact = hContact; + ace->bmHeight = bminfo.bmHeight; + ace->bmWidth = bminfo.bmWidth; + + BOOL noTransparency = DBGetContactSettingByte(0, AVS_MODULE, "RemoveAllTransparency", 0); + + // Calc image hash + if (hContact != 0 && hContact != (HANDLE)-1) + { + // Have to reset settings? -> do it if image changed + DWORD imgHash = GetImgHash(ace->hbmPic); + + if (imgHash != DBGetContactSettingDword(hContact, "ContactPhoto", "ImageHash", 0)) + { + ResetTranspSettings(hContact); + DBWriteContactSettingDword(hContact, "ContactPhoto", "ImageHash", imgHash); + } + + // Make transparent? + if (!noTransparency && !isTransparentImage + && DBGetContactSettingByte(hContact, "ContactPhoto", "MakeTransparentBkg", + DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0))) + { + if (MakeTransparentBkg(hContact, &ace->hbmPic)) + { + ace->dwFlags |= AVS_CUSTOMTRANSPBKG | AVS_HASTRANSPARENCY; + GetObject(ace->hbmPic, sizeof(bminfo), &bminfo); + isTransparentImage = TRUE; + } + } + } + else if (hContact == (HANDLE)-1) // My avatars + { + if (!noTransparency && !isTransparentImage + && DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0) + && DBGetContactSettingByte(0, AVS_MODULE, "MakeMyAvatarsTransparent", 0)) + { + if (MakeTransparentBkg(0, &ace->hbmPic)) + { + ace->dwFlags |= AVS_CUSTOMTRANSPBKG | AVS_HASTRANSPARENCY; + GetObject(ace->hbmPic, sizeof(bminfo), &bminfo); + isTransparentImage = TRUE; + } + } + } + + if (DBGetContactSettingByte(0, AVS_MODULE, "MakeGrayscale", 0)) + { + ace->hbmPic = MakeGrayscale(hContact, ace->hbmPic); + } + + if (noTransparency) + { + fei->FI_CorrectBitmap32Alpha(ace->hbmPic, TRUE); + isTransparentImage = FALSE; + } + + if (bminfo.bmBitsPixel == 32 && isTransparentImage) + { + if (fei->FI_Premultiply(ace->hbmPic)) + { + ace->dwFlags |= AVS_HASTRANSPARENCY; + } + ace->dwFlags |= AVS_PREMULTIPLIED; + } + + if (szProto) + { + protoPicCacheEntry *pAce = (protoPicCacheEntry *)ace; + if (hContact == 0) + pAce->dwFlags |= AVS_PROTOPIC; + else if (hContact == (HANDLE)-1) + pAce->dwFlags |= AVS_OWNAVATAR; + } + + return 1; + } + return -1; +} + +/* + * link a new cache block with the already existing chain of blocks + */ + +static struct CacheNode *AddToList(struct CacheNode *node) { + struct CacheNode *pCurrent = g_Cache; + + while(pCurrent->pNextNode != 0) + pCurrent = pCurrent->pNextNode; + + pCurrent->pNextNode = node; + return pCurrent; +} + +struct CacheNode *FindAvatarInCache(HANDLE hContact, BOOL add, BOOL findAny = FALSE) +{ + struct CacheNode *cacheNode = g_Cache, *foundNode = NULL; + + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto == NULL || !DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1)) + return NULL; + + EnterCriticalSection(&cachecs); + + while(cacheNode) + { + if (cacheNode->ace.hContact == hContact) + { + cacheNode->ace.t_lastAccess = time(NULL); + foundNode = cacheNode->loaded || findAny ? cacheNode : NULL; + LeaveCriticalSection(&cachecs); + return foundNode; + } + if (foundNode == NULL && cacheNode->ace.hContact == 0) + foundNode = cacheNode; // found an empty and usable node + + cacheNode = cacheNode->pNextNode; + } + + // not found + + if (add) + { + if (foundNode == NULL) { // no free entry found, create a new and append it to the list + EnterCriticalSection(&alloccs); // protect memory block allocation + struct CacheNode *newNode = AllocCacheBlock(); + AddToList(newNode); + foundNode = newNode; + LeaveCriticalSection(&alloccs); + } + + foundNode->ace.hContact = hContact; + if (g_MetaAvail) + foundNode->dwFlags |= (DBGetContactSettingByte(hContact, g_szMetaName, "IsSubcontact", 0) ? MC_ISSUBCONTACT : 0); + foundNode->loaded = FALSE; + foundNode->mustLoad = 1; // pic loader will watch this and load images + LeaveCriticalSection(&cachecs); + SetEvent(hLoaderEvent); // wake him up + return NULL; + } + else + { + foundNode = NULL; + } + LeaveCriticalSection(&cachecs); + return foundNode; +} + +#define POLYNOMIAL (0x488781ED) /* This is the CRC Poly */ +#define TOPBIT (1 << (WIDTH - 1)) /* MSB */ +#define WIDTH 32 + +static int GetFileHash(TCHAR* filename) +{ + HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + + int remainder = 0; + char data[1024]; + DWORD dwRead; + do + { + // Read file chunk + dwRead = 0; + ReadFile(hFile, data, 1024, &dwRead, NULL); + + /* loop through each byte of data */ + for (int byte = 0; byte < (int) dwRead; ++byte) { + /* store the next byte into the remainder */ + remainder ^= (data[byte] << (WIDTH - 8)); + /* calculate for all 8 bits in the byte */ + for (int bit = 8; bit > 0; --bit) { + /* check if MSB of remainder is a one */ + if (remainder & TOPBIT) + remainder = (remainder << 1) ^ POLYNOMIAL; + else + remainder = (remainder << 1); + } + } + } while(dwRead == 1024); + + CloseHandle(hFile); + + return remainder; +} + +static int ProtocolAck(WPARAM wParam, LPARAM lParam) +{ + ACKDATA *ack = (ACKDATA *) lParam; + + if (ack != NULL && ack->type == ACKTYPE_AVATAR && ack->hContact != 0 + // Ignore metacontacts + && (!g_MetaAvail || strcmp(ack->szModule, g_szMetaName))) + { + if (ack->result == ACKRESULT_SUCCESS) + { + if (ack->hProcess == NULL) + ProcessAvatarInfo(ack->hContact, GAIR_NOAVATAR, NULL, ack->szModule); + else + ProcessAvatarInfo(ack->hContact, GAIR_SUCCESS, (PROTO_AVATAR_INFORMATIONT *) ack->hProcess, ack->szModule); + } + else if (ack->result == ACKRESULT_FAILED) + { + ProcessAvatarInfo(ack->hContact, GAIR_FAILED, (PROTO_AVATAR_INFORMATIONT *) ack->hProcess, ack->szModule); + } + else if (ack->result == ACKRESULT_STATUS) + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ack->hContact, 0); + if (szProto == NULL || Proto_NeedDelaysForAvatars(szProto)) + { + // Queue + DBWriteContactSettingByte(ack->hContact, "ContactPhoto", "NeedUpdate", 1); + QueueAdd(ack->hContact); + } + else + { + // Fetch it now + FetchAvatarFor(ack->hContact, szProto); + } + } + } + return 0; +} + +INT_PTR ProtectAvatar(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + BYTE was_locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); + + if (fei == NULL || was_locked == (BYTE)lParam) // no need for redundant lockings... + return 0; + + if (hContact) { + if (!was_locked) + MakePathRelative(hContact); + DBWriteContactSettingByte(hContact, "ContactPhoto", "Locked", lParam ? 1 : 0); + if (lParam == 0) + MakePathRelative(hContact); + ChangeAvatar(hContact, TRUE); + } + return 0; +} + +/* + * for subclassing the open file dialog... + */ +struct OpenFileSubclassData { + BYTE *locking_request; + BYTE setView; +}; + +static BOOL CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { + OPENFILENAME *ofn = (OPENFILENAME *)lParam; + + OpenFileSubclassData *data = (OpenFileSubclassData *) malloc(sizeof(OpenFileSubclassData)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data); + data->locking_request = (BYTE *)ofn->lCustData; + data->setView = TRUE; + + TranslateDialogDefault(hwnd); + CheckDlgButton(hwnd, IDC_PROTECTAVATAR, *(data->locking_request)); + break; + } + + case WM_COMMAND: + if (LOWORD(wParam) == IDC_PROTECTAVATAR) + { + OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + *(data->locking_request) = IsDlgButtonChecked(hwnd, IDC_PROTECTAVATAR) ? TRUE : FALSE; + } + break; + + case WM_NOTIFY: + { + OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (data->setView) + { + HWND hwndParent = GetParent(hwnd); + HWND hwndLv = FindWindowEx(hwndParent, NULL, _T("SHELLDLL_DefView"), NULL) ; + if (hwndLv != NULL) + { + SendMessage(hwndLv, WM_COMMAND, SHVIEW_THUMBNAIL, 0); + data->setView = FALSE; + } + } + } + break; + + case WM_NCDESTROY: + OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + free((OpenFileSubclassData *)data); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)0); + break; + } + + return FALSE; +} + +/* + * set an avatar (service function) + * if lParam == NULL, a open file dialog will be opened, otherwise, lParam is taken as a FULL + * image filename (will be checked for existance, though) + */ + +INT_PTR avSetAvatar(HANDLE hContact, TCHAR* tszPath) +{ + BYTE is_locked = 0; + TCHAR FileName[MAX_PATH], szBackupName[MAX_PATH]; + TCHAR *szFinalName = NULL; + HANDLE hFile = 0; + BYTE locking_request; + + if (hContact == NULL || fei == NULL) + return 0; + + is_locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); + + if ( tszPath == NULL ) { + OPENFILENAME ofn = {0}; + TCHAR filter[256]; + + filter[0] = '\0'; + CallService(MS_UTILS_GETBITMAPFILTERSTRINGST, SIZEOF(filter), ( LPARAM )filter); + + if (IsWinVer2000Plus()) + ofn.lStructSize = sizeof(ofn); + else + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = 0; + ofn.lpstrFile = FileName; + ofn.lpstrFilter = filter; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK; + ofn.lpstrInitialDir = _T("."); + *FileName = '\0'; + ofn.lpstrDefExt = _T(""); + ofn.hInstance = g_hInst; + ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENSUBCLASS); + ofn.lpfnHook = (LPOFNHOOKPROC)OpenFileSubclass; + locking_request = is_locked; + ofn.lCustData = (LPARAM)&locking_request; + if (GetOpenFileName(&ofn)) { + szFinalName = FileName; + is_locked = locking_request ? 1 : is_locked; + } + else + return 0; + } + else + szFinalName = tszPath; + + /* + * filename is now set, check it and perform all needed action + */ + + if ((hFile = CreateFile(szFinalName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) + return 0; + + // file exists... + + CloseHandle(hFile); + + AVS_pathToRelative(szFinalName, szBackupName); + DBWriteContactSettingTString(hContact, "ContactPhoto", "Backup", szBackupName); + + DBWriteContactSettingByte(hContact, "ContactPhoto", "Locked", is_locked); + DBWriteContactSettingTString(hContact, "ContactPhoto", "File", szFinalName); + MakePathRelative(hContact, szFinalName); + // Fix cache + ChangeAvatar(hContact, TRUE); + + return 0; +} + +INT_PTR SetAvatar(WPARAM wParam, LPARAM lParam) +{ return avSetAvatar(( HANDLE )wParam, A2T(( const char* )lParam )); +} + +#if defined( _UNICODE ) +INT_PTR SetAvatarW(WPARAM wParam, LPARAM lParam) +{ return avSetAvatar(( HANDLE )wParam, ( TCHAR* )lParam ); +} +#endif + +/* + * see if is possible to set the avatar for the expecified protocol + */ +static INT_PTR CanSetMyAvatar(WPARAM wParam, LPARAM lParam) +{ + char *protocol = (char *) wParam; + if (protocol == NULL || fei == NULL) + return 0; + + return ProtoServiceExists(protocol, PS_SETMYAVATAR); +} + +struct SetMyAvatarHookData { + char *protocol; + BOOL square; + BOOL grow; + + BOOL thumbnail; +}; + + +/* + * Callback to set thumbnaill view to open dialog + */ +static UINT_PTR CALLBACK SetMyAvatarHookProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { + InterlockedExchange(&hwndSetMyAvatar, (LONG) hwnd); + + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam); + OPENFILENAME *ofn = (OPENFILENAME *)lParam; + SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData; + data->thumbnail = TRUE; + + SetWindowText(GetDlgItem(hwnd, IDC_MAKE_SQUARE), TranslateT("Make the avatar square")); + SetWindowText(GetDlgItem(hwnd, IDC_GROW), TranslateT("Grow avatar to fit max allowed protocol size")); + + CheckDlgButton(hwnd, IDC_MAKE_SQUARE, data->square ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwnd, IDC_GROW, data->grow ? BST_CHECKED : BST_UNCHECKED); + + if (data->protocol != NULL && (Proto_AvatarImageProportion(data->protocol) & PIP_SQUARE)) + EnableWindow(GetDlgItem(hwnd, IDC_MAKE_SQUARE), FALSE); + } + break; + + case WM_NOTIFY: + { + OPENFILENAME *ofn = (OPENFILENAME *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData; + if (data->thumbnail) + { + HWND hwndParent = GetParent(hwnd); + HWND hwndLv = FindWindowEx(hwndParent, NULL, _T("SHELLDLL_DefView"), NULL) ; + if (hwndLv != NULL) + { + SendMessage(hwndLv, WM_COMMAND, SHVIEW_THUMBNAIL, 0); + data->thumbnail = FALSE; + } + } + break; + } + case WM_DESTROY: + { + OPENFILENAME *ofn = (OPENFILENAME *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData; + data->square = IsDlgButtonChecked(hwnd, IDC_MAKE_SQUARE); + data->grow = IsDlgButtonChecked(hwnd, IDC_GROW); + + InterlockedExchange(&hwndSetMyAvatar, 0); + break; + } + } + + return 0; +} + +const TCHAR *GetFormatExtension(int format) +{ + if (format == PA_FORMAT_PNG) + return _T(".png"); + if (format == PA_FORMAT_JPEG) + return _T(".jpg"); + if (format == PA_FORMAT_ICON) + return _T(".ico"); + if (format == PA_FORMAT_BMP) + return _T(".bmp"); + if (format == PA_FORMAT_GIF) + return _T(".gif"); + if (format == PA_FORMAT_SWF) + return _T(".swf"); + if (format == PA_FORMAT_XML) + return _T(".xml"); + + return NULL; +} + +int GetImageFormat(TCHAR *filename) +{ + size_t len = lstrlen(filename); + + if (len < 5) + return PA_FORMAT_UNKNOWN; + + if (_tcsicmp(_T(".png"), &filename[len-4]) == 0) + return PA_FORMAT_PNG; + + if (_tcsicmp(_T(".jpg"), &filename[len-4]) == 0 || _tcsicmp(_T(".jpeg"), &filename[len-4]) == 0) + return PA_FORMAT_JPEG; + + if (_tcsicmp(_T(".ico"), &filename[len-4]) == 0) + return PA_FORMAT_ICON; + + if (_tcsicmp(_T(".bmp"), &filename[len-4]) == 0 || _tcsicmp(_T(".rle"), &filename[len-4]) == 0) + return PA_FORMAT_BMP; + + if (_tcsicmp(_T(".gif"), &filename[len-4]) == 0) + return PA_FORMAT_GIF; + + if (_tcsicmp(_T(".swf"), &filename[len-4]) == 0) + return PA_FORMAT_SWF; + + if (_tcsicmp(_T(".xml"), &filename[len-4]) == 0) + return PA_FORMAT_XML; + + return PA_FORMAT_UNKNOWN; +} + +static void FilterGetStrings(TCHAR *filter, int bytesLeft, BOOL xml, BOOL swf) +{ + TCHAR *pfilter; + int wParam = bytesLeft; + + lstrcpyn(filter, TranslateT("All Files"), bytesLeft); bytesLeft-=lstrlen(filter); + _tcsncat(filter, _T(" (*.bmp;*.jpg;*.gif;*.png"), bytesLeft); + if (swf) _tcscat(filter, _T(";*.swf")); + if (xml) _tcscat(filter, _T(";*.xml")); + _tcscat(filter, _T(")")); + pfilter=filter+lstrlen(filter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.BMP;*.RLE;*.JPG;*.JPEG;*.GIF;*.PNG"), bytesLeft); + if (swf) _tcscat(pfilter, _T(";*.SWF")); + if (xml) _tcscat(pfilter, _T(";*.XML")); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + + lstrcpyn(pfilter, TranslateT("Windows Bitmaps"), bytesLeft); bytesLeft-=lstrlen(pfilter); + _tcsncat(pfilter, _T(" (*.bmp;*.rle)"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.BMP;*.RLE"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + + lstrcpyn(pfilter,TranslateT("JPEG Bitmaps"),bytesLeft); bytesLeft-=lstrlen(pfilter); + _tcsncat(pfilter, _T(" (*.jpg;*.jpeg)"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.JPG;*.JPEG"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + + lstrcpyn(pfilter,TranslateT("GIF Bitmaps"),bytesLeft); bytesLeft-=lstrlen(pfilter); + _tcsncat(pfilter, _T(" (*.gif)"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.GIF"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + + lstrcpyn(pfilter,TranslateT("PNG Bitmaps"), bytesLeft); bytesLeft-=lstrlen(pfilter); + _tcsncat(pfilter, _T(" (*.png)"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.PNG"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + + if (swf) + { + lstrcpyn(pfilter,TranslateT("Flash Animations"), bytesLeft); bytesLeft-=lstrlen(pfilter); + _tcsncat(pfilter, _T(" (*.swf)"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.SWF"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + } + + if (xml) + { + lstrcpyn(pfilter, TranslateT("XML Files"), bytesLeft); bytesLeft-=lstrlen(pfilter); + _tcsncat(pfilter, _T(" (*.xml)"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + lstrcpyn(pfilter, _T("*.XML"), bytesLeft); + pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); + } + + if (bytesLeft) *pfilter='\0'; +} + +static void DeleteGlobalUserAvatar() +{ + DBVARIANT dbv = {0}; + if (DBGetContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) + return; + + TCHAR szFilename[MAX_PATH]; + AVS_pathToAbsolute(dbv.ptszVal, szFilename); + DBFreeVariant(&dbv); + + DeleteFile(szFilename); + DBDeleteContactSetting(NULL, AVS_MODULE, "GlobalUserAvatarFile"); +} + +static void SetIgnoreNotify(char *protocol, BOOL ignore) +{ + for(int i = 0; i < g_MyAvatars.getCount(); i++) { + if (protocol == NULL || !lstrcmpA(g_MyAvatars[i].szProtoname, protocol)) { + if (ignore) + g_MyAvatars[i].dwFlags |= AVS_IGNORENOTIFY; + else + g_MyAvatars[i].dwFlags &= ~AVS_IGNORENOTIFY; + } + } +} + +static int InternalRemoveMyAvatar(char *protocol) +{ + SetIgnoreNotify(protocol, TRUE); + + // Remove avatar + int ret = 0; + if (protocol != NULL) + { + if (ProtoServiceExists(protocol, PS_SETMYAVATAR)) + ret = SaveAvatar(protocol, NULL); + else + ret = -3; + + if (ret == 0) + { + // Has global avatar? + DBVARIANT dbv = {0}; + if (!DBGetContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) + { + DBFreeVariant(&dbv); + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); + DeleteGlobalUserAvatar(); + } + } + } + else + { + PROTOACCOUNT **accs; + int i,count; + + ProtoEnumAccounts( &count, &accs ); + for (i = 0; i < count; i++) + { + if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR)) + continue; + + if (!Proto_IsAvatarsEnabled( accs[i]->szModuleName )) + continue; + + // Found a protocol + int retTmp = SaveAvatar( accs[i]->szModuleName, NULL); + if (retTmp != 0) + ret = retTmp; + } + + DeleteGlobalUserAvatar(); + + if (ret) + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); + else + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 0); + } + + SetIgnoreNotify(protocol, FALSE); + + ReportMyAvatarChanged((WPARAM)(( protocol == NULL ) ? "" : protocol ), 0); + return ret; +} + +static int InternalSetMyAvatar(char *protocol, TCHAR *szFinalName, SetMyAvatarHookData &data, BOOL allAcceptXML, BOOL allAcceptSWF) +{ + HANDLE hFile = 0; + + int format = GetImageFormat(szFinalName); + if (format == PA_FORMAT_UNKNOWN || (hFile = CreateFile(szFinalName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) + return -3; + + CloseHandle(hFile); + + // file exists... + + HBITMAP hBmp = NULL; + + if (format == PA_FORMAT_SWF) + { + if (!allAcceptSWF) + return -4; + } + else if (format == PA_FORMAT_XML) + { + if (!allAcceptXML) + return -4; + } + else + { + // Try to open if is not a flash or XML + hBmp = (HBITMAP) CallService(MS_IMG_LOAD, (WPARAM) szFinalName, IMGL_TCHAR); + if (hBmp == NULL) + return -4; + } + + SetIgnoreNotify(protocol, TRUE); + + int ret = 0; + if (protocol != NULL) + { + ret = SetProtoMyAvatar(protocol, hBmp, szFinalName, format, data.square, data.grow); + + if (ret == 0) + { + DeleteGlobalUserAvatar(); + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); + } + } + else + { + PROTOACCOUNT **accs; + int i,count; + + ProtoEnumAccounts( &count, &accs ); + for (i = 0; i < count; i++) + { + if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR)) + continue; + + if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName )) + continue; + + int retTmp = SetProtoMyAvatar( accs[i]->szModuleName, hBmp, szFinalName, format, data.square, data.grow); + if (retTmp != 0) + ret = retTmp; + } + + DeleteGlobalUserAvatar(); + + if (ret) + { + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); + } + else + { + // Copy avatar file to store as global one + TCHAR globalFile[1024]; + BOOL saved = TRUE; + if (FoldersGetCustomPathT(hGlobalAvatarFolder, globalFile, SIZEOF(globalFile), _T(""))) + { + mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\%s"), g_szDataPath, _T("GlobalAvatar")); + CreateDirectory(globalFile, NULL); + } + + TCHAR *ext = _tcsrchr(szFinalName, _T('.')); // Can't be NULL here + if (format == PA_FORMAT_XML || format == PA_FORMAT_SWF) + { + mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar%s"), globalFile, ext); + CopyFile(szFinalName, globalFile, FALSE); + } + else + { + // Resize (to avoid too big avatars) + ResizeBitmap rb = {0}; + rb.size = sizeof(ResizeBitmap); + rb.hBmp = hBmp; + rb.max_height = 300; + rb.max_width = 300; + rb.fit = (data.grow ? 0 : RESIZEBITMAP_FLAG_DONT_GROW) + | (data.square ? RESIZEBITMAP_MAKE_SQUARE : RESIZEBITMAP_KEEP_PROPORTIONS); + + HBITMAP hBmpTmp = (HBITMAP) BmpFilterResizeBitmap((WPARAM)&rb, 0); + + // Check if need to resize + if (hBmpTmp == hBmp || hBmpTmp == NULL) + { + // Use original image + mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar%s"), globalFile, ext); + CopyFile(szFinalName, globalFile, FALSE); + } + else + { + // Save as PNG + mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar.png"), globalFile); + if (BmpFilterSaveBitmap((WPARAM) hBmpTmp, (LPARAM) globalFile)) + saved = FALSE; + + DeleteObject(hBmpTmp); + } + } + + if (saved) + { + TCHAR relFile[1024]; + if (AVS_pathToRelative(globalFile, relFile)) + DBWriteContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", relFile); + else + DBWriteContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", globalFile); + + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 0); + } + else + { + DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); + } + } + } + + DeleteObject(hBmp); + + SetIgnoreNotify(protocol, FALSE); + + ReportMyAvatarChanged((WPARAM)(( protocol == NULL ) ? "" : protocol ), 0); + return ret; +} + +/* + * set an avatar for a protocol (service function) + * if lParam == NULL, a open file dialog will be opened, otherwise, lParam is taken as a FULL + * image filename (will be checked for existance, though) + */ + +INT_PTR avSetMyAvatar( char* protocol, TCHAR* tszPath ) +{ + TCHAR FileName[MAX_PATH]; + TCHAR *szFinalName = NULL; + BOOL allAcceptXML; + BOOL allAcceptSWF; + + // Protocol allow seting of avatar? + if (protocol != NULL && !CanSetMyAvatar((WPARAM) protocol, 0)) + return -1; + + if (tszPath == NULL && hwndSetMyAvatar != 0) + { + SetForegroundWindow((HWND) hwndSetMyAvatar); + SetFocus((HWND) hwndSetMyAvatar); + ShowWindow((HWND) hwndSetMyAvatar, SW_SHOW); + return -2; + } + + SetMyAvatarHookData data = { 0 }; + + // Check for XML and SWF + if (protocol == NULL) + { + allAcceptXML = TRUE; + allAcceptSWF = TRUE; + + PROTOACCOUNT **accs; + int i,count; + + ProtoEnumAccounts( &count, &accs ); + for (i = 0; i < count; i++) + { + if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR)) + continue; + + if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName )) + continue; + + allAcceptXML = allAcceptXML && Proto_IsAvatarFormatSupported( accs[i]->szModuleName, PA_FORMAT_XML); + allAcceptSWF = allAcceptSWF && Proto_IsAvatarFormatSupported( accs[i]->szModuleName, PA_FORMAT_SWF); + } + + data.square = DBGetContactSettingByte(0, AVS_MODULE, "SetAllwaysMakeSquare", 0); + } + else + { + allAcceptXML = Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_XML); + allAcceptSWF = Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_SWF); + + data.protocol = protocol; + data.square = (Proto_AvatarImageProportion(protocol) & PIP_SQUARE) + || DBGetContactSettingByte(0, AVS_MODULE, "SetAllwaysMakeSquare", 0); + } + + if (tszPath == NULL) { + OPENFILENAME ofn = {0}; + TCHAR filter[512]; + TCHAR inipath[1024]; + + data.protocol = protocol; + + filter[0] = '\0'; + FilterGetStrings(filter, SIZEOF(filter), allAcceptXML, allAcceptSWF); + + FoldersGetCustomPathT(hMyAvatarsFolder, inipath, SIZEOF(inipath), _T(".")); + + if (IsWinVer2000Plus()) + ofn.lStructSize = sizeof(ofn); + else + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.hwndOwner = 0; + ofn.lpstrFile = FileName; + ofn.lpstrFilter = filter; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK; + ofn.lpstrInitialDir = inipath; + ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SET_OWN_SUBCLASS); + ofn.lpfnHook = SetMyAvatarHookProc; + ofn.lCustData = (LPARAM) &data; + + *FileName = '\0'; + ofn.lpstrDefExt = _T(""); + ofn.hInstance = g_hInst; + + TCHAR title[256]; + if (protocol == NULL) + mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Avatar")); + else + { + TCHAR* prototmp = mir_a2t(protocol); + mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Avatar for %s"), prototmp); + mir_free(prototmp); + } + ofn.lpstrTitle = title; + + if (GetOpenFileName(&ofn)) + szFinalName = FileName; + else + return 1; + } + else + szFinalName = (TCHAR *)tszPath; + + /* + * filename is now set, check it and perform all needed action + */ + + if (szFinalName[0] == '\0') + return InternalRemoveMyAvatar(protocol); + + return InternalSetMyAvatar(protocol, szFinalName, data, allAcceptXML, allAcceptSWF); +} + +static INT_PTR SetMyAvatar( WPARAM wParam, LPARAM lParam ) +{ return avSetMyAvatar(( char* )wParam, A2T(( const char* )lParam )); +} + +#if defined( _UNICODE ) +static INT_PTR SetMyAvatarW( WPARAM wParam, LPARAM lParam ) +{ return avSetMyAvatar(( char* )wParam, ( TCHAR* )lParam ); +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +static DWORD GetFileSize(TCHAR *szFilename) +{ + HANDLE hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + + DWORD low = GetFileSize(hFile, NULL); + + CloseHandle(hFile); + + if (low == INVALID_FILE_SIZE) + return 0; + + return low; +} + +struct SaveProtocolData { + DWORD max_size; + TCHAR image_file_name[MAX_PATH]; + BOOL saved; + BOOL need_smaller_size; + int width; + int height; + TCHAR temp_file[MAX_PATH]; + HBITMAP hBmpProto; +}; + +static void SaveImage(SaveProtocolData &d, char *protocol, int format) +{ + if (Proto_IsAvatarFormatSupported(protocol, format)) + { + mir_sntprintf(d.image_file_name, SIZEOF(d.image_file_name), _T("%s%s"), d.temp_file, GetFormatExtension(format)); + if (!BmpFilterSaveBitmapT(d.hBmpProto, d.image_file_name, format == PA_FORMAT_JPEG ? JPEG_QUALITYSUPERB : 0)) + { + if (d.max_size != 0 && GetFileSize(d.image_file_name) > d.max_size) + { + DeleteFile(d.image_file_name); + + if (format == PA_FORMAT_JPEG) + { + // Try with lower quality + if (!BmpFilterSaveBitmapT(d.hBmpProto, d.image_file_name, JPEG_QUALITYGOOD)) + { + if (GetFileSize(d.image_file_name) > d.max_size) + { + DeleteFile(d.image_file_name); + d.need_smaller_size = TRUE; + } + else + d.saved = TRUE; + } + } + else + d.need_smaller_size = TRUE; + } + else + d.saved = TRUE; + } + } +} + +static int SetProtoMyAvatar(char *protocol, HBITMAP hBmp, TCHAR *originalFilename, int originalFormat, + BOOL square, BOOL grow) +{ + if (!ProtoServiceExists(protocol, PS_SETMYAVATAR)) + return -1; + + // If is swf or xml, just set it + + if (originalFormat == PA_FORMAT_SWF) + { + if (!Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_SWF)) + return -1; + + return SaveAvatar(protocol, originalFilename); + } + + if (originalFormat == PA_FORMAT_XML) + { + if (!Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_XML)) + return -1; + + return SaveAvatar(protocol, originalFilename); + } + + // Get protocol info + SaveProtocolData d = {0}; + + d.max_size = (DWORD) Proto_GetAvatarMaxFileSize(protocol); + + Proto_GetAvatarMaxSize(protocol, &d.width, &d.height); + int orig_width = d.width; + int orig_height = d.height; + + if (Proto_AvatarImageProportion(protocol) & PIP_SQUARE) + square = TRUE; + + + // Try to save until a valid image is found or we give up + int num_tries = 0; + do { + // Lets do it + ResizeBitmap rb; + rb.size = sizeof(ResizeBitmap); + rb.hBmp = hBmp; + rb.max_height = d.height; + rb.max_width = d.width; + rb.fit = (grow ? 0 : RESIZEBITMAP_FLAG_DONT_GROW) + | (square ? RESIZEBITMAP_MAKE_SQUARE : RESIZEBITMAP_KEEP_PROPORTIONS); + + d.hBmpProto = (HBITMAP) BmpFilterResizeBitmap((WPARAM)&rb, 0); + + if (d.hBmpProto == NULL) + { + if (d.temp_file[0] != '\0') + DeleteFile(d.temp_file); + return -1; + } + + // Check if can use original image + if (d.hBmpProto == hBmp + && Proto_IsAvatarFormatSupported(protocol, originalFormat) + && (d.max_size == 0 || GetFileSize(originalFilename) < d.max_size)) + { + if (d.temp_file[0] != '\0') + DeleteFile(d.temp_file); + + // Use original image + return SaveAvatar(protocol, originalFilename); + } + + // Create a temporary file (if was not created already) + if (d.temp_file[0] == '\0') + { + d.temp_file[0] = '\0'; + if (GetTempPath(MAX_PATH, d.temp_file) == 0 + || GetTempFileName(d.temp_file, _T("mir_av_"), 0, d.temp_file) == 0) + { + DeleteObject(d.hBmpProto); + return -1; + } + } + + // Which format? + + // First try to use original format + if (originalFormat != PA_FORMAT_BMP) + SaveImage(d, protocol, originalFormat); + + if (!d.saved && originalFormat != PA_FORMAT_PNG) + SaveImage(d, protocol, PA_FORMAT_PNG); + + if (!d.saved && originalFormat != PA_FORMAT_JPEG) + SaveImage(d, protocol, PA_FORMAT_JPEG); + + if (!d.saved && originalFormat != PA_FORMAT_GIF) + SaveImage(d, protocol, PA_FORMAT_GIF); + + if (!d.saved) + SaveImage(d, protocol, PA_FORMAT_BMP); + + num_tries++; + if (!d.saved && d.need_smaller_size && num_tries < 4) + { + // Cleanup + if (d.hBmpProto != hBmp) + DeleteObject(d.hBmpProto); + + // use a smaller size + d.width = orig_width * (4 - num_tries) / 4; + d.height = orig_height * (4 - num_tries) / 4; + } + + } while(!d.saved && d.need_smaller_size && num_tries < 4); + + int ret; + + if (d.saved) + { + // Call proto service + ret = SaveAvatar(protocol, d.image_file_name); + DeleteFile(d.image_file_name); + } + else + { + ret = -1; + } + + if (d.temp_file[0] != '\0') + DeleteFile(d.temp_file); + + if (d.hBmpProto != hBmp) + DeleteObject(d.hBmpProto); + + return ret; +} + +static INT_PTR ContactOptions(WPARAM wParam, LPARAM lParam) +{ + if (wParam) + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AVATAROPTIONS), 0, DlgProcAvatarOptions, (LPARAM)wParam); + return 0; +} + +INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam) +{ + int i; + char *szProto = (char *)lParam; + + if (wParam || g_shutDown || fei == NULL) + return 0; + + if (lParam == 0 || IsBadReadPtr(szProto, 4)) + return 0; + + for(i = 0; i < g_MyAvatars.getCount(); i++) { + if (!lstrcmpA(szProto, g_MyAvatars[i].szProtoname) && g_MyAvatars[i].hbmPic != 0) + return (INT_PTR)&g_MyAvatars[i]; + } + return 0; +} + +static protoPicCacheEntry *GetProtoDefaultAvatar(HANDLE hContact) +{ + char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto) { + for(int i = 0; i < g_ProtoPictures.getCount(); i++) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if ( !lstrcmpA(p.szProtoname, szProto) && p.hbmPic != NULL) + return &g_ProtoPictures[i]; + } + } + return NULL; +} + +HANDLE GetContactThatHaveTheAvatar(HANDLE hContact, int locked = -1) +{ + if (g_MetaAvail && DBGetContactSettingByte(NULL, g_szMetaName, "Enabled", 0)) { + if (DBGetContactSettingDword(hContact, g_szMetaName, "NumContacts", 0) >= 1) { + if (locked == -1) + locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); + + if (!locked) + hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0); + } + } + return hContact; +} + +INT_PTR GetAvatarBitmap(WPARAM wParam, LPARAM lParam) +{ + if (wParam == 0 || g_shutDown || fei == NULL) + return 0; + + HANDLE hContact = (HANDLE) wParam; + hContact = GetContactThatHaveTheAvatar(hContact); + + // Get the node + struct CacheNode *node = FindAvatarInCache(hContact, TRUE); + if (node == NULL || !node->loaded) + return (INT_PTR) GetProtoDefaultAvatar(hContact); + else + return (INT_PTR) &node->ace; +} + +// Just delete an avatar from cache +// An cache entry is never deleted. What is deleted is the image handle inside it +// This is done this way to keep track of which avatars avs have to keep track +void DeleteAvatarFromCache(HANDLE hContact, BOOL forever) +{ + hContact = GetContactThatHaveTheAvatar(hContact); + + struct CacheNode *node = FindAvatarInCache(hContact, FALSE); + if (node == NULL) { + struct CacheNode temp_node = {0}; + if (g_MetaAvail) + temp_node.dwFlags |= (DBGetContactSettingByte(hContact, g_szMetaName, "IsSubcontact", 0) ? MC_ISSUBCONTACT : 0); + NotifyMetaAware(hContact, &temp_node, (AVATARCACHEENTRY *)GetProtoDefaultAvatar(hContact)); + return; + } + node->mustLoad = -1; // mark for deletion + if (forever) + node->dwFlags |= AVS_DELETENODEFOREVER; + SetEvent(hLoaderEvent); +} + +int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist, int pa_format) +{ + if (g_shutDown) + return 0; + + hContact = GetContactThatHaveTheAvatar(hContact); + + // Get the node + struct CacheNode *node = FindAvatarInCache(hContact, g_AvatarHistoryAvail && fNotifyHist, TRUE); + if (node == NULL) + return 0; + + if (fNotifyHist) + node->dwFlags |= AVH_MUSTNOTIFY; + + node->mustLoad = fLoad ? 1 : -1; + node->pa_format = pa_format; + SetEvent(hLoaderEvent); + return 0; +} + +/* + * this thread scans the cache and handles nodes which have mustLoad set to > 0 (must be loaded/reloaded) or + * nodes where mustLoad is < 0 (must be deleted). + * its waken up by the event and tries to lock the cache only when absolutely necessary. + */ + +static void PicLoader(LPVOID param) +{ + DWORD dwDelay = DBGetContactSettingDword(NULL, AVS_MODULE, "picloader_sleeptime", 80); + + if (dwDelay < 30) + dwDelay = 30; + else if (dwDelay > 100) + dwDelay = 100; + + while(!g_shutDown) { + struct CacheNode *node = g_Cache; + + while(!g_shutDown && node) { + if (node->mustLoad > 0 && node->ace.hContact) { + node->mustLoad = 0; + AVATARCACHEENTRY ace_temp; + + if (DBGetContactSettingByte(node->ace.hContact, "ContactPhoto", "NeedUpdate", 0)) + QueueAdd(node->ace.hContact); + + CopyMemory(&ace_temp, &node->ace, sizeof(AVATARCACHEENTRY)); + ace_temp.hbmPic = 0; + + int result = CreateAvatarInCache(node->ace.hContact, &ace_temp, NULL); + + if (result == -2) + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)node->ace.hContact, 0); + if (szProto == NULL || Proto_NeedDelaysForAvatars(szProto)) + { + QueueAdd(node->ace.hContact); + } + else + { + if (FetchAvatarFor(node->ace.hContact, szProto) == GAIR_SUCCESS) + // Try yo create again + result = CreateAvatarInCache(node->ace.hContact, &ace_temp, NULL); + } + } + + if ((result == 1 && ace_temp.hbmPic != 0)) // Loaded + { + HBITMAP oldPic = node->ace.hbmPic; + + EnterCriticalSection(&cachecs); + CopyMemory(&node->ace, &ace_temp, sizeof(AVATARCACHEENTRY)); + node->loaded = TRUE; + LeaveCriticalSection(&cachecs); + if (oldPic) + DeleteObject(oldPic); + NotifyMetaAware(node->ace.hContact, node); + } + else if (result == 0 || result == -3) // Has no avatar + { + HBITMAP oldPic = node->ace.hbmPic; + + EnterCriticalSection(&cachecs); + CopyMemory(&node->ace, &ace_temp, sizeof(AVATARCACHEENTRY)); + node->loaded = FALSE; + node->mustLoad = 0; + LeaveCriticalSection(&cachecs); + if (oldPic) + DeleteObject(oldPic); + NotifyMetaAware(node->ace.hContact, node); + } + + mir_sleep(dwDelay); + } + else if (node->mustLoad < 0 && node->ace.hContact) { // delete this picture + HANDLE hContact = node->ace.hContact; + EnterCriticalSection(&cachecs); + node->mustLoad = 0; + node->loaded = 0; + if (node->ace.hbmPic) + DeleteObject(node->ace.hbmPic); + ZeroMemory(&node->ace, sizeof(AVATARCACHEENTRY)); + if (node->dwFlags & AVS_DELETENODEFOREVER) { + node->dwFlags &= ~AVS_DELETENODEFOREVER; + } else { + node->ace.hContact = hContact; + } + LeaveCriticalSection(&cachecs); + NotifyMetaAware(hContact, node, (AVATARCACHEENTRY *)GetProtoDefaultAvatar(hContact)); + } + // protect this by changes from the cache block allocator as it can cause inconsistencies while working + // on allocating a new block. + EnterCriticalSection(&alloccs); + node = node->pNextNode; + LeaveCriticalSection(&alloccs); + } + WaitForSingleObject(hLoaderEvent, INFINITE); + //_DebugTrace(0, "pic loader awake..."); + ResetEvent(hLoaderEvent); + } +} + +static int MetaChanged(WPARAM wParam, LPARAM lParam) +{ + if (wParam == 0 || g_shutDown) + return 0; + + AVATARCACHEENTRY *ace; + + HANDLE hContact = (HANDLE) wParam; + HANDLE hSubContact = GetContactThatHaveTheAvatar(hContact); + + // Get the node + struct CacheNode *node = FindAvatarInCache(hSubContact, TRUE); + if (node == NULL || !node->loaded) { + ace = (AVATARCACHEENTRY *)GetProtoDefaultAvatar(hSubContact); + QueueAdd(hSubContact); + } + else + ace = &node->ace; + + NotifyEventHooks(hEventChanged, (WPARAM)hContact, (LPARAM)ace); + return 0; +} + +static LIST arServices( 10 ); + +static int DestroyServicesAndEvents() +{ + UnhookEvent(hContactSettingChanged); + UnhookEvent(hProtoAckHook); + UnhookEvent(hUserInfoInitHook); + UnhookEvent(hOptInit); + UnhookEvent(hModulesLoaded); + UnhookEvent(hPresutdown); + UnhookEvent(hOkToExit); + UnhookEvent(hAccChanged); + + for ( int i=0; i < arServices.getCount(); i++ ) + DestroyServiceFunction( arServices[i] ); + + arServices.destroy(); + + DestroyHookableEvent(hEventChanged); + DestroyHookableEvent(hEventContactAvatarChanged); + DestroyHookableEvent(hMyAvatarChanged); + hEventChanged = 0; + hEventContactAvatarChanged = 0; + hMyAvatarChanged = 0; + UnhookEvent(hEventDeleted); + return 0; +} + +static void LoadDefaultInfo() +{ + protoPicCacheEntry* pce = new protoPicCacheEntry; + if (CreateAvatarInCache(0, pce, AVS_DEFAULT) != 1) + DBDeleteContactSetting(0, PPICT_MODULE, AVS_DEFAULT); + + pce->szProtoname = mir_strdup(AVS_DEFAULT); + pce->tszAccName = mir_tstrdup(TranslateT(AVS_DEFAULT)); + g_ProtoPictures.insert(pce); +} + +static void LoadProtoInfo( PROTOCOLDESCRIPTOR* proto ) +{ + if ( proto->type == PROTOTYPE_PROTOCOL && proto->cbSize == sizeof( *proto )) + { + char protoName[MAX_PATH]; + mir_snprintf(protoName, SIZEOF(protoName), "Global avatar for %s accounts", proto->szName); + TCHAR protoNameTmp[MAX_PATH]; + TCHAR *tszName = mir_a2t(proto->szName); + mir_sntprintf(protoNameTmp, SIZEOF(protoNameTmp), TranslateT("Global avatar for %s accounts"), tszName); + protoPicCacheEntry* pce = new protoPicCacheEntry; + if (CreateAvatarInCache(0, pce, protoName) != 1) + DBDeleteContactSetting(0, PPICT_MODULE, protoName); + + pce->szProtoname = mir_strdup(protoName); + pce->tszAccName = mir_tstrdup(protoNameTmp); + g_ProtoPictures.insert(pce); + mir_free(tszName); + } +} + +static void LoadAccountInfo( PROTOACCOUNT* acc ) +{ + protoPicCacheEntry* pce = new protoPicCacheEntry; + if ( CreateAvatarInCache(0, pce, acc->szModuleName ) != 1 ) + DBDeleteContactSetting(0, PPICT_MODULE, acc->szModuleName); + + pce->szProtoname = mir_strdup( acc->szModuleName ); + pce->tszAccName = mir_tstrdup( acc->tszAccountName ); + g_ProtoPictures.insert( pce ); + + pce = new protoPicCacheEntry; + CreateAvatarInCache((HANDLE)-1, pce, acc->szModuleName ); + pce->szProtoname = mir_strdup( acc->szModuleName ); + pce->tszAccName = mir_tstrdup( acc->tszAccountName ); + g_MyAvatars.insert( pce ); +} + +static int OnAccChanged(WPARAM wParam, LPARAM lParam) +{ + PROTOACCOUNT* pa = ( PROTOACCOUNT* )lParam; + + switch( wParam ) { + case PRAC_ADDED: + LoadAccountInfo( pa ); + break; + + case PRAC_REMOVED: + { + int idx; + protoPicCacheEntry tmp; + tmp.szProtoname = mir_strdup(pa->szModuleName); + if (( idx = g_ProtoPictures.getIndex( &tmp )) != -1 ) + g_ProtoPictures.remove( idx ); + if (( idx = g_MyAvatars.getIndex( &tmp )) != -1 ) + g_MyAvatars.remove( idx ); + } + break; + } + + return 0; +} + +static int ModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + int i; + DBVARIANT dbv = {0}; + TCHAR szEventName[100]; + int result = 0; + + InitPolls(); + + mir_sntprintf(szEventName, 100, _T("avs_loaderthread_%d"), GetCurrentThreadId()); + hLoaderEvent = CreateEvent(NULL, TRUE, FALSE, szEventName); + hLoaderThread = (HANDLE) mir_forkthread(PicLoader, 0); + SetThreadPriority(hLoaderThread, THREAD_PRIORITY_IDLE); + + // Folders plugin support + if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) + { + hMyAvatarsFolder = (HANDLE) FoldersRegisterCustomPathT("Avatars", "My Avatars", + MIRANDA_USERDATAT _T("\\Avatars")); + + hGlobalAvatarFolder = (HANDLE) FoldersRegisterCustomPathT("Avatars", "My Global Avatar Cache", + MIRANDA_USERDATAT _T("\\Avatars")); + } + + g_AvatarHistoryAvail = ServiceExists(MS_AVATARHISTORY_ENABLED); + + g_MetaAvail = ServiceExists(MS_MC_GETPROTOCOLNAME) ? TRUE : FALSE; + if (g_MetaAvail) { + g_szMetaName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0); + if (g_szMetaName == NULL) + g_MetaAvail = FALSE; + } + + PROTOACCOUNT **accs = NULL; + int accCount; + ProtoEnumAccounts( &accCount, &accs ); + + if ( fei != NULL ) + { + LoadDefaultInfo(); + PROTOCOLDESCRIPTOR** proto; + int protoCount; + CallService(MS_PROTO_ENUMPROTOS, ( WPARAM )&protoCount, ( LPARAM )&proto); + for ( i=0; i < protoCount; i++ ) + LoadProtoInfo( proto[i] ); + for(i = 0; i < accCount; i++) + LoadAccountInfo( accs[i] ); + } + + // Load global avatar + protoPicCacheEntry* pce = new protoPicCacheEntry; + CreateAvatarInCache((HANDLE)-1, pce, ""); + pce->szProtoname = mir_strdup(""); + g_MyAvatars.insert( pce ); + + hAccChanged = HookEvent(ME_PROTO_ACCLISTCHANGED, OnAccChanged); + hPresutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, ShutdownProc); + hOkToExit = HookEvent(ME_SYSTEM_OKTOEXIT, OkToExitProc); + hUserInfoInitHook = HookEvent(ME_USERINFO_INITIALISE, OnDetailsInit); + + return 0; +} + +static void ReloadMyAvatar(LPVOID lpParam) +{ + char *szProto = (char *)lpParam; + + mir_sleep(500); + for(int i = 0; !g_shutDown && i < g_MyAvatars.getCount(); i++) { + char *myAvatarProto = g_MyAvatars[i].szProtoname; + + if (szProto[0] == 0) { + // Notify to all possibles + if (lstrcmpA(myAvatarProto, szProto)) { + if (!ProtoServiceExists( myAvatarProto, PS_SETMYAVATAR)) + continue; + if (!Proto_IsAvatarsEnabled( myAvatarProto )) + continue; + } + + } else if (lstrcmpA(myAvatarProto, szProto)) { + continue; + } + + if (g_MyAvatars[i].hbmPic) + DeleteObject(g_MyAvatars[i].hbmPic); + + if (CreateAvatarInCache((HANDLE)-1, &g_MyAvatars[i], myAvatarProto) != -1) + NotifyEventHooks(hMyAvatarChanged, (WPARAM)myAvatarProto, (LPARAM)&g_MyAvatars[i]); + else + NotifyEventHooks(hMyAvatarChanged, (WPARAM)myAvatarProto, 0); + } + + free(lpParam); +} + +static INT_PTR ReportMyAvatarChanged(WPARAM wParam, LPARAM lParam) +{ + if (wParam == NULL) + return -1; + + char *proto = (char *) wParam; + + for(int i = 0; i < g_MyAvatars.getCount(); i++) { + if (g_MyAvatars[i].dwFlags & AVS_IGNORENOTIFY) + continue; + + if ( !lstrcmpA(g_MyAvatars[i].szProtoname, proto)) { + LPVOID lpParam = (void *)malloc(lstrlenA(g_MyAvatars[i].szProtoname) + 2); + strcpy((char *)lpParam, g_MyAvatars[i].szProtoname); + mir_forkthread(ReloadMyAvatar, lpParam); + return 0; + } + } + + return -2; +} + +static int ContactSettingChanged(WPARAM wParam, LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + + if (cws == NULL || g_shutDown) + return 0; + + if (wParam == 0) { + if (!strcmp(cws->szSetting, "AvatarFile") + || !strcmp(cws->szSetting, "PictObject") + || !strcmp(cws->szSetting, "AvatarHash") + || !strcmp(cws->szSetting, "AvatarSaved")) + { + ReportMyAvatarChanged((WPARAM) cws->szModule, 0); + } + return 0; + } + else if (g_MetaAvail && !strcmp(cws->szModule, g_szMetaName)) { + if (lstrlenA(cws->szSetting) > 6 && !strncmp(cws->szSetting, "Status", 5)) + MetaChanged(wParam, 0); + } + return 0; +} + +static int ContactDeleted(WPARAM wParam, LPARAM lParam) +{ + DeleteAvatarFromCache((HANDLE)wParam, TRUE); + + return 0; +} + +static int OptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = g_hInst; + odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY | ODPF_TCHAR; + odp.ptszGroup = LPGENT("Customize"); + odp.ptszTitle = LPGENT("Avatars"); + + odp.ptszTab = LPGENT("Protocols"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_PICTS); + odp.pfnDlgProc = DlgProcOptionsProtos; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); + + odp.ptszTab = LPGENT("Contact Avatars"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_AVATARS); + odp.pfnDlgProc = DlgProcOptionsAvatars; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); + + odp.ptszTab = LPGENT("Own Avatars"); + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_OWN); + odp.pfnDlgProc = DlgProcOptionsOwn; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); + + return 0; +} + +static int OkToExitProc(WPARAM wParam, LPARAM lParam) +{ + EnterCriticalSection(&cachecs); + g_shutDown = TRUE; + + DestroyServicesAndEvents(); + + LeaveCriticalSection(&cachecs); + + SetEvent(hLoaderEvent); + FreePolls(); + return 0; +} + +static int ShutdownProc(WPARAM wParam, LPARAM lParam) +{ + DeleteCriticalSection(&cachecs); + DeleteCriticalSection(&alloccs); + return 0; +} + +void InternalDrawAvatar(AVATARDRAWREQUEST *r, HBITMAP hbm, LONG bmWidth, LONG bmHeight, DWORD dwFlags) +{ + float dScale = 0; + int newHeight, newWidth; + HDC hdcAvatar; + HBITMAP hbmMem; + DWORD topoffset = 0, leftoffset = 0; + HRGN rgn = 0, oldRgn = 0; + int targetWidth = r->rcDraw.right - r->rcDraw.left; + int targetHeight = r->rcDraw.bottom - r->rcDraw.top; + BLENDFUNCTION bf = {0}; + + hdcAvatar = CreateCompatibleDC(r->hTargetDC); + hbmMem = (HBITMAP)SelectObject(hdcAvatar, hbm); + + if ((r->dwFlags & AVDRQ_DONTRESIZEIFSMALLER) && bmHeight <= targetHeight && bmWidth <= targetWidth) { + newHeight = bmHeight; + newWidth = bmWidth; + } + else if (bmHeight >= bmWidth) { + dScale = targetHeight / (float)bmHeight; + newHeight = targetHeight; + newWidth = (int) (bmWidth * dScale); + } + else { + dScale = targetWidth / (float)bmWidth; + newWidth = targetWidth; + newHeight = (int) (bmHeight * dScale); + } + + topoffset = targetHeight > newHeight ? (targetHeight - newHeight) / 2 : 0; + leftoffset = targetWidth > newWidth ? (targetWidth - newWidth) / 2 : 0; + + // create the region for the avatar border - use the same region for clipping, if needed. + + oldRgn = CreateRectRgn(0,0,1,1); + + if (GetClipRgn(r->hTargetDC, oldRgn) != 1) + { + DeleteObject(oldRgn); + oldRgn = NULL; + } + + if (r->dwFlags & AVDRQ_ROUNDEDCORNER) + rgn = CreateRoundRectRgn(r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, r->rcDraw.left + leftoffset + newWidth + 1, r->rcDraw.top + topoffset + newHeight + 1, 2 * r->radius, 2 * r->radius); + else + rgn = CreateRectRgn(r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, r->rcDraw.left + leftoffset + newWidth, r->rcDraw.top + topoffset + newHeight); + + ExtSelectClipRgn(r->hTargetDC, rgn, RGN_AND); + + bf.SourceConstantAlpha = r->alpha > 0 ? r->alpha : 255; + bf.AlphaFormat = dwFlags & AVS_PREMULTIPLIED ? AC_SRC_ALPHA : 0; + + if (!(r->dwFlags & AVDRQ_AERO)) + SetStretchBltMode(r->hTargetDC, HALFTONE); + //else + // FillRect(r->hTargetDC, &r->rcDraw, (HBRUSH)GetStockObject(BLACK_BRUSH)); + + if (r->dwFlags & AVDRQ_FORCEFASTALPHA && !(r->dwFlags & AVDRQ_AERO) && AvsAlphaBlend) { + AvsAlphaBlend( + r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, + hdcAvatar, 0, 0, bmWidth, bmHeight, bf); + } else { + if ((bf.SourceConstantAlpha == 255 && bf.AlphaFormat == 0 && !(r->dwFlags & AVDRQ_FORCEALPHA) && !(r->dwFlags & AVDRQ_AERO)) || !AvsAlphaBlend) { + StretchBlt(r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, hdcAvatar, 0, 0, bmWidth, bmHeight, SRCCOPY); + } else { + /* + * get around SUCKY AlphaBlend() rescaling quality... + */ + FIBITMAP *fb = fei->FI_CreateDIBFromHBITMAP(hbm); + FIBITMAP *fbResized = fei->FI_Rescale(fb, newWidth, newHeight, FILTER_BICUBIC); + HBITMAP hbmResized = fei->FI_CreateHBITMAPFromDIB(fbResized); + fei->FI_Unload(fb); + fei->FI_Unload(fbResized); + + HBITMAP hbmTempOld; + HDC hdcTemp = CreateCompatibleDC(r->hTargetDC); + hbmTempOld = (HBITMAP)SelectObject(hdcTemp, hbmResized); + + AvsAlphaBlend( + r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, + hdcTemp, 0, 0, newWidth, newHeight, bf); + + SelectObject(hdcTemp, hbmTempOld); + DeleteObject(hbmResized); + DeleteDC(hdcTemp); + } + + if ((r->dwFlags & AVDRQ_DRAWBORDER) && !((r->dwFlags & AVDRQ_HIDEBORDERONTRANSPARENCY) && (dwFlags & AVS_HASTRANSPARENCY))) { + HBRUSH br = CreateSolidBrush(r->clrBorder); + HBRUSH brOld = (HBRUSH)SelectObject(r->hTargetDC, br); + FrameRgn(r->hTargetDC, rgn, br, 1, 1); + SelectObject(r->hTargetDC, brOld); + DeleteObject(br); + } + + SelectClipRgn(r->hTargetDC, oldRgn); + DeleteObject(rgn); + if (oldRgn) DeleteObject(oldRgn); + + SelectObject(hdcAvatar, hbmMem); + DeleteDC(hdcAvatar); + } +} + +INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam) +{ + AVATARDRAWREQUEST *r = (AVATARDRAWREQUEST *)lParam; + AVATARCACHEENTRY *ace = NULL; + + if (fei == NULL || r == NULL || IsBadReadPtr((void *)r, sizeof(AVATARDRAWREQUEST))) + return 0; + + if (r->cbSize != sizeof(AVATARDRAWREQUEST)) + return 0; + + if (r->dwFlags & AVDRQ_PROTOPICT) { + if (r->szProto == NULL) + return 0; + + for(int i = 0; i < g_ProtoPictures.getCount(); i++) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if ( !lstrcmpA(p.szProtoname, r->szProto) && lstrlenA(r->szProto) == lstrlenA(p.szProtoname) && p.hbmPic != 0) { + ace = (AVATARCACHEENTRY *)&g_ProtoPictures[i]; + break; + } + } + } + else if (r->dwFlags & AVDRQ_OWNPIC) { + if (r->szProto == NULL) + return 0; + + if (r->szProto[0] == '\0' && DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) + return -1; + + ace = (AVATARCACHEENTRY *)GetMyAvatar(0, (LPARAM)r->szProto); + } + else + ace = (AVATARCACHEENTRY *)GetAvatarBitmap((WPARAM)r->hContact, 0); + + if (ace && (!(r->dwFlags & AVDRQ_RESPECTHIDDEN) || !(ace->dwFlags & AVS_HIDEONCLIST))) { + ace->t_lastAccess = time(NULL); + + if (ace->bmHeight == 0 || ace->bmWidth == 0 || ace->hbmPic == 0) + return 0; + + InternalDrawAvatar(r, ace->hbmPic, ace->bmWidth, ace->bmHeight, ace->dwFlags); + return 1; + } + + return 0; +} + +static int OnDetailsInit(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE) lParam; + if (hContact == NULL) + { + // User dialog + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.flags = ODPF_TCHAR; + odp.hIcon = g_hIcon; + odp.hInstance = g_hInst; + odp.pfnDlgProc = DlgProcAvatarProtoInfo; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROTO_AVATARS); + odp.ptszTitle = LPGENT("Avatar"); + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + else + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto == NULL || DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1)) + { + // Contact dialog + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.flags = ODPF_TCHAR; + odp.hIcon = g_hIcon; + odp.hInstance = g_hInst; + odp.pfnDlgProc = DlgProcAvatarUserInfo; + odp.position = -2000000000; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_USER_AVATAR); + odp.ptszTitle = LPGENT("Avatar"); + CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); + } + } + return 0; +} + +static int LoadAvatarModule() +{ + mir_getMMI ( &mmi ); + mir_getLI ( &li ); + mir_getLP( &pluginInfoEx ); + + init_mir_thread(); + + InitializeCriticalSection(&cachecs); + InitializeCriticalSection(&alloccs); + + hOptInit = HookEvent(ME_OPT_INITIALISE, OptInit); + hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); + hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged); + hEventDeleted = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); + hProtoAckHook = HookEvent(ME_PROTO_ACK, ProtocolAck); + + arServices.insert( CreateServiceFunction( MS_AV_GETAVATARBITMAP, GetAvatarBitmap )); + arServices.insert( CreateServiceFunction( MS_AV_PROTECTAVATAR, ProtectAvatar )); + arServices.insert( CreateServiceFunction( MS_AV_SETAVATAR, SetAvatar )); + arServices.insert( CreateServiceFunction( MS_AV_SETMYAVATAR, SetMyAvatar )); + arServices.insert( CreateServiceFunction( MS_AV_CANSETMYAVATAR, CanSetMyAvatar )); + arServices.insert( CreateServiceFunction( MS_AV_CONTACTOPTIONS, ContactOptions )); + arServices.insert( CreateServiceFunction( MS_AV_DRAWAVATAR, DrawAvatarPicture )); + arServices.insert( CreateServiceFunction( MS_AV_GETMYAVATAR, GetMyAvatar )); + arServices.insert( CreateServiceFunction( MS_AV_REPORTMYAVATARCHANGED, ReportMyAvatarChanged )); + arServices.insert( CreateServiceFunction( MS_AV_LOADBITMAP32, BmpFilterLoadBitmap32 )); + arServices.insert( CreateServiceFunction( MS_AV_SAVEBITMAP, BmpFilterSaveBitmap )); + arServices.insert( CreateServiceFunction( MS_AV_CANSAVEBITMAP, BmpFilterCanSaveBitmap )); + arServices.insert( CreateServiceFunction( MS_AV_RESIZEBITMAP, BmpFilterResizeBitmap )); + + #if defined( _UNICODE ) + arServices.insert( CreateServiceFunction( MS_AV_SETAVATARW, SetAvatarW )); + arServices.insert( CreateServiceFunction( MS_AV_SETMYAVATARW, SetMyAvatarW )); + #endif + + hEventChanged = CreateHookableEvent(ME_AV_AVATARCHANGED); + hEventContactAvatarChanged = CreateHookableEvent(ME_AV_CONTACTAVATARCHANGED); + hMyAvatarChanged = CreateHookableEvent(ME_AV_MYAVATARCHANGED); + + AllocCacheBlock(); + + HMODULE hDll; + if (hDll = GetModuleHandle(_T("gdi32"))) + AvsAlphaBlend = (BOOL (WINAPI *)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION)) GetProcAddress(hDll, "GdiAlphaBlend"); + if (AvsAlphaBlend == NULL && (hDll = LoadLibrary(_T("msimg32.dll")))) + AvsAlphaBlend = (BOOL (WINAPI *)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION)) GetProcAddress(hDll, "AlphaBlend"); + + TCHAR* tmpPath = Utils_ReplaceVarsT(_T("%miranda_userdata%")); + lstrcpyn(g_szDataPath, tmpPath, SIZEOF(g_szDataPath)-1); + mir_free(tmpPath); + g_szDataPath[MAX_PATH - 1] = 0; + _tcslwr(g_szDataPath); + + return 0; +} + +extern "C" BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) +{ + g_hInst = hInstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion) +{ + if (mirandaVersion < MIRANDA_VERSION_CORE) + return NULL; + return &pluginInfoEx; +} + +static const MUUID interfaces[] = { { 0xece29554, 0x1cf0, 0x41da, { 0x85, 0x82, 0xfb, 0xe8, 0x45, 0x5c, 0x6b, 0xec } }, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID * MirandaPluginInterfaces(void) +{ + return interfaces; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK * link) +{ + INT_PTR result = CALLSERVICE_NOTFOUND; + + pluginLink = link; + mir_getLP( &pluginInfoEx ); + + if (ServiceExists(MS_IMG_GETINTERFACE)) + result = CallService(MS_IMG_GETINTERFACE, FI_IF_VERSION, (LPARAM)&fei); + + if (fei == NULL || result != S_OK) { + MessageBox(0, TranslateT("Fatal error, image services not found. Avatar services will be disabled."), TranslateT("Avatar Service"), MB_OK); + return 1; + } + LoadACC(); + return LoadAvatarModule(); +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + struct CacheNode *pNode = g_Cache; + + while(pNode) { + //DeleteCriticalSection(&pNode->cs); + if (pNode->ace.hbmPic != 0) + DeleteObject(pNode->ace.hbmPic); + pNode = pNode->pNextNode; + } + + for(int i = 0; i < g_curBlock; i++) + free(g_cacheBlocks[i]); + free(g_cacheBlocks); + + g_ProtoPictures.destroy(); + g_MyAvatars.destroy(); + + CloseHandle(hLoaderEvent); + DeleteCriticalSection(&alloccs); + DeleteCriticalSection(&cachecs); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +protoPicCacheEntry::~protoPicCacheEntry() +{ + if ( hbmPic != 0 ) + DeleteObject( hbmPic ); + mir_free( szProtoname ); + mir_free( tszAccName ); +} + +void protoPicCacheEntry::clear() +{ + if (hbmPic != 0) + DeleteObject(hbmPic); + + memset(this, 0, sizeof(avatarCacheEntry)); +} + +/* +wParam=(int *)max width of avatar - will be set (-1 for no max) +lParam=(int *)max height of avatar - will be set (-1 for no max) +return=0 for sucess +*/ +#define PS_GETMYAVATARMAXSIZE "/GetMyAvatarMaxSize" + +/* +wParam=0 +lParam=0 +return=One of PIP_SQUARE, PIP_FREEPROPORTIONS +*/ +#define PIP_FREEPROPORTIONS 0 +#define PIP_SQUARE 1 +#define PS_GETMYAVATARIMAGEPROPORTION "/GetMyAvatarImageProportion" + +/* +wParam = 0 +lParam = PA_FORMAT_* // avatar format +return = 1 (supported) or 0 (not supported) +*/ +#define PS_ISAVATARFORMATSUPPORTED "/IsAvatarFormatSupported" + + + +BOOL Proto_IsAvatarsEnabled(const char *proto) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + return CallProtoService(proto, PS_GETAVATARCAPS, AF_ENABLED, 0); + + return TRUE; +} + +BOOL Proto_IsAvatarFormatSupported(const char *proto, int format) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + return CallProtoService(proto, PS_GETAVATARCAPS, AF_FORMATSUPPORTED, format); + + if (ProtoServiceExists(proto, PS_ISAVATARFORMATSUPPORTED)) + return CallProtoService(proto, PS_ISAVATARFORMATSUPPORTED, 0, format); + + if (format >= PA_FORMAT_SWF) + return FALSE; + + return TRUE; +} + +int Proto_AvatarImageProportion(const char *proto) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + return CallProtoService(proto, PS_GETAVATARCAPS, AF_PROPORTION, 0); + + if (ProtoServiceExists(proto, PS_GETMYAVATARIMAGEPROPORTION)) + return CallProtoService(proto, PS_GETMYAVATARIMAGEPROPORTION, 0, 0); + + return 0; +} + +void Proto_GetAvatarMaxSize(const char *proto, int *width, int *height) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + { + POINT maxSize; + CallProtoService(proto, PS_GETAVATARCAPS, AF_MAXSIZE, (LPARAM) &maxSize); + *width = maxSize.y; + *height = maxSize.x; + } + else if (ProtoServiceExists(proto, PS_GETMYAVATARMAXSIZE)) + { + CallProtoService(proto, PS_GETMYAVATARMAXSIZE, (WPARAM) width, (LPARAM) height); + } + else + { + *width = 300; + *height = 300; + } + + if (*width < 0) + *width = 0; + else if (*width > 300) + *width = 300; + + if (*height < 0) + *height = 0; + else if (*height > 300) + *height = 300; +} + +BOOL Proto_NeedDelaysForAvatars(const char *proto) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + { + int ret = CallProtoService(proto, PS_GETAVATARCAPS, AF_DONTNEEDDELAYS, 0); + if (ret > 0) + return FALSE; + else + return TRUE; + } + + return TRUE; +} + +int Proto_GetAvatarMaxFileSize(const char *proto) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + return CallProtoService(proto, PS_GETAVATARCAPS, AF_MAXFILESIZE, 0); + + return 0; +} + +int Proto_GetDelayAfterFail(const char *proto) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + return CallProtoService(proto, PS_GETAVATARCAPS, AF_DELAYAFTERFAIL, 0); + + return 0; +} + +BOOL Proto_IsFetchingAlwaysAllowed(const char *proto) +{ + if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) + return CallProtoService(proto, PS_GETAVATARCAPS, AF_FETCHALWAYS, 0); + + return FALSE; +} diff --git a/plugins/AVS/mir_thread.cpp b/plugins/AVS/mir_thread.cpp new file mode 100644 index 0000000000..d12a0c9731 --- /dev/null +++ b/plugins/AVS/mir_thread.cpp @@ -0,0 +1,50 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#include "commonheaders.h" + + +BOOL g_shutDown = FALSE; +static HANDLE hShutdownEvent = NULL; +static HANDLE hOkToExit = NULL; + + +static int OkToExitProc(WPARAM wParam, LPARAM lParam) +{ + g_shutDown = TRUE; + SetEvent(hShutdownEvent); + CloseHandle(hShutdownEvent); + UnhookEvent(hOkToExit); + return 0; +} + + +void init_mir_thread() +{ + hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + hOkToExit = HookEvent(ME_SYSTEM_OKTOEXIT, OkToExitProc); +} + + +void mir_sleep(int time) +{ + if (!g_shutDown) + WaitForSingleObject(hShutdownEvent, time); +} diff --git a/plugins/AVS/mir_thread.h b/plugins/AVS/mir_thread.h new file mode 100644 index 0000000000..0f4f20fe8e --- /dev/null +++ b/plugins/AVS/mir_thread.h @@ -0,0 +1,49 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __MIR_THREAD_H__ +# define __MIR_THREAD_H__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +void init_mir_thread(); + + +// This variable need to be constantly checked against and the thread function must exit +// when this is true +extern BOOL g_shutDown; + +void mir_sleep(int time); + + + + + + +#ifdef __cplusplus +} +#endif + +#endif // __MIR_THREAD_H__ diff --git a/plugins/AVS/options.cpp b/plugins/AVS/options.cpp new file mode 100644 index 0000000000..58502a9655 --- /dev/null +++ b/plugins/AVS/options.cpp @@ -0,0 +1,1147 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +#define DM_SETAVATARNAME (WM_USER + 10) +#define DM_REALODAVATAR (WM_USER + 11) +#define DM_AVATARCHANGED (WM_USER + 12) +#define DM_PROTOCOLCHANGED (WM_USER + 13) + +extern int _DebugPopup(HANDLE hContact, const char *fmt, ...); +extern INT_PTR SetAvatar(WPARAM wParam, LPARAM lParam); +extern OBJLIST g_ProtoPictures; +extern HANDLE hEventChanged; +extern HINSTANCE g_hInst; +extern HICON g_hIcon; + +extern int CreateAvatarInCache(HANDLE hContact, struct avatarCacheEntry *ace, char *szProto); +extern INT_PTR ProtectAvatar(WPARAM wParam, LPARAM lParam); +extern int SetAvatarAttribute(HANDLE hContact, DWORD attrib, int mode); +extern int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist = FALSE, int pa_format = 0); +extern void DeleteAvatarFromCache(HANDLE, BOOL); +extern HBITMAP LoadPNG(struct avatarCacheEntry *ace, char *szFilename); +extern HANDLE GetContactThatHaveTheAvatar(HANDLE hContact, int locked = -1); + +extern int ProtoServiceExists(const char *szModule,const char *szService); +extern BOOL Proto_IsAvatarsEnabled(const char *proto); +extern BOOL ScreenToClient(HWND hWnd, LPRECT lpRect); + +static BOOL dialoginit = TRUE; + +struct WindowData { + HANDLE hContact; + HANDLE hHook; +}; + +static void RemoveProtoPic(const char *szProto) +{ + DBDeleteContactSetting(NULL, PPICT_MODULE, szProto); + + if ( szProto == NULL ) + return; + + if ( !lstrcmpA(AVS_DEFAULT, szProto )) { + for (int i = 0; i < g_ProtoPictures.getCount(); i++) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if (p.szProtoname == NULL) + continue; + + p.clear(); + CreateAvatarInCache(0, &p, ( char* )p.szProtoname); + NotifyEventHooks(hEventChanged, 0, (LPARAM)&p); + } + return; + } + + if (strstr(szProto, "Global avatar for")) { + char szProtoname[MAX_PATH] = {0}; + lstrcpynA(szProtoname, szProto, lstrlenA(szProto)- lstrlenA("accounts")); + lstrcpyA(szProtoname, strrchr(szProtoname, ' ') + 1); + for (int i = 0; i < g_ProtoPictures.getCount(); i++) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + + PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)p.szProtoname); + if (pdescr == NULL && lstrcmpA(p.szProtoname, szProto)) + continue; + + if (!lstrcmpA(p.szProtoname, szProto) || !lstrcmpA(pdescr->szProtoName, szProtoname)) { + if (p.szProtoname == NULL) + continue; + + p.clear(); + CreateAvatarInCache(0, &p, ( char* )p.szProtoname); + NotifyEventHooks( hEventChanged, 0, (LPARAM)&p ); + } + } + return; + } + + for (int i = 0; i < g_ProtoPictures.getCount(); i++) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if ( !lstrcmpA( p.szProtoname, szProto )) { + p.clear(); + NotifyEventHooks( hEventChanged, 0, (LPARAM)&p ); + } + } +} + +static void SetProtoPic(char *szProto) +{ + TCHAR FileName[MAX_PATH]; + OPENFILENAME ofn={0}; + TCHAR filter[256]; + + filter[0] = '\0'; + CallService(MS_UTILS_GETBITMAPFILTERSTRINGST, SIZEOF(filter), ( LPARAM )filter); + + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.lpstrFilter = filter; + ofn.hwndOwner=0; + ofn.lpstrFile = FileName; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.Flags=OFN_HIDEREADONLY; + ofn.lpstrInitialDir = _T("."); + *FileName = '\0'; + ofn.lpstrDefExt = _T(""); + if ( GetOpenFileName( &ofn )) { + HANDLE hFile; + + if ((hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) + return; + + CloseHandle(hFile); + + TCHAR szNewPath[MAX_PATH]; + AVS_pathToRelative(FileName, szNewPath); + DBWriteContactSettingTString(NULL, PPICT_MODULE, szProto, szNewPath); + + if (!lstrcmpA(AVS_DEFAULT, szProto)) { + for ( int i = 0; i < g_ProtoPictures.getCount(); i++ ) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if (lstrlenA(p.szProtoname) != 0) { + if (p.hbmPic == 0) { + CreateAvatarInCache(0, &p, ( char* )szProto); + NotifyEventHooks(hEventChanged, 0, (LPARAM)&p); + } + } + } + } + else if (strstr(szProto, "Global avatar for")) { + char szProtoname[MAX_PATH] = {0}; + lstrcpynA(szProtoname, szProto, lstrlenA(szProto)- lstrlenA("accounts")); + lstrcpyA(szProtoname, strrchr(szProtoname, ' ') + 1); + for (int i = 0; i < g_ProtoPictures.getCount(); i++) { + PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)g_ProtoPictures[i].szProtoname); + if (pdescr == NULL && lstrcmpA(g_ProtoPictures[i].szProtoname, szProto)) + continue; + + if (!lstrcmpA(g_ProtoPictures[i].szProtoname, szProto) || !lstrcmpA(pdescr->szProtoName, szProtoname)) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if (lstrlenA(p.szProtoname) != 0) { + if (p.hbmPic == 0) { + CreateAvatarInCache(0, &p, ( char* )szProto); + NotifyEventHooks(hEventChanged, 0, (LPARAM)&p); + } + } + } + } + } + else { + for (int i = 0; i < g_ProtoPictures.getCount(); i++) { + protoPicCacheEntry& p = g_ProtoPictures[i]; + if ( lstrlenA(p.szProtoname) == 0) + break; + + if (!strcmp(p.szProtoname, szProto) && lstrlenA(p.szProtoname) == lstrlenA(szProto)) { + if (p.hbmPic != 0) + DeleteObject(p.hbmPic); + ZeroMemory(&p, sizeof(avatarCacheEntry)); + CreateAvatarInCache(0, &p, ( char* )szProto); + NotifyEventHooks(hEventChanged, 0, (LPARAM)&p ); + break; + } + } + } + } +} + +static char* g_selectedProto; + +INT_PTR CALLBACK DlgProcOptionsAvatars(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_SHOWWARNINGS, DBGetContactSettingByte(0, AVS_MODULE, "warnings", 0)); + CheckDlgButton(hwndDlg, IDC_MAKE_GRAYSCALE, DBGetContactSettingByte(0, AVS_MODULE, "MakeGrayscale", 0)); + CheckDlgButton(hwndDlg, IDC_MAKE_TRANSPARENT_BKG, DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0)); + CheckDlgButton(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL, DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", 0)); + + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2)); + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5)); + + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10)); + { + BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL), enabled); + } + + return TRUE; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_BKG_NUM_POINTS || LOWORD(wParam) == IDC_BKG_COLOR_DIFFERENCE) + && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) + return FALSE; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_MAKE_TRANSPARENT_BKG: + { + BOOL transp_enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL), transp_enabled); + break; + } + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, AVS_MODULE, "warnings", IsDlgButtonChecked(hwndDlg, IDC_SHOWWARNINGS) ? 1 : 0); + DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeGrayscale", IsDlgButtonChecked(hwndDlg, IDC_MAKE_GRAYSCALE) ? 1 : 0); + DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeTransparentBkg", IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG) ? 1 : 0); + DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL) ? 1 : 0); + DBWriteContactSettingWord(NULL, AVS_MODULE, "TranspBkgNumPoints", (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, AVS_MODULE, "TranspBkgColorDiff", (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_GETPOS, 0, 0)); + } } + break; + } + return FALSE; +} + +INT_PTR CALLBACK DlgProcOptionsOwn(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_MAKE_MY_AVATARS_TRANSP, DBGetContactSettingByte(0, AVS_MODULE, "MakeMyAvatarsTransparent", 0)); + CheckDlgButton(hwndDlg, IDC_SET_MAKE_SQUARE, DBGetContactSettingByte(0, AVS_MODULE, "SetAllwaysMakeSquare", 0)); + + return TRUE; + + case WM_COMMAND: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeMyAvatarsTransparent", IsDlgButtonChecked(hwndDlg, IDC_MAKE_MY_AVATARS_TRANSP) ? 1 : 0); + DBWriteContactSettingByte(NULL, AVS_MODULE, "SetAllwaysMakeSquare", IsDlgButtonChecked(hwndDlg, IDC_SET_MAKE_SQUARE) ? 1 : 0); + } } + break; + } + return FALSE; +} + +static char* GetProtoFromList(HWND hwndDlg, int iItem) +{ + LVITEM item; + item.mask = LVIF_PARAM; + item.iItem = iItem; + if ( !ListView_GetItem( GetDlgItem(hwndDlg, IDC_PROTOCOLS), &item )) + return NULL; + + protoPicCacheEntry* pce = ( protoPicCacheEntry* )item.lParam; + return ( pce == NULL ) ? NULL : pce->szProtoname; +} + +INT_PTR CALLBACK DlgProcOptionsProtos(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); + HWND hwndChoosePic = GetDlgItem(hwndDlg, IDC_SETPROTOPIC); + HWND hwndRemovePic = GetDlgItem(hwndDlg, IDC_REMOVEPROTOPIC); + + switch (msg) { + case WM_INITDIALOG: + { + LVITEM item = {0}; + LVCOLUMN lvc = {0}; + UINT64 newItem = 0; + + dialoginit = TRUE; + TranslateDialogDefault(hwndDlg); + ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); + lvc.mask = LVCF_FMT; + lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; + ListView_InsertColumn(hwndList, 0, &lvc); + + item.mask = LVIF_TEXT | LVIF_PARAM; + item.iItem = 1000; + for (int i = 0; i < g_ProtoPictures.getCount(); i++ ) { + item.lParam = ( LPARAM )&g_ProtoPictures[i]; + item.pszText = g_ProtoPictures[i].tszAccName; + newItem = ListView_InsertItem(hwndList, &item); + if (newItem >= 0) + ListView_SetCheckState(hwndList, newItem, + DBGetContactSettingByte(NULL, AVS_MODULE, g_ProtoPictures[i].szProtoname, 1) ? TRUE : FALSE); + } + ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); + ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); + EnableWindow(hwndChoosePic, FALSE); + EnableWindow(hwndRemovePic, FALSE); + + dialoginit = FALSE; + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_SETPROTOPIC: + case IDC_REMOVEPROTOPIC: + { + int iItem = ListView_GetSelectionMark(hwndList); + char* szProto = GetProtoFromList(hwndDlg, iItem); + if ( szProto ) { + if (LOWORD(wParam) == IDC_SETPROTOPIC) + SetProtoPic( szProto ); + else + RemoveProtoPic( szProto ); + + NMHDR nm = { hwndList, IDC_PROTOCOLS, NM_CLICK }; + SendMessage(hwndDlg, WM_NOTIFY, 0, (LPARAM)&nm); + } + break; + } + } + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + + if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_PROTOPIC) { + AVATARDRAWREQUEST avdrq = {0}; + avdrq.cbSize = sizeof(avdrq); + avdrq.hTargetDC = dis->hDC; + avdrq.dwFlags |= AVDRQ_PROTOPICT; + avdrq.szProto = g_selectedProto; + GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw); + CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq); + } + return TRUE; + } + + case WM_NOTIFY: + if (dialoginit) + break; + + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_PROTOCOLS: + switch (((LPNMHDR) lParam)->code) { + case LVN_KEYDOWN: + { + NMLVKEYDOWN* ptkd = (NMLVKEYDOWN*)lParam; + if (ptkd&&ptkd->wVKey==VK_SPACE&&ListView_GetSelectedCount(ptkd->hdr.hwndFrom)==1) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case LVN_ITEMCHANGED: + { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_PROTOCOLS)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK)) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case NM_CLICK: + { + EnableWindow(hwndChoosePic, TRUE); + EnableWindow(hwndRemovePic, TRUE); + + int iItem = ListView_GetSelectionMark(hwndList); + g_selectedProto = GetProtoFromList(hwndDlg, iItem); + if ( g_selectedProto ) { + DBVARIANT dbv = {0}; + if (!DBGetContactSettingTString(NULL, PPICT_MODULE, g_selectedProto, &dbv)) + { + if (!AVS_pathIsAbsolute(dbv.ptszVal)) + { + TCHAR szFinalPath[MAX_PATH]; + mir_sntprintf(szFinalPath, SIZEOF(szFinalPath), _T("%%miranda_path%%\\%s"), dbv.ptszVal); + SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, szFinalPath); + } + else SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, dbv.ptszVal); + + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); + DBFreeVariant(&dbv); + } + else { + SetWindowText(GetDlgItem(hwndDlg, IDC_PROTOAVATARNAME), _T("")); + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); + } + } + break; + } + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + for (int i = 0; i < ListView_GetItemCount(hwndList); i++) { + char *szProto = GetProtoFromList(hwndDlg, i); + + BOOL oldVal = DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1); + BOOL newVal = ListView_GetCheckState(hwndList, i); + + if (oldVal && !newVal) + { + HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact != NULL) + { + char* szContactProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szContactProto != NULL && !strcmp(szContactProto, szProto)) + DeleteAvatarFromCache(hContact, TRUE); + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + } + + if (newVal) + DBWriteContactSettingByte(NULL, AVS_MODULE, szProto, 1); + else + DBWriteContactSettingByte(NULL, AVS_MODULE, szProto, 0); + } + } + } + } + break; + } + return FALSE; +} + +void LoadTransparentData(HWND hwndDlg, HANDLE hContact) +{ + CheckDlgButton(hwndDlg, IDC_MAKETRANSPBKG, DBGetContactSettingByte(hContact, "ContactPhoto", "MakeTransparentBkg", DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0))); + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5))); + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgColorDiff", DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10))); + + BOOL transp_enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), transp_enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), transp_enabled); +} + +void SaveTransparentData(HWND hwndDlg, HANDLE hContact) +{ + BOOL transp = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); + if (DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0) == transp) + DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); + else + DBWriteContactSettingByte(hContact, "ContactPhoto", "MakeTransparentBkg", transp); + + WORD tmp = (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_GETPOS, 0, 0); + if (DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5) == tmp) + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); + else + DBWriteContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", tmp); + + tmp = (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_GETPOS, 0, 0); + if (DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10) == tmp) + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); + else + DBWriteContactSettingWord(hContact, "ContactPhoto", "TranspBkgColorDiff", tmp); +} + +void SaveTransparentData(HWND hwndDlg, HANDLE hContact, BOOL locked) +{ + SaveTransparentData(hwndDlg, hContact); + + HANDLE tmp = GetContactThatHaveTheAvatar(hContact, locked); + if (tmp != hContact) + SaveTransparentData(hwndDlg, tmp); +} + +INT_PTR CALLBACK DlgProcAvatarOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact; + struct WindowData *dat = (struct WindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + if (dat) + hContact = dat->hContact; + + switch(msg) { + case WM_INITDIALOG: + { + TCHAR szTitle[512]; + TCHAR *szNick = NULL; + struct WindowData *dat = (struct WindowData *)malloc(sizeof(struct WindowData)); + + if (dat) + dat->hContact = (HANDLE)lParam; + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + hContact = (HANDLE)lParam; + TranslateDialogDefault(hwndDlg); + if (hContact) { + szNick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR); + mir_sntprintf(szTitle, 500, TranslateT("Set avatar options for %s"), szNick); + SetWindowText(hwndDlg, szTitle); + } + SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, FALSE); + CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_HIDEAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0) ? TRUE : FALSE); + + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), 0); + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2)); + + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), 0); + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + + LoadTransparentData(hwndDlg, GetContactThatHaveTheAvatar(hContact)); + dat->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwndDlg, DM_AVATARCHANGED); + SendMessage(hwndDlg, WM_SETICON, IMAGE_ICON, (LPARAM)g_hIcon); + } + return TRUE; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case ID_USE_DEFAULTS: + hContact = GetContactThatHaveTheAvatar(hContact); + + DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); + + LoadTransparentData(hwndDlg, hContact); + + SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); + break; + + case IDOK: + { + BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR); + int hidden = IsDlgButtonChecked(hwndDlg, IDC_HIDEAVATAR) ? 1 : 0; + SetAvatarAttribute(hContact, AVS_HIDEONCLIST, hidden); + if (hidden != DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0)) + DBWriteContactSettingByte(hContact, "ContactPhoto", "Hidden", hidden); + + if (!locked && DBGetContactSettingByte(hContact, "ContactPhoto", "NeedUpdate", 0)) + QueueAdd(hContact); + + // Continue to the cancel handle + } + + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + + case IDC_PROTECTAVATAR: + { + BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR); + ProtectAvatar((WPARAM)hContact, locked ? 1 : 0); + } + break; + + case IDC_CHANGE: + SetAvatar((WPARAM)hContact, 0); + SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); + CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); + break; + + case IDC_BKG_NUM_POINTS: + case IDC_BKG_COLOR_DIFFERENCE: + if (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) + break; + + case IDC_MAKETRANSPBKG: + { + BOOL enable = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enable); + + SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); + } + break; + + case IDC_RESET: + { + char *szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + DBVARIANT dbv = {0}; + + ProtectAvatar((WPARAM)hContact, 0); + if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { + if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { + DeleteFile(dbv.ptszVal); + DBFreeVariant(&dbv); + } + } + DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); + DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); + DBDeleteContactSetting(hContact, szProto, "AvatarHash"); + DBDeleteContactSetting(hContact, szProto, "AvatarSaved"); + DeleteAvatarFromCache(hContact, FALSE); + + QueueAdd(hContact); + + DestroyWindow(hwndDlg); + } + break; + + case IDC_DELETE: + { + DBVARIANT dbv = {0}; + ProtectAvatar((WPARAM)hContact, 0); + if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { + if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { + DeleteFile(dbv.ptszVal); + DBFreeVariant(&dbv); + } + } + DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); + DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); + DeleteAvatarFromCache(hContact, FALSE); + SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); + break; + } + } + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + + if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_PROTOPIC) { + AVATARDRAWREQUEST avdrq = {0}; + GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw); + + FillRect(dis->hDC, &avdrq.rcDraw, GetSysColorBrush(COLOR_BTNFACE)); + + avdrq.hContact = hContact; + avdrq.cbSize = sizeof(avdrq); + avdrq.hTargetDC = dis->hDC; + avdrq.dwFlags |= AVDRQ_DRAWBORDER; + avdrq.clrBorder = GetSysColor(COLOR_BTNTEXT); + avdrq.radius = 6; + if (!CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq)) + { + // Get text rectangle + RECT rc = avdrq.rcDraw; + rc.top += 10; + rc.bottom -= 10; + rc.left += 10; + rc.right -= 10; + + // Calc text size + RECT rc_ret = rc; + DrawText(dis->hDC, TranslateT("Contact has no avatar"), -1, &rc_ret, + DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT); + + // Calc needed size + rc.top += ((rc.bottom - rc.top) - (rc_ret.bottom - rc_ret.top)) / 2; + rc.bottom = rc.top + (rc_ret.bottom - rc_ret.top); + DrawText(dis->hDC, TranslateT("Contact has no avatar"), -1, &rc, + DT_WORDBREAK | DT_NOPREFIX | DT_CENTER); + } + + FrameRect(dis->hDC, &avdrq.rcDraw, GetSysColorBrush(COLOR_BTNSHADOW)); + } + return TRUE; + } + case DM_SETAVATARNAME: + { + TCHAR szFinalName[MAX_PATH]; + DBVARIANT dbv = {0}; + BYTE is_locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); + + szFinalName[0] = 0; + + if (is_locked && !DBGetContactSettingTString(hContact, "ContactPhoto", "Backup", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, szFinalName); + DBFreeVariant(&dbv); + } + else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "RFile", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, szFinalName); + DBFreeVariant(&dbv); + } + else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { + AVS_pathToAbsolute(dbv.ptszVal, szFinalName); + DBFreeVariant(&dbv); + } + szFinalName[MAX_PATH - 1] = 0; + SetDlgItemText(hwndDlg, IDC_AVATARNAME, szFinalName); + break; + } + + case DM_REALODAVATAR: + SaveTransparentData(hwndDlg, hContact, IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR)); + ChangeAvatar(hContact, TRUE); + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); + break; + + case DM_AVATARCHANGED: + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); + break; + + case WM_NCDESTROY: + if (dat) { + UnhookEvent(dat->hHook); + free(dat); + } + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + break; + } + return FALSE; +} + +INT_PTR CALLBACK DlgProcAvatarUserInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact; + struct WindowData *dat = (struct WindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + if (dat) + hContact = dat->hContact; + + switch(msg) { + case WM_INITDIALOG: + { + dat = (struct WindowData *) malloc(sizeof(struct WindowData)); + if (dat == NULL) + return FALSE; + dat->hContact = (HANDLE)lParam; + + HWND protopic = GetDlgItem(hwndDlg, IDC_PROTOPIC); + SendMessage(protopic, AVATAR_SETCONTACT, 0, (LPARAM) dat->hContact); + SendMessage(protopic, AVATAR_SETAVATARBORDERCOLOR, 0, (LPARAM) GetSysColor(COLOR_BTNSHADOW)); + SendMessage(protopic, AVATAR_SETNOAVATARTEXT, 0, (LPARAM) LPGENT("Contact has no avatar")); + SendMessage(protopic, AVATAR_RESPECTHIDDEN, 0, (LPARAM) FALSE); + SendMessage(protopic, AVATAR_SETRESIZEIFSMALLER, 0, (LPARAM) FALSE); + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); + hContact = (HANDLE)lParam; + TranslateDialogDefault(hwndDlg); + SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); + CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); + CheckDlgButton(hwndDlg, IDC_HIDEAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0) ? TRUE : FALSE); + + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), 0); + SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2)); + + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), 0); + SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + + LoadTransparentData(hwndDlg, GetContactThatHaveTheAvatar(hContact)); + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case ID_USE_DEFAULTS: + hContact = GetContactThatHaveTheAvatar(hContact); + + DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); + DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); + + LoadTransparentData(hwndDlg, hContact); + + SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); + break; + + case IDC_CHANGE: + SetAvatar((WPARAM)hContact, 0); + SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); + CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); + break; + + case IDC_HIDEAVATAR: + { + int hidden = IsDlgButtonChecked(hwndDlg, IDC_HIDEAVATAR) ? 1 : 0; + SetAvatarAttribute(hContact, AVS_HIDEONCLIST, hidden); + if (hidden != DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0)) + DBWriteContactSettingByte(hContact, "ContactPhoto", "Hidden", hidden); + break; + } + + case IDC_PROTECTAVATAR: + { + BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR); + SaveTransparentData(hwndDlg, hContact, locked); + ProtectAvatar((WPARAM)hContact, locked ? 1 : 0); + + break; + } + case IDC_BKG_NUM_POINTS: + case IDC_BKG_COLOR_DIFFERENCE: + if (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) + break; + case IDC_MAKETRANSPBKG: + { + BOOL enable = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enable); + EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enable); + + SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); + break; + } + case IDC_RESET: + { + char *szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + DBVARIANT dbv = {0}; + + ProtectAvatar((WPARAM)hContact, 0); + if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { + if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { + DeleteFile(dbv.ptszVal); + DBFreeVariant(&dbv); + } + } + DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); + DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); + DBDeleteContactSetting(hContact, szProto, "AvatarHash"); + DBDeleteContactSetting(hContact, szProto, "AvatarSaved"); + DeleteAvatarFromCache(hContact, FALSE); + + QueueAdd(hContact); + break; + } + case IDC_DELETE: + { + DBVARIANT dbv = {0}; + + ProtectAvatar((WPARAM)hContact, 0); + if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { + if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { + DeleteFile(dbv.ptszVal); + DBFreeVariant(&dbv); + } + } + DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); + DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); + DeleteAvatarFromCache(hContact, FALSE); + SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); + break; + } + } + break; + + case DM_REALODAVATAR: + SaveTransparentData(hwndDlg, hContact, IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR)); + ChangeAvatar(hContact, TRUE); + break; + + case WM_NCDESTROY: + if (dat) + free(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + break; + } + return FALSE; +} + +static char * GetSelectedProtocol(HWND hwndDlg) +{ + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); + + // Get selection + int iItem = ListView_GetSelectionMark(hwndList); + if (iItem < 0) + return NULL; + + // Get protocol name + LVITEM item = {0}; + item.mask = LVIF_PARAM; + item.iItem = iItem; + SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&item); + return ( char* ) item.lParam; +} + +static void EnableDisableControls(HWND hwndDlg, char *proto) +{ + if (IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) + { + if (proto == NULL) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); + } + else + { + if (!ProtoServiceExists(proto, PS_SETMYAVATAR)) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE); + + int width, height; + SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_GETUSEDSPACE, (WPARAM) &width, (LPARAM) &height); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), (LPARAM) width != 0 || height != 0); + } + } + } + else + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE); + + if (DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); + } + else + { + int width, height; + SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_GETUSEDSPACE, (WPARAM) &width, (LPARAM) &height); + EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), (LPARAM) width != 0 || height != 0); + } + } +} + +static void OffsetWindow(HWND parent, HWND hwnd, int dx, int dy) +{ + RECT rc; + GetWindowRect(hwnd, &rc); + ScreenToClient(parent, &rc); + OffsetRect(&rc, dx, dy); + MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); +} + +static void EnableDisableProtocols(HWND hwndDlg, BOOL init) +{ + int diff = 147; // Pre-calc + BOOL perProto = IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO); + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); + + if (perProto) + { + if (!init && !IsWindowVisible(hwndList)) + { + // Show list of protocols + ShowWindow(hwndList, SW_SHOW); + + // Move controls + OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_PROTOPIC), diff, 0); + OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_CHANGE), diff, 0); + OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_DELETE), diff, 0); + } + + char * proto = GetSelectedProtocol(hwndDlg); + if (proto == NULL) + { + ListView_SetItemState(hwndList, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x0F); + } + else + { + SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, (LPARAM) proto); + EnableDisableControls(hwndDlg, proto); + } + } + else + { + if (init || IsWindowVisible(hwndList)) + { + // Show list of protocols + ShowWindow(hwndList, SW_HIDE); + + // Move controls + OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_PROTOPIC), -diff, 0); + OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_CHANGE), -diff, 0); + OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_DELETE), -diff, 0); + } + + SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, NULL); + } +} + +INT_PTR CALLBACK DlgProcAvatarProtoInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + HWND protopic = GetDlgItem(hwndDlg, IDC_PROTOPIC); + SendMessage(protopic, AVATAR_SETAVATARBORDERCOLOR, 0, (LPARAM) GetSysColor(COLOR_BTNSHADOW)); + SendMessage(protopic, AVATAR_SETNOAVATARTEXT, 0, (LPARAM) LPGENT("No avatar")); + SendMessage(protopic, AVATAR_SETRESIZEIFSMALLER, 0, (LPARAM) FALSE); + + HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); + ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_SUBITEMIMAGES); + + HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus()? ILC_COLOR32 : ILC_COLOR16), 4, 0); + ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); + + LVCOLUMN lvc = {0}; + lvc.mask = LVCF_FMT; + lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; + ListView_InsertColumn(hwndList, 0, &lvc); + + LVITEM item = {0}; + item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + item.iItem = 1000; + + // List protocols + PROTOACCOUNT **accs; + int i, count, num = 0; + + ProtoEnumAccounts( &count, &accs ); + for (i = 0; i < count; i++) + { + if ( !ProtoServiceExists( accs[i]->szModuleName, PS_GETMYAVATAR)) + continue; + + if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName )) + continue; + + ImageList_AddIcon(hIml, LoadSkinnedProtoIcon( accs[i]->szModuleName, ID_STATUS_ONLINE)); + item.pszText = accs[i]->tszAccountName; + item.iImage = num; + item.lParam = (LPARAM)accs[i]->szModuleName; + + ListView_InsertItem(hwndList, &item); + num++; + } + + ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); + ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); + + // Check if should show per protocol avatars + CheckDlgButton(hwndDlg, IDC_PER_PROTO, DBGetContactSettingByte(NULL, AVS_MODULE, "PerProtocolUserAvatars", 1)); + EnableDisableProtocols(hwndDlg, TRUE); + } + break; + + case WM_NOTIFY: + { + LPNMHDR nm = (LPNMHDR) lParam; + switch(nm->idFrom) { + case IDC_PROTOCOLS: + switch (nm->code) { + case LVN_ITEMCHANGED: + { + LPNMLISTVIEW li = (LPNMLISTVIEW) nm; + if (li->uNewState & LVIS_SELECTED) + { + SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, li->lParam); + EnableDisableControls(hwndDlg, ( char* ) li->lParam); + } + } + break; + } + break; + + case IDC_PROTOPIC: + switch (nm->code) { + case NM_AVATAR_CHANGED: + EnableDisableControls(hwndDlg, GetSelectedProtocol(hwndDlg)); + break; + } + break; + } + break; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDC_CHANGE: + if (!IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) + avSetMyAvatar(NULL, NULL); + else { + char *proto = GetSelectedProtocol(hwndDlg); + if (proto != NULL) + avSetMyAvatar(proto, NULL); + } + break; + + case IDC_DELETE: + if (!IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) { + if (MessageBox(hwndDlg, TranslateT("Are you sure you want to remove your avatar?"), TranslateT("Global Avatar"), MB_YESNO) == IDYES) + avSetMyAvatar(NULL, _T("")); + } + else { + char *proto = GetSelectedProtocol(hwndDlg); + if (proto == NULL) + break; + + char description[256]; + CallProtoService(proto, PS_GETNAME, SIZEOF(description),(LPARAM) description); + TCHAR *descr = mir_a2t(description); + if (MessageBox(hwndDlg, TranslateT("Are you sure you want to remove your avatar?"), descr, MB_YESNO) == IDYES) + avSetMyAvatar(proto, _T("")); + mir_free(descr); + } + break; + + case IDC_PER_PROTO: + DBWriteContactSettingByte(NULL, AVS_MODULE, "PerProtocolUserAvatars", IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO) ? 1 : 0); + EnableDisableProtocols(hwndDlg, FALSE); + break; + } + break; + } + return FALSE; +} diff --git a/plugins/AVS/poll.cpp b/plugins/AVS/poll.cpp new file mode 100644 index 0000000000..32553a9c33 --- /dev/null +++ b/plugins/AVS/poll.cpp @@ -0,0 +1,319 @@ +/* +Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +/* +It has 1 queue: +A queue to request items. One request is done at a time, REQUEST_WAIT_TIME miliseconts after it has beeing fired + ACKRESULT_STATUS. This thread only requests the avatar (and maybe add it to the cache queue) +*/ + +#define REQUEST_WAIT_TIME 3000 + +// Time to wait before re-requesting an avatar that failed +#define REQUEST_FAIL_WAIT_TIME (3 * 60 * 60 * 1000) + +// Time to wait before re-requesting an avatar that received an wait for +#define REQUEST_WAITFOR_WAIT_TIME (30 * 60 * 1000) + +// Number of mileseconds the threads wait until take a look if it is time to request another item +#define POOL_DELAY 1000 + +// Number of mileseconds the threads wait after a GAIR_WAITFOR is returned +#define REQUEST_DELAY 18000 + + +// Prototypes /////////////////////////////////////////////////////////////////////////// + +static void RequestThread(void *vParam); + +extern HANDLE hShutdownEvent; +extern char *g_szMetaName; +extern int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist = FALSE, int pa_format = 0); +extern int DeleteAvatar(HANDLE hContact); +extern void MakePathRelative(HANDLE hContact, TCHAR *path); +int Proto_GetDelayAfterFail(const char *proto); +BOOL Proto_IsFetchingAlwaysAllowed(const char *proto); + +struct CacheNode *FindAvatarInCache(HANDLE hContact, BOOL add, BOOL findAny = FALSE); + +extern HANDLE hEventContactAvatarChanged; +extern BOOL g_AvatarHistoryAvail; +extern FI_INTERFACE *fei; + +#ifdef _DEBUG +int _DebugTrace(const char *fmt, ...); +int _DebugTrace(HANDLE hContact, const char *fmt, ...); +#endif + +// Functions //////////////////////////////////////////////////////////////////////////// + +// Items with higher priority at end +static int QueueSortItems( const QueueItem* i1, const QueueItem* i2) +{ + return i2->check_time - i1->check_time; +} + +static OBJLIST queue( 20, QueueSortItems ); +static CRITICAL_SECTION cs; +static int waitTime; + +void InitPolls() +{ + waitTime = REQUEST_WAIT_TIME; + InitializeCriticalSection( &cs ); + + // Init request queue + mir_forkthread(RequestThread, NULL); +} + +void FreePolls() +{ +} + +// Return true if this protocol can have avatar requested +static BOOL PollProtocolCanHaveAvatar(const char *szProto) +{ + int pCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0); + int status = CallProtoService(szProto, PS_GETSTATUS, 0, 0); + return (pCaps & PF4_AVATARS) + && (g_szMetaName == NULL || strcmp(g_szMetaName, szProto)) + && ((status > ID_STATUS_OFFLINE && status != ID_STATUS_INVISIBLE) || Proto_IsFetchingAlwaysAllowed(szProto)); +} + +// Return true if this protocol has to be checked +static BOOL PollCheckProtocol(const char *szProto) +{ + return DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1); +} + +// Return true if this contact can have avatar requested +static BOOL PollContactCanHaveAvatar(HANDLE hContact, const char *szProto) +{ + int status = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); + return (Proto_IsFetchingAlwaysAllowed(szProto) || status != ID_STATUS_OFFLINE) + && !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) + && DBGetContactSettingByte(hContact, "CList", "ApparentMode", 0) != ID_STATUS_OFFLINE; +} + +// Return true if this contact has to be checked +static BOOL PollCheckContact(HANDLE hContact, const char *szProto) +{ + return !DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) + && FindAvatarInCache(hContact, FALSE, TRUE) != NULL; +} + +static void QueueRemove(HANDLE hContact) +{ + EnterCriticalSection(&cs); + + for (int i = queue.getCount()-1 ; i >= 0 ; i-- ) { + QueueItem& item = queue[i]; + if (item.hContact == hContact) + queue.remove(i); + } + + LeaveCriticalSection(&cs); +} + +static void QueueAdd(HANDLE hContact, int waitTime) +{ + if(fei == NULL) + return; + + EnterCriticalSection(&cs); + + // Only add if not exists yet + int i; + for (i = queue.getCount()-1; i >= 0; i--) + if ( queue[i].hContact == hContact) + break; + + if (i < 0) { + QueueItem *item = new QueueItem; + if (item != NULL) { + item->hContact = hContact; + item->check_time = GetTickCount() + waitTime; + queue.insert(item); + } } + + LeaveCriticalSection(&cs); +} + +// Add an contact to a queue +void QueueAdd(HANDLE hContact) +{ + QueueAdd(hContact, waitTime); +} + +void ProcessAvatarInfo(HANDLE hContact, int type, PROTO_AVATAR_INFORMATIONT *pai, const char *szProto) +{ + QueueRemove(hContact); + + if (type == GAIR_SUCCESS) + { + if (pai == NULL) + return; + + // Fix settings in DB + DBDeleteContactSetting(hContact, "ContactPhoto", "NeedUpdate"); + DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); + if (!DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0)) + DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); + DBWriteContactSettingTString(hContact, "ContactPhoto", "File", pai->filename); + DBWriteContactSettingWord(hContact, "ContactPhoto", "Format", pai->format); + + if (pai->format == PA_FORMAT_PNG || pai->format == PA_FORMAT_JPEG + || pai->format == PA_FORMAT_ICON || pai->format == PA_FORMAT_BMP + || pai->format == PA_FORMAT_GIF) + { + // We can load it! + MakePathRelative(hContact, pai->filename); + ChangeAvatar(hContact, TRUE, TRUE, pai->format); + } + else + { + // As we can't load it, notify but don't load + ChangeAvatar(hContact, FALSE, TRUE, pai->format); + } + } + else if (type == GAIR_NOAVATAR) + { + DBDeleteContactSetting(hContact, "ContactPhoto", "NeedUpdate"); + + if (DBGetContactSettingByte(NULL, AVS_MODULE, "RemoveAvatarWhenContactRemoves", 1)) + { + // Delete settings + DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); + if (!DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0)) + DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); + DBDeleteContactSetting(hContact, "ContactPhoto", "File"); + DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); + + // Fix cache + ChangeAvatar(hContact, FALSE, TRUE, 0); + } + } + else if (type == GAIR_FAILED) + { + int wait = Proto_GetDelayAfterFail(szProto); + if (wait > 0) + { + // Reschedule to request after needed time (and avoid requests before that) + EnterCriticalSection(&cs); + QueueRemove(hContact); + QueueAdd(hContact, wait); + LeaveCriticalSection(&cs); + } + } +} + +int FetchAvatarFor(HANDLE hContact, char *szProto = NULL) +{ + int result = GAIR_NOAVATAR; + + if (szProto == NULL) + szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + + if (szProto != NULL && PollProtocolCanHaveAvatar(szProto) && PollContactCanHaveAvatar(hContact, szProto)) + { + // Can have avatar, but must request it? + if ( + (g_AvatarHistoryAvail && CallService(MS_AVATARHISTORY_ENABLED, (WPARAM) hContact, 0)) + || (PollCheckProtocol(szProto) && PollCheckContact(hContact, szProto)) + ) + { + // Request it + PROTO_AVATAR_INFORMATIONT pai_s = {0}; + pai_s.cbSize = sizeof(pai_s); + pai_s.hContact = hContact; + //_DebugTrace(hContact, "schedule request"); + INT_PTR res = CallProtoService(szProto, PS_GETAVATARINFOT, GAIF_FORCE, (LPARAM)&pai_s); +#ifdef _UNICODE + if (res == CALLSERVICE_NOTFOUND) + { + PROTO_AVATAR_INFORMATION pai = {0}; + pai.cbSize = sizeof(pai); + pai.hContact = hContact; + res = CallProtoService(szProto, PS_GETAVATARINFO, GAIF_FORCE, (LPARAM)&pai); + MultiByteToWideChar( CP_ACP, 0, pai.filename, -1, pai_s.filename, SIZEOF(pai_s.filename)); + pai_s.format = pai.format; + } +#endif + if (res != CALLSERVICE_NOTFOUND) result = res; + ProcessAvatarInfo(pai_s.hContact, result, &pai_s, szProto); + } + } + + return result; +} + +static void RequestThread(void *vParam) +{ + while (!g_shutDown) + { + EnterCriticalSection(&cs); + + if ( queue.getCount() == 0 ) + { + // No items, so supend thread + LeaveCriticalSection(&cs); + + mir_sleep(POOL_DELAY); + } + else + { + // Take a look at first item + QueueItem& qi = queue[ queue.getCount()-1 ]; + + if (qi.check_time > GetTickCount()) + { + // Not time to request yet, wait... + LeaveCriticalSection(&cs); + mir_sleep(POOL_DELAY); + } + else + { + // Will request this item + HANDLE hContact = qi.hContact; + queue.remove( queue.getCount()-1 ); + + QueueRemove(hContact); + + LeaveCriticalSection(&cs); + + if (FetchAvatarFor(hContact) == GAIR_WAITFOR) + { + // Mark to not request this contact avatar for more 30 min + EnterCriticalSection(&cs); + QueueRemove(hContact); + QueueAdd(hContact, REQUEST_WAITFOR_WAIT_TIME); + LeaveCriticalSection(&cs); + + // Wait a little until requesting again + mir_sleep(REQUEST_DELAY); + } + } + } + } + + DeleteCriticalSection(&cs); + queue.destroy(); +} diff --git a/plugins/AVS/poll.h b/plugins/AVS/poll.h new file mode 100644 index 0000000000..9761e7360a --- /dev/null +++ b/plugins/AVS/poll.h @@ -0,0 +1,36 @@ +/* +Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __POLL_H__ +# define __POLL_H__ + +struct QueueItem +{ + HANDLE hContact; + DWORD check_time; +}; + +void InitPolls(); +void FreePolls(); + +// Add an contact to a queue +void QueueAdd(HANDLE hContact); + +#endif // __POLL_H__ diff --git a/plugins/AVS/res/avatar.ico b/plugins/AVS/res/avatar.ico new file mode 100644 index 0000000000..3525625479 Binary files /dev/null and b/plugins/AVS/res/avatar.ico differ diff --git a/plugins/AVS/resource.h b/plugins/AVS/resource.h new file mode 100644 index 0000000000..2d8ba9add0 --- /dev/null +++ b/plugins/AVS/resource.h @@ -0,0 +1,60 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by avs.rc +// +#define ID_USE_DEFAULTS 3 +#define IDD_OPTIONS 101 +#define IDD_OPTIONS_PICTS 101 +#define IDD_OPENSUBCLASS 102 +#define IDD_AVATAROPTIONS 103 +#define IDI_AVATAR 104 +#define IDD_SET_OWN_SUBCLASS 105 +#define IDD_DIALOG1 106 +#define IDD_USER_AVATAR 106 +#define IDD_PROTO_AVATARS 107 +#define IDD_OPTIONS_AVATARS 109 +#define IDD_OPTIONS_OWN 110 +#define IDC_PROTOCOLS 1001 +#define IDC_CLIST 1002 +#define IDC_SETPROTOPIC 1003 +#define IDC_PROTOPIC 1004 +#define IDC_REMOVEPROTOPIC 1005 +#define IDC_PROTOAVATARNAME 1006 +#define IDC_CHECK1 1007 +#define IDC_PROTECTAVATAR 1007 +#define IDC_SHOWWARNINGS 1007 +#define IDC_PER_PROTO 1007 +#define IDC_CHANGE 1008 +#define IDC_MAKE_TRANSPARENT_BKG 1008 +#define IDC_GROW 1008 +#define IDC_RESET 1009 +#define IDC_MAKE_GRAYSCALE 1009 +#define IDC_AVATARNAME 1010 +#define IDC_MAKE_GRAYSCALE2 1010 +#define IDC_SET_MAKE_SQUARE 1010 +#define IDC_HIDEAVATAR 1011 +#define IDC_DELETE 1012 +#define IDC_MAKETRANSPBKG 1013 +#define IDC_GUESS_LEVEL 1014 +#define IDC_BKG_NUM_POINTS 1014 +#define IDC_COMBO1 1015 +#define IDC_BKG_NUM_POINTS_SPIN 1015 +#define IDC_BKG_COLOR_DIFFERENCE 1016 +#define IDC_SIZELIMITSPIN3 1017 +#define IDC_BKG_COLOR_DIFFERENCE_SPIN 1017 +#define IDC_BKG_NUM_POINTS_L 1018 +#define IDC_BKG_COLOR_DIFFERENCE_L 1019 +#define IDC_MAKE_TRANSP_PROPORTIONAL 1020 +#define IDC_MAKE_MY_AVATARS_TRANSP 1021 +#define IDC_MAKE_SQUARE 1023 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1024 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/AVS/vc6.rc b/plugins/AVS/vc6.rc new file mode 100644 index 0000000000..99a8f9da1d --- /dev/null +++ b/plugins/AVS/vc6.rc @@ -0,0 +1,2 @@ +#include "avs.rc" +#include "version.rc" diff --git a/plugins/AVS/version.h b/plugins/AVS/version.h new file mode 100644 index 0000000000..826d9fdefb --- /dev/null +++ b/plugins/AVS/version.h @@ -0,0 +1,5 @@ +#include "../../include/m_version.h" + +#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION +#define __VERSION_STRING MIRANDA_VERSION_STRING +#define __VERSION_DWORD MIRANDA_VERSION_DWORD diff --git a/plugins/AVS/version.rc b/plugins/AVS/version.rc new file mode 100644 index 0000000000..43d374df60 --- /dev/null +++ b/plugins/AVS/version.rc @@ -0,0 +1,113 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" +#include "version.h" +#include "winres.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page( 1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "\r\n" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN +#if !defined(UNICODE) + VALUE "Comments", "Service plugin to load and update avatars for Miranda IM" + VALUE "CompanyName", "Written by Nightwish and Pescuma for Miranda IM project" + VALUE "FileDescription", "Service plugin to load and update avatars for Miranda IM" + VALUE "FileVersion", __FILEVERSION_STRING + VALUE "InternalName", "avs" + VALUE "LegalCopyright", "Copyright (C) 2010, Nightwish, Pescuma" + VALUE "LegalTrademarks", "Licensed under the Gnu General Public License V2 or any later version" + VALUE "OriginalFilename", "avs.dll" + VALUE "ProductName", "Miranda IM Avatar Service plugin" + VALUE "ProductVersion", __FILEVERSION_STRING +#else + VALUE "Comments", "Service plugin to load and update avatars for Miranda IM" + VALUE "CompanyName", "Written by Nightwish and Pescuma for Miranda IM project" + VALUE "FileDescription", "Service plugin to load and update avatars for Miranda IM" + VALUE "FileVersion", __FILEVERSION_STRING + VALUE "InternalName", "avsW" + VALUE "LegalCopyright", "Copyright (C) 2010, Nightwish, Pescuma" + VALUE "LegalTrademarks", "Licensed under the Gnu General Public License V2 or any later version" + VALUE "OriginalFilename", "avs.dll" + VALUE "ProductName", "Miranda IM Avatar Service (Unicode)" + VALUE "ProductVersion", __FILEVERSION_STRING +#endif + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + +#endif // AFX_RESOURCE_DLL diff --git a/plugins/Avs/CHANGELOG.AVS b/plugins/Avs/CHANGELOG.AVS deleted file mode 100644 index a673bdff73..0000000000 --- a/plugins/Avs/CHANGELOG.AVS +++ /dev/null @@ -1,182 +0,0 @@ - - Version history: - -0.0.2.6 - 2006/08/03 - - * added file hashing (pescuma) - * rewrote the picture loading code. It is now running in a background thread - at low priority. The loader thread is the only instance which actually writes - to the cache entries. It does this with a small delay and notifies the hook - subscribers when a picture has been loaded. While it is not fully loaded, - the fallback protocol picture may be used. This makes connecting or - loading the clist with lots of avatars significantly faster at the cost - of delayed picture appearance. - It may also help with the sporadic lockups since the part of the code which - runs in the callers thread context is now much simpler. - -0.0.2.5 - 2006/07/30 - - * fixed updater support - * moved InitPolls() to ModulesLoaded() to avoid a problem with missing - core services. - * fixed keyboard navigation glitch in the Customize->Contact pictures dialog. - -0.0.2.4 - 2006/07/30 - - * bugfix (missing protocol avatars after migrating to new relpath) - * added proper version info resource record (showing ansi/unicode) - * added project files for Visual C++ 6 (source code release only) - -0.0.2.3 - 2006/07/11 - - * should now work better with metacontacts. Subcontact avatar changes are - "forwarded" to the master contact. - - * relative path names are now relative to the DATABASE directory, not - Mirandas root directory. - - * missing picture files and/or invalid database entries will now result - in a refresh request. - -0.0.2.0 introduced big internal changes. New request queue system (written by Pescuma) - loadavatars no longer depends on imgdecoder.dll, but needs a recent png2dib - plugin (supplied with Miranda 0.4.3.x nightly builds) - -0.0.1.12 - 0.0.2.2 - released via nightlys (see SVN changelog) - -0.0.1.11 - 2005/11/10 - - + added patch by pescuma for making normal avatars transparent (or semi- - transparent). - There are global (under Customize->Contact pictures) and per contact settings - (contact menu -> Contact picture...). In order to get good results, you will need - to tweak the settings a bit - it works for most avatar pictures with a uni-color - background, but it really depends on the image. - - + built with Visual Studio 2005 (Visual C++ 8.0). The DLL is now statically - linked, so they are somewhat bigger, but it avoids error messages because of the - new VC++ 8 runtime which is not installed on most PCs. - - + added unicode version (loadavatarsW.dll) which will display unicode nicknames in - the "per user" contact picture dialog. - - + added services and events to manage own avatar pictures. See m_avatars.h for more - information. Also, the drawing service was enhanced to allow drawing your own - avatars. - -0.0.1.10 - 2005/10/19 - - ! added support for jabber avatar updates. - - + better cleanup on Unload() - -0.0.1.9 - 2005/10/18 - - * accept .dat as valid image extension (sometimes, icq avatars are saved as .dat - files, even if they are actually JPG images (reason unknown, but we can load - them anyway. MS_UTILS_LOADBITMAP will return an error when the file is not - really a valid image - the extension doesn't matter). - -0.0.1.8 - 2005/10/17 - - ! fix. Don't show tray warning messages about invalid avatar file size when - the option "Show warning messages" on Customize->Contact pictures is unchecked. - - * changed way how protocols are enabled/disabled. After protocols have been added - or removed, "new" protocols are automatically enabled, so you don't have to do - that manually any more. - - * you can completely disable the size limit check by setting the size limit on - Customize->Contact List to 0 (zero). - -0.0.1.7 - 2005/10/16 - - * bugfix: check filenames more aggressivly. - - * bugfix: premultiply was broken (thanks FYR) - - + added a service to draw a contacts picture to a target device context. - See m_avatars.h for description on how to use that service. - - + added file size limitation to the picture loader. The default are 70Kbytes, - should be enough for most avatar pictures (they have to be small images). - The limit can be increased on the option page (Customize->contact pictures). - -0.0.1.5 - 2005/09/15 - - + added updater support - - * moved option page to Customize->Contact pictures - -0.0.1.4 - 2005/08/31 - - * cache reallocs will now send avatar change notifies (realloc() may move the - cache in memory, so pointers to avatar cache entries may become invalid). - - ! bugfix - badly written protocols which load themself too late are now - skipped and won't cause troubles because of the protocol list reallocation. - -0.0.1.3 - 2005/08/30 - - + ability to lock the avatar (protect from automatic updates). Useful, if you - have set a local contact picture and don't want it to be overwritten. - Actually, the feature does not really lock the avatar updating - it will - only save the picture from being overwritten. - - + added UI to set/change/lock avatar. DEVELOPERS please check m_avatars.h on how - to use the service from your own plugins. There are now services to lock and/or - set the avatar, either by providing a valid image filename or by using a file - selection dialog. Also, there is a service to call the avatar dialog for a - hContact. - - * struct avatarCacheEntry has changed too. It now provides szFilename which - will contain the full image filename of the current avatar in use. - - * added a menu item to the contact menu which allows to set avatar options (local - picture, locked avatar, and a "hidden" attribute). - The hidden attribute is set in the struct avatarCacheEntry - - + added support for PNG images (imgdecoder.dll needs to be present in either the - main miranda directory or the \Plugins subfolder. Transparent PNG images are - supported and the avatar service will perform the premultiplication of alpha - values so that the image can (and should) be rendered with the AlphaBlend() - API. - -0.0.1.2 - 2005/08/20 - - + the service now creates and uses relative filenames for all contact pictures, - including protocol avatars, if possible. - - * for protocols which are in "invisible" status, no active avatar fetching - is performed. This is to avoid problems with MSN and privacy issues for - other protocols (if you're invisible, then the protocol should not initiate - any outbound communications which may require direct p2p connections). - - * an option page has been added. Currently, you can: - - + select, for which protocols the service should ACTIVELY fetch avatars. - If you set a protocols to "inactive" (uncheck it), already existing - avatars for contacts of that protocol will continue to work, but the - service will no longer actively refresh avatars. - - + set protocol pictures (pseudo avatars). You can select local pictures - for each installed protocol. These will be used as a fallback then, if - no avatar is available for a contact. You can also remove these pictures. - - * don't fetch avatars for contacts which are either blocked or set on the - invisibility list (ApparentMode == ID_STATUS_OFFLINE). Reason: No active - outbound communications w/o user intervention should be initiated for blocked - contacts. - - + added support for the updater plugin. - -0.0.1.1 - 2005/08/06 - - * changed API. Don't return HBITMAP directly, but instead, it returns - a pointer to a struct avatarCacheEntry which can be used to obtain - the bitmap handle. - -0.0.1.0 - 2005/08/05 - - * initial release, cvs import. - diff --git a/plugins/Avs/README b/plugins/Avs/README deleted file mode 100644 index d82d1d7fec..0000000000 --- a/plugins/Avs/README +++ /dev/null @@ -1,94 +0,0 @@ - - Load avatars 0.0.1.0 - -------------------- - -This is a SERVICE plugin, which means, it doesn't provide anything useful -on its own except for a few service(s) and event(s) which can be used by -other plugins. - -What it does? -------------- - -It loads avatars on demand and maintains an internal cache of avatar -bitmap handles. It also handles avatar changes transparently and can -notify event subscribers about avatar changes. - -How it works? -------------- - -The service MS_AV_GETAVATARBITMAP returns a pointer to a cache entry, if an -avatar is present for that contact. The service MAY return 0, in which -case, there is no valid avatar yet. However, that doesn't mean there -isn't ANY avatar, just that the avatar is not yet ready for use. When -someone calls the service requesting an avatar, the plugin will try -to get the avatar (if possible) and notify all subscribers via a -hookable event as soon as the avatar is ready. If the avatar is -already in the cache, it simply returns the cached entry. - -Whenever an avatar changes, the plugin fires an event, passing the -contacts handle in wParam and a data structure with the avatar information -in lParam. Plugins which use the bitmap handles returned by -MS_AV_GETAVATARBITMAP MUST subscribe to ME_AV_AVATARCHANGED, because the -original bitmap handle may become invalid when the avatar changes. - -Fetching avatars is done in a separate thread with reasonable delays to -avoid getting into troubles with flood protection(s). Avatars are cached -"in memory". - - -The included clist_nicer_plus.dll is a demonstration of how the avatar -service works and can be used by developers. Having a central instance -which maintains avatars saves resources and increases performance. - - -// example, how to use it (FOR DEVS only) - -#include "m_avatars.h" - -struct avatarCacheEntry *ace = 0; -HBITMAP hbmAvatar = 0; - -ace = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0); - -/* - now, check the return value. if it is 0, then the avatar is not yet ready or unavailble - for that contact. if it was only "not ready", your plugin will be notified by the - hookable event ME_AV_AVATARCHANGED - - if the return value is != 0, then it is a valid bitmap handle. DON'T DESTROY IT IN YOUR CODE -*/ - - -/* - * event function - * initialise with: - * HANDLE hEvent = HookEvent(ME_AV_AVATARCHANGED, AvatarChanged); - */ - -static int AvatarChanged(WPARAM wParam, LPARAM lParam) -{ - struct avatarCacheEntry *ace = (struct avatarCacheEntry *)lParam; - HANDLE hContact = (HANDLE)wParam; - - if(ace == NULL) - return 0; - if(ace->cbSize != sizeof(struct avatarCacheEntry)) - return 0; // safety check(s) - - HBITMAP hbmAvatar = ace->hbmPic; - ... - ... -} - - -TODO: maybe more intelligent cache managment, including auto-expire of avatars which - have not been used for a while. - - -Copyright and license: ----------------------- - -This plugin is released under the terms of the GNU general public license V2 or any later -version. - -Written, 2005 by Nightwish, silvercircle@gmail.com diff --git a/plugins/Avs/README.SOURCE b/plugins/Avs/README.SOURCE deleted file mode 100644 index 5f87280afe..0000000000 --- a/plugins/Avs/README.SOURCE +++ /dev/null @@ -1,25 +0,0 @@ - -Source code for the loadavatars (avatar service plugin) is available via -anonymous SVN at: - -http://svn.berlios.de/svnroot/repos/mimplugins/trunk/avs/ - -You need a SVN client to access this, I recommend TortoiseSVN for Windows which -is easy to use and provides a good UI. - -To compile, you need a complete checkout of Mirandas main source repository and -Visual C++ 6 with service pack 6 + the latest platform SDK installed. - -Project files are provided for Visual C++ 6 and Visual Studio 2005 (aka Visual -C++ 8). The sources may compile with Mingw32/GCC, but this is not supported at -this time. - -This plugin for the Miranda Instant messenger is licensed under the GNU -General Public License Version 2. - -The code was written by: - -Nightwish (silvercircle@gmail.com) (original idea and implementation) -Pescuma (major rewrite for version 0.0.2.0 with new request/poll code and most of - the image manipulation utilities). - diff --git a/plugins/Avs/acc.cpp b/plugins/Avs/acc.cpp deleted file mode 100644 index f62009b43d..0000000000 --- a/plugins/Avs/acc.cpp +++ /dev/null @@ -1,908 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2004 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" - -extern FI_INTERFACE *fei; - -int GetImageFormat(TCHAR *filename); -INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam); -INT_PTR GetAvatarBitmap(WPARAM wParam, LPARAM lParam); -INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam); -void InternalDrawAvatar(AVATARDRAWREQUEST *r, HBITMAP hbm, LONG bmWidth, LONG bmHeight, DWORD dwFlags); - - -#define DM_AVATARCHANGED (WM_USER + 20) -#define DM_MYAVATARCHANGED (WM_USER + 21) - -#define GIF_DISPOSAL_UNSPECIFIED 0 -#define GIF_DISPOSAL_LEAVE 1 -#define GIF_DISPOSAL_BACKGROUND 2 -#define GIF_DISPOSAL_PREVIOUS 3 - -typedef struct -{ - HANDLE hContact; - char proto[64]; - HANDLE hHook; - HANDLE hHookMy; - HFONT hFont; // font - COLORREF borderColor; - COLORREF bkgColor; - COLORREF avatarBorderColor; - int avatarRoundCornerRadius; - TCHAR noAvatarText[128]; - BOOL respectHidden; - BOOL showingFlash; - BOOL resizeIfSmaller; - BOOL fAero; - BOOL showingAnimatedGif; - - struct { - HBITMAP *hbms; - int *times; - - FIMULTIBITMAP *multi; - FIBITMAP *dib; - int frameCount; - int logicalWidth; - int logicalHeight; - BOOL loop; - RGBQUAD background; - BOOL started; - - struct { - int num; - int top; - int left; - int width; - int height; - int disposal_method; - } frame; - } ag; - -} ACCData; - - -void ResizeFlash(HWND hwnd, ACCData* data) -{ - if ((data->hContact != NULL || data->proto[0] != '\0') - && ServiceExists(MS_FAVATAR_RESIZE)) - { - RECT rc; - GetClientRect(hwnd, &rc); - - if (data->borderColor != -1 || data->avatarBorderColor != -1) - { - rc.left ++; - rc.right -= 2; - rc.top ++; - rc.bottom -= 2; - } - - FLASHAVATAR fa = {0}; - fa.hContact = data->hContact; - fa.cProto = data->proto; - fa.hParentWindow = hwnd; - fa.id = 1675; - CallService(MS_FAVATAR_RESIZE, (WPARAM)&fa, (LPARAM)&rc); - CallService(MS_FAVATAR_SETPOS, (WPARAM)&fa, (LPARAM)&rc); - } -} - -void SetBkgFlash(HWND hwnd, ACCData* data) -{ - if ((data->hContact != NULL || data->proto[0] != '\0') - && ServiceExists(MS_FAVATAR_SETBKCOLOR)) - { - FLASHAVATAR fa = {0}; - fa.hContact = data->hContact; - fa.cProto = data->proto; - fa.hParentWindow = hwnd; - fa.id = 1675; - - if (data->bkgColor != -1) - CallService(MS_FAVATAR_SETBKCOLOR, (WPARAM)&fa, (LPARAM)data->bkgColor); - else - CallService(MS_FAVATAR_SETBKCOLOR, (WPARAM)&fa, (LPARAM)RGB(255,255,255)); - } -} - -void DestroyFlash(HWND hwnd, ACCData* data) -{ - if (!data->showingFlash) - return; - - if ((data->hContact != NULL || data->proto[0] != '\0') - && ServiceExists(MS_FAVATAR_DESTROY)) - { - FLASHAVATAR fa = {0}; - fa.hContact = data->hContact; - fa.cProto = data->proto; - fa.hParentWindow = hwnd; - fa.id = 1675; - CallService(MS_FAVATAR_DESTROY, (WPARAM)&fa, 0); - } - - data->showingFlash = FALSE; -} - -void StartFlash(HWND hwnd, ACCData* data) -{ - if (!ServiceExists(MS_FAVATAR_MAKE)) - return; - - int format; - if (data->hContact != NULL) - { - format = DBGetContactSettingWord(data->hContact, "ContactPhoto", "Format", 0); - } - else if (data->proto[0] != '\0') - { - protoPicCacheEntry *ace = NULL; - for(int i = 0; i < g_MyAvatars.getCount(); i++) - { - if (!lstrcmpA(data->proto, g_MyAvatars[i].szProtoname)) - { - ace = &g_MyAvatars[i]; - break; - } - } - - if (ace != NULL && ace->szFilename != NULL) - format = GetImageFormat(ace->szFilename); - else - format = 0; - } - else - return; - - if (format != PA_FORMAT_XML && format != PA_FORMAT_SWF) - return; - - FLASHAVATAR fa = {0}; - fa.hContact = data->hContact; - fa.cProto = data->proto; - fa.hParentWindow = hwnd; - fa.id = 1675; - CallService(MS_FAVATAR_MAKE, (WPARAM)&fa, 0); - - if (fa.hWindow == NULL) - return; - - data->showingFlash = TRUE; - ResizeFlash(hwnd, data); - SetBkgFlash(hwnd, data); -} - -BOOL AnimatedGifGetData(ACCData* data) -{ - FIBITMAP *page = fei->FI_LockPage(data->ag.multi, 0); - if (page == NULL) - return FALSE; - - // Get info - FITAG *tag = NULL; - if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalWidth", &tag)) - goto ERR; - data->ag.logicalWidth = *(WORD *)fei->FI_GetTagValue(tag); - - if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "LogicalHeight", &tag)) - goto ERR; - data->ag.logicalHeight = *(WORD *)fei->FI_GetTagValue(tag); - - if (!fei->FI_GetMetadata(FIMD_ANIMATION, page, "Loop", &tag)) - goto ERR; - data->ag.loop = (*(LONG *)fei->FI_GetTagValue(tag) > 0); - - if (fei->FI_HasBackgroundColor(page)) - fei->FI_GetBackgroundColor(page, &data->ag.background); - - fei->FI_UnlockPage(data->ag.multi, page, FALSE); - return TRUE; - -ERR: - fei->FI_UnlockPage(data->ag.multi, page, FALSE); - return FALSE; -} - -void AnimatedGifDispodeFrame(ACCData* data) -{ - if (data->ag.frame.disposal_method == GIF_DISPOSAL_PREVIOUS) - { - // TODO - } - else if (data->ag.frame.disposal_method == GIF_DISPOSAL_BACKGROUND) - { - for (int y = 0; y < data->ag.frame.height; y++) - { - RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(data->ag.dib, - data->ag.logicalHeight - (y + data->ag.frame.top) - 1) + data->ag.frame.left; - for (int x = 0; x < data->ag.frame.width; x++) - *scanline++ = data->ag.background; - } - } -} - -void AnimatedGifMountFrame(ACCData* data, int page) -{ - data->ag.frame.num = page; - - if (data->ag.hbms[page] != NULL) - { - data->ag.frame.disposal_method = GIF_DISPOSAL_LEAVE; - return; - } - - FIBITMAP *dib = fei->FI_LockPage(data->ag.multi, data->ag.frame.num); - if (dib == NULL) - return; - - FITAG *tag = NULL; - if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameLeft", &tag)) - data->ag.frame.left = *(WORD *)fei->FI_GetTagValue(tag); - else - data->ag.frame.left = 0; - - if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTop", &tag)) - data->ag.frame.top = *(WORD *)fei->FI_GetTagValue(tag); - else - data->ag.frame.top = 0; - - if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "FrameTime", &tag)) - data->ag.times[page] = *(LONG *)fei->FI_GetTagValue(tag); - else - data->ag.times[page] = 0; - - if (fei->FI_GetMetadata(FIMD_ANIMATION, dib, "DisposalMethod", &tag)) - data->ag.frame.disposal_method = *(BYTE *)fei->FI_GetTagValue(tag); - else - data->ag.frame.disposal_method = 0; - - data->ag.frame.width = fei->FI_GetWidth(dib); - data->ag.frame.height = fei->FI_GetHeight(dib); - - - //decode page - int palSize = fei->FI_GetColorsUsed(dib); - RGBQUAD *pal = fei->FI_GetPalette(dib); - bool have_transparent = false; - int transparent_color = -1; - if( fei->FI_IsTransparent(dib) ) { - int count = fei->FI_GetTransparencyCount(dib); - BYTE *table = fei->FI_GetTransparencyTable(dib); - for( int i = 0; i < count; i++ ) { - if( table[i] == 0 ) { - have_transparent = true; - transparent_color = i; - break; - } - } - } - - //copy page data into logical buffer, with full alpha opaqueness - for( int y = 0; y < data->ag.frame.height; y++ ) { - RGBQUAD *scanline = (RGBQUAD *)fei->FI_GetScanLine(data->ag.dib, data->ag.logicalHeight - (y + data->ag.frame.top) - 1) + data->ag.frame.left; - BYTE *pageline = fei->FI_GetScanLine(dib, data->ag.frame.height - y - 1); - for( int x = 0; x < data->ag.frame.width; x++ ) { - if( !have_transparent || *pageline != transparent_color ) { - *scanline = pal[*pageline]; - scanline->rgbReserved = 255; - } - scanline++; - pageline++; - } - } - - data->ag.hbms[page] = fei->FI_CreateHBITMAPFromDIB(data->ag.dib); - - fei->FI_UnlockPage(data->ag.multi, dib, FALSE); -} - -void AnimatedGifDeleteTmpValues(ACCData* data) -{ - if (data->ag.multi != NULL) - { - fei->FI_CloseMultiBitmap(data->ag.multi, 0); - data->ag.multi = NULL; - } - - if (data->ag.dib != NULL) - { - fei->FI_Unload(data->ag.dib); - data->ag.dib = NULL; - } -} - -void DestroyAnimatedGif(HWND hwnd, ACCData* data) -{ - if (!data->showingAnimatedGif) - return; - - AnimatedGifDeleteTmpValues(data); - - if (data->ag.hbms != NULL) - { - for (int i = 0; i < data->ag.frameCount; i++) - if (data->ag.hbms[i] != NULL) - DeleteObject(data->ag.hbms[i]); - - free(data->ag.hbms); - data->ag.hbms = NULL; - } - - if (data->ag.times != NULL) - { - free(data->ag.times); - data->ag.times = NULL; - } - - data->showingAnimatedGif = FALSE; -} - -void StartAnimatedGif(HWND hwnd, ACCData* data) -{ - if (fei == NULL) - return; - - int x, y; - AVATARCACHEENTRY *ace = NULL; - - if (data->hContact != NULL) - ace = (AVATARCACHEENTRY *) GetAvatarBitmap((WPARAM) data->hContact, 0); - else - ace = (AVATARCACHEENTRY *) GetMyAvatar(0, (LPARAM) data->proto); - - if (ace == NULL) - return; - - int format = GetImageFormat(ace->szFilename); - if (format != PA_FORMAT_GIF) - return; - - FREE_IMAGE_FORMAT fif = fei->FI_GetFileTypeT(ace->szFilename, 0); - if(fif == FIF_UNKNOWN) - fif = fei->FI_GetFIFFromFilenameT(ace->szFilename); - - data->ag.multi = fei->FI_OpenMultiBitmapT(fif, ace->szFilename, FALSE, TRUE, FALSE, GIF_LOAD256); - if (data->ag.multi == NULL) - return; - - data->ag.frameCount = fei->FI_GetPageCount(data->ag.multi); - if (data->ag.frameCount <= 1) - goto ERR; - - if (!AnimatedGifGetData(data)) - goto ERR; - - //allocate entire logical area - data->ag.dib = fei->FI_Allocate(data->ag.logicalWidth, data->ag.logicalHeight, 32, 0, 0, 0); - if (data->ag.dib == NULL) - goto ERR; - - //fill with background color to start - for (y = 0; y < data->ag.logicalHeight; y++) - { - RGBQUAD *scanline = (RGBQUAD *) fei->FI_GetScanLine(data->ag.dib, y); - for (x = 0; x < data->ag.logicalWidth; x++) - *scanline++ = data->ag.background; - } - - data->ag.hbms = (HBITMAP *) malloc(sizeof(HBITMAP) * data->ag.frameCount); - memset(data->ag.hbms, 0, sizeof(HBITMAP) * data->ag.frameCount); - - data->ag.times = (int *) malloc(sizeof(int) * data->ag.frameCount); - memset(data->ag.times, 0, sizeof(int) * data->ag.frameCount); - - AnimatedGifMountFrame(data, 0); - - data->showingAnimatedGif = TRUE; - - return; -ERR: - fei->FI_CloseMultiBitmap(data->ag.multi, 0); - data->ag.multi = NULL; -} - -void DestroyAnimation(HWND hwnd, ACCData* data) -{ - DestroyFlash(hwnd, data); - DestroyAnimatedGif(hwnd, data); -} - -void StartAnimation(HWND hwnd, ACCData* data) -{ - StartFlash(hwnd, data); - - if (!data->showingFlash) - StartAnimatedGif(hwnd, data); -} - -BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) -{ - BOOL ret; - - POINT pt; - - pt.x = lpRect->left; - pt.y = lpRect->top; - - ret = ScreenToClient(hWnd, &pt); - - if (!ret) return ret; - - lpRect->left = pt.x; - lpRect->top = pt.y; - - - pt.x = lpRect->right; - pt.y = lpRect->bottom; - - ret = ScreenToClient(hWnd, &pt); - - lpRect->right = pt.x; - lpRect->bottom = pt.y; - - return ret; -} - -static void Invalidate(HWND hwnd) -{ - ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); - if (data->bkgColor == -1) - { - HWND parent = GetParent(hwnd); - RECT rc; - GetWindowRect(hwnd, &rc); - ScreenToClient(parent, &rc); - InvalidateRect(parent, &rc, TRUE); - } - InvalidateRect(hwnd, NULL, TRUE); -} - -static void NotifyAvatarChange(HWND hwnd) -{ - PSHNOTIFY pshn = {0}; - pshn.hdr.idFrom = GetDlgCtrlID(hwnd); - pshn.hdr.hwndFrom = hwnd; - pshn.hdr.code = NM_AVATAR_CHANGED; - pshn.lParam = 0; - SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) &pshn); -} - -static void DrawText(HDC hdc, HFONT hFont, const RECT &rc, const TCHAR *text) -{ - HGDIOBJ oldFont = SelectObject(hdc, hFont); - - // Get text rectangle - RECT tr = rc; - tr.top += 10; - tr.bottom -= 10; - tr.left += 10; - tr.right -= 10; - - // Calc text size - RECT tr_ret = tr; - DrawText(hdc, text, -1, &tr_ret, - DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT); - - // Calc needed size - tr.top += ((tr.bottom - tr.top) - (tr_ret.bottom - tr_ret.top)) / 2; - tr.bottom = tr.top + (tr_ret.bottom - tr_ret.top); - DrawText(hdc, text, -1, &tr, - DT_WORDBREAK | DT_NOPREFIX | DT_CENTER); - - SelectObject(hdc, oldFont); -} - -static LRESULT CALLBACK ACCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - ACCData* data = (ACCData *) GetWindowLongPtr(hwnd, 0); - switch(msg) - { - case WM_NCCREATE: - { - SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | BS_OWNERDRAW); - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT); - - data = (ACCData*) mir_alloc(sizeof(ACCData)); - if (data == NULL) - return FALSE; - SetWindowLongPtr(hwnd, 0, (LONG_PTR)data); - - ZeroMemory(data, sizeof(ACCData)); - data->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwnd, DM_AVATARCHANGED); - data->hHookMy = HookEventMessage(ME_AV_MYAVATARCHANGED, hwnd, DM_MYAVATARCHANGED); - data->hFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT); - data->borderColor = -1; - data->bkgColor = -1; - data->avatarBorderColor = -1; - data->respectHidden = TRUE; - data->showingFlash = FALSE; - data->resizeIfSmaller = TRUE; - data->showingAnimatedGif = FALSE; - data->fAero = FALSE; - - return TRUE; - } - case WM_NCDESTROY: - { - DestroyAnimation(hwnd, data); - if (data) - { - UnhookEvent(data->hHook); - UnhookEvent(data->hHookMy); - mir_free(data); - } - SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); - break; - } - case WM_SETFONT: - { - data->hFont = (HFONT)wParam; - Invalidate(hwnd); - break; - } - case AVATAR_SETCONTACT: - { - DestroyAnimation(hwnd, data); - - data->hContact = (HANDLE) lParam; - lstrcpynA(data->proto, (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)data->hContact, 0), sizeof(data->proto)); - - StartAnimation(hwnd, data); - - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETPROTOCOL: - { - DestroyAnimation(hwnd, data); - - data->hContact = NULL; - if (lParam == NULL) - data->proto[0] = '\0'; - else - lstrcpynA(data->proto, (char *) lParam, sizeof(data->proto)); - - StartAnimation(hwnd, data); - - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETBKGCOLOR: - { - data->bkgColor = (COLORREF) lParam; - if (data->showingFlash) - SetBkgFlash(hwnd, data); - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETBORDERCOLOR: - { - data->borderColor = (COLORREF) lParam; - if (data->showingFlash) - ResizeFlash(hwnd, data); - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETAVATARBORDERCOLOR: - { - data->avatarBorderColor = (COLORREF) lParam; - if (data->showingFlash) - ResizeFlash(hwnd, data); - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETAVATARROUNDCORNERRADIUS: - { - data->avatarRoundCornerRadius = (int) lParam; - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETNOAVATARTEXT: - { - lstrcpyn(data->noAvatarText, TranslateTS((TCHAR*) lParam), SIZEOF(data->noAvatarText)); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_RESPECTHIDDEN: - { - data->respectHidden = (BOOL) lParam; - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - case AVATAR_SETRESIZEIFSMALLER: - { - data->resizeIfSmaller = (BOOL) lParam; - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - return TRUE; - } - - case AVATAR_SETAEROCOMPATDRAWING: - data->fAero = lParam; - return(TRUE); - - case AVATAR_GETUSEDSPACE: - { - int *width = (int *)wParam; - int *height = (int *)lParam; - - RECT rc; - GetClientRect(hwnd, &rc); - - // Get avatar - if (data->showingFlash && ServiceExists(MS_FAVATAR_GETINFO)) - { - FLASHAVATAR fa = {0}; - fa.hContact = data->hContact; - fa.cProto = data->proto; - fa.hParentWindow = hwnd; - fa.id = 1675; - CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0); - if (fa.hWindow != NULL) - { - *width = rc.right - rc.left; - *height = rc.bottom - rc.top; - return TRUE; - } - } - - avatarCacheEntry *ace; - if (data->hContact == NULL) - ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) data->proto); - else - ace = (avatarCacheEntry *) CallService(MS_AV_GETAVATARBITMAP, (WPARAM) data->hContact, 0); - - if (ace == NULL || ace->bmHeight == 0 || ace->bmWidth == 0 - || (data->respectHidden && (ace->dwFlags & AVS_HIDEONCLIST))) - { - *width = 0; - *height = 0; - return TRUE; - } - - // Get its size - int targetWidth = rc.right - rc.left; - int targetHeight = rc.bottom - rc.top; - - if (!data->resizeIfSmaller && ace->bmHeight <= targetHeight && ace->bmWidth <= targetWidth) - { - *height = ace->bmHeight; - *width = ace->bmWidth; - } - else if (ace->bmHeight > ace->bmWidth) - { - float dScale = targetHeight / (float)ace->bmHeight; - *height = targetHeight; - *width = (int) (ace->bmWidth * dScale); - } - else - { - float dScale = targetWidth / (float)ace->bmWidth; - *height = (int) (ace->bmHeight * dScale); - *width = targetWidth; - } - - return TRUE; - } - case DM_AVATARCHANGED: - { - if (data->hContact == (HANDLE) wParam) - { - DestroyAnimation(hwnd, data); - StartAnimation(hwnd, data); - - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - } - break; - } - case DM_MYAVATARCHANGED: - { - if (data->hContact == NULL && strcmp(data->proto, (char*) wParam) == 0) - { - DestroyAnimation(hwnd, data); - StartAnimation(hwnd, data); - - NotifyAvatarChange(hwnd); - Invalidate(hwnd); - } - break; - } - case WM_NCPAINT: - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - if (hdc == NULL) - break; - - int oldBkMode = SetBkMode(hdc, TRANSPARENT); - SetStretchBltMode(hdc, HALFTONE); - - RECT rc; - GetClientRect(hwnd, &rc); - - // Draw background - if (data->bkgColor != -1) - { - HBRUSH hbrush = CreateSolidBrush(data->bkgColor); - FillRect(hdc, &rc, hbrush); - DeleteObject(hbrush); - } - - if (data->hContact == NULL && data->proto[0] == '\0' - && DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) - { - DrawText(hdc, data->hFont, rc, TranslateT("Protocols have different avatars")); - } - - // Has a flash avatar - else if (data->showingFlash) - { - // Don't draw - - // Draw control border if needed - if (data->borderColor == -1 && data->avatarBorderColor != -1) - { - HBRUSH hbrush = CreateSolidBrush(data->avatarBorderColor); - FrameRect(hdc, &rc, hbrush); - DeleteObject(hbrush); - } - } - - // Has an animated gif - // Has a "normal" image - else - { - // Draw avatar - AVATARDRAWREQUEST avdrq = {0}; - avdrq.cbSize = sizeof(avdrq); - avdrq.rcDraw = rc; - avdrq.hContact = data->hContact; - avdrq.szProto = data->proto; - avdrq.hTargetDC = hdc; - avdrq.dwFlags = AVDRQ_HIDEBORDERONTRANSPARENCY - | (data->respectHidden ? AVDRQ_RESPECTHIDDEN : 0) - | (data->hContact != NULL ? 0 : AVDRQ_OWNPIC) - | (data->avatarBorderColor == -1 ? 0 : AVDRQ_DRAWBORDER) - | (data->avatarRoundCornerRadius <= 0 ? 0 : AVDRQ_ROUNDEDCORNER) - | (data->fAero ? AVDRQ_AERO : 0) - | (data->resizeIfSmaller ? 0 : AVDRQ_DONTRESIZEIFSMALLER); - avdrq.clrBorder = data->avatarBorderColor; - avdrq.radius = data->avatarRoundCornerRadius; - - INT_PTR ret; - if (data->showingAnimatedGif) - { - InternalDrawAvatar(&avdrq, data->ag.hbms[data->ag.frame.num], data->ag.logicalWidth, data->ag.logicalHeight, 0); - ret = 1; - - if (!data->ag.started) - { - SetTimer(hwnd, 0, data->ag.times[data->ag.frame.num], NULL); - data->ag.started = TRUE; - } - } - else - ret = DrawAvatarPicture(0, (LPARAM)&avdrq); - - if (ret == 0) - DrawText(hdc, data->hFont, rc, data->noAvatarText); - } - - // Draw control border - if (data->borderColor != -1) - { - HBRUSH hbrush = CreateSolidBrush(data->borderColor); - FrameRect(hdc, &rc, hbrush); - DeleteObject(hbrush); - } - - SetBkMode(hdc, oldBkMode); - - EndPaint(hwnd, &ps); - return TRUE; - } - case WM_ERASEBKGND: - { - HDC hdc = (HDC) wParam; - RECT rc; - GetClientRect(hwnd, &rc); - - // Draw background - if (data->bkgColor != -1) - { - HBRUSH hbrush = CreateSolidBrush(data->bkgColor); - FillRect(hdc, &rc, hbrush); - DeleteObject(hbrush); - } - - // Draw control border - if (data->borderColor != -1) - { - HBRUSH hbrush = CreateSolidBrush(data->borderColor); - FrameRect(hdc, &rc, hbrush); - DeleteObject(hbrush); - } - - return TRUE; - } - case WM_SIZE: - { - if (data->showingFlash) - ResizeFlash(hwnd, data); - InvalidateRect(hwnd, NULL, TRUE); - break; - } - case WM_TIMER: - { - if (wParam != 0) - break; - KillTimer(hwnd, 0); - - if (!data->showingAnimatedGif) - break; - - AnimatedGifDispodeFrame(data); - - int frame = data->ag.frame.num + 1; - if (frame >= data->ag.frameCount) - { - // Don't need fi data no more - AnimatedGifDeleteTmpValues(data); - frame = 0; - } - AnimatedGifMountFrame(data, frame); - - data->ag.started = FALSE; - InvalidateRect(hwnd, NULL, FALSE); - - break; - } - } - return DefWindowProc(hwnd, msg, wParam, lParam); -} - - -int LoadACC() -{ - WNDCLASSEX wc = {0}; - wc.cbSize = sizeof(wc); - wc.lpszClassName = AVATAR_CONTROL_CLASS; - wc.lpfnWndProc = ACCWndProc; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.cbWndExtra = sizeof(ACCData*); - wc.hbrBackground = 0; - wc.style = CS_GLOBALCLASS; - RegisterClassEx(&wc); - return 0; -} diff --git a/plugins/Avs/acc.h b/plugins/Avs/acc.h deleted file mode 100644 index 11b235adc0..0000000000 --- a/plugins/Avs/acc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - - -#ifndef __ACC_H__ -# define __ACC_H__ - -class A2T -{ - TCHAR* buf; - -public: - A2T( const char* s ) : buf( mir_a2t( s )) {} - A2T( const char* s, int cp ) : buf( mir_a2t_cp( s, cp )) {} - ~A2T() { mir_free(buf); } - - __forceinline operator TCHAR*() const - { return buf; - } -}; - -INT_PTR avSetAvatar( HANDLE hContact, TCHAR* tszPath ); -INT_PTR avSetMyAvatar( char* szProto, TCHAR* tszPath ); - -int LoadACC(); - - -#endif // __ACC_H__ diff --git a/plugins/Avs/avs.rc b/plugins/Avs/avs.rc deleted file mode 100644 index e1818ede8d..0000000000 --- a/plugins/Avs/avs.rc +++ /dev/null @@ -1,251 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Neutral resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -#ifdef _WIN32 -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_OPTIONS_PICTS DIALOGEX 0, 0, 299, 214 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - CTEXT "The pictures you can set here are used as default avatars\nfor contacts that don't have their own.\nUse the checkboxes to enable/disable showing avatars for the protocols.",IDC_STATIC,0,13,294,27 - CONTROL "",IDC_PROTOCOLS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,19,83,150,85 - PUSHBUTTON "Set default picture",IDC_SETPROTOPIC,176,83,106,14 - PUSHBUTTON "Delete default picture",IDC_REMOVEPROTOPIC,176,99,106,14 - CONTROL "",IDC_PROTOPIC,"Button",BS_OWNERDRAW,197,118,56,50 - EDITTEXT IDC_PROTOAVATARNAME,18,176,264,30,ES_MULTILINE | ES_READONLY,WS_EX_CLIENTEDGE - CTEXT "CAUTION: These pictures are NOT your own avatars.\nTo set your own Avatar goto Main Menu | View/Change My Details | Avatars",IDC_STATIC,0,53,294,18 -END - -IDD_OPTIONS_AVATARS DIALOGEX 0, 0, 302, 189 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - CONTROL "Try to draw avatar background transparent (for images without transparency)",IDC_MAKE_TRANSPARENT_BKG, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,17,278,12 - LTEXT "Num of points to define bkg:",IDC_BKG_NUM_POINTS_L,33,31,135,11 - EDITTEXT IDC_BKG_NUM_POINTS,173,30,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_BKG_NUM_POINTS_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,209,30,11,12 - LTEXT "Color difference allowed:",IDC_BKG_COLOR_DIFFERENCE_L,33,44,135,11 - EDITTEXT IDC_BKG_COLOR_DIFFERENCE,173,43,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_BKG_COLOR_DIFFERENCE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,209,42,11,12 - CONTROL "Make transparency proportional to color diff",IDC_MAKE_TRANSP_PROPORTIONAL, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,33,57,247,10 - CONTROL "Draw avatars grayscale",IDC_MAKE_GRAYSCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,72,269,13 - CONTROL "Show warning messages",IDC_SHOWWARNINGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,87,269,13 -END - -IDD_OPTIONS_OWN DIALOGEX 0, 0, 302, 75 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - CONTROL "When setting avatars, always make them square",IDC_SET_MAKE_SQUARE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,17,281,11 - CONTROL "Try to draw own avatar background transparent (for images without transparency)",IDC_MAKE_MY_AVATARS_TRANSP, - "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,30,289,16 - LTEXT "This uses the same additional options as in ""Contact Avatars"" tab",IDC_STATIC,17,50,257,13 -END - -IDD_OPENSUBCLASS DIALOGEX 0, 0, 246, 18 -STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - CONTROL "Protect the picture and prevent automatic avatars from overwriting it",IDC_PROTECTAVATAR, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,237,8 -END - -IDD_SET_OWN_SUBCLASS DIALOG 0, 0, 323, 31 -STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Make the avatar square",IDC_MAKE_SQUARE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,0,237,8 - CONTROL "Resize the avatar to fit max allowed protocol size",IDC_GROW, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,12,237,8 -END - -IDD_AVATAROPTIONS DIALOGEX 0, 0, 213, 212 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Dialog" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - GROUPBOX "Contact picture",IDC_STATIC,5,5,202,96 - CONTROL "",IDC_PROTOPIC,"Button",BS_OWNERDRAW,12,16,56,50 - PUSHBUTTON "Change",IDC_CHANGE,138,15,61,14 - PUSHBUTTON "Delete",IDC_DELETE,138,32,61,14 - PUSHBUTTON "Reset",IDC_RESET,138,49,61,14 - EDITTEXT IDC_AVATARNAME,12,68,187,29,ES_MULTILINE | ES_READONLY,WS_EX_CLIENTEDGE - GROUPBOX "Picture options",IDC_STATIC,5,102,202,92 - CONTROL "Protect the picture",IDC_PROTECTAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,112,186,8 - CONTROL "Set as hidden",IDC_HIDEAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,122,186,11 - CONTROL "Try to make picture background transparent",IDC_MAKETRANSPBKG, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,133,186,11 - LTEXT "Num of points to define bkg:",IDC_BKG_NUM_POINTS_L,23,148,118,11 - EDITTEXT IDC_BKG_NUM_POINTS,145,146,42,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_BKG_NUM_POINTS_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,187,147,11,12 - LTEXT "Color difference allowed:",IDC_BKG_COLOR_DIFFERENCE_L,23,162,118,11 - EDITTEXT IDC_BKG_COLOR_DIFFERENCE,145,160,42,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_BKG_COLOR_DIFFERENCE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,188,160,11,12 - DEFPUSHBUTTON "Use defaults",ID_USE_DEFAULTS,11,177,63,12 - DEFPUSHBUTTON "OK",IDOK,93,197,50,14 - DEFPUSHBUTTON "Cancel",IDCANCEL,151,197,50,14 -END - -IDD_USER_AVATAR DIALOGEX 0, 0, 222, 152 -STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD -EXSTYLE WS_EX_CONTROLPARENT -FONT 8, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - CONTROL "",IDC_PROTOPIC,"MAvatarControlClass",0x0,3,4,96,89 - PUSHBUTTON "Change",IDC_CHANGE,3,102,96,14 - PUSHBUTTON "Delete",IDC_DELETE,3,118,96,14 - PUSHBUTTON "Reset",IDC_RESET,3,134,96,14 - GROUPBOX " Options ",IDC_STATIC,107,3,111,50 - CONTROL "Protect the picture",IDC_PROTECTAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,18,93,8 - CONTROL "Set as hidden",IDC_HIDEAVATAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,34,93,11 - GROUPBOX " Background ",IDC_STATIC,107,59,111,89 - CONTROL "Transparent",IDC_MAKETRANSPBKG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,118,74,93,11 - LTEXT "Points:",IDC_BKG_NUM_POINTS_L,129,91,38,11 - EDITTEXT IDC_BKG_NUM_POINTS,169,89,42,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_BKG_NUM_POINTS_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,199,80,11,12 - LTEXT "Color diff:",IDC_BKG_COLOR_DIFFERENCE_L,129,108,38,11 - EDITTEXT IDC_BKG_COLOR_DIFFERENCE,169,106,42,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_BKG_COLOR_DIFFERENCE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,199,117,11,12 - PUSHBUTTON "Use defaults",ID_USE_DEFAULTS,118,130,63,12 -END - -IDD_PROTO_AVATARS DIALOGEX 0, 0, 222, 152 -STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD -EXSTYLE WS_EX_CONTROLPARENT -FONT 8, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - CONTROL "",IDC_PROTOCOLS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,3,4,101,126 - CONTROL "",IDC_PROTOPIC,"MAvatarControlClass",0x0,114,4,96,89 - PUSHBUTTON "Set",IDC_CHANGE,114,100,96,14 - PUSHBUTTON "Delete",IDC_DELETE,114,116,96,14 - CONTROL "Use per protocol avatars",IDC_PER_PROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,3,137,215,11 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_OPTIONS_PICTS, DIALOG - BEGIN - RIGHTMARGIN, 294 - END - - IDD_OPENSUBCLASS, DIALOG - BEGIN - RIGHTMARGIN, 208 - TOPMARGIN, 7 - END - - IDD_AVATAROPTIONS, DIALOG - BEGIN - RIGHTMARGIN, 207 - BOTTOMMARGIN, 211 - END - - IDD_USER_AVATAR, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 218 - TOPMARGIN, 4 - BOTTOMMARGIN, 148 - END - - IDD_PROTO_AVATARS, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 218 - TOPMARGIN, 4 - BOTTOMMARGIN, 148 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_AVATAR ICON "res/avatar.ico" -#endif // Neutral resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/plugins/Avs/avs_10.vcxproj b/plugins/Avs/avs_10.vcxproj deleted file mode 100644 index c512086a8d..0000000000 --- a/plugins/Avs/avs_10.vcxproj +++ /dev/null @@ -1,290 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - AVS - {7711F563-6473-4ABD-B5E3-477CE8384AD6} - avs - - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - false - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30128.1 - $(SolutionDir)$(Configuration)/Plugins\ - $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ - true - $(SolutionDir)$(Configuration)64/Plugins\ - $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ - true - $(SolutionDir)$(Configuration)/Plugins\ - $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ - true - $(SolutionDir)$(Configuration)64/Plugins\ - $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ - true - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\Debug_Unicode/avatars.tlb - - - - - Disabled - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - true - Fast - Use - commonheaders.h - Level3 - EditAndContinue - 4996;%(DisableSpecificWarnings) - - - _DEBUG;UNICODE;%(PreprocessorDefinitions) - ../../include/msapi - - - comctl32.lib;msimg32.lib;%(AdditionalDependencies) - true - false - $(IntDir)$(TargetName).lib - Windows - 0x5130000 - - - - - _DEBUG;%(PreprocessorDefinitions) - true - true - X64 - .\Debug_Unicode/avatars.tlb - - - - - Disabled - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - true - Fast - false - Use - commonheaders.h - Level3 - ProgramDatabase - 4996;%(DisableSpecificWarnings) - - - _DEBUG;UNICODE;%(PreprocessorDefinitions) - 0x0809 - ../../include/msapi - - - comctl32.lib;msimg32.lib;%(AdditionalDependencies) - true - type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies) - true - $(TargetDir)$(TargetName).pdb - false - $(IntDir)$(TargetName).lib - MachineX64 - 0x5130000 - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - Win32 - .\Release_Unicode/avatars.tlb - - - - - Full - OnlyExplicitInline - Size - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) - true - false - MultiThreadedDLL - false - true - Fast - Use - commonheaders.h - Level3 - 4996;%(DisableSpecificWarnings) - - - NDEBUG;UNICODE;%(PreprocessorDefinitions) - ../../include/msapi - - - /IGNORE:4089 /filealign:512 %(AdditionalOptions) - comctl32.lib;msimg32.lib;%(AdditionalDependencies) - true - true - true - 0x5130000 - false - $(IntDir)$(TargetName).lib - Windows - - - - - NDEBUG;%(PreprocessorDefinitions) - true - true - X64 - .\Release_Unicode/avatars.tlb - - - - - Full - OnlyExplicitInline - Size - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN64;NDEBUG;_WINDOWS;UNICODE;_USRDLL;LOADAVATARS_EXPORTS;%(PreprocessorDefinitions) - true - false - MultiThreadedDLL - false - true - Fast - Use - commonheaders.h - Level3 - 4996;%(DisableSpecificWarnings) - - - NDEBUG;UNICODE;%(PreprocessorDefinitions) - ../../include/msapi - - - /IGNORE:4089 /filealign:512 %(AdditionalOptions) - comctl32.lib;msimg32.lib;%(AdditionalDependencies) - type=%27Win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies) - true - true - true - 0x5130000 - false - $(IntDir)$(TargetName).lib - Windows - - - - - - - Create - Create - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/Avs/avs_10.vcxproj.filters b/plugins/Avs/avs_10.vcxproj.filters deleted file mode 100644 index 6f6d39f743..0000000000 --- a/plugins/Avs/avs_10.vcxproj.filters +++ /dev/null @@ -1,70 +0,0 @@ - - - - - {8803e79e-1c62-4fcc-8daf-35634ce5e990} - cpp;c;cxx;rc;def;r;odl;idl;hpj;bat - - - {533b0c62-6839-47b0-bf0d-03e20a1a4e06} - h;hpp;hxx;hm;inl - - - {214ac298-955e-4931-a01c-3516a7206928} - ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - - - Resource Files - - - Source Files - - - \ No newline at end of file diff --git a/plugins/Avs/commonheaders.h b/plugins/Avs/commonheaders.h deleted file mode 100644 index 70b0c88fae..0000000000 --- a/plugins/Avs/commonheaders.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2004 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -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 MIRANDA_VER 0x0A00 -#define _WIN32_WINNT 0x0501 - -#include "m_stdhdr.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "m_folders.h" - -#include -#include -#include -#include "m_metacontacts.h" -#include "m_avatarhistory.h" - -#include "resource.h" -#include "m_updater.h" -#include "m_flash.h" -#include "image_utils.h" -#include "mir_thread.h" -#include "poll.h" -#include "m_acc.h" -#include "acc.h" - - -// shared vars -//extern HINSTANCE g_hInst; - -/* most free()'s are invalid when the code is executed from a dll, so this changes - all the bad free()'s to good ones, however it's still incorrect code. The reasons for not - changing them include: - - * DBFreeVariant has a CallService() lookup - * free() is executed in some large loops to do with clist creation of group data - * easy search and replace - -*/ - -// The same fields as avatarCacheEntry + proto name -struct protoPicCacheEntry : public avatarCacheEntry -{ - __inline void* operator new( size_t size ) { return mir_alloc( size ); } - __inline void operator delete( void* p ) { mir_free( p ); } - - protoPicCacheEntry() { memset(this, 0, sizeof(*this)); }; - ~protoPicCacheEntry(); - - void clear(); - - char* szProtoname; - TCHAR* tszAccName; -}; - -extern OBJLIST g_ProtoPictures, g_MyAvatars; - - -int SetAvatarAttribute(HANDLE hContact, DWORD attrib, int mode); - -#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) ) - - -#define GAIR_FAILED 1000 - -#define AVS_IGNORENOTIFY 0x1000 - -#define AVS_DEFAULT "Global avatar" diff --git a/plugins/Avs/image_utils.cpp b/plugins/Avs/image_utils.cpp deleted file mode 100644 index f6b6c7a98b..0000000000 --- a/plugins/Avs/image_utils.cpp +++ /dev/null @@ -1,757 +0,0 @@ -#include "commonheaders.h" -#include "image_utils.h" - -#include -#include - -/* -Theese are the ones needed -#include -#include -#include -#include -#include -#include -*/ - -extern int _DebugTrace(const char *fmt, ...); -extern int _DebugTrace(HANDLE hContact, const char *fmt, ...); - - -#define GET_PIXEL(__P__, __X__, __Y__) ( __P__ + width * 4 * (__Y__) + 4 * (__X__) ) - - -extern FI_INTERFACE *fei; - -// Make a bitmap all transparent, but only if it is a 32bpp -void MakeBmpTransparent(HBITMAP hBitmap) -{ - BITMAP bmp; - DWORD dwLen; - BYTE *p; - - GetObject(hBitmap, sizeof(bmp), &bmp); - - if (bmp.bmBitsPixel != 32) - return; - - dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); - p = (BYTE *)malloc(dwLen); - if (p == NULL) - return; - - memset(p, 0, dwLen); - SetBitmapBits(hBitmap, dwLen, p); - - free(p); -} - -// Resize ///////////////////////////////////////////////////////////////////////////////////////// - - -// Returns a copy of the bitmap with the size especified -// wParam = ResizeBitmap * -// lParam = NULL -INT_PTR BmpFilterResizeBitmap(WPARAM wParam,LPARAM lParam) -{ - // Call freeiamge service (is here only for backward compatibility) - return CallService(MS_IMG_RESIZE, wParam, lParam); -} - -HBITMAP CopyBitmapTo32(HBITMAP hBitmap) -{ - BITMAPINFO RGB32BitsBITMAPINFO; - BYTE * ptPixels; - HBITMAP hDirectBitmap; - - BITMAP bmp; - DWORD dwLen; - BYTE *p; - - GetObject(hBitmap, sizeof(bmp), &bmp); - - dwLen = bmp.bmWidth * bmp.bmHeight * 4; - p = (BYTE *)malloc(dwLen); - if (p == NULL) - return NULL; - - // Create bitmap - ZeroMemory(&RGB32BitsBITMAPINFO, sizeof(BITMAPINFO)); - RGB32BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - RGB32BitsBITMAPINFO.bmiHeader.biWidth = bmp.bmWidth; - RGB32BitsBITMAPINFO.bmiHeader.biHeight = bmp.bmHeight; - RGB32BitsBITMAPINFO.bmiHeader.biPlanes = 1; - RGB32BitsBITMAPINFO.bmiHeader.biBitCount = 32; - - hDirectBitmap = CreateDIBSection(NULL, - (BITMAPINFO *)&RGB32BitsBITMAPINFO, - DIB_RGB_COLORS, - (void **)&ptPixels, - NULL, 0); - - // Copy data - if (bmp.bmBitsPixel != 32) - { - HDC hdcOrig, hdcDest; - HBITMAP oldOrig, oldDest; - - hdcOrig = CreateCompatibleDC(NULL); - oldOrig = (HBITMAP) SelectObject(hdcOrig, hBitmap); - - hdcDest = CreateCompatibleDC(NULL); - oldDest = (HBITMAP) SelectObject(hdcDest, hDirectBitmap); - - BitBlt(hdcDest, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOrig, 0, 0, SRCCOPY); - - SelectObject(hdcDest, oldDest); - DeleteObject(hdcDest); - SelectObject(hdcOrig, oldOrig); - DeleteObject(hdcOrig); - - // Set alpha - fei->FI_CorrectBitmap32Alpha(hDirectBitmap, FALSE); - } - else - { - GetBitmapBits(hBitmap, dwLen, p); - SetBitmapBits(hDirectBitmap, dwLen, p); - } - - free(p); - - return hDirectBitmap; -} - -HBITMAP CreateBitmap32(int cx, int cy) -{ - BITMAPINFO RGB32BitsBITMAPINFO; - UINT * ptPixels; - HBITMAP DirectBitmap; - - ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); - RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); - RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth; - RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight; - RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; - RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; - - DirectBitmap = CreateDIBSection(NULL, - (BITMAPINFO *)&RGB32BitsBITMAPINFO, - DIB_RGB_COLORS, - (void **)&ptPixels, - NULL, 0); - return DirectBitmap; -} - -// Set the color of points that are transparent -void SetTranspBkgColor(HBITMAP hBitmap, COLORREF color) -{ - BITMAP bmp; - DWORD dwLen; - BYTE *p; - int x, y; - - GetObject(hBitmap, sizeof(bmp), &bmp); - - if (bmp.bmBitsPixel != 32) - return; - - dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); - p = (BYTE *)malloc(dwLen); - if (p == NULL) - return; - memset(p, 0, dwLen); - - GetBitmapBits(hBitmap, dwLen, p); - - bool changed = false; - for (y = 0; y < bmp.bmHeight; ++y) { - BYTE *px = p + bmp.bmWidth * 4 * y; - - for (x = 0; x < bmp.bmWidth; ++x) - { - if (px[3] == 0) - { - px[0] = GetBValue(color); - px[1] = GetGValue(color); - px[2] = GetRValue(color); - changed = true; - } - px += 4; - } - } - - if (changed) - SetBitmapBits(hBitmap, dwLen, p); - - free(p); -} - - -#define HIMETRIC_INCH 2540 // HIMETRIC units per inch - -void SetHIMETRICtoDP(HDC hdc, SIZE* sz) -{ - POINT pt; - int nMapMode = GetMapMode(hdc); - if ( nMapMode < MM_ISOTROPIC && nMapMode != MM_TEXT ) - { - // when using a constrained map mode, map against physical inch - SetMapMode(hdc,MM_HIMETRIC); - pt.x = sz->cx; - pt.y = sz->cy; - LPtoDP(hdc,&pt,1); - sz->cx = pt.x; - sz->cy = pt.y; - SetMapMode(hdc, nMapMode); - } - else - { - // map against logical inch for non-constrained mapping modes - int cxPerInch, cyPerInch; - cxPerInch = GetDeviceCaps(hdc,LOGPIXELSX); - cyPerInch = GetDeviceCaps(hdc,LOGPIXELSY); - sz->cx = MulDiv(sz->cx, cxPerInch, HIMETRIC_INCH); - sz->cy = MulDiv(sz->cy, cyPerInch, HIMETRIC_INCH); - } - - pt.x = sz->cx; - pt.y = sz->cy; - DPtoLP(hdc,&pt,1); - sz->cx = pt.x; - sz->cy = pt.y; -} - -INT_PTR BmpFilterLoadBitmap32(WPARAM wParam,LPARAM lParam) -{ - FIBITMAP *dib32 = NULL; - - if(fei == NULL) - return 0; - - FIBITMAP *dib = (FIBITMAP *)CallService(MS_IMG_LOAD, lParam, IMGL_RETURNDIB|IMGL_TCHAR); - - if(dib == NULL) - return 0; - - if(fei->FI_GetBPP(dib) != 32) { - dib32 = fei->FI_ConvertTo32Bits(dib); - fei->FI_Unload(dib); - } - else - dib32 = dib; - - if(dib32) { - if(fei->FI_IsTransparent(dib32)) { - if(wParam) { - DWORD *dwTrans = (DWORD *)wParam; - *dwTrans = 1; - } - } - if(fei->FI_GetWidth(dib32) > 128 || fei->FI_GetHeight(dib32) > 128) { - FIBITMAP *dib_new = fei->FI_MakeThumbnail(dib32, 128, FALSE); - fei->FI_Unload(dib32); - if(dib_new == NULL) - return 0; - dib32 = dib_new; - } - - HBITMAP bitmap = fei->FI_CreateHBITMAPFromDIB(dib32); - - fei->FI_Unload(dib32); - fei->FI_CorrectBitmap32Alpha(bitmap, FALSE); - return (INT_PTR)bitmap; - } - return 0; -} - -static HWND hwndClui = 0; - -// -// Save /////////////////////////////////////////////////////////////////////////////////////////// -// PNG and BMP will be saved as 32bit images, jpg as 24bit with default quality (75) -// returns 1 on success, 0 on failure - -int BmpFilterSaveBitmap(HBITMAP hBmp, char *szFile, int flags) -{ - IMGSRVC_INFO i = {0}; - i.cbSize = sizeof(IMGSRVC_INFO); - i.szName = szFile; - i.hbm = hBmp; - i.dwMask = IMGI_HBITMAP; - i.fif = FIF_UNKNOWN; - - return !CallService(MS_IMG_SAVE, (WPARAM) &i, MAKELONG(0, flags)); -} - - -int BmpFilterSaveBitmapW(HBITMAP hBmp, wchar_t *wszFile, int flags) -{ - IMGSRVC_INFO i = {0}; - i.cbSize = sizeof(IMGSRVC_INFO); - i.wszName = wszFile; - i.hbm = hBmp; - i.dwMask = IMGI_HBITMAP; - i.fif = FIF_UNKNOWN; - - return !CallService(MS_IMG_SAVE, (WPARAM) &i, MAKELONG(IMGL_WCHAR, flags)); -} - -// Save an HBITMAP to an image -// wParam = HBITMAP -// lParam = filename -INT_PTR BmpFilterSaveBitmap(WPARAM wParam,LPARAM lParam) -{ - if ( fei == NULL ) - return -1; - - const char *szFile = (const char*)lParam; - char szFilename[MAX_PATH]; - if ( !CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szFile, (LPARAM)szFilename)) - mir_snprintf(szFilename, SIZEOF(szFilename), "%s", szFile); - - int filenameLen = lstrlenA( szFilename ); - if ( filenameLen > 4 ) - return BmpFilterSaveBitmap(( HBITMAP )wParam, szFilename, 0); - - return -1; -} - -#if defined(_UNICODE) -INT_PTR BmpFilterSaveBitmapW(WPARAM wParam,LPARAM lParam) -{ - if ( fei == NULL ) - return -1; - - const wchar_t *wszFile = (const wchar_t *)lParam; - wchar_t wszFilename[MAX_PATH]; - if ( !CallService(MS_UTILS_PATHTOABSOLUTEW, (WPARAM)wszFile, (LPARAM)wszFilename)) - mir_sntprintf(wszFilename, SIZEOF(wszFilename), _T("%s"), wszFile); - - int filenameLen = lstrlenW( wszFilename ); - if ( filenameLen > 4 ) - return BmpFilterSaveBitmapW(( HBITMAP )wParam, wszFilename, 0 ); - - return -1; -} -#endif - -// Returns != 0 if can save that type of image, = 0 if cant -// wParam = 0 -// lParam = PA_FORMAT_* // image format -// kept for compatibilty - with freeimage we can save all common formats - -INT_PTR BmpFilterCanSaveBitmap(WPARAM wParam,LPARAM lParam) -{ - return 1; -} - - -// Other utilities //////////////////////////////////////////////////////////////////////////////// - - -static BOOL ColorsAreTheSame(int colorDiff, BYTE *px1, BYTE *px2) -{ - return abs(px1[0] - px2[0]) <= colorDiff - && abs(px1[1] - px2[1]) <= colorDiff - && abs(px1[2] - px2[2]) <= colorDiff; -} - - -void AddToStack(int *stack, int *topPos, int x, int y) -{ - int i; - - // Already is in stack? - for(i = 0 ; i < *topPos ; i += 2) - { - if (stack[i] == x && stack[i+1] == y) - return; - } - - stack[*topPos] = x; - (*topPos)++; - - stack[*topPos] = y; - (*topPos)++; -} - - -BOOL GetColorForPoint(int colorDiff, BYTE *p, int width, int height, - int x0, int y0, int x1, int y1, int x2, int y2, BOOL *foundBkg, BYTE colors[][3]) -{ - BYTE *px1, *px2, *px3; - - px1 = GET_PIXEL(p, x0,y0); - px2 = GET_PIXEL(p, x1,y1); - px3 = GET_PIXEL(p, x2,y2); - - // If any of the corners have transparency, forget about it - // Not using != 255 because some MSN bmps have 254 in some positions - if (px1[3] < 253 || px2[3] < 253 || px3[3] < 253) - return FALSE; - - // See if is the same color - if (ColorsAreTheSame(colorDiff, px1, px2) && ColorsAreTheSame(colorDiff, px3, px2)) - { - *foundBkg = TRUE; - memmove(colors, px1, 3); - } - else - { - *foundBkg = FALSE; - } - - return TRUE; -} - - -DWORD GetImgHash(HBITMAP hBitmap) -{ - BITMAP bmp; - DWORD dwLen; - WORD *p; - - GetObject(hBitmap, sizeof(bmp), &bmp); - - dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); - p = (WORD *)malloc(dwLen); - if (p == NULL) - return 0; - memset(p, 0, dwLen); - - GetBitmapBits(hBitmap, dwLen, p); - - DWORD ret = 0; - for (DWORD i = 0 ; i < dwLen/2 ; i++) - ret += p[i]; - - free(p); - - return ret; -} - -/* - * Changes the handle to a grayscale image - */ -HBITMAP MakeGrayscale(HANDLE hContact, HBITMAP hBitmap) -{ - if(hBitmap) { - FIBITMAP *dib = fei->FI_CreateDIBFromHBITMAP(hBitmap); - - if(dib) { - FIBITMAP *dib_new = fei->FI_ConvertToGreyscale(dib); - fei->FI_Unload(dib); - if(dib_new) { - DeleteObject(hBitmap); - HBITMAP hbm_new = fei->FI_CreateHBITMAPFromDIB(dib_new); - fei->FI_Unload(dib_new); - return hbm_new; - } - } - } - return hBitmap; -} - -/* - * See if finds a transparent background in image, and set its transparency - * Return TRUE if found a transparent background - */ -BOOL MakeTransparentBkg(HANDLE hContact, HBITMAP *hBitmap) -{ - BYTE *p = NULL; - DWORD dwLen; - int width, height, i, j; - BITMAP bmp; - BYTE colors[8][3]; - BOOL foundBkg[8]; - BYTE *px1; - int count, maxCount, selectedColor; - HBITMAP hBmpTmp; - int colorDiff; - - GetObject(*hBitmap, sizeof(bmp), &bmp); - width = bmp.bmWidth; - height = bmp.bmHeight; - colorDiff = DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgColorDiff", - DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10)); - - // Min 5x5 to easy things in loop - if (width <= 4 || height <= 4) - return FALSE; - - dwLen = width * height * 4; - p = (BYTE *)malloc(dwLen); - if (p == NULL) - { - return FALSE; - } - - if (bmp.bmBitsPixel == 32) - { - hBmpTmp = *hBitmap; - } - else - { - // Convert to 32 bpp - hBmpTmp = CopyBitmapTo32(*hBitmap); - } - - GetBitmapBits(hBmpTmp, dwLen, p); - - // **** Get corner colors - - // Top left - if (!GetColorForPoint(colorDiff, p, width, height, - 0, 0, 0, 1, 1, 0, &foundBkg[0], &colors[0])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Top center - if (!GetColorForPoint(colorDiff, p, width, height, - width/2, 0, width/2-1, 0, width/2+1, 0, &foundBkg[1], &colors[1])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Top Right - if (!GetColorForPoint(colorDiff, p, width, height, - width-1, 0, width-1, 1, width-2, 0, &foundBkg[2], &colors[2])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Center left - if (!GetColorForPoint(colorDiff, p, width, height, - 0, height/2, 0, height/2-1, 0, height/2+1, &foundBkg[3], &colors[3])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Center left - if (!GetColorForPoint(colorDiff, p, width, height, - width-1, height/2, width-1, height/2-1, width-1, height/2+1, &foundBkg[4], &colors[4])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Bottom left - if (!GetColorForPoint(colorDiff, p, width, height, - 0, height-1, 0, height-2, 1, height-1, &foundBkg[5], &colors[5])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Bottom center - if (!GetColorForPoint(colorDiff, p, width, height, - width/2, height-1, width/2-1, height-1, width/2+1, height-1, &foundBkg[6], &colors[6])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Bottom Right - if (!GetColorForPoint(colorDiff, p, width, height, - width-1, height-1, width-1, height-2, width-2, height-1, &foundBkg[7], &colors[7])) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // **** X corners have to have the same color - - count = 0; - for (i = 0 ; i < 8 ; i++) - { - if (foundBkg[i]) - count++; - } - - if (count < DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", - DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5))) - { - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Ok, X corners at least have a color, lets compare then - maxCount = 0; - for (i = 0 ; i < 8 ; i++) - { - if (foundBkg[i]) - { - count = 0; - - for (j = 0 ; j < 8 ; j++) - { - if (foundBkg[j] && ColorsAreTheSame(colorDiff, (BYTE *) &colors[i], (BYTE *) &colors[j])) - count++; - } - - if (count > maxCount) - { - maxCount = count; - selectedColor = i; - } - } - } - - if (maxCount < DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", - DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5))) - { - // Not enought corners with the same color - if (hBmpTmp != *hBitmap) DeleteObject(hBmpTmp); - free(p); - return FALSE; - } - - // Get bkg color as mean of colors - { - int bkgColor[3]; - - bkgColor[0] = 0; - bkgColor[1] = 0; - bkgColor[2] = 0; - for (i = 0 ; i < 8 ; i++) - { - if (foundBkg[i] && ColorsAreTheSame(colorDiff, (BYTE *) &colors[i], (BYTE *) &colors[selectedColor])) - { - bkgColor[0] += colors[i][0]; - bkgColor[1] += colors[i][1]; - bkgColor[2] += colors[i][2]; - } - } - bkgColor[0] /= maxCount; - bkgColor[1] /= maxCount; - bkgColor[2] /= maxCount; - - colors[selectedColor][0] = bkgColor[0]; - colors[selectedColor][1] = bkgColor[1]; - colors[selectedColor][2] = bkgColor[2]; - } - - // **** Set alpha for the background color, from the borders - - if (hBmpTmp != *hBitmap) - { - DeleteObject(*hBitmap); - - *hBitmap = hBmpTmp; - - GetObject(*hBitmap, sizeof(bmp), &bmp); - GetBitmapBits(*hBitmap, dwLen, p); - } - - { - // Set alpha from borders - int x, y; - int topPos = 0; - int curPos = 0; - int *stack = (int *)malloc(width * height * 2 * sizeof(int)); - bool transpProportional = (DBGetContactSettingByte(NULL, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", 0) != 0); - - if (stack == NULL) - { - free(p); - return FALSE; - } - - // Put four corners - AddToStack(stack, &topPos, 0, 0); - AddToStack(stack, &topPos, width/2, 0); - AddToStack(stack, &topPos, width-1, 0); - AddToStack(stack, &topPos, 0, height/2); - AddToStack(stack, &topPos, width-1, height/2); - AddToStack(stack, &topPos, 0, height-1); - AddToStack(stack, &topPos, width/2, height-1); - AddToStack(stack, &topPos, width-1, height-1); - - while(curPos < topPos) - { - // Get pos - x = stack[curPos]; curPos++; - y = stack[curPos]; curPos++; - - // Get pixel - px1 = GET_PIXEL(p, x, y); - - // It won't change the transparency if one exists - // (This avoid an endless loop too) - // Not using == 255 because some MSN bmps have 254 in some positions - if (px1[3] >= 253) - { - if (ColorsAreTheSame(colorDiff, px1, (BYTE *) &colors[selectedColor])) - { - if (transpProportional) - { - px1[3] = min(252, - (abs(px1[0] - colors[selectedColor][0]) - + abs(px1[1] - colors[selectedColor][1]) - + abs(px1[2] - colors[selectedColor][2])) / 3); - } - else - { - px1[3] = 0; - } - - // Add 4 neighbours - - if (x + 1 < width) - AddToStack(stack, &topPos, x + 1, y); - - if (x - 1 >= 0) - AddToStack(stack, &topPos, x - 1, y); - - if (y + 1 < height) - AddToStack(stack, &topPos, x, y + 1); - - if (y - 1 >= 0) - AddToStack(stack, &topPos, x, y - 1); - } - } - } - - free(stack); - } - - dwLen = SetBitmapBits(*hBitmap, dwLen, p); - free(p); - - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Other utils - -int SaveAvatar( const char* protocol, const TCHAR* tszFileName ) -{ - int result = CallProtoService(protocol, PS_SETMYAVATART, 0, ( LPARAM )tszFileName); - #if defined( _UNICODE ) - if ( result == CALLSERVICE_NOTFOUND ) { - if ( tszFileName != NULL ) { - char szFileName[ MAX_PATH ]; - WideCharToMultiByte( CP_ACP, 0, tszFileName, -1, szFileName, SIZEOF(szFileName), 0, 0 ); - result = CallProtoService(protocol, PS_SETMYAVATAR, 0, ( LPARAM )szFileName); - } - else result = CallProtoService(protocol, PS_SETMYAVATAR, 0, 0); - } - #endif - - return result; -} diff --git a/plugins/Avs/image_utils.h b/plugins/Avs/image_utils.h deleted file mode 100644 index 2dd75d8211..0000000000 --- a/plugins/Avs/image_utils.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __IMAGE_UTILS_H__ -# define __IMAGE_UTILS_H__ - -#define _WIN32_WINNT 0x0501 -#include - -#include - - -// Load an image -// wParam = NULL -// lParam = filename -INT_PTR BmpFilterLoadBitmap32(WPARAM wParam,LPARAM lParam); - -// Save an HBITMAP to an image -// wParam = HBITMAP -// lParam = full path of filename -INT_PTR BmpFilterSaveBitmap(WPARAM wParam,LPARAM lParam); -#if defined(_UNICODE) - INT_PTR BmpFilterSaveBitmapW(WPARAM wParam,LPARAM lParam); - #define BmpFilterSaveBitmapT BmpFilterSaveBitmapW -#else - #define BmpFilterSaveBitmapT BmpFilterSaveBitmap -#endif - -// Returns != 0 if can save that type of image, = 0 if cant -// wParam = 0 -// lParam = PA_FORMAT_* // image format -INT_PTR BmpFilterCanSaveBitmap(WPARAM wParam,LPARAM lParam); - -// Returns a copy of the bitmap with the size especified or the original bitmap if nothing has to be changed -// wParam = ResizeBitmap * -// lParam = NULL -INT_PTR BmpFilterResizeBitmap(WPARAM wParam,LPARAM lParam); - - -int BmpFilterSaveBitmap(HBITMAP hBmp, char *szFile, int flags); -#if defined(_UNICODE) - int BmpFilterSaveBitmapW(HBITMAP hBmp, wchar_t *wszFile, int flags); - #define BmpFilterSaveBitmapT BmpFilterSaveBitmapW -#else - #define BmpFilterSaveBitmapT BmpFilterSaveBitmap -#endif - -HBITMAP CopyBitmapTo32(HBITMAP hBitmap); - -BOOL PreMultiply(HBITMAP hBitmap); -BOOL MakeTransparentBkg(HANDLE hContact, HBITMAP *hBitmap); -HBITMAP MakeGrayscale(HANDLE hContact, HBITMAP hBitmap); -DWORD GetImgHash(HBITMAP hBitmap); - -int AVS_pathIsAbsolute(const TCHAR *path); -size_t AVS_pathToRelative(const TCHAR *sPrc, TCHAR *pOut); -size_t AVS_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut); - -int SaveAvatar( const char* protocol, const TCHAR* tszFileName ); - -#endif // __IMAGE_UTILS_H__ diff --git a/plugins/Avs/license.txt b/plugins/Avs/license.txt deleted file mode 100644 index 7f1161073d..0000000000 --- a/plugins/Avs/license.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - 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 - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/plugins/Avs/main.cpp b/plugins/Avs/main.cpp deleted file mode 100644 index bb4ebc236f..0000000000 --- a/plugins/Avs/main.cpp +++ /dev/null @@ -1,2684 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2004 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" -#include "version.h" - -HINSTANCE g_hInst = 0; -PLUGINLINK *pluginLink; -MM_INTERFACE mmi; -LIST_INTERFACE li; -int hLangpack; - -static TCHAR g_szDataPath[MAX_PATH]; // user datae path (read at startup only) -static BOOL g_MetaAvail = FALSE; -BOOL g_AvatarHistoryAvail = FALSE; -static long hwndSetMyAvatar = 0; - -static HANDLE hMyAvatarsFolder = 0; -static HANDLE hGlobalAvatarFolder = 0; -static HANDLE hLoaderEvent = 0; -static HANDLE hLoaderThread = 0; - -static HANDLE hOptInit = 0; -static HANDLE hModulesLoaded = 0; -static HANDLE hPresutdown = 0; -static HANDLE hOkToExit = 0; -static HANDLE hAccChanged = 0; - -HANDLE hProtoAckHook = 0, hContactSettingChanged = 0, hEventChanged = 0, hEventContactAvatarChanged = 0, - hMyAvatarChanged = 0, hEventDeleted = 0, hUserInfoInitHook = 0; -HICON g_hIcon = 0; - -BOOL (WINAPI *AvsAlphaBlend)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION) = NULL; - -static struct CacheNode *g_Cache = 0; -static CRITICAL_SECTION cachecs, alloccs; - -static int ComparePicture( const protoPicCacheEntry* p1, const protoPicCacheEntry* p2 ) -{ - if ((lstrcmpA(p1->szProtoname, "Global avatar") == 0) || strstr(p1->szProtoname, "Global avatar")) - return -1; - if ((lstrcmpA(p2->szProtoname, "Global avatar") == 0) || strstr(p1->szProtoname, "Global avatar")) - return 1; - return lstrcmpA( p1->szProtoname, p2->szProtoname ); -} - -OBJLIST - g_ProtoPictures( 10, ComparePicture ), - g_MyAvatars( 10, ComparePicture ); - -char* g_szMetaName = NULL; - -#ifndef SHVIEW_THUMBNAIL -#define SHVIEW_THUMBNAIL 0x702D -#endif - -// Stores the id of the dialog - -int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist = FALSE, int pa_format = 0); -static int ShutdownProc(WPARAM wParam, LPARAM lParam); -static int OkToExitProc(WPARAM wParam, LPARAM lParam); -static int OnDetailsInit(WPARAM wParam, LPARAM lParam); -static int GetFileHash(TCHAR* filename); -static DWORD GetFileSize(TCHAR *szFilename); - -void ProcessAvatarInfo(HANDLE hContact, int type, PROTO_AVATAR_INFORMATIONT *pai, const char *szProto); -int FetchAvatarFor(HANDLE hContact, char *szProto = NULL); -static INT_PTR ReportMyAvatarChanged(WPARAM wParam, LPARAM lParam); - -BOOL Proto_IsAvatarsEnabled(const char *proto); -BOOL Proto_IsAvatarFormatSupported(const char *proto, int format); -void Proto_GetAvatarMaxSize(const char *proto, int *width, int *height); -int Proto_AvatarImageProportion(const char *proto); -BOOL Proto_NeedDelaysForAvatars(const char *proto); -int Proto_GetAvatarMaxFileSize(const char *proto); -int Proto_GetDelayAfterFail(const char *proto); - -FI_INTERFACE *fei = 0; - -PLUGININFOEX pluginInfoEx = { - sizeof(PLUGININFOEX), -#if defined(_UNICODE) - "Avatar service (Unicode)", -#else - "Avatar service", -#endif - __VERSION_DWORD, - "Load and manage contact pictures for other plugins.", - "Nightwish, Pescuma", - "", - "Copyright 2000-2012 Miranda-IM project", - "http://www.miranda-im.org", - UNICODE_AWARE, - 0, -#if defined(_UNICODE) -// {E00F1643-263C-4599-B84B-053E5C511D29} - { 0xe00f1643, 0x263c, 0x4599, { 0xb8, 0x4b, 0x5, 0x3e, 0x5c, 0x51, 0x1d, 0x29 } } -#else -// {C9E01EB0-A119-42d2-B340-E8678F5FEAD8} - { 0xc9e01eb0, 0xa119, 0x42d2, { 0xb3, 0x40, 0xe8, 0x67, 0x8f, 0x5f, 0xea, 0xd8 } } -#endif -}; - -extern INT_PTR CALLBACK DlgProcOptionsAvatars(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -extern INT_PTR CALLBACK DlgProcOptionsProtos(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -extern INT_PTR CALLBACK DlgProcOptionsOwn(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -extern INT_PTR CALLBACK DlgProcAvatarOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -extern INT_PTR CALLBACK DlgProcAvatarUserInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); -extern INT_PTR CALLBACK DlgProcAvatarProtoInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); - - -static int SetProtoMyAvatar(char *protocol, HBITMAP hBmp, TCHAR *originalFilename, int format, BOOL square, BOOL grow); - -// See if a protocol service exists -int ProtoServiceExists(const char *szModule,const char *szService) -{ - char str[MAXMODULELABELLENGTH * 2]; - strcpy(str,szModule); - strcat(str,szService); - return ServiceExists(str); -} - - -/* - * output a notification message. - * may accept a hContact to include the contacts nickname in the notification message... - * the actual message is using printf() rules for formatting and passing the arguments... - * - * can display the message either as systray notification (baloon popup) or using the - * popup plugin. - */ - -#ifdef _DEBUG - -int _DebugTrace(const char *fmt, ...) -{ - char debug[2048]; - int ibsize = 2047; - va_list va; - va_start(va, fmt); - - mir_snprintf(debug, SIZEOF(debug) - 10, " ***** AVS [%08d] [ID:%04x]: ", GetTickCount(), GetCurrentThreadId()); - OutputDebugStringA(debug); - _vsnprintf(debug, ibsize, fmt, va); - OutputDebugStringA(debug); - OutputDebugStringA(" ***** \n"); - - return 0; -} - -int _DebugTrace(HANDLE hContact, const char *fmt, ...) -{ - char text[1024]; - size_t len; - va_list va; - - char *name = NULL; - char *proto = NULL; - if (hContact != NULL) - { - name = (char*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0); - proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - } - - mir_snprintf(text, SIZEOF(text) - 10, " ***** AVS [%08d] [ID:%04x]: [%08d - %s - %s] ", - GetTickCount(), GetCurrentThreadId(), hContact, proto == NULL ? "" : proto, name == NULL ? "" : name); - len = strlen(text); - - va_start(va, fmt); - mir_vsnprintf(&text[len], SIZEOF(text) - len, fmt, va); - va_end(va); - - OutputDebugStringA(text); - OutputDebugStringA(" ***** \n"); - - return 0; -} - -#endif - -/* - * path utilities (make avatar paths relative to *PROFILE* directory, not miranda directory. - * taken and modified from core services - */ - -int AVS_pathIsAbsolute(const TCHAR *path) -{ - if (!path || !(lstrlen(path) > 2)) - return 0; - if ((path[1]==':'&&path[2]=='\\')||(path[0]=='\\'&&path[1]=='\\')) return 1; - return 0; -} - -size_t AVS_pathToRelative(const TCHAR *pSrc, TCHAR *pOut) -{ - if (!pSrc || !*pSrc || _tcslen(pSrc) > MAX_PATH) return 0; - if (!AVS_pathIsAbsolute( pSrc )) - lstrcpyn(pOut, pSrc, MAX_PATH); - else { - TCHAR szTmp[MAX_PATH]; - mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc); - _tcslwr(szTmp); - if (_tcsstr(szTmp, g_szDataPath)) - lstrcpyn(pOut, pSrc + _tcslen(g_szDataPath) + 1, MAX_PATH); - else - lstrcpyn(pOut, pSrc, MAX_PATH); - } - return _tcslen(pOut); -} - -size_t AVS_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut) -{ - if (!pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH) - return 0; - - if (AVS_pathIsAbsolute(pSrc) || !_istalnum(pSrc[0])) - lstrcpyn(pOut, pSrc, MAX_PATH); - else - mir_sntprintf(pOut, MAX_PATH, _T("%s\\%s"), g_szDataPath, pSrc, MAX_PATH); - return lstrlen(pOut); -} - -static void NotifyMetaAware(HANDLE hContact, struct CacheNode *node = NULL, AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)-1) -{ - if (ace == (AVATARCACHEENTRY *)-1) - ace = &node->ace; - - NotifyEventHooks(hEventChanged, (WPARAM)hContact, (LPARAM)ace); - - if (g_MetaAvail && (node->dwFlags & MC_ISSUBCONTACT) && DBGetContactSettingByte(NULL, g_szMetaName, "Enabled", 0)) { - HANDLE hMasterContact = (HANDLE)DBGetContactSettingDword(hContact, g_szMetaName, "Handle", 0); - - if (hMasterContact && (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hMasterContact, 0) == hContact && - !DBGetContactSettingByte(hMasterContact, "ContactPhoto", "Locked", 0)) - NotifyEventHooks(hEventChanged, (WPARAM)hMasterContact, (LPARAM)ace); - } - if (node->dwFlags & AVH_MUSTNOTIFY) { - // Fire the event for avatar history - node->dwFlags &= ~AVH_MUSTNOTIFY; - if (node->ace.szFilename[0] != '\0') { - CONTACTAVATARCHANGEDNOTIFICATION cacn = {0}; - cacn.cbSize = sizeof(CONTACTAVATARCHANGEDNOTIFICATION); - cacn.hContact = hContact; - cacn.format = node->pa_format; - _tcsncpy(cacn.filename, node->ace.szFilename, MAX_PATH); - cacn.filename[MAX_PATH - 1] = 0; - - // Get hash - char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto != NULL) { - DBVARIANT dbv = {0}; - if (!DBGetContactSetting(hContact, szProto, "AvatarHash", &dbv)) { - if (dbv.type == DBVT_TCHAR) { - _tcsncpy(cacn.hash, dbv.ptszVal, SIZEOF(cacn.hash)); - } else if (dbv.type == DBVT_BLOB) { - // Lets use base64 encode - char *tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - int i; - for(i = 0; i < dbv.cpbVal / 3 && i*4+3 < sizeof(cacn.hash)-1; i++) { - BYTE a = dbv.pbVal[i*3]; - BYTE b = i*3 + 1 < dbv.cpbVal ? dbv.pbVal[i*3 + 1] : 0; - BYTE c = i*3 + 2 < dbv.cpbVal ? dbv.pbVal[i*3 + 2] : 0; - - cacn.hash[i*4] = tab[(a & 0xFC) >> 2]; - cacn.hash[i*4+1] = tab[((a & 0x3) << 4) + ((b & 0xF0) >> 4)]; - cacn.hash[i*4+2] = tab[((b & 0xF) << 2) + ((c & 0xC0) >> 6)]; - cacn.hash[i*4+3] = tab[c & 0x3F]; - } - if (dbv.cpbVal % 3 != 0 && i*4+3 < sizeof(cacn.hash)-1) { - BYTE a = dbv.pbVal[i*3]; - BYTE b = i*3 + 1 < dbv.cpbVal ? dbv.pbVal[i*3 + 1] : 0; - - cacn.hash[i*4] = tab[(a & 0xFC) >> 2]; - cacn.hash[i*4+1] = tab[((a & 0x3) << 4) + ((b & 0xF0) >> 4)]; - if (i + 1 < dbv.cpbVal) - cacn.hash[i*4+2] = tab[((b & 0xF) << 4)]; - else - cacn.hash[i*4+2] = '='; - cacn.hash[i*4+3] = '='; - } - } - DBFreeVariant(&dbv); - } - } - - // Default value - if (cacn.hash[0] == '\0') - mir_sntprintf(cacn.hash, SIZEOF(cacn.hash), _T("AVS-HASH-%x"), GetFileHash(cacn.filename)); - - NotifyEventHooks(hEventContactAvatarChanged, (WPARAM)cacn.hContact, (LPARAM)&cacn); - } - else - NotifyEventHooks(hEventContactAvatarChanged, (WPARAM)hContact, NULL); - } -} - -static int g_maxBlock = 0, g_curBlock = 0; -static struct CacheNode **g_cacheBlocks = NULL; - -/* - * allocate a cache block and add it to the list of blocks - * does not link the new block with the old block(s) - caller needs to do this - */ - -static struct CacheNode *AllocCacheBlock() -{ - struct CacheNode *allocedBlock = NULL; - - allocedBlock = (struct CacheNode *)malloc(CACHE_BLOCKSIZE * sizeof(struct CacheNode)); - ZeroMemory((void *)allocedBlock, sizeof(struct CacheNode) * CACHE_BLOCKSIZE); - - for(int i = 0; i < CACHE_BLOCKSIZE - 1; i++) - { - //InitializeCriticalSection(&allocedBlock[i].cs); - allocedBlock[i].pNextNode = &allocedBlock[i + 1]; // pre-link the alloced block - } - //InitializeCriticalSection(&allocedBlock[CACHE_BLOCKSIZE - 1].cs); - - if (g_Cache == NULL) // first time only... - g_Cache = allocedBlock; - - // add it to the list of blocks - - if (g_curBlock == g_maxBlock) { - g_maxBlock += 10; - g_cacheBlocks = (struct CacheNode **)realloc(g_cacheBlocks, g_maxBlock * sizeof(struct CacheNode *)); - } - g_cacheBlocks[g_curBlock++] = allocedBlock; - - return(allocedBlock); -} - -int SetAvatarAttribute(HANDLE hContact, DWORD attrib, int mode) -{ - struct CacheNode *cacheNode = g_Cache; - - while(cacheNode) { - if (cacheNode->ace.hContact == hContact) { - DWORD dwFlags = cacheNode->ace.dwFlags; - - cacheNode->ace.dwFlags = mode ? cacheNode->ace.dwFlags | attrib : cacheNode->ace.dwFlags & ~attrib; - if (cacheNode->ace.dwFlags != dwFlags) - NotifyMetaAware(hContact, cacheNode); - break; - } - cacheNode = cacheNode->pNextNode; - } - return 0; -} - -/* - * convert the avatar image path to a relative one... - * given: contact handle, path to image - */ -void MakePathRelative(HANDLE hContact, TCHAR *path) -{ - TCHAR szFinalPath[MAX_PATH]; - szFinalPath[0] = '\0'; - - size_t result = AVS_pathToRelative(path, szFinalPath); - if (result && lstrlen(szFinalPath) > 0) { - DBWriteContactSettingTString(hContact, "ContactPhoto", "RFile", szFinalPath); - if (!DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0)) - DBWriteContactSettingTString(hContact, "ContactPhoto", "Backup", szFinalPath); - } -} - -/* - * convert the avatar image path to a relative one... - * given: contact handle - */ - -static void MakePathRelative(HANDLE hContact) -{ - DBVARIANT dbv = {0}; - - if (!DBGetContactSetting(hContact, "ContactPhoto", "File", &dbv)) { - if (dbv.type == DBVT_TCHAR) { - MakePathRelative(hContact, dbv.ptszVal); - } - DBFreeVariant(&dbv); - } -} - -static void ResetTranspSettings(HANDLE hContact) -{ - DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); -} - -static TCHAR *getJGMailID(char *szProto) -{ - static TCHAR szJID[MAX_PATH+1]; - DBVARIANT dbva={0}, dbvb={0}; - - szJID[0] = '\0'; - if (DBGetContactSettingTString(NULL, szProto, "LoginName", &dbva)) - return szJID; - if (DBGetContactSettingTString(NULL, szProto, "LoginServer", &dbvb)) { - DBFreeVariant(&dbva); - return szJID; - } - - mir_sntprintf(szJID, SIZEOF(szJID), _T("%s@%s"), dbva.ptszVal, dbvb.ptszVal); - DBFreeVariant(&dbva); - DBFreeVariant(&dbvb); - return szJID; -} - -// create the avatar in cache -// returns 0 if not created (no avatar), iIndex otherwise, -2 if has to request avatar, -3 if avatar too big -int CreateAvatarInCache(HANDLE hContact, avatarCacheEntry *ace, char *szProto) -{ - DBVARIANT dbv = {0}; - char *szExt = NULL; - TCHAR tszFilename[MAX_PATH]; - HANDLE hFile = INVALID_HANDLE_VALUE; - DWORD dwFileSizeHigh = 0, dwFileSize = 0, sizeLimit = 0; - - tszFilename[0] = 0; - - ace->hbmPic = 0; - ace->dwFlags = 0; - ace->bmHeight = 0; - ace->bmWidth = 0; - ace->lpDIBSection = NULL; - ace->szFilename[0] = 0; - - if (szProto == NULL) { - char *proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (proto == NULL || !DBGetContactSettingByte(NULL, AVS_MODULE, proto, 1)) { - return -1; - } - - if (DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) - && !DBGetContactSettingTString(hContact, "ContactPhoto", "Backup", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "RFile", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - else { - return -2; - } - } - else { - if (hContact == 0) { // create a protocol picture in the proto picture cache - if (!DBGetContactSettingTString(NULL, PPICT_MODULE, szProto, &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - else { - if (lstrcmpA(szProto, AVS_DEFAULT)) { - if (!DBGetContactSettingTString(NULL, PPICT_MODULE, AVS_DEFAULT, &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - - if (!strstr(szProto, "Global avatar for")) { - PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)szProto); - if (pdescr == NULL) - return -1; - char key[MAX_PATH]; - mir_snprintf(key, SIZEOF(key), "Global avatar for %s accounts", pdescr->szProtoName); - if (!DBGetContactSettingTString(NULL, PPICT_MODULE, key, &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - } - } - } - } - else if (hContact == (HANDLE)-1) { // create own picture - note, own avatars are not on demand, they are loaded once at - // startup and everytime they are changed. - if (szProto[0] == '\0') { - // Global avatar - if ( DBGetContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) - return -10; - - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - else if (ProtoServiceExists(szProto, PS_GETMYAVATART)) { - if (CallProtoService(szProto, PS_GETMYAVATART, (WPARAM)tszFilename, (LPARAM)MAX_PATH)) - tszFilename[0] = '\0'; - } -#if defined( _UNICODE ) - else if (ProtoServiceExists(szProto, PS_GETMYAVATAR)) { - char szFileName[ MAX_PATH ]; - if (CallProtoService(szProto, PS_GETMYAVATAR, (WPARAM)szFileName, (LPARAM)MAX_PATH)) - tszFilename[0] = '\0'; - else - MultiByteToWideChar( CP_ACP, 0, szFileName, -1, tszFilename, SIZEOF( tszFilename )); - } -#endif - else if (!DBGetContactSettingTString(NULL, szProto, "AvatarFile", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, tszFilename); - DBFreeVariant(&dbv); - } - else return -1; - } - } - - if ( lstrlen(tszFilename) < 4 ) - return -1; - - TCHAR* tmpPath = Utils_ReplaceVarsT(tszFilename); - mir_sntprintf(tszFilename, SIZEOF(tszFilename), _T("%s"), tmpPath); - mir_free(tmpPath); - - if ((hFile = CreateFile(tszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) - return -2; - - CloseHandle(hFile); - WPARAM isTransparentImage = 0; - - ace->hbmPic = (HBITMAP) BmpFilterLoadBitmap32((WPARAM)&isTransparentImage, (LPARAM)tszFilename); - ace->dwFlags = 0; - ace->bmHeight = 0; - ace->bmWidth = 0; - ace->lpDIBSection = NULL; - _tcsncpy(ace->szFilename, tszFilename, MAX_PATH); - ace->szFilename[MAX_PATH - 1] = 0; - if (ace->hbmPic != 0) { - BITMAP bminfo; - - GetObject(ace->hbmPic, sizeof(bminfo), &bminfo); - - ace->cbSize = sizeof(avatarCacheEntry); - ace->dwFlags = AVS_BITMAP_VALID; - if (hContact != NULL && DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0)) - ace->dwFlags |= AVS_HIDEONCLIST; - ace->hContact = hContact; - ace->bmHeight = bminfo.bmHeight; - ace->bmWidth = bminfo.bmWidth; - - BOOL noTransparency = DBGetContactSettingByte(0, AVS_MODULE, "RemoveAllTransparency", 0); - - // Calc image hash - if (hContact != 0 && hContact != (HANDLE)-1) - { - // Have to reset settings? -> do it if image changed - DWORD imgHash = GetImgHash(ace->hbmPic); - - if (imgHash != DBGetContactSettingDword(hContact, "ContactPhoto", "ImageHash", 0)) - { - ResetTranspSettings(hContact); - DBWriteContactSettingDword(hContact, "ContactPhoto", "ImageHash", imgHash); - } - - // Make transparent? - if (!noTransparency && !isTransparentImage - && DBGetContactSettingByte(hContact, "ContactPhoto", "MakeTransparentBkg", - DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0))) - { - if (MakeTransparentBkg(hContact, &ace->hbmPic)) - { - ace->dwFlags |= AVS_CUSTOMTRANSPBKG | AVS_HASTRANSPARENCY; - GetObject(ace->hbmPic, sizeof(bminfo), &bminfo); - isTransparentImage = TRUE; - } - } - } - else if (hContact == (HANDLE)-1) // My avatars - { - if (!noTransparency && !isTransparentImage - && DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0) - && DBGetContactSettingByte(0, AVS_MODULE, "MakeMyAvatarsTransparent", 0)) - { - if (MakeTransparentBkg(0, &ace->hbmPic)) - { - ace->dwFlags |= AVS_CUSTOMTRANSPBKG | AVS_HASTRANSPARENCY; - GetObject(ace->hbmPic, sizeof(bminfo), &bminfo); - isTransparentImage = TRUE; - } - } - } - - if (DBGetContactSettingByte(0, AVS_MODULE, "MakeGrayscale", 0)) - { - ace->hbmPic = MakeGrayscale(hContact, ace->hbmPic); - } - - if (noTransparency) - { - fei->FI_CorrectBitmap32Alpha(ace->hbmPic, TRUE); - isTransparentImage = FALSE; - } - - if (bminfo.bmBitsPixel == 32 && isTransparentImage) - { - if (fei->FI_Premultiply(ace->hbmPic)) - { - ace->dwFlags |= AVS_HASTRANSPARENCY; - } - ace->dwFlags |= AVS_PREMULTIPLIED; - } - - if (szProto) - { - protoPicCacheEntry *pAce = (protoPicCacheEntry *)ace; - if (hContact == 0) - pAce->dwFlags |= AVS_PROTOPIC; - else if (hContact == (HANDLE)-1) - pAce->dwFlags |= AVS_OWNAVATAR; - } - - return 1; - } - return -1; -} - -/* - * link a new cache block with the already existing chain of blocks - */ - -static struct CacheNode *AddToList(struct CacheNode *node) { - struct CacheNode *pCurrent = g_Cache; - - while(pCurrent->pNextNode != 0) - pCurrent = pCurrent->pNextNode; - - pCurrent->pNextNode = node; - return pCurrent; -} - -struct CacheNode *FindAvatarInCache(HANDLE hContact, BOOL add, BOOL findAny = FALSE) -{ - struct CacheNode *cacheNode = g_Cache, *foundNode = NULL; - - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto == NULL || !DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1)) - return NULL; - - EnterCriticalSection(&cachecs); - - while(cacheNode) - { - if (cacheNode->ace.hContact == hContact) - { - cacheNode->ace.t_lastAccess = time(NULL); - foundNode = cacheNode->loaded || findAny ? cacheNode : NULL; - LeaveCriticalSection(&cachecs); - return foundNode; - } - if (foundNode == NULL && cacheNode->ace.hContact == 0) - foundNode = cacheNode; // found an empty and usable node - - cacheNode = cacheNode->pNextNode; - } - - // not found - - if (add) - { - if (foundNode == NULL) { // no free entry found, create a new and append it to the list - EnterCriticalSection(&alloccs); // protect memory block allocation - struct CacheNode *newNode = AllocCacheBlock(); - AddToList(newNode); - foundNode = newNode; - LeaveCriticalSection(&alloccs); - } - - foundNode->ace.hContact = hContact; - if (g_MetaAvail) - foundNode->dwFlags |= (DBGetContactSettingByte(hContact, g_szMetaName, "IsSubcontact", 0) ? MC_ISSUBCONTACT : 0); - foundNode->loaded = FALSE; - foundNode->mustLoad = 1; // pic loader will watch this and load images - LeaveCriticalSection(&cachecs); - SetEvent(hLoaderEvent); // wake him up - return NULL; - } - else - { - foundNode = NULL; - } - LeaveCriticalSection(&cachecs); - return foundNode; -} - -#define POLYNOMIAL (0x488781ED) /* This is the CRC Poly */ -#define TOPBIT (1 << (WIDTH - 1)) /* MSB */ -#define WIDTH 32 - -static int GetFileHash(TCHAR* filename) -{ - HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return 0; - - int remainder = 0; - char data[1024]; - DWORD dwRead; - do - { - // Read file chunk - dwRead = 0; - ReadFile(hFile, data, 1024, &dwRead, NULL); - - /* loop through each byte of data */ - for (int byte = 0; byte < (int) dwRead; ++byte) { - /* store the next byte into the remainder */ - remainder ^= (data[byte] << (WIDTH - 8)); - /* calculate for all 8 bits in the byte */ - for (int bit = 8; bit > 0; --bit) { - /* check if MSB of remainder is a one */ - if (remainder & TOPBIT) - remainder = (remainder << 1) ^ POLYNOMIAL; - else - remainder = (remainder << 1); - } - } - } while(dwRead == 1024); - - CloseHandle(hFile); - - return remainder; -} - -static int ProtocolAck(WPARAM wParam, LPARAM lParam) -{ - ACKDATA *ack = (ACKDATA *) lParam; - - if (ack != NULL && ack->type == ACKTYPE_AVATAR && ack->hContact != 0 - // Ignore metacontacts - && (!g_MetaAvail || strcmp(ack->szModule, g_szMetaName))) - { - if (ack->result == ACKRESULT_SUCCESS) - { - if (ack->hProcess == NULL) - ProcessAvatarInfo(ack->hContact, GAIR_NOAVATAR, NULL, ack->szModule); - else - ProcessAvatarInfo(ack->hContact, GAIR_SUCCESS, (PROTO_AVATAR_INFORMATIONT *) ack->hProcess, ack->szModule); - } - else if (ack->result == ACKRESULT_FAILED) - { - ProcessAvatarInfo(ack->hContact, GAIR_FAILED, (PROTO_AVATAR_INFORMATIONT *) ack->hProcess, ack->szModule); - } - else if (ack->result == ACKRESULT_STATUS) - { - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)ack->hContact, 0); - if (szProto == NULL || Proto_NeedDelaysForAvatars(szProto)) - { - // Queue - DBWriteContactSettingByte(ack->hContact, "ContactPhoto", "NeedUpdate", 1); - QueueAdd(ack->hContact); - } - else - { - // Fetch it now - FetchAvatarFor(ack->hContact, szProto); - } - } - } - return 0; -} - -INT_PTR ProtectAvatar(WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact = (HANDLE)wParam; - BYTE was_locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); - - if (fei == NULL || was_locked == (BYTE)lParam) // no need for redundant lockings... - return 0; - - if (hContact) { - if (!was_locked) - MakePathRelative(hContact); - DBWriteContactSettingByte(hContact, "ContactPhoto", "Locked", lParam ? 1 : 0); - if (lParam == 0) - MakePathRelative(hContact); - ChangeAvatar(hContact, TRUE); - } - return 0; -} - -/* - * for subclassing the open file dialog... - */ -struct OpenFileSubclassData { - BYTE *locking_request; - BYTE setView; -}; - -static BOOL CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) { - case WM_INITDIALOG: - { - OPENFILENAME *ofn = (OPENFILENAME *)lParam; - - OpenFileSubclassData *data = (OpenFileSubclassData *) malloc(sizeof(OpenFileSubclassData)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)data); - data->locking_request = (BYTE *)ofn->lCustData; - data->setView = TRUE; - - TranslateDialogDefault(hwnd); - CheckDlgButton(hwnd, IDC_PROTECTAVATAR, *(data->locking_request)); - break; - } - - case WM_COMMAND: - if (LOWORD(wParam) == IDC_PROTECTAVATAR) - { - OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - *(data->locking_request) = IsDlgButtonChecked(hwnd, IDC_PROTECTAVATAR) ? TRUE : FALSE; - } - break; - - case WM_NOTIFY: - { - OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (data->setView) - { - HWND hwndParent = GetParent(hwnd); - HWND hwndLv = FindWindowEx(hwndParent, NULL, _T("SHELLDLL_DefView"), NULL) ; - if (hwndLv != NULL) - { - SendMessage(hwndLv, WM_COMMAND, SHVIEW_THUMBNAIL, 0); - data->setView = FALSE; - } - } - } - break; - - case WM_NCDESTROY: - OpenFileSubclassData *data= (OpenFileSubclassData *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - free((OpenFileSubclassData *)data); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)0); - break; - } - - return FALSE; -} - -/* - * set an avatar (service function) - * if lParam == NULL, a open file dialog will be opened, otherwise, lParam is taken as a FULL - * image filename (will be checked for existance, though) - */ - -INT_PTR avSetAvatar(HANDLE hContact, TCHAR* tszPath) -{ - BYTE is_locked = 0; - TCHAR FileName[MAX_PATH], szBackupName[MAX_PATH]; - TCHAR *szFinalName = NULL; - HANDLE hFile = 0; - BYTE locking_request; - - if (hContact == NULL || fei == NULL) - return 0; - - is_locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); - - if ( tszPath == NULL ) { - OPENFILENAME ofn = {0}; - TCHAR filter[256]; - - filter[0] = '\0'; - CallService(MS_UTILS_GETBITMAPFILTERSTRINGST, SIZEOF(filter), ( LPARAM )filter); - - if (IsWinVer2000Plus()) - ofn.lStructSize = sizeof(ofn); - else - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.hwndOwner = 0; - ofn.lpstrFile = FileName; - ofn.lpstrFilter = filter; - ofn.nMaxFile = MAX_PATH; - ofn.nMaxFileTitle = MAX_PATH; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK; - ofn.lpstrInitialDir = _T("."); - *FileName = '\0'; - ofn.lpstrDefExt = _T(""); - ofn.hInstance = g_hInst; - ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENSUBCLASS); - ofn.lpfnHook = (LPOFNHOOKPROC)OpenFileSubclass; - locking_request = is_locked; - ofn.lCustData = (LPARAM)&locking_request; - if (GetOpenFileName(&ofn)) { - szFinalName = FileName; - is_locked = locking_request ? 1 : is_locked; - } - else - return 0; - } - else - szFinalName = tszPath; - - /* - * filename is now set, check it and perform all needed action - */ - - if ((hFile = CreateFile(szFinalName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) - return 0; - - // file exists... - - CloseHandle(hFile); - - AVS_pathToRelative(szFinalName, szBackupName); - DBWriteContactSettingTString(hContact, "ContactPhoto", "Backup", szBackupName); - - DBWriteContactSettingByte(hContact, "ContactPhoto", "Locked", is_locked); - DBWriteContactSettingTString(hContact, "ContactPhoto", "File", szFinalName); - MakePathRelative(hContact, szFinalName); - // Fix cache - ChangeAvatar(hContact, TRUE); - - return 0; -} - -INT_PTR SetAvatar(WPARAM wParam, LPARAM lParam) -{ return avSetAvatar(( HANDLE )wParam, A2T(( const char* )lParam )); -} - -#if defined( _UNICODE ) -INT_PTR SetAvatarW(WPARAM wParam, LPARAM lParam) -{ return avSetAvatar(( HANDLE )wParam, ( TCHAR* )lParam ); -} -#endif - -/* - * see if is possible to set the avatar for the expecified protocol - */ -static INT_PTR CanSetMyAvatar(WPARAM wParam, LPARAM lParam) -{ - char *protocol = (char *) wParam; - if (protocol == NULL || fei == NULL) - return 0; - - return ProtoServiceExists(protocol, PS_SETMYAVATAR); -} - -struct SetMyAvatarHookData { - char *protocol; - BOOL square; - BOOL grow; - - BOOL thumbnail; -}; - - -/* - * Callback to set thumbnaill view to open dialog - */ -static UINT_PTR CALLBACK SetMyAvatarHookProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) { - case WM_INITDIALOG: - { - InterlockedExchange(&hwndSetMyAvatar, (LONG) hwnd); - - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lParam); - OPENFILENAME *ofn = (OPENFILENAME *)lParam; - SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData; - data->thumbnail = TRUE; - - SetWindowText(GetDlgItem(hwnd, IDC_MAKE_SQUARE), TranslateT("Make the avatar square")); - SetWindowText(GetDlgItem(hwnd, IDC_GROW), TranslateT("Grow avatar to fit max allowed protocol size")); - - CheckDlgButton(hwnd, IDC_MAKE_SQUARE, data->square ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwnd, IDC_GROW, data->grow ? BST_CHECKED : BST_UNCHECKED); - - if (data->protocol != NULL && (Proto_AvatarImageProportion(data->protocol) & PIP_SQUARE)) - EnableWindow(GetDlgItem(hwnd, IDC_MAKE_SQUARE), FALSE); - } - break; - - case WM_NOTIFY: - { - OPENFILENAME *ofn = (OPENFILENAME *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData; - if (data->thumbnail) - { - HWND hwndParent = GetParent(hwnd); - HWND hwndLv = FindWindowEx(hwndParent, NULL, _T("SHELLDLL_DefView"), NULL) ; - if (hwndLv != NULL) - { - SendMessage(hwndLv, WM_COMMAND, SHVIEW_THUMBNAIL, 0); - data->thumbnail = FALSE; - } - } - break; - } - case WM_DESTROY: - { - OPENFILENAME *ofn = (OPENFILENAME *)GetWindowLongPtr(hwnd, GWLP_USERDATA); - SetMyAvatarHookData *data = (SetMyAvatarHookData *) ofn->lCustData; - data->square = IsDlgButtonChecked(hwnd, IDC_MAKE_SQUARE); - data->grow = IsDlgButtonChecked(hwnd, IDC_GROW); - - InterlockedExchange(&hwndSetMyAvatar, 0); - break; - } - } - - return 0; -} - -const TCHAR *GetFormatExtension(int format) -{ - if (format == PA_FORMAT_PNG) - return _T(".png"); - if (format == PA_FORMAT_JPEG) - return _T(".jpg"); - if (format == PA_FORMAT_ICON) - return _T(".ico"); - if (format == PA_FORMAT_BMP) - return _T(".bmp"); - if (format == PA_FORMAT_GIF) - return _T(".gif"); - if (format == PA_FORMAT_SWF) - return _T(".swf"); - if (format == PA_FORMAT_XML) - return _T(".xml"); - - return NULL; -} - -int GetImageFormat(TCHAR *filename) -{ - size_t len = lstrlen(filename); - - if (len < 5) - return PA_FORMAT_UNKNOWN; - - if (_tcsicmp(_T(".png"), &filename[len-4]) == 0) - return PA_FORMAT_PNG; - - if (_tcsicmp(_T(".jpg"), &filename[len-4]) == 0 || _tcsicmp(_T(".jpeg"), &filename[len-4]) == 0) - return PA_FORMAT_JPEG; - - if (_tcsicmp(_T(".ico"), &filename[len-4]) == 0) - return PA_FORMAT_ICON; - - if (_tcsicmp(_T(".bmp"), &filename[len-4]) == 0 || _tcsicmp(_T(".rle"), &filename[len-4]) == 0) - return PA_FORMAT_BMP; - - if (_tcsicmp(_T(".gif"), &filename[len-4]) == 0) - return PA_FORMAT_GIF; - - if (_tcsicmp(_T(".swf"), &filename[len-4]) == 0) - return PA_FORMAT_SWF; - - if (_tcsicmp(_T(".xml"), &filename[len-4]) == 0) - return PA_FORMAT_XML; - - return PA_FORMAT_UNKNOWN; -} - -static void FilterGetStrings(TCHAR *filter, int bytesLeft, BOOL xml, BOOL swf) -{ - TCHAR *pfilter; - int wParam = bytesLeft; - - lstrcpyn(filter, TranslateT("All Files"), bytesLeft); bytesLeft-=lstrlen(filter); - _tcsncat(filter, _T(" (*.bmp;*.jpg;*.gif;*.png"), bytesLeft); - if (swf) _tcscat(filter, _T(";*.swf")); - if (xml) _tcscat(filter, _T(";*.xml")); - _tcscat(filter, _T(")")); - pfilter=filter+lstrlen(filter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.BMP;*.RLE;*.JPG;*.JPEG;*.GIF;*.PNG"), bytesLeft); - if (swf) _tcscat(pfilter, _T(";*.SWF")); - if (xml) _tcscat(pfilter, _T(";*.XML")); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - - lstrcpyn(pfilter, TranslateT("Windows Bitmaps"), bytesLeft); bytesLeft-=lstrlen(pfilter); - _tcsncat(pfilter, _T(" (*.bmp;*.rle)"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.BMP;*.RLE"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - - lstrcpyn(pfilter,TranslateT("JPEG Bitmaps"),bytesLeft); bytesLeft-=lstrlen(pfilter); - _tcsncat(pfilter, _T(" (*.jpg;*.jpeg)"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.JPG;*.JPEG"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - - lstrcpyn(pfilter,TranslateT("GIF Bitmaps"),bytesLeft); bytesLeft-=lstrlen(pfilter); - _tcsncat(pfilter, _T(" (*.gif)"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.GIF"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - - lstrcpyn(pfilter,TranslateT("PNG Bitmaps"), bytesLeft); bytesLeft-=lstrlen(pfilter); - _tcsncat(pfilter, _T(" (*.png)"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.PNG"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - - if (swf) - { - lstrcpyn(pfilter,TranslateT("Flash Animations"), bytesLeft); bytesLeft-=lstrlen(pfilter); - _tcsncat(pfilter, _T(" (*.swf)"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.SWF"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - } - - if (xml) - { - lstrcpyn(pfilter, TranslateT("XML Files"), bytesLeft); bytesLeft-=lstrlen(pfilter); - _tcsncat(pfilter, _T(" (*.xml)"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - lstrcpyn(pfilter, _T("*.XML"), bytesLeft); - pfilter+=lstrlen(pfilter)+1; bytesLeft=wParam-(pfilter-filter); - } - - if (bytesLeft) *pfilter='\0'; -} - -static void DeleteGlobalUserAvatar() -{ - DBVARIANT dbv = {0}; - if (DBGetContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) - return; - - TCHAR szFilename[MAX_PATH]; - AVS_pathToAbsolute(dbv.ptszVal, szFilename); - DBFreeVariant(&dbv); - - DeleteFile(szFilename); - DBDeleteContactSetting(NULL, AVS_MODULE, "GlobalUserAvatarFile"); -} - -static void SetIgnoreNotify(char *protocol, BOOL ignore) -{ - for(int i = 0; i < g_MyAvatars.getCount(); i++) { - if (protocol == NULL || !lstrcmpA(g_MyAvatars[i].szProtoname, protocol)) { - if (ignore) - g_MyAvatars[i].dwFlags |= AVS_IGNORENOTIFY; - else - g_MyAvatars[i].dwFlags &= ~AVS_IGNORENOTIFY; - } - } -} - -static int InternalRemoveMyAvatar(char *protocol) -{ - SetIgnoreNotify(protocol, TRUE); - - // Remove avatar - int ret = 0; - if (protocol != NULL) - { - if (ProtoServiceExists(protocol, PS_SETMYAVATAR)) - ret = SaveAvatar(protocol, NULL); - else - ret = -3; - - if (ret == 0) - { - // Has global avatar? - DBVARIANT dbv = {0}; - if (!DBGetContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv)) - { - DBFreeVariant(&dbv); - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); - DeleteGlobalUserAvatar(); - } - } - } - else - { - PROTOACCOUNT **accs; - int i,count; - - ProtoEnumAccounts( &count, &accs ); - for (i = 0; i < count; i++) - { - if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR)) - continue; - - if (!Proto_IsAvatarsEnabled( accs[i]->szModuleName )) - continue; - - // Found a protocol - int retTmp = SaveAvatar( accs[i]->szModuleName, NULL); - if (retTmp != 0) - ret = retTmp; - } - - DeleteGlobalUserAvatar(); - - if (ret) - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); - else - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 0); - } - - SetIgnoreNotify(protocol, FALSE); - - ReportMyAvatarChanged((WPARAM)(( protocol == NULL ) ? "" : protocol ), 0); - return ret; -} - -static int InternalSetMyAvatar(char *protocol, TCHAR *szFinalName, SetMyAvatarHookData &data, BOOL allAcceptXML, BOOL allAcceptSWF) -{ - HANDLE hFile = 0; - - int format = GetImageFormat(szFinalName); - if (format == PA_FORMAT_UNKNOWN || (hFile = CreateFile(szFinalName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) - return -3; - - CloseHandle(hFile); - - // file exists... - - HBITMAP hBmp = NULL; - - if (format == PA_FORMAT_SWF) - { - if (!allAcceptSWF) - return -4; - } - else if (format == PA_FORMAT_XML) - { - if (!allAcceptXML) - return -4; - } - else - { - // Try to open if is not a flash or XML - hBmp = (HBITMAP) CallService(MS_IMG_LOAD, (WPARAM) szFinalName, IMGL_TCHAR); - if (hBmp == NULL) - return -4; - } - - SetIgnoreNotify(protocol, TRUE); - - int ret = 0; - if (protocol != NULL) - { - ret = SetProtoMyAvatar(protocol, hBmp, szFinalName, format, data.square, data.grow); - - if (ret == 0) - { - DeleteGlobalUserAvatar(); - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); - } - } - else - { - PROTOACCOUNT **accs; - int i,count; - - ProtoEnumAccounts( &count, &accs ); - for (i = 0; i < count; i++) - { - if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR)) - continue; - - if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName )) - continue; - - int retTmp = SetProtoMyAvatar( accs[i]->szModuleName, hBmp, szFinalName, format, data.square, data.grow); - if (retTmp != 0) - ret = retTmp; - } - - DeleteGlobalUserAvatar(); - - if (ret) - { - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); - } - else - { - // Copy avatar file to store as global one - TCHAR globalFile[1024]; - BOOL saved = TRUE; - if (FoldersGetCustomPathT(hGlobalAvatarFolder, globalFile, SIZEOF(globalFile), _T(""))) - { - mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\%s"), g_szDataPath, _T("GlobalAvatar")); - CreateDirectory(globalFile, NULL); - } - - TCHAR *ext = _tcsrchr(szFinalName, _T('.')); // Can't be NULL here - if (format == PA_FORMAT_XML || format == PA_FORMAT_SWF) - { - mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar%s"), globalFile, ext); - CopyFile(szFinalName, globalFile, FALSE); - } - else - { - // Resize (to avoid too big avatars) - ResizeBitmap rb = {0}; - rb.size = sizeof(ResizeBitmap); - rb.hBmp = hBmp; - rb.max_height = 300; - rb.max_width = 300; - rb.fit = (data.grow ? 0 : RESIZEBITMAP_FLAG_DONT_GROW) - | (data.square ? RESIZEBITMAP_MAKE_SQUARE : RESIZEBITMAP_KEEP_PROPORTIONS); - - HBITMAP hBmpTmp = (HBITMAP) BmpFilterResizeBitmap((WPARAM)&rb, 0); - - // Check if need to resize - if (hBmpTmp == hBmp || hBmpTmp == NULL) - { - // Use original image - mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar%s"), globalFile, ext); - CopyFile(szFinalName, globalFile, FALSE); - } - else - { - // Save as PNG - mir_sntprintf(globalFile, SIZEOF(globalFile), _T("%s\\my_global_avatar.png"), globalFile); - if (BmpFilterSaveBitmap((WPARAM) hBmpTmp, (LPARAM) globalFile)) - saved = FALSE; - - DeleteObject(hBmpTmp); - } - } - - if (saved) - { - TCHAR relFile[1024]; - if (AVS_pathToRelative(globalFile, relFile)) - DBWriteContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", relFile); - else - DBWriteContactSettingTString(NULL, AVS_MODULE, "GlobalUserAvatarFile", globalFile); - - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 0); - } - else - { - DBWriteContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1); - } - } - } - - DeleteObject(hBmp); - - SetIgnoreNotify(protocol, FALSE); - - ReportMyAvatarChanged((WPARAM)(( protocol == NULL ) ? "" : protocol ), 0); - return ret; -} - -/* - * set an avatar for a protocol (service function) - * if lParam == NULL, a open file dialog will be opened, otherwise, lParam is taken as a FULL - * image filename (will be checked for existance, though) - */ - -INT_PTR avSetMyAvatar( char* protocol, TCHAR* tszPath ) -{ - TCHAR FileName[MAX_PATH]; - TCHAR *szFinalName = NULL; - BOOL allAcceptXML; - BOOL allAcceptSWF; - - // Protocol allow seting of avatar? - if (protocol != NULL && !CanSetMyAvatar((WPARAM) protocol, 0)) - return -1; - - if (tszPath == NULL && hwndSetMyAvatar != 0) - { - SetForegroundWindow((HWND) hwndSetMyAvatar); - SetFocus((HWND) hwndSetMyAvatar); - ShowWindow((HWND) hwndSetMyAvatar, SW_SHOW); - return -2; - } - - SetMyAvatarHookData data = { 0 }; - - // Check for XML and SWF - if (protocol == NULL) - { - allAcceptXML = TRUE; - allAcceptSWF = TRUE; - - PROTOACCOUNT **accs; - int i,count; - - ProtoEnumAccounts( &count, &accs ); - for (i = 0; i < count; i++) - { - if ( !ProtoServiceExists( accs[i]->szModuleName, PS_SETMYAVATAR)) - continue; - - if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName )) - continue; - - allAcceptXML = allAcceptXML && Proto_IsAvatarFormatSupported( accs[i]->szModuleName, PA_FORMAT_XML); - allAcceptSWF = allAcceptSWF && Proto_IsAvatarFormatSupported( accs[i]->szModuleName, PA_FORMAT_SWF); - } - - data.square = DBGetContactSettingByte(0, AVS_MODULE, "SetAllwaysMakeSquare", 0); - } - else - { - allAcceptXML = Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_XML); - allAcceptSWF = Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_SWF); - - data.protocol = protocol; - data.square = (Proto_AvatarImageProportion(protocol) & PIP_SQUARE) - || DBGetContactSettingByte(0, AVS_MODULE, "SetAllwaysMakeSquare", 0); - } - - if (tszPath == NULL) { - OPENFILENAME ofn = {0}; - TCHAR filter[512]; - TCHAR inipath[1024]; - - data.protocol = protocol; - - filter[0] = '\0'; - FilterGetStrings(filter, SIZEOF(filter), allAcceptXML, allAcceptSWF); - - FoldersGetCustomPathT(hMyAvatarsFolder, inipath, SIZEOF(inipath), _T(".")); - - if (IsWinVer2000Plus()) - ofn.lStructSize = sizeof(ofn); - else - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.hwndOwner = 0; - ofn.lpstrFile = FileName; - ofn.lpstrFilter = filter; - ofn.nMaxFile = MAX_PATH; - ofn.nMaxFileTitle = MAX_PATH; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK; - ofn.lpstrInitialDir = inipath; - ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SET_OWN_SUBCLASS); - ofn.lpfnHook = SetMyAvatarHookProc; - ofn.lCustData = (LPARAM) &data; - - *FileName = '\0'; - ofn.lpstrDefExt = _T(""); - ofn.hInstance = g_hInst; - - TCHAR title[256]; - if (protocol == NULL) - mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Avatar")); - else - { - TCHAR* prototmp = mir_a2t(protocol); - mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Avatar for %s"), prototmp); - mir_free(prototmp); - } - ofn.lpstrTitle = title; - - if (GetOpenFileName(&ofn)) - szFinalName = FileName; - else - return 1; - } - else - szFinalName = (TCHAR *)tszPath; - - /* - * filename is now set, check it and perform all needed action - */ - - if (szFinalName[0] == '\0') - return InternalRemoveMyAvatar(protocol); - - return InternalSetMyAvatar(protocol, szFinalName, data, allAcceptXML, allAcceptSWF); -} - -static INT_PTR SetMyAvatar( WPARAM wParam, LPARAM lParam ) -{ return avSetMyAvatar(( char* )wParam, A2T(( const char* )lParam )); -} - -#if defined( _UNICODE ) -static INT_PTR SetMyAvatarW( WPARAM wParam, LPARAM lParam ) -{ return avSetMyAvatar(( char* )wParam, ( TCHAR* )lParam ); -} -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -static DWORD GetFileSize(TCHAR *szFilename) -{ - HANDLE hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return 0; - - DWORD low = GetFileSize(hFile, NULL); - - CloseHandle(hFile); - - if (low == INVALID_FILE_SIZE) - return 0; - - return low; -} - -struct SaveProtocolData { - DWORD max_size; - TCHAR image_file_name[MAX_PATH]; - BOOL saved; - BOOL need_smaller_size; - int width; - int height; - TCHAR temp_file[MAX_PATH]; - HBITMAP hBmpProto; -}; - -static void SaveImage(SaveProtocolData &d, char *protocol, int format) -{ - if (Proto_IsAvatarFormatSupported(protocol, format)) - { - mir_sntprintf(d.image_file_name, SIZEOF(d.image_file_name), _T("%s%s"), d.temp_file, GetFormatExtension(format)); - if (!BmpFilterSaveBitmapT(d.hBmpProto, d.image_file_name, format == PA_FORMAT_JPEG ? JPEG_QUALITYSUPERB : 0)) - { - if (d.max_size != 0 && GetFileSize(d.image_file_name) > d.max_size) - { - DeleteFile(d.image_file_name); - - if (format == PA_FORMAT_JPEG) - { - // Try with lower quality - if (!BmpFilterSaveBitmapT(d.hBmpProto, d.image_file_name, JPEG_QUALITYGOOD)) - { - if (GetFileSize(d.image_file_name) > d.max_size) - { - DeleteFile(d.image_file_name); - d.need_smaller_size = TRUE; - } - else - d.saved = TRUE; - } - } - else - d.need_smaller_size = TRUE; - } - else - d.saved = TRUE; - } - } -} - -static int SetProtoMyAvatar(char *protocol, HBITMAP hBmp, TCHAR *originalFilename, int originalFormat, - BOOL square, BOOL grow) -{ - if (!ProtoServiceExists(protocol, PS_SETMYAVATAR)) - return -1; - - // If is swf or xml, just set it - - if (originalFormat == PA_FORMAT_SWF) - { - if (!Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_SWF)) - return -1; - - return SaveAvatar(protocol, originalFilename); - } - - if (originalFormat == PA_FORMAT_XML) - { - if (!Proto_IsAvatarFormatSupported(protocol, PA_FORMAT_XML)) - return -1; - - return SaveAvatar(protocol, originalFilename); - } - - // Get protocol info - SaveProtocolData d = {0}; - - d.max_size = (DWORD) Proto_GetAvatarMaxFileSize(protocol); - - Proto_GetAvatarMaxSize(protocol, &d.width, &d.height); - int orig_width = d.width; - int orig_height = d.height; - - if (Proto_AvatarImageProportion(protocol) & PIP_SQUARE) - square = TRUE; - - - // Try to save until a valid image is found or we give up - int num_tries = 0; - do { - // Lets do it - ResizeBitmap rb; - rb.size = sizeof(ResizeBitmap); - rb.hBmp = hBmp; - rb.max_height = d.height; - rb.max_width = d.width; - rb.fit = (grow ? 0 : RESIZEBITMAP_FLAG_DONT_GROW) - | (square ? RESIZEBITMAP_MAKE_SQUARE : RESIZEBITMAP_KEEP_PROPORTIONS); - - d.hBmpProto = (HBITMAP) BmpFilterResizeBitmap((WPARAM)&rb, 0); - - if (d.hBmpProto == NULL) - { - if (d.temp_file[0] != '\0') - DeleteFile(d.temp_file); - return -1; - } - - // Check if can use original image - if (d.hBmpProto == hBmp - && Proto_IsAvatarFormatSupported(protocol, originalFormat) - && (d.max_size == 0 || GetFileSize(originalFilename) < d.max_size)) - { - if (d.temp_file[0] != '\0') - DeleteFile(d.temp_file); - - // Use original image - return SaveAvatar(protocol, originalFilename); - } - - // Create a temporary file (if was not created already) - if (d.temp_file[0] == '\0') - { - d.temp_file[0] = '\0'; - if (GetTempPath(MAX_PATH, d.temp_file) == 0 - || GetTempFileName(d.temp_file, _T("mir_av_"), 0, d.temp_file) == 0) - { - DeleteObject(d.hBmpProto); - return -1; - } - } - - // Which format? - - // First try to use original format - if (originalFormat != PA_FORMAT_BMP) - SaveImage(d, protocol, originalFormat); - - if (!d.saved && originalFormat != PA_FORMAT_PNG) - SaveImage(d, protocol, PA_FORMAT_PNG); - - if (!d.saved && originalFormat != PA_FORMAT_JPEG) - SaveImage(d, protocol, PA_FORMAT_JPEG); - - if (!d.saved && originalFormat != PA_FORMAT_GIF) - SaveImage(d, protocol, PA_FORMAT_GIF); - - if (!d.saved) - SaveImage(d, protocol, PA_FORMAT_BMP); - - num_tries++; - if (!d.saved && d.need_smaller_size && num_tries < 4) - { - // Cleanup - if (d.hBmpProto != hBmp) - DeleteObject(d.hBmpProto); - - // use a smaller size - d.width = orig_width * (4 - num_tries) / 4; - d.height = orig_height * (4 - num_tries) / 4; - } - - } while(!d.saved && d.need_smaller_size && num_tries < 4); - - int ret; - - if (d.saved) - { - // Call proto service - ret = SaveAvatar(protocol, d.image_file_name); - DeleteFile(d.image_file_name); - } - else - { - ret = -1; - } - - if (d.temp_file[0] != '\0') - DeleteFile(d.temp_file); - - if (d.hBmpProto != hBmp) - DeleteObject(d.hBmpProto); - - return ret; -} - -static INT_PTR ContactOptions(WPARAM wParam, LPARAM lParam) -{ - if (wParam) - CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_AVATAROPTIONS), 0, DlgProcAvatarOptions, (LPARAM)wParam); - return 0; -} - -INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam) -{ - int i; - char *szProto = (char *)lParam; - - if (wParam || g_shutDown || fei == NULL) - return 0; - - if (lParam == 0 || IsBadReadPtr(szProto, 4)) - return 0; - - for(i = 0; i < g_MyAvatars.getCount(); i++) { - if (!lstrcmpA(szProto, g_MyAvatars[i].szProtoname) && g_MyAvatars[i].hbmPic != 0) - return (INT_PTR)&g_MyAvatars[i]; - } - return 0; -} - -static protoPicCacheEntry *GetProtoDefaultAvatar(HANDLE hContact) -{ - char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto) { - for(int i = 0; i < g_ProtoPictures.getCount(); i++) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if ( !lstrcmpA(p.szProtoname, szProto) && p.hbmPic != NULL) - return &g_ProtoPictures[i]; - } - } - return NULL; -} - -HANDLE GetContactThatHaveTheAvatar(HANDLE hContact, int locked = -1) -{ - if (g_MetaAvail && DBGetContactSettingByte(NULL, g_szMetaName, "Enabled", 0)) { - if (DBGetContactSettingDword(hContact, g_szMetaName, "NumContacts", 0) >= 1) { - if (locked == -1) - locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); - - if (!locked) - hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0); - } - } - return hContact; -} - -INT_PTR GetAvatarBitmap(WPARAM wParam, LPARAM lParam) -{ - if (wParam == 0 || g_shutDown || fei == NULL) - return 0; - - HANDLE hContact = (HANDLE) wParam; - hContact = GetContactThatHaveTheAvatar(hContact); - - // Get the node - struct CacheNode *node = FindAvatarInCache(hContact, TRUE); - if (node == NULL || !node->loaded) - return (INT_PTR) GetProtoDefaultAvatar(hContact); - else - return (INT_PTR) &node->ace; -} - -// Just delete an avatar from cache -// An cache entry is never deleted. What is deleted is the image handle inside it -// This is done this way to keep track of which avatars avs have to keep track -void DeleteAvatarFromCache(HANDLE hContact, BOOL forever) -{ - hContact = GetContactThatHaveTheAvatar(hContact); - - struct CacheNode *node = FindAvatarInCache(hContact, FALSE); - if (node == NULL) { - struct CacheNode temp_node = {0}; - if (g_MetaAvail) - temp_node.dwFlags |= (DBGetContactSettingByte(hContact, g_szMetaName, "IsSubcontact", 0) ? MC_ISSUBCONTACT : 0); - NotifyMetaAware(hContact, &temp_node, (AVATARCACHEENTRY *)GetProtoDefaultAvatar(hContact)); - return; - } - node->mustLoad = -1; // mark for deletion - if (forever) - node->dwFlags |= AVS_DELETENODEFOREVER; - SetEvent(hLoaderEvent); -} - -int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist, int pa_format) -{ - if (g_shutDown) - return 0; - - hContact = GetContactThatHaveTheAvatar(hContact); - - // Get the node - struct CacheNode *node = FindAvatarInCache(hContact, g_AvatarHistoryAvail && fNotifyHist, TRUE); - if (node == NULL) - return 0; - - if (fNotifyHist) - node->dwFlags |= AVH_MUSTNOTIFY; - - node->mustLoad = fLoad ? 1 : -1; - node->pa_format = pa_format; - SetEvent(hLoaderEvent); - return 0; -} - -/* - * this thread scans the cache and handles nodes which have mustLoad set to > 0 (must be loaded/reloaded) or - * nodes where mustLoad is < 0 (must be deleted). - * its waken up by the event and tries to lock the cache only when absolutely necessary. - */ - -static void PicLoader(LPVOID param) -{ - DWORD dwDelay = DBGetContactSettingDword(NULL, AVS_MODULE, "picloader_sleeptime", 80); - - if (dwDelay < 30) - dwDelay = 30; - else if (dwDelay > 100) - dwDelay = 100; - - while(!g_shutDown) { - struct CacheNode *node = g_Cache; - - while(!g_shutDown && node) { - if (node->mustLoad > 0 && node->ace.hContact) { - node->mustLoad = 0; - AVATARCACHEENTRY ace_temp; - - if (DBGetContactSettingByte(node->ace.hContact, "ContactPhoto", "NeedUpdate", 0)) - QueueAdd(node->ace.hContact); - - CopyMemory(&ace_temp, &node->ace, sizeof(AVATARCACHEENTRY)); - ace_temp.hbmPic = 0; - - int result = CreateAvatarInCache(node->ace.hContact, &ace_temp, NULL); - - if (result == -2) - { - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)node->ace.hContact, 0); - if (szProto == NULL || Proto_NeedDelaysForAvatars(szProto)) - { - QueueAdd(node->ace.hContact); - } - else - { - if (FetchAvatarFor(node->ace.hContact, szProto) == GAIR_SUCCESS) - // Try yo create again - result = CreateAvatarInCache(node->ace.hContact, &ace_temp, NULL); - } - } - - if ((result == 1 && ace_temp.hbmPic != 0)) // Loaded - { - HBITMAP oldPic = node->ace.hbmPic; - - EnterCriticalSection(&cachecs); - CopyMemory(&node->ace, &ace_temp, sizeof(AVATARCACHEENTRY)); - node->loaded = TRUE; - LeaveCriticalSection(&cachecs); - if (oldPic) - DeleteObject(oldPic); - NotifyMetaAware(node->ace.hContact, node); - } - else if (result == 0 || result == -3) // Has no avatar - { - HBITMAP oldPic = node->ace.hbmPic; - - EnterCriticalSection(&cachecs); - CopyMemory(&node->ace, &ace_temp, sizeof(AVATARCACHEENTRY)); - node->loaded = FALSE; - node->mustLoad = 0; - LeaveCriticalSection(&cachecs); - if (oldPic) - DeleteObject(oldPic); - NotifyMetaAware(node->ace.hContact, node); - } - - mir_sleep(dwDelay); - } - else if (node->mustLoad < 0 && node->ace.hContact) { // delete this picture - HANDLE hContact = node->ace.hContact; - EnterCriticalSection(&cachecs); - node->mustLoad = 0; - node->loaded = 0; - if (node->ace.hbmPic) - DeleteObject(node->ace.hbmPic); - ZeroMemory(&node->ace, sizeof(AVATARCACHEENTRY)); - if (node->dwFlags & AVS_DELETENODEFOREVER) { - node->dwFlags &= ~AVS_DELETENODEFOREVER; - } else { - node->ace.hContact = hContact; - } - LeaveCriticalSection(&cachecs); - NotifyMetaAware(hContact, node, (AVATARCACHEENTRY *)GetProtoDefaultAvatar(hContact)); - } - // protect this by changes from the cache block allocator as it can cause inconsistencies while working - // on allocating a new block. - EnterCriticalSection(&alloccs); - node = node->pNextNode; - LeaveCriticalSection(&alloccs); - } - WaitForSingleObject(hLoaderEvent, INFINITE); - //_DebugTrace(0, "pic loader awake..."); - ResetEvent(hLoaderEvent); - } -} - -static int MetaChanged(WPARAM wParam, LPARAM lParam) -{ - if (wParam == 0 || g_shutDown) - return 0; - - AVATARCACHEENTRY *ace; - - HANDLE hContact = (HANDLE) wParam; - HANDLE hSubContact = GetContactThatHaveTheAvatar(hContact); - - // Get the node - struct CacheNode *node = FindAvatarInCache(hSubContact, TRUE); - if (node == NULL || !node->loaded) { - ace = (AVATARCACHEENTRY *)GetProtoDefaultAvatar(hSubContact); - QueueAdd(hSubContact); - } - else - ace = &node->ace; - - NotifyEventHooks(hEventChanged, (WPARAM)hContact, (LPARAM)ace); - return 0; -} - -static LIST arServices( 10 ); - -static int DestroyServicesAndEvents() -{ - UnhookEvent(hContactSettingChanged); - UnhookEvent(hProtoAckHook); - UnhookEvent(hUserInfoInitHook); - UnhookEvent(hOptInit); - UnhookEvent(hModulesLoaded); - UnhookEvent(hPresutdown); - UnhookEvent(hOkToExit); - UnhookEvent(hAccChanged); - - for ( int i=0; i < arServices.getCount(); i++ ) - DestroyServiceFunction( arServices[i] ); - - arServices.destroy(); - - DestroyHookableEvent(hEventChanged); - DestroyHookableEvent(hEventContactAvatarChanged); - DestroyHookableEvent(hMyAvatarChanged); - hEventChanged = 0; - hEventContactAvatarChanged = 0; - hMyAvatarChanged = 0; - UnhookEvent(hEventDeleted); - return 0; -} - -static void LoadDefaultInfo() -{ - protoPicCacheEntry* pce = new protoPicCacheEntry; - if (CreateAvatarInCache(0, pce, AVS_DEFAULT) != 1) - DBDeleteContactSetting(0, PPICT_MODULE, AVS_DEFAULT); - - pce->szProtoname = mir_strdup(AVS_DEFAULT); - pce->tszAccName = mir_tstrdup(TranslateT(AVS_DEFAULT)); - g_ProtoPictures.insert(pce); -} - -static void LoadProtoInfo( PROTOCOLDESCRIPTOR* proto ) -{ - if ( proto->type == PROTOTYPE_PROTOCOL && proto->cbSize == sizeof( *proto )) - { - char protoName[MAX_PATH]; - mir_snprintf(protoName, SIZEOF(protoName), "Global avatar for %s accounts", proto->szName); - TCHAR protoNameTmp[MAX_PATH]; - TCHAR *tszName = mir_a2t(proto->szName); - mir_sntprintf(protoNameTmp, SIZEOF(protoNameTmp), TranslateT("Global avatar for %s accounts"), tszName); - protoPicCacheEntry* pce = new protoPicCacheEntry; - if (CreateAvatarInCache(0, pce, protoName) != 1) - DBDeleteContactSetting(0, PPICT_MODULE, protoName); - - pce->szProtoname = mir_strdup(protoName); - pce->tszAccName = mir_tstrdup(protoNameTmp); - g_ProtoPictures.insert(pce); - mir_free(tszName); - } -} - -static void LoadAccountInfo( PROTOACCOUNT* acc ) -{ - protoPicCacheEntry* pce = new protoPicCacheEntry; - if ( CreateAvatarInCache(0, pce, acc->szModuleName ) != 1 ) - DBDeleteContactSetting(0, PPICT_MODULE, acc->szModuleName); - - pce->szProtoname = mir_strdup( acc->szModuleName ); - pce->tszAccName = mir_tstrdup( acc->tszAccountName ); - g_ProtoPictures.insert( pce ); - - pce = new protoPicCacheEntry; - CreateAvatarInCache((HANDLE)-1, pce, acc->szModuleName ); - pce->szProtoname = mir_strdup( acc->szModuleName ); - pce->tszAccName = mir_tstrdup( acc->tszAccountName ); - g_MyAvatars.insert( pce ); -} - -static int OnAccChanged(WPARAM wParam, LPARAM lParam) -{ - PROTOACCOUNT* pa = ( PROTOACCOUNT* )lParam; - - switch( wParam ) { - case PRAC_ADDED: - LoadAccountInfo( pa ); - break; - - case PRAC_REMOVED: - { - int idx; - protoPicCacheEntry tmp; - tmp.szProtoname = mir_strdup(pa->szModuleName); - if (( idx = g_ProtoPictures.getIndex( &tmp )) != -1 ) - g_ProtoPictures.remove( idx ); - if (( idx = g_MyAvatars.getIndex( &tmp )) != -1 ) - g_MyAvatars.remove( idx ); - } - break; - } - - return 0; -} - -static int ModulesLoaded(WPARAM wParam, LPARAM lParam) -{ - int i; - DBVARIANT dbv = {0}; - TCHAR szEventName[100]; - int result = 0; - - InitPolls(); - - mir_sntprintf(szEventName, 100, _T("avs_loaderthread_%d"), GetCurrentThreadId()); - hLoaderEvent = CreateEvent(NULL, TRUE, FALSE, szEventName); - hLoaderThread = (HANDLE) mir_forkthread(PicLoader, 0); - SetThreadPriority(hLoaderThread, THREAD_PRIORITY_IDLE); - - // Folders plugin support - if (ServiceExists(MS_FOLDERS_REGISTER_PATH)) - { - hMyAvatarsFolder = (HANDLE) FoldersRegisterCustomPathT("Avatars", "My Avatars", - MIRANDA_USERDATAT _T("\\Avatars")); - - hGlobalAvatarFolder = (HANDLE) FoldersRegisterCustomPathT("Avatars", "My Global Avatar Cache", - MIRANDA_USERDATAT _T("\\Avatars")); - } - - g_AvatarHistoryAvail = ServiceExists(MS_AVATARHISTORY_ENABLED); - - g_MetaAvail = ServiceExists(MS_MC_GETPROTOCOLNAME) ? TRUE : FALSE; - if (g_MetaAvail) { - g_szMetaName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0); - if (g_szMetaName == NULL) - g_MetaAvail = FALSE; - } - - PROTOACCOUNT **accs = NULL; - int accCount; - ProtoEnumAccounts( &accCount, &accs ); - - if ( fei != NULL ) - { - LoadDefaultInfo(); - PROTOCOLDESCRIPTOR** proto; - int protoCount; - CallService(MS_PROTO_ENUMPROTOS, ( WPARAM )&protoCount, ( LPARAM )&proto); - for ( i=0; i < protoCount; i++ ) - LoadProtoInfo( proto[i] ); - for(i = 0; i < accCount; i++) - LoadAccountInfo( accs[i] ); - } - - // Load global avatar - protoPicCacheEntry* pce = new protoPicCacheEntry; - CreateAvatarInCache((HANDLE)-1, pce, ""); - pce->szProtoname = mir_strdup(""); - g_MyAvatars.insert( pce ); - - hAccChanged = HookEvent(ME_PROTO_ACCLISTCHANGED, OnAccChanged); - hPresutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, ShutdownProc); - hOkToExit = HookEvent(ME_SYSTEM_OKTOEXIT, OkToExitProc); - hUserInfoInitHook = HookEvent(ME_USERINFO_INITIALISE, OnDetailsInit); - - return 0; -} - -static void ReloadMyAvatar(LPVOID lpParam) -{ - char *szProto = (char *)lpParam; - - mir_sleep(500); - for(int i = 0; !g_shutDown && i < g_MyAvatars.getCount(); i++) { - char *myAvatarProto = g_MyAvatars[i].szProtoname; - - if (szProto[0] == 0) { - // Notify to all possibles - if (lstrcmpA(myAvatarProto, szProto)) { - if (!ProtoServiceExists( myAvatarProto, PS_SETMYAVATAR)) - continue; - if (!Proto_IsAvatarsEnabled( myAvatarProto )) - continue; - } - - } else if (lstrcmpA(myAvatarProto, szProto)) { - continue; - } - - if (g_MyAvatars[i].hbmPic) - DeleteObject(g_MyAvatars[i].hbmPic); - - if (CreateAvatarInCache((HANDLE)-1, &g_MyAvatars[i], myAvatarProto) != -1) - NotifyEventHooks(hMyAvatarChanged, (WPARAM)myAvatarProto, (LPARAM)&g_MyAvatars[i]); - else - NotifyEventHooks(hMyAvatarChanged, (WPARAM)myAvatarProto, 0); - } - - free(lpParam); -} - -static INT_PTR ReportMyAvatarChanged(WPARAM wParam, LPARAM lParam) -{ - if (wParam == NULL) - return -1; - - char *proto = (char *) wParam; - - for(int i = 0; i < g_MyAvatars.getCount(); i++) { - if (g_MyAvatars[i].dwFlags & AVS_IGNORENOTIFY) - continue; - - if ( !lstrcmpA(g_MyAvatars[i].szProtoname, proto)) { - LPVOID lpParam = (void *)malloc(lstrlenA(g_MyAvatars[i].szProtoname) + 2); - strcpy((char *)lpParam, g_MyAvatars[i].szProtoname); - mir_forkthread(ReloadMyAvatar, lpParam); - return 0; - } - } - - return -2; -} - -static int ContactSettingChanged(WPARAM wParam, LPARAM lParam) -{ - DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; - - if (cws == NULL || g_shutDown) - return 0; - - if (wParam == 0) { - if (!strcmp(cws->szSetting, "AvatarFile") - || !strcmp(cws->szSetting, "PictObject") - || !strcmp(cws->szSetting, "AvatarHash") - || !strcmp(cws->szSetting, "AvatarSaved")) - { - ReportMyAvatarChanged((WPARAM) cws->szModule, 0); - } - return 0; - } - else if (g_MetaAvail && !strcmp(cws->szModule, g_szMetaName)) { - if (lstrlenA(cws->szSetting) > 6 && !strncmp(cws->szSetting, "Status", 5)) - MetaChanged(wParam, 0); - } - return 0; -} - -static int ContactDeleted(WPARAM wParam, LPARAM lParam) -{ - DeleteAvatarFromCache((HANDLE)wParam, TRUE); - - return 0; -} - -static int OptInit(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp; - - ZeroMemory(&odp, sizeof(odp)); - odp.cbSize = sizeof(odp); - odp.position = 0; - odp.hInstance = g_hInst; - odp.flags = ODPF_BOLDGROUPS | ODPF_EXPERTONLY | ODPF_TCHAR; - odp.ptszGroup = LPGENT("Customize"); - odp.ptszTitle = LPGENT("Avatars"); - - odp.ptszTab = LPGENT("Protocols"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_PICTS); - odp.pfnDlgProc = DlgProcOptionsProtos; - CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); - - odp.ptszTab = LPGENT("Contact Avatars"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_AVATARS); - odp.pfnDlgProc = DlgProcOptionsAvatars; - CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); - - odp.ptszTab = LPGENT("Own Avatars"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_OWN); - odp.pfnDlgProc = DlgProcOptionsOwn; - CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); - - return 0; -} - -static int OkToExitProc(WPARAM wParam, LPARAM lParam) -{ - EnterCriticalSection(&cachecs); - g_shutDown = TRUE; - - DestroyServicesAndEvents(); - - LeaveCriticalSection(&cachecs); - - SetEvent(hLoaderEvent); - FreePolls(); - return 0; -} - -static int ShutdownProc(WPARAM wParam, LPARAM lParam) -{ - DeleteCriticalSection(&cachecs); - DeleteCriticalSection(&alloccs); - return 0; -} - -void InternalDrawAvatar(AVATARDRAWREQUEST *r, HBITMAP hbm, LONG bmWidth, LONG bmHeight, DWORD dwFlags) -{ - float dScale = 0; - int newHeight, newWidth; - HDC hdcAvatar; - HBITMAP hbmMem; - DWORD topoffset = 0, leftoffset = 0; - HRGN rgn = 0, oldRgn = 0; - int targetWidth = r->rcDraw.right - r->rcDraw.left; - int targetHeight = r->rcDraw.bottom - r->rcDraw.top; - BLENDFUNCTION bf = {0}; - - hdcAvatar = CreateCompatibleDC(r->hTargetDC); - hbmMem = (HBITMAP)SelectObject(hdcAvatar, hbm); - - if ((r->dwFlags & AVDRQ_DONTRESIZEIFSMALLER) && bmHeight <= targetHeight && bmWidth <= targetWidth) { - newHeight = bmHeight; - newWidth = bmWidth; - } - else if (bmHeight >= bmWidth) { - dScale = targetHeight / (float)bmHeight; - newHeight = targetHeight; - newWidth = (int) (bmWidth * dScale); - } - else { - dScale = targetWidth / (float)bmWidth; - newWidth = targetWidth; - newHeight = (int) (bmHeight * dScale); - } - - topoffset = targetHeight > newHeight ? (targetHeight - newHeight) / 2 : 0; - leftoffset = targetWidth > newWidth ? (targetWidth - newWidth) / 2 : 0; - - // create the region for the avatar border - use the same region for clipping, if needed. - - oldRgn = CreateRectRgn(0,0,1,1); - - if (GetClipRgn(r->hTargetDC, oldRgn) != 1) - { - DeleteObject(oldRgn); - oldRgn = NULL; - } - - if (r->dwFlags & AVDRQ_ROUNDEDCORNER) - rgn = CreateRoundRectRgn(r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, r->rcDraw.left + leftoffset + newWidth + 1, r->rcDraw.top + topoffset + newHeight + 1, 2 * r->radius, 2 * r->radius); - else - rgn = CreateRectRgn(r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, r->rcDraw.left + leftoffset + newWidth, r->rcDraw.top + topoffset + newHeight); - - ExtSelectClipRgn(r->hTargetDC, rgn, RGN_AND); - - bf.SourceConstantAlpha = r->alpha > 0 ? r->alpha : 255; - bf.AlphaFormat = dwFlags & AVS_PREMULTIPLIED ? AC_SRC_ALPHA : 0; - - if (!(r->dwFlags & AVDRQ_AERO)) - SetStretchBltMode(r->hTargetDC, HALFTONE); - //else - // FillRect(r->hTargetDC, &r->rcDraw, (HBRUSH)GetStockObject(BLACK_BRUSH)); - - if (r->dwFlags & AVDRQ_FORCEFASTALPHA && !(r->dwFlags & AVDRQ_AERO) && AvsAlphaBlend) { - AvsAlphaBlend( - r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, - hdcAvatar, 0, 0, bmWidth, bmHeight, bf); - } else { - if ((bf.SourceConstantAlpha == 255 && bf.AlphaFormat == 0 && !(r->dwFlags & AVDRQ_FORCEALPHA) && !(r->dwFlags & AVDRQ_AERO)) || !AvsAlphaBlend) { - StretchBlt(r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, hdcAvatar, 0, 0, bmWidth, bmHeight, SRCCOPY); - } else { - /* - * get around SUCKY AlphaBlend() rescaling quality... - */ - FIBITMAP *fb = fei->FI_CreateDIBFromHBITMAP(hbm); - FIBITMAP *fbResized = fei->FI_Rescale(fb, newWidth, newHeight, FILTER_BICUBIC); - HBITMAP hbmResized = fei->FI_CreateHBITMAPFromDIB(fbResized); - fei->FI_Unload(fb); - fei->FI_Unload(fbResized); - - HBITMAP hbmTempOld; - HDC hdcTemp = CreateCompatibleDC(r->hTargetDC); - hbmTempOld = (HBITMAP)SelectObject(hdcTemp, hbmResized); - - AvsAlphaBlend( - r->hTargetDC, r->rcDraw.left + leftoffset, r->rcDraw.top + topoffset, newWidth, newHeight, - hdcTemp, 0, 0, newWidth, newHeight, bf); - - SelectObject(hdcTemp, hbmTempOld); - DeleteObject(hbmResized); - DeleteDC(hdcTemp); - } - - if ((r->dwFlags & AVDRQ_DRAWBORDER) && !((r->dwFlags & AVDRQ_HIDEBORDERONTRANSPARENCY) && (dwFlags & AVS_HASTRANSPARENCY))) { - HBRUSH br = CreateSolidBrush(r->clrBorder); - HBRUSH brOld = (HBRUSH)SelectObject(r->hTargetDC, br); - FrameRgn(r->hTargetDC, rgn, br, 1, 1); - SelectObject(r->hTargetDC, brOld); - DeleteObject(br); - } - - SelectClipRgn(r->hTargetDC, oldRgn); - DeleteObject(rgn); - if (oldRgn) DeleteObject(oldRgn); - - SelectObject(hdcAvatar, hbmMem); - DeleteDC(hdcAvatar); - } -} - -INT_PTR DrawAvatarPicture(WPARAM wParam, LPARAM lParam) -{ - AVATARDRAWREQUEST *r = (AVATARDRAWREQUEST *)lParam; - AVATARCACHEENTRY *ace = NULL; - - if (fei == NULL || r == NULL || IsBadReadPtr((void *)r, sizeof(AVATARDRAWREQUEST))) - return 0; - - if (r->cbSize != sizeof(AVATARDRAWREQUEST)) - return 0; - - if (r->dwFlags & AVDRQ_PROTOPICT) { - if (r->szProto == NULL) - return 0; - - for(int i = 0; i < g_ProtoPictures.getCount(); i++) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if ( !lstrcmpA(p.szProtoname, r->szProto) && lstrlenA(r->szProto) == lstrlenA(p.szProtoname) && p.hbmPic != 0) { - ace = (AVATARCACHEENTRY *)&g_ProtoPictures[i]; - break; - } - } - } - else if (r->dwFlags & AVDRQ_OWNPIC) { - if (r->szProto == NULL) - return 0; - - if (r->szProto[0] == '\0' && DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) - return -1; - - ace = (AVATARCACHEENTRY *)GetMyAvatar(0, (LPARAM)r->szProto); - } - else - ace = (AVATARCACHEENTRY *)GetAvatarBitmap((WPARAM)r->hContact, 0); - - if (ace && (!(r->dwFlags & AVDRQ_RESPECTHIDDEN) || !(ace->dwFlags & AVS_HIDEONCLIST))) { - ace->t_lastAccess = time(NULL); - - if (ace->bmHeight == 0 || ace->bmWidth == 0 || ace->hbmPic == 0) - return 0; - - InternalDrawAvatar(r, ace->hbmPic, ace->bmWidth, ace->bmHeight, ace->dwFlags); - return 1; - } - - return 0; -} - -static int OnDetailsInit(WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact = (HANDLE) lParam; - if (hContact == NULL) - { - // User dialog - OPTIONSDIALOGPAGE odp = {0}; - odp.cbSize = sizeof(odp); - odp.flags = ODPF_TCHAR; - odp.hIcon = g_hIcon; - odp.hInstance = g_hInst; - odp.pfnDlgProc = DlgProcAvatarProtoInfo; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_PROTO_AVATARS); - odp.ptszTitle = LPGENT("Avatar"); - CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); - } - else - { - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (szProto == NULL || DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1)) - { - // Contact dialog - OPTIONSDIALOGPAGE odp = {0}; - odp.cbSize = sizeof(odp); - odp.flags = ODPF_TCHAR; - odp.hIcon = g_hIcon; - odp.hInstance = g_hInst; - odp.pfnDlgProc = DlgProcAvatarUserInfo; - odp.position = -2000000000; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_USER_AVATAR); - odp.ptszTitle = LPGENT("Avatar"); - CallService(MS_USERINFO_ADDPAGE, wParam, (LPARAM)&odp); - } - } - return 0; -} - -static int LoadAvatarModule() -{ - mir_getMMI ( &mmi ); - mir_getLI ( &li ); - mir_getLP( &pluginInfoEx ); - - init_mir_thread(); - - InitializeCriticalSection(&cachecs); - InitializeCriticalSection(&alloccs); - - hOptInit = HookEvent(ME_OPT_INITIALISE, OptInit); - hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded); - hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged); - hEventDeleted = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); - hProtoAckHook = HookEvent(ME_PROTO_ACK, ProtocolAck); - - arServices.insert( CreateServiceFunction( MS_AV_GETAVATARBITMAP, GetAvatarBitmap )); - arServices.insert( CreateServiceFunction( MS_AV_PROTECTAVATAR, ProtectAvatar )); - arServices.insert( CreateServiceFunction( MS_AV_SETAVATAR, SetAvatar )); - arServices.insert( CreateServiceFunction( MS_AV_SETMYAVATAR, SetMyAvatar )); - arServices.insert( CreateServiceFunction( MS_AV_CANSETMYAVATAR, CanSetMyAvatar )); - arServices.insert( CreateServiceFunction( MS_AV_CONTACTOPTIONS, ContactOptions )); - arServices.insert( CreateServiceFunction( MS_AV_DRAWAVATAR, DrawAvatarPicture )); - arServices.insert( CreateServiceFunction( MS_AV_GETMYAVATAR, GetMyAvatar )); - arServices.insert( CreateServiceFunction( MS_AV_REPORTMYAVATARCHANGED, ReportMyAvatarChanged )); - arServices.insert( CreateServiceFunction( MS_AV_LOADBITMAP32, BmpFilterLoadBitmap32 )); - arServices.insert( CreateServiceFunction( MS_AV_SAVEBITMAP, BmpFilterSaveBitmap )); - arServices.insert( CreateServiceFunction( MS_AV_CANSAVEBITMAP, BmpFilterCanSaveBitmap )); - arServices.insert( CreateServiceFunction( MS_AV_RESIZEBITMAP, BmpFilterResizeBitmap )); - - #if defined( _UNICODE ) - arServices.insert( CreateServiceFunction( MS_AV_SETAVATARW, SetAvatarW )); - arServices.insert( CreateServiceFunction( MS_AV_SETMYAVATARW, SetMyAvatarW )); - #endif - - hEventChanged = CreateHookableEvent(ME_AV_AVATARCHANGED); - hEventContactAvatarChanged = CreateHookableEvent(ME_AV_CONTACTAVATARCHANGED); - hMyAvatarChanged = CreateHookableEvent(ME_AV_MYAVATARCHANGED); - - AllocCacheBlock(); - - HMODULE hDll; - if (hDll = GetModuleHandle(_T("gdi32"))) - AvsAlphaBlend = (BOOL (WINAPI *)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION)) GetProcAddress(hDll, "GdiAlphaBlend"); - if (AvsAlphaBlend == NULL && (hDll = LoadLibrary(_T("msimg32.dll")))) - AvsAlphaBlend = (BOOL (WINAPI *)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION)) GetProcAddress(hDll, "AlphaBlend"); - - TCHAR* tmpPath = Utils_ReplaceVarsT(_T("%miranda_userdata%")); - lstrcpyn(g_szDataPath, tmpPath, SIZEOF(g_szDataPath)-1); - mir_free(tmpPath); - g_szDataPath[MAX_PATH - 1] = 0; - _tcslwr(g_szDataPath); - - return 0; -} - -extern "C" BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved) -{ - g_hInst = hInstDLL; - return TRUE; -} - -extern "C" __declspec(dllexport) PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion) -{ - if (mirandaVersion < MIRANDA_VERSION_CORE) - return NULL; - return &pluginInfoEx; -} - -static const MUUID interfaces[] = { { 0xece29554, 0x1cf0, 0x41da, { 0x85, 0x82, 0xfb, 0xe8, 0x45, 0x5c, 0x6b, 0xec } }, MIID_LAST}; -extern "C" __declspec(dllexport) const MUUID * MirandaPluginInterfaces(void) -{ - return interfaces; -} - -extern "C" int __declspec(dllexport) Load(PLUGINLINK * link) -{ - INT_PTR result = CALLSERVICE_NOTFOUND; - - pluginLink = link; - mir_getLP( &pluginInfoEx ); - - if (ServiceExists(MS_IMG_GETINTERFACE)) - result = CallService(MS_IMG_GETINTERFACE, FI_IF_VERSION, (LPARAM)&fei); - - if (fei == NULL || result != S_OK) { - MessageBox(0, TranslateT("Fatal error, image services not found. Avatar services will be disabled."), TranslateT("Avatar Service"), MB_OK); - return 1; - } - LoadACC(); - return LoadAvatarModule(); -} - -extern "C" int __declspec(dllexport) Unload(void) -{ - struct CacheNode *pNode = g_Cache; - - while(pNode) { - //DeleteCriticalSection(&pNode->cs); - if (pNode->ace.hbmPic != 0) - DeleteObject(pNode->ace.hbmPic); - pNode = pNode->pNextNode; - } - - for(int i = 0; i < g_curBlock; i++) - free(g_cacheBlocks[i]); - free(g_cacheBlocks); - - g_ProtoPictures.destroy(); - g_MyAvatars.destroy(); - - CloseHandle(hLoaderEvent); - DeleteCriticalSection(&alloccs); - DeleteCriticalSection(&cachecs); - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -protoPicCacheEntry::~protoPicCacheEntry() -{ - if ( hbmPic != 0 ) - DeleteObject( hbmPic ); - mir_free( szProtoname ); - mir_free( tszAccName ); -} - -void protoPicCacheEntry::clear() -{ - if (hbmPic != 0) - DeleteObject(hbmPic); - - memset(this, 0, sizeof(avatarCacheEntry)); -} - -/* -wParam=(int *)max width of avatar - will be set (-1 for no max) -lParam=(int *)max height of avatar - will be set (-1 for no max) -return=0 for sucess -*/ -#define PS_GETMYAVATARMAXSIZE "/GetMyAvatarMaxSize" - -/* -wParam=0 -lParam=0 -return=One of PIP_SQUARE, PIP_FREEPROPORTIONS -*/ -#define PIP_FREEPROPORTIONS 0 -#define PIP_SQUARE 1 -#define PS_GETMYAVATARIMAGEPROPORTION "/GetMyAvatarImageProportion" - -/* -wParam = 0 -lParam = PA_FORMAT_* // avatar format -return = 1 (supported) or 0 (not supported) -*/ -#define PS_ISAVATARFORMATSUPPORTED "/IsAvatarFormatSupported" - - - -BOOL Proto_IsAvatarsEnabled(const char *proto) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - return CallProtoService(proto, PS_GETAVATARCAPS, AF_ENABLED, 0); - - return TRUE; -} - -BOOL Proto_IsAvatarFormatSupported(const char *proto, int format) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - return CallProtoService(proto, PS_GETAVATARCAPS, AF_FORMATSUPPORTED, format); - - if (ProtoServiceExists(proto, PS_ISAVATARFORMATSUPPORTED)) - return CallProtoService(proto, PS_ISAVATARFORMATSUPPORTED, 0, format); - - if (format >= PA_FORMAT_SWF) - return FALSE; - - return TRUE; -} - -int Proto_AvatarImageProportion(const char *proto) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - return CallProtoService(proto, PS_GETAVATARCAPS, AF_PROPORTION, 0); - - if (ProtoServiceExists(proto, PS_GETMYAVATARIMAGEPROPORTION)) - return CallProtoService(proto, PS_GETMYAVATARIMAGEPROPORTION, 0, 0); - - return 0; -} - -void Proto_GetAvatarMaxSize(const char *proto, int *width, int *height) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - { - POINT maxSize; - CallProtoService(proto, PS_GETAVATARCAPS, AF_MAXSIZE, (LPARAM) &maxSize); - *width = maxSize.y; - *height = maxSize.x; - } - else if (ProtoServiceExists(proto, PS_GETMYAVATARMAXSIZE)) - { - CallProtoService(proto, PS_GETMYAVATARMAXSIZE, (WPARAM) width, (LPARAM) height); - } - else - { - *width = 300; - *height = 300; - } - - if (*width < 0) - *width = 0; - else if (*width > 300) - *width = 300; - - if (*height < 0) - *height = 0; - else if (*height > 300) - *height = 300; -} - -BOOL Proto_NeedDelaysForAvatars(const char *proto) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - { - int ret = CallProtoService(proto, PS_GETAVATARCAPS, AF_DONTNEEDDELAYS, 0); - if (ret > 0) - return FALSE; - else - return TRUE; - } - - return TRUE; -} - -int Proto_GetAvatarMaxFileSize(const char *proto) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - return CallProtoService(proto, PS_GETAVATARCAPS, AF_MAXFILESIZE, 0); - - return 0; -} - -int Proto_GetDelayAfterFail(const char *proto) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - return CallProtoService(proto, PS_GETAVATARCAPS, AF_DELAYAFTERFAIL, 0); - - return 0; -} - -BOOL Proto_IsFetchingAlwaysAllowed(const char *proto) -{ - if (ProtoServiceExists(proto, PS_GETAVATARCAPS)) - return CallProtoService(proto, PS_GETAVATARCAPS, AF_FETCHALWAYS, 0); - - return FALSE; -} diff --git a/plugins/Avs/mir_thread.cpp b/plugins/Avs/mir_thread.cpp deleted file mode 100644 index d12a0c9731..0000000000 --- a/plugins/Avs/mir_thread.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright (C) 2005 Ricardo Pescuma Domenecci - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - - -#include "commonheaders.h" - - -BOOL g_shutDown = FALSE; -static HANDLE hShutdownEvent = NULL; -static HANDLE hOkToExit = NULL; - - -static int OkToExitProc(WPARAM wParam, LPARAM lParam) -{ - g_shutDown = TRUE; - SetEvent(hShutdownEvent); - CloseHandle(hShutdownEvent); - UnhookEvent(hOkToExit); - return 0; -} - - -void init_mir_thread() -{ - hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - hOkToExit = HookEvent(ME_SYSTEM_OKTOEXIT, OkToExitProc); -} - - -void mir_sleep(int time) -{ - if (!g_shutDown) - WaitForSingleObject(hShutdownEvent, time); -} diff --git a/plugins/Avs/mir_thread.h b/plugins/Avs/mir_thread.h deleted file mode 100644 index 0f4f20fe8e..0000000000 --- a/plugins/Avs/mir_thread.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright (C) 2005 Ricardo Pescuma Domenecci - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - - -#ifndef __MIR_THREAD_H__ -# define __MIR_THREAD_H__ - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -void init_mir_thread(); - - -// This variable need to be constantly checked against and the thread function must exit -// when this is true -extern BOOL g_shutDown; - -void mir_sleep(int time); - - - - - - -#ifdef __cplusplus -} -#endif - -#endif // __MIR_THREAD_H__ diff --git a/plugins/Avs/options.cpp b/plugins/Avs/options.cpp deleted file mode 100644 index 58502a9655..0000000000 --- a/plugins/Avs/options.cpp +++ /dev/null @@ -1,1147 +0,0 @@ -/* - -Miranda IM: the free IM client for Microsoft* Windows* - -Copyright 2000-2004 Miranda ICQ/IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" - -#define DM_SETAVATARNAME (WM_USER + 10) -#define DM_REALODAVATAR (WM_USER + 11) -#define DM_AVATARCHANGED (WM_USER + 12) -#define DM_PROTOCOLCHANGED (WM_USER + 13) - -extern int _DebugPopup(HANDLE hContact, const char *fmt, ...); -extern INT_PTR SetAvatar(WPARAM wParam, LPARAM lParam); -extern OBJLIST g_ProtoPictures; -extern HANDLE hEventChanged; -extern HINSTANCE g_hInst; -extern HICON g_hIcon; - -extern int CreateAvatarInCache(HANDLE hContact, struct avatarCacheEntry *ace, char *szProto); -extern INT_PTR ProtectAvatar(WPARAM wParam, LPARAM lParam); -extern int SetAvatarAttribute(HANDLE hContact, DWORD attrib, int mode); -extern int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist = FALSE, int pa_format = 0); -extern void DeleteAvatarFromCache(HANDLE, BOOL); -extern HBITMAP LoadPNG(struct avatarCacheEntry *ace, char *szFilename); -extern HANDLE GetContactThatHaveTheAvatar(HANDLE hContact, int locked = -1); - -extern int ProtoServiceExists(const char *szModule,const char *szService); -extern BOOL Proto_IsAvatarsEnabled(const char *proto); -extern BOOL ScreenToClient(HWND hWnd, LPRECT lpRect); - -static BOOL dialoginit = TRUE; - -struct WindowData { - HANDLE hContact; - HANDLE hHook; -}; - -static void RemoveProtoPic(const char *szProto) -{ - DBDeleteContactSetting(NULL, PPICT_MODULE, szProto); - - if ( szProto == NULL ) - return; - - if ( !lstrcmpA(AVS_DEFAULT, szProto )) { - for (int i = 0; i < g_ProtoPictures.getCount(); i++) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if (p.szProtoname == NULL) - continue; - - p.clear(); - CreateAvatarInCache(0, &p, ( char* )p.szProtoname); - NotifyEventHooks(hEventChanged, 0, (LPARAM)&p); - } - return; - } - - if (strstr(szProto, "Global avatar for")) { - char szProtoname[MAX_PATH] = {0}; - lstrcpynA(szProtoname, szProto, lstrlenA(szProto)- lstrlenA("accounts")); - lstrcpyA(szProtoname, strrchr(szProtoname, ' ') + 1); - for (int i = 0; i < g_ProtoPictures.getCount(); i++) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - - PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)p.szProtoname); - if (pdescr == NULL && lstrcmpA(p.szProtoname, szProto)) - continue; - - if (!lstrcmpA(p.szProtoname, szProto) || !lstrcmpA(pdescr->szProtoName, szProtoname)) { - if (p.szProtoname == NULL) - continue; - - p.clear(); - CreateAvatarInCache(0, &p, ( char* )p.szProtoname); - NotifyEventHooks( hEventChanged, 0, (LPARAM)&p ); - } - } - return; - } - - for (int i = 0; i < g_ProtoPictures.getCount(); i++) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if ( !lstrcmpA( p.szProtoname, szProto )) { - p.clear(); - NotifyEventHooks( hEventChanged, 0, (LPARAM)&p ); - } - } -} - -static void SetProtoPic(char *szProto) -{ - TCHAR FileName[MAX_PATH]; - OPENFILENAME ofn={0}; - TCHAR filter[256]; - - filter[0] = '\0'; - CallService(MS_UTILS_GETBITMAPFILTERSTRINGST, SIZEOF(filter), ( LPARAM )filter); - - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.lpstrFilter = filter; - ofn.hwndOwner=0; - ofn.lpstrFile = FileName; - ofn.nMaxFile = MAX_PATH; - ofn.nMaxFileTitle = MAX_PATH; - ofn.Flags=OFN_HIDEREADONLY; - ofn.lpstrInitialDir = _T("."); - *FileName = '\0'; - ofn.lpstrDefExt = _T(""); - if ( GetOpenFileName( &ofn )) { - HANDLE hFile; - - if ((hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) - return; - - CloseHandle(hFile); - - TCHAR szNewPath[MAX_PATH]; - AVS_pathToRelative(FileName, szNewPath); - DBWriteContactSettingTString(NULL, PPICT_MODULE, szProto, szNewPath); - - if (!lstrcmpA(AVS_DEFAULT, szProto)) { - for ( int i = 0; i < g_ProtoPictures.getCount(); i++ ) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if (lstrlenA(p.szProtoname) != 0) { - if (p.hbmPic == 0) { - CreateAvatarInCache(0, &p, ( char* )szProto); - NotifyEventHooks(hEventChanged, 0, (LPARAM)&p); - } - } - } - } - else if (strstr(szProto, "Global avatar for")) { - char szProtoname[MAX_PATH] = {0}; - lstrcpynA(szProtoname, szProto, lstrlenA(szProto)- lstrlenA("accounts")); - lstrcpyA(szProtoname, strrchr(szProtoname, ' ') + 1); - for (int i = 0; i < g_ProtoPictures.getCount(); i++) { - PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)g_ProtoPictures[i].szProtoname); - if (pdescr == NULL && lstrcmpA(g_ProtoPictures[i].szProtoname, szProto)) - continue; - - if (!lstrcmpA(g_ProtoPictures[i].szProtoname, szProto) || !lstrcmpA(pdescr->szProtoName, szProtoname)) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if (lstrlenA(p.szProtoname) != 0) { - if (p.hbmPic == 0) { - CreateAvatarInCache(0, &p, ( char* )szProto); - NotifyEventHooks(hEventChanged, 0, (LPARAM)&p); - } - } - } - } - } - else { - for (int i = 0; i < g_ProtoPictures.getCount(); i++) { - protoPicCacheEntry& p = g_ProtoPictures[i]; - if ( lstrlenA(p.szProtoname) == 0) - break; - - if (!strcmp(p.szProtoname, szProto) && lstrlenA(p.szProtoname) == lstrlenA(szProto)) { - if (p.hbmPic != 0) - DeleteObject(p.hbmPic); - ZeroMemory(&p, sizeof(avatarCacheEntry)); - CreateAvatarInCache(0, &p, ( char* )szProto); - NotifyEventHooks(hEventChanged, 0, (LPARAM)&p ); - break; - } - } - } - } -} - -static char* g_selectedProto; - -INT_PTR CALLBACK DlgProcOptionsAvatars(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - - CheckDlgButton(hwndDlg, IDC_SHOWWARNINGS, DBGetContactSettingByte(0, AVS_MODULE, "warnings", 0)); - CheckDlgButton(hwndDlg, IDC_MAKE_GRAYSCALE, DBGetContactSettingByte(0, AVS_MODULE, "MakeGrayscale", 0)); - CheckDlgButton(hwndDlg, IDC_MAKE_TRANSPARENT_BKG, DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0)); - CheckDlgButton(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL, DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", 0)); - - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2)); - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5)); - - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10)); - { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL), enabled); - } - - return TRUE; - - case WM_COMMAND: - if ((LOWORD(wParam) == IDC_BKG_NUM_POINTS || LOWORD(wParam) == IDC_BKG_COLOR_DIFFERENCE) - && (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())) - return FALSE; - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - switch (((LPNMHDR) lParam)->idFrom) { - case IDC_MAKE_TRANSPARENT_BKG: - { - BOOL transp_enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL), transp_enabled); - break; - } - case 0: - switch (((LPNMHDR) lParam)->code) { - case PSN_APPLY: - DBWriteContactSettingByte(NULL, AVS_MODULE, "warnings", IsDlgButtonChecked(hwndDlg, IDC_SHOWWARNINGS) ? 1 : 0); - DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeGrayscale", IsDlgButtonChecked(hwndDlg, IDC_MAKE_GRAYSCALE) ? 1 : 0); - DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeTransparentBkg", IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSPARENT_BKG) ? 1 : 0); - DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeTransparencyProportionalToColorDiff", IsDlgButtonChecked(hwndDlg, IDC_MAKE_TRANSP_PROPORTIONAL) ? 1 : 0); - DBWriteContactSettingWord(NULL, AVS_MODULE, "TranspBkgNumPoints", (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_GETPOS, 0, 0)); - DBWriteContactSettingWord(NULL, AVS_MODULE, "TranspBkgColorDiff", (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_GETPOS, 0, 0)); - } } - break; - } - return FALSE; -} - -INT_PTR CALLBACK DlgProcOptionsOwn(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - - CheckDlgButton(hwndDlg, IDC_MAKE_MY_AVATARS_TRANSP, DBGetContactSettingByte(0, AVS_MODULE, "MakeMyAvatarsTransparent", 0)); - CheckDlgButton(hwndDlg, IDC_SET_MAKE_SQUARE, DBGetContactSettingByte(0, AVS_MODULE, "SetAllwaysMakeSquare", 0)); - - return TRUE; - - case WM_COMMAND: - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - switch (((LPNMHDR) lParam)->idFrom) { - case 0: - switch (((LPNMHDR) lParam)->code) { - case PSN_APPLY: - DBWriteContactSettingByte(NULL, AVS_MODULE, "MakeMyAvatarsTransparent", IsDlgButtonChecked(hwndDlg, IDC_MAKE_MY_AVATARS_TRANSP) ? 1 : 0); - DBWriteContactSettingByte(NULL, AVS_MODULE, "SetAllwaysMakeSquare", IsDlgButtonChecked(hwndDlg, IDC_SET_MAKE_SQUARE) ? 1 : 0); - } } - break; - } - return FALSE; -} - -static char* GetProtoFromList(HWND hwndDlg, int iItem) -{ - LVITEM item; - item.mask = LVIF_PARAM; - item.iItem = iItem; - if ( !ListView_GetItem( GetDlgItem(hwndDlg, IDC_PROTOCOLS), &item )) - return NULL; - - protoPicCacheEntry* pce = ( protoPicCacheEntry* )item.lParam; - return ( pce == NULL ) ? NULL : pce->szProtoname; -} - -INT_PTR CALLBACK DlgProcOptionsProtos(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); - HWND hwndChoosePic = GetDlgItem(hwndDlg, IDC_SETPROTOPIC); - HWND hwndRemovePic = GetDlgItem(hwndDlg, IDC_REMOVEPROTOPIC); - - switch (msg) { - case WM_INITDIALOG: - { - LVITEM item = {0}; - LVCOLUMN lvc = {0}; - UINT64 newItem = 0; - - dialoginit = TRUE; - TranslateDialogDefault(hwndDlg); - ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); - lvc.mask = LVCF_FMT; - lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; - ListView_InsertColumn(hwndList, 0, &lvc); - - item.mask = LVIF_TEXT | LVIF_PARAM; - item.iItem = 1000; - for (int i = 0; i < g_ProtoPictures.getCount(); i++ ) { - item.lParam = ( LPARAM )&g_ProtoPictures[i]; - item.pszText = g_ProtoPictures[i].tszAccName; - newItem = ListView_InsertItem(hwndList, &item); - if (newItem >= 0) - ListView_SetCheckState(hwndList, newItem, - DBGetContactSettingByte(NULL, AVS_MODULE, g_ProtoPictures[i].szProtoname, 1) ? TRUE : FALSE); - } - ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); - ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); - EnableWindow(hwndChoosePic, FALSE); - EnableWindow(hwndRemovePic, FALSE); - - dialoginit = FALSE; - } - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_SETPROTOPIC: - case IDC_REMOVEPROTOPIC: - { - int iItem = ListView_GetSelectionMark(hwndList); - char* szProto = GetProtoFromList(hwndDlg, iItem); - if ( szProto ) { - if (LOWORD(wParam) == IDC_SETPROTOPIC) - SetProtoPic( szProto ); - else - RemoveProtoPic( szProto ); - - NMHDR nm = { hwndList, IDC_PROTOCOLS, NM_CLICK }; - SendMessage(hwndDlg, WM_NOTIFY, 0, (LPARAM)&nm); - } - break; - } - } - break; - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; - - if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_PROTOPIC) { - AVATARDRAWREQUEST avdrq = {0}; - avdrq.cbSize = sizeof(avdrq); - avdrq.hTargetDC = dis->hDC; - avdrq.dwFlags |= AVDRQ_PROTOPICT; - avdrq.szProto = g_selectedProto; - GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw); - CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq); - } - return TRUE; - } - - case WM_NOTIFY: - if (dialoginit) - break; - - switch (((LPNMHDR) lParam)->idFrom) { - case IDC_PROTOCOLS: - switch (((LPNMHDR) lParam)->code) { - case LVN_KEYDOWN: - { - NMLVKEYDOWN* ptkd = (NMLVKEYDOWN*)lParam; - if (ptkd&&ptkd->wVKey==VK_SPACE&&ListView_GetSelectedCount(ptkd->hdr.hwndFrom)==1) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - break; - case LVN_ITEMCHANGED: - { - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - if (IsWindowVisible(GetDlgItem(hwndDlg, IDC_PROTOCOLS)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK)) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - break; - case NM_CLICK: - { - EnableWindow(hwndChoosePic, TRUE); - EnableWindow(hwndRemovePic, TRUE); - - int iItem = ListView_GetSelectionMark(hwndList); - g_selectedProto = GetProtoFromList(hwndDlg, iItem); - if ( g_selectedProto ) { - DBVARIANT dbv = {0}; - if (!DBGetContactSettingTString(NULL, PPICT_MODULE, g_selectedProto, &dbv)) - { - if (!AVS_pathIsAbsolute(dbv.ptszVal)) - { - TCHAR szFinalPath[MAX_PATH]; - mir_sntprintf(szFinalPath, SIZEOF(szFinalPath), _T("%%miranda_path%%\\%s"), dbv.ptszVal); - SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, szFinalPath); - } - else SetDlgItemText(hwndDlg, IDC_PROTOAVATARNAME, dbv.ptszVal); - - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); - DBFreeVariant(&dbv); - } - else { - SetWindowText(GetDlgItem(hwndDlg, IDC_PROTOAVATARNAME), _T("")); - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); - } - } - break; - } - } - break; - case 0: - switch (((LPNMHDR) lParam)->code) { - case PSN_APPLY: - { - for (int i = 0; i < ListView_GetItemCount(hwndList); i++) { - char *szProto = GetProtoFromList(hwndDlg, i); - - BOOL oldVal = DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1); - BOOL newVal = ListView_GetCheckState(hwndList, i); - - if (oldVal && !newVal) - { - HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact != NULL) - { - char* szContactProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); - if (szContactProto != NULL && !strcmp(szContactProto, szProto)) - DeleteAvatarFromCache(hContact, TRUE); - - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); - } - } - - if (newVal) - DBWriteContactSettingByte(NULL, AVS_MODULE, szProto, 1); - else - DBWriteContactSettingByte(NULL, AVS_MODULE, szProto, 0); - } - } - } - } - break; - } - return FALSE; -} - -void LoadTransparentData(HWND hwndDlg, HANDLE hContact) -{ - CheckDlgButton(hwndDlg, IDC_MAKETRANSPBKG, DBGetContactSettingByte(hContact, "ContactPhoto", "MakeTransparentBkg", DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0))); - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5))); - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETPOS, 0, (LPARAM)DBGetContactSettingWord(hContact, "ContactPhoto", "TranspBkgColorDiff", DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10))); - - BOOL transp_enabled = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), transp_enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), transp_enabled); -} - -void SaveTransparentData(HWND hwndDlg, HANDLE hContact) -{ - BOOL transp = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); - if (DBGetContactSettingByte(0, AVS_MODULE, "MakeTransparentBkg", 0) == transp) - DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); - else - DBWriteContactSettingByte(hContact, "ContactPhoto", "MakeTransparentBkg", transp); - - WORD tmp = (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_GETPOS, 0, 0); - if (DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgNumPoints", 5) == tmp) - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); - else - DBWriteContactSettingWord(hContact, "ContactPhoto", "TranspBkgNumPoints", tmp); - - tmp = (WORD) SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_GETPOS, 0, 0); - if (DBGetContactSettingWord(0, AVS_MODULE, "TranspBkgColorDiff", 10) == tmp) - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); - else - DBWriteContactSettingWord(hContact, "ContactPhoto", "TranspBkgColorDiff", tmp); -} - -void SaveTransparentData(HWND hwndDlg, HANDLE hContact, BOOL locked) -{ - SaveTransparentData(hwndDlg, hContact); - - HANDLE tmp = GetContactThatHaveTheAvatar(hContact, locked); - if (tmp != hContact) - SaveTransparentData(hwndDlg, tmp); -} - -INT_PTR CALLBACK DlgProcAvatarOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact; - struct WindowData *dat = (struct WindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - if (dat) - hContact = dat->hContact; - - switch(msg) { - case WM_INITDIALOG: - { - TCHAR szTitle[512]; - TCHAR *szNick = NULL; - struct WindowData *dat = (struct WindowData *)malloc(sizeof(struct WindowData)); - - if (dat) - dat->hContact = (HANDLE)lParam; - - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); - hContact = (HANDLE)lParam; - TranslateDialogDefault(hwndDlg); - if (hContact) { - szNick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR); - mir_sntprintf(szTitle, 500, TranslateT("Set avatar options for %s"), szNick); - SetWindowText(hwndDlg, szTitle); - } - SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); - ShowWindow(hwndDlg, SW_SHOWNORMAL); - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, FALSE); - CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); - CheckDlgButton(hwndDlg, IDC_HIDEAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0) ? TRUE : FALSE); - - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), 0); - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2)); - - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), 0); - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); - - LoadTransparentData(hwndDlg, GetContactThatHaveTheAvatar(hContact)); - dat->hHook = HookEventMessage(ME_AV_AVATARCHANGED, hwndDlg, DM_AVATARCHANGED); - SendMessage(hwndDlg, WM_SETICON, IMAGE_ICON, (LPARAM)g_hIcon); - } - return TRUE; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case ID_USE_DEFAULTS: - hContact = GetContactThatHaveTheAvatar(hContact); - - DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); - - LoadTransparentData(hwndDlg, hContact); - - SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); - break; - - case IDOK: - { - BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR); - int hidden = IsDlgButtonChecked(hwndDlg, IDC_HIDEAVATAR) ? 1 : 0; - SetAvatarAttribute(hContact, AVS_HIDEONCLIST, hidden); - if (hidden != DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0)) - DBWriteContactSettingByte(hContact, "ContactPhoto", "Hidden", hidden); - - if (!locked && DBGetContactSettingByte(hContact, "ContactPhoto", "NeedUpdate", 0)) - QueueAdd(hContact); - - // Continue to the cancel handle - } - - case IDCANCEL: - DestroyWindow(hwndDlg); - break; - - case IDC_PROTECTAVATAR: - { - BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR); - ProtectAvatar((WPARAM)hContact, locked ? 1 : 0); - } - break; - - case IDC_CHANGE: - SetAvatar((WPARAM)hContact, 0); - SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); - CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); - break; - - case IDC_BKG_NUM_POINTS: - case IDC_BKG_COLOR_DIFFERENCE: - if (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) - break; - - case IDC_MAKETRANSPBKG: - { - BOOL enable = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enable); - - SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); - } - break; - - case IDC_RESET: - { - char *szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - DBVARIANT dbv = {0}; - - ProtectAvatar((WPARAM)hContact, 0); - if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { - if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { - DeleteFile(dbv.ptszVal); - DBFreeVariant(&dbv); - } - } - DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); - DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); - DBDeleteContactSetting(hContact, "ContactPhoto", "File"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); - DBDeleteContactSetting(hContact, szProto, "AvatarHash"); - DBDeleteContactSetting(hContact, szProto, "AvatarSaved"); - DeleteAvatarFromCache(hContact, FALSE); - - QueueAdd(hContact); - - DestroyWindow(hwndDlg); - } - break; - - case IDC_DELETE: - { - DBVARIANT dbv = {0}; - ProtectAvatar((WPARAM)hContact, 0); - if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { - if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { - DeleteFile(dbv.ptszVal); - DBFreeVariant(&dbv); - } - } - DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); - DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); - DBDeleteContactSetting(hContact, "ContactPhoto", "File"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); - DeleteAvatarFromCache(hContact, FALSE); - SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); - break; - } - } - break; - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; - - if (dis->CtlType == ODT_BUTTON && dis->CtlID == IDC_PROTOPIC) { - AVATARDRAWREQUEST avdrq = {0}; - GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), &avdrq.rcDraw); - - FillRect(dis->hDC, &avdrq.rcDraw, GetSysColorBrush(COLOR_BTNFACE)); - - avdrq.hContact = hContact; - avdrq.cbSize = sizeof(avdrq); - avdrq.hTargetDC = dis->hDC; - avdrq.dwFlags |= AVDRQ_DRAWBORDER; - avdrq.clrBorder = GetSysColor(COLOR_BTNTEXT); - avdrq.radius = 6; - if (!CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdrq)) - { - // Get text rectangle - RECT rc = avdrq.rcDraw; - rc.top += 10; - rc.bottom -= 10; - rc.left += 10; - rc.right -= 10; - - // Calc text size - RECT rc_ret = rc; - DrawText(dis->hDC, TranslateT("Contact has no avatar"), -1, &rc_ret, - DT_WORDBREAK | DT_NOPREFIX | DT_CENTER | DT_CALCRECT); - - // Calc needed size - rc.top += ((rc.bottom - rc.top) - (rc_ret.bottom - rc_ret.top)) / 2; - rc.bottom = rc.top + (rc_ret.bottom - rc_ret.top); - DrawText(dis->hDC, TranslateT("Contact has no avatar"), -1, &rc, - DT_WORDBREAK | DT_NOPREFIX | DT_CENTER); - } - - FrameRect(dis->hDC, &avdrq.rcDraw, GetSysColorBrush(COLOR_BTNSHADOW)); - } - return TRUE; - } - case DM_SETAVATARNAME: - { - TCHAR szFinalName[MAX_PATH]; - DBVARIANT dbv = {0}; - BYTE is_locked = DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0); - - szFinalName[0] = 0; - - if (is_locked && !DBGetContactSettingTString(hContact, "ContactPhoto", "Backup", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, szFinalName); - DBFreeVariant(&dbv); - } - else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "RFile", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, szFinalName); - DBFreeVariant(&dbv); - } - else if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { - AVS_pathToAbsolute(dbv.ptszVal, szFinalName); - DBFreeVariant(&dbv); - } - szFinalName[MAX_PATH - 1] = 0; - SetDlgItemText(hwndDlg, IDC_AVATARNAME, szFinalName); - break; - } - - case DM_REALODAVATAR: - SaveTransparentData(hwndDlg, hContact, IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR)); - ChangeAvatar(hContact, TRUE); - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); - break; - - case DM_AVATARCHANGED: - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOPIC), NULL, TRUE); - break; - - case WM_NCDESTROY: - if (dat) { - UnhookEvent(dat->hHook); - free(dat); - } - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - break; - } - return FALSE; -} - -INT_PTR CALLBACK DlgProcAvatarUserInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact; - struct WindowData *dat = (struct WindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - if (dat) - hContact = dat->hContact; - - switch(msg) { - case WM_INITDIALOG: - { - dat = (struct WindowData *) malloc(sizeof(struct WindowData)); - if (dat == NULL) - return FALSE; - dat->hContact = (HANDLE)lParam; - - HWND protopic = GetDlgItem(hwndDlg, IDC_PROTOPIC); - SendMessage(protopic, AVATAR_SETCONTACT, 0, (LPARAM) dat->hContact); - SendMessage(protopic, AVATAR_SETAVATARBORDERCOLOR, 0, (LPARAM) GetSysColor(COLOR_BTNSHADOW)); - SendMessage(protopic, AVATAR_SETNOAVATARTEXT, 0, (LPARAM) LPGENT("Contact has no avatar")); - SendMessage(protopic, AVATAR_RESPECTHIDDEN, 0, (LPARAM) FALSE); - SendMessage(protopic, AVATAR_SETRESIZEIFSMALLER, 0, (LPARAM) FALSE); - - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); - hContact = (HANDLE)lParam; - TranslateDialogDefault(hwndDlg); - SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); - CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); - CheckDlgButton(hwndDlg, IDC_HIDEAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0) ? TRUE : FALSE); - - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), 0); - SendDlgItemMessage(hwndDlg, IDC_BKG_NUM_POINTS_SPIN, UDM_SETRANGE, 0, MAKELONG(8, 2)); - - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), 0); - SendDlgItemMessage(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); - - LoadTransparentData(hwndDlg, GetContactThatHaveTheAvatar(hContact)); - } - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) { - case ID_USE_DEFAULTS: - hContact = GetContactThatHaveTheAvatar(hContact); - - DBDeleteContactSetting(hContact, "ContactPhoto", "MakeTransparentBkg"); - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgNumPoints"); - DBDeleteContactSetting(hContact, "ContactPhoto", "TranspBkgColorDiff"); - - LoadTransparentData(hwndDlg, hContact); - - SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); - break; - - case IDC_CHANGE: - SetAvatar((WPARAM)hContact, 0); - SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); - CheckDlgButton(hwndDlg, IDC_PROTECTAVATAR, DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) ? TRUE : FALSE); - break; - - case IDC_HIDEAVATAR: - { - int hidden = IsDlgButtonChecked(hwndDlg, IDC_HIDEAVATAR) ? 1 : 0; - SetAvatarAttribute(hContact, AVS_HIDEONCLIST, hidden); - if (hidden != DBGetContactSettingByte(hContact, "ContactPhoto", "Hidden", 0)) - DBWriteContactSettingByte(hContact, "ContactPhoto", "Hidden", hidden); - break; - } - - case IDC_PROTECTAVATAR: - { - BOOL locked = IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR); - SaveTransparentData(hwndDlg, hContact, locked); - ProtectAvatar((WPARAM)hContact, locked ? 1 : 0); - - break; - } - case IDC_BKG_NUM_POINTS: - case IDC_BKG_COLOR_DIFFERENCE: - if (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus()) - break; - case IDC_MAKETRANSPBKG: - { - BOOL enable = IsDlgButtonChecked(hwndDlg, IDC_MAKETRANSPBKG); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_L), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS_SPIN), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_NUM_POINTS), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_L), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE_SPIN), enable); - EnableWindow(GetDlgItem(hwndDlg, IDC_BKG_COLOR_DIFFERENCE), enable); - - SendMessage(hwndDlg, DM_REALODAVATAR, 0, 0); - break; - } - case IDC_RESET: - { - char *szProto = ( char* )CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - DBVARIANT dbv = {0}; - - ProtectAvatar((WPARAM)hContact, 0); - if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { - if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { - DeleteFile(dbv.ptszVal); - DBFreeVariant(&dbv); - } - } - DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); - DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); - DBDeleteContactSetting(hContact, "ContactPhoto", "File"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); - DBDeleteContactSetting(hContact, szProto, "AvatarHash"); - DBDeleteContactSetting(hContact, szProto, "AvatarSaved"); - DeleteAvatarFromCache(hContact, FALSE); - - QueueAdd(hContact); - break; - } - case IDC_DELETE: - { - DBVARIANT dbv = {0}; - - ProtectAvatar((WPARAM)hContact, 0); - if (MessageBox(0, TranslateT("Delete picture file from disk (may be necessary to force a reload, but will delete local pictures)?"), TranslateT("Reset contact picture"), MB_YESNO) == IDYES) { - if (!DBGetContactSettingTString(hContact, "ContactPhoto", "File", &dbv)) { - DeleteFile(dbv.ptszVal); - DBFreeVariant(&dbv); - } - } - DBDeleteContactSetting(hContact, "ContactPhoto", "Locked"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); - DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); - DBDeleteContactSetting(hContact, "ContactPhoto", "File"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); - DeleteAvatarFromCache(hContact, FALSE); - SendMessage(hwndDlg, DM_SETAVATARNAME, 0, 0); - break; - } - } - break; - - case DM_REALODAVATAR: - SaveTransparentData(hwndDlg, hContact, IsDlgButtonChecked(hwndDlg, IDC_PROTECTAVATAR)); - ChangeAvatar(hContact, TRUE); - break; - - case WM_NCDESTROY: - if (dat) - free(dat); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - break; - } - return FALSE; -} - -static char * GetSelectedProtocol(HWND hwndDlg) -{ - HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); - - // Get selection - int iItem = ListView_GetSelectionMark(hwndList); - if (iItem < 0) - return NULL; - - // Get protocol name - LVITEM item = {0}; - item.mask = LVIF_PARAM; - item.iItem = iItem; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&item); - return ( char* ) item.lParam; -} - -static void EnableDisableControls(HWND hwndDlg, char *proto) -{ - if (IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) - { - if (proto == NULL) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); - } - else - { - if (!ProtoServiceExists(proto, PS_SETMYAVATAR)) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); - } - else - { - EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE); - - int width, height; - SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_GETUSEDSPACE, (WPARAM) &width, (LPARAM) &height); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), (LPARAM) width != 0 || height != 0); - } - } - } - else - { - EnableWindow(GetDlgItem(hwndDlg, IDC_CHANGE), TRUE); - - if (DBGetContactSettingByte(NULL, AVS_MODULE, "GlobalUserAvatarNotConsistent", 1)) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); - } - else - { - int width, height; - SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_GETUSEDSPACE, (WPARAM) &width, (LPARAM) &height); - EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), (LPARAM) width != 0 || height != 0); - } - } -} - -static void OffsetWindow(HWND parent, HWND hwnd, int dx, int dy) -{ - RECT rc; - GetWindowRect(hwnd, &rc); - ScreenToClient(parent, &rc); - OffsetRect(&rc, dx, dy); - MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); -} - -static void EnableDisableProtocols(HWND hwndDlg, BOOL init) -{ - int diff = 147; // Pre-calc - BOOL perProto = IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO); - HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); - - if (perProto) - { - if (!init && !IsWindowVisible(hwndList)) - { - // Show list of protocols - ShowWindow(hwndList, SW_SHOW); - - // Move controls - OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_PROTOPIC), diff, 0); - OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_CHANGE), diff, 0); - OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_DELETE), diff, 0); - } - - char * proto = GetSelectedProtocol(hwndDlg); - if (proto == NULL) - { - ListView_SetItemState(hwndList, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x0F); - } - else - { - SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, (LPARAM) proto); - EnableDisableControls(hwndDlg, proto); - } - } - else - { - if (init || IsWindowVisible(hwndList)) - { - // Show list of protocols - ShowWindow(hwndList, SW_HIDE); - - // Move controls - OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_PROTOPIC), -diff, 0); - OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_CHANGE), -diff, 0); - OffsetWindow(hwndDlg, GetDlgItem(hwndDlg, IDC_DELETE), -diff, 0); - } - - SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, NULL); - } -} - -INT_PTR CALLBACK DlgProcAvatarProtoInfo(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - HWND protopic = GetDlgItem(hwndDlg, IDC_PROTOPIC); - SendMessage(protopic, AVATAR_SETAVATARBORDERCOLOR, 0, (LPARAM) GetSysColor(COLOR_BTNSHADOW)); - SendMessage(protopic, AVATAR_SETNOAVATARTEXT, 0, (LPARAM) LPGENT("No avatar")); - SendMessage(protopic, AVATAR_SETRESIZEIFSMALLER, 0, (LPARAM) FALSE); - - HWND hwndList = GetDlgItem(hwndDlg, IDC_PROTOCOLS); - ListView_SetExtendedListViewStyleEx(hwndList, 0, LVS_EX_SUBITEMIMAGES); - - HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus()? ILC_COLOR32 : ILC_COLOR16), 4, 0); - ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); - - LVCOLUMN lvc = {0}; - lvc.mask = LVCF_FMT; - lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT; - ListView_InsertColumn(hwndList, 0, &lvc); - - LVITEM item = {0}; - item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; - item.iItem = 1000; - - // List protocols - PROTOACCOUNT **accs; - int i, count, num = 0; - - ProtoEnumAccounts( &count, &accs ); - for (i = 0; i < count; i++) - { - if ( !ProtoServiceExists( accs[i]->szModuleName, PS_GETMYAVATAR)) - continue; - - if ( !Proto_IsAvatarsEnabled( accs[i]->szModuleName )) - continue; - - ImageList_AddIcon(hIml, LoadSkinnedProtoIcon( accs[i]->szModuleName, ID_STATUS_ONLINE)); - item.pszText = accs[i]->tszAccountName; - item.iImage = num; - item.lParam = (LPARAM)accs[i]->szModuleName; - - ListView_InsertItem(hwndList, &item); - num++; - } - - ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE); - ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP); - - // Check if should show per protocol avatars - CheckDlgButton(hwndDlg, IDC_PER_PROTO, DBGetContactSettingByte(NULL, AVS_MODULE, "PerProtocolUserAvatars", 1)); - EnableDisableProtocols(hwndDlg, TRUE); - } - break; - - case WM_NOTIFY: - { - LPNMHDR nm = (LPNMHDR) lParam; - switch(nm->idFrom) { - case IDC_PROTOCOLS: - switch (nm->code) { - case LVN_ITEMCHANGED: - { - LPNMLISTVIEW li = (LPNMLISTVIEW) nm; - if (li->uNewState & LVIS_SELECTED) - { - SendDlgItemMessage(hwndDlg, IDC_PROTOPIC, AVATAR_SETPROTOCOL, 0, li->lParam); - EnableDisableControls(hwndDlg, ( char* ) li->lParam); - } - } - break; - } - break; - - case IDC_PROTOPIC: - switch (nm->code) { - case NM_AVATAR_CHANGED: - EnableDisableControls(hwndDlg, GetSelectedProtocol(hwndDlg)); - break; - } - break; - } - break; - } - case WM_COMMAND: - switch(LOWORD(wParam)) { - case IDC_CHANGE: - if (!IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) - avSetMyAvatar(NULL, NULL); - else { - char *proto = GetSelectedProtocol(hwndDlg); - if (proto != NULL) - avSetMyAvatar(proto, NULL); - } - break; - - case IDC_DELETE: - if (!IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO)) { - if (MessageBox(hwndDlg, TranslateT("Are you sure you want to remove your avatar?"), TranslateT("Global Avatar"), MB_YESNO) == IDYES) - avSetMyAvatar(NULL, _T("")); - } - else { - char *proto = GetSelectedProtocol(hwndDlg); - if (proto == NULL) - break; - - char description[256]; - CallProtoService(proto, PS_GETNAME, SIZEOF(description),(LPARAM) description); - TCHAR *descr = mir_a2t(description); - if (MessageBox(hwndDlg, TranslateT("Are you sure you want to remove your avatar?"), descr, MB_YESNO) == IDYES) - avSetMyAvatar(proto, _T("")); - mir_free(descr); - } - break; - - case IDC_PER_PROTO: - DBWriteContactSettingByte(NULL, AVS_MODULE, "PerProtocolUserAvatars", IsDlgButtonChecked(hwndDlg, IDC_PER_PROTO) ? 1 : 0); - EnableDisableProtocols(hwndDlg, FALSE); - break; - } - break; - } - return FALSE; -} diff --git a/plugins/Avs/poll.cpp b/plugins/Avs/poll.cpp deleted file mode 100644 index 32553a9c33..0000000000 --- a/plugins/Avs/poll.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* -Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" - -/* -It has 1 queue: -A queue to request items. One request is done at a time, REQUEST_WAIT_TIME miliseconts after it has beeing fired - ACKRESULT_STATUS. This thread only requests the avatar (and maybe add it to the cache queue) -*/ - -#define REQUEST_WAIT_TIME 3000 - -// Time to wait before re-requesting an avatar that failed -#define REQUEST_FAIL_WAIT_TIME (3 * 60 * 60 * 1000) - -// Time to wait before re-requesting an avatar that received an wait for -#define REQUEST_WAITFOR_WAIT_TIME (30 * 60 * 1000) - -// Number of mileseconds the threads wait until take a look if it is time to request another item -#define POOL_DELAY 1000 - -// Number of mileseconds the threads wait after a GAIR_WAITFOR is returned -#define REQUEST_DELAY 18000 - - -// Prototypes /////////////////////////////////////////////////////////////////////////// - -static void RequestThread(void *vParam); - -extern HANDLE hShutdownEvent; -extern char *g_szMetaName; -extern int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist = FALSE, int pa_format = 0); -extern int DeleteAvatar(HANDLE hContact); -extern void MakePathRelative(HANDLE hContact, TCHAR *path); -int Proto_GetDelayAfterFail(const char *proto); -BOOL Proto_IsFetchingAlwaysAllowed(const char *proto); - -struct CacheNode *FindAvatarInCache(HANDLE hContact, BOOL add, BOOL findAny = FALSE); - -extern HANDLE hEventContactAvatarChanged; -extern BOOL g_AvatarHistoryAvail; -extern FI_INTERFACE *fei; - -#ifdef _DEBUG -int _DebugTrace(const char *fmt, ...); -int _DebugTrace(HANDLE hContact, const char *fmt, ...); -#endif - -// Functions //////////////////////////////////////////////////////////////////////////// - -// Items with higher priority at end -static int QueueSortItems( const QueueItem* i1, const QueueItem* i2) -{ - return i2->check_time - i1->check_time; -} - -static OBJLIST queue( 20, QueueSortItems ); -static CRITICAL_SECTION cs; -static int waitTime; - -void InitPolls() -{ - waitTime = REQUEST_WAIT_TIME; - InitializeCriticalSection( &cs ); - - // Init request queue - mir_forkthread(RequestThread, NULL); -} - -void FreePolls() -{ -} - -// Return true if this protocol can have avatar requested -static BOOL PollProtocolCanHaveAvatar(const char *szProto) -{ - int pCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0); - int status = CallProtoService(szProto, PS_GETSTATUS, 0, 0); - return (pCaps & PF4_AVATARS) - && (g_szMetaName == NULL || strcmp(g_szMetaName, szProto)) - && ((status > ID_STATUS_OFFLINE && status != ID_STATUS_INVISIBLE) || Proto_IsFetchingAlwaysAllowed(szProto)); -} - -// Return true if this protocol has to be checked -static BOOL PollCheckProtocol(const char *szProto) -{ - return DBGetContactSettingByte(NULL, AVS_MODULE, szProto, 1); -} - -// Return true if this contact can have avatar requested -static BOOL PollContactCanHaveAvatar(HANDLE hContact, const char *szProto) -{ - int status = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE); - return (Proto_IsFetchingAlwaysAllowed(szProto) || status != ID_STATUS_OFFLINE) - && !DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) - && DBGetContactSettingByte(hContact, "CList", "ApparentMode", 0) != ID_STATUS_OFFLINE; -} - -// Return true if this contact has to be checked -static BOOL PollCheckContact(HANDLE hContact, const char *szProto) -{ - return !DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0) - && FindAvatarInCache(hContact, FALSE, TRUE) != NULL; -} - -static void QueueRemove(HANDLE hContact) -{ - EnterCriticalSection(&cs); - - for (int i = queue.getCount()-1 ; i >= 0 ; i-- ) { - QueueItem& item = queue[i]; - if (item.hContact == hContact) - queue.remove(i); - } - - LeaveCriticalSection(&cs); -} - -static void QueueAdd(HANDLE hContact, int waitTime) -{ - if(fei == NULL) - return; - - EnterCriticalSection(&cs); - - // Only add if not exists yet - int i; - for (i = queue.getCount()-1; i >= 0; i--) - if ( queue[i].hContact == hContact) - break; - - if (i < 0) { - QueueItem *item = new QueueItem; - if (item != NULL) { - item->hContact = hContact; - item->check_time = GetTickCount() + waitTime; - queue.insert(item); - } } - - LeaveCriticalSection(&cs); -} - -// Add an contact to a queue -void QueueAdd(HANDLE hContact) -{ - QueueAdd(hContact, waitTime); -} - -void ProcessAvatarInfo(HANDLE hContact, int type, PROTO_AVATAR_INFORMATIONT *pai, const char *szProto) -{ - QueueRemove(hContact); - - if (type == GAIR_SUCCESS) - { - if (pai == NULL) - return; - - // Fix settings in DB - DBDeleteContactSetting(hContact, "ContactPhoto", "NeedUpdate"); - DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); - if (!DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0)) - DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); - DBWriteContactSettingTString(hContact, "ContactPhoto", "File", pai->filename); - DBWriteContactSettingWord(hContact, "ContactPhoto", "Format", pai->format); - - if (pai->format == PA_FORMAT_PNG || pai->format == PA_FORMAT_JPEG - || pai->format == PA_FORMAT_ICON || pai->format == PA_FORMAT_BMP - || pai->format == PA_FORMAT_GIF) - { - // We can load it! - MakePathRelative(hContact, pai->filename); - ChangeAvatar(hContact, TRUE, TRUE, pai->format); - } - else - { - // As we can't load it, notify but don't load - ChangeAvatar(hContact, FALSE, TRUE, pai->format); - } - } - else if (type == GAIR_NOAVATAR) - { - DBDeleteContactSetting(hContact, "ContactPhoto", "NeedUpdate"); - - if (DBGetContactSettingByte(NULL, AVS_MODULE, "RemoveAvatarWhenContactRemoves", 1)) - { - // Delete settings - DBDeleteContactSetting(hContact, "ContactPhoto", "RFile"); - if (!DBGetContactSettingByte(hContact, "ContactPhoto", "Locked", 0)) - DBDeleteContactSetting(hContact, "ContactPhoto", "Backup"); - DBDeleteContactSetting(hContact, "ContactPhoto", "File"); - DBDeleteContactSetting(hContact, "ContactPhoto", "Format"); - - // Fix cache - ChangeAvatar(hContact, FALSE, TRUE, 0); - } - } - else if (type == GAIR_FAILED) - { - int wait = Proto_GetDelayAfterFail(szProto); - if (wait > 0) - { - // Reschedule to request after needed time (and avoid requests before that) - EnterCriticalSection(&cs); - QueueRemove(hContact); - QueueAdd(hContact, wait); - LeaveCriticalSection(&cs); - } - } -} - -int FetchAvatarFor(HANDLE hContact, char *szProto = NULL) -{ - int result = GAIR_NOAVATAR; - - if (szProto == NULL) - szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - - if (szProto != NULL && PollProtocolCanHaveAvatar(szProto) && PollContactCanHaveAvatar(hContact, szProto)) - { - // Can have avatar, but must request it? - if ( - (g_AvatarHistoryAvail && CallService(MS_AVATARHISTORY_ENABLED, (WPARAM) hContact, 0)) - || (PollCheckProtocol(szProto) && PollCheckContact(hContact, szProto)) - ) - { - // Request it - PROTO_AVATAR_INFORMATIONT pai_s = {0}; - pai_s.cbSize = sizeof(pai_s); - pai_s.hContact = hContact; - //_DebugTrace(hContact, "schedule request"); - INT_PTR res = CallProtoService(szProto, PS_GETAVATARINFOT, GAIF_FORCE, (LPARAM)&pai_s); -#ifdef _UNICODE - if (res == CALLSERVICE_NOTFOUND) - { - PROTO_AVATAR_INFORMATION pai = {0}; - pai.cbSize = sizeof(pai); - pai.hContact = hContact; - res = CallProtoService(szProto, PS_GETAVATARINFO, GAIF_FORCE, (LPARAM)&pai); - MultiByteToWideChar( CP_ACP, 0, pai.filename, -1, pai_s.filename, SIZEOF(pai_s.filename)); - pai_s.format = pai.format; - } -#endif - if (res != CALLSERVICE_NOTFOUND) result = res; - ProcessAvatarInfo(pai_s.hContact, result, &pai_s, szProto); - } - } - - return result; -} - -static void RequestThread(void *vParam) -{ - while (!g_shutDown) - { - EnterCriticalSection(&cs); - - if ( queue.getCount() == 0 ) - { - // No items, so supend thread - LeaveCriticalSection(&cs); - - mir_sleep(POOL_DELAY); - } - else - { - // Take a look at first item - QueueItem& qi = queue[ queue.getCount()-1 ]; - - if (qi.check_time > GetTickCount()) - { - // Not time to request yet, wait... - LeaveCriticalSection(&cs); - mir_sleep(POOL_DELAY); - } - else - { - // Will request this item - HANDLE hContact = qi.hContact; - queue.remove( queue.getCount()-1 ); - - QueueRemove(hContact); - - LeaveCriticalSection(&cs); - - if (FetchAvatarFor(hContact) == GAIR_WAITFOR) - { - // Mark to not request this contact avatar for more 30 min - EnterCriticalSection(&cs); - QueueRemove(hContact); - QueueAdd(hContact, REQUEST_WAITFOR_WAIT_TIME); - LeaveCriticalSection(&cs); - - // Wait a little until requesting again - mir_sleep(REQUEST_DELAY); - } - } - } - } - - DeleteCriticalSection(&cs); - queue.destroy(); -} diff --git a/plugins/Avs/poll.h b/plugins/Avs/poll.h deleted file mode 100644 index 9761e7360a..0000000000 --- a/plugins/Avs/poll.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - - -#ifndef __POLL_H__ -# define __POLL_H__ - -struct QueueItem -{ - HANDLE hContact; - DWORD check_time; -}; - -void InitPolls(); -void FreePolls(); - -// Add an contact to a queue -void QueueAdd(HANDLE hContact); - -#endif // __POLL_H__ diff --git a/plugins/Avs/res/avatar.ico b/plugins/Avs/res/avatar.ico deleted file mode 100644 index 3525625479..0000000000 Binary files a/plugins/Avs/res/avatar.ico and /dev/null differ diff --git a/plugins/Avs/resource.h b/plugins/Avs/resource.h deleted file mode 100644 index 2d8ba9add0..0000000000 --- a/plugins/Avs/resource.h +++ /dev/null @@ -1,60 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by avs.rc -// -#define ID_USE_DEFAULTS 3 -#define IDD_OPTIONS 101 -#define IDD_OPTIONS_PICTS 101 -#define IDD_OPENSUBCLASS 102 -#define IDD_AVATAROPTIONS 103 -#define IDI_AVATAR 104 -#define IDD_SET_OWN_SUBCLASS 105 -#define IDD_DIALOG1 106 -#define IDD_USER_AVATAR 106 -#define IDD_PROTO_AVATARS 107 -#define IDD_OPTIONS_AVATARS 109 -#define IDD_OPTIONS_OWN 110 -#define IDC_PROTOCOLS 1001 -#define IDC_CLIST 1002 -#define IDC_SETPROTOPIC 1003 -#define IDC_PROTOPIC 1004 -#define IDC_REMOVEPROTOPIC 1005 -#define IDC_PROTOAVATARNAME 1006 -#define IDC_CHECK1 1007 -#define IDC_PROTECTAVATAR 1007 -#define IDC_SHOWWARNINGS 1007 -#define IDC_PER_PROTO 1007 -#define IDC_CHANGE 1008 -#define IDC_MAKE_TRANSPARENT_BKG 1008 -#define IDC_GROW 1008 -#define IDC_RESET 1009 -#define IDC_MAKE_GRAYSCALE 1009 -#define IDC_AVATARNAME 1010 -#define IDC_MAKE_GRAYSCALE2 1010 -#define IDC_SET_MAKE_SQUARE 1010 -#define IDC_HIDEAVATAR 1011 -#define IDC_DELETE 1012 -#define IDC_MAKETRANSPBKG 1013 -#define IDC_GUESS_LEVEL 1014 -#define IDC_BKG_NUM_POINTS 1014 -#define IDC_COMBO1 1015 -#define IDC_BKG_NUM_POINTS_SPIN 1015 -#define IDC_BKG_COLOR_DIFFERENCE 1016 -#define IDC_SIZELIMITSPIN3 1017 -#define IDC_BKG_COLOR_DIFFERENCE_SPIN 1017 -#define IDC_BKG_NUM_POINTS_L 1018 -#define IDC_BKG_COLOR_DIFFERENCE_L 1019 -#define IDC_MAKE_TRANSP_PROPORTIONAL 1020 -#define IDC_MAKE_MY_AVATARS_TRANSP 1021 -#define IDC_MAKE_SQUARE 1023 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 108 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1024 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/plugins/Avs/vc6.rc b/plugins/Avs/vc6.rc deleted file mode 100644 index 99a8f9da1d..0000000000 --- a/plugins/Avs/vc6.rc +++ /dev/null @@ -1,2 +0,0 @@ -#include "avs.rc" -#include "version.rc" diff --git a/plugins/Avs/version.h b/plugins/Avs/version.h deleted file mode 100644 index 826d9fdefb..0000000000 --- a/plugins/Avs/version.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "../../include/m_version.h" - -#define __FILEVERSION_STRING MIRANDA_VERSION_FILEVERSION -#define __VERSION_STRING MIRANDA_VERSION_STRING -#define __VERSION_DWORD MIRANDA_VERSION_DWORD diff --git a/plugins/Avs/version.rc b/plugins/Avs/version.rc deleted file mode 100644 index 43d374df60..0000000000 --- a/plugins/Avs/version.rc +++ /dev/null @@ -1,113 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" -#include "version.h" -#include "winres.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page( 1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "\r\n" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION __FILEVERSION_STRING - PRODUCTVERSION __FILEVERSION_STRING - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN -#if !defined(UNICODE) - VALUE "Comments", "Service plugin to load and update avatars for Miranda IM" - VALUE "CompanyName", "Written by Nightwish and Pescuma for Miranda IM project" - VALUE "FileDescription", "Service plugin to load and update avatars for Miranda IM" - VALUE "FileVersion", __FILEVERSION_STRING - VALUE "InternalName", "avs" - VALUE "LegalCopyright", "Copyright (C) 2010, Nightwish, Pescuma" - VALUE "LegalTrademarks", "Licensed under the Gnu General Public License V2 or any later version" - VALUE "OriginalFilename", "avs.dll" - VALUE "ProductName", "Miranda IM Avatar Service plugin" - VALUE "ProductVersion", __FILEVERSION_STRING -#else - VALUE "Comments", "Service plugin to load and update avatars for Miranda IM" - VALUE "CompanyName", "Written by Nightwish and Pescuma for Miranda IM project" - VALUE "FileDescription", "Service plugin to load and update avatars for Miranda IM" - VALUE "FileVersion", __FILEVERSION_STRING - VALUE "InternalName", "avsW" - VALUE "LegalCopyright", "Copyright (C) 2010, Nightwish, Pescuma" - VALUE "LegalTrademarks", "Licensed under the Gnu General Public License V2 or any later version" - VALUE "OriginalFilename", "avs.dll" - VALUE "ProductName", "Miranda IM Avatar Service (Unicode)" - VALUE "ProductVersion", __FILEVERSION_STRING -#endif - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - -#endif // AFX_RESOURCE_DLL diff --git a/plugins/BASS_interface/Bass.h b/plugins/BASS_interface/Bass.h new file mode 100644 index 0000000000..cf0a66cf2b --- /dev/null +++ b/plugins/BASS_interface/Bass.h @@ -0,0 +1,920 @@ +/* + BASS 2.4 C/C++ header file + Copyright (c) 1999-2010 Un4seen Developments Ltd. + + See the BASS.CHM file for more detailed documentation +*/ + +#ifndef BASS_H +#define BASS_H + +#ifdef _WIN32 +#include +typedef unsigned __int64 QWORD; +#else +#include +#define WINAPI +#define CALLBACK +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef uint64_t QWORD; +#ifndef __OBJC__ +typedef int BOOL; +#endif +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#define LOBYTE(a) (BYTE)(a) +#define HIBYTE(a) (BYTE)((a)>>8) +#define LOWORD(a) (WORD)(a) +#define HIWORD(a) (WORD)((a)>>16) +#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8)) +#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16)) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BASSVERSION 0x204 // API version +#define BASSVERSIONTEXT "2.4" + +#ifndef BASSDEF +#define BASSDEF(f) WINAPI f +#endif + +typedef DWORD HMUSIC; // MOD music handle +typedef DWORD HSAMPLE; // sample handle +typedef DWORD HCHANNEL; // playing sample's channel handle +typedef DWORD HSTREAM; // sample stream handle +typedef DWORD HRECORD; // recording handle +typedef DWORD HSYNC; // synchronizer handle +typedef DWORD HDSP; // DSP handle +typedef DWORD HFX; // DX8 effect handle +typedef DWORD HPLUGIN; // Plugin handle + +// Error codes returned by BASS_ErrorGetCode +#define BASS_OK 0 // all is OK +#define BASS_ERROR_MEM 1 // memory error +#define BASS_ERROR_FILEOPEN 2 // can't open the file +#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver +#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost +#define BASS_ERROR_HANDLE 5 // invalid handle +#define BASS_ERROR_FORMAT 6 // unsupported sample format +#define BASS_ERROR_POSITION 7 // invalid position +#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called +#define BASS_ERROR_START 9 // BASS_Start has not been successfully called +#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever +#define BASS_ERROR_NOCHAN 18 // can't get a free channel +#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified +#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified +#define BASS_ERROR_NO3D 21 // no 3D support +#define BASS_ERROR_NOEAX 22 // no EAX support +#define BASS_ERROR_DEVICE 23 // illegal device number +#define BASS_ERROR_NOPLAY 24 // not playing +#define BASS_ERROR_FREQ 25 // illegal sample rate +#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream +#define BASS_ERROR_NOHW 29 // no hardware voices available +#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data +#define BASS_ERROR_NONET 32 // no internet connection could be opened +#define BASS_ERROR_CREATE 33 // couldn't create the file +#define BASS_ERROR_NOFX 34 // effects are not available +#define BASS_ERROR_NOTAVAIL 37 // requested data is not available +#define BASS_ERROR_DECODE 38 // the channel is a "decoding channel" +#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed +#define BASS_ERROR_TIMEOUT 40 // connection timedout +#define BASS_ERROR_FILEFORM 41 // unsupported file format +#define BASS_ERROR_SPEAKER 42 // unavailable speaker +#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons) +#define BASS_ERROR_CODEC 44 // codec is not available/supported +#define BASS_ERROR_ENDED 45 // the channel/file has ended +#define BASS_ERROR_BUSY 46 // the device is busy +#define BASS_ERROR_UNKNOWN -1 // some other mystery problem + +// BASS_SetConfig options +#define BASS_CONFIG_BUFFER 0 +#define BASS_CONFIG_UPDATEPERIOD 1 +#define BASS_CONFIG_GVOL_SAMPLE 4 +#define BASS_CONFIG_GVOL_STREAM 5 +#define BASS_CONFIG_GVOL_MUSIC 6 +#define BASS_CONFIG_CURVE_VOL 7 +#define BASS_CONFIG_CURVE_PAN 8 +#define BASS_CONFIG_FLOATDSP 9 +#define BASS_CONFIG_3DALGORITHM 10 +#define BASS_CONFIG_NET_TIMEOUT 11 +#define BASS_CONFIG_NET_BUFFER 12 +#define BASS_CONFIG_PAUSE_NOPLAY 13 +#define BASS_CONFIG_NET_PREBUF 15 +#define BASS_CONFIG_NET_PASSIVE 18 +#define BASS_CONFIG_REC_BUFFER 19 +#define BASS_CONFIG_NET_PLAYLIST 21 +#define BASS_CONFIG_MUSIC_VIRTUAL 22 +#define BASS_CONFIG_VERIFY 23 +#define BASS_CONFIG_UPDATETHREADS 24 +#define BASS_CONFIG_DEV_BUFFER 27 +#define BASS_CONFIG_DEV_DEFAULT 36 +#define BASS_CONFIG_NET_READTIMEOUT 37 + +// BASS_SetConfigPtr options +#define BASS_CONFIG_NET_AGENT 16 +#define BASS_CONFIG_NET_PROXY 17 + +// Initialization flags +#define BASS_DEVICE_8BITS 1 // use 8 bit resolution, else 16 bit +#define BASS_DEVICE_MONO 2 // use mono, else stereo +#define BASS_DEVICE_3D 4 // enable 3D functionality +#define BASS_DEVICE_LATENCY 256 // calculate device latency (BASS_INFO struct) +#define BASS_DEVICE_CPSPEAKERS 1024 // detect speakers via Windows control panel +#define BASS_DEVICE_SPEAKERS 2048 // force enabling of speaker assignment +#define BASS_DEVICE_NOSPEAKER 4096 // ignore speaker arrangement +#ifdef __linux__ +#define BASS_DEVICE_DMIX 8192 // use ALSA "dmix" plugin +#endif + +// DirectSound interfaces (for use with BASS_GetDSoundObject) +#define BASS_OBJECT_DS 1 // IDirectSound +#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener + +// Device info structure +typedef struct { +#ifdef _WIN32_WCE + const wchar_t *name; // description + const wchar_t *driver; // driver +#else + const char *name; // description + const char *driver; // driver +#endif + DWORD flags; +} BASS_DEVICEINFO; + +// BASS_DEVICEINFO flags +#define BASS_DEVICE_ENABLED 1 +#define BASS_DEVICE_DEFAULT 2 +#define BASS_DEVICE_INIT 4 + +typedef struct { + DWORD flags; // device capabilities (DSCAPS_xxx flags) + DWORD hwsize; // size of total device hardware memory + DWORD hwfree; // size of free device hardware memory + DWORD freesam; // number of free sample slots in the hardware + DWORD free3d; // number of free 3D sample slots in the hardware + DWORD minrate; // min sample rate supported by the hardware + DWORD maxrate; // max sample rate supported by the hardware + BOOL eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used) + DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) + DWORD dsver; // DirectSound version + DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) + DWORD initflags;// BASS_Init "flags" parameter + DWORD speakers; // number of speakers available + DWORD freq; // current output rate (Vista/OSX only) +} BASS_INFO; + +// BASS_INFO flags (from DSOUND.H) +#define DSCAPS_CONTINUOUSRATE 0x00000010 // supports all sample rates between min/maxrate +#define DSCAPS_EMULDRIVER 0x00000020 // device does NOT have hardware DirectSound support +#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft +#define DSCAPS_SECONDARYMONO 0x00000100 // mono +#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo +#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit +#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit + +// Recording device info structure +typedef struct { + DWORD flags; // device capabilities (DSCCAPS_xxx flags) + DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) + DWORD inputs; // number of inputs + BOOL singlein; // TRUE = only 1 input can be set at a time + DWORD freq; // current input rate (Vista/OSX only) +} BASS_RECORDINFO; + +// BASS_RECORDINFO flags (from DSOUND.H) +#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording support +#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft + +// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H) +#ifndef WAVE_FORMAT_1M08 +#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ +#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ +#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ +#endif + +// Sample info structure +typedef struct { + DWORD freq; // default playback rate + float volume; // default volume (0-1) + float pan; // default pan (-1=left, 0=middle, 1=right) + DWORD flags; // BASS_SAMPLE_xxx flags + DWORD length; // length (in bytes) + DWORD max; // maximum simultaneous playbacks + DWORD origres; // original resolution bits + DWORD chans; // number of channels + DWORD mingap; // minimum gap (ms) between creating channels + DWORD mode3d; // BASS_3DMODE_xxx mode + float mindist; // minimum distance + float maxdist; // maximum distance + DWORD iangle; // angle of inside projection cone + DWORD oangle; // angle of outside projection cone + float outvol; // delta-volume outside the projection cone + DWORD vam; // voice allocation/management flags (BASS_VAM_xxx) + DWORD priority; // priority (0=lowest, 0xffffffff=highest) +} BASS_SAMPLE; + +#define BASS_SAMPLE_8BITS 1 // 8 bit +#define BASS_SAMPLE_FLOAT 256 // 32-bit floating-point +#define BASS_SAMPLE_MONO 2 // mono +#define BASS_SAMPLE_LOOP 4 // looped +#define BASS_SAMPLE_3D 8 // 3D functionality +#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing +#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only) +#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management +#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects +#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume +#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing +#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only) + +#define BASS_STREAM_PRESCAN 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1) +#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN +#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stop/ends +#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file streams +#define BASS_STREAM_BLOCK 0x100000 // download/play internet file stream in small blocks +#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode (BASS_ChannelGetData) +#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC + +#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT +#define BASS_MUSIC_MONO BASS_SAMPLE_MONO +#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP +#define BASS_MUSIC_3D BASS_SAMPLE_3D +#define BASS_MUSIC_FX BASS_SAMPLE_FX +#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE +#define BASS_MUSIC_DECODE BASS_STREAM_DECODE +#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length +#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN +#define BASS_MUSIC_RAMP 0x200 // normal ramping +#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping +#define BASS_MUSIC_SURROUND 0x800 // surround sound +#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2) +#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does +#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does +#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing +#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing +#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position +#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position +#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect +#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples + +// Speaker assignment flags +#define BASS_SPEAKER_FRONT 0x1000000 // front speakers +#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers +#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1) +#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1) +#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15) +#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left +#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right +#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT + +#define BASS_UNICODE 0x80000000 + +#define BASS_RECORD_PAUSE 0x8000 // start recording paused + +// DX7 voice allocation & management flags +#define BASS_VAM_HARDWARE 1 +#define BASS_VAM_SOFTWARE 2 +#define BASS_VAM_TERM_TIME 4 +#define BASS_VAM_TERM_DIST 8 +#define BASS_VAM_TERM_PRIO 16 + +// Channel info structure +typedef struct { + DWORD freq; // default playback rate + DWORD chans; // channels + DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags + DWORD ctype; // type of channel + DWORD origres; // original resolution + HPLUGIN plugin; // plugin + HSAMPLE sample; // sample + const char *filename; // filename +} BASS_CHANNELINFO; + +// BASS_CHANNELINFO types +#define BASS_CTYPE_SAMPLE 1 +#define BASS_CTYPE_RECORD 2 +#define BASS_CTYPE_STREAM 0x10000 +#define BASS_CTYPE_STREAM_OGG 0x10002 +#define BASS_CTYPE_STREAM_MP1 0x10003 +#define BASS_CTYPE_STREAM_MP2 0x10004 +#define BASS_CTYPE_STREAM_MP3 0x10005 +#define BASS_CTYPE_STREAM_AIFF 0x10006 +#define BASS_CTYPE_STREAM_CA 0x10007 +#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec +#define BASS_CTYPE_STREAM_WAV_PCM 0x50001 +#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 +#define BASS_CTYPE_MUSIC_MOD 0x20000 +#define BASS_CTYPE_MUSIC_MTM 0x20001 +#define BASS_CTYPE_MUSIC_S3M 0x20002 +#define BASS_CTYPE_MUSIC_XM 0x20003 +#define BASS_CTYPE_MUSIC_IT 0x20004 +#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag + +typedef struct { + DWORD ctype; // channel type +#ifdef _WIN32_WCE + const wchar_t *name; // format description + const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...) +#else + const char *name; // format description + const char *exts; // file extension filter (*.ext1;*.ext2;etc...) +#endif +} BASS_PLUGINFORM; + +typedef struct { + DWORD version; // version (same form as BASS_GetVersion) + DWORD formatc; // number of formats + const BASS_PLUGINFORM *formats; // the array of formats +} BASS_PLUGININFO; + +// 3D vector (for 3D positions/velocities/orientations) +typedef struct BASS_3DVECTOR { +#ifdef __cplusplus + BASS_3DVECTOR() {}; + BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; +#endif + float x; // +=right, -=left + float y; // +=up, -=down + float z; // +=front, -=behind +} BASS_3DVECTOR; + +// 3D channel modes +#define BASS_3DMODE_NORMAL 0 // normal 3D processing +#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener +#define BASS_3DMODE_OFF 2 // no 3D processing + +// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM) +#define BASS_3DALG_DEFAULT 0 +#define BASS_3DALG_OFF 1 +#define BASS_3DALG_FULL 2 +#define BASS_3DALG_LIGHT 3 + +// EAX environments, use with BASS_SetEAXParameters +enum +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + EAX_ENVIRONMENT_COUNT // total number of environments +}; + +// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx) +#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F +#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F +#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F +#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F +#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F +#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F +#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F +#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F +#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F +#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F +#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F +#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F +#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F +#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F +#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F +#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F +#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F +#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F +#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F +#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F +#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F +#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F +#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F +#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F +#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F +#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F + +typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user); +/* User stream callback function. NOTE: A stream function should obviously be as quick +as possible, other streams (and MOD musics) can't be mixed until it's finished. +handle : The stream that needs writing +buffer : Buffer to write the samples in +length : Number of bytes to write +user : The 'user' parameter value given when calling BASS_StreamCreate +RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end + the stream. */ + +#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag + +// special STREAMPROCs +#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream +#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream + +// BASS_StreamCreateFileUser file systems +#define STREAMFILE_NOBUFFER 0 +#define STREAMFILE_BUFFER 1 +#define STREAMFILE_BUFFERPUSH 2 + +// User file stream callback functions +typedef void (CALLBACK FILECLOSEPROC)(void *user); +typedef QWORD (CALLBACK FILELENPROC)(void *user); +typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user); +typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user); + +typedef struct { + FILECLOSEPROC *close; + FILELENPROC *length; + FILEREADPROC *read; + FILESEEKPROC *seek; +} BASS_FILEPROCS; + +// BASS_StreamPutFileData options +#define BASS_FILEDATA_END 0 // end & close the file + +// BASS_StreamGetFilePosition modes +#define BASS_FILEPOS_CURRENT 0 +#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT +#define BASS_FILEPOS_DOWNLOAD 1 +#define BASS_FILEPOS_END 2 +#define BASS_FILEPOS_START 3 +#define BASS_FILEPOS_CONNECTED 4 +#define BASS_FILEPOS_BUFFER 5 +#define BASS_FILEPOS_SOCKET 6 + +typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user); +/* Internet stream download callback function. +buffer : Buffer containing the downloaded data... NULL=end of download +length : Number of bytes in the buffer +user : The 'user' parameter value given when calling BASS_StreamCreateURL */ + +// BASS_ChannelSetSync types +#define BASS_SYNC_POS 0 +#define BASS_SYNC_END 2 +#define BASS_SYNC_META 4 +#define BASS_SYNC_SLIDE 5 +#define BASS_SYNC_STALL 6 +#define BASS_SYNC_DOWNLOAD 7 +#define BASS_SYNC_FREE 8 +#define BASS_SYNC_SETPOS 11 +#define BASS_SYNC_MUSICPOS 10 +#define BASS_SYNC_MUSICINST 1 +#define BASS_SYNC_MUSICFX 3 +#define BASS_SYNC_OGG_CHANGE 12 +#define BASS_SYNC_MIXTIME 0x40000000 // FLAG: sync at mixtime, else at playtime +#define BASS_SYNC_ONETIME 0x80000000 // FLAG: sync only once, else continuously + +typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user); +/* Sync callback function. NOTE: a sync callback function should be very +quick as other syncs can't be processed until it has finished. If the sync +is a "mixtime" sync, then other streams and MOD musics can't be mixed until +it's finished either. +handle : The sync that has occured +channel: Channel that the sync occured in +data : Additional data associated with the sync's occurance +user : The 'user' parameter given when calling BASS_ChannelSetSync */ + +typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user); +/* DSP callback function. NOTE: A DSP function should obviously be as quick as +possible... other DSP functions, streams and MOD musics can not be processed +until it's finished. +handle : The DSP handle +channel: Channel that the DSP is being applied to +buffer : Buffer to apply the DSP to +length : Number of bytes in the buffer +user : The 'user' parameter given when calling BASS_ChannelSetDSP */ + +typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user); +/* Recording callback function. +handle : The recording handle +buffer : Buffer containing the recorded sample data +length : Number of bytes +user : The 'user' parameter value given when calling BASS_RecordStart +RETURN : TRUE = continue recording, FALSE = stop */ + +// BASS_ChannelIsActive return values +#define BASS_ACTIVE_STOPPED 0 +#define BASS_ACTIVE_PLAYING 1 +#define BASS_ACTIVE_STALLED 2 +#define BASS_ACTIVE_PAUSED 3 + +// Channel attributes +#define BASS_ATTRIB_FREQ 1 +#define BASS_ATTRIB_VOL 2 +#define BASS_ATTRIB_PAN 3 +#define BASS_ATTRIB_EAXMIX 4 +#define BASS_ATTRIB_NOBUFFER 5 +#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 +#define BASS_ATTRIB_MUSIC_PANSEP 0x101 +#define BASS_ATTRIB_MUSIC_PSCALER 0x102 +#define BASS_ATTRIB_MUSIC_BPM 0x103 +#define BASS_ATTRIB_MUSIC_SPEED 0x104 +#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105 +#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel # +#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument # + +// BASS_ChannelGetData flags +#define BASS_DATA_AVAILABLE 0 // query how much data is buffered +#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data +#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT +#define BASS_DATA_FFT512 0x80000001 // 512 FFT +#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT +#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT +#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT +#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT +#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT +#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined +#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window +#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias + +// BASS_ChannelGetTags types : what's returned +#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure +#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block +#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings +#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings +#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings +#define BASS_TAG_META 5 // ICY metadata : ANSI string +#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings +#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string +#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string +#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure +#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings +#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure +#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure +#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string +#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure +#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string +#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string +#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers +#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string +#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string + +// ID3v1 tag structure +typedef struct { + char id[3]; + char title[30]; + char artist[30]; + char album[30]; + char year[4]; + char comment[30]; + BYTE genre; +} TAG_ID3; + +// Binary APE tag structure +typedef struct { + const char *key; + const void *data; + DWORD length; +} TAG_APE_BINARY; + +// BWF "bext" tag structure +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) +#endif +#pragma pack(push,1) +typedef struct { + char Description[256]; // description + char Originator[32]; // name of the originator + char OriginatorReference[32]; // reference of the originator + char OriginationDate[10]; // date of creation (yyyy-mm-dd) + char OriginationTime[8]; // time of creation (hh-mm-ss) + QWORD TimeReference; // first sample count since midnight (little-endian) + WORD Version; // BWF version (little-endian) + BYTE UMID[64]; // SMPTE UMID + BYTE Reserved[190]; +#if defined(__GNUC__) && __GNUC__<3 + char CodingHistory[0]; // history +#elif 1 // change to 0 if compiler fails the following line + char CodingHistory[]; // history +#else + char CodingHistory[1]; // history +#endif +} TAG_BEXT; +#pragma pack(pop) +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// BWF "cart" tag structures +typedef struct +{ + DWORD dwUsage; // FOURCC timer usage ID + DWORD dwValue; // timer value in samples from head +} TAG_CART_TIMER; + +typedef struct +{ + char Version[4]; // version of the data structure + char Title[64]; // title of cart audio sequence + char Artist[64]; // artist or creator name + char CutID[64]; // cut number identification + char ClientID[64]; // client identification + char Category[64]; // category ID, PSA, NEWS, etc + char Classification[64]; // classification or auxiliary key + char OutCue[64]; // out cue text + char StartDate[10]; // yyyy-mm-dd + char StartTime[8]; // hh:mm:ss + char EndDate[10]; // yyyy-mm-dd + char EndTime[8]; // hh:mm:ss + char ProducerAppID[64]; // name of vendor or application + char ProducerAppVersion[64]; // version of producer application + char UserDef[64]; // user defined text + DWORD dwLevelReference; // sample value for 0 dB reference + TAG_CART_TIMER PostTimer[8]; // 8 time markers after head + char Reserved[276]; + char URL[1024]; // uniform resource locator +#if defined(__GNUC__) && __GNUC__<3 + char TagText[0]; // free form text for scripts or tags +#elif 1 // change to 0 if compiler fails the following line + char TagText[]; // free form text for scripts or tags +#else + char TagText[1]; // free form text for scripts or tags +#endif +} TAG_CART; + +// CoreAudio codec info structure +typedef struct { + DWORD ftype; // file format + DWORD atype; // audio format + const char *name; // description +} TAG_CA_CODEC; + +// BASS_ChannelGetLength/GetPosition/SetPosition modes +#define BASS_POS_BYTE 0 // byte position +#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) +#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position +#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking + +// BASS_RecordSetInput flags +#define BASS_INPUT_OFF 0x10000 +#define BASS_INPUT_ON 0x20000 + +#define BASS_INPUT_TYPE_MASK 0xff000000 +#define BASS_INPUT_TYPE_UNDEF 0x00000000 +#define BASS_INPUT_TYPE_DIGITAL 0x01000000 +#define BASS_INPUT_TYPE_LINE 0x02000000 +#define BASS_INPUT_TYPE_MIC 0x03000000 +#define BASS_INPUT_TYPE_SYNTH 0x04000000 +#define BASS_INPUT_TYPE_CD 0x05000000 +#define BASS_INPUT_TYPE_PHONE 0x06000000 +#define BASS_INPUT_TYPE_SPEAKER 0x07000000 +#define BASS_INPUT_TYPE_WAVE 0x08000000 +#define BASS_INPUT_TYPE_AUX 0x09000000 +#define BASS_INPUT_TYPE_ANALOG 0x0a000000 + +// DX8 effect types, use with BASS_ChannelSetFX +enum +{ + BASS_FX_DX8_CHORUS, + BASS_FX_DX8_COMPRESSOR, + BASS_FX_DX8_DISTORTION, + BASS_FX_DX8_ECHO, + BASS_FX_DX8_FLANGER, + BASS_FX_DX8_GARGLE, + BASS_FX_DX8_I3DL2REVERB, + BASS_FX_DX8_PARAMEQ, + BASS_FX_DX8_REVERB +}; + +typedef struct { + float fWetDryMix; + float fDepth; + float fFeedback; + float fFrequency; + DWORD lWaveform; // 0=triangle, 1=sine + float fDelay; + DWORD lPhase; // BASS_DX8_PHASE_xxx +} BASS_DX8_CHORUS; + +typedef struct { + float fGain; + float fAttack; + float fRelease; + float fThreshold; + float fRatio; + float fPredelay; +} BASS_DX8_COMPRESSOR; + +typedef struct { + float fGain; + float fEdge; + float fPostEQCenterFrequency; + float fPostEQBandwidth; + float fPreLowpassCutoff; +} BASS_DX8_DISTORTION; + +typedef struct { + float fWetDryMix; + float fFeedback; + float fLeftDelay; + float fRightDelay; + BOOL lPanDelay; +} BASS_DX8_ECHO; + +typedef struct { + float fWetDryMix; + float fDepth; + float fFeedback; + float fFrequency; + DWORD lWaveform; // 0=triangle, 1=sine + float fDelay; + DWORD lPhase; // BASS_DX8_PHASE_xxx +} BASS_DX8_FLANGER; + +typedef struct { + DWORD dwRateHz; // Rate of modulation in hz + DWORD dwWaveShape; // 0=triangle, 1=square +} BASS_DX8_GARGLE; + +typedef struct { + int lRoom; // [-10000, 0] default: -1000 mB + int lRoomHF; // [-10000, 0] default: 0 mB + float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 + float flDecayTime; // [0.1, 20.0] default: 1.49s + float flDecayHFRatio; // [0.1, 2.0] default: 0.83 + int lReflections; // [-10000, 1000] default: -2602 mB + float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s + int lReverb; // [-10000, 2000] default: 200 mB + float flReverbDelay; // [0.0, 0.1] default: 0.011 s + float flDiffusion; // [0.0, 100.0] default: 100.0 % + float flDensity; // [0.0, 100.0] default: 100.0 % + float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz +} BASS_DX8_I3DL2REVERB; + +typedef struct { + float fCenter; + float fBandwidth; + float fGain; +} BASS_DX8_PARAMEQ; + +typedef struct { + float fInGain; // [-96.0,0.0] default: 0.0 dB + float fReverbMix; // [-96.0,0.0] default: 0.0 db + float fReverbTime; // [0.001,3000.0] default: 1000.0 ms + float fHighFreqRTRatio; // [0.001,0.999] default: 0.001 +} BASS_DX8_REVERB; + +#define BASS_DX8_PHASE_NEG_180 0 +#define BASS_DX8_PHASE_NEG_90 1 +#define BASS_DX8_PHASE_ZERO 2 +#define BASS_DX8_PHASE_90 3 +#define BASS_DX8_PHASE_180 4 + +BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); +DWORD BASSDEF(BASS_GetConfig)(DWORD option); +BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, void *value); +void *BASSDEF(BASS_GetConfigPtr)(DWORD option); +DWORD BASSDEF(BASS_GetVersion)(); +int BASSDEF(BASS_ErrorGetCode)(); +BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); +#if defined(_WIN32) && !defined(_WIN32_WCE) +BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); +#else +BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, void *dsguid); +#endif +BOOL BASSDEF(BASS_SetDevice)(DWORD device); +DWORD BASSDEF(BASS_GetDevice)(); +BOOL BASSDEF(BASS_Free)(); +#if defined(_WIN32) && !defined(_WIN32_WCE) +void *BASSDEF(BASS_GetDSoundObject)(DWORD object); +#endif +BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info); +BOOL BASSDEF(BASS_Update)(DWORD length); +float BASSDEF(BASS_GetCPU)(); +BOOL BASSDEF(BASS_Start)(); +BOOL BASSDEF(BASS_Stop)(); +BOOL BASSDEF(BASS_Pause)(); +BOOL BASSDEF(BASS_SetVolume)(float volume); +float BASSDEF(BASS_GetVolume)(); + +HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags); +BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle); +const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle); + +BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf); +BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf); +BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top); +BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top); +void BASSDEF(BASS_Apply3D)(); +#if defined(_WIN32) && !defined(_WIN32_WCE) +BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay, float damp); +BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay, float *damp); +#endif + +HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq); +BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle); + +HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags); +HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags); +BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle); +BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer); +BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer); +BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info); +BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info); +HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew); +DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels); +BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle); + +HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user); +HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); +HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); +HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user); +BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle); +QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode); +DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length); +DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length); + +BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); +BOOL BASSDEF(BASS_RecordInit)(int device); +BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device); +DWORD BASSDEF(BASS_RecordGetDevice)(); +BOOL BASSDEF(BASS_RecordFree)(); +BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info); +const char *BASSDEF(BASS_RecordGetInputName)(int input); +BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume); +DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume); +HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user); + +double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos); +QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos); +DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle); +BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device); +DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle); +BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info); +const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags); +DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask); +BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length); +BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock); +BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart); +BOOL BASSDEF(BASS_ChannelStop)(DWORD handle); +BOOL BASSDEF(BASS_ChannelPause)(DWORD handle); +BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value); +BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value); +BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time); +BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib); +BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol); +BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol); +BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel); +BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel); +QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode); +BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode); +QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode); +DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle); +DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length); +HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user); +BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync); +HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority); +BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp); +BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan); +BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan); +HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority); +BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx); + +BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params); +BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params); +BOOL BASSDEF(BASS_FXReset)(HFX handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/BASS_interface/Bass.rc b/plugins/BASS_interface/Bass.rc new file mode 100644 index 0000000000..31ca4098d3 --- /dev/null +++ b/plugins/BASS_interface/Bass.rc @@ -0,0 +1,109 @@ +// Microsoft Visual C++ generated resource script. +// +#include +#include +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Ðóññêèé (Ðîññèÿ) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_BASSSoundOnOffUp ICON "res/BASSSoundOnOffUp.ico" +IDI_BASSSoundOnOffDown ICON "res/BASSSoundOnOffDown.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPTIONS DIALOGEX 0, 0, 313, 240 +STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 1 +BEGIN + GROUPBOX "un4seen's bass interface", IDC_STATIC, 5, 5, 302, 231 + LTEXT "bass.dll loading error", IDC_BASSVERSION, 20, 20, 210, 8, SS_LEFT + LTEXT "Current bass.dll path:", IDC_CURRPATHLABEL, 20, 45, 210, 8, SS_LEFT + LTEXT "", IDC_CURRPATH, 20, 60, 210, 8, SS_LEFT | SS_PATHELLIPSIS + LTEXT "Maximum number of bass internal channels:", IDC_MAXCHANNELLABEL, 20, 85, 210, 8, SS_LEFT + COMBOBOX IDC_MAXCHANNEL, 20, 100, 48, 14, CBS_DROPDOWNLIST | CBS_HASSTRINGS + LTEXT "Output device:", IDC_OUTDEVICELABEL, 20, 125, 240, 8, SS_LEFT + COMBOBOX IDC_OUTDEVICE, 20, 140, 236, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS + LTEXT "Volume:", IDC_VOLUMELABEL, 20, 165, 165, 8, SS_LEFT + CONTROL "", IDC_VOLUME, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 20, 180, 273, 10 + AUTOCHECKBOX "Quiet time:", IDC_QUIETTIME, 20, 205, 55, 10 + CONTROL "", IDC_TIME1, DATETIMEPICK_CLASS, WS_TABSTOP | WS_DISABLED | DTS_TIMEFORMAT | DTS_UPDOWN | DTS_RIGHTALIGN, 79, 202, 35, 15 + CONTROL "", IDC_TIME2, DATETIMEPICK_CLASS, WS_TABSTOP | WS_DISABLED | DTS_TIMEFORMAT | DTS_UPDOWN | DTS_RIGHTALIGN, 135, 202, 35, 15 + CTEXT "-", IDC_STATIC, 117, 205, 15, 8, SS_CENTER + CONTROL "download bass library", IDC_GETBASS, "Hyperlink", 0x50010002, 74, 222, 228, 10 + GROUPBOX "Play only if", IDC_STATIC, 235, 5, 72, 117 + AUTOCHECKBOX "Offline", IDC_CHECKBOX1, 240, 20, 65, 8 + AUTOCHECKBOX "Online", IDC_CHECKBOX2, 240, 30, 65, 8 + AUTOCHECKBOX "Away", IDC_CHECKBOX3, 240, 40, 65, 8 + AUTOCHECKBOX "NA", IDC_CHECKBOX4, 240, 50, 65, 8 + AUTOCHECKBOX "Occupied", IDC_CHECKBOX5, 240, 60, 65, 8 + AUTOCHECKBOX "DND", IDC_CHECKBOX6, 240, 70, 65, 8 + AUTOCHECKBOX "Free for chat", IDC_CHECKBOX7, 240, 80, 65, 8 + AUTOCHECKBOX "Invisible", IDC_CHECKBOX8, 240, 90, 65, 8 + AUTOCHECKBOX "On the phone", IDC_CHECKBOX9, 240, 100, 65, 8 + AUTOCHECKBOX "Out to lunch", IDC_CHECKBOX10, 240, 110, 65, 8 + AUTOCHECKBOX "Preview", IDC_PREVIEW, 200, 165, 90, 8, BS_RIGHT, WS_EX_RIGHT +END + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Ðóññêèé (Ðîññèÿ) resources +///////////////////////////////////////////////////////////////////////////// + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED \ No newline at end of file diff --git a/plugins/BASS_interface/Bass_interface.h b/plugins/BASS_interface/Bass_interface.h new file mode 100644 index 0000000000..e42e85127b --- /dev/null +++ b/plugins/BASS_interface/Bass_interface.h @@ -0,0 +1,46 @@ +/* +Copyright (C) 2010, 2011 tico-tico +*/ + +#ifndef __BASS_INTERFACE_H__ +#define __BASS_INTERFACE_H__ + +#define MIRANDA_VER 0x0A00 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m_toolbar.h" + +#include "resource.h" +#include "version.h" + +#define BASSDEF(f) (WINAPI *f) +#include "bass.h" + +#define LOADBASSFUNCTION(f) (*((void**)&f)=(void*)GetProcAddress(hBass,#f)) + +#define MIID_BASSINT {0x2f07ea05, 0x05b5, 0x4ff0, { 0x87, 0x5d, 0xc5, 0x90, 0xda, 0x2d, 0xda, 0xc1 }} //2f07ea05-05b5-4ff0-875d-c590da2ddac1 + +#define ModuleName "Bass Interface" + +#define OPT_VOLUME "Volume" +#define OPT_BASSPATH "PathToDll" +#define OPT_MAXCHAN "MaxChannels" +#define OPT_OUTDEVICE "OutDevice" +#define OPT_QUIETTIME "QuietTime" +#define OPT_TIME1 "Time1" +#define OPT_TIME2 "Time2" +#define OPT_STATUS "StatMask" +#define OPT_PREVIEW "Preview" +#define OPT_DEVOPEN "DevOpen" + +#endif diff --git a/plugins/BASS_interface/Bass_interface.sln b/plugins/BASS_interface/Bass_interface.sln new file mode 100644 index 0000000000..5be096af29 --- /dev/null +++ b/plugins/BASS_interface/Bass_interface.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bass_interface", "Bass_interface.vcxproj", "{3933E789-D185-41DC-8169-9FF4365B6015}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|Win32.ActiveCfg = Debug|Win32 + {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|Win32.Build.0 = Debug|Win32 + {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|x64.ActiveCfg = Debug|x64 + {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|x64.Build.0 = Debug|x64 + {3933E789-D185-41DC-8169-9FF4365B6015}.Release|Win32.ActiveCfg = Release|Win32 + {3933E789-D185-41DC-8169-9FF4365B6015}.Release|Win32.Build.0 = Release|Win32 + {3933E789-D185-41DC-8169-9FF4365B6015}.Release|x64.ActiveCfg = Release|x64 + {3933E789-D185-41DC-8169-9FF4365B6015}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/plugins/BASS_interface/Bass_interface.vcxproj b/plugins/BASS_interface/Bass_interface.vcxproj new file mode 100644 index 0000000000..d793eb6d65 --- /dev/null +++ b/plugins/BASS_interface/Bass_interface.vcxproj @@ -0,0 +1,203 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {3933E789-D185-41DC-8169-9FF4365B6015} + bass_interface + Win32Proj + BASS_interface + + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + true + + + DynamicLibrary + Unicode + + + DynamicLibrary + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + $(SolutionDir)$(Configuration)/Plugins\ + $(SolutionDir)$(Configuration)64/Plugins\ + $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ + $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + true + true + true + true + + + + Disabled + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + Level3 + EditAndContinue + 4996;%(DisableSpecificWarnings) + + + true + Windows + $(IntDir)$(TargetName).lib + + + ../../include/msapi + + + + + Disabled + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;_DEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Level3 + 4996;%(DisableSpecificWarnings) + + + true + Windows + $(IntDir)$(TargetName).lib + + + ../../include/msapi + + + + + Full + OnlyExplicitInline + false + Size + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + Fast + Level3 + 4996;%(DisableSpecificWarnings) + + + Windows + true + true + $(IntDir)$(TargetName).lib + true + + + ../../include/msapi + + + + + Full + OnlyExplicitInline + false + Size + ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) + WIN64;NDEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + Fast + Level3 + 4996;%(DisableSpecificWarnings) + + + Windows + true + true + $(IntDir)$(TargetName).lib + true + + + ../../include/msapi + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/BASS_interface/Bass_interface.vcxproj.filters b/plugins/BASS_interface/Bass_interface.vcxproj.filters new file mode 100644 index 0000000000..025a1f421b --- /dev/null +++ b/plugins/BASS_interface/Bass_interface.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + Resource Files + + + + + Source Files + + + \ No newline at end of file diff --git a/plugins/BASS_interface/Main.cpp b/plugins/BASS_interface/Main.cpp new file mode 100644 index 0000000000..3c9d5108a5 --- /dev/null +++ b/plugins/BASS_interface/Main.cpp @@ -0,0 +1,513 @@ +/* +Copyright (C) 2010, 2011 tico-tico +*/ + +#include "bass_interface.h" + +HINSTANCE hInst; +PLUGINLINK *pluginLink; +int hLangpack; + +PLUGININFOEX pluginInfo={ + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + 0, + MIID_BASSINT +}; + +struct MM_INTERFACE mmi; + +static HANDLE hHooks[5] = {0}; +static HANDLE hService; +static HINSTANCE hBass = NULL; + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +static const MUUID interfaces[] = {MIID_BASSINT, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +#define MAXCHAN 5 +static TCHAR CurrBassPath[MAX_PATH], tmp[MAX_PATH]; +static int sndNSnd = 0, sndLimSnd; +static HSTREAM sndSSnd[MAXCHAN] = {0}; + +static WORD TimeWrd1, TimeWrd2, StatMask; +static BOOL QuietTime, Preview, EnPreview; +static int Volume; +static int device = -1; +static int newBass = 0; +static HWND ClistHWND; + +static int OnPlaySnd(WPARAM wParam, LPARAM lParam) +{ + char * pszFile = (char *) lParam; SYSTEMTIME systime; WORD currtime, currstat; BOOL doPlay = TRUE; + + GetLocalTime(&systime); + currtime = MAKEWORD(systime.wMinute, systime.wHour); + + currstat = 1; + switch (CallService(MS_CLIST_GETSTATUSMODE, 0, 0)) + { + case ID_STATUS_OUTTOLUNCH: currstat <<= 1; + case ID_STATUS_ONTHEPHONE: currstat <<= 1; + case ID_STATUS_INVISIBLE: currstat <<= 1; + case ID_STATUS_FREECHAT: currstat <<= 1; + case ID_STATUS_DND: currstat <<= 1; + case ID_STATUS_OCCUPIED: currstat <<= 1; + case ID_STATUS_NA: currstat <<= 1; + case ID_STATUS_AWAY: currstat <<= 1; + case ID_STATUS_ONLINE: currstat <<= 1; + } + + if ( !DBGetContactSettingByte(NULL,"Skin","UseSound",0) ) doPlay = FALSE; + + if ( QuietTime ) + if ( + ((TimeWrd1 < TimeWrd2) && (TimeWrd1 <= currtime && currtime < TimeWrd2)) || + ((TimeWrd2 < TimeWrd1) && (TimeWrd1 <= currtime || currtime < TimeWrd2)) + ) doPlay = FALSE; + + if ( !(currstat & StatMask) ) doPlay = FALSE; + + if ( Preview || (int)wParam==1 ) doPlay = TRUE; + + if ( !pszFile ) doPlay = FALSE; + + if ( doPlay ) + { + BASS_StreamFree(sndSSnd[sndNSnd]); + sndSSnd[sndNSnd] = BASS_StreamCreateFile(FALSE, pszFile, 0, 0, BASS_STREAM_AUTOFREE); + BASS_ChannelPlay(sndSSnd[sndNSnd], FALSE); + sndNSnd = (sndNSnd+1)%sndLimSnd; + } + + Preview = FALSE; + + return 0; +} + +#define SLIDER_MIN 0 +#define SLIDER_MAX 100 + +INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + int i; SYSTEMTIME systime = {0}; + + TranslateDialogDefault(hwndDlg); + + SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_RESETCONTENT, 0, 0); + for(i=1; i<=MAXCHAN; i++) + SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_ADDSTRING, 0, (LPARAM)_itot(i, tmp, 10)); + + SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_SETCURSEL, sndLimSnd - 1, 0); + + SendDlgItemMessage(hwndDlg, IDC_CURRPATH, WM_SETTEXT, 0, (LPARAM)CurrBassPath); + + SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_SETRANGE, FALSE, MAKELONG(SLIDER_MIN,SLIDER_MAX)); + SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_SETPOS, TRUE, Volume); + SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_SETPAGESIZE, 0, 5); + + systime.wHour = HIBYTE(TimeWrd1); + systime.wMinute = LOBYTE(TimeWrd1); + systime.wYear = 2000; + systime.wMonth = 1; + systime.wDay = 1; + SendDlgItemMessage(hwndDlg, IDC_TIME1, DTM_SETFORMAT, 0, (LPARAM)_T("HH:mm")); + SendDlgItemMessage(hwndDlg, IDC_TIME1, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&systime); + systime.wHour = HIBYTE(TimeWrd2); + systime.wMinute = LOBYTE(TimeWrd2); + SendDlgItemMessage(hwndDlg, IDC_TIME2, DTM_SETFORMAT, 0, (LPARAM)_T("HH:mm")); + SendDlgItemMessage(hwndDlg, IDC_TIME2, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&systime); + + CheckDlgButton(hwndDlg, IDC_PREVIEW, EnPreview ? BST_CHECKED : BST_UNCHECKED); + + for(i = IDC_CHECKBOX1; i < IDC_CHECKBOX10+1; i++) + { + if (StatMask & (1 << (i-IDC_CHECKBOX1))) + CheckDlgButton(hwndDlg, i, BST_CHECKED); + } + + if (QuietTime) + { + EnableWindow(GetDlgItem(hwndDlg,IDC_TIME1), TRUE); + EnableWindow(GetDlgItem(hwndDlg,IDC_TIME2), TRUE); + CheckDlgButton(hwndDlg, IDC_QUIETTIME, BST_CHECKED); + } + if (hBass == NULL) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_VOLUME), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_MAXCHANNEL), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_OUTDEVICE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_QUIETTIME), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), FALSE); + + for(i = IDC_CHECKBOX1; i < IDC_CHECKBOX10+1; i++) + { + EnableWindow(GetDlgItem(hwndDlg, i), FALSE); + } + } + else + { + DBVARIANT dbv = {0}; BASS_DEVICEINFO info; DWORD bassver = BASS_GetVersion(); + + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("un4seen's bass version: %d.%d.%d.%d"), bassver >> 24, (bassver >> 16) & 0xff, (bassver >> 8) & 0xff, bassver & 0xff); + SendDlgItemMessage(hwndDlg, IDC_BASSVERSION, WM_SETTEXT, 0, (LPARAM)tmp); + + SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_RESETCONTENT, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_ADDSTRING, 0, (LPARAM)TranslateT("--default device--")); + SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_SETCURSEL, 0, 0); + DBGetContactSettingString(NULL, ModuleName, OPT_OUTDEVICE, &dbv); + for (i=1; BASS_GetDeviceInfo(i+newBass, &info); i++) + { + SendDlgItemMessageA(hwndDlg, IDC_OUTDEVICE, CB_ADDSTRING, 0, (LPARAM)info.name); + if (!lstrcmpA(dbv.pszVal, info.name)) + SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_SETCURSEL, i, 0); + } + DBFreeVariant(&dbv); + } + + return 1; + } + + case WM_HSCROLL: + if (hBass != NULL) + if (LOWORD(wParam) == SB_ENDSCROLL || LOWORD(wParam) == SB_THUMBTRACK) + { + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_GETPOS, 0, 0) * 100); + Preview = TRUE; + if (EnPreview) SkinPlaySound("AlertMsg"); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + if (hBass != NULL) + { + int i; SYSTEMTIME systime; + + SendDlgItemMessageA(hwndDlg, IDC_OUTDEVICE, WM_GETTEXT, sizeof(tmp), (LPARAM)tmp); + DBWriteContactSettingString(NULL, ModuleName, OPT_OUTDEVICE, (char *)tmp); + + Volume = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_GETPOS, 0, 0); + DBWriteContactSettingByte(NULL, ModuleName, OPT_VOLUME, Volume); + + sndLimSnd = SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_GETCURSEL, 0, 0) + 1; + if ( sndLimSnd > MAXCHAN ) sndLimSnd = MAXCHAN; + DBWriteContactSettingByte(NULL, ModuleName, OPT_MAXCHAN, sndLimSnd); + + QuietTime = IsDlgButtonChecked(hwndDlg, IDC_QUIETTIME) == BST_CHECKED; + DBWriteContactSettingByte(NULL, ModuleName, OPT_QUIETTIME, QuietTime); + + SendDlgItemMessage(hwndDlg, IDC_TIME1, DTM_GETSYSTEMTIME, 0, (LPARAM)&systime); + TimeWrd1 = MAKEWORD(systime.wMinute, systime.wHour); + DBWriteContactSettingWord(NULL, ModuleName, OPT_TIME1, TimeWrd1); + + SendDlgItemMessage(hwndDlg, IDC_TIME2, DTM_GETSYSTEMTIME, 0, (LPARAM)&systime); + TimeWrd2 = MAKEWORD(systime.wMinute, systime.wHour); + DBWriteContactSettingWord(NULL, ModuleName, OPT_TIME2, TimeWrd2); + + EnPreview = IsDlgButtonChecked(hwndDlg, IDC_PREVIEW) == BST_CHECKED; + DBWriteContactSettingByte(NULL, ModuleName, OPT_PREVIEW, EnPreview); + + StatMask = 0; + for(i = IDC_CHECKBOX10; i > IDC_CHECKBOX1-1; i--) + { + StatMask <<= 1; + if(IsDlgButtonChecked(hwndDlg, i) == BST_CHECKED) + StatMask |= 1; + } + + DBWriteContactSettingWord(NULL, ModuleName, OPT_STATUS, StatMask); + + device = SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_GETCURSEL, 0, 0); + if (device == 0) device = -1; + else device += newBass; + if (CallService(MS_TB_GETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", 0)==TBST_RELEASED) + { + BASS_Free(); + BASS_Init(device, 44100, 0, ClistHWND, NULL); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100 ); + } + } + return 1; + + case PSN_RESET: + if (hBass != NULL) + { + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100); + } + return 1; + + case DTN_DATETIMECHANGE: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + return 1; + } + break; + + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_QUIETTIME: + { + BOOL b = IsDlgButtonChecked(hwndDlg, IDC_QUIETTIME) == BST_CHECKED; + EnableWindow(GetDlgItem(hwndDlg,IDC_TIME1), b); + EnableWindow(GetDlgItem(hwndDlg,IDC_TIME2), b); + } + case IDC_MAXCHANNEL: + case IDC_OUTDEVICE: + case IDC_CHECKBOX1: + case IDC_CHECKBOX2: + case IDC_CHECKBOX3: + case IDC_CHECKBOX4: + case IDC_CHECKBOX5: + case IDC_CHECKBOX6: + case IDC_CHECKBOX7: + case IDC_CHECKBOX8: + case IDC_CHECKBOX9: + case IDC_CHECKBOX10: + case IDC_PREVIEW: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_GETBASS: + CallService(MS_UTILS_OPENURL , 1, (LPARAM)"http://www.un4seen.com/"); + break; + } + break; + + //case WM_CLOSE: + // EndDialog(hwndDlg, 0); + } + return 0; +} + +struct +{ + char* szDescr; + char* szName; + int defIconID; +} +static const iconList[] = +{ + { "Audio device is opened", "BASSSoundOnOffUp", IDI_BASSSoundOnOffUp }, + { "Audio device is closed", "BASSSoundOnOffDown", IDI_BASSSoundOnOffDown } +}; + +static HANDLE hIconLibItem[SIZEOF(iconList)]; + +void InitIcons(void) +{ + int i; char szSettingName[100]; SKINICONDESC sid = {0}; TCHAR szFile[MAX_PATH]; + + GetModuleFileName(hInst, szFile, SIZEOF(szFile)); + + sid.cbSize = sizeof(SKINICONDESC); + sid.ptszDefaultFile = szFile; + sid.cx = sid.cy = 16; + sid.pszName = szSettingName; + sid.pszSection = ModuleName; + sid.flags = SIDF_PATH_TCHAR; + + for (i = 0; i < SIZEOF(iconList); i++) + { + mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", ModuleName, iconList[i].szName); + + sid.pszDescription = (char*)iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + hIconLibItem[i] = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); + } +} + +int OptionsInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = {0}; + + odp.cbSize = sizeof(odp); + odp.position = 0; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.ptszTitle = _T(ModuleName); + odp.pfnDlgProc = OptionsProc; + odp.ptszGroup = _T("Customize"); + odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR; + + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + return 0; +} + +INT_PTR BASSSoundOnOff(WPARAM wParam, LPARAM lParam) +{ + if (hBass != NULL) + { + BOOL opened = CallService(MS_TB_GETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", 0) == TBST_RELEASED; + + if ( opened ) + { + BASS_Free(); // Close Device + } + else + { + BASS_Init(device, 44100, 0, ClistHWND, NULL); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100 ); + } + + CallService(MS_TB_SETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", opened ? TBST_PUSHED : TBST_RELEASED); + DBWriteContactSettingByte(NULL, ModuleName, OPT_DEVOPEN, !opened); + } + return 0; +} + +int OnToolbarLoaded(WPARAM wParam, LPARAM lParam) +{ + TBButton tbb = {0}; + tbb.cbSize = sizeof(TBButton); + tbb.pszButtonID = "BASSSoundOnOff"; + tbb.pszButtonName = Translate("Open/close audio device"); + tbb.pszServiceName = "BASSinterface/BASSSoundOnOff"; + tbb.pszTooltipUp = Translate("Audio device is opened"); + tbb.pszTooltipDn = Translate("Audio device is closed"); + tbb.hPrimaryIconHandle = hIconLibItem[0]; + tbb.hSecondaryIconHandle = hIconLibItem[1]; + tbb.tbbFlags = TBBF_SHOWTOOLTIP; + tbb.defPos = 1000; + + CallService(MS_TB_ADDBUTTON, 0, (LPARAM)&tbb); + + return 0; +} + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + DBVARIANT dbv = {0}; + + if (DBGetContactSettingTString(NULL, ModuleName, OPT_BASSPATH, &dbv)) + { + DBWriteContactSettingTString(NULL, ModuleName, OPT_BASSPATH, _T("Plugins\\Bass\\Bass.dll")); + lstrcpy(tmp, _T("Plugins\\Bass\\Bass.dll")); + } + else + { + lstrcpy(tmp, dbv.ptszVal); + } + + DBFreeVariant(&dbv); + + CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)tmp, (LPARAM)CurrBassPath); + hBass = LoadLibrary(CurrBassPath); + + if (hBass != NULL) + { + if (LOADBASSFUNCTION(BASS_Init) != NULL && LOADBASSFUNCTION(BASS_SetConfig) != NULL && + LOADBASSFUNCTION(BASS_ChannelPlay) != NULL && LOADBASSFUNCTION(BASS_StreamCreateFile) != NULL && + LOADBASSFUNCTION(BASS_GetVersion) != NULL && LOADBASSFUNCTION(BASS_StreamFree) != NULL && + LOADBASSFUNCTION(BASS_GetDeviceInfo) != NULL && LOADBASSFUNCTION(BASS_Free)) + { + int i; BASS_DEVICEINFO info; + + newBass = (BASS_SetConfig(BASS_CONFIG_DEV_DEFAULT, TRUE) != 0); // will use new "Default" device + + if (!DBGetContactSettingString(NULL, ModuleName, OPT_OUTDEVICE, &dbv)) + { + for (i=1; BASS_GetDeviceInfo(i, &info); i++) + if (!lstrcmpA(dbv.pszVal, info.name)) + device = i; + } + DBFreeVariant(&dbv); + + sndLimSnd = DBGetContactSettingByte(NULL, ModuleName, OPT_MAXCHAN, MAXCHAN); + if ( sndLimSnd > MAXCHAN ) sndLimSnd = MAXCHAN; + TimeWrd1 = DBGetContactSettingWord(NULL, ModuleName, OPT_TIME1, 0); + TimeWrd2 = DBGetContactSettingWord(NULL, ModuleName, OPT_TIME2, 0); + QuietTime = DBGetContactSettingByte(NULL, ModuleName, OPT_QUIETTIME, 0); + EnPreview = DBGetContactSettingByte(NULL, ModuleName, OPT_PREVIEW, 0); + + StatMask = DBGetContactSettingWord(NULL, ModuleName, OPT_STATUS, 0x3ff); + + ClistHWND = (HWND)CallService("CLUI/GetHwnd", 0, 0); + if (DBGetContactSettingByte(NULL, ModuleName, OPT_DEVOPEN, 1)) + BASS_Init(device, 44100, 0, ClistHWND, NULL); + else + CallService(MS_TB_SETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", TBST_PUSHED); + + Volume = DBGetContactSettingByte(NULL, ModuleName, OPT_VOLUME, 33); + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100 ); + hHooks[3] = HookEvent(ME_SKIN_PLAYINGSOUND, OnPlaySnd); + } + else + { + FreeLibrary(hBass); + hBass = NULL; + } + } + + hHooks[4] = HookEvent(ME_OPT_INITIALISE, OptionsInit); + + return 0; +} + +int OnShutdown(WPARAM wParam, LPARAM lParam) +{ + if(hBass != NULL) + { + BASS_Free(); + FreeLibrary(hBass); + } + + return 0; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + pluginLink = link; + mir_getLP(&pluginInfo); + mir_getMMI(&mmi); + + hHooks[0] = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + hHooks[1] = HookEvent(ME_SYSTEM_SHUTDOWN, OnShutdown); + hHooks[2] = HookEvent(ME_TB_MODULELOADED, OnToolbarLoaded); + + hService = CreateServiceFunction("BASSinterface/BASSSoundOnOff", BASSSoundOnOff); + + InitIcons(); + + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + int i; + for (i = 0; i < SIZEOF(hHooks); i++) + { + if (hHooks[i]) + UnhookEvent(hHooks[i]); + } + + DestroyServiceFunction(hService); + + return 0; +} \ No newline at end of file diff --git a/plugins/BASS_interface/Resource.h b/plugins/BASS_interface/Resource.h new file mode 100644 index 0000000000..fb35fa7855 --- /dev/null +++ b/plugins/BASS_interface/Resource.h @@ -0,0 +1,31 @@ +#ifndef IDC_STATIC +#define IDC_STATIC (-1) +#endif + +#define IDD_OPTIONS 101 +#define IDC_BASSVERSION 1000 +#define IDC_VOLUMELABEL 1001 +#define IDC_CURRPATHLABEL 1002 +#define IDC_OUTDEVICELABEL 1004 +#define IDC_OUTDEVICE 1005 +#define IDC_QUIETTIME 1008 +#define IDC_CURRPATH 1009 +#define IDC_MAXCHANNELLABEL 1010 +#define IDC_MAXCHANNEL 1011 +#define IDC_VOLUME 1012 +#define IDC_GETBASS 1013 +#define IDC_TIME1 1014 +#define IDC_TIME2 1015 +#define IDC_CHECKBOX1 1100 +#define IDC_CHECKBOX2 1101 +#define IDC_CHECKBOX3 1102 +#define IDC_CHECKBOX4 1103 +#define IDC_CHECKBOX5 1104 +#define IDC_CHECKBOX6 1105 +#define IDC_CHECKBOX7 1106 +#define IDC_CHECKBOX8 1107 +#define IDC_CHECKBOX9 1108 +#define IDC_CHECKBOX10 1109 +#define IDC_PREVIEW 1110 +#define IDI_BASSSoundOnOffUp 200 +#define IDI_BASSSoundOnOffDown 201 diff --git a/plugins/BASS_interface/Version.h b/plugins/BASS_interface/Version.h new file mode 100644 index 0000000000..814a8951dd --- /dev/null +++ b/plugins/BASS_interface/Version.h @@ -0,0 +1,28 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 0 +#define __RELEASE_NUM 0 +#define __BUILD_NUM 13 + +#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM +#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM + +#define __STRINGIFY_IMPL(x) #x +#define __STRINGIFY(x) __STRINGIFY_IMPL(x) +#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS) + +#ifdef _UNICODE +#if defined(WIN64) || defined(_WIN64) + #define __PLUGIN_NAME "Bass_interface (Unicode x64)" +#else + #define __PLUGIN_NAME "Bass_interface (Unicode)" +#endif +#else + #define __PLUGIN_NAME "Bass_interface" +#endif +#define __INTERNAL_NAME "Bass_interface" +#define __FILENAME "Bass_interface.dll" +#define __DESCRIPTION "un4seen's bass interface Miranda IM plugin." +#define __AUTHOR "tico-tico" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "" +#define __COPYRIGHT "© 2010, 2011 tico-tico" diff --git a/plugins/BASS_interface/Version.rc b/plugins/BASS_interface/Version.rc new file mode 100644 index 0000000000..e637f0cb33 --- /dev/null +++ b/plugins/BASS_interface/Version.rc @@ -0,0 +1,38 @@ +// Microsoft Visual C++ generated resource script. +// +#include "afxres.h" +#include "version.h" + +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#endif //_WIN32 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/plugins/BASS_interface/res/BASSSoundOnOffDown.ico b/plugins/BASS_interface/res/BASSSoundOnOffDown.ico new file mode 100644 index 0000000000..a10bfce204 Binary files /dev/null and b/plugins/BASS_interface/res/BASSSoundOnOffDown.ico differ diff --git a/plugins/BASS_interface/res/BASSSoundOnOffUp.ico b/plugins/BASS_interface/res/BASSSoundOnOffUp.ico new file mode 100644 index 0000000000..bee9f065a0 Binary files /dev/null and b/plugins/BASS_interface/res/BASSSoundOnOffUp.ico differ diff --git a/plugins/Bass_interface/Bass.h b/plugins/Bass_interface/Bass.h deleted file mode 100644 index cf0a66cf2b..0000000000 --- a/plugins/Bass_interface/Bass.h +++ /dev/null @@ -1,920 +0,0 @@ -/* - BASS 2.4 C/C++ header file - Copyright (c) 1999-2010 Un4seen Developments Ltd. - - See the BASS.CHM file for more detailed documentation -*/ - -#ifndef BASS_H -#define BASS_H - -#ifdef _WIN32 -#include -typedef unsigned __int64 QWORD; -#else -#include -#define WINAPI -#define CALLBACK -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint32_t DWORD; -typedef uint64_t QWORD; -#ifndef __OBJC__ -typedef int BOOL; -#endif -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif -#define LOBYTE(a) (BYTE)(a) -#define HIBYTE(a) (BYTE)((a)>>8) -#define LOWORD(a) (WORD)(a) -#define HIWORD(a) (WORD)((a)>>16) -#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8)) -#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16)) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define BASSVERSION 0x204 // API version -#define BASSVERSIONTEXT "2.4" - -#ifndef BASSDEF -#define BASSDEF(f) WINAPI f -#endif - -typedef DWORD HMUSIC; // MOD music handle -typedef DWORD HSAMPLE; // sample handle -typedef DWORD HCHANNEL; // playing sample's channel handle -typedef DWORD HSTREAM; // sample stream handle -typedef DWORD HRECORD; // recording handle -typedef DWORD HSYNC; // synchronizer handle -typedef DWORD HDSP; // DSP handle -typedef DWORD HFX; // DX8 effect handle -typedef DWORD HPLUGIN; // Plugin handle - -// Error codes returned by BASS_ErrorGetCode -#define BASS_OK 0 // all is OK -#define BASS_ERROR_MEM 1 // memory error -#define BASS_ERROR_FILEOPEN 2 // can't open the file -#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver -#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost -#define BASS_ERROR_HANDLE 5 // invalid handle -#define BASS_ERROR_FORMAT 6 // unsupported sample format -#define BASS_ERROR_POSITION 7 // invalid position -#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called -#define BASS_ERROR_START 9 // BASS_Start has not been successfully called -#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever -#define BASS_ERROR_NOCHAN 18 // can't get a free channel -#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified -#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified -#define BASS_ERROR_NO3D 21 // no 3D support -#define BASS_ERROR_NOEAX 22 // no EAX support -#define BASS_ERROR_DEVICE 23 // illegal device number -#define BASS_ERROR_NOPLAY 24 // not playing -#define BASS_ERROR_FREQ 25 // illegal sample rate -#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream -#define BASS_ERROR_NOHW 29 // no hardware voices available -#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data -#define BASS_ERROR_NONET 32 // no internet connection could be opened -#define BASS_ERROR_CREATE 33 // couldn't create the file -#define BASS_ERROR_NOFX 34 // effects are not available -#define BASS_ERROR_NOTAVAIL 37 // requested data is not available -#define BASS_ERROR_DECODE 38 // the channel is a "decoding channel" -#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed -#define BASS_ERROR_TIMEOUT 40 // connection timedout -#define BASS_ERROR_FILEFORM 41 // unsupported file format -#define BASS_ERROR_SPEAKER 42 // unavailable speaker -#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons) -#define BASS_ERROR_CODEC 44 // codec is not available/supported -#define BASS_ERROR_ENDED 45 // the channel/file has ended -#define BASS_ERROR_BUSY 46 // the device is busy -#define BASS_ERROR_UNKNOWN -1 // some other mystery problem - -// BASS_SetConfig options -#define BASS_CONFIG_BUFFER 0 -#define BASS_CONFIG_UPDATEPERIOD 1 -#define BASS_CONFIG_GVOL_SAMPLE 4 -#define BASS_CONFIG_GVOL_STREAM 5 -#define BASS_CONFIG_GVOL_MUSIC 6 -#define BASS_CONFIG_CURVE_VOL 7 -#define BASS_CONFIG_CURVE_PAN 8 -#define BASS_CONFIG_FLOATDSP 9 -#define BASS_CONFIG_3DALGORITHM 10 -#define BASS_CONFIG_NET_TIMEOUT 11 -#define BASS_CONFIG_NET_BUFFER 12 -#define BASS_CONFIG_PAUSE_NOPLAY 13 -#define BASS_CONFIG_NET_PREBUF 15 -#define BASS_CONFIG_NET_PASSIVE 18 -#define BASS_CONFIG_REC_BUFFER 19 -#define BASS_CONFIG_NET_PLAYLIST 21 -#define BASS_CONFIG_MUSIC_VIRTUAL 22 -#define BASS_CONFIG_VERIFY 23 -#define BASS_CONFIG_UPDATETHREADS 24 -#define BASS_CONFIG_DEV_BUFFER 27 -#define BASS_CONFIG_DEV_DEFAULT 36 -#define BASS_CONFIG_NET_READTIMEOUT 37 - -// BASS_SetConfigPtr options -#define BASS_CONFIG_NET_AGENT 16 -#define BASS_CONFIG_NET_PROXY 17 - -// Initialization flags -#define BASS_DEVICE_8BITS 1 // use 8 bit resolution, else 16 bit -#define BASS_DEVICE_MONO 2 // use mono, else stereo -#define BASS_DEVICE_3D 4 // enable 3D functionality -#define BASS_DEVICE_LATENCY 256 // calculate device latency (BASS_INFO struct) -#define BASS_DEVICE_CPSPEAKERS 1024 // detect speakers via Windows control panel -#define BASS_DEVICE_SPEAKERS 2048 // force enabling of speaker assignment -#define BASS_DEVICE_NOSPEAKER 4096 // ignore speaker arrangement -#ifdef __linux__ -#define BASS_DEVICE_DMIX 8192 // use ALSA "dmix" plugin -#endif - -// DirectSound interfaces (for use with BASS_GetDSoundObject) -#define BASS_OBJECT_DS 1 // IDirectSound -#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener - -// Device info structure -typedef struct { -#ifdef _WIN32_WCE - const wchar_t *name; // description - const wchar_t *driver; // driver -#else - const char *name; // description - const char *driver; // driver -#endif - DWORD flags; -} BASS_DEVICEINFO; - -// BASS_DEVICEINFO flags -#define BASS_DEVICE_ENABLED 1 -#define BASS_DEVICE_DEFAULT 2 -#define BASS_DEVICE_INIT 4 - -typedef struct { - DWORD flags; // device capabilities (DSCAPS_xxx flags) - DWORD hwsize; // size of total device hardware memory - DWORD hwfree; // size of free device hardware memory - DWORD freesam; // number of free sample slots in the hardware - DWORD free3d; // number of free 3D sample slots in the hardware - DWORD minrate; // min sample rate supported by the hardware - DWORD maxrate; // max sample rate supported by the hardware - BOOL eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used) - DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) - DWORD dsver; // DirectSound version - DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) - DWORD initflags;// BASS_Init "flags" parameter - DWORD speakers; // number of speakers available - DWORD freq; // current output rate (Vista/OSX only) -} BASS_INFO; - -// BASS_INFO flags (from DSOUND.H) -#define DSCAPS_CONTINUOUSRATE 0x00000010 // supports all sample rates between min/maxrate -#define DSCAPS_EMULDRIVER 0x00000020 // device does NOT have hardware DirectSound support -#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft -#define DSCAPS_SECONDARYMONO 0x00000100 // mono -#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo -#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit -#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit - -// Recording device info structure -typedef struct { - DWORD flags; // device capabilities (DSCCAPS_xxx flags) - DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) - DWORD inputs; // number of inputs - BOOL singlein; // TRUE = only 1 input can be set at a time - DWORD freq; // current input rate (Vista/OSX only) -} BASS_RECORDINFO; - -// BASS_RECORDINFO flags (from DSOUND.H) -#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording support -#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft - -// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H) -#ifndef WAVE_FORMAT_1M08 -#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ -#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ -#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ -#endif - -// Sample info structure -typedef struct { - DWORD freq; // default playback rate - float volume; // default volume (0-1) - float pan; // default pan (-1=left, 0=middle, 1=right) - DWORD flags; // BASS_SAMPLE_xxx flags - DWORD length; // length (in bytes) - DWORD max; // maximum simultaneous playbacks - DWORD origres; // original resolution bits - DWORD chans; // number of channels - DWORD mingap; // minimum gap (ms) between creating channels - DWORD mode3d; // BASS_3DMODE_xxx mode - float mindist; // minimum distance - float maxdist; // maximum distance - DWORD iangle; // angle of inside projection cone - DWORD oangle; // angle of outside projection cone - float outvol; // delta-volume outside the projection cone - DWORD vam; // voice allocation/management flags (BASS_VAM_xxx) - DWORD priority; // priority (0=lowest, 0xffffffff=highest) -} BASS_SAMPLE; - -#define BASS_SAMPLE_8BITS 1 // 8 bit -#define BASS_SAMPLE_FLOAT 256 // 32-bit floating-point -#define BASS_SAMPLE_MONO 2 // mono -#define BASS_SAMPLE_LOOP 4 // looped -#define BASS_SAMPLE_3D 8 // 3D functionality -#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing -#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only) -#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management -#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects -#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume -#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing -#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only) - -#define BASS_STREAM_PRESCAN 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1) -#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN -#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stop/ends -#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file streams -#define BASS_STREAM_BLOCK 0x100000 // download/play internet file stream in small blocks -#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode (BASS_ChannelGetData) -#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC - -#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT -#define BASS_MUSIC_MONO BASS_SAMPLE_MONO -#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP -#define BASS_MUSIC_3D BASS_SAMPLE_3D -#define BASS_MUSIC_FX BASS_SAMPLE_FX -#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE -#define BASS_MUSIC_DECODE BASS_STREAM_DECODE -#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length -#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN -#define BASS_MUSIC_RAMP 0x200 // normal ramping -#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping -#define BASS_MUSIC_SURROUND 0x800 // surround sound -#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2) -#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does -#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does -#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing -#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing -#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position -#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position -#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect -#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples - -// Speaker assignment flags -#define BASS_SPEAKER_FRONT 0x1000000 // front speakers -#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers -#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1) -#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1) -#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15) -#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left -#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right -#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT - -#define BASS_UNICODE 0x80000000 - -#define BASS_RECORD_PAUSE 0x8000 // start recording paused - -// DX7 voice allocation & management flags -#define BASS_VAM_HARDWARE 1 -#define BASS_VAM_SOFTWARE 2 -#define BASS_VAM_TERM_TIME 4 -#define BASS_VAM_TERM_DIST 8 -#define BASS_VAM_TERM_PRIO 16 - -// Channel info structure -typedef struct { - DWORD freq; // default playback rate - DWORD chans; // channels - DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags - DWORD ctype; // type of channel - DWORD origres; // original resolution - HPLUGIN plugin; // plugin - HSAMPLE sample; // sample - const char *filename; // filename -} BASS_CHANNELINFO; - -// BASS_CHANNELINFO types -#define BASS_CTYPE_SAMPLE 1 -#define BASS_CTYPE_RECORD 2 -#define BASS_CTYPE_STREAM 0x10000 -#define BASS_CTYPE_STREAM_OGG 0x10002 -#define BASS_CTYPE_STREAM_MP1 0x10003 -#define BASS_CTYPE_STREAM_MP2 0x10004 -#define BASS_CTYPE_STREAM_MP3 0x10005 -#define BASS_CTYPE_STREAM_AIFF 0x10006 -#define BASS_CTYPE_STREAM_CA 0x10007 -#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec -#define BASS_CTYPE_STREAM_WAV_PCM 0x50001 -#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 -#define BASS_CTYPE_MUSIC_MOD 0x20000 -#define BASS_CTYPE_MUSIC_MTM 0x20001 -#define BASS_CTYPE_MUSIC_S3M 0x20002 -#define BASS_CTYPE_MUSIC_XM 0x20003 -#define BASS_CTYPE_MUSIC_IT 0x20004 -#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag - -typedef struct { - DWORD ctype; // channel type -#ifdef _WIN32_WCE - const wchar_t *name; // format description - const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...) -#else - const char *name; // format description - const char *exts; // file extension filter (*.ext1;*.ext2;etc...) -#endif -} BASS_PLUGINFORM; - -typedef struct { - DWORD version; // version (same form as BASS_GetVersion) - DWORD formatc; // number of formats - const BASS_PLUGINFORM *formats; // the array of formats -} BASS_PLUGININFO; - -// 3D vector (for 3D positions/velocities/orientations) -typedef struct BASS_3DVECTOR { -#ifdef __cplusplus - BASS_3DVECTOR() {}; - BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; -#endif - float x; // +=right, -=left - float y; // +=up, -=down - float z; // +=front, -=behind -} BASS_3DVECTOR; - -// 3D channel modes -#define BASS_3DMODE_NORMAL 0 // normal 3D processing -#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener -#define BASS_3DMODE_OFF 2 // no 3D processing - -// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM) -#define BASS_3DALG_DEFAULT 0 -#define BASS_3DALG_OFF 1 -#define BASS_3DALG_FULL 2 -#define BASS_3DALG_LIGHT 3 - -// EAX environments, use with BASS_SetEAXParameters -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT // total number of environments -}; - -// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx) -#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F -#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F -#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F -#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F -#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F -#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F -#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F -#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F -#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F -#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F -#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F -#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F -#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F -#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F -#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F -#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F -#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F -#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F -#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F -#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F -#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F -#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F -#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F -#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F -#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F -#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F - -typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user); -/* User stream callback function. NOTE: A stream function should obviously be as quick -as possible, other streams (and MOD musics) can't be mixed until it's finished. -handle : The stream that needs writing -buffer : Buffer to write the samples in -length : Number of bytes to write -user : The 'user' parameter value given when calling BASS_StreamCreate -RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end - the stream. */ - -#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag - -// special STREAMPROCs -#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream -#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream - -// BASS_StreamCreateFileUser file systems -#define STREAMFILE_NOBUFFER 0 -#define STREAMFILE_BUFFER 1 -#define STREAMFILE_BUFFERPUSH 2 - -// User file stream callback functions -typedef void (CALLBACK FILECLOSEPROC)(void *user); -typedef QWORD (CALLBACK FILELENPROC)(void *user); -typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user); -typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user); - -typedef struct { - FILECLOSEPROC *close; - FILELENPROC *length; - FILEREADPROC *read; - FILESEEKPROC *seek; -} BASS_FILEPROCS; - -// BASS_StreamPutFileData options -#define BASS_FILEDATA_END 0 // end & close the file - -// BASS_StreamGetFilePosition modes -#define BASS_FILEPOS_CURRENT 0 -#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT -#define BASS_FILEPOS_DOWNLOAD 1 -#define BASS_FILEPOS_END 2 -#define BASS_FILEPOS_START 3 -#define BASS_FILEPOS_CONNECTED 4 -#define BASS_FILEPOS_BUFFER 5 -#define BASS_FILEPOS_SOCKET 6 - -typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user); -/* Internet stream download callback function. -buffer : Buffer containing the downloaded data... NULL=end of download -length : Number of bytes in the buffer -user : The 'user' parameter value given when calling BASS_StreamCreateURL */ - -// BASS_ChannelSetSync types -#define BASS_SYNC_POS 0 -#define BASS_SYNC_END 2 -#define BASS_SYNC_META 4 -#define BASS_SYNC_SLIDE 5 -#define BASS_SYNC_STALL 6 -#define BASS_SYNC_DOWNLOAD 7 -#define BASS_SYNC_FREE 8 -#define BASS_SYNC_SETPOS 11 -#define BASS_SYNC_MUSICPOS 10 -#define BASS_SYNC_MUSICINST 1 -#define BASS_SYNC_MUSICFX 3 -#define BASS_SYNC_OGG_CHANGE 12 -#define BASS_SYNC_MIXTIME 0x40000000 // FLAG: sync at mixtime, else at playtime -#define BASS_SYNC_ONETIME 0x80000000 // FLAG: sync only once, else continuously - -typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user); -/* Sync callback function. NOTE: a sync callback function should be very -quick as other syncs can't be processed until it has finished. If the sync -is a "mixtime" sync, then other streams and MOD musics can't be mixed until -it's finished either. -handle : The sync that has occured -channel: Channel that the sync occured in -data : Additional data associated with the sync's occurance -user : The 'user' parameter given when calling BASS_ChannelSetSync */ - -typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user); -/* DSP callback function. NOTE: A DSP function should obviously be as quick as -possible... other DSP functions, streams and MOD musics can not be processed -until it's finished. -handle : The DSP handle -channel: Channel that the DSP is being applied to -buffer : Buffer to apply the DSP to -length : Number of bytes in the buffer -user : The 'user' parameter given when calling BASS_ChannelSetDSP */ - -typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user); -/* Recording callback function. -handle : The recording handle -buffer : Buffer containing the recorded sample data -length : Number of bytes -user : The 'user' parameter value given when calling BASS_RecordStart -RETURN : TRUE = continue recording, FALSE = stop */ - -// BASS_ChannelIsActive return values -#define BASS_ACTIVE_STOPPED 0 -#define BASS_ACTIVE_PLAYING 1 -#define BASS_ACTIVE_STALLED 2 -#define BASS_ACTIVE_PAUSED 3 - -// Channel attributes -#define BASS_ATTRIB_FREQ 1 -#define BASS_ATTRIB_VOL 2 -#define BASS_ATTRIB_PAN 3 -#define BASS_ATTRIB_EAXMIX 4 -#define BASS_ATTRIB_NOBUFFER 5 -#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 -#define BASS_ATTRIB_MUSIC_PANSEP 0x101 -#define BASS_ATTRIB_MUSIC_PSCALER 0x102 -#define BASS_ATTRIB_MUSIC_BPM 0x103 -#define BASS_ATTRIB_MUSIC_SPEED 0x104 -#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105 -#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel # -#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument # - -// BASS_ChannelGetData flags -#define BASS_DATA_AVAILABLE 0 // query how much data is buffered -#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data -#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT -#define BASS_DATA_FFT512 0x80000001 // 512 FFT -#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT -#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT -#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT -#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT -#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT -#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined -#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window -#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias - -// BASS_ChannelGetTags types : what's returned -#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure -#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block -#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings -#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings -#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings -#define BASS_TAG_META 5 // ICY metadata : ANSI string -#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings -#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string -#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string -#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure -#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings -#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure -#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure -#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string -#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure -#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string -#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string -#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers -#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string -#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string - -// ID3v1 tag structure -typedef struct { - char id[3]; - char title[30]; - char artist[30]; - char album[30]; - char year[4]; - char comment[30]; - BYTE genre; -} TAG_ID3; - -// Binary APE tag structure -typedef struct { - const char *key; - const void *data; - DWORD length; -} TAG_APE_BINARY; - -// BWF "bext" tag structure -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4200) -#endif -#pragma pack(push,1) -typedef struct { - char Description[256]; // description - char Originator[32]; // name of the originator - char OriginatorReference[32]; // reference of the originator - char OriginationDate[10]; // date of creation (yyyy-mm-dd) - char OriginationTime[8]; // time of creation (hh-mm-ss) - QWORD TimeReference; // first sample count since midnight (little-endian) - WORD Version; // BWF version (little-endian) - BYTE UMID[64]; // SMPTE UMID - BYTE Reserved[190]; -#if defined(__GNUC__) && __GNUC__<3 - char CodingHistory[0]; // history -#elif 1 // change to 0 if compiler fails the following line - char CodingHistory[]; // history -#else - char CodingHistory[1]; // history -#endif -} TAG_BEXT; -#pragma pack(pop) -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// BWF "cart" tag structures -typedef struct -{ - DWORD dwUsage; // FOURCC timer usage ID - DWORD dwValue; // timer value in samples from head -} TAG_CART_TIMER; - -typedef struct -{ - char Version[4]; // version of the data structure - char Title[64]; // title of cart audio sequence - char Artist[64]; // artist or creator name - char CutID[64]; // cut number identification - char ClientID[64]; // client identification - char Category[64]; // category ID, PSA, NEWS, etc - char Classification[64]; // classification or auxiliary key - char OutCue[64]; // out cue text - char StartDate[10]; // yyyy-mm-dd - char StartTime[8]; // hh:mm:ss - char EndDate[10]; // yyyy-mm-dd - char EndTime[8]; // hh:mm:ss - char ProducerAppID[64]; // name of vendor or application - char ProducerAppVersion[64]; // version of producer application - char UserDef[64]; // user defined text - DWORD dwLevelReference; // sample value for 0 dB reference - TAG_CART_TIMER PostTimer[8]; // 8 time markers after head - char Reserved[276]; - char URL[1024]; // uniform resource locator -#if defined(__GNUC__) && __GNUC__<3 - char TagText[0]; // free form text for scripts or tags -#elif 1 // change to 0 if compiler fails the following line - char TagText[]; // free form text for scripts or tags -#else - char TagText[1]; // free form text for scripts or tags -#endif -} TAG_CART; - -// CoreAudio codec info structure -typedef struct { - DWORD ftype; // file format - DWORD atype; // audio format - const char *name; // description -} TAG_CA_CODEC; - -// BASS_ChannelGetLength/GetPosition/SetPosition modes -#define BASS_POS_BYTE 0 // byte position -#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) -#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position -#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking - -// BASS_RecordSetInput flags -#define BASS_INPUT_OFF 0x10000 -#define BASS_INPUT_ON 0x20000 - -#define BASS_INPUT_TYPE_MASK 0xff000000 -#define BASS_INPUT_TYPE_UNDEF 0x00000000 -#define BASS_INPUT_TYPE_DIGITAL 0x01000000 -#define BASS_INPUT_TYPE_LINE 0x02000000 -#define BASS_INPUT_TYPE_MIC 0x03000000 -#define BASS_INPUT_TYPE_SYNTH 0x04000000 -#define BASS_INPUT_TYPE_CD 0x05000000 -#define BASS_INPUT_TYPE_PHONE 0x06000000 -#define BASS_INPUT_TYPE_SPEAKER 0x07000000 -#define BASS_INPUT_TYPE_WAVE 0x08000000 -#define BASS_INPUT_TYPE_AUX 0x09000000 -#define BASS_INPUT_TYPE_ANALOG 0x0a000000 - -// DX8 effect types, use with BASS_ChannelSetFX -enum -{ - BASS_FX_DX8_CHORUS, - BASS_FX_DX8_COMPRESSOR, - BASS_FX_DX8_DISTORTION, - BASS_FX_DX8_ECHO, - BASS_FX_DX8_FLANGER, - BASS_FX_DX8_GARGLE, - BASS_FX_DX8_I3DL2REVERB, - BASS_FX_DX8_PARAMEQ, - BASS_FX_DX8_REVERB -}; - -typedef struct { - float fWetDryMix; - float fDepth; - float fFeedback; - float fFrequency; - DWORD lWaveform; // 0=triangle, 1=sine - float fDelay; - DWORD lPhase; // BASS_DX8_PHASE_xxx -} BASS_DX8_CHORUS; - -typedef struct { - float fGain; - float fAttack; - float fRelease; - float fThreshold; - float fRatio; - float fPredelay; -} BASS_DX8_COMPRESSOR; - -typedef struct { - float fGain; - float fEdge; - float fPostEQCenterFrequency; - float fPostEQBandwidth; - float fPreLowpassCutoff; -} BASS_DX8_DISTORTION; - -typedef struct { - float fWetDryMix; - float fFeedback; - float fLeftDelay; - float fRightDelay; - BOOL lPanDelay; -} BASS_DX8_ECHO; - -typedef struct { - float fWetDryMix; - float fDepth; - float fFeedback; - float fFrequency; - DWORD lWaveform; // 0=triangle, 1=sine - float fDelay; - DWORD lPhase; // BASS_DX8_PHASE_xxx -} BASS_DX8_FLANGER; - -typedef struct { - DWORD dwRateHz; // Rate of modulation in hz - DWORD dwWaveShape; // 0=triangle, 1=square -} BASS_DX8_GARGLE; - -typedef struct { - int lRoom; // [-10000, 0] default: -1000 mB - int lRoomHF; // [-10000, 0] default: 0 mB - float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 - float flDecayTime; // [0.1, 20.0] default: 1.49s - float flDecayHFRatio; // [0.1, 2.0] default: 0.83 - int lReflections; // [-10000, 1000] default: -2602 mB - float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s - int lReverb; // [-10000, 2000] default: 200 mB - float flReverbDelay; // [0.0, 0.1] default: 0.011 s - float flDiffusion; // [0.0, 100.0] default: 100.0 % - float flDensity; // [0.0, 100.0] default: 100.0 % - float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz -} BASS_DX8_I3DL2REVERB; - -typedef struct { - float fCenter; - float fBandwidth; - float fGain; -} BASS_DX8_PARAMEQ; - -typedef struct { - float fInGain; // [-96.0,0.0] default: 0.0 dB - float fReverbMix; // [-96.0,0.0] default: 0.0 db - float fReverbTime; // [0.001,3000.0] default: 1000.0 ms - float fHighFreqRTRatio; // [0.001,0.999] default: 0.001 -} BASS_DX8_REVERB; - -#define BASS_DX8_PHASE_NEG_180 0 -#define BASS_DX8_PHASE_NEG_90 1 -#define BASS_DX8_PHASE_ZERO 2 -#define BASS_DX8_PHASE_90 3 -#define BASS_DX8_PHASE_180 4 - -BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); -DWORD BASSDEF(BASS_GetConfig)(DWORD option); -BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, void *value); -void *BASSDEF(BASS_GetConfigPtr)(DWORD option); -DWORD BASSDEF(BASS_GetVersion)(); -int BASSDEF(BASS_ErrorGetCode)(); -BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); -#if defined(_WIN32) && !defined(_WIN32_WCE) -BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); -#else -BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, void *dsguid); -#endif -BOOL BASSDEF(BASS_SetDevice)(DWORD device); -DWORD BASSDEF(BASS_GetDevice)(); -BOOL BASSDEF(BASS_Free)(); -#if defined(_WIN32) && !defined(_WIN32_WCE) -void *BASSDEF(BASS_GetDSoundObject)(DWORD object); -#endif -BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info); -BOOL BASSDEF(BASS_Update)(DWORD length); -float BASSDEF(BASS_GetCPU)(); -BOOL BASSDEF(BASS_Start)(); -BOOL BASSDEF(BASS_Stop)(); -BOOL BASSDEF(BASS_Pause)(); -BOOL BASSDEF(BASS_SetVolume)(float volume); -float BASSDEF(BASS_GetVolume)(); - -HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags); -BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle); -const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle); - -BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf); -BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf); -BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top); -BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top); -void BASSDEF(BASS_Apply3D)(); -#if defined(_WIN32) && !defined(_WIN32_WCE) -BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay, float damp); -BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay, float *damp); -#endif - -HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq); -BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle); - -HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags); -HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags); -BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle); -BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer); -BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer); -BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info); -BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info); -HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew); -DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels); -BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle); - -HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user); -HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); -HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); -HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user); -BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle); -QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode); -DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length); -DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length); - -BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); -BOOL BASSDEF(BASS_RecordInit)(int device); -BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device); -DWORD BASSDEF(BASS_RecordGetDevice)(); -BOOL BASSDEF(BASS_RecordFree)(); -BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info); -const char *BASSDEF(BASS_RecordGetInputName)(int input); -BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume); -DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume); -HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user); - -double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos); -QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos); -DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle); -BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device); -DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle); -BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info); -const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags); -DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask); -BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length); -BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock); -BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart); -BOOL BASSDEF(BASS_ChannelStop)(DWORD handle); -BOOL BASSDEF(BASS_ChannelPause)(DWORD handle); -BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value); -BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value); -BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time); -BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib); -BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol); -BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol); -BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel); -BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel); -QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode); -BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode); -QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode); -DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle); -DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length); -HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user); -BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync); -HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority); -BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp); -BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan); -BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan); -HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority); -BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx); - -BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params); -BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params); -BOOL BASSDEF(BASS_FXReset)(HFX handle); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/plugins/Bass_interface/Bass.rc b/plugins/Bass_interface/Bass.rc deleted file mode 100644 index 31ca4098d3..0000000000 --- a/plugins/Bass_interface/Bass.rc +++ /dev/null @@ -1,109 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include -#include -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Ðóññêèé (Ðîññèÿ) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT -#pragma code_page(1251) - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_BASSSoundOnOffUp ICON "res/BASSSoundOnOffUp.ico" -IDI_BASSSoundOnOffDown ICON "res/BASSSoundOnOffDown.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_OPTIONS DIALOGEX 0, 0, 313, 240 -STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW -EXSTYLE WS_EX_CONTROLPARENT -FONT 8, "MS Shell Dlg", 0, 0, 1 -BEGIN - GROUPBOX "un4seen's bass interface", IDC_STATIC, 5, 5, 302, 231 - LTEXT "bass.dll loading error", IDC_BASSVERSION, 20, 20, 210, 8, SS_LEFT - LTEXT "Current bass.dll path:", IDC_CURRPATHLABEL, 20, 45, 210, 8, SS_LEFT - LTEXT "", IDC_CURRPATH, 20, 60, 210, 8, SS_LEFT | SS_PATHELLIPSIS - LTEXT "Maximum number of bass internal channels:", IDC_MAXCHANNELLABEL, 20, 85, 210, 8, SS_LEFT - COMBOBOX IDC_MAXCHANNEL, 20, 100, 48, 14, CBS_DROPDOWNLIST | CBS_HASSTRINGS - LTEXT "Output device:", IDC_OUTDEVICELABEL, 20, 125, 240, 8, SS_LEFT - COMBOBOX IDC_OUTDEVICE, 20, 140, 236, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS - LTEXT "Volume:", IDC_VOLUMELABEL, 20, 165, 165, 8, SS_LEFT - CONTROL "", IDC_VOLUME, TRACKBAR_CLASS, WS_TABSTOP | TBS_BOTH | TBS_NOTICKS, 20, 180, 273, 10 - AUTOCHECKBOX "Quiet time:", IDC_QUIETTIME, 20, 205, 55, 10 - CONTROL "", IDC_TIME1, DATETIMEPICK_CLASS, WS_TABSTOP | WS_DISABLED | DTS_TIMEFORMAT | DTS_UPDOWN | DTS_RIGHTALIGN, 79, 202, 35, 15 - CONTROL "", IDC_TIME2, DATETIMEPICK_CLASS, WS_TABSTOP | WS_DISABLED | DTS_TIMEFORMAT | DTS_UPDOWN | DTS_RIGHTALIGN, 135, 202, 35, 15 - CTEXT "-", IDC_STATIC, 117, 205, 15, 8, SS_CENTER - CONTROL "download bass library", IDC_GETBASS, "Hyperlink", 0x50010002, 74, 222, 228, 10 - GROUPBOX "Play only if", IDC_STATIC, 235, 5, 72, 117 - AUTOCHECKBOX "Offline", IDC_CHECKBOX1, 240, 20, 65, 8 - AUTOCHECKBOX "Online", IDC_CHECKBOX2, 240, 30, 65, 8 - AUTOCHECKBOX "Away", IDC_CHECKBOX3, 240, 40, 65, 8 - AUTOCHECKBOX "NA", IDC_CHECKBOX4, 240, 50, 65, 8 - AUTOCHECKBOX "Occupied", IDC_CHECKBOX5, 240, 60, 65, 8 - AUTOCHECKBOX "DND", IDC_CHECKBOX6, 240, 70, 65, 8 - AUTOCHECKBOX "Free for chat", IDC_CHECKBOX7, 240, 80, 65, 8 - AUTOCHECKBOX "Invisible", IDC_CHECKBOX8, 240, 90, 65, 8 - AUTOCHECKBOX "On the phone", IDC_CHECKBOX9, 240, 100, 65, 8 - AUTOCHECKBOX "Out to lunch", IDC_CHECKBOX10, 240, 110, 65, 8 - AUTOCHECKBOX "Preview", IDC_PREVIEW, 200, 165, 90, 8, BS_RIGHT, WS_EX_RIGHT -END - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // Ðóññêèé (Ðîññèÿ) resources -///////////////////////////////////////////////////////////////////////////// - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED \ No newline at end of file diff --git a/plugins/Bass_interface/Bass_interface.h b/plugins/Bass_interface/Bass_interface.h deleted file mode 100644 index e42e85127b..0000000000 --- a/plugins/Bass_interface/Bass_interface.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright (C) 2010, 2011 tico-tico -*/ - -#ifndef __BASS_INTERFACE_H__ -#define __BASS_INTERFACE_H__ - -#define MIRANDA_VER 0x0A00 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "m_toolbar.h" - -#include "resource.h" -#include "version.h" - -#define BASSDEF(f) (WINAPI *f) -#include "bass.h" - -#define LOADBASSFUNCTION(f) (*((void**)&f)=(void*)GetProcAddress(hBass,#f)) - -#define MIID_BASSINT {0x2f07ea05, 0x05b5, 0x4ff0, { 0x87, 0x5d, 0xc5, 0x90, 0xda, 0x2d, 0xda, 0xc1 }} //2f07ea05-05b5-4ff0-875d-c590da2ddac1 - -#define ModuleName "Bass Interface" - -#define OPT_VOLUME "Volume" -#define OPT_BASSPATH "PathToDll" -#define OPT_MAXCHAN "MaxChannels" -#define OPT_OUTDEVICE "OutDevice" -#define OPT_QUIETTIME "QuietTime" -#define OPT_TIME1 "Time1" -#define OPT_TIME2 "Time2" -#define OPT_STATUS "StatMask" -#define OPT_PREVIEW "Preview" -#define OPT_DEVOPEN "DevOpen" - -#endif diff --git a/plugins/Bass_interface/Bass_interface.sln b/plugins/Bass_interface/Bass_interface.sln deleted file mode 100644 index 5be096af29..0000000000 --- a/plugins/Bass_interface/Bass_interface.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bass_interface", "Bass_interface.vcxproj", "{3933E789-D185-41DC-8169-9FF4365B6015}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|Win32.ActiveCfg = Debug|Win32 - {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|Win32.Build.0 = Debug|Win32 - {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|x64.ActiveCfg = Debug|x64 - {3933E789-D185-41DC-8169-9FF4365B6015}.Debug|x64.Build.0 = Debug|x64 - {3933E789-D185-41DC-8169-9FF4365B6015}.Release|Win32.ActiveCfg = Release|Win32 - {3933E789-D185-41DC-8169-9FF4365B6015}.Release|Win32.Build.0 = Release|Win32 - {3933E789-D185-41DC-8169-9FF4365B6015}.Release|x64.ActiveCfg = Release|x64 - {3933E789-D185-41DC-8169-9FF4365B6015}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/plugins/Bass_interface/Bass_interface.vcxproj b/plugins/Bass_interface/Bass_interface.vcxproj deleted file mode 100644 index 587bdb09c3..0000000000 --- a/plugins/Bass_interface/Bass_interface.vcxproj +++ /dev/null @@ -1,203 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {3933E789-D185-41DC-8169-9FF4365B6015} - bass_interface - Win32Proj - Bass_interface - - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - true - - - DynamicLibrary - Unicode - - - DynamicLibrary - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Configuration)/Plugins\ - $(SolutionDir)$(Configuration)64/Plugins\ - $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ - $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ - $(SolutionDir)$(Configuration)/Plugins\ - $(SolutionDir)$(Configuration)64/Plugins\ - $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ - $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ - AllRules.ruleset - AllRules.ruleset - - - - - AllRules.ruleset - AllRules.ruleset - - - - - true - true - true - true - - - - Disabled - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - Level3 - EditAndContinue - 4996;%(DisableSpecificWarnings) - - - true - Windows - $(IntDir)$(TargetName).lib - - - ../../include/msapi - - - - - Disabled - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN64;_DEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level3 - 4996;%(DisableSpecificWarnings) - - - true - Windows - $(IntDir)$(TargetName).lib - - - ../../include/msapi - - - - - Full - OnlyExplicitInline - false - Size - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - Fast - Level3 - 4996;%(DisableSpecificWarnings) - - - Windows - true - true - $(IntDir)$(TargetName).lib - true - - - ../../include/msapi - - - - - Full - OnlyExplicitInline - false - Size - ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN64;NDEBUG;_WINDOWS;_USRDLL;BASS_INTERFACE_EXPORTS;%(PreprocessorDefinitions) - true - - - MultiThreadedDLL - false - true - Fast - Level3 - 4996;%(DisableSpecificWarnings) - - - Windows - true - true - $(IntDir)$(TargetName).lib - true - - - ../../include/msapi - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/Bass_interface/Bass_interface.vcxproj.filters b/plugins/Bass_interface/Bass_interface.vcxproj.filters deleted file mode 100644 index 025a1f421b..0000000000 --- a/plugins/Bass_interface/Bass_interface.vcxproj.filters +++ /dev/null @@ -1,44 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - Resource Files - - - - - Source Files - - - \ No newline at end of file diff --git a/plugins/Bass_interface/Main.cpp b/plugins/Bass_interface/Main.cpp deleted file mode 100644 index 3c9d5108a5..0000000000 --- a/plugins/Bass_interface/Main.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* -Copyright (C) 2010, 2011 tico-tico -*/ - -#include "bass_interface.h" - -HINSTANCE hInst; -PLUGINLINK *pluginLink; -int hLangpack; - -PLUGININFOEX pluginInfo={ - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), - __DESCRIPTION, - __AUTHOR, - __AUTHOREMAIL, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - 0, - MIID_BASSINT -}; - -struct MM_INTERFACE mmi; - -static HANDLE hHooks[5] = {0}; -static HANDLE hService; -static HINSTANCE hBass = NULL; - -extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) -{ - hInst=hinstDLL; - return TRUE; -} - -extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) -{ - return &pluginInfo; -} - -static const MUUID interfaces[] = {MIID_BASSINT, MIID_LAST}; -extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) -{ - return interfaces; -} - -#define MAXCHAN 5 -static TCHAR CurrBassPath[MAX_PATH], tmp[MAX_PATH]; -static int sndNSnd = 0, sndLimSnd; -static HSTREAM sndSSnd[MAXCHAN] = {0}; - -static WORD TimeWrd1, TimeWrd2, StatMask; -static BOOL QuietTime, Preview, EnPreview; -static int Volume; -static int device = -1; -static int newBass = 0; -static HWND ClistHWND; - -static int OnPlaySnd(WPARAM wParam, LPARAM lParam) -{ - char * pszFile = (char *) lParam; SYSTEMTIME systime; WORD currtime, currstat; BOOL doPlay = TRUE; - - GetLocalTime(&systime); - currtime = MAKEWORD(systime.wMinute, systime.wHour); - - currstat = 1; - switch (CallService(MS_CLIST_GETSTATUSMODE, 0, 0)) - { - case ID_STATUS_OUTTOLUNCH: currstat <<= 1; - case ID_STATUS_ONTHEPHONE: currstat <<= 1; - case ID_STATUS_INVISIBLE: currstat <<= 1; - case ID_STATUS_FREECHAT: currstat <<= 1; - case ID_STATUS_DND: currstat <<= 1; - case ID_STATUS_OCCUPIED: currstat <<= 1; - case ID_STATUS_NA: currstat <<= 1; - case ID_STATUS_AWAY: currstat <<= 1; - case ID_STATUS_ONLINE: currstat <<= 1; - } - - if ( !DBGetContactSettingByte(NULL,"Skin","UseSound",0) ) doPlay = FALSE; - - if ( QuietTime ) - if ( - ((TimeWrd1 < TimeWrd2) && (TimeWrd1 <= currtime && currtime < TimeWrd2)) || - ((TimeWrd2 < TimeWrd1) && (TimeWrd1 <= currtime || currtime < TimeWrd2)) - ) doPlay = FALSE; - - if ( !(currstat & StatMask) ) doPlay = FALSE; - - if ( Preview || (int)wParam==1 ) doPlay = TRUE; - - if ( !pszFile ) doPlay = FALSE; - - if ( doPlay ) - { - BASS_StreamFree(sndSSnd[sndNSnd]); - sndSSnd[sndNSnd] = BASS_StreamCreateFile(FALSE, pszFile, 0, 0, BASS_STREAM_AUTOFREE); - BASS_ChannelPlay(sndSSnd[sndNSnd], FALSE); - sndNSnd = (sndNSnd+1)%sndLimSnd; - } - - Preview = FALSE; - - return 0; -} - -#define SLIDER_MIN 0 -#define SLIDER_MAX 100 - -INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch(msg) - { - case WM_INITDIALOG: - { - int i; SYSTEMTIME systime = {0}; - - TranslateDialogDefault(hwndDlg); - - SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_RESETCONTENT, 0, 0); - for(i=1; i<=MAXCHAN; i++) - SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_ADDSTRING, 0, (LPARAM)_itot(i, tmp, 10)); - - SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_SETCURSEL, sndLimSnd - 1, 0); - - SendDlgItemMessage(hwndDlg, IDC_CURRPATH, WM_SETTEXT, 0, (LPARAM)CurrBassPath); - - SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_SETRANGE, FALSE, MAKELONG(SLIDER_MIN,SLIDER_MAX)); - SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_SETPOS, TRUE, Volume); - SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_SETPAGESIZE, 0, 5); - - systime.wHour = HIBYTE(TimeWrd1); - systime.wMinute = LOBYTE(TimeWrd1); - systime.wYear = 2000; - systime.wMonth = 1; - systime.wDay = 1; - SendDlgItemMessage(hwndDlg, IDC_TIME1, DTM_SETFORMAT, 0, (LPARAM)_T("HH:mm")); - SendDlgItemMessage(hwndDlg, IDC_TIME1, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&systime); - systime.wHour = HIBYTE(TimeWrd2); - systime.wMinute = LOBYTE(TimeWrd2); - SendDlgItemMessage(hwndDlg, IDC_TIME2, DTM_SETFORMAT, 0, (LPARAM)_T("HH:mm")); - SendDlgItemMessage(hwndDlg, IDC_TIME2, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&systime); - - CheckDlgButton(hwndDlg, IDC_PREVIEW, EnPreview ? BST_CHECKED : BST_UNCHECKED); - - for(i = IDC_CHECKBOX1; i < IDC_CHECKBOX10+1; i++) - { - if (StatMask & (1 << (i-IDC_CHECKBOX1))) - CheckDlgButton(hwndDlg, i, BST_CHECKED); - } - - if (QuietTime) - { - EnableWindow(GetDlgItem(hwndDlg,IDC_TIME1), TRUE); - EnableWindow(GetDlgItem(hwndDlg,IDC_TIME2), TRUE); - CheckDlgButton(hwndDlg, IDC_QUIETTIME, BST_CHECKED); - } - if (hBass == NULL) - { - EnableWindow(GetDlgItem(hwndDlg, IDC_VOLUME), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_MAXCHANNEL), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_OUTDEVICE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_QUIETTIME), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PREVIEW), FALSE); - - for(i = IDC_CHECKBOX1; i < IDC_CHECKBOX10+1; i++) - { - EnableWindow(GetDlgItem(hwndDlg, i), FALSE); - } - } - else - { - DBVARIANT dbv = {0}; BASS_DEVICEINFO info; DWORD bassver = BASS_GetVersion(); - - mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("un4seen's bass version: %d.%d.%d.%d"), bassver >> 24, (bassver >> 16) & 0xff, (bassver >> 8) & 0xff, bassver & 0xff); - SendDlgItemMessage(hwndDlg, IDC_BASSVERSION, WM_SETTEXT, 0, (LPARAM)tmp); - - SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_RESETCONTENT, 0, 0); - SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_ADDSTRING, 0, (LPARAM)TranslateT("--default device--")); - SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_SETCURSEL, 0, 0); - DBGetContactSettingString(NULL, ModuleName, OPT_OUTDEVICE, &dbv); - for (i=1; BASS_GetDeviceInfo(i+newBass, &info); i++) - { - SendDlgItemMessageA(hwndDlg, IDC_OUTDEVICE, CB_ADDSTRING, 0, (LPARAM)info.name); - if (!lstrcmpA(dbv.pszVal, info.name)) - SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_SETCURSEL, i, 0); - } - DBFreeVariant(&dbv); - } - - return 1; - } - - case WM_HSCROLL: - if (hBass != NULL) - if (LOWORD(wParam) == SB_ENDSCROLL || LOWORD(wParam) == SB_THUMBTRACK) - { - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_GETPOS, 0, 0) * 100); - Preview = TRUE; - if (EnPreview) SkinPlaySound("AlertMsg"); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - break; - - case WM_NOTIFY: - switch(((LPNMHDR)lParam)->code) - { - case PSN_APPLY: - if (hBass != NULL) - { - int i; SYSTEMTIME systime; - - SendDlgItemMessageA(hwndDlg, IDC_OUTDEVICE, WM_GETTEXT, sizeof(tmp), (LPARAM)tmp); - DBWriteContactSettingString(NULL, ModuleName, OPT_OUTDEVICE, (char *)tmp); - - Volume = (DWORD)SendDlgItemMessage(hwndDlg, IDC_VOLUME, TBM_GETPOS, 0, 0); - DBWriteContactSettingByte(NULL, ModuleName, OPT_VOLUME, Volume); - - sndLimSnd = SendDlgItemMessage(hwndDlg, IDC_MAXCHANNEL, CB_GETCURSEL, 0, 0) + 1; - if ( sndLimSnd > MAXCHAN ) sndLimSnd = MAXCHAN; - DBWriteContactSettingByte(NULL, ModuleName, OPT_MAXCHAN, sndLimSnd); - - QuietTime = IsDlgButtonChecked(hwndDlg, IDC_QUIETTIME) == BST_CHECKED; - DBWriteContactSettingByte(NULL, ModuleName, OPT_QUIETTIME, QuietTime); - - SendDlgItemMessage(hwndDlg, IDC_TIME1, DTM_GETSYSTEMTIME, 0, (LPARAM)&systime); - TimeWrd1 = MAKEWORD(systime.wMinute, systime.wHour); - DBWriteContactSettingWord(NULL, ModuleName, OPT_TIME1, TimeWrd1); - - SendDlgItemMessage(hwndDlg, IDC_TIME2, DTM_GETSYSTEMTIME, 0, (LPARAM)&systime); - TimeWrd2 = MAKEWORD(systime.wMinute, systime.wHour); - DBWriteContactSettingWord(NULL, ModuleName, OPT_TIME2, TimeWrd2); - - EnPreview = IsDlgButtonChecked(hwndDlg, IDC_PREVIEW) == BST_CHECKED; - DBWriteContactSettingByte(NULL, ModuleName, OPT_PREVIEW, EnPreview); - - StatMask = 0; - for(i = IDC_CHECKBOX10; i > IDC_CHECKBOX1-1; i--) - { - StatMask <<= 1; - if(IsDlgButtonChecked(hwndDlg, i) == BST_CHECKED) - StatMask |= 1; - } - - DBWriteContactSettingWord(NULL, ModuleName, OPT_STATUS, StatMask); - - device = SendDlgItemMessage(hwndDlg, IDC_OUTDEVICE, CB_GETCURSEL, 0, 0); - if (device == 0) device = -1; - else device += newBass; - if (CallService(MS_TB_GETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", 0)==TBST_RELEASED) - { - BASS_Free(); - BASS_Init(device, 44100, 0, ClistHWND, NULL); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100 ); - } - } - return 1; - - case PSN_RESET: - if (hBass != NULL) - { - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100); - } - return 1; - - case DTN_DATETIMECHANGE: - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - return 1; - } - break; - - case WM_COMMAND: - switch(LOWORD(wParam)) - { - case IDC_QUIETTIME: - { - BOOL b = IsDlgButtonChecked(hwndDlg, IDC_QUIETTIME) == BST_CHECKED; - EnableWindow(GetDlgItem(hwndDlg,IDC_TIME1), b); - EnableWindow(GetDlgItem(hwndDlg,IDC_TIME2), b); - } - case IDC_MAXCHANNEL: - case IDC_OUTDEVICE: - case IDC_CHECKBOX1: - case IDC_CHECKBOX2: - case IDC_CHECKBOX3: - case IDC_CHECKBOX4: - case IDC_CHECKBOX5: - case IDC_CHECKBOX6: - case IDC_CHECKBOX7: - case IDC_CHECKBOX8: - case IDC_CHECKBOX9: - case IDC_CHECKBOX10: - case IDC_PREVIEW: - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - case IDC_GETBASS: - CallService(MS_UTILS_OPENURL , 1, (LPARAM)"http://www.un4seen.com/"); - break; - } - break; - - //case WM_CLOSE: - // EndDialog(hwndDlg, 0); - } - return 0; -} - -struct -{ - char* szDescr; - char* szName; - int defIconID; -} -static const iconList[] = -{ - { "Audio device is opened", "BASSSoundOnOffUp", IDI_BASSSoundOnOffUp }, - { "Audio device is closed", "BASSSoundOnOffDown", IDI_BASSSoundOnOffDown } -}; - -static HANDLE hIconLibItem[SIZEOF(iconList)]; - -void InitIcons(void) -{ - int i; char szSettingName[100]; SKINICONDESC sid = {0}; TCHAR szFile[MAX_PATH]; - - GetModuleFileName(hInst, szFile, SIZEOF(szFile)); - - sid.cbSize = sizeof(SKINICONDESC); - sid.ptszDefaultFile = szFile; - sid.cx = sid.cy = 16; - sid.pszName = szSettingName; - sid.pszSection = ModuleName; - sid.flags = SIDF_PATH_TCHAR; - - for (i = 0; i < SIZEOF(iconList); i++) - { - mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", ModuleName, iconList[i].szName); - - sid.pszDescription = (char*)iconList[i].szDescr; - sid.iDefaultIndex = -iconList[i].defIconID; - hIconLibItem[i] = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); - } -} - -int OptionsInit(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = {0}; - - odp.cbSize = sizeof(odp); - odp.position = 0; - odp.hInstance = hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); - odp.ptszTitle = _T(ModuleName); - odp.pfnDlgProc = OptionsProc; - odp.ptszGroup = _T("Customize"); - odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR; - - CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); - return 0; -} - -INT_PTR BASSSoundOnOff(WPARAM wParam, LPARAM lParam) -{ - if (hBass != NULL) - { - BOOL opened = CallService(MS_TB_GETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", 0) == TBST_RELEASED; - - if ( opened ) - { - BASS_Free(); // Close Device - } - else - { - BASS_Init(device, 44100, 0, ClistHWND, NULL); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100 ); - } - - CallService(MS_TB_SETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", opened ? TBST_PUSHED : TBST_RELEASED); - DBWriteContactSettingByte(NULL, ModuleName, OPT_DEVOPEN, !opened); - } - return 0; -} - -int OnToolbarLoaded(WPARAM wParam, LPARAM lParam) -{ - TBButton tbb = {0}; - tbb.cbSize = sizeof(TBButton); - tbb.pszButtonID = "BASSSoundOnOff"; - tbb.pszButtonName = Translate("Open/close audio device"); - tbb.pszServiceName = "BASSinterface/BASSSoundOnOff"; - tbb.pszTooltipUp = Translate("Audio device is opened"); - tbb.pszTooltipDn = Translate("Audio device is closed"); - tbb.hPrimaryIconHandle = hIconLibItem[0]; - tbb.hSecondaryIconHandle = hIconLibItem[1]; - tbb.tbbFlags = TBBF_SHOWTOOLTIP; - tbb.defPos = 1000; - - CallService(MS_TB_ADDBUTTON, 0, (LPARAM)&tbb); - - return 0; -} - -int OnModulesLoaded(WPARAM wParam, LPARAM lParam) -{ - DBVARIANT dbv = {0}; - - if (DBGetContactSettingTString(NULL, ModuleName, OPT_BASSPATH, &dbv)) - { - DBWriteContactSettingTString(NULL, ModuleName, OPT_BASSPATH, _T("Plugins\\Bass\\Bass.dll")); - lstrcpy(tmp, _T("Plugins\\Bass\\Bass.dll")); - } - else - { - lstrcpy(tmp, dbv.ptszVal); - } - - DBFreeVariant(&dbv); - - CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)tmp, (LPARAM)CurrBassPath); - hBass = LoadLibrary(CurrBassPath); - - if (hBass != NULL) - { - if (LOADBASSFUNCTION(BASS_Init) != NULL && LOADBASSFUNCTION(BASS_SetConfig) != NULL && - LOADBASSFUNCTION(BASS_ChannelPlay) != NULL && LOADBASSFUNCTION(BASS_StreamCreateFile) != NULL && - LOADBASSFUNCTION(BASS_GetVersion) != NULL && LOADBASSFUNCTION(BASS_StreamFree) != NULL && - LOADBASSFUNCTION(BASS_GetDeviceInfo) != NULL && LOADBASSFUNCTION(BASS_Free)) - { - int i; BASS_DEVICEINFO info; - - newBass = (BASS_SetConfig(BASS_CONFIG_DEV_DEFAULT, TRUE) != 0); // will use new "Default" device - - if (!DBGetContactSettingString(NULL, ModuleName, OPT_OUTDEVICE, &dbv)) - { - for (i=1; BASS_GetDeviceInfo(i, &info); i++) - if (!lstrcmpA(dbv.pszVal, info.name)) - device = i; - } - DBFreeVariant(&dbv); - - sndLimSnd = DBGetContactSettingByte(NULL, ModuleName, OPT_MAXCHAN, MAXCHAN); - if ( sndLimSnd > MAXCHAN ) sndLimSnd = MAXCHAN; - TimeWrd1 = DBGetContactSettingWord(NULL, ModuleName, OPT_TIME1, 0); - TimeWrd2 = DBGetContactSettingWord(NULL, ModuleName, OPT_TIME2, 0); - QuietTime = DBGetContactSettingByte(NULL, ModuleName, OPT_QUIETTIME, 0); - EnPreview = DBGetContactSettingByte(NULL, ModuleName, OPT_PREVIEW, 0); - - StatMask = DBGetContactSettingWord(NULL, ModuleName, OPT_STATUS, 0x3ff); - - ClistHWND = (HWND)CallService("CLUI/GetHwnd", 0, 0); - if (DBGetContactSettingByte(NULL, ModuleName, OPT_DEVOPEN, 1)) - BASS_Init(device, 44100, 0, ClistHWND, NULL); - else - CallService(MS_TB_SETBUTTONSTATEBYID, (WPARAM)"BASSSoundOnOff", TBST_PUSHED); - - Volume = DBGetContactSettingByte(NULL, ModuleName, OPT_VOLUME, 33); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume * 100 ); - hHooks[3] = HookEvent(ME_SKIN_PLAYINGSOUND, OnPlaySnd); - } - else - { - FreeLibrary(hBass); - hBass = NULL; - } - } - - hHooks[4] = HookEvent(ME_OPT_INITIALISE, OptionsInit); - - return 0; -} - -int OnShutdown(WPARAM wParam, LPARAM lParam) -{ - if(hBass != NULL) - { - BASS_Free(); - FreeLibrary(hBass); - } - - return 0; -} - -extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) -{ - pluginLink = link; - mir_getLP(&pluginInfo); - mir_getMMI(&mmi); - - hHooks[0] = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); - hHooks[1] = HookEvent(ME_SYSTEM_SHUTDOWN, OnShutdown); - hHooks[2] = HookEvent(ME_TB_MODULELOADED, OnToolbarLoaded); - - hService = CreateServiceFunction("BASSinterface/BASSSoundOnOff", BASSSoundOnOff); - - InitIcons(); - - return 0; -} - -extern "C" int __declspec(dllexport) Unload(void) -{ - int i; - for (i = 0; i < SIZEOF(hHooks); i++) - { - if (hHooks[i]) - UnhookEvent(hHooks[i]); - } - - DestroyServiceFunction(hService); - - return 0; -} \ No newline at end of file diff --git a/plugins/Bass_interface/Resource.h b/plugins/Bass_interface/Resource.h deleted file mode 100644 index fb35fa7855..0000000000 --- a/plugins/Bass_interface/Resource.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef IDC_STATIC -#define IDC_STATIC (-1) -#endif - -#define IDD_OPTIONS 101 -#define IDC_BASSVERSION 1000 -#define IDC_VOLUMELABEL 1001 -#define IDC_CURRPATHLABEL 1002 -#define IDC_OUTDEVICELABEL 1004 -#define IDC_OUTDEVICE 1005 -#define IDC_QUIETTIME 1008 -#define IDC_CURRPATH 1009 -#define IDC_MAXCHANNELLABEL 1010 -#define IDC_MAXCHANNEL 1011 -#define IDC_VOLUME 1012 -#define IDC_GETBASS 1013 -#define IDC_TIME1 1014 -#define IDC_TIME2 1015 -#define IDC_CHECKBOX1 1100 -#define IDC_CHECKBOX2 1101 -#define IDC_CHECKBOX3 1102 -#define IDC_CHECKBOX4 1103 -#define IDC_CHECKBOX5 1104 -#define IDC_CHECKBOX6 1105 -#define IDC_CHECKBOX7 1106 -#define IDC_CHECKBOX8 1107 -#define IDC_CHECKBOX9 1108 -#define IDC_CHECKBOX10 1109 -#define IDC_PREVIEW 1110 -#define IDI_BASSSoundOnOffUp 200 -#define IDI_BASSSoundOnOffDown 201 diff --git a/plugins/Bass_interface/Version.h b/plugins/Bass_interface/Version.h deleted file mode 100644 index 814a8951dd..0000000000 --- a/plugins/Bass_interface/Version.h +++ /dev/null @@ -1,28 +0,0 @@ -#define __MAJOR_VERSION 0 -#define __MINOR_VERSION 0 -#define __RELEASE_NUM 0 -#define __BUILD_NUM 13 - -#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM -#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM - -#define __STRINGIFY_IMPL(x) #x -#define __STRINGIFY(x) __STRINGIFY_IMPL(x) -#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS) - -#ifdef _UNICODE -#if defined(WIN64) || defined(_WIN64) - #define __PLUGIN_NAME "Bass_interface (Unicode x64)" -#else - #define __PLUGIN_NAME "Bass_interface (Unicode)" -#endif -#else - #define __PLUGIN_NAME "Bass_interface" -#endif -#define __INTERNAL_NAME "Bass_interface" -#define __FILENAME "Bass_interface.dll" -#define __DESCRIPTION "un4seen's bass interface Miranda IM plugin." -#define __AUTHOR "tico-tico" -#define __AUTHOREMAIL "" -#define __AUTHORWEB "" -#define __COPYRIGHT "© 2010, 2011 tico-tico" diff --git a/plugins/Bass_interface/Version.rc b/plugins/Bass_interface/Version.rc deleted file mode 100644 index e637f0cb33..0000000000 --- a/plugins/Bass_interface/Version.rc +++ /dev/null @@ -1,38 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "afxres.h" -#include "version.h" - -#ifdef _WIN32 -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#endif //_WIN32 - -VS_VERSION_INFO VERSIONINFO - FILEVERSION __FILEVERSION_STRING - PRODUCTVERSION __FILEVERSION_STRING - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x0L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "FileDescription", __DESCRIPTION - VALUE "InternalName", __PLUGIN_NAME - VALUE "LegalCopyright", __COPYRIGHT - VALUE "OriginalFilename", __FILENAME - VALUE "ProductName", __PLUGIN_NAME - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END diff --git a/plugins/Bass_interface/res/BASSSoundOnOffDown.ico b/plugins/Bass_interface/res/BASSSoundOnOffDown.ico deleted file mode 100644 index a10bfce204..0000000000 Binary files a/plugins/Bass_interface/res/BASSSoundOnOffDown.ico and /dev/null differ diff --git a/plugins/Bass_interface/res/BASSSoundOnOffUp.ico b/plugins/Bass_interface/res/BASSSoundOnOffUp.ico deleted file mode 100644 index bee9f065a0..0000000000 Binary files a/plugins/Bass_interface/res/BASSSoundOnOffUp.ico and /dev/null differ diff --git a/plugins/BossKeyPlus/BossKey_10.vcxproj b/plugins/BossKeyPlus/BossKey_10.vcxproj index 4a151c5848..d0be9fe273 100644 --- a/plugins/BossKeyPlus/BossKey_10.vcxproj +++ b/plugins/BossKeyPlus/BossKey_10.vcxproj @@ -26,23 +26,21 @@ DynamicLibrary - false Unicode DynamicLibrary - false Unicode + true DynamicLibrary - false Unicode DynamicLibrary - false Unicode + true @@ -72,7 +70,6 @@ $(SolutionDir)$(Configuration)/Obj/$(ProjectName)\ $(SolutionDir)$(Configuration)64/Plugins\ $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ - false $(SolutionDir)$(Configuration)64/Plugins\ $(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\ AllRules.ruleset @@ -87,6 +84,10 @@ AllRules.ruleset + true + true + true + true @@ -100,37 +101,27 @@ Full - Default Size - true ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;BossKey_EXPORTS;%(PreprocessorDefinitions) true MultiThreadedDLL true - - Level3 - - NDEBUG;%(PreprocessorDefinitions) + ../../include/msapi comctl32.lib;%(AdditionalDependencies) - ../../lib;%(AdditionalLibraryDirectories) 0x32270000 false - - $(IntDir)$(TargetName).lib - MachineX86 - $(TargetDir)$(TargetName).pdb - UseLinkTimeCodeGeneration true true true + Windows @@ -148,28 +139,21 @@ ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;BossKey_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks - MultiThreadedDebug - - - - + MultiThreadedDebugDLL Level3 EditAndContinue - - _DEBUG;%(PreprocessorDefinitions) + ../../include/msapi comctl32.lib;%(AdditionalDependencies) true false - - $(IntDir)$(TargetName).lib - MachineX86 - $(TargetDir)$(TargetName).pdb + Windows + 0x32270000 @@ -184,47 +168,29 @@ Full - Default Size ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - _WIN64;%(PreprocessorDefinitions) + WIN64;NDEBUG;_WINDOWS;_USRDLL;BossKey_EXPORTS;%(PreprocessorDefinitions) true MultiThreadedDLL true - - - $(IntDir)$(ProjectName).pch - $(IntDir) - $(IntDir) - $(IntDir)vc70.pdb Level3 - true - true NDEBUG;%(PreprocessorDefinitions) - 0x0000 + ../../include/msapi comctl32.lib;%(AdditionalDependencies) - $(OutDir)$(ProjectName).dll - true - ../../lib;%(AdditionalLibraryDirectories) - false true - $(TargetDir)$(TargetName).pdb - false 0x32270000 false - - $(IntDir)$(TargetName).lib - MachineX64 true true - UseLinkTimeCodeGeneration + Windows @@ -240,35 +206,22 @@ Disabled ../../include;../ExternalAPI;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;BossKey_EXPORTS;%(PreprocessorDefinitions) + WIN64;_DEBUG;_WINDOWS;_USRDLL;BossKey_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks - MultiThreadedDebug - - - $(IntDir)$(ProjectName).pch - - - $(IntDir) - $(IntDir)vc70.pdb + MultiThreadedDebugDLL Level3 - true - ProgramDatabase _DEBUG;%(PreprocessorDefinitions) - 0x0419 + ../../include/msapi comctl32.lib;%(AdditionalDependencies) - $(OutDir)$(ProjectName).dll - true true - $(TargetDir)$(TargetName).pdb false - - $(IntDir)$(TargetName).lib - MachineX64 + 0x32270000 + Windows -- cgit v1.2.3