586 lines
17 KiB
C++
586 lines
17 KiB
C++
|
#define PLUGIN_VERSION L"3.36"
|
||
|
#include "main.h"
|
||
|
#include "resource.h"
|
||
|
#include "api__ml_local.h"
|
||
|
#include "..\..\General\gen_ml/config.h"
|
||
|
#include <commctrl.h>
|
||
|
#include ".\ml_local.h"
|
||
|
#include "..\..\General\gen_ml/ml_ipc_0313.h"
|
||
|
#include "../replicant/nu/AutoChar.h"
|
||
|
#include <api/service/waServiceFactory.h>
|
||
|
#include "../playlist/api_playlistmanager.h"
|
||
|
#include "mldbApiFactory.h"
|
||
|
#include "../nu/ServiceWatcher.h"
|
||
|
#include "LocalMediaCOM.h"
|
||
|
#include <tataki/export.h>
|
||
|
#include <strsafe.h>
|
||
|
#if 0
|
||
|
// disabled since not building cloud dlls
|
||
|
#include "../ml_cloud/CloudCallback.h"
|
||
|
#endif
|
||
|
|
||
|
static ServiceWatcher serviceWatcher;
|
||
|
static LocalMediaCOM localMediaCOM;
|
||
|
MLDBAPIFactory mldbApiFactory;
|
||
|
mlAddTreeItemStruct newTree;
|
||
|
|
||
|
#if 0
|
||
|
// disabled since not building cloud dlls
|
||
|
static class CloudCallbacks : public CloudCallback
|
||
|
{
|
||
|
void OnCloudUploadStart(const wchar_t *filename) {
|
||
|
SendMessage(m_curview_hwnd, WM_APP + 5, 0, (LPARAM)filename);
|
||
|
}
|
||
|
|
||
|
void OnCloudUploadDone(const wchar_t *filename, int code) {
|
||
|
SendMessage(m_curview_hwnd, WM_APP + 5, MAKEWPARAM(code, 1), (LPARAM)filename);
|
||
|
}
|
||
|
} cloudCallback;
|
||
|
#endif
|
||
|
|
||
|
LRESULT ML_IPC_MENUFUCKER_BUILD = -1, ML_IPC_MENUFUCKER_RESULT = -1;
|
||
|
int IPC_CLOUD_ENABLED = -1;
|
||
|
|
||
|
int CreateView(int treeItem, HWND parent);
|
||
|
|
||
|
static int Init();
|
||
|
static void Quit();
|
||
|
static INT_PTR MessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3);
|
||
|
|
||
|
void SaveAll();
|
||
|
|
||
|
prefsDlgRecW preferences;
|
||
|
|
||
|
static wchar_t preferencesName[64] = {0};
|
||
|
|
||
|
int winampVersion = 0;
|
||
|
int substantives = 0;
|
||
|
int play_enq_rnd_alt = 0;
|
||
|
|
||
|
// Delay load library control << begin >>
|
||
|
#include <delayimp.h>
|
||
|
#pragma comment(lib, "delayimp")
|
||
|
|
||
|
bool nde_error = false;
|
||
|
|
||
|
FARPROC WINAPI FailHook(unsigned dliNotify, DelayLoadInfo *dli)
|
||
|
{
|
||
|
nde_error = true;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
extern "C"
|
||
|
{
|
||
|
PfnDliHook __pfnDliFailureHook2 = FailHook;
|
||
|
}
|
||
|
// Delay load library control << end >>
|
||
|
*/
|
||
|
|
||
|
#define CBCLASS PLCallBackW
|
||
|
START_DISPATCH;
|
||
|
VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
|
||
|
END_DISPATCH;
|
||
|
#undef CBCLASS
|
||
|
|
||
|
template <class api_T>
|
||
|
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
|
||
|
{
|
||
|
if (plugin.service)
|
||
|
{
|
||
|
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
|
||
|
if (factory)
|
||
|
api_t = reinterpret_cast<api_T *>( factory->getInterface() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <class api_T>
|
||
|
void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
|
||
|
{
|
||
|
if (plugin.service && api_t)
|
||
|
{
|
||
|
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
|
||
|
if (factory)
|
||
|
factory->releaseInterface(api_t);
|
||
|
}
|
||
|
api_t = NULL;
|
||
|
}
|
||
|
|
||
|
extern WORD waMenuID;
|
||
|
DEFINE_EXTERNAL_SERVICE(api_application, WASABI_API_APP);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_explorerfindfile, WASABI_API_EXPLORERFINDFILE);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_language, WASABI_API_LNG);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_syscb, WASABI_API_SYSCB);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_memmgr, WASABI_API_MEMMGR);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_albumart, AGAVE_API_ALBUMART);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_metadata, AGAVE_API_METADATA);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_playlistmanager, AGAVE_API_PLAYLISTMANAGER);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_itunes_importer, AGAVE_API_ITUNES_IMPORTER);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_playlist_generator, AGAVE_API_PLAYLIST_GENERATOR);
|
||
|
DEFINE_EXTERNAL_SERVICE(api_threadpool, WASABI_API_THREADPOOL);
|
||
|
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
|
||
|
|
||
|
int sse_flag;
|
||
|
int Init()
|
||
|
{
|
||
|
#ifdef _M_IX86
|
||
|
int flags_edx;
|
||
|
_asm
|
||
|
{
|
||
|
mov eax, 1
|
||
|
cpuid
|
||
|
mov flags_edx, edx
|
||
|
}
|
||
|
|
||
|
sse_flag = flags_edx & 0x02000000;
|
||
|
#else
|
||
|
sse_flag=1; // always supported on amd64
|
||
|
#endif
|
||
|
InitializeCriticalSection(&g_db_cs);
|
||
|
|
||
|
waMenuID = (WORD)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_REGISTER_LOWORD_COMMAND);
|
||
|
|
||
|
Tataki::Init(plugin.service);
|
||
|
|
||
|
plugin.service->service_register(&mldbApiFactory);
|
||
|
|
||
|
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
|
||
|
ServiceBuild(WASABI_API_LNG, languageApiGUID);
|
||
|
ServiceBuild(WASABI_API_EXPLORERFINDFILE, ExplorerFindFileApiGUID);
|
||
|
ServiceBuild(AGAVE_API_ALBUMART, albumArtGUID);
|
||
|
ServiceBuild(AGAVE_API_METADATA, api_metadataGUID);
|
||
|
ServiceBuild(WASABI_API_MEMMGR, memMgrApiServiceGuid);
|
||
|
ServiceBuild(WASABI_API_SYSCB, syscbApiServiceGuid);
|
||
|
ServiceBuild(AGAVE_API_PLAYLISTMANAGER, api_playlistmanagerGUID);
|
||
|
ServiceBuild(WASABI_API_THREADPOOL, ThreadPoolGUID);
|
||
|
//ServiceBuild(AGAVE_API_PLAYLIST_GENERATOR, api_playlist_generator::getServiceGuid());
|
||
|
|
||
|
serviceWatcher.WatchWith(plugin.service);
|
||
|
serviceWatcher.WatchFor(&AGAVE_API_ITUNES_IMPORTER, api_itunes_importer::getServiceGuid());
|
||
|
serviceWatcher.WatchFor(&AGAVE_API_PLAYLIST_GENERATOR, api_playlist_generator::getServiceGuid());
|
||
|
WASABI_API_SYSCB->syscb_registerCallback(&serviceWatcher);
|
||
|
#if 0
|
||
|
// disabled since not building cloud dlls
|
||
|
WASABI_API_SYSCB->syscb_registerCallback(&cloudCallback);
|
||
|
#endif
|
||
|
|
||
|
// need to have this initialised before we try to do anything with localisation features
|
||
|
WASABI_API_START_LANG(plugin.hDllInstance,MlLocalLangGUID);
|
||
|
|
||
|
wchar_t buf[2] = {0};
|
||
|
if(LoadString(WASABI_API_LNG_HINST,IDS_SUBSTANTIVES,buf,2)){
|
||
|
substantives = 1;
|
||
|
}
|
||
|
|
||
|
// this is used to load alternative play/enqueue random strings where
|
||
|
// the default implementation will cause pluralisation issue eg de-de
|
||
|
buf[0] = 0;
|
||
|
if(LoadString(WASABI_API_LNG_HINST,IDS_PLAY_ENQ_RND_ALTERNATIVE,buf,2)){
|
||
|
play_enq_rnd_alt = 1;
|
||
|
}
|
||
|
|
||
|
static wchar_t szDescription[256];
|
||
|
StringCchPrintfW(szDescription, ARRAYSIZE(szDescription),
|
||
|
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_LOCAL_MEDIA), PLUGIN_VERSION);
|
||
|
plugin.description = (char*)szDescription;
|
||
|
|
||
|
ML_IPC_MENUFUCKER_BUILD = (int)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"menufucker_build", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
||
|
ML_IPC_MENUFUCKER_RESULT = (int)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"menufucker_result", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
||
|
IPC_CLOUD_ENABLED = SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"WinampCloudEnabled", IPC_REGISTER_WINAMP_IPCMESSAGE);
|
||
|
|
||
|
mediaLibrary.library = plugin.hwndLibraryParent;
|
||
|
mediaLibrary.winamp = plugin.hwndWinampParent;
|
||
|
mediaLibrary.instance = plugin.hDllInstance;
|
||
|
winampVersion = mediaLibrary.GetWinampVersion();
|
||
|
|
||
|
mediaLibrary.AddDispatch(L"LocalMedia", &localMediaCOM);
|
||
|
|
||
|
// this may look unused, but we want to get this here since mediaLibrary will cache the inidir
|
||
|
// and then we don't run into weird multithreaded SendMessage issues
|
||
|
mediaLibrary.GetIniDirectory();
|
||
|
mediaLibrary.GetIniDirectoryW();
|
||
|
|
||
|
preferences.hInst = WASABI_API_LNG_HINST;
|
||
|
preferences.dlgID = IDD_PREFSFR;
|
||
|
preferences.proc = (void *)PrefsProc;
|
||
|
preferences.name = WASABI_API_LNGSTRINGW_BUF(IDS_LOCAL_MEDIA,preferencesName,64);
|
||
|
preferences.where = 6; // 0;
|
||
|
mediaLibrary.AddPreferences(preferences);
|
||
|
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_AUDIO, TREE_IMAGE_LOCAL_AUDIO, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_MOSTPLAYED, TREE_IMAGE_LOCAL_MOSTPLAYED, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_NEVERPLAYED, TREE_IMAGE_LOCAL_NEVERPLAYED, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_RECENTLYPLAYED, TREE_IMAGE_LOCAL_RECENTLYPLAYED, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_RECENTLYADDED, TREE_IMAGE_LOCAL_RECENTLYADDED, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_TOPRATED, TREE_IMAGE_LOCAL_TOPRATED, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_VIDEO, TREE_IMAGE_LOCAL_VIDEO, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_PODCASTS, TREE_IMAGE_LOCAL_PODCASTS, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
mediaLibrary.AddTreeImage(IDB_TREEITEM_RECENTLYMODIFIED, TREE_IMAGE_LOCAL_RECENTLYMODIFIED, (BMPFILTERPROC)FILTER_DEFAULT1);
|
||
|
|
||
|
int ret = init();
|
||
|
if (ret) return ret;
|
||
|
|
||
|
NAVINSERTSTRUCT nis = {0};
|
||
|
nis.item.cbSize = sizeof(NAVITEM);
|
||
|
nis.item.pszText = WASABI_API_LNGSTRINGW(IDS_LOCAL_MEDIA);
|
||
|
nis.item.pszInvariant = L"Local Media";
|
||
|
nis.item.style = NIS_HASCHILDREN;
|
||
|
nis.item.id = 1000; // benski> use the old ID for backwards compatability
|
||
|
nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_STYLE | NIMF_ITEMID;
|
||
|
|
||
|
// map to item id (will probably have to change but is a quick port to support invariant item naming)
|
||
|
NAVITEM nvItem = {sizeof(NAVITEM),0,NIMF_ITEMID,};
|
||
|
nvItem.hItem = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
|
||
|
MLNavItem_GetInfo(plugin.hwndLibraryParent, &nvItem);
|
||
|
m_query_tree = nvItem.id;
|
||
|
|
||
|
loadQueryTree();
|
||
|
|
||
|
m_query_mode = 0;
|
||
|
m_query_metafile = L"default.vmd";
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void Quit()
|
||
|
{
|
||
|
serviceWatcher.StopWatching();
|
||
|
serviceWatcher.Clear();
|
||
|
|
||
|
// deregister this first, otherwise people might try to use it after we shut down the database!
|
||
|
plugin.service->service_deregister(&mldbApiFactory);
|
||
|
|
||
|
UnhookPlaylistEditor();
|
||
|
|
||
|
Scan_Kill();
|
||
|
|
||
|
closeDb();
|
||
|
|
||
|
delete(g_view_metaconf);
|
||
|
g_view_metaconf = 0;
|
||
|
|
||
|
delete g_config;
|
||
|
g_config = NULL;
|
||
|
|
||
|
KillArtThread();
|
||
|
|
||
|
for (QueryList::iterator i = m_query_list.begin();i != m_query_list.end();i++)
|
||
|
{
|
||
|
queryItem *item = i->second;
|
||
|
if (item)
|
||
|
{
|
||
|
free(item->metafn);
|
||
|
free(item->name);
|
||
|
free(item->query);
|
||
|
}
|
||
|
free(item);
|
||
|
}
|
||
|
m_query_list.clear();
|
||
|
DeleteCriticalSection(&g_db_cs);
|
||
|
|
||
|
ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
|
||
|
ServiceRelease(WASABI_API_LNG, languageApiGUID);
|
||
|
ServiceRelease(AGAVE_API_ALBUMART, albumArtGUID);
|
||
|
ServiceRelease(WASABI_API_MEMMGR, memMgrApiServiceGuid);
|
||
|
ServiceRelease(AGAVE_API_METADATA, api_metadataGUID);
|
||
|
ServiceRelease(WASABI_API_SYSCB, syscbApiServiceGuid);
|
||
|
ServiceRelease(AGAVE_API_PLAYLISTMANAGER, api_playlistmanagerGUID);
|
||
|
ServiceRelease(AGAVE_API_ITUNES_IMPORTER, api_itunes_importer::getServiceGuid());
|
||
|
ServiceRelease(WASABI_API_THREADPOOL, ThreadPoolGUID);
|
||
|
ServiceRelease(AGAVE_API_PLAYLIST_GENERATOR, api_playlist_generator::getServiceGuid());
|
||
|
|
||
|
Tataki::Quit();
|
||
|
}
|
||
|
|
||
|
INT_PTR MessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3)
|
||
|
{
|
||
|
switch (message_type)
|
||
|
{
|
||
|
case ML_MSG_TREE_ONCREATEVIEW: // param1 = param of tree item, param2 is HWND of parent. return HWND if it is us
|
||
|
if (param1 == m_query_tree || m_query_list[param1])
|
||
|
return (INT_PTR)onTreeViewSelectChange((HWND)param2);
|
||
|
else
|
||
|
return 0;
|
||
|
|
||
|
case ML_MSG_NAVIGATION_CONTEXTMENU:
|
||
|
{
|
||
|
HNAVITEM hItem = (HNAVITEM)param1;
|
||
|
HNAVITEM myItem = MLNavCtrl_FindItemById(plugin.hwndLibraryParent, m_query_tree);
|
||
|
if (hItem == myItem)
|
||
|
{
|
||
|
queriesContextMenu(param1, (HWND)param2, MAKEPOINTS(param3));
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NAVITEM nvItem = {sizeof(NAVITEM),hItem,NIMF_ITEMID,};
|
||
|
MLNavItem_GetInfo(plugin.hwndLibraryParent, &nvItem);
|
||
|
if (m_query_list[nvItem.id])
|
||
|
{
|
||
|
view_queryContextMenu(param1, (HWND)param2, MAKEPOINTS(param3), nvItem.id);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
case ML_MSG_TREE_ONCLICK:
|
||
|
if (param1 == m_query_tree)
|
||
|
return OnLocalMediaClick(param2, (HWND)param3);
|
||
|
else if (m_query_list[param1])
|
||
|
return OnLocalMediaItemClick(param2, param1, (HWND)param3);
|
||
|
else
|
||
|
return 0;
|
||
|
|
||
|
case ML_MSG_TREE_ONDRAG:
|
||
|
if (m_query_list[param1])
|
||
|
{
|
||
|
int *type = reinterpret_cast<int *>(param3);
|
||
|
*type = ML_TYPE_ITEMRECORDLIST;
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case ML_MSG_TREE_ONDROP:
|
||
|
if (param3 != NULL && param1 != NULL) // here we go - finishing moving view
|
||
|
{
|
||
|
if (m_query_list[param1])
|
||
|
{
|
||
|
if (param3 == m_query_tree || m_query_list[param3])
|
||
|
{
|
||
|
QueryList::iterator src = m_query_list.find(param1);
|
||
|
mediaLibrary.RemoveTreeItem(src->first);
|
||
|
MLTREEITEMW srcItem = {sizeof(MLTREEITEMW), };
|
||
|
|
||
|
srcItem.title = src->second->name;
|
||
|
srcItem.hasChildren = 0;
|
||
|
srcItem.parentId = m_query_tree;
|
||
|
srcItem.id = param3;
|
||
|
srcItem.imageIndex = src->second->imgIndex;
|
||
|
mediaLibrary.InsertTreeItem(srcItem);
|
||
|
|
||
|
auto item = src->second;
|
||
|
m_query_list.erase(param1);
|
||
|
m_query_list.insert({ srcItem.id, item });
|
||
|
|
||
|
saveQueryTree();
|
||
|
mediaLibrary.SelectTreeItem(srcItem.id);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (m_query_list[param1])
|
||
|
{
|
||
|
mlDropItemStruct m = {0};
|
||
|
m.type = ML_TYPE_ITEMRECORDLISTW;
|
||
|
m.p = *(POINT *)param2;
|
||
|
m.flags = ML_HANDLEDRAG_FLAG_NOCURSOR | ML_HANDLEDRAG_FLAG_NAME;
|
||
|
|
||
|
// build an itemRecordList
|
||
|
queryItem *item = m_query_list[param1];
|
||
|
wchar_t configDir[MAX_PATH] = {0};
|
||
|
PathCombineW(configDir, g_viewsDir, item->metafn);
|
||
|
C_Config viewconf(configDir);
|
||
|
|
||
|
EnterCriticalSection(&g_db_cs);
|
||
|
nde_scanner_t s = NDE_Table_CreateScanner(g_table);
|
||
|
NDE_Scanner_Query(s, item->query);
|
||
|
itemRecordListW obj = {0, };
|
||
|
saveQueryToListW(&viewconf, s, &obj, 0, 0, (resultsniff_funcW)-1);
|
||
|
NDE_Table_DestroyScanner(g_table, s);
|
||
|
LeaveCriticalSection(&g_db_cs);
|
||
|
m.data = (void *) & obj;
|
||
|
AutoChar whatsThisNameUsedForAnyway(item->name);
|
||
|
m.name = whatsThisNameUsedForAnyway;
|
||
|
|
||
|
pluginHandleIpcMessage(ML_IPC_HANDLEDROP, (WPARAM)&m);
|
||
|
if (m.result < 1)
|
||
|
{
|
||
|
m.result = 0;
|
||
|
m.type = ML_TYPE_ITEMRECORDLIST;
|
||
|
itemRecordList objA={0,};
|
||
|
convertRecordList(&objA, &obj);
|
||
|
m.data = (void*)&objA;
|
||
|
pluginHandleIpcMessage(ML_IPC_HANDLEDRAG, (WPARAM)&m);
|
||
|
freeRecordList(&objA);
|
||
|
}
|
||
|
freeRecordList(&obj);
|
||
|
}
|
||
|
return 0;
|
||
|
|
||
|
case ML_MSG_CONFIG:
|
||
|
mediaLibrary.GoToPreferences(preferences._id);
|
||
|
return TRUE;
|
||
|
|
||
|
case ML_MSG_VIEW_PLAY_ENQUEUE_CHANGE:
|
||
|
enqueuedef = param1;
|
||
|
groupBtn = param2;
|
||
|
PostMessage(m_curview_hwnd, WM_APP + 104, param1, param2);
|
||
|
return 0;
|
||
|
|
||
|
case ML_MSG_ONSENDTOBUILD:
|
||
|
if (param1 == ML_TYPE_ITEMRECORDLISTW || param1 == ML_TYPE_ITEMRECORDLIST ||
|
||
|
param1 == ML_TYPE_FILENAMES || param1 == ML_TYPE_FILENAMESW)
|
||
|
{
|
||
|
if (!myMenu) mediaLibrary.AddToSendTo(WASABI_API_LNGSTRINGW(IDS_ADD_TO_LOCAL_MEDIA), param2, (INT_PTR)MessageProc);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ML_MSG_ONSENDTOSELECT:
|
||
|
case ML_MSG_TREE_ONDROPTARGET: // return -1 if not allowed, 1 if allowed, or 0 if not our tree item
|
||
|
// set with droptarget defaults =)
|
||
|
INT_PTR type, data;
|
||
|
|
||
|
if (message_type == ML_MSG_ONSENDTOSELECT)
|
||
|
{
|
||
|
if (param3 != (INT_PTR)MessageProc) return 0;
|
||
|
|
||
|
type = param1;
|
||
|
data = param2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (param1 != m_query_tree && !m_query_list[param1]) return 0;
|
||
|
|
||
|
type = param2;
|
||
|
data = param3;
|
||
|
|
||
|
if (!data)
|
||
|
{
|
||
|
return (type == ML_TYPE_ITEMRECORDLISTW || type == ML_TYPE_ITEMRECORDLIST ||
|
||
|
type == ML_TYPE_FILENAMES || type == ML_TYPE_FILENAMESW ||
|
||
|
type == ML_TYPE_PLAYLIST) ? 1 : -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (data)
|
||
|
{
|
||
|
if (type == ML_TYPE_ITEMRECORDLIST)
|
||
|
{
|
||
|
itemRecordList *p = (itemRecordList*)data;
|
||
|
for (int x = 0; x < p->Size; x ++)
|
||
|
mediaLibrary.AddToMediaLibrary(p->Items[x].filename);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
else if (type == ML_TYPE_ITEMRECORDLISTW)
|
||
|
{
|
||
|
itemRecordListW *p = (itemRecordListW*)data;
|
||
|
for (int x = 0; x < p->Size; x ++)
|
||
|
mediaLibrary.AddToMediaLibrary(p->Items[x].filename);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
else if (type == ML_TYPE_PLAYLIST)
|
||
|
{
|
||
|
mlPlaylist * pl = (mlPlaylist *)data;
|
||
|
PLCallBackW plCB;
|
||
|
if (AGAVE_API_PLAYLISTMANAGER && PLAYLISTMANAGER_SUCCESS != AGAVE_API_PLAYLISTMANAGER->Load(pl->filename, &plCB))
|
||
|
{
|
||
|
mediaLibrary.AddToMediaLibrary(pl->filename);
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
else if (type == ML_TYPE_FILENAMES)
|
||
|
{
|
||
|
const char *p = (const char*)data;
|
||
|
while (p && *p)
|
||
|
{
|
||
|
PLCallBackW plCB;
|
||
|
if (AGAVE_API_PLAYLISTMANAGER && PLAYLISTMANAGER_SUCCESS != AGAVE_API_PLAYLISTMANAGER->Load(AutoWide(p), &plCB))
|
||
|
{
|
||
|
mediaLibrary.AddToMediaLibrary(p);
|
||
|
}
|
||
|
p += strlen(p) + 1;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
else if (type == ML_TYPE_FILENAMESW)
|
||
|
{
|
||
|
const wchar_t *p = (const wchar_t*)data;
|
||
|
while (p && *p)
|
||
|
{
|
||
|
PLCallBackW plCB;
|
||
|
if (AGAVE_API_PLAYLISTMANAGER && PLAYLISTMANAGER_SUCCESS != AGAVE_API_PLAYLISTMANAGER->Load(p, &plCB))
|
||
|
{
|
||
|
mediaLibrary.AddToMediaLibrary(p);
|
||
|
}
|
||
|
p += wcslen(p) + 1;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ML_MSG_TREE_ONKEYDOWN:
|
||
|
{
|
||
|
NMTVKEYDOWN *p = (NMTVKEYDOWN*)param2;
|
||
|
int ctrl = (GetAsyncKeyState(VK_CONTROL)&0x8000);
|
||
|
int shift = (GetAsyncKeyState(VK_SHIFT)&0x8000);
|
||
|
|
||
|
if (p->wVKey == VK_INSERT && !shift)
|
||
|
{
|
||
|
if (!ctrl)
|
||
|
addNewQuery(plugin.hwndLibraryParent);
|
||
|
else
|
||
|
if (!g_bgscan_scanning) SendMessage(plugin.hwndLibraryParent, WM_USER + 575, 0xffff00dd, 0);
|
||
|
|
||
|
PostMessageW(plugin.hwndLibraryParent, WM_NEXTDLGCTL, (WPARAM)param3, (LPARAM)TRUE);
|
||
|
return 1;
|
||
|
}
|
||
|
else if (m_query_list[param1])
|
||
|
{
|
||
|
if (p->wVKey == VK_F2 && !shift && !ctrl)
|
||
|
{
|
||
|
queryEditItem(param1);
|
||
|
}
|
||
|
else if (p->wVKey == VK_DELETE && !shift && !ctrl)
|
||
|
{
|
||
|
queryDeleteItem(plugin.hwndLibraryParent, param1);
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
|
||
|
PostMessageW(plugin.hwndLibraryParent, WM_NEXTDLGCTL, (WPARAM)param3, (LPARAM)TRUE);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
case ML_IPC_HOOKEXTINFO:
|
||
|
if (IPC_HookExtInfo(param1)) return 1;
|
||
|
break;
|
||
|
|
||
|
case ML_IPC_HOOKEXTINFOW:
|
||
|
if (IPC_HookExtInfoW(param1)) return 1;
|
||
|
break;
|
||
|
|
||
|
case ML_IPC_HOOKTITLEW:
|
||
|
if (IPC_HookTitleInfo(param1)) return 1;
|
||
|
break;
|
||
|
|
||
|
case ML_MSG_PLAYING_FILE:
|
||
|
if (param1) onStartPlayFileTrack((const wchar_t *)param1, false);
|
||
|
break;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
extern "C" winampMediaLibraryPlugin plugin =
|
||
|
{
|
||
|
MLHDR_VER,
|
||
|
"nullsoft(ml_local.dll)",
|
||
|
Init,
|
||
|
Quit,
|
||
|
MessageProc,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
};
|
||
|
|
||
|
extern "C" __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
|
||
|
{
|
||
|
return &plugin;
|
||
|
}
|