aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Library/ml_disc/main.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Library/ml_disc/main.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Library/ml_disc/main.cpp')
-rw-r--r--Src/Plugins/Library/ml_disc/main.cpp1273
1 files changed, 1273 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_disc/main.cpp b/Src/Plugins/Library/ml_disc/main.cpp
new file mode 100644
index 00000000..6f39f2f3
--- /dev/null
+++ b/Src/Plugins/Library/ml_disc/main.cpp
@@ -0,0 +1,1273 @@
+#include "Main.h"
+#include "ReplayGain.h"
+#include "../nu/AutoChar.h"
+#include "../nu/MediaLibraryInterface.h"
+#include "./resource.h"
+#include "./settings.h"
+#include "./copyfiles.h"
+#include "../winamp/wa_ipc.h"
+//#include <primosdk.h>
+#include <shlwapi.h>
+#include <imapi.h>
+#include <imapierror.h>
+#include "../nu/ns_wc.h"
+#include <vector>
+#include <strsafe.h>
+
+#define VERSION_MAJOR 2
+#define VERSION_MINOR 0
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(x) (sizeof(x)/sizeof(*x))
+#endif
+
+typedef struct _LISTENER
+{
+ HWND hwnd;
+ UINT uMsg;
+ CHAR cLetter;
+} LISTENER;
+
+typedef struct _NAVITEMENUMPARAM
+{
+ NAVITEMENUMPROC callback;
+ LPARAM param;
+} NAVITEMENUMPARAM;
+
+typedef enum _BTNSTATE
+{
+ BTNSTATE_NORMAL = 0,
+ BTNSTATE_HILITED = 1,
+ BTNSTATE_PRESSED = 2,
+ BTNSTATE_DISABLED = 3,
+} BTNSTATE;
+
+#define ICON_SIZE_CX 14
+#define ICON_SIZE_CY 14
+
+#define NAVBUTTON_STATECHECK_DELAY 100
+static int Init();
+static void Quit();
+
+HNAVITEM hniMain = NULL;
+static LRESULT delay_ml_startup;
+static HMLIMGLST hmlilIcons = NULL;
+LARGE_INTEGER freq;
+
+#define NAVITEM_PREFIX L"_ml_disc_"
+#define NAVITEM_PREFIX_SIZE (sizeof(NAVITEM_PREFIX)/sizeof(wchar_t))
+
+#define NCS_EX_SHOWEJECT 0x0100
+
+C_Config *g_config, *g_view_metaconf = NULL;
+HMENU g_context_menus;
+
+prefsDlgRecW myPrefsItemCD = {0};
+INT_PTR imgIndex = 0;
+wchar_t randb[64] = {0};
+static wchar_t cdrip[64];
+
+static DWORD g_navStyle = NCS_FULLROWSELECT | NCS_SHOWICONS;
+static DWORD riphash = 0;
+
+static std::vector<LPARAM> driveList;
+
+static LISTENER activeListener = { NULL, 0, };
+static WNDPROC oldWinampWndProc = NULL;
+
+api_application *WASABI_API_APP = 0;
+api_stats *AGAVE_API_STATS = 0;
+
+// wasabi based services for localisation support
+api_language *WASABI_API_LNG = 0;
+HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
+
+static UINT uMsgBurnerNotify = 0;
+static UINT uMsgRipperNotify = 0;
+static UINT uMsgNavStyleUpdate = 0;
+static UINT uMsgCopyNotify = 0;
+
+static void CALLBACK Invoke_OnDriveManagerNotify(WORD wCode, INT_PTR param);
+static void Plugin_OnMLVisible(BOOL bVisible);
+void ShowHideRipBurnParent(void);
+
+
+
+static void DriveParam_RegisterDrive(DRIVE *drive)
+{
+ LPARAM param;
+ size_t index;
+
+ param = (LPARAM)drive;
+ if (NULL == param)
+ return;
+
+ index = driveList.size();
+ while(index--)
+ {
+ if(param == driveList[index])
+ return;
+ }
+
+ driveList.push_back(param);
+}
+
+static void DriveParam_UnregisterDrive(DRIVE *drive)
+{
+ LPARAM param;
+ size_t index;
+
+ param = (LPARAM)drive;
+ if (NULL == param)
+ return;
+
+ index = driveList.size();
+ while(index--)
+ {
+ if(param == driveList[index])
+ {
+ driveList.erase(driveList.begin() + index);
+ return;
+ }
+ }
+}
+
+static BOOL DriveParam_IsValid(LPARAM param)
+{
+ if (param > 0x0000FFFF)
+ {
+ size_t index = driveList.size();
+ while(index--)
+ {
+ if(param == driveList[index])
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+DRIVE *Plugin_GetDriveFromNavItem(HNAVITEM hItem)
+{
+ NAVITEM item;
+
+ if (!hItem) return NULL;
+
+ item.cbSize = sizeof(NAVITEM);
+ item.mask = NIMF_PARAM;
+ item.hItem = hItem;
+
+ return (MLNavItem_GetInfo(plugin.hwndLibraryParent, &item) && DriveParam_IsValid(item.lParam)) ?
+ (DRIVE*)item.lParam : NULL;
+}
+
+HNAVITEM Plugin_GetNavItemFromLetter(CHAR cLetter)
+{
+ NAVCTRLFINDPARAMS fp = {0};
+ wchar_t invariant[32] = {0};
+
+ if (S_OK == StringCchPrintfW(invariant, sizeof(invariant)/sizeof(wchar_t), L"%s%c", NAVITEM_PREFIX, cLetter))
+ {
+ fp.cchLength = -1;
+ fp.pszName = invariant;
+ fp.compFlags = NICF_INVARIANT;
+
+ return MLNavCtrl_FindItemByName(plugin.hwndLibraryParent, &fp);
+ }
+ return NULL;
+}
+
+static BOOL CALLBACK EnumerateNavItemsCB(HNAVITEM hItem, LPARAM param)
+{
+ DRIVE *pDrive = Plugin_GetDriveFromNavItem(hItem);
+ return (pDrive) ? ((NAVITEMENUMPARAM*)param)->callback(hItem, pDrive, ((NAVITEMENUMPARAM*)param)->param) : TRUE;
+}
+
+BOOL Plugin_EnumerateNavItems(NAVITEMENUMPROC callback, LPARAM param)
+{
+ NAVITEMENUMPARAM pluginenum;
+ NAVCTRLENUMPARAMS navenum;
+ if (!callback) return FALSE;
+
+ pluginenum.callback = callback;
+ pluginenum.param = param;
+
+ navenum.hItemStart = hniMain;
+ navenum.lParam = (LPARAM)&pluginenum;
+ navenum.enumProc = EnumerateNavItemsCB;
+
+ return MLNavCtrl_EnumItems(plugin.hwndLibraryParent, &navenum);
+}
+
+void Plugin_RegisterListener(HWND hwnd, UINT uMsg, CHAR cLetter)
+{
+ activeListener.hwnd = hwnd;
+ activeListener.uMsg = uMsg;
+ activeListener.cLetter = cLetter;
+}
+
+void Plugin_UnregisterListener(HWND hwnd)
+{
+ ZeroMemory(&activeListener, sizeof(LISTENER));
+}
+
+static BOOL CALLBACK EnumNavItems_OnUIChangeCB(HNAVITEM hItem, DRIVE *pDrive, LPARAM param)
+{
+ if (pDrive) pDrive->textSize = 0;
+ return TRUE;
+}
+
+static void UpdatedNavStyles(void)
+{
+ g_navStyle = MLNavCtrl_GetStyle(plugin.hwndLibraryParent);
+ if (0 != g_view_metaconf->ReadInt(TEXT("showeject"), 1)) g_navStyle |= NCS_EX_SHOWEJECT;
+}
+
+static BOOL CALLBACK EnumerateNavItemsRemoveCB(HNAVITEM hItem, DRIVE *pDrive, LPARAM param)
+{
+ if(pDrive)
+ {
+ MLNavCtrl_DeleteItem(plugin.hwndLibraryParent,hItem);
+ Plugin_EnumerateNavItems(EnumerateNavItemsRemoveCB, 0);
+ }
+ return TRUE;
+}
+
+static BOOL Plugin_QueryOkToQuit()
+{
+ CHAR szLetters[24] = {0};
+ INT c = DriveManager_GetDriveList(szLetters, ARRAYSIZE(szLetters));
+ while(c-- > 0)
+ {
+ INT msgId;
+ if (cdrip_isextracting(szLetters[c])) msgId = IDS_YOU_ARE_CURRENTLY_RIPPING_AUDIO_CD_MUST_CANCEL_TO_CLOSE_WINAMP;
+ else if (MLDisc_IsDiscCopying(szLetters[c])) msgId = IDS_YOU_ARE_CURRENTLY_COPYING_DATA_CD_MUST_CANCEL_TO_CLOSE_WINAMP;
+ else msgId = 0;
+ if (msgId)
+ {
+ wchar_t buffer[512] = {0};
+ StringCchPrintfW(buffer, 512, WASABI_API_LNGSTRINGW(msgId), szLetters[c]);
+ MessageBoxW(plugin.hwndWinampParent, buffer, WASABI_API_LNGSTRINGW(IDS_NOTIFICATION),
+ MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+LRESULT CALLBACK WinampWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if(uMsgNavStyleUpdate == uMsg)
+ {
+ if(!wParam)
+ {
+ UpdatedNavStyles();
+ Plugin_EnumerateNavItems(EnumNavItems_OnUIChangeCB, 0);
+ }
+ else
+ {
+ Plugin_EnumerateNavItems(EnumerateNavItemsRemoveCB, 0);
+ ShowHideRipBurnParent();
+ DriveManager_Uninitialize(0);
+ DriveManager_Initialize(Invoke_OnDriveManagerNotify, TRUE);
+ Plugin_OnMLVisible((BOOL)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_IS_VISIBLE, 0));
+ }
+ }
+ else if (uMsgBurnerNotify == uMsg) // burner broadcast message LOWORD(wParam) = drive letter, lParam = (BOOL)bStarted. if bStarted = TRUE - burning started, otherwise burning finished
+ {
+ if (0 == HIWORD(wParam))
+ {
+ DriveManager_SetDriveMode((CHAR)LOWORD(wParam), (0 != lParam) ? DM_MODE_BURNING : DM_MODE_READY);
+ }
+ }
+ else if (uMsgRipperNotify == uMsg)
+ {
+ if (HIWORD(wParam)) // another instance of winamp quering
+ {
+ if (LOWORD(wParam) && cdrip_isextracting((CHAR)LOWORD(wParam))) SendNotifyMessage((HWND)lParam, uMsgRipperNotify, LOWORD(wParam), (LPARAM)TRUE);
+ else
+ {
+ CHAR cLetter;
+ cLetter = (CHAR)cdrip_isextracting(-1);
+ if (cLetter) SendNotifyMessage((HWND)lParam, uMsgRipperNotify, cLetter, (LPARAM)TRUE);
+ }
+ }
+ else
+ {
+ DriveManager_SetDriveMode((CHAR)LOWORD(wParam), (0 != lParam) ? DM_MODE_RIPPING : DM_MODE_READY);
+ }
+ }
+ else if (uMsgCopyNotify == uMsg)
+ {
+ if (HIWORD(wParam))
+ {
+ if (LOWORD(wParam) && MLDisc_IsDiscCopying((CHAR)LOWORD(wParam))) SendNotifyMessage((HWND)lParam, uMsgCopyNotify, LOWORD(wParam), (LPARAM)TRUE);
+ else
+ {
+ CHAR szLetters[24] = {0};
+ INT c = DriveManager_GetDriveList(szLetters, ARRAYSIZE(szLetters));
+ while(c-- > 0)
+ {
+ if (MLDisc_IsDiscCopying(szLetters[c]))
+ SendNotifyMessage((HWND)lParam, uMsgCopyNotify, szLetters[c], (LPARAM)TRUE);
+ }
+ }
+ }
+ else
+ {
+ DriveManager_SetDriveMode((CHAR)LOWORD(wParam), (0 != lParam) ? DM_MODE_COPYING : DM_MODE_READY);
+ }
+ }
+ else if (WM_WA_IPC == uMsg)
+ {
+ switch(lParam)
+ {
+ case IPC_SKIN_CHANGED:
+ case IPC_CB_RESETFONT:
+ UpdatedNavStyles();
+ Plugin_EnumerateNavItems(EnumNavItems_OnUIChangeCB, 0);
+ break;
+ case IPC_FILE_TAG_MAY_HAVE_UPDATED:
+ case IPC_FILE_TAG_MAY_HAVE_UPDATEDW:
+ if (activeListener.hwnd) SendMessageW(activeListener.hwnd, activeListener.uMsg, (WPARAM)lParam, (LPARAM)wParam);
+ break;
+ }
+ if(lParam == delay_ml_startup)
+ {
+ if(!wParam)
+ {
+ PostMessage(plugin.hwndWinampParent, WM_WA_IPC, 1, delay_ml_startup);
+ }
+ else if(wParam == 1)
+ {
+ // TODO: benski> temp-hack fix for now -- if (SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_IS_VISIBLE, 0))
+ {
+ DriveManager_Initialize(Invoke_OnDriveManagerNotify, TRUE);
+ MLDisc_InitializeCopyData();
+
+ DriveManager_Resume(TRUE);
+ SendNotifyMessage(HWND_BROADCAST, uMsgBurnerNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
+ SendNotifyMessage(HWND_BROADCAST, uMsgRipperNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
+ SendNotifyMessage(HWND_BROADCAST, uMsgCopyNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
+ }
+ }
+ }
+ }
+ return (oldWinampWndProc) ? CallWindowProcW(oldWinampWndProc, hwnd, uMsg, wParam, lParam) : DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static DM_UNITINFO2_PARAM unitinfo;
+static char szDesc[1024];
+static DWORD szTypes[64];
+
+static void CALLBACK FreeParam(DM_NOTIFY_PARAM *phdr)
+{
+ if (!phdr) return;
+ switch(phdr->opCode)
+ {
+ case DMOP_TITLE:
+ if (((DM_TITLE_PARAM*)phdr)->pszTitle) free(((DM_TITLE_PARAM*)phdr)->pszTitle);
+ break;
+ }
+ free(phdr);
+}
+static void RegisterIcons()
+{
+ MLIMAGELISTCREATE mlilCreate;
+ MLIMAGESOURCE mlis;
+ MLIMAGELISTITEM mlilItem;
+
+ if (hmlilIcons) return;
+
+ mlilCreate.cx = ICON_SIZE_CX;
+ mlilCreate.cy = ICON_SIZE_CY;
+ mlilCreate.cInitial = 5;
+ mlilCreate.cGrow = 1;
+ mlilCreate.cCacheSize = 3;
+ mlilCreate.flags = MLILC_COLOR24;
+
+ hmlilIcons = MLImageList_Create(plugin.hwndLibraryParent, &mlilCreate);
+ if (!hmlilIcons) return;
+
+ ZeroMemory(&mlilItem, sizeof(MLIMAGELISTITEM));
+ mlilItem.cbSize = sizeof(MLIMAGELISTITEM);
+ mlilItem.hmlil = hmlilIcons;
+ mlilItem.filterUID = MLIF_FILTER1_UID;
+ mlilItem.pmlImgSource = &mlis;
+
+ ZeroMemory(&mlis, sizeof(MLIMAGESOURCE));
+ mlis.cbSize = sizeof(MLIMAGESOURCE);
+ mlis.type = SRC_TYPE_PNG;
+ mlis.hInst = plugin.hDllInstance;
+
+ mlis.lpszName = MAKEINTRESOURCEW(IDB_NAVITEM_CDROM);
+ MLImageList_Add(plugin.hwndLibraryParent, &mlilItem);
+
+ mlis.lpszName = MAKEINTRESOURCEW(IDB_EJECT_NORMAL);
+ MLImageList_Add(plugin.hwndLibraryParent, &mlilItem);
+
+ mlis.lpszName = MAKEINTRESOURCEW(IDB_EJECT_HILITED);
+ MLImageList_Add(plugin.hwndLibraryParent, &mlilItem);
+
+ mlis.lpszName = MAKEINTRESOURCEW(IDB_EJECT_PRESSED);
+ MLImageList_Add(plugin.hwndLibraryParent, &mlilItem);
+
+ mlis.lpszName = MAKEINTRESOURCEW(IDB_EJECT_DISABLED);
+ MLImageList_Add(plugin.hwndLibraryParent, &mlilItem);
+
+}
+
+
+static BOOL UpdateTitle(CHAR cLetter, LPCWSTR pszTitle)
+{
+ HNAVITEM hItem;
+ NAVITEM item;
+ DRIVE *pDrive;
+
+ hItem = Plugin_GetNavItemFromLetter(cLetter);
+ if (!hItem) return FALSE;
+
+ pDrive = Plugin_GetDriveFromNavItem(hItem);
+ if (!pDrive) return FALSE;
+
+ if (S_OK != StringCchCopyW(pDrive->szTitle, sizeof(pDrive->szTitle)/sizeof(wchar_t), (pszTitle) ? pszTitle : L"")) return FALSE;
+
+ pDrive->textSize = 0;
+
+ item.cbSize = sizeof(NAVITEM);
+ item.mask = NIMF_TEXT;
+ item.hItem = hItem;
+ item.pszText = pDrive->szTitle;
+
+ return MLNavItem_SetInfo(plugin.hwndLibraryParent, &item);
+
+}
+static void QueryTitle(CHAR cLetter)
+{
+ DM_TITLE_PARAM *pdtp;
+
+ pdtp = (DM_TITLE_PARAM*)calloc(4, sizeof(DM_TITLE_PARAM));
+ if (pdtp)
+ {
+ pdtp->header.callback = (INT_PTR)Invoke_OnDriveManagerNotify;
+ pdtp->header.cLetter = cLetter;
+ pdtp->header.uMsg = NULL;
+ pdtp->header.fnFree = FreeParam;
+ pdtp->cchTitle = 256;
+ pdtp->pszTitle = (wchar_t*)calloc(pdtp->cchTitle, sizeof(wchar_t));
+
+ DriveManager_QueryTitle(pdtp);
+ }
+}
+static void Drive_OnAdded(CHAR cLetter)
+{
+ wchar_t szInvariant[32] = {0};
+
+ DRIVE *pDrive;
+ NAVINSERTSTRUCT nis = {0};
+ wchar_t szDriveType[32] = {0}, szDriveCap[64] = {0};
+
+ pDrive = (DRIVE*)calloc(1, sizeof(DRIVE));
+ if (!pDrive) return;
+
+ StringCchPrintfW(szInvariant, sizeof(szInvariant)/sizeof(wchar_t), L"%s%c", NAVITEM_PREFIX, cLetter);
+
+ pDrive->cLetter = cLetter;
+ pDrive->cMode = DriveManager_GetDriveMode(cLetter);
+
+ WASABI_API_LNGSTRINGW_BUF(IDS_CD, szDriveType, sizeof(szDriveType)/sizeof(wchar_t));
+ WASABI_API_LNGSTRINGW_BUF(IDS_DRIVE_CAP, szDriveCap, sizeof(szDriveCap)/sizeof(wchar_t));
+ StringCchPrintfW(pDrive->szTitle, sizeof(pDrive->szTitle)/sizeof(wchar_t), L"%s %s (%C:)", szDriveType, szDriveCap, (WCHAR)cLetter);
+
+ if (NULL == hmlilIcons) RegisterIcons();
+
+ ZeroMemory(&nis, sizeof(NAVINSERTSTRUCT));
+ nis.hParent = hniMain;
+ nis.item.cbSize = sizeof(NAVITEM);
+ nis.item.pszText = pDrive->szTitle;
+ nis.item.pszInvariant = szInvariant;
+ nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_PARAM | NIMF_STYLE;
+ nis.item.style = NIS_CUSTOMDRAW | NIS_WANTSETCURSOR | NIS_WANTHITTEST;
+ nis.item.styleMask = nis.item.style;
+ nis.item.lParam = (LPARAM)pDrive;
+
+ if (NULL != MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis))
+ {
+ DriveParam_RegisterDrive(pDrive);
+ }
+}
+
+static void Drive_OnChanged(CHAR cLetter)
+{
+ QueryTitle(cLetter);
+}
+
+static void Drive_OnRemoved(CHAR cLetter)
+{
+ HNAVITEM hItem;
+ hItem = Plugin_GetNavItemFromLetter(cLetter);
+ if (hItem) MLNavCtrl_DeleteItem(plugin.hwndLibraryParent, hItem);
+ if (riphash && (0xFF & (riphash >> 24)) == (UCHAR)cLetter) riphash = 0;
+}
+
+static void Drive_OnModeChanged(CHAR cLetter, CHAR cMode)
+{
+ HNAVITEM hItem;
+ DRIVE *pDrive;
+
+ hItem = Plugin_GetNavItemFromLetter(cLetter);
+ if (!hItem) return;
+
+ pDrive = Plugin_GetDriveFromNavItem(hItem);
+ if (pDrive)
+ {
+ NAVITEMINAVLIDATE inv;
+
+ pDrive->cMode = cMode;
+
+ inv.fErase = FALSE;
+ inv.hItem = hItem;
+ inv.prc = NULL;
+ MLNavItem_Invalidate(plugin.hwndLibraryParent, &inv);
+ }
+}
+
+static void Medium_OnAdded(CHAR cLetter)
+{
+ if (riphash && (0xFF & (riphash >> 24)) == (UCHAR)cLetter) riphash = 0;
+ QueryTitle(cLetter);
+}
+
+static void Medium_OnRemoved(CHAR cLetter)
+{
+ if (riphash && (0xFF & (riphash >> 24)) == (UCHAR)cLetter) riphash = 0;
+ QueryTitle(cLetter);
+}
+
+static void OnDriveMangerOpCompleted(DM_NOTIFY_PARAM *phdr)
+{
+ switch(phdr->opCode)
+ {
+ case DMOP_TITLE:
+ if (S_OK == phdr->result) UpdateTitle(phdr->cLetter, ((DM_TITLE_PARAM*)phdr)->pszTitle);
+ break;
+ }
+}
+
+static void CALLBACK OnDriveManagerNotify(ULONG_PTR param)
+{
+ WORD code;
+ CHAR cLetter;
+
+ code = LOWORD(param);
+ cLetter = (CHAR)(0xFF & HIWORD(param));
+
+ switch(code)
+ {
+ case DMW_DRIVEADDED: Drive_OnAdded(cLetter); break;
+ case DMW_DRIVEREMOVED: Drive_OnRemoved(cLetter); break;
+ case DMW_DRIVECHANGED: Drive_OnChanged(cLetter); break;
+ case DMW_MEDIUMARRIVED: Medium_OnAdded(cLetter); break;
+ case DMW_MEDIUMREMOVED: Medium_OnRemoved(cLetter); break;
+ case DMW_MODECHANGED: Drive_OnModeChanged(cLetter, ((CHAR)(HIWORD(param)>>8))); break;
+
+ }
+ if (activeListener.hwnd && (0 == activeListener.cLetter || cLetter == activeListener.cLetter))
+ PostMessageW(activeListener.hwnd, activeListener.uMsg, (WPARAM)code, (LPARAM)HIWORD(param));
+}
+
+static void CALLBACK Invoke_OnDriveManagerNotify(WORD wCode, INT_PTR param)
+{
+ switch(wCode)
+ {
+ case DMW_DRIVEADDED:
+ case DMW_DRIVEREMOVED:
+ case DMW_DRIVECHANGED:
+ case DMW_MEDIUMARRIVED:
+ case DMW_MEDIUMREMOVED:
+ case DMW_MODECHANGED:
+ if (GetCurrentThreadId() != GetWindowThreadProcessId(plugin.hwndLibraryParent, NULL))
+ {
+ HANDLE htWA = (WASABI_API_APP) ? WASABI_API_APP->main_getMainThreadHandle() : NULL;
+ if (htWA)
+ {
+ QueueUserAPC(OnDriveManagerNotify, htWA, MAKELONG(wCode, (WORD)(param)));
+ CloseHandle(htWA);
+ }
+ }
+ else OnDriveManagerNotify(MAKELONG(wCode, (WORD)(param)));
+ break;
+ case DMW_OPCOMPLETED: OnDriveMangerOpCompleted((DM_NOTIFY_PARAM*)param); break;
+ }
+}
+
+void ShowHideRipBurnParent(void)
+{
+ BOOL bVal;
+ if (S_OK == Settings_GetBool(C_GLOBAL, GF_SHOWPARENT, &bVal) && bVal)
+ {
+ if(!hniMain)
+ {
+ NAVINSERTSTRUCT nis;
+ ZeroMemory(&nis, sizeof(NAVITEM));
+ nis.item.cbSize = sizeof(NAVITEM);
+ nis.item.pszText = WASABI_API_LNGSTRINGW_BUF(IDS_RIP_AND_BURN, randb,64);
+ nis.item.pszInvariant = NAVITEM_PREFIX L"main";
+ nis.item.mask = NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | NIMF_PARAM;
+ nis.item.style = NIS_HASCHILDREN;
+ nis.item.styleMask = nis.item.style;
+ nis.item.lParam = 0L;
+ hniMain = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
+ }
+ }
+ else
+ {
+ if(hniMain)
+ {
+ MLNavCtrl_DeleteItem(plugin.hwndLibraryParent,hniMain);
+ }
+ hniMain = NULL;
+ }
+}
+
+int Init()
+{
+ QueryPerformanceFrequency(&freq);
+
+ // get the Application service
+ waServiceFactory *sf = plugin.service->service_getServiceByGuid(applicationApiServiceGuid);
+ if (sf) WASABI_API_APP = (api_application *)sf->getInterface();
+
+ // loader so that we can get the localisation service api for use
+ sf = plugin.service->service_getServiceByGuid(languageApiGUID);
+ if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
+
+ sf = plugin.service->service_getServiceByGuid(AnonymousStatsGUID);
+ if (sf) AGAVE_API_STATS = reinterpret_cast<api_stats*>(sf->getInterface());
+
+ // need to have this initialised before we try to do anything with localisation features
+ WASABI_API_START_LANG(plugin.hDllInstance,MlDiscLangGUID);
+
+ mediaLibrary.library = plugin.hwndLibraryParent;
+ mediaLibrary.winamp = plugin.hwndWinampParent;
+ mediaLibrary.instance = plugin.hDllInstance;
+
+ static wchar_t szDescription[256];
+ StringCchPrintf(szDescription, ARRAYSIZE(szDescription),
+ WASABI_API_LNGSTRINGW(IDS_NULLSOFT_RIP_AND_BURN), VERSION_MAJOR, VERSION_MINOR);
+ plugin.description = (char*)szDescription;
+
+ // add to Winamp preferences
+ myPrefsItemCD.dlgID = IDD_PREFSCDRIPFR;
+ myPrefsItemCD.name = WASABI_API_LNGSTRINGW_BUF(IDS_CD_RIPPING,cdrip,64);
+ myPrefsItemCD.proc = (void*)CDRipPrefsProc;
+ myPrefsItemCD.hInst = WASABI_API_LNG_HINST;
+ myPrefsItemCD.where = 6; // media library
+ SENDWAIPC(plugin.hwndWinampParent, IPC_ADD_PREFS_DLGW, (WPARAM)&myPrefsItemCD);
+
+ wchar_t szIniFile[MAX_PATH],
+ *INI_DIR = (wchar_t*)SENDWAIPC(plugin.hwndWinampParent, IPC_GETINIDIRECTORYW, 0);
+
+ PathCombine(szIniFile, INI_DIR, TEXT("Plugins\\gen_ml.ini"));
+ g_config = new C_Config(szIniFile);
+
+ PathCombine(szIniFile, INI_DIR, TEXT("Plugins\\ml\\cdrom.vmd"));
+ g_view_metaconf = new C_Config(szIniFile);
+
+ g_context_menus = WASABI_API_LOADMENU(IDR_CONTEXTMENUS);
+
+ oldWinampWndProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(plugin.hwndWinampParent, GWLP_WNDPROC, (LONG)(LONG_PTR)WinampWndProc);
+
+ if (!uMsgBurnerNotify) uMsgBurnerNotify = RegisterWindowMessageA("WABURNER_BROADCAST_MSG");
+ if (!uMsgRipperNotify) uMsgRipperNotify = RegisterWindowMessageA("WARIPPER_BROADCAST_MSG");
+ if (!uMsgCopyNotify) uMsgCopyNotify = RegisterWindowMessageA("WACOPY_BROADCAST_MSG");
+ if (!uMsgNavStyleUpdate) uMsgNavStyleUpdate = RegisterWindowMessageW(L"ripburn_nav_update");
+
+ UpdatedNavStyles();
+ ShowHideRipBurnParent();
+
+ delay_ml_startup = SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"ml_disc_delay", IPC_REGISTER_WINAMP_IPCMESSAGE);
+ PostMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, delay_ml_startup);
+ return ML_INIT_SUCCESS;
+}
+
+void Quit()
+{
+ DriveManager_Uninitialize(4000); // allow to wait for 4 sec.
+ MLDisc_ReleaseCopyData();
+ delete(g_view_metaconf);
+ g_view_metaconf = 0;
+
+ delete(g_config);
+ g_config = NULL;
+
+ if (rgThread)
+ {
+ QueueUserAPC(QuitThread, rgThread, 0);
+ WaitForSingleObject(rgThread, INFINITE);
+ CloseHandle(rgThread);
+ rgThread = 0;
+ }
+
+ waServiceFactory *sf = plugin.service->service_getServiceByGuid(AnonymousStatsGUID);
+ if (sf) sf->releaseInterface(AGAVE_API_STATS);
+}
+
+int getFileInfo(const char *filename, const char *metadata, char *dest, int len)
+{
+ dest[0] = 0;
+ extendedFileInfoStruct efis = { filename, metadata, dest, len, };
+ return (int)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM) & efis, IPC_GET_EXTENDED_FILE_INFO); //will return 1 if wa2 supports this IPC call
+}
+
+int getFileInfoW(const wchar_t *filename, const wchar_t *metadata, wchar_t *dest, int len)
+{
+ if (dest && len)
+ dest[0] = 0;
+ extendedFileInfoStructW efis = { filename, metadata, dest, len, };
+ return (int)(INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&efis, IPC_GET_EXTENDED_FILE_INFOW); //will return 1 if wa2 supports this IPC call
+}
+
+
+void Plugin_ShowRippingPreferences(void)
+{
+ SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&myPrefsItemCD, IPC_OPENPREFSTOPAGE);
+}
+BOOL Plugin_IsExtractScheduled(CHAR cLetter)
+{
+ BOOL result;
+ if (riphash && (0xFF & (riphash >> 24)) == (UCHAR)cLetter)
+ {
+ DWORD mediumSN;
+ char devname[] = "X:\\";
+ devname[0] = cLetter;
+ result = (GetVolumeInformationA(devname, NULL, 0, &mediumSN, NULL, NULL, NULL, 0) && (0x00FFFFFF & riphash) == mediumSN);
+ riphash = 0;
+ }
+ else result = FALSE;
+ return result;
+}
+
+
+static int Root_OnContextMenu(HNAVITEM hItem, HWND hHost, POINTS pts)
+{
+ HMENU hMenu = GetSubMenu(g_context_menus, 7);
+ if (!hMenu) return 0;
+
+ POINT pt;
+ POINTSTOPOINT(pt, pts);
+ if (-1 == pt.x || -1 == pt.y)
+ {
+ NAVITEMGETRECT itemRect;
+ itemRect.fItem = FALSE;
+ itemRect.hItem = hItem;
+ if (MLNavItem_GetRect(plugin.hwndLibraryParent, &itemRect))
+ {
+ MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
+ pt.x = itemRect.rc.left + 2;
+ pt.y = itemRect.rc.top + 2;
+ }
+ }
+
+ int r = Menu_TrackPopup(plugin.hwndLibraryParent, hMenu,
+ TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_NONOTIFY,
+ pt.x, pt.y, hHost, NULL);
+ switch (r)
+ {
+ case ID_NAVIGATION_PREFERENCES: Plugin_ShowRippingPreferences(); return 1;
+ case ID_NAVIGATION_HELP: SENDWAIPC(plugin.hwndWinampParent, IPC_OPEN_URL, L"https://help.winamp.com/hc/articles/8111574760468-CD-Ripping-with-Winamp"); return 1;
+ break;
+ }
+ return 0;
+}
+
+static int Plugin_OnContextMenu(HNAVITEM hItem, HWND hHost, POINTS pts, CHAR cLetter)
+{
+ HMENU hMenu = GetSubMenu(g_context_menus, 2);
+ if (!hMenu) return 0;
+
+ MENUITEMINFO mii = { sizeof(MENUITEMINFO), };
+ mii.fMask = MIIM_STATE;
+ if (GetMenuItemInfo(hMenu, ID_CDROMMENU_EJECTCD, FALSE, &mii))
+ {
+ mii.fState &= ~(MFS_ENABLED | MFS_DISABLED);
+ mii.fState |= ((DM_MODE_READY == DriveManager_GetDriveMode(cLetter)) ? MFS_ENABLED : MFS_DISABLED);
+ SetMenuItemInfo(hMenu, ID_CDROMMENU_EJECTCD, FALSE, &mii);
+ }
+
+ POINT pt;
+ POINTSTOPOINT(pt, pts);
+ if (-1 == pt.x || -1 == pt.y)
+ {
+ NAVITEMGETRECT itemRect;
+ itemRect.fItem = FALSE;
+ itemRect.hItem = hItem;
+ if (MLNavItem_GetRect(plugin.hwndLibraryParent, &itemRect))
+ {
+ MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
+ pt.x = itemRect.rc.left + 2;
+ pt.y = itemRect.rc.top + 2;
+ }
+ }
+
+ int r = Menu_TrackPopup(plugin.hwndLibraryParent, hMenu,
+ TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_NONOTIFY,
+ pt.x, pt.y, hHost, NULL);
+ switch (r)
+ {
+ case ID_CDROMMENU_EXTRACT_CONFIGURE: Plugin_ShowRippingPreferences(); return 1;
+ case ID_CDROMMENU_EXTRACT_HELP: SENDWAIPC(plugin.hwndWinampParent, IPC_OPEN_URL, L"https://help.winamp.com/hc/articles/8111574760468-CD-Ripping-with-Winamp"); return 1;
+ case ID_CDROMMENU_PLAYALL:
+ case ID_CDROMMENU_ENQUEUEALL:
+ {
+ int enq = r == ID_CDROMMENU_ENQUEUEALL;
+ itemRecordList obj = {0, };
+ saveCDToItemRecordList(cLetter, &obj, NULL);
+ mlSendToWinampStruct p;
+ p.type = ML_TYPE_CDTRACKS;
+ p.enqueue = enq | 2;
+ p.data = &obj;
+ SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_SENDTOWINAMP, (WPARAM)&p);
+ freeRecordList(&obj);
+ }
+ break;
+ case ID_CDROMMENU_EXTRACT_EXTRACTALL:
+ riphash = 0;
+ if (hItem)
+ {
+ if (hItem == MLNavCtrl_GetSelection(plugin.hwndLibraryParent))
+ {
+ HWND hwnd = (HWND)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_GETCURRENTVIEW, 0);
+ if (hwnd && SendMessageW(hwnd, WM_EXTRACTDISC, cLetter, 0)) break;
+ }
+
+ char devname[] = "X:\\";
+ devname[0] = cLetter;
+ if (!GetVolumeInformationA(devname, NULL, 0, &riphash, NULL, NULL, NULL, 0)) riphash = 0;
+ if (riphash) riphash = ((0x00FFFFFF & riphash) | (cLetter << 24));
+ MLNavItem_Select(plugin.hwndLibraryParent, hItem);
+ }
+ break;
+ case ID_CDROMMENU_EJECTCD:
+ {
+ CHAR cMode;
+ cMode = DriveManager_GetDriveMode(cLetter);
+ if (DM_MODE_READY != cMode)
+ {
+ wchar_t title[32] = {0};
+ MessageBox(plugin.hwndLibraryParent,
+ WASABI_API_LNGSTRINGW((DM_MODE_RIPPING == cMode) ? IDS_ERROR_CD_RIP_IN_PROGRESS : IDS_ERROR_CD_BURN_IN_PROGRESS),
+ WASABI_API_LNGSTRINGW_BUF(IDS_CD_EJECT,title,32), 0);
+ return FALSE;
+ }
+ else DriveManager_Eject(cLetter, DM_EJECT_REMOVE);
+ }
+ break;
+ }
+ Sleep(100);
+ MSG msg;
+ while (PeekMessageW(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); //eat return
+ return 0;
+}
+
+static DWORD resumeTick = 0; // this is cheating
+static void Plugin_OnMLVisible(BOOL bVisible)
+{
+ if (bVisible)
+ {
+ DriveManager_Resume(TRUE);
+ resumeTick = GetTickCount();
+ SendNotifyMessage(HWND_BROADCAST, uMsgBurnerNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
+ SendNotifyMessage(HWND_BROADCAST, uMsgRipperNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
+ SendNotifyMessage(HWND_BROADCAST, uMsgCopyNotify, MAKEWPARAM(0, 0xffff), (LPARAM)plugin.hwndWinampParent);
+ return;
+ }
+ else DriveManager_Suspend();
+}
+
+static HWND Plugin_OnViewCreate(HNAVITEM hItem, HWND hwndParent)
+{
+ if (hItem == hniMain)
+ {
+ return WASABI_API_CREATEDIALOGW(IDD_VIEW_RIPBURN, hwndParent, view_ripburnDialogProc);
+ }
+ else
+ {
+ DRIVE *pDrive = Plugin_GetDriveFromNavItem(hItem);
+ if (pDrive) return CreateContainerWindow(hwndParent, pDrive->cLetter, ((GetTickCount() - resumeTick) > 100));
+ resumeTick = 0;
+ }
+ return NULL;
+}
+static BOOL Plugin_OnNavItemDelete(HNAVITEM hItem)
+{
+ DRIVE *pDrive = Plugin_GetDriveFromNavItem(hItem);
+ if (!pDrive) return FALSE;
+ DriveParam_UnregisterDrive(pDrive);
+ free(pDrive);
+ return TRUE;
+}
+
+static BOOL Plugin_OnNavItemClick(HNAVITEM hItem, UINT nAction, HWND hwndParent)
+{
+ return FALSE;
+}
+
+static INT Plugin_OnNavCustomDraw(HNAVITEM hItem, NAVITEMDRAW *pnicd, LPARAM lParam)
+{
+ static INT indent = 0;
+ DRIVE *pDrive;
+
+ if (FALSE == DriveParam_IsValid(lParam))
+ return FALSE;
+
+ pDrive = (DRIVE*)lParam;
+
+ if (0 == indent) indent = MLNavCtrl_GetIndent(plugin.hwndLibraryParent);
+ switch(pnicd->drawStage)
+ {
+ case NIDS_PREPAINT:
+ if (pnicd->prc->bottom > 0 && pnicd->prc->bottom > pnicd->prc->top)
+ {
+ HIMAGELIST himl;
+ INT realIndex, l, t, r;
+ MLIMAGELISTREALINDEX mlilRealIndex;
+
+ himl = MLImageList_GetRealList(plugin.hwndLibraryParent, hmlilIcons);
+
+ mlilRealIndex.cbSize = sizeof(MLIMAGELISTREALINDEX);
+ mlilRealIndex.hmlil = hmlilIcons;
+ mlilRealIndex.rgbBk = GetBkColor(pnicd->hdc);
+ mlilRealIndex.rgbFg = GetTextColor(pnicd->hdc);
+
+ t = pnicd->prc->top + (pnicd->prc->bottom - pnicd->prc->top - ICON_SIZE_CY)/2;
+ l = pnicd->prc->left + (indent*pnicd->iLevel) + 3;
+ r = pnicd->prc->right;
+
+ mlilRealIndex.mlilIndex = 0;
+ realIndex = ((NCS_SHOWICONS & g_navStyle) && himl && l < pnicd->prc->right) ?
+ MLImageList_GetRealIndex(plugin.hwndLibraryParent, &mlilRealIndex) : -1;
+ if (-1 != realIndex) // draw icon
+ {
+ if (ImageList_Draw(himl, realIndex, pnicd->hdc, l, t, ILD_NORMAL))
+ {
+ ExcludeClipRect(pnicd->hdc, l, t, l + ICON_SIZE_CX, t + ICON_SIZE_CY);
+ l += (ICON_SIZE_CX + 5);
+ }
+ }
+
+ pDrive->bEjectVisible = FALSE;
+ mlilRealIndex.mlilIndex = 1 + ((DM_MODE_READY == pDrive->cMode) ? pDrive->nBtnState : BTNSTATE_DISABLED);
+ realIndex = ((NCS_EX_SHOWEJECT & g_navStyle) && himl && (r - l) > (24 + 6 + ICON_SIZE_CX)) ?
+ MLImageList_GetRealIndex(plugin.hwndLibraryParent, &mlilRealIndex) : -1;
+ if (-1 != realIndex)
+ {
+ if (ImageList_Draw(himl, realIndex, pnicd->hdc, r - (ICON_SIZE_CX + 2), t, ILD_NORMAL))
+ {
+ r -= (ICON_SIZE_CX + 2);
+ ExcludeClipRect(pnicd->hdc, r, t, r + ICON_SIZE_CX, t + ICON_SIZE_CY);
+ r -= 4;
+ pDrive->bEjectVisible = TRUE;
+ }
+ }
+
+ if (*pDrive->szTitle && l < r)
+ {
+ RECT rt;
+ INT textH, textW;
+ COLORREF rgbOld(0), rgbBkOld(0);
+
+ if (!pDrive->textSize || (pDrive->textOrigWidth > r-l-3 && pDrive->itemWidth > (pnicd->prc->right - pnicd->prc->left)) ||
+ (LOWORD(pDrive->textSize) != pDrive->textOrigWidth && pDrive->itemWidth < (pnicd->prc->right - pnicd->prc->left)))
+ {
+ NAVITEM item;
+ item.cbSize = sizeof(NAVITEM);
+ item.mask = NIMF_TEXT;
+ item.hItem = hItem;
+ item.cchTextMax = sizeof(pDrive->szTitle)/sizeof(wchar_t);
+ item.pszText = pDrive->szTitle;
+ MLNavItem_GetInfo(plugin.hwndLibraryParent, &item);
+ {
+ if (pDrive->szTitle != item.pszText)
+ {
+ StringCchCopyW(pDrive->szTitle, sizeof(pDrive->szTitle)/sizeof(wchar_t), item.pszText);
+ }
+ if (!pDrive->textSize)
+ {
+ SetRect(&rt, 0, 0, 1, 1);
+ DrawTextW(pnicd->hdc, pDrive->szTitle, -1, &rt, DT_SINGLELINE | DT_CALCRECT);
+ pDrive->textOrigWidth = rt.right - rt.left;
+ }
+ SetRect(&rt, 0, 0, r - l - 3, 1);
+ textH = DrawTextW(pnicd->hdc, pDrive->szTitle, -1, &rt, DT_SINGLELINE|DT_CALCRECT|DT_END_ELLIPSIS|DT_MODIFYSTRING);
+ textW = rt.right - rt.left;
+ pDrive->textSize = (DWORD)MAKELONG(textW, textH);
+ }
+ }
+ else
+ {
+ textW = LOWORD(pDrive->textSize);
+ textH = HIWORD(pDrive->textSize);
+ }
+
+ if (0 == (NCS_FULLROWSELECT & g_navStyle) && ((NIS_SELECTED | NIS_DROPHILITED) & pnicd->itemState))
+ {
+ rgbOld = SetTextColor(pnicd->hdc, pnicd->clrText);
+ rgbBkOld = SetBkColor(pnicd->hdc, pnicd->clrTextBk);
+ }
+
+ if (r > (l + textW + 7)) r = l + textW + 7;
+
+ SetRect(&rt, l, pnicd->prc->top, r, pnicd->prc->bottom);
+
+ t = pnicd->prc->top + (pnicd->prc->bottom - pnicd->prc->top - textH)/2;
+ ExtTextOutW(pnicd->hdc, rt.left + 2, t, ETO_CLIPPED | ETO_OPAQUE, &rt, pDrive->szTitle, lstrlenW(pDrive->szTitle), 0);
+ if (0 == (NCS_FULLROWSELECT & g_navStyle) && (NIS_FOCUSED & pnicd->itemState) &&
+ 0 == (0x1 /*UISF_HIDEFOCUS*/ & (INT)SendMessageW(MLNavCtrl_GetHWND(plugin.hwndLibraryParent), 0x129 /*WM_QUERYUISTATE*/, 0, 0L)))
+ {
+ DrawFocusRect(pnicd->hdc, &rt);
+ }
+ ExcludeClipRect(pnicd->hdc, rt.left, rt.top, rt.right, rt.bottom);
+
+
+ if (0 == (NCS_FULLROWSELECT & g_navStyle) && ((NIS_SELECTED | NIS_DROPHILITED) & pnicd->itemState))
+ {
+ if (rgbOld != pnicd->clrText) SetTextColor(pnicd->hdc, rgbOld);
+ if (rgbBkOld != pnicd->clrTextBk) SetBkColor(pnicd->hdc, rgbBkOld);
+ }
+ }
+
+ pDrive->itemWidth = (WORD)(pnicd->prc->right - pnicd->prc->left);
+
+ if (NCS_FULLROWSELECT & g_navStyle)
+ {
+ ExtTextOutW(pnicd->hdc, 0, 0, ETO_OPAQUE, pnicd->prc, L"", 0, 0);
+ return NICDRF_SKIPDEFAULT;
+ }
+ else ExcludeClipRect(pnicd->hdc, pnicd->prc->left, pnicd->prc->top, pnicd->prc->right, pnicd->prc->bottom);
+ }
+ break;
+ case NIDS_POSTPAINT:
+ break;
+ }
+ return NICDRF_DODEFAULT;
+}
+
+static HNAVITEM hItemActive = NULL;
+
+static BOOL GetEjectBtnRect(HNAVITEM hItem, RECT *prc)
+{
+ NAVITEMGETRECT navRect;
+ navRect.fItem = FALSE;
+ navRect.hItem = hItem;
+
+ if (!hItem || !prc || !MLNavItem_GetRect(plugin.hwndLibraryParent, &navRect)) return FALSE;
+
+ navRect.rc.right -= 2;
+ navRect.rc.left = navRect.rc.right - ICON_SIZE_CX;
+ navRect.rc.top += (navRect.rc.bottom - navRect.rc.top - ICON_SIZE_CY)/2;
+ navRect.rc.bottom = navRect.rc.top + ICON_SIZE_CY;
+
+ CopyRect(prc, &navRect.rc);
+ return TRUE;
+}
+
+static INT_PTR Plugin_OnNavHitTest(HNAVITEM hItem, NAVHITTEST *pnavHitTest, LPARAM lParam)
+{
+ DRIVE *pDrive;
+
+ if (FALSE == DriveParam_IsValid(lParam))
+ return FALSE;
+
+ pDrive = (DRIVE*)lParam;
+
+ if ((NAVHT_ONITEMRIGHT | NAVHT_ONITEM) & pnavHitTest->flags)
+ {
+ RECT rb;
+
+ if (pDrive->bEjectVisible && GetEjectBtnRect(hItem, &rb) &&
+ pnavHitTest->pt.x >= rb.left && pnavHitTest->pt.x <= rb.right &&
+ pnavHitTest->pt.y >= rb.top && pnavHitTest->pt.y <= rb.bottom)
+ {
+ pnavHitTest->flags = NAVHT_NOWHERE;
+ pnavHitTest->hItem = NULL;
+ }
+ }
+ return 1;
+}
+
+static void CALLBACK NavButton_TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ DRIVE *pDrive;
+ POINT pt;
+ RECT rb;
+
+ pDrive = (hItemActive) ? Plugin_GetDriveFromNavItem(hItemActive) : NULL;
+ if (!pDrive || (BYTE)BTNSTATE_NORMAL == pDrive->nBtnState || !pDrive->bEjectVisible || !GetEjectBtnRect(hItemActive, &rb))
+ {
+ KillTimer(NULL, idEvent);
+ return;
+ }
+
+ GetCursorPos(&pt);
+ MapWindowPoints(HWND_DESKTOP, MLNavCtrl_GetHWND(plugin.hwndLibraryParent), &pt, 1);
+
+
+ if (pt.x < rb.left || pt.x > rb.right || pt.y < rb.top || pt.y > rb.bottom)
+ {
+ NAVITEMINAVLIDATE inv;
+
+ KillTimer(NULL, idEvent);
+
+ inv.fErase = FALSE;
+ inv.hItem = hItemActive;
+ inv.prc = &rb;
+
+ hItemActive = NULL;
+ pDrive->nBtnState = BTNSTATE_NORMAL;
+
+ MLNavItem_Invalidate(plugin.hwndLibraryParent, &inv);
+ }
+}
+
+static INT_PTR Plugin_OnNavSetCursor(HNAVITEM hItem, LPARAM lParam)
+{
+ POINT pt;
+ DRIVE *pDrive;
+ BYTE state;
+ RECT rb;
+
+ if (FALSE == DriveParam_IsValid(lParam))
+ return FALSE;
+
+ pDrive = (DRIVE*)lParam;
+
+ if (DM_MODE_READY != pDrive->cMode || !pDrive->bEjectVisible || !GetEjectBtnRect(hItem, &rb)) return -1;
+
+ GetCursorPos(&pt);
+
+ MapWindowPoints(HWND_DESKTOP, MLNavCtrl_GetHWND(plugin.hwndLibraryParent), &pt, 1);
+ if (pt.x >= rb.left && pt.x <= rb.right && pt.y >= rb.top && pt.y <= rb.bottom)
+ {
+ state = (BYTE)((0x8000 & GetAsyncKeyState( GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON)) ?
+ BTNSTATE_PRESSED : BTNSTATE_HILITED);
+ }
+ else state = BTNSTATE_NORMAL;
+
+ if (pDrive->nBtnState != state)
+ {
+
+ NAVITEMINAVLIDATE inv;
+
+ if ((BYTE)BTNSTATE_PRESSED == pDrive->nBtnState && BTNSTATE_HILITED == state)
+ {
+ DriveManager_Eject(pDrive->cLetter, DM_EJECT_CHANGE);
+ }
+
+ if (pDrive->timerId)
+ {
+ KillTimer(NULL, pDrive->timerId);
+ pDrive->timerId = 0;
+ }
+ if (hItemActive)
+ {
+ DRIVE *pDriveOld = Plugin_GetDriveFromNavItem(hItemActive);
+ if (pDriveOld)
+ {
+ RECT rb2;
+ if (pDriveOld->timerId)
+ {
+ KillTimer(NULL, pDriveOld->timerId);
+ pDriveOld->timerId = NULL;
+ }
+ if ((BYTE)BTNSTATE_NORMAL != pDriveOld->nBtnState && GetEjectBtnRect(hItemActive, &rb2))
+ {
+ pDriveOld->nBtnState = BTNSTATE_NORMAL;
+ inv.fErase = FALSE;
+ inv.hItem = hItemActive;
+ inv.prc = &rb2;
+ MLNavItem_Invalidate(plugin.hwndLibraryParent, &inv);
+ }
+ hItemActive = NULL;
+ }
+ }
+
+ if (BTNSTATE_NORMAL != state)
+ {
+ hItemActive = hItem;
+ pDrive->timerId = SetTimer(NULL, 0, NAVBUTTON_STATECHECK_DELAY, NavButton_TimerProc);
+ }
+
+ pDrive->nBtnState = state;
+
+ inv.fErase = FALSE;
+ inv.hItem = hItem;
+ inv.prc = &rb;
+ MLNavItem_Invalidate(plugin.hwndLibraryParent, &inv);
+
+ }
+
+
+ return -1;
+}
+
+static BOOL Plugin_OnConfig(void)
+{
+ SendMessageW(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&myPrefsItemCD, IPC_OPENPREFSTOPAGE);
+ return TRUE;
+}
+
+static INT_PTR pluginMessageProc(int msg, INT_PTR param1, INT_PTR param2, INT_PTR param3)
+{
+ HNAVITEM hItem;
+
+ if (msg >= ML_MSG_TREE_BEGIN && msg <= ML_MSG_TREE_END)
+ {
+ hItem = (msg < ML_MSG_NAVIGATION_FIRST) ? MLNavCtrl_FindItemById(plugin.hwndLibraryParent, param1) : (HNAVITEM)param1;
+ if (!hItem) return 0;
+ } else hItem = NULL;
+
+ switch (msg)
+ {
+ case ML_MSG_TREE_ONCREATEVIEW: return (INT_PTR)Plugin_OnViewCreate(hItem, (HWND)param2);
+ case ML_MSG_NAVIGATION_ONDELETE: return (INT_PTR)Plugin_OnNavItemDelete(hItem);
+ case ML_MSG_NAVIGATION_ONCUSTOMDRAW: return (INT_PTR)Plugin_OnNavCustomDraw(hItem, (NAVITEMDRAW*)param2, (LPARAM)param3);
+ case ML_MSG_NAVIGATION_ONHITTEST: return (INT_PTR)Plugin_OnNavHitTest(hItem, (NAVHITTEST*)param2, (LPARAM)param3);
+ case ML_MSG_NAVIGATION_ONSETCURSOR: return (INT_PTR)Plugin_OnNavSetCursor(hItem, (LPARAM)param3);
+ case ML_MSG_NAVIGATION_CONTEXTMENU:
+ {
+ DRIVE *pDrive;
+ if (hniMain && (hItem == hniMain))
+ return Root_OnContextMenu(hItem, (HWND)param2, MAKEPOINTS(param3));
+
+ //Plugin Item
+ pDrive = Plugin_GetDriveFromNavItem(hItem);
+ if (pDrive)
+ return Plugin_OnContextMenu(hItem, (HWND)param2, MAKEPOINTS(param3), pDrive->cLetter);
+
+ return 0;
+ }
+ case ML_MSG_TREE_ONCLICK: return (INT_PTR)Plugin_OnNavItemClick(hItem, (UINT)param2, (HWND)param3);
+ case ML_MSG_CONFIG: return (INT_PTR)Plugin_OnConfig();
+ case ML_MSG_MLVISIBLE: Plugin_OnMLVisible((BOOL)param1); break;
+ case ML_MSG_NOTOKTOQUIT: if (!Plugin_QueryOkToQuit()) { return TRUE; } break;
+ }
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+extern "C" winampMediaLibraryPlugin plugin =
+{
+ MLHDR_VER,
+ "nullsoft(ml_disc.dll)",
+ Init,
+ Quit,
+ pluginMessageProc,
+ 0,
+ 0,
+ 0,
+};
+
+extern "C" __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
+{
+ return &plugin;
+} \ No newline at end of file