123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- #include "main.h"
- #include "./api__ml_online.h"
- #include "./config.h"
- #include "./navigation.h"
- #include "./resource.h"
- #include "./preferences.h"
- #include "./serviceHelper.h"
- #include "../../General/gen_ml/ml.h"
- #include "../../General/gen_ml/ml_ipc_0313.h"
- #include "../nu/MediaLibraryInterface.h"
- #include "../nu/AutoChar.h"
- #include "../nu/ns_wc.h"
- #include "../nu/AutoWide.h"
- #include <vector>
- #include "../nu/nonewthrow.c"
- #include "../nu/ConfigCOM.h"
- #include "BufferCache.h"
- #include "OMCOM.h"
- #include "JNetCom.h" // for buffer_map
- #include <shlwapi.h>
- #include <strsafe.h>
- static int Plugin_Init();
- static void Plugin_Quit();
- static INT_PTR Plugin_MessageProc(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3);
- static Navigation *navigation = NULL;
- static std::vector<PLUGINUNLOADCALLBACK> *unloadCallbacks = NULL;
- C_Config *g_config=NULL;
- extern "C" winampMediaLibraryPlugin plugin =
- {
- MLHDR_VER,
- "nullsoft(ml_online.dll)",
- Plugin_Init,
- Plugin_Quit,
- Plugin_MessageProc,
- 0,
- 0,
- 0,
- };
- HINSTANCE Plugin_GetInstance(void)
- {
- return plugin.hDllInstance;
- }
- HWND Plugin_GetWinamp(void)
- {
- return plugin.hwndWinampParent;
- }
- HWND Plugin_GetLibrary(void)
- {
- return plugin.hwndLibraryParent;
- }
- HRESULT Plugin_GetNavigation(Navigation **instance)
- {
- if(NULL == instance) return E_POINTER;
- if (NULL == navigation)
- {
- *instance = NULL;
- return E_UNEXPECTED;
- }
- *instance = navigation;
- navigation->AddRef();
- return S_OK;
- }
- typedef struct __PLUGINTIMERREC
- {
- UINT_PTR id;
- PLUGINTIMERPROC callback;
- ULONG_PTR data;
- } PLUGINTIMERREC;
- typedef std::vector<PLUGINTIMERREC> PluginTimerList;
- static void CALLBACK Plugin_TimerProcDispath(HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD elapsedMs)
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL != hLibrary && FALSE != IsWindow(hLibrary))
- {
- PluginTimerList *list = (PluginTimerList*)GetProp(hLibrary, L"OnlineMediaTimerData");
- if (NULL != list)
- {
- size_t index = list->size();
- while(index--)
- {
- PLUGINTIMERREC *rec = &list->at(index);
- if (rec->id == eventId)
- {
- rec->callback(eventId, elapsedMs, rec->data);
- return;
- }
- }
- }
- }
- KillTimer(hwnd, eventId);
- }
- UINT_PTR Plugin_SetTimer(UINT elapseMs, PLUGINTIMERPROC callback, ULONG_PTR data)
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary || FALSE == IsWindow(hLibrary))
- return 0;
-
- if (GetCurrentThreadId() != GetWindowThreadProcessId(hLibrary, NULL))
- return 0;
- if (NULL == callback)
- return 0;
- PluginTimerList *list = (PluginTimerList*)GetProp(hLibrary, L"OnlineMediaTimerData");
- if (NULL == list)
- {
- list = new PluginTimerList();
- if (NULL == list) return 0;
- if (0 == SetProp(hLibrary, L"OnlineMediaTimerData", list))
- {
- delete(list);
- return 0;
- }
- }
- PLUGINTIMERREC rec;
- rec.data = data;
- rec.callback = callback;
- rec.id = SetTimer(NULL, NULL, elapseMs, Plugin_TimerProcDispath);
- if (0 == rec.id)
- {
- if (0 == list->size())
- {
- RemoveProp(hLibrary, L"OnlineMediaTimerData");
- delete(list);
- }
- return 0;
- }
- list->push_back(rec);
- return rec.id;
- }
- void Plugin_KillTimer(UINT_PTR eventId)
- {
- KillTimer(NULL, eventId);
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary || FALSE == IsWindow(hLibrary))
- return;
-
- PluginTimerList *list = (PluginTimerList*)GetProp(hLibrary, L"OnlineMediaTimerData");
- if (NULL == list) return;
-
- size_t index = list->size();
- while(index--)
- {
- if (list->at(index).id == eventId)
- {
- list->erase(list->begin() + index);
- break;
- }
- }
- if (0 == list->size())
- {
- RemoveProp(hLibrary, L"OnlineMediaTimerData");
- delete(list);
- }
- }
- static void Plugin_UninitializeTimer()
- {
- HWND hLibrary = Plugin_GetLibrary();
- if (NULL == hLibrary || FALSE == IsWindow(hLibrary))
- return;
-
- PluginTimerList *list = (PluginTimerList*)GetProp(hLibrary, L"OnlineMediaTimerData");
- RemoveProp(hLibrary, L"OnlineMediaTimerData");
- if (NULL == list) return;
-
- size_t index = list->size();
- while(index--)
- {
- KillTimer(NULL, list->at(index).id);
- }
- delete(list);
- }
- wchar_t g_w_cachedir[2048] = {0};
- int winampVersion=0;
- OMCOM omCOM;
- URLMap urlMap;
- MetadataMap metadataMap;
- Nullsoft::Utility::LockGuard urlMapGuard;
- void LoadCacheItem( wchar_t *path )
- {
- FILECACHETYPE cachefile = {0};
- unsigned long size = 0;
- HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) return;
- ReadFile(hFile, &cachefile, sizeof(FILECACHETYPE),&size, NULL);
- if ( size == sizeof(FILECACHETYPE ))
- {
- size = 0;
- time_t now = time(NULL);
- //read the header, validate
- if ( cachefile.version == FILECACHEVERSION )
- {
- if ( now < cachefile.expires )
- {
- char *url = (char *)calloc((size_t)cachefile.urllen, sizeof(char));
- if (url)
- {
- size = 0;
- ReadFile(hFile, url, (DWORD)cachefile.urllen, &size, NULL);
- if ( cachefile.urllen == size ) // we read it ok!
- {
- char tempbuf[16384] = {0};
- Buffer_GrowBuf *newbuffer = new Buffer_GrowBuf;
- INT64 readin=0;
- newbuffer->expire_time = (time_t)cachefile.expires;
- while ( readin != cachefile.datalen )
- {
- DWORD toread=(DWORD)cachefile.datalen - (DWORD)readin;
- if ( toread > 16384 ) toread=16384;
- size = 0;
- int success = ReadFile(hFile, &tempbuf, toread , &size, NULL);
- if ( success )
- {
- if ( size )
- {
- newbuffer->add(tempbuf,(int)size);
- readin += size;
- }
- }
- else
- {
- break;
- }
- }
- if ( readin != cachefile.datalen )
- {
- delete newbuffer;
- }
- else
- {
- buffer_map[(wchar_t *)AutoWide(url)]=newbuffer;
- }
- }
- else
- {
- free(url);
- }
- }
- }
- }
- }
- CloseHandle(hFile);
- DeleteFile(path);
- }
- void LoadCache()
- {
- WIN32_FIND_DATA FindFileData = {0};
- HANDLE hFind;
- wchar_t searchs[2048] = {0};
- buffer_map.clear();
- StringCchPrintf(searchs, 2048, L"%s\\*.w5x",g_w_cachedir);
- hFind = FindFirstFile(searchs, &FindFileData);
- if ( hFind != INVALID_HANDLE_VALUE )
- {
- do
- {
- wchar_t activefile[2048] = {0};
- StringCchPrintf(activefile, 2048, L"%s\\%s",g_w_cachedir,FindFileData.cFileName);
- LoadCacheItem(activefile);
- } while ( FindNextFile(hFind, &FindFileData) );
- FindClose(hFind);
- }
- }
- void SaveCache()
- {
- BufferMap::iterator buffer_it;
- DWORD start=0xABBACAFE;
- for(buffer_it = buffer_map.begin();buffer_it != buffer_map.end(); buffer_it++)
- {
- time_t now = time(NULL);
- if ( buffer_it->second->expire_time > now )
- {
- wchar_t filename[2048] = {0};
- FILECACHETYPE cachefile;
- HANDLE hFile;
- INT64 size=0;
- memset((void *)&cachefile,0,sizeof(FILECACHETYPE));
- cachefile.version = FILECACHEVERSION;
- cachefile.expires = buffer_it->second->expire_time;
- AutoChar charUrl(buffer_it->first.c_str());
- cachefile.urllen = strlen(charUrl)+1;
- cachefile.datalen = buffer_it->second->getlen()+1;
- StringCchPrintf(filename, 2048, L"%s\\%08X.w5x",g_w_cachedir,start++);
- hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile != INVALID_HANDLE_VALUE)
- {
- WriteFile(hFile, &cachefile, sizeof(FILECACHETYPE),(LPDWORD)&size,NULL);
- if ( size == sizeof(FILECACHETYPE) )
- {
- char blank[2]="\0";
- size = 0; WriteFile(hFile, (char *)charUrl ,(DWORD)cachefile.urllen, (LPDWORD)&size, NULL);
- size = 0; WriteFile(hFile, buffer_it->second->get() , (DWORD)buffer_it->second->getlen(), (LPDWORD)&size, NULL);
- size = 0; WriteFile(hFile, blank , 1, (LPDWORD)&size, NULL);
- }
- else
- {
- CloseHandle(hFile);
- hFile=NULL;
- DeleteFile(filename);
- }
- }
- if (hFile)
- {
- CloseHandle(hFile);
- hFile=NULL;
- }
- }
- }
- }
- void initConfigCache()
- {
- wchar_t iniFileName[2048] = {0};
- mediaLibrary.BuildPath(L"Plugins\\ml", iniFileName, 2048);
- CreateDirectory(iniFileName, NULL);
- mediaLibrary.BuildPath(L"Plugins\\ml\\cache", g_w_cachedir, 2048);
- CreateDirectory(g_w_cachedir, NULL);
- mediaLibrary.BuildPath(L"Plugins\\ml\\ml_online.ini", iniFileName, 2048);
- AutoChar charFn(iniFileName);
- g_config = new C_Config(AutoChar(iniFileName));
- int x = g_config->ReadInt("maxbandwidth", MAXBANDWIDTH );
- g_config->WriteInt("maxbandwidth",x);
- x = g_config->ReadInt("minbandwidth",1);
- g_config->WriteInt("minbandwidth",x);
- LoadCache();
- }
- static void Plugin_ExecuteOpenOnce()
- {
- CHAR szBuffer[128] = {0};
- INT cchLen = Config_ReadStr("Navigation", "openOnce", NULL, szBuffer, ARRAYSIZE(szBuffer));
- if (0 != cchLen)
- {
- UINT serviceId;
- if (FALSE != StrToIntExA(szBuffer, STIF_SUPPORT_HEX, (INT*)&serviceId))
- {
-
- cchLen = Config_ReadStr("Navigation", "openOnceMode", NULL, szBuffer, ARRAYSIZE(szBuffer));
- UINT showMode;
- if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "popup", -1, szBuffer, cchLen))
- showMode = SHOWMODE_POPUP;
- else if (CSTR_EQUAL == CompareStringA(CSTR_INVARIANT, NORM_IGNORECASE, "ensureVisible", -1, szBuffer, cchLen))
- showMode = SHOWMODE_ENSUREVISIBLE;
- else
- showMode = SHOWMODE_NORMAL;
- ServiceHelper_ShowService(serviceId, showMode);
- }
-
- Config_WriteStr("Navigation", "openOnce", NULL);
- Config_WriteStr("Navigation", "openOnceMode", NULL);
- }
- }
- static int Plugin_Init()
- {
- if (FAILED(WasabiApi_Initialize(plugin.hDllInstance, plugin.service)))
- return 1;
- if (FAILED(WasabiApi_LoadDefaults()) ||
- NULL == OMBROWSERMNGR ||
- NULL == OMSERVICEMNGR ||
- NULL == OMUTILITY)
- {
- WasabiApi_Release();
- return 2;
- }
- ServiceHelper_Initialize();
- if (NULL != WASABI_API_LNG)
- {
- static wchar_t szDescription[256];
- StringCchPrintf(szDescription, ARRAYSIZE(szDescription),
- WASABI_API_LNGSTRINGW(IDS_PLUGIN_NAME),
- PLUGIN_VERSION_MAJOR, PLUGIN_VERSION_MINOR);
- plugin.description = (char*)szDescription;
- }
- mediaLibrary.library = plugin.hwndLibraryParent;
- mediaLibrary.winamp = plugin.hwndWinampParent;
- mediaLibrary.instance = plugin.hDllInstance;
- winampVersion = mediaLibrary.GetWinampVersion();
- omCOM.Publish();
-
- Preferences_Register();
- if (NULL == navigation)
- {
- if (FAILED(Navigation::CreateInstance(&navigation)))
- {
- navigation = NULL;
- if (NULL != unloadCallbacks)
- {
- size_t index = unloadCallbacks->size();
- while(index--)
- unloadCallbacks->at(index)();
- delete(unloadCallbacks);
- }
- Preferences_Unregister();
- WasabiApi_Release();
- return 3;
- }
- }
- initConfigCache();
-
- Plugin_ExecuteOpenOnce();
- return ML_INIT_SUCCESS;
- }
- static void Plugin_Quit()
- {
- SaveCache();
- buffer_map.clear();
- Plugin_UninitializeTimer();
- if (NULL != navigation)
- {
- navigation->Finish();
- navigation->Release();
- navigation = NULL;
- }
- if (NULL != unloadCallbacks)
- {
- size_t index = unloadCallbacks->size();
- while(index--)
- unloadCallbacks->at(index)();
- delete(unloadCallbacks);
- unloadCallbacks = NULL;
- }
- Preferences_Unregister();
- WasabiApi_Release();
- }
- static INT_PTR TitleHook(waHookTitleStructW *hookTitle)
- {
- if (NULL == hookTitle ||
- NULL == hookTitle->filename)
- {
- return 0;
- }
- Nullsoft::Utility::AutoLock lock(urlMapGuard);
- // this is kinda slow but AOL Videos is so underused anyway that this map won't fill up much
- URLMap::iterator itr;
- for (itr=urlMap.begin();itr!=urlMap.end();itr++)
- {
- if (!_wcsnicmp(hookTitle->filename, itr->url.c_str(), itr->url_wcslen))
- {
- if (NULL != hookTitle->title)
- StringCchCopy(hookTitle->title, 2048, itr->title.c_str());
-
- hookTitle->length = itr->length;
- return 1;
- }
- }
- return 0;
- }
- static INT_PTR MetadataHook(extendedFileInfoStructW *hookMetadata)
- {
- if (NULL == hookMetadata ||
- NULL == hookMetadata->filename ||
- NULL == hookMetadata->metadata)
- {
- return 0;
- }
- Nullsoft::Utility::AutoLock lock(urlMapGuard);
- // this is kinda slow but AOL Videos is so underused anyway that this map won't fill up much
- MetadataMap::iterator itr;
- for (itr=metadataMap.begin();itr!=metadataMap.end();itr++)
- {
- if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, hookMetadata->filename, -1, itr->url.c_str(), - 1) &&
- CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, hookMetadata->metadata, -1, itr->tag.c_str(), - 1))
- {
- StringCchCopy(hookMetadata->ret, hookMetadata->retlen, itr->metadata.c_str());
- return 1;
- }
- }
- return 0;
- }
- static INT_PTR Plugin_MessageProc(int msg, INT_PTR param1, INT_PTR param2, INT_PTR param3)
- {
- INT_PTR result = 0;
- if (NULL != navigation &&
- FALSE != navigation->ProcessMessage(msg, param1, param2, param3, &result))
- {
- return result;
- }
-
- switch (msg)
- {
- case ML_IPC_HOOKTITLEW: return TitleHook((waHookTitleStructW *)param1);
- case ML_IPC_HOOKEXTINFOW: return MetadataHook((extendedFileInfoStructW *)param1);
- case ML_MSG_CONFIG: Preferences_Show(); return TRUE;
- }
- return FALSE;
- }
- void Plugin_RegisterUnloadCallback(PLUGINUNLOADCALLBACK callback)
- {
- if (NULL == unloadCallbacks)
- {
- unloadCallbacks = new std::vector<PLUGINUNLOADCALLBACK>();
- if (NULL == unloadCallbacks)
- return;
- }
- unloadCallbacks->push_back(callback);
- }
- extern "C" __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
- {
- return &plugin;
- }
- #if 0
- extern "C" __declspec( dllexport ) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) {
- // prompt to remove our settings with default as no (just incase)
- /*if(MessageBoxA(hwndDlg,"Do you also want to remove the saved settings for this plugin?",
- plugin.description,MB_YESNO|MB_DEFBUTTON2) == IDYES)
- {
- WritePrivateProfileString("ml_rg", 0, 0, iniFile);
- }*/
- // also attempt to remove the ReplayGainAnalysis.dll so everything is kept cleaner
- /*char path[MAX_PATH] = {0};
- GetModuleFileName(hDllInst, path, MAX_PATH);
- PathRemoveFileSpec(path);
- PathAppend(path, "ReplayGainAnalysis.dll");
- // if we get a handle then try to lower the handle count so we can delete
- HINSTANCE rgLib = GetModuleHandle(path);
- if(rgLib)
- FreeLibrary(rgLib);
- DeleteFile(path);*/
- // allow an on-the-fly removal (since we've got to be with a compatible client build)
- return ML_PLUGIN_UNINSTALL_NOW;
- }
- #endif
|