winamp/Src/Plugins/Library/ml_playlists/AMNWatcher.cpp
2024-09-24 14:54:57 +02:00

242 lines
7.0 KiB
C++

#include "main.h"
#include "./amnwatcher.h"
#include <shlobj.h>
#include <strsafe.h>
#include "playlists.h"
#include "PlaylistManager.h"
#include "PlaylistView.h"
waServiceFactory *AMNWatcher::watcherFactory = NULL;
BOOL IsMusicNowWantUs(void)
{
HKEY key;
DWORD value = 0, length = sizeof(DWORD);
if (ERROR_SUCCESS == RegOpenKeyExW( HKEY_CURRENT_USER, L"Software\\AOL Music Now\\UserPreferences", 0, KEY_QUERY_VALUE, &key ))
{
long retCode = RegQueryValueExW(key, L"IntegrateWithWinamp", NULL, NULL, (LPBYTE) & value, &length);
if (ERROR_SUCCESS != retCode) value = TRUE;
RegCloseKey(key);
}
return value;
}
BOOL GetMusicNowPlaylistPath(LPWSTR *pathNew, LPWSTR *pathOld) // CAUTION!!! this function will allocate memory for the string using malloc
{
// first check rgistry
HKEY key;
*pathNew = NULL;
*pathOld = NULL;
if (ERROR_SUCCESS == RegOpenKeyExW( HKEY_CURRENT_USER, L"Software\\AOL Music Now\\UserPreferences", 0, KEY_QUERY_VALUE, &key ))
{
const wchar_t *rPath = L"PlaylistDirectory";
DWORD length;
if (ERROR_SUCCESS == RegQueryValueExW(key, rPath, NULL, NULL, NULL, &length)) // try registry ( for future)
{
*pathNew = (LPWSTR)malloc(length);
if (ERROR_SUCCESS != RegQueryValueExW(key, rPath, NULL, NULL, (LPBYTE)*pathNew, &length)) { free(*pathNew); *pathNew = NULL; }
}
RegCloseKey(key);
if (*pathNew && !PathFileExists(*pathNew)) { free(*pathNew); *pathNew = NULL; } //check that path is actualy exist
LPITEMIDLIST pidl;
if (S_OK == SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &pidl))
{
wchar_t path[MAX_PATH*4] = {0};
if(SHGetPathFromIDListW(pidl, path))
{
const wchar_t *suffix = L"Music Now Playlists";
int cchLen = lstrlenW(path) + lstrlenW(suffix) + 32;
if (!*pathNew) // no luck - use deafult's
{
*pathNew = (LPWSTR)malloc(cchLen*sizeof(wchar_t));
StringCchPrintfW(*pathNew, cchLen, L"%s\\%s", path, suffix);
if (!PathFileExists(*pathNew)) {free(*pathNew); *pathNew = NULL; }// i give up - can't find anything
}
// now let's try old path
*pathOld = (LPWSTR)malloc(cchLen*sizeof(wchar_t));
StringCchPrintfW(*pathOld, cchLen, L"%s\\AOL %s", path, suffix);
if (!PathFileExists(*pathOld)) { free(*pathOld); *pathOld = NULL; }
}
CoTaskMemFree(pidl);
}
}
return (NULL != *pathNew) || (NULL != *pathOld);
}
AMNWatcher::AMNWatcher(void) : watcherOld(NULL), watcherNew(NULL), dirty(FALSE)
{}
AMNWatcher::~AMNWatcher(void)
{
//Destroy(); // have to just let it leak. you should call Destroy() manually
}
int AMNWatcher::Init(api_service *service, const wchar_t *trackPath)
{
BOOL retCode = FALSE;
if (!IsMusicNowWantUs()) return retCode;
if (watcherFactory) return retCode;
LPWSTR pathNew, pathOld;
if (!GetMusicNowPlaylistPath(&pathNew, &pathOld)) return retCode;
int cchLen = lstrlenW(pathNew);
if (cchLen > 1 && pathNew[cchLen -1] == L'\\') pathNew[cchLen -1] = 0x00;
cchLen = lstrlenW(pathOld);
if (cchLen > 1 && pathOld[cchLen -1] == L'\\') pathOld[cchLen -1] = 0x00;
watcherFactory = service->service_getServiceByGuid(watcherGUID);
if (watcherFactory)
{
if (pathNew)
{
watcherNew = (api_watcher*)watcherFactory->getInterface();
watcherNew->Create( L"WAMN_PLS_NEW", pathNew, TRUE, WATCHER_TRACKMODE_CENTRAL, OnWatcherNotify);
}
if (pathOld)
{
watcherOld = (api_watcher*)watcherFactory->getInterface();
watcherOld->Create( L"WAMN_PLS_OLD", pathOld, TRUE, WATCHER_TRACKMODE_CENTRAL, OnWatcherNotify);
}
for (int i = 0; i < 2; i++)
{
api_watcher *watcher = (i) ? watcherOld : watcherNew;
if (!watcher) continue;
watcher->SetExtensionFilter(L"WPL", WATCHER_FILTERTYPE_INCLUDE);
watcher->SetUserData(this);
watcher->SetCallBack(OnWatcherNotify);
watcher->SetTrackingPath(trackPath);
watcher->Start();
watcher->ForceScan(FALSE, SCANPRIORITY_IDLE);
}
}
free(pathNew);
free(pathOld);
return TRUE;
}
void AMNWatcher::Destroy(void)
{
if (watcherNew)
{
watcherNew->Stop();
watcherFactory->releaseInterface(watcherNew);
watcherNew = NULL;
}
if (watcherOld)
{
watcherOld->Stop();
watcherFactory->releaseInterface(watcherOld);
watcherOld = NULL;
}
}
int AMNWatcher::OnWatcherNotify(api_watcher *sender, UINT message, LONG_PTR param, void* userdata)
{
UNREFERENCED_PARAMETER(sender);
AMNWatcher *watcher = (AMNWatcher*)userdata;
if (WATCHER_MSG_FILE == message)
{
WATCHERCHANGEINFO *info = (WATCHERCHANGEINFO*)param;
// ignore some names
if (info->cchFile >= 21) // can be "AOL Music Now - Auido.wpl" or "AOL Music Now - Video.wpl"
{
const wchar_t *testname = info->file + info->cchFile - 21;
if (CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, NULL, testname, 9, L"Music Now", 9)) return 1;
}
else if ( 17 == info->cchFile && CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, NULL, info->file, 13, L"AOL Music Now", 13)) return 1;
wchar_t fullName[MAX_PATH*4];
PathCombineW(fullName, info->path, info->file);
size_t i(0);
switch (info->state)
{
case WATCHER_FILESTATE_ADDED:
case WATCHER_FILESTATE_CHANGED:
{
if (!info->file)
break;
wchar_t *title = _wcsdup(info->file);
unsigned int len = lstrlen(title);
while (len && title[len] != '.') len--;
if (len != 0) title[len] = 0x00;
while (i != playlists.size() && lstrcmpW(fullName, playlists.at(i).filename)) i++;
if ( i == playlists.size())
{
AddPlaylist(title, fullName, TRUE, playlistManager->CountItems(fullName));
watcher->dirty = TRUE;
}
else
{
int length = playlistManager->GetLengthMilliseconds(fullName);
int numItems = (int)playlistManager->CountItems(fullName);
if (playlists.at(i).length != length || playlists.at(i).numItems != numItems)
{
StringCchCopy(playlists.at(i).title, 1024, title);
playlists.at(i).length = length;
playlists.at(i).numItems = numItems;
HWND hwnd = (HWND) SendMessage(plugin.hwndLibraryParent, WM_ML_IPC, 0, ML_IPC_GETCURRENTVIEW);
if (hwnd)
{
wchar_t* title = (wchar_t*)GetPropW(hwnd, L"TITLE");
if (title && 0 == lstrcmp(title, playlists[i].title)) SendMessage(hwnd, WM_PLAYLIST_RELOAD, 0, 0);
}
watcher->dirty = TRUE;
}
}
free(title);
}
break;
case WATCHER_FILESTATE_REMOVED:
{
for ( i = 0; i < playlists.size(); i++)
{
if (0 == lstrcmpW(fullName, playlists.at(i).filename))
{
HWND hwnd = (HWND) SendMessage(plugin.hwndLibraryParent, WM_ML_IPC, 0, ML_IPC_GETCURRENTVIEW);
if (hwnd)
{
wchar_t* title = (wchar_t *)GetPropW(hwnd, L"TITLE");
if (title && 0 == lstrcmp(title, playlists[i].title)) SendMessage(hwnd, WM_PLAYLIST_UNLOAD, 0, 0);
}
if (playlists.at(i).treeId)
mediaLibrary.RemoveTreeItem(playlists.at(i).treeId);
playlists.eraseAt(i);
i--;
watcher->dirty = TRUE;
break;
}
}
}
break;
}
}
else if (WATCHER_MSG_STATUS == message)
{
if (STATUS_SCANER_STOPPED == param || STATUS_SCANER_FINISHED == param)
{
if (watcher->dirty)
{
SavePlaylists();
RefreshPlaylistsList();
watcher->dirty = FALSE;
}
}
}
return 1;
}