123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- #include "precomp__gen_ff.h"
- #include "main.h"
- #include "../Agave/Language/api_language.h"
- #include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
- #include "../nu/AutoWide.h"
- #include "../nu/AutoChar.h"
- #include "../nu/AutoCharFn.h"
- #include "wa2frontend.h"
- #include "resource.h"
- #include "../nu/ns_wc.h"
- #include "../nu/refcount.h"
- #include "api/skin/widgets/xuidownloadslist.h"
- #include <shlobj.h>
- #include <shlwapi.h>
- #include <api/script/objects/systemobj.h>
- extern wchar_t *INI_DIR;
- static void createDirForFileW(wchar_t *str)
- {
- wchar_t *p = str;
- if ((p[0] ==L'\\' || p[0] ==L'/') && (p[1] ==L'\\' || p[1] ==L'/'))
- {
- p += 2;
- while (p && *p && *p !=L'\\' && *p !=L'/') p++;
- if (!p || !*p) return ;
- p++;
- while (p && *p && *p !=L'\\' && *p !=L'/') p++;
- }
- else
- {
- while (p && *p && *p !=L'\\' && *p !=L'/') p++;
- }
- while (p && *p)
- {
- while (p && *p !=L'\\' && *p !=L'/' && *p) p = CharNextW(p);
- if (p && *p)
- {
- wchar_t lp = *p;
- *p = 0;
- CreateDirectoryW(str, NULL);
- *p++ = lp;
- }
- }
- }
- static wchar_t* defaultPathToStore()
- {
- static wchar_t pathToStore[MAX_PATH] = {0};
- if(FAILED(SHGetFolderPathW(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, pathToStore)))
- {
- if(FAILED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, pathToStore)))
- {
- lstrcpynW(pathToStore, L"C:\\My Music", MAX_PATH);
- }
- }
- return pathToStore;
- }
- static void GetPathToStore(wchar_t path_to_store[MAX_PATH])
- {
- GetPrivateProfileStringW( L"gen_ml_config", L"extractpath", defaultPathToStore(), path_to_store, MAX_PATH, (const wchar_t *)SendMessageW( plugin.hwndParent, WM_WA_IPC, 0, IPC_GETMLINIFILEW ) );
- }
- void Winamp2FrontEnd::getDownloadPath(wchar_t path2store[MAX_PATH])
- {
- GetPathToStore(path2store);
- }
- void Winamp2FrontEnd::setDownloadPath(const wchar_t * path2store)
- {
- WritePrivateProfileStringA( "gen_ml_config", "extractpath", AutoChar( path2store, CP_UTF8 ), (const char *)SendMessageW( plugin.hwndParent, WM_WA_IPC, 0, IPC_GETMLINIFILE ) );
- }
- class DownloadCallback : public Countable<ifc_downloadManagerCallback>
- {
- public:
- DownloadCallback( const wchar_t *destination_filepath, bool storeInMl = true, bool notifyDownloadsList = true )
- {
- WCSCPYN( this->destination_filepath, destination_filepath, MAX_PATH );
- this->storeInMl = storeInMl;
- this->notifyDownloadsList = notifyDownloadsList;
- }
- void OnFinish( DownloadToken token );
- void OnError( DownloadToken token, int error )
- {
- if ( notifyDownloadsList )
- DownloadsList::onDownloadError( token, error );
- Release();
- }
- void OnCancel( DownloadToken token )
- {
- if ( notifyDownloadsList )
- DownloadsList::onDownloadCancel( token );
- Release();
- }
- void OnTick( DownloadToken token )
- {
- if ( notifyDownloadsList )
- DownloadsList::onDownloadTick( token );
- }
- const wchar_t *getPreferredFilePath()
- {
- return destination_filepath;
- }
- bool getStoreInML()
- {
- return storeInMl;
- }
- REFERENCE_COUNT_IMPLEMENTATION;
- protected:
- RECVS_DISPATCH;
- private:
- bool storeInMl;
- bool notifyDownloadsList;
- wchar_t destination_filepath[ MAX_PATH ];
- };
- // TODO: benski> this is a big hack. we should have a MIME manager in Winamp
- struct
- {
- const char *mime; const char *ext;
- }
- hack_mimes[] = { {"audio/mpeg", ".mp3"} };
- void DownloadCallback::OnFinish(DownloadToken token)
- {
- api_httpreceiver *http = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
- if (http)
- {
- const char *extension = 0;
- const char *headers = http->getallheaders();
- // we're trying to figure out wtf kind of file this is
- if (!extension) // just adding this if to make this easier to re-arrange
- {
- // 1) check if there's a content-disposition, it might have an extension
- const char *content_disposition = http->getheader("content-disposition");
- if (content_disposition)
- {
- const char *content_filename = strstr(content_disposition, "filename=");
- if (content_filename && *content_filename)
- {
- content_filename+=9;
- extension = PathFindExtensionA(content_filename);
- }
- }
- }
- if (!extension)
- {
- // 2) check MIME type for something good
- const char *content_type = http->getheader("content-type");
- if (content_type)
- {
- for (int i=0;i!=sizeof(hack_mimes)/sizeof(hack_mimes[0]);i++)
- {
- if (!strcmp(hack_mimes[i].mime, content_type))
- {
- extension=hack_mimes[i].ext;
- }
- }
- }
- }
- const char *url = http->get_url();
- if (!extension)
- {
- // 3) check if URL has an extension
-
- if (url) // umm, we better have a URL :) but worth a check
- {
- extension = PathFindExtensionA(url);
- }
- }
- if (!extension)
- {
- // 4) ask for winamp's default extension and use that (most likely mp3)
- extension=".mp3"; // TODO: actually use the setting and not hardcode this :)
- }
- // then we rename the file
- wchar_t temppath[MAX_PATH-14] = {0};
- wchar_t filename[MAX_PATH] = {0};
- GetTempPathW(MAX_PATH-14, temppath);
- GetTempFileNameW(temppath, L"atf", 0, filename);
- PathRemoveExtensionW(filename);
- PathAddExtensionW(filename, AutoWide(extension));
-
- const wchar_t *downloadDest = WAC_API_DOWNLOADMANAGER->GetLocation(token);
- MoveFileW(downloadDest, filename);
-
- // then we build a filename with ATF
- wchar_t formatted_filename[MAX_PATH] = {0}, path_to_store[MAX_PATH] = {0};
- if (!WCSICMP(this->getPreferredFilePath(), L""))
- GetPathToStore(path_to_store);
- else
- WCSCPYN(path_to_store, this->getPreferredFilePath(), MAX_PATH);
- // TODO: benski> this is very temporary
- char temp_filename[MAX_PATH] = {0}, *t = temp_filename,
- *tfn = PathFindFileNameA(url);
- while(tfn && *tfn)
- {
- if(*tfn == '%')
- {
- if(_strnicmp(tfn,"%20",3))
- {
- *t = *tfn;
- }
- else{
- *t = ' ';
- tfn = CharNextA(tfn);
- tfn = CharNextA(tfn);
- }
- }
- else
- {
- *t = *tfn;
- }
- tfn = CharNextA(tfn);
- t = CharNextA(t);
- }
- *t = 0;
- PathCombineW(formatted_filename, path_to_store, AutoWide(temp_filename));
- createDirForFileW(formatted_filename);
- // then move the file there
- if (!MoveFileW(filename, formatted_filename))
- {
- CopyFileW(filename, formatted_filename, FALSE);
- DeleteFileW(filename);
- }
- //Std::messageBox(formatted_filename, filename, 0);
- if (this->getStoreInML() && PathFileExistsW(formatted_filename))
- {
- // then add to the media library :)
- // TOOD: benski> use api_mldb because it's more thread-friendly than SendMessageW
- HWND library = wa2.getMediaLibrary();
- LMDB_FILE_ADD_INFOW fi = {const_cast<wchar_t *>(formatted_filename), -1, -1};
- SendMessageW(library, WM_ML_IPC, (WPARAM)&fi, ML_IPC_DB_ADDORUPDATEFILEW);
- PostMessage(library, WM_ML_IPC, 0, ML_IPC_DB_SYNCDB);
- }
- if (notifyDownloadsList)
- DownloadsList::onDownloadEnd(token, const_cast<wchar_t *>(formatted_filename));
-
- SystemObject::onDownloadFinished(AutoWide(url), true, formatted_filename);
- Release();
- return;
- }
- if (notifyDownloadsList)
- DownloadsList::onDownloadEnd(token, NULL);
- Release();
- }
- int Winamp2FrontEnd::DownloadFile( const char *url, const wchar_t *destfilepath, bool addToMl, bool notifyDownloadsList )
- {
- DownloadCallback *callback = new DownloadCallback( destfilepath, addToMl, notifyDownloadsList );
- DownloadToken dt = WAC_API_DOWNLOADMANAGER->Download( url, callback );
- // Notify <DownloadsList/>
- if ( notifyDownloadsList )
- DownloadsList::onDownloadStart( url, dt );
- return 0;
- /*
- HTTPRETRIEVEFILEW func = (HTTPRETRIEVEFILEW) SendMessageW(hwnd_winamp, WM_WA_IPC, 0, IPC_GETHTTPGETTERW);
- if (func || func == (HTTPRETRIEVEFILEW)1)
- return func(NULL, url, destfilename, title);
- else
- return 0;
- */
- }
- #define CBCLASS DownloadCallback
- START_DISPATCH;
- REFERENCE_COUNTED;
- VCB( IFC_DOWNLOADMANAGERCALLBACK_ONFINISH, OnFinish )
- VCB( IFC_DOWNLOADMANAGERCALLBACK_ONTICK, OnTick )
- VCB( IFC_DOWNLOADMANAGERCALLBACK_ONERROR, OnError )
- VCB( IFC_DOWNLOADMANAGERCALLBACK_ONCANCEL, OnCancel )
- END_DISPATCH;
- #undef CBCLASS
|