aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Library/ml_downloads/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_downloads/Main.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Library/ml_downloads/Main.cpp')
-rw-r--r--Src/Plugins/Library/ml_downloads/Main.cpp387
1 files changed, 387 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_downloads/Main.cpp b/Src/Plugins/Library/ml_downloads/Main.cpp
new file mode 100644
index 00000000..09a260eb
--- /dev/null
+++ b/Src/Plugins/Library/ml_downloads/Main.cpp
@@ -0,0 +1,387 @@
+#include "main.h"
+#include "DownloadsDialog.h"
+#include "DownloadsParse.h"
+#include "Preferences.h"
+#include "XMLWriter.h"
+#include "..\..\General\gen_ml/ml.h"
+#include "Defaults.h"
+#include "..\..\General\gen_ml/ml_ipc_0313.h"
+
+#include "api__ml_downloads.h"
+#include "Downloaded.h"
+#include "DownloadStatus.h"
+#include <api/service/waServiceFactory.h>
+
+#include <strsafe.h>
+
+wchar_t *ml_cfg = 0,
+ xmlFileName[1024] = {0};
+
+ATOM VIEWPROP = 0;
+
+api_downloadManager *WAC_API_DOWNLOADMANAGER = 0;
+DownloadViewCallback *downloadViewCallback = 0;
+
+static int Init();
+static void Quit();
+static INT_PTR MessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3);
+
+DWORD threadStorage=TLS_OUT_OF_INDEXES;
+extern "C" winampMediaLibraryPlugin plugin =
+ {
+ MLHDR_VER,
+ "nullsoft(ml_downloads.dll)",
+ Init,
+ Quit,
+ MessageProc,
+ 0,
+ 0,
+ 0,
+ };
+
+//static prefsDlgRecW preferences;
+//static wchar_t preferencesName[64] = {0};
+int downloads_treeItem = 0,
+ podcast_parent = 0,
+ no_auto_hide = 0;
+HANDLE hMainThread;
+
+HCURSOR hDragNDropCursor;
+int winampVersion = 0, dirty = 0;
+
+api_application *applicationApi = NULL;
+api_explorerfindfile *WASABI_API_EXPLORERFINDFILE = 0;
+
+// wasabi based services for localisation support
+api_language *WASABI_API_LNG = 0;
+HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
+
+int icons[4] = {-1, -1, -1, -1};
+int activeIcon = 0;
+int totalIcons = 4;
+static Nullsoft::Utility::LockGuard navigationLock;
+
+// used to get the downloads view parented to the podcast view
+#define CSTR_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
+#define NAVITEM_PREFIX L"podcast_svc_"
+#define SERVICE_PODCAST 720
+
+enum
+{
+ DOWNLOADS_TIMER_NAVNODE = 35784,
+};
+
+HNAVITEM Navigation_FindService(UINT serviceId)
+{
+ HWND hLibrary = plugin.hwndLibraryParent;
+ INT cchPrefix = ARRAYSIZE(NAVITEM_PREFIX) - 1;
+
+ WCHAR szBuffer[256] = {0};
+ NAVITEM itemInfo = {0};
+ itemInfo.cbSize = sizeof(itemInfo);
+ itemInfo.mask = NIMF_TEXTINVARIANT;
+ itemInfo.cchInvariantMax = ARRAYSIZE(szBuffer);
+ itemInfo.pszInvariant = szBuffer;
+ itemInfo.hItem = MLNavCtrl_GetFirst(hLibrary);
+
+ while(NULL != itemInfo.hItem)
+ {
+ if (FALSE != MLNavItem_GetInfo(hLibrary, &itemInfo) &&
+ CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, itemInfo.pszInvariant, cchPrefix,
+ NAVITEM_PREFIX, cchPrefix))
+ {
+ return itemInfo.hItem;
+ }
+ itemInfo.hItem = MLNavItem_GetNext(hLibrary, itemInfo.hItem);
+ }
+ return NULL;
+}
+
+void Navigation_Update_Icon(void)
+{
+ Nullsoft::Utility::AutoLock navlock(navigationLock);
+
+ HNAVITEM hItem = NULL;
+ if(downloads_treeItem)
+ {
+ hItem = MLNavCtrl_FindItemById(plugin.hwndLibraryParent,downloads_treeItem);
+ }
+
+ if (hItem)
+ {
+ NAVITEM item;
+ item.cbSize = sizeof(NAVITEM);
+ item.hItem = hItem;
+ item.iSelectedImage = item.iImage = icons[activeIcon];
+ activeIcon = (activeIcon + 1) % totalIcons;
+ item.mask = NIMF_IMAGE | NIMF_IMAGESEL;
+ MLNavItem_SetInfo(plugin.hwndLibraryParent, &item);
+ }
+}
+
+BOOL Navigation_Update(void)
+{
+ int activeDownloads = 0;
+ int historyDownloads = 0;
+ {
+ Nullsoft::Utility::AutoLock historylock(downloadedFiles.downloadedLock);
+ historyDownloads = (int)downloadedFiles.downloadList.size();
+ }
+
+ {
+ Nullsoft::Utility::AutoLock statuslock(downloadStatus.statusLock);
+ activeDownloads = (int)downloadStatus.downloads.size();
+ }
+
+ Nullsoft::Utility::AutoLock navlock(navigationLock);
+ HNAVITEM hItem = NULL;
+ if (downloads_treeItem)
+ {
+ hItem = MLNavCtrl_FindItemById(plugin.hwndLibraryParent,downloads_treeItem);
+ }
+
+ NAVINSERTSTRUCT nis = {0};
+ nis.item.cbSize = sizeof(NAVITEM);
+ nis.item.pszText = WASABI_API_LNGSTRINGW(IDS_DOWNLOADS);
+ nis.item.iSelectedImage = nis.item.iImage = icons[0];
+
+ WCHAR szName[256] = {0};
+ if (activeDownloads && SUCCEEDED(StringCchPrintf(szName, ARRAYSIZE(szName), L"%s (%u)", WASABI_API_LNGSTRINGW(IDS_DOWNLOADS), activeDownloads)))
+ nis.item.pszText = szName;
+
+ if (activeDownloads > 0 || historyDownloads > 0 || no_auto_hide == 2)
+ {
+ if (!hItem)
+ {
+ nis.item.pszInvariant = NAVITEM_UNIQUESTR;
+ nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL;
+ if(podcast_parent) nis.hParent = Navigation_FindService(SERVICE_PODCAST);
+ NAVITEM nvItem = {sizeof(NAVITEM),0,NIMF_ITEMID,};
+
+ nvItem.hItem = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
+
+ MLNavItem_GetInfo(plugin.hwndLibraryParent, &nvItem);
+ downloads_treeItem = nvItem.id;
+ }
+ else
+ {
+ nis.item.hItem = hItem;
+ nis.item.mask = NIMF_TEXT;
+ MLNavItem_SetInfo(plugin.hwndLibraryParent, &nis.item);
+ }
+ }
+ else if (hItem)
+ {
+ nis.item.hItem = hItem;
+ nis.item.mask = NIMF_TEXT | NIMF_IMAGE | NIMF_IMAGESEL;
+ MLNavItem_SetInfo(plugin.hwndLibraryParent, &nis.item);
+ }
+
+ return TRUE;
+}
+
+void CALLBACK Downloads_Nav_Timer(HWND hwnd, UINT uMsg, UINT_PTR eventId, ULONG elapsed)
+{
+ switch (eventId)
+ {
+ case DOWNLOADS_TIMER_NAVNODE:
+ if (downloadStatus.CurrentlyDownloading())
+ Navigation_Update_Icon();
+ break;
+ }
+}
+
+
+int Init()
+{
+ hMainThread = GetCurrentThread();
+ hDragNDropCursor = LoadCursor( GetModuleHandle( L"gen_ml.dll" ), MAKEINTRESOURCE( ML_IDC_DRAGDROP ) );
+ threadStorage = TlsAlloc();
+
+ if ( 0 == VIEWPROP )
+ {
+ VIEWPROP = GlobalAddAtom( L"Nullsoft_DownloadsView" );
+ if ( VIEWPROP == 0 )
+ return ML_INIT_FAILURE;
+ }
+
+ winampVersion = (int)SendMessage( plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETVERSION );
+
+ waServiceFactory *sf = plugin.service->service_getServiceByGuid( DownloadManagerGUID );
+ if ( !sf ) // no sense in continuing
+ return ML_INIT_FAILURE;
+ else
+ WAC_API_DOWNLOADMANAGER = reinterpret_cast<api_downloadManager *>( 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( applicationApiServiceGuid );
+ if ( sf )
+ WASABI_API_APP = reinterpret_cast<api_application*>( sf->getInterface() );
+
+ sf = plugin.service->service_getServiceByGuid( ExplorerFindFileApiGUID );
+ if ( sf )
+ WASABI_API_EXPLORERFINDFILE = reinterpret_cast<api_explorerfindfile*>( sf->getInterface() );
+
+ // need to have this initialised before we try to do anything with localisation features
+ WASABI_API_START_LANG( plugin.hDllInstance, MlDownloadsLangGUID );
+
+ 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;
+
+ BuildDefaults( plugin.hwndWinampParent );
+
+ mediaLibrary.BuildPath( L"Plugins\\ml\\downloads.xml", xmlFileName, 1024 );
+ if ( PathFileExists( xmlFileName ) )
+ {
+ DownloadsParse downloader;
+ downloader.DownloadFile( xmlFileName );
+ }
+ else
+ {
+ wchar_t xmlRssFileName[ 1024 ] = { 0 };
+ mediaLibrary.BuildPath( L"Plugins\\ml\\feeds\\rss.xml", xmlRssFileName, 1024 );
+ {
+ DownloadsParse rssDownloader;
+ rssDownloader.DownloadFile( xmlRssFileName );
+ }
+ }
+
+ icons[ 0 ] = mediaLibrary.AddTreeImageBmp( IDB_TREEITEM_DOWNLOADS );
+ icons[ 1 ] = mediaLibrary.AddTreeImageBmp( IDB_TREEITEM_DOWNLOADS1 );
+ icons[ 2 ] = mediaLibrary.AddTreeImageBmp( IDB_TREEITEM_DOWNLOADS2 );
+ icons[ 3 ] = mediaLibrary.AddTreeImageBmp( IDB_TREEITEM_DOWNLOADS3 );
+
+ ml_cfg = (wchar_t *)SendMessage( plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETMLINIFILEW );
+
+ podcast_parent = ( !!GetPrivateProfileInt( L"gen_ml_config", L"podcast_parent", 0, ml_cfg ) );
+ no_auto_hide = GetPrivateProfileInt( L"gen_ml_config", L"no_auto_hide", 0, ml_cfg );
+
+ Navigation_Update();
+
+ downloadViewCallback = new DownloadViewCallback();
+ WAC_API_DOWNLOADMANAGER->RegisterStatusCallback( downloadViewCallback );
+
+ SetTimer( plugin.hwndLibraryParent, DOWNLOADS_TIMER_NAVNODE, 1000, Downloads_Nav_Timer );
+
+ return ML_INIT_SUCCESS;
+}
+
+void Quit()
+{
+ KillTimer( plugin.hwndLibraryParent, DOWNLOADS_TIMER_NAVNODE );
+
+ // If there are still files downloading, cancel download to remove incomplete downloaded files
+ while ( downloadStatus.CurrentlyDownloading() )
+ {
+ Nullsoft::Utility::AutoLock lock(downloadStatus.statusLock);
+ DownloadToken dltoken = downloadStatus.downloads.begin()->first;
+ WAC_API_DOWNLOADMANAGER->CancelDownload(dltoken);
+ }
+
+ if (dirty)
+ {
+ SaveDownloads( xmlFileName, downloadedFiles );
+ dirty = 0;
+ }
+
+ WAC_API_DOWNLOADMANAGER->UnregisterStatusCallback( downloadViewCallback );
+ downloadViewCallback->Release();
+
+ waServiceFactory *sf = plugin.service->service_getServiceByGuid( applicationApiServiceGuid );
+ if ( sf != NULL )
+ sf->releaseInterface(WASABI_API_APP);
+
+ sf = plugin.service->service_getServiceByGuid(ExplorerFindFileApiGUID);
+ if ( sf != NULL )
+ sf->releaseInterface(WASABI_API_EXPLORERFINDFILE);
+
+ sf = plugin.service->service_getServiceByGuid(DownloadManagerGUID);
+ if ( sf != NULL )
+ sf->releaseInterface(WAC_API_DOWNLOADMANAGER);
+
+ if ( VIEWPROP != 0 )
+ {
+ GlobalDeleteAtom(VIEWPROP);
+ VIEWPROP = 0;
+ }
+}
+
+HWND CALLBACK DownloadDialog_Create( HWND hParent );
+
+INT_PTR MessageProc( int msg, INT_PTR param1, INT_PTR param2, INT_PTR param3 )
+{
+ switch ( msg )
+ {
+ case ML_MSG_DOWNLOADS_VIEW_LOADED:
+ return TRUE;
+
+ case ML_MSG_DOWNLOADS_VIEW_POSITION:
+ {
+ // toggle the position of the node based on the preferences settings
+ if ( param2 )
+ {
+ podcast_parent = (int)param1;
+ if ( downloads_treeItem )
+ {
+ HNAVITEM hItem = MLNavCtrl_FindItemById( plugin.hwndLibraryParent, downloads_treeItem );
+ if (hItem)
+ {
+ if ( MLNavCtrl_DeleteItem( plugin.hwndLibraryParent, hItem ) )
+ {
+ downloads_treeItem = 0;
+ }
+ }
+ }
+ }
+
+ Navigation_Update();
+ return 0;
+ }
+
+ case ML_MSG_TREE_ONCREATEVIEW:
+ return ( param1 == downloads_treeItem ) ? (INT_PTR)DownloadDialog_Create( (HWND)param2 ) : 0;
+
+ case ML_MSG_NO_CONFIG:
+ return TRUE;
+
+ case ML_MSG_NOTOKTOQUIT:
+ if (downloadStatus.CurrentlyDownloading())
+ {
+ wchar_t titleStr[32] = {0};
+ if ( MessageBox( plugin.hwndLibraryParent, WASABI_API_LNGSTRINGW( IDS_CANCEL_DOWNLOADS_AND_QUIT ), WASABI_API_LNGSTRINGW_BUF( IDS_CONFIRM_QUIT, titleStr, 32 ), MB_YESNO | MB_ICONQUESTION ) == IDNO )
+ return TRUE;
+ }
+ return FALSE;
+
+ case ML_MSG_WRITE_CONFIG:
+ if ( dirty )
+ {
+ SaveDownloads( xmlFileName, downloadedFiles );
+ dirty = 0;
+ }
+ break;
+
+ case ML_MSG_VIEW_PLAY_ENQUEUE_CHANGE:
+ enqueuedef = (int)param1;
+ groupBtn = (int)param2;
+ PostMessage( downloads_window, WM_APP + 104, param1, param2 );
+ return 0;
+ }
+
+ return 0;
+}
+
+
+extern "C" __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
+{
+ return &plugin;
+} \ No newline at end of file