aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Library/ml_bookmarks
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_bookmarks
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Library/ml_bookmarks')
-rw-r--r--Src/Plugins/Library/ml_bookmarks/api__ml_bookmarks.h15
-rw-r--r--Src/Plugins/Library/ml_bookmarks/bookmark.cpp32
-rw-r--r--Src/Plugins/Library/ml_bookmarks/bookmark.h18
-rw-r--r--Src/Plugins/Library/ml_bookmarks/listview.cpp128
-rw-r--r--Src/Plugins/Library/ml_bookmarks/listview.h144
-rw-r--r--Src/Plugins/Library/ml_bookmarks/main.cpp122
-rw-r--r--Src/Plugins/Library/ml_bookmarks/main.h28
-rw-r--r--Src/Plugins/Library/ml_bookmarks/ml_bookmarks.rc186
-rw-r--r--Src/Plugins/Library/ml_bookmarks/ml_bookmarks.sln30
-rw-r--r--Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj317
-rw-r--r--Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj.filters100
-rw-r--r--Src/Plugins/Library/ml_bookmarks/resource.h46
-rw-r--r--Src/Plugins/Library/ml_bookmarks/resources/ti_bookmarks_16x16x16.bmpbin0 -> 568 bytes
-rw-r--r--Src/Plugins/Library/ml_bookmarks/version.rc239
-rw-r--r--Src/Plugins/Library/ml_bookmarks/view.cpp1512
15 files changed, 2717 insertions, 0 deletions
diff --git a/Src/Plugins/Library/ml_bookmarks/api__ml_bookmarks.h b/Src/Plugins/Library/ml_bookmarks/api__ml_bookmarks.h
new file mode 100644
index 00000000..2f9ee071
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/api__ml_bookmarks.h
@@ -0,0 +1,15 @@
+#ifndef NULLSOFT_API_ML_BOOKMARKS_H
+#define NULLSOFT_API_ML_BOOKMARKS_H
+
+#include "api/service/waServiceFactory.h"
+
+#include "../Agave/Language/api_language.h"
+
+#include "../Winamp/api_stats.h"
+extern api_stats *statsApi;
+#define AGAVE_API_STATS statsApi
+
+#include "api/application/api_application.h"
+#define WASABI_API_APP applicationApi
+
+#endif // !NULLSOFT_API_ML_BOOKMARKS_H \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/bookmark.cpp b/Src/Plugins/Library/ml_bookmarks/bookmark.cpp
new file mode 100644
index 00000000..c7ad05e1
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/bookmark.cpp
@@ -0,0 +1,32 @@
+/** (c) Nullsoft, Inc. C O N F I D E N T I A L
+ ** Filename:
+ ** Project:
+ ** Description:
+ ** Author:
+ ** Created:
+ **/
+#include "bookmark.h"
+
+BookmarkWriter::BookmarkWriter():fp(0)
+{
+}
+
+void BookmarkWriter::Open(const wchar_t *filename)
+{
+ fp=_wfopen(filename, L"a+t");
+}
+
+void BookmarkWriter::New(const wchar_t *filename)
+{
+ fp=_wfopen(filename, L"wt");
+}
+
+void BookmarkWriter::Write(const char *filename, const char *title)
+{
+ fprintf(fp,"%s\n%s\n",filename,title);
+}
+
+void BookmarkWriter::Close()
+{
+ if (fp) fclose(fp);
+} \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/bookmark.h b/Src/Plugins/Library/ml_bookmarks/bookmark.h
new file mode 100644
index 00000000..5921e82e
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/bookmark.h
@@ -0,0 +1,18 @@
+#ifndef NULLSOFT_BOOKMARKH
+#define NULLSOFT_BOOKMARKH
+
+#include <stdio.h>
+
+class BookmarkWriter
+{
+public:
+ BookmarkWriter();
+ void New(const wchar_t *filename);
+ void Open(const wchar_t *filename);
+ void Write(const char *filename, const char *title);
+ void Close();
+private:
+ FILE *fp;
+};
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/listview.cpp b/Src/Plugins/Library/ml_bookmarks/listview.cpp
new file mode 100644
index 00000000..a3ceb22c
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/listview.cpp
@@ -0,0 +1,128 @@
+/*
+** Copyright (C) 2003 Nullsoft, Inc.
+**
+** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
+** liable for any damages arising from the use of this software.
+**
+** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
+** alter it and redistribute it freely, subject to the following restrictions:
+**
+** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
+** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+**
+** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+**
+** 3. This notice may not be removed or altered from any source distribution.
+**
+*/
+
+#include <windows.h>
+#include <commctrl.h>
+#include "listview.h"
+
+#ifdef GEN_ML_EXPORTS
+#include "main.h" // for getting the font
+#include "config.h"
+#endif
+// bp Comment: all the calls beginning "ListView_" are
+// MACROs defined in commctrl.h
+
+void W_ListView :: AddCol (char *text, int w)
+{
+ LVCOLUMN lvc={0,};
+ lvc.mask = LVCF_TEXT|LVCF_WIDTH;
+ lvc.pszText = text;
+ if (w) lvc.cx=w;
+ ListView_InsertColumn (m_hwnd, m_col, &lvc);
+ m_col++;
+}
+
+int W_ListView::GetColumnWidth (int col)
+{
+ if (col < 0 || col >= m_col) return 0;
+ return ListView_GetColumnWidth (m_hwnd, col);
+}
+
+
+int W_ListView::GetParam (int p)
+{
+ LVITEM lvi={0,};
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = p;
+ ListView_GetItem (m_hwnd, &lvi);
+ return lvi.lParam;
+}
+
+int W_ListView::InsertItem (int p, char *text, int param)
+{
+ LVITEM lvi={0,};
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.iItem = p;
+ lvi.pszText = text;
+ lvi.cchTextMax=strlen (text);
+ lvi.lParam = param;
+ return ListView_InsertItem (m_hwnd, &lvi);
+}
+
+
+void W_ListView::SetItemText (int p, int si, char *text)
+{
+ LVITEM lvi={0,};
+ lvi.iItem = p;
+ lvi.iSubItem = si;
+ lvi.mask = LVIF_TEXT;
+ lvi.pszText = text;
+ lvi.cchTextMax = strlen (text);
+ ListView_SetItem (m_hwnd, &lvi);
+}
+
+void W_ListView::SetItemParam (int p, int param)
+{
+ LVITEM lvi={0,};
+ lvi.iItem = p;
+ lvi.mask=LVIF_PARAM;
+ lvi.lParam=param;
+ ListView_SetItem (m_hwnd, &lvi);
+}
+
+void W_ListView::refreshFont ()
+{
+ if (m_font)
+ {
+ DeleteFont (m_font);
+ SetWindowFont (m_hwnd, NULL, FALSE);
+ }
+ m_font = NULL;
+
+ HWND h;
+#ifdef GEN_ML_EXPORTS
+ h=g_hwnd;
+#else
+ h=m_libraryparent;
+#endif
+ if (h && m_allowfonts)
+ {
+ int a=SendMessage (h, WM_USER+0x1000 /*WM_ML_IPC*/,66, 0x0600 /*ML_IPC_SKIN_WADLG_GETFUNC*/);
+ if (a)
+ {
+ m_font= (HFONT)a;
+ SetWindowFont (m_hwnd, m_font, FALSE);
+ }
+ }
+ InvalidateRect (m_hwnd, NULL, TRUE);
+}
+
+void W_ListView::setallowfonts (int allow)
+{
+ m_allowfonts=allow;
+}
+
+void W_ListView::setwnd (HWND hwnd)
+{
+ m_hwnd = hwnd;
+ if (hwnd)
+ {
+ ListView_SetExtendedListViewStyle (hwnd, LVS_EX_FULLROWSELECT|LVS_EX_UNDERLINEHOT );
+ refreshFont ();
+ }
+}
diff --git a/Src/Plugins/Library/ml_bookmarks/listview.h b/Src/Plugins/Library/ml_bookmarks/listview.h
new file mode 100644
index 00000000..5938a4dc
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/listview.h
@@ -0,0 +1,144 @@
+/*
+** Copyright (C) 2003 Nullsoft, Inc.
+**
+** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
+** liable for any damages arising from the use of this software.
+**
+** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
+** alter it and redistribute it freely, subject to the following restrictions:
+**
+** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
+** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+**
+** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+**
+** 3. This notice may not be removed or altered from any source distribution.
+**
+*/
+#if 0
+#ifndef _LISTVIEW_H_
+#define _LISTVIEW_H_
+
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+
+class W_ListView
+{
+public:
+ W_ListView()
+ {
+ m_hwnd=NULL;
+ m_col=0;
+ m_allowfonts=1;
+ m_font=NULL;
+#ifndef GEN_ML_EXPORTS
+ m_libraryparent=NULL;
+#endif
+ }
+ W_ListView(HWND hwnd)
+ {
+ m_hwnd=NULL;
+ m_col=0;
+ m_allowfonts=1;
+ m_font=NULL;
+#ifndef GEN_ML_EXPORTS
+ m_libraryparent=NULL;
+#endif
+ setwnd(hwnd);
+ }
+ ~W_ListView()
+ {
+ if (m_font) DeleteFont(m_font);
+ m_font=0;
+ }
+
+ void refreshFont();
+
+#ifndef GEN_ML_EXPORTS
+ void setLibraryParentWnd(HWND hwndParent)
+ {
+ m_libraryparent=hwndParent;
+ }// for Winamp Font getting stuff
+#endif
+ void setallowfonts(int allow=1);
+ void setwnd(HWND hwnd);
+ void AddCol(char *text, int w);
+ int GetCount(void)
+ {
+ return ListView_GetItemCount(m_hwnd);
+ }
+ int GetParam(int p);
+ void DeleteItem(int n)
+ {
+ ListView_DeleteItem(m_hwnd,n);
+ }
+ void Clear(void)
+ {
+ ListView_DeleteAllItems(m_hwnd);
+ }
+ int GetSelected(int x)
+ {
+ return(ListView_GetItemState(m_hwnd, x, LVIS_SELECTED) & LVIS_SELECTED)?1:0;
+ }
+
+ int GetSelectedCount()
+ {
+ return ListView_GetSelectedCount(m_hwnd);
+ }
+
+ int GetSelectionMark()
+ {
+ return ListView_GetSelectionMark(m_hwnd);
+ }
+ void SetSelected(int x)
+ {
+ ListView_SetItemState(m_hwnd,x,LVIS_SELECTED,LVIS_SELECTED);
+ }
+ int InsertItem(int p, char *text, int param);
+ void GetItemRect(int i, RECT *r)
+ {
+ ListView_GetItemRect(m_hwnd, i, r, LVIR_BOUNDS);
+ }
+ void SetItemText(int p, int si, char *text);
+ void SetItemParam(int p, int param);
+
+ void GetText(int p, int si, char *text, int maxlen)
+ {
+ ListView_GetItemText(m_hwnd, p, si, text, maxlen);
+ }
+ int FindItemByParam(int param)
+ {
+ LVFINDINFO fi={LVFI_PARAM,0,param};
+ return ListView_FindItem(m_hwnd,-1,&fi);
+ }
+ int FindItemByPoint(int x, int y)
+ {
+ int l=GetCount();
+ for (int i=0;i<l;i++)
+ {
+ RECT r;
+ GetItemRect(i, &r);
+ if (r.left<=x && r.right>=x && r.top<=y && r.bottom>=y) return i;
+ }
+ return -1;
+ }
+ int GetColumnWidth(int col);
+ HWND getwnd(void)
+ {
+ return m_hwnd;
+ }
+
+protected:
+ HWND m_hwnd;
+ HFONT m_font;
+ int m_col;
+ int m_allowfonts;
+#ifndef GEN_ML_EXPORTS
+ HWND m_libraryparent;
+#endif
+};
+
+#endif//_LISTVIEW_H_
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/main.cpp b/Src/Plugins/Library/ml_bookmarks/main.cpp
new file mode 100644
index 00000000..c85674ba
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/main.cpp
@@ -0,0 +1,122 @@
+//#define PLUGIN_NAME "Nullsoft Bookmarks"
+#define PLUGIN_VERSION L"1.27"
+
+#include "Main.h"
+#include "../nu/AutoWide.h"
+#include <strsafe.h>
+#include "../../General/gen_ml/menu.h"
+#include "../../General/gen_ml/ml_ipc_0313.h"
+
+static int Init();
+static void Quit();
+
+extern "C" winampMediaLibraryPlugin plugin =
+{
+ MLHDR_VER,
+ "nullsoft(ml_bookmarks.dll)",
+ Init,
+ Quit,
+ bm_pluginMessageProc,
+ 0,
+ 0,
+ 0,
+};
+
+int bookmark_treeItem = 0;
+HMENU g_context_menus, g_context_menus2;
+HCURSOR hDragNDropCursor;
+C_Config *g_config;
+WNDPROC waProc=0;
+
+// wasabi based services for localisation support
+api_language *WASABI_API_LNG = 0;
+HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
+api_stats *AGAVE_API_STATS = 0;
+api_application *WASABI_API_APP = 0;
+
+static DWORD WINAPI wa_newWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (msg == WM_WA_IPC && lParam == IPC_ADDBOOKMARK && wParam && wParam != 666)
+ {
+ bookmark_notifyAdd(AutoWide((char*)wParam));
+ }
+ else if (msg == WM_WA_IPC && lParam == IPC_ADDBOOKMARKW && wParam && wParam != 666)
+ {
+ bookmark_notifyAdd((wchar_t*)wParam);
+ }
+ else if ((msg == WM_COMMAND || msg == WM_SYSCOMMAND) && LOWORD(wParam) == WINAMP_EDIT_BOOKMARKS)
+ {
+ mediaLibrary.ShowMediaLibrary();
+ mediaLibrary.SwitchToPluginView(bookmark_treeItem);
+ return 0;
+ }
+
+ if (waProc)
+ return (DWORD)CallWindowProcW(waProc, hwnd, msg, wParam, lParam);
+ else
+ return (DWORD)DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+int Init()
+{
+ waProc = (WNDPROC)SetWindowLongPtrW( plugin.hwndWinampParent, GWLP_WNDPROC, (LONG_PTR)wa_newWndProc );
+
+ mediaLibrary.library = plugin.hwndLibraryParent;
+ mediaLibrary.winamp = plugin.hwndWinampParent;
+ mediaLibrary.instance = plugin.hDllInstance;
+
+ waServiceFactory *sf = plugin.service->service_getServiceByGuid( languageApiGUID );
+ if ( sf )
+ WASABI_API_LNG = reinterpret_cast<api_language *>( sf->getInterface() );
+
+ sf = plugin.service->service_getServiceByGuid( AnonymousStatsGUID );
+ if ( sf )
+ AGAVE_API_STATS = reinterpret_cast<api_stats *>( sf->getInterface() );
+
+ sf = plugin.service->service_getServiceByGuid( applicationApiServiceGuid );
+ if ( sf )
+ WASABI_API_APP = reinterpret_cast<api_application *>( sf->getInterface() );
+
+ // need to have this initialised before we try to do anything with localisation features
+ WASABI_API_START_LANG( plugin.hDllInstance, MlBookmarkLangGUID );
+
+ static wchar_t szDescription[ 256 ];
+ StringCchPrintfW( szDescription, ARRAYSIZE( szDescription ), WASABI_API_LNGSTRINGW( IDS_NULLSOFT_BOOKMARKS ), PLUGIN_VERSION );
+ plugin.description = (char *)szDescription;
+
+ wchar_t inifile[ MAX_PATH ] = { 0 };
+ mediaLibrary.BuildPath( L"Plugins", inifile, MAX_PATH );
+ CreateDirectoryW( inifile, NULL );
+
+ mediaLibrary.BuildPath( L"Plugins\\gen_ml.ini", inifile, MAX_PATH );
+ g_config = new C_Config( inifile );
+
+ g_context_menus = WASABI_API_LOADMENU( IDR_MENU1 );
+ g_context_menus2 = WASABI_API_LOADMENU( IDR_MENU1 );
+ hDragNDropCursor = LoadCursor( GetModuleHandle( L"gen_ml.dll" ), MAKEINTRESOURCE( ML_IDC_DRAGDROP ) );
+
+ NAVINSERTSTRUCT nis = { 0 };
+ nis.item.cbSize = sizeof( NAVITEM );
+ nis.item.pszText = WASABI_API_LNGSTRINGW( IDS_BOOKMARKS );
+ nis.item.pszInvariant = L"Bookmarks";
+ nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL;
+ nis.item.iSelectedImage = nis.item.iImage = mediaLibrary.AddTreeImageBmp( IDB_TREEITEM_BOOKMARKS );
+
+ // 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 );
+ bookmark_treeItem = nvItem.id;
+
+ return 0;
+}
+
+void Quit()
+{
+ delete g_config;
+}
+
+extern "C" __declspec(dllexport) winampMediaLibraryPlugin *winampGetMediaLibraryPlugin()
+{
+ return &plugin;
+} \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/main.h b/Src/Plugins/Library/ml_bookmarks/main.h
new file mode 100644
index 00000000..d8c2f355
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/main.h
@@ -0,0 +1,28 @@
+#ifndef NULLSOFT_BOOKMARKS_MAIN_H
+#define NULLSOFT_BOOKMARKS_MAIN_H
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include "api__ml_bookmarks.h"
+
+#include "../Plugins/General/gen_ml/ml.h"
+#include "../nu/MediaLibraryInterface.h"
+
+#include "resource.h"
+
+#include "../winamp/wa_ipc.h"
+//#include "../Plugins/General/gen_ml/ml.h"
+#include "../Plugins/General/gen_ml/config.h"
+
+
+#define WINAMP_EDIT_BOOKMARKS 40320
+
+INT_PTR bm_pluginMessageProc( int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3 );
+
+extern winampMediaLibraryPlugin plugin;
+extern int bookmark_treeItem;
+
+void bookmark_notifyAdd( wchar_t *filenametitle );
+
+#endif // !NULLSOFT_BOOKMARKS_MAIN_H
diff --git a/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.rc b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.rc
new file mode 100644
index 00000000..f36fe7f8
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.rc
@@ -0,0 +1,186 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU
+BEGIN
+ POPUP "BMWnd"
+ BEGIN
+ MENUITEM "Play selection\tEnter", ID_BMWND_PLAYSELECTEDFILES
+ MENUITEM "Enqueue selection\tShift+Enter", ID_BMWND_ENQUEUESELECTEDFILES
+ MENUITEM "Send to:", ID_BMWND_SENDTO
+ MENUITEM SEPARATOR
+ MENUITEM "Select all\tCtrl+A", ID_BMWND_SELECTALL
+ MENUITEM SEPARATOR
+ MENUITEM "Remove selected bookmarks\tDel", ID_BMWND_REMOVESELECTEDBOOKMARKS
+ MENUITEM "Edit selected bookmarks\tCtrl+E", ID_BMWND_EDITSELECTEDBOOKMARKS
+ END
+ POPUP "BMWndIcon"
+ BEGIN
+ MENUITEM "Play all bookmarks\tEnter", ID_BMWND_PLAYSELECTEDFILES
+ MENUITEM "Enqueue all bookmarks\tShift+Enter", ID_BMWND_ENQUEUESELECTEDFILES
+ MENUITEM SEPARATOR
+ MENUITEM "Help", ID_BMWND_HELP
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_VIEW_BM DIALOGEX 0, 0, 186, 92
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
+EXSTYLE WS_EX_ACCEPTFILES | WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_TABSTOP,0,0,184,79
+ CONTROL "Play",IDC_BUTTON_PLAY,"Button",BS_OWNERDRAW | WS_TABSTOP,0,81,35,11
+ CONTROL "Enqueue",IDC_BUTTON_ENQUEUE,"Button",BS_OWNERDRAW | WS_TABSTOP,38,81,35,11
+ CONTROL "Edit",IDC_EDITBOOK,"Button",BS_OWNERDRAW | WS_TABSTOP,76,81,36,11
+ CONTROL "Delete",IDC_REMOVEBOOK,"Button",BS_OWNERDRAW | WS_TABSTOP,114,81,36,11
+END
+
+IDD_EDITBOOKMARK DIALOGEX 0, 0, 241, 65
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Edit Bookmark"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Title",IDC_STATIC,8,10,14,8,SS_CENTERIMAGE
+ EDITTEXT IDC_TITLE,28,7,206,14,ES_AUTOHSCROLL
+ LTEXT "File",IDC_STATIC,8,29,12,8,SS_CENTERIMAGE
+ EDITTEXT IDC_FILE,28,26,187,14,ES_AUTOHSCROLL
+ PUSHBUTTON "&...",IDC_EDIT_FN,218,25,16,15
+ DEFPUSHBUTTON "&OK",IDOK,6,44,50,14
+ PUSHBUTTON "&Cancel",IDCANCEL,60,44,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_EDITBOOKMARK, DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 234
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 58
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_TREEITEM_BOOKMARKS BITMAP "resources\\ti_bookmarks_16x16x16.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_VIEW_BM_ACCELERATORS ACCELERATORS
+BEGIN
+ "A", ID_BMWND_SELECTALL, VIRTKEY, CONTROL, NOINVERT
+ "E", ID_BMWND_EDITSELECTEDBOOKMARKS, VIRTKEY, CONTROL, NOINVERT
+ VK_DELETE, ID_BMWND_REMOVESELECTEDBOOKMARKS, VIRTKEY, NOINVERT
+ VK_RETURN, ID_BMWND_PLAYSELECTEDFILES, VIRTKEY, NOINVERT
+ VK_RETURN, ID_BMWND_ENQUEUESELECTEDFILES, VIRTKEY, SHIFT, NOINVERT
+ VK_RETURN, IDC_BUTTON_CUSTOM, VIRTKEY, SHIFT, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_NULLSOFT_BOOKMARKS "Nullsoft Bookmarks v%s"
+ 65535 "{A3A1E7C0-761B-4391-A08A-F0D7AF38931C}"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_BOOKMARKS "Bookmarks"
+ IDS_ADD_TO_BOOKMARKS "Add to bookmarks"
+ IDS_BOOKMARK_TITLE "Bookmark Title"
+ IDS_BOOKMARK_FN_URL "Bookmark Filename/URL"
+ IDS_BROWSE_FOR_BM_ENTRY "Browse for bookmark entry..."
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.sln b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.sln
new file mode 100644
index 00000000..746468be
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.sln
@@ -0,0 +1,30 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29509.3
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ml_bookmarks", "ml_bookmarks.vcxproj", "{24335E73-2704-466A-8265-4314DD99886A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {24335E73-2704-466A-8265-4314DD99886A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {24335E73-2704-466A-8265-4314DD99886A}.Debug|Win32.Build.0 = Debug|Win32
+ {24335E73-2704-466A-8265-4314DD99886A}.Debug|x64.ActiveCfg = Debug|x64
+ {24335E73-2704-466A-8265-4314DD99886A}.Debug|x64.Build.0 = Debug|x64
+ {24335E73-2704-466A-8265-4314DD99886A}.Release|Win32.ActiveCfg = Release|Win32
+ {24335E73-2704-466A-8265-4314DD99886A}.Release|Win32.Build.0 = Release|Win32
+ {24335E73-2704-466A-8265-4314DD99886A}.Release|x64.ActiveCfg = Release|x64
+ {24335E73-2704-466A-8265-4314DD99886A}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {91C2E933-BA43-4ADA-A8B4-B3A2E571BA11}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj
new file mode 100644
index 00000000..669a0893
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj
@@ -0,0 +1,317 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{24335E73-2704-466A-8265-4314DD99886A}</ProjectGuid>
+ <RootNamespace>ml_bookmarks</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ <EmbedManifest>true</EmbedManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <EmbedManifest>true</EmbedManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ <EmbedManifest>true</EmbedManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <EmbedManifest>true</EmbedManifest>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg">
+ <VcpkgEnableManifest>false</VcpkgEnableManifest>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Manifest>
+ <OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
+ </Manifest>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4302;4311;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Manifest>
+ <OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
+ </Manifest>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Manifest>
+ <OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
+ </Manifest>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;ML_BOOKMARKS_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <DisableSpecificWarnings>4302;4311;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ModuleDefinitionFile>
+ </ModuleDefinitionFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Manifest>
+ <OutputManifestFile>$(IntDir)$(TargetName)$(TargetExt).intermediate.manifest</OutputManifestFile>
+ </Manifest>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\General\gen_ml\config.cpp" />
+ <ClCompile Include="..\..\General\gen_ml\menu.cpp" />
+ <ClCompile Include="..\..\..\nu\DialogSkinner.cpp" />
+ <ClCompile Include="..\..\..\nu\listview.cpp" />
+ <ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp" />
+ <ClCompile Include="..\..\..\nu\menushortcuts.cpp" />
+ <ClCompile Include="bookmark.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="view.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\General\gen_ml\config.h" />
+ <ClInclude Include="..\..\General\gen_ml\menu.h" />
+ <ClInclude Include="..\..\..\nu\DialogSkinner.h" />
+ <ClInclude Include="..\..\..\nu\listview.h" />
+ <ClInclude Include="..\..\..\nu\MediaLibraryInterface.h" />
+ <ClInclude Include="..\..\..\nu\menushortcuts.h" />
+ <ClInclude Include="api__ml_bookmarks.h" />
+ <ClInclude Include="bookmark.h" />
+ <ClInclude Include="main.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="ml_bookmarks.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="resources\ti_bookmarks_16x16x16.bmp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
+ <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj.filters b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj.filters
new file mode 100644
index 00000000..7207ea75
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/ml_bookmarks.vcxproj.filters
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="view.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bookmark.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\General\gen_ml\config.cpp">
+ <Filter>Source Files\gen_ml</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\nu\DialogSkinner.cpp">
+ <Filter>Source Files\nu</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\nu\listview.cpp">
+ <Filter>Source Files\nu</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\nu\MediaLibraryInterface.cpp">
+ <Filter>Source Files\nu</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\General\gen_ml\menu.cpp">
+ <Filter>Source Files\gen_ml</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\nu\menushortcuts.cpp">
+ <Filter>Source Files\nu</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="api__ml_bookmarks.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="bookmark.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="main.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\General\gen_ml\config.h">
+ <Filter>Header Files\gen_ml</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\nu\DialogSkinner.h">
+ <Filter>Header Files\nu</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\nu\listview.h">
+ <Filter>Header Files\nu</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\nu\MediaLibraryInterface.h">
+ <Filter>Header Files\nu</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\General\gen_ml\menu.h">
+ <Filter>Header Files\gen_ml</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\nu\menushortcuts.h">
+ <Filter>Header Files\nu</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{b4c6c983-ad68-4d2d-a542-7f1bf6b1c155}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{f072eba6-51ff-4c40-b136-bf3c79f3e120}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{b04fff17-1af4-4d74-b609-169c1a32b097}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Image Files">
+ <UniqueIdentifier>{56f5b459-ac0f-423d-b448-563135bf4bd8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\gen_ml">
+ <UniqueIdentifier>{f4c07660-d9f0-42b1-8745-0d6446aef60f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\nu">
+ <UniqueIdentifier>{d31d9efd-4434-46c5-8d2d-8a894aa24055}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\gen_ml">
+ <UniqueIdentifier>{00b097a1-1383-414f-8c19-82f97c6d06a5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\nu">
+ <UniqueIdentifier>{8eaf67d8-c524-468a-a78b-334c69d1cf9e}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="ml_bookmarks.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="resources\ti_bookmarks_16x16x16.bmp">
+ <Filter>Image Files</Filter>
+ </Image>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/Plugins/Library/ml_bookmarks/resource.h b/Src/Plugins/Library/ml_bookmarks/resource.h
new file mode 100644
index 00000000..037b9841
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/resource.h
@@ -0,0 +1,46 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by ml_bookmarks.rc
+//
+#define IDS_BOOKMARKS 1
+#define IDS_ADD_TO_BOOKMARKS 2
+#define IDS_BOOKMARK_TITLE 3
+#define IDS_BOOKMARK_FN_URL 4
+#define IDS_BROWSE_FOR_BM_ENTRY 5
+#define IDR_MENU1 101
+#define IDD_VIEW_BM 102
+#define IDD_EDITBOOKMARK 103
+#define IDC_CURSOR1 105
+#define IDB_BITMAP1 106
+#define IDR_VIEW_BM_ACCELERATORS 111
+#define IDC_BUTTON_CUSTOM 1000
+#define IDC_LIST 1001
+#define IDC_BUTTON_PLAY 1002
+#define IDC_BUTTON_ENQUEUE 1003
+#define IDB_TREEITEM_BOOKMARKS 1003
+#define IDC_EDITBOOK 1004
+#define IDC_REMOVEBOOK 1005
+#define IDC_TITLE 1006
+#define IDC_FILE 1008
+#define IDC_EDIT_FN 1009
+#define ID_BMWND_PLAYSELECTEDFILES 40001
+#define ID_BMWND_ENQUEUESELECTEDFILES 40002
+#define ID_BMWND_REMOVESELECTEDBOOKMARKS 40003
+#define ID_BMWND_EDITSELECTEDBOOKMARKS 40004
+#define ID_BMWND_SELECTALL 40005
+#define ID_Menu 40006
+#define ID_BMWNDICON_HELP 40007
+#define ID_BMWND_HELP 40008
+#define ID_BMWND_SENDTO 40012
+#define IDS_NULLSOFT_BOOKMARKS 65534
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 114
+#define _APS_NEXT_COMMAND_VALUE 40013
+#define _APS_NEXT_CONTROL_VALUE 1010
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/Plugins/Library/ml_bookmarks/resources/ti_bookmarks_16x16x16.bmp b/Src/Plugins/Library/ml_bookmarks/resources/ti_bookmarks_16x16x16.bmp
new file mode 100644
index 00000000..92f58e77
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/resources/ti_bookmarks_16x16x16.bmp
Binary files differ
diff --git a/Src/Plugins/Library/ml_bookmarks/version.rc2 b/Src/Plugins/Library/ml_bookmarks/version.rc2
new file mode 100644
index 00000000..b5ce38cb
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "../../../Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,27,0,0
+ PRODUCTVERSION WINAMP_PRODUCTVER
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Winamp SA"
+ VALUE "FileDescription", "Winamp Media Library Plug-in"
+ VALUE "FileVersion", "1,27,0,0"
+ VALUE "InternalName", "Nullsoft Bookmarks"
+ VALUE "LegalCopyright", "Copyright © 2003-2023 Winamp SA"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "ml_bookmark.dll"
+ VALUE "ProductName", "Winamp"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/Src/Plugins/Library/ml_bookmarks/view.cpp b/Src/Plugins/Library/ml_bookmarks/view.cpp
new file mode 100644
index 00000000..f89196a0
--- /dev/null
+++ b/Src/Plugins/Library/ml_bookmarks/view.cpp
@@ -0,0 +1,1512 @@
+#include "main.h"
+#include "../nu/AutoCharFn.h"
+#include "../nu/DialogSkinner.h"
+#include "Bookmark.h"
+#include "../../General/gen_ml/ml_ipc.h"
+#include <string>
+#include "../nu/ListView.h"
+#include "../nu/AutoChar.h"
+#include "../nu/AutoWide.h"
+#include "../nu/menushortcuts.h"
+#include <strsafe.h>
+#include "../../General/gen_ml/menu.h"
+
+INT_PTR CALLBACK view_bmDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
+static W_ListView m_bmlist;
+static HWND m_headerhwnd, m_hwnd;
+extern C_Config *g_config;
+static int customAllowed, groupBtn = 1, enqueuedef;
+static viewButtons view;
+
+// used for the send-to menu bits
+static INT_PTR IPC_LIBRARY_SENDTOMENU;
+static librarySendToMenuStruct s;
+BOOL myMenu = FALSE;
+
+extern HMENU g_context_menus, g_context_menus2;
+extern HCURSOR hDragNDropCursor;
+
+static int bookmark_contextMenu( INT_PTR param1, HWND parent, POINTS pts );
+static void bookmarks_contextMenu( HWND hwndDlg, HWND from, int x, int y );
+static void bookmark_onTreeEnterDblClk();
+
+static int pluginHandleIpcMessage(int msg, int param)
+{
+ return (int)SendMessage(plugin.hwndLibraryParent, WM_ML_IPC, param, msg);
+}
+
+void bookmark_notifyAdd(wchar_t *filenametitle)
+{
+ if (!m_hwnd || !filenametitle) return;
+ int cnt=m_bmlist.GetCount();
+ m_bmlist.InsertItem(cnt,filenametitle+lstrlenW(filenametitle)+1,0);
+ m_bmlist.SetItemText(cnt,1,filenametitle);
+}
+
+INT_PTR bm_pluginMessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3)
+{
+ if (message_type == ML_MSG_NO_CONFIG)
+ {
+ return TRUE;
+ }
+ else if (message_type == ML_MSG_TREE_ONCLICK)
+ {
+ switch(param2)
+ {
+ case ML_ACTION_ENTER:
+ case ML_ACTION_DBLCLICK:
+ if (param1 == bookmark_treeItem)
+ bookmark_onTreeEnterDblClk();
+ break;
+ }
+ }
+ else if (message_type == ML_MSG_TREE_ONCREATEVIEW && param1 == bookmark_treeItem)
+ {
+ return (INT_PTR)WASABI_API_CREATEDIALOGW(IDD_VIEW_BM, (HWND)param2, view_bmDialogProc);
+ }
+ else if (message_type == ML_MSG_NAVIGATION_CONTEXTMENU)
+ {
+ return bookmark_contextMenu(param1, (HWND)param2, MAKEPOINTS(param3));
+ }
+ else if (message_type == ML_MSG_ONSENDTOBUILD)
+ {
+ if (!myMenu &&
+ (param1 == ML_TYPE_ITEMRECORDLISTW || param1 == ML_TYPE_ITEMRECORDLIST ||
+ param1 == ML_TYPE_FILENAMES || param1 == ML_TYPE_STREAMNAMES ||
+ param1 == ML_TYPE_FILENAMESW || param1 == ML_TYPE_STREAMNAMESW ||
+ param1 == ML_TYPE_CDTRACKS))
+ mediaLibrary.AddToSendTo(WASABI_API_LNGSTRINGW(IDS_ADD_TO_BOOKMARKS),
+ param2, (INT_PTR)bm_pluginMessageProc);
+ }
+ else if (message_type == ML_MSG_ONSENDTOSELECT || message_type == ML_MSG_TREE_ONDROPTARGET)
+ {
+ // set with droptarget defaults =)
+ UINT_PTR type = 0,data = 0;
+
+ if (message_type == ML_MSG_ONSENDTOSELECT)
+ {
+ if (param3 != (INT_PTR)bm_pluginMessageProc) return 0;
+
+ type=(int)param1;
+ data = (int)param2;
+ }
+ else
+ {
+ if (param1 != bookmark_treeItem) return 0;
+
+ type=(int)param2;
+ data=(int)param3;
+
+ if (!data)
+ {
+ return (type == ML_TYPE_ITEMRECORDLISTW || type == ML_TYPE_ITEMRECORDLIST ||
+ type == ML_TYPE_FILENAMES || type == ML_TYPE_STREAMNAMES ||
+ type == ML_TYPE_FILENAMESW || type == ML_TYPE_STREAMNAMESW ||
+ type == ML_TYPE_CDTRACKS ||
+ type == ML_TYPE_PLAYLIST || type == ML_TYPE_PLAYLISTS) ? 1 : -1;
+ }
+ }
+
+ if (data)
+ {
+ if (type == ML_TYPE_ITEMRECORDLIST || type == ML_TYPE_CDTRACKS)
+ {
+ itemRecordList *p=(itemRecordList*)data;
+ for (int x = 0; x < p->Size; x ++)
+ mediaLibrary.AddBookmarkW(AutoWide(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.AddBookmarkW(p->Items[x].filename);
+
+ return 1;
+ }
+ else if (type == ML_TYPE_FILENAMES || type == ML_TYPE_STREAMNAMES)
+ {
+ char *p=(char*)data;
+ while (p && *p)
+ {
+ mediaLibrary.AddBookmark(p);
+ p+=lstrlenA(p)+1;
+ }
+ return 1;
+ }
+ else if (type == ML_TYPE_FILENAMESW || type == ML_TYPE_STREAMNAMESW)
+ {
+ wchar_t *p=(wchar_t*)data;
+ while (p && *p)
+ {
+ mediaLibrary.AddBookmarkW(p);
+ p+=wcslen(p)+1;
+ }
+ return 1;
+ }
+ else if(type == ML_TYPE_PLAYLIST)
+ {
+ mediaLibrary.AddBookmarkW((wchar_t*)((mlPlaylist*)data)->filename);
+ return 1;
+ }
+ else if(type == ML_TYPE_PLAYLISTS)
+ {
+ mlPlaylist **playlists = (mlPlaylist **)data;
+ while (playlists && *playlists)
+ {
+ mlPlaylist *pl = *playlists;
+ mediaLibrary.AddBookmarkW((wchar_t*)pl->filename);
+ playlists++;
+ }
+ return 1;
+ }
+ }
+ }
+ else if (message_type == ML_MSG_VIEW_PLAY_ENQUEUE_CHANGE)
+ {
+ enqueuedef = (int)param1;
+ groupBtn = (int)param2;
+ PostMessage(m_hwnd, WM_APP + 104, param1, param2);
+ return 0;
+ }
+ return 0;
+}
+
+static void playFiles(int enqueue, int all)
+{
+ int cnt=0;
+ int l=m_bmlist.GetCount();
+ for(int i=0;i<l;i++)
+ {
+ if(all || m_bmlist.GetSelected(i))
+ {
+ if (!cnt)
+ {
+ if(!enqueue) SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_DELETE);
+ cnt++;
+ }
+ //send the file to winamp
+ COPYDATASTRUCT cds = {0};
+ cds.dwData = IPC_ENQUEUEFILEW;
+ wchar_t buf[1024] = {0};
+ m_bmlist.GetText(i,1,buf,sizeof(buf)-1);
+ buf[1023]=0;
+ cds.lpData = (void *) buf;
+ cds.cbData = (lstrlenW((wchar_t*)cds.lpData)+1)*sizeof(wchar_t); // include space for null char
+ SendMessage(plugin.hwndWinampParent,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
+ }
+ }
+ if (cnt)
+ {
+ if(!enqueue) SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_STARTPLAY);
+ }
+}
+
+static wchar_t *g_bmedit_fn, *g_bmedit_ft;
+
+static BOOL CALLBACK BookMarkEditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ SetDlgItemTextW(hwndDlg,IDC_TITLE,g_bmedit_ft);
+ SetDlgItemTextW(hwndDlg,IDC_FILE,g_bmedit_fn);
+ return 0;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ GetDlgItemTextW(hwndDlg,IDC_TITLE,g_bmedit_ft,1024);
+ GetDlgItemTextW(hwndDlg,IDC_FILE,g_bmedit_fn,1024);
+ case IDCANCEL:
+ EndDialog(hwndDlg,0);
+ return 0;
+ case IDC_EDIT_FN:
+ {
+ wchar_t fn[1024] = {0};
+ GetDlgItemTextW(hwndDlg,IDC_FILE,fn,1024);
+ OPENFILENAMEW of = {0};
+ of.lStructSize = sizeof(OPENFILENAMEW);
+ of.hwndOwner = hwndDlg;
+ of.nMaxFileTitle = 32;
+ of.lpstrFilter = (wchar_t*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,1,IPC_GET_EXTLISTW);
+ of.nMaxCustFilter = 1024;
+ of.lpstrFile = fn;
+ of.nMaxFile = 1024;
+ of.lpstrTitle = WASABI_API_LNGSTRINGW(IDS_BROWSE_FOR_BM_ENTRY);
+ of.Flags = OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_EXPLORER|
+ OFN_PATHMUSTEXIST|OFN_ENABLESIZING;
+
+ if(GetOpenFileNameW(&of))
+ {
+ SetDlgItemTextW(hwndDlg,IDC_FILE,fn);
+ }
+ GlobalFree((void*)of.lpstrFilter);
+ }
+ break;
+ }
+ return 0;
+ }
+ return 0;
+}
+
+static void readbookmarks(int play1enqueue2=0)
+{
+ if (!play1enqueue2) m_bmlist.Clear();
+
+ int x=0;
+ FILE *fp=NULL;
+ wchar_t *fnp=(wchar_t*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,666,IPC_ADDBOOKMARKW);
+ if ((unsigned int)fnp < 65536) return;
+
+ fp=_wfopen(fnp,L"rt");
+ if (fp)
+ {
+ while (1)
+ {
+ char ft[4096] = {0}, fn[4096] = {0};
+ fgets(fn,4096,fp);
+ if (feof(fp)) break;
+ fgets(ft,4096,fp);
+ if (feof(fp)) break;
+ if (ft[0] && fn[0])
+ {
+ if (fn[strlen(fn)-1]=='\n') fn[strlen(fn)-1]=0;
+ if (ft[strlen(ft)-1]=='\n') ft[strlen(ft)-1]=0;
+ if (ft[0] && fn[0])
+ {
+ if (!play1enqueue2)
+ {
+ m_bmlist.InsertItem(x,AutoWide(ft,CP_UTF8),0);
+ m_bmlist.SetItemText(x,1,AutoWide(fn,CP_UTF8));
+ }
+ else
+ {
+ if (!x)
+ {
+ if(play1enqueue2==1) SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_DELETE);
+ }
+ //send the file to winamp
+ COPYDATASTRUCT cds = {0};
+ cds.dwData = IPC_ENQUEUEFILEW;
+ cds.lpData = (void *)AutoWideDup(fn,CP_UTF8);
+ cds.cbData = (lstrlenW((wchar_t *) cds.lpData)+1)*sizeof(wchar_t); // include space for null char
+ SendMessage(plugin.hwndWinampParent,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
+ }
+ x++;
+ }
+ }
+ }
+ fclose(fp);
+ }
+
+ if (!play1enqueue2 && AGAVE_API_STATS)
+ {
+ AGAVE_API_STATS->SetStat(api_stats::BOOKMARK_COUNT, m_bmlist.GetCount());
+ }
+
+ if (x && play1enqueue2 == 1)
+ {
+ SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_STARTPLAY);
+ }
+}
+
+static void writebookmarks()
+{
+ wchar_t *fnp = (wchar_t *)SendMessage( plugin.hwndWinampParent, WM_WA_IPC, 666, IPC_ADDBOOKMARKW );
+
+ if ( (unsigned int)fnp < 65536 )
+ return;
+
+ BookmarkWriter bookmarks;
+ bookmarks.New( fnp );
+
+ int l = m_bmlist.GetCount();
+ for ( int x = 0; x < l; x++ )
+ {
+ wchar_t ftW[ 4096 ] = { 0 }, fnW[ 4096 ] = { 0 };
+ m_bmlist.GetText( x, 0, ftW, ARRAYSIZE( ftW ) );
+ m_bmlist.GetText( x, 1, fnW, ARRAYSIZE( fnW ) );
+ bookmarks.Write( AutoChar( fnW, CP_UTF8 ), AutoChar( ftW, CP_UTF8 ) );
+ }
+
+ bookmarks.Close();
+
+ fnp = (wchar_t *)SendMessage( plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_ADDBOOKMARKW );
+
+ if ( (unsigned int)fnp < 65536 )
+ return;
+
+ bookmarks.New( fnp );
+
+ for ( int x = 0; x < l; x++ )
+ {
+ char ft[ 4096 ] = { 0 }, fn[ 4096 ] = { 0 };
+
+ m_bmlist.GetText( x, 0, ft, sizeof( ft ) );
+ m_bmlist.GetText( x, 1, fn, sizeof( fn ) );
+
+ bookmarks.Write( fn, ft );
+ }
+
+ bookmarks.Close();
+}
+
+static void bookmark_onTreeEnterDblClk()
+{
+ int enq = ( ( !!( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) ) ^ ( !!g_config->ReadInt( L"enqueuedef", 0 ) ) );
+ readbookmarks( enq ? 2 : 1 );
+}
+
+void SyncMenuWithAccelerators(HWND hwndDlg, HMENU menu)
+{
+ HACCEL szAccel[24] = {0};
+ INT c = WASABI_API_APP->app_getAccelerators(hwndDlg, szAccel, sizeof(szAccel)/sizeof(szAccel[0]), FALSE);
+ AppendMenuShortcuts(menu, szAccel, c, MSF_REPLACE);
+}
+
+void SwapPlayEnqueueInMenu(HMENU listMenu)
+{
+ int playPos=-1, enqueuePos=-1;
+ MENUITEMINFOW playItem={sizeof(MENUITEMINFOW), 0,}, enqueueItem={sizeof(MENUITEMINFOW), 0,};
+
+ int numItems = GetMenuItemCount(listMenu);
+
+ for (int i=0;i<numItems;i++)
+ {
+ UINT id = GetMenuItemID(listMenu, i);
+ if (id == ID_BMWND_PLAYSELECTEDFILES)
+ {
+ playItem.fMask = MIIM_ID;
+ playPos = i;
+ GetMenuItemInfoW(listMenu, i, TRUE, &playItem);
+ }
+ else if (id == ID_BMWND_ENQUEUESELECTEDFILES)
+ {
+ enqueueItem.fMask = MIIM_ID;
+ enqueuePos= i;
+ GetMenuItemInfoW(listMenu, i, TRUE, &enqueueItem);
+ }
+ }
+
+ playItem.wID = ID_BMWND_ENQUEUESELECTEDFILES;
+ enqueueItem.wID = ID_BMWND_PLAYSELECTEDFILES;
+ SetMenuItemInfoW(listMenu, playPos, TRUE, &playItem);
+ SetMenuItemInfoW(listMenu, enqueuePos, TRUE, &enqueueItem);
+}
+
+void UpdateMenuItems(HWND hwndDlg, HMENU menu)
+{
+ bool swapPlayEnqueue=false;
+ if (g_config->ReadInt(L"enqueuedef", 0) == 1)
+ {
+ SwapPlayEnqueueInMenu(menu);
+ swapPlayEnqueue=true;
+ }
+
+ SyncMenuWithAccelerators(hwndDlg, menu);
+ if (swapPlayEnqueue) SwapPlayEnqueueInMenu(menu);
+}
+
+static int bookmark_contextMenu(INT_PTR param1, HWND hHost, POINTS pts)
+{
+ HNAVITEM hItem = (HNAVITEM)param1;
+ HNAVITEM myItem = MLNavCtrl_FindItemById(plugin.hwndLibraryParent, bookmark_treeItem);
+ if (hItem != myItem)
+ return FALSE;
+
+ POINT pt;
+ POINTSTOPOINT(pt, pts);
+ if (-1 == pt.x || -1 == pt.y)
+ {
+ NAVITEMGETRECT itemRect;
+ itemRect.fItem = FALSE;
+ itemRect.hItem = hItem;
+ if (MLNavItem_GetRect(plugin.hwndLibraryParent, &itemRect))
+ {
+ MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
+ pt.x = itemRect.rc.left + 2;
+ pt.y = itemRect.rc.top + 2;
+ }
+ }
+
+ HMENU menu=GetSubMenu(g_context_menus,1);
+
+ bool swapPlayEnqueue=false;
+ if (g_config->ReadInt(L"enqueuedef", 0) == 1)
+ {
+ SwapPlayEnqueueInMenu(menu);
+ swapPlayEnqueue=true;
+ }
+
+ if(!IsWindow(m_hwnd))
+ {
+ HACCEL accel = WASABI_API_LOADACCELERATORSW(IDR_VIEW_BM_ACCELERATORS);
+ int size = CopyAcceleratorTable(accel,0,0);
+ AppendMenuShortcuts(menu, &accel, size, MSF_REPLACE);
+ }
+ else
+ {
+ SyncMenuWithAccelerators(m_hwnd, menu);
+ }
+
+ if (swapPlayEnqueue)
+ SwapPlayEnqueueInMenu(menu);
+
+ int r = Menu_TrackPopup(plugin.hwndLibraryParent, menu,
+ TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_NONOTIFY,
+ pt.x, pt.y, hHost, NULL);
+ switch(r)
+ {
+ case ID_BMWND_PLAYSELECTEDFILES:
+ readbookmarks(1);
+ break;
+ case ID_BMWND_ENQUEUESELECTEDFILES:
+ readbookmarks(2);
+ break;
+ case ID_BMWND_HELP:
+ SENDWAIPC(plugin.hwndWinampParent, IPC_OPEN_URL, L"https://help.winamp.com/hc/articles/8105304048660-The-Winamp-Media-Library");
+ break;
+ }
+ Sleep(100);
+ MSG msg;
+ while(PeekMessage(&msg,NULL,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE)); //eat return
+ return TRUE;
+}
+
+static void bookmarks_contextMenu(HWND hwndDlg, HWND from, int x, int y)
+{
+ if (from != m_bmlist.getwnd())
+ return ;
+
+ POINT pt = {x,y};
+
+ if (x == -1 || y == -1) // x and y are -1 if the user invoked a shift-f10 popup menu
+ {
+ RECT itemRect = {0};
+ int selected = m_bmlist.GetNextSelected();
+ if (selected != -1) // if something is selected we'll drop the menu from there
+ {
+ m_bmlist.GetItemRect(selected, &itemRect);
+ ClientToScreen(hwndDlg, (POINT *)&itemRect);
+ }
+ else // otherwise we'll drop it from the top-left corner of the listview, adjusting for the header location
+ {
+ GetWindowRect(hwndDlg, &itemRect);
+
+ HWND hHeader = (HWND)SNDMSG(from, LVM_GETHEADER, 0, 0L);
+ RECT headerRect;
+ if ((WS_VISIBLE & GetWindowLongPtr(hHeader, GWL_STYLE)) && GetWindowRect(hHeader, &headerRect))
+ {
+ itemRect.top += (headerRect.bottom - headerRect.top);
+ }
+ }
+ x = itemRect.left;
+ y = itemRect.top;
+ }
+
+ HWND hHeader = (HWND)SNDMSG(from, LVM_GETHEADER, 0, 0L);
+ RECT headerRect;
+ if (0 == (WS_VISIBLE & GetWindowLongPtr(hHeader, GWL_STYLE)) || FALSE == GetWindowRect(hHeader, &headerRect))
+ {
+ SetRectEmpty(&headerRect);
+ }
+
+ if (FALSE != PtInRect(&headerRect, pt))
+ {
+ return;
+ }
+
+ HMENU menu=GetSubMenu(g_context_menus,0);
+ UpdateMenuItems(hwndDlg, menu);
+ ZeroMemory(&s, sizeof(librarySendToMenuStruct));
+
+ IPC_LIBRARY_SENDTOMENU = (INT_PTR)SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&"LibrarySendToMenu",IPC_REGISTER_WINAMP_IPCMESSAGE);
+ if (IPC_LIBRARY_SENDTOMENU > 65536 && SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)0,IPC_LIBRARY_SENDTOMENU)==0xffffffff)
+ {
+ s.mode = 1;
+ s.hwnd = hwndDlg;
+ s.data_type = ML_TYPE_FILENAMESW;
+ s.ctx[1] = 1;
+ s.build_hMenu = CreatePopupMenu();
+
+ MENUITEMINFOW mii = {0};
+ mii.cbSize = sizeof(MENUITEMINFOW);
+ mii.fMask = MIIM_SUBMENU;
+ mii.hSubMenu = s.build_hMenu;
+ SetMenuItemInfoW(menu, 2, TRUE, &mii);
+ }
+
+ UINT menuStatus;
+ if (m_bmlist.GetNextSelected(-1) == -1)
+ {
+ menuStatus = MF_BYCOMMAND | MF_GRAYED;
+ EnableMenuItem(menu, 2, MF_BYPOSITION | MF_GRAYED);
+ }
+ else
+ {
+ menuStatus = MF_BYCOMMAND | MF_ENABLED;
+ EnableMenuItem(menu, 2, MF_BYPOSITION | MF_ENABLED);
+ }
+
+ EnableMenuItem(menu, ID_BMWND_PLAYSELECTEDFILES, menuStatus);
+ EnableMenuItem(menu, ID_BMWND_ENQUEUESELECTEDFILES, menuStatus);
+ EnableMenuItem(menu, ID_BMWND_REMOVESELECTEDBOOKMARKS, menuStatus);
+ EnableMenuItem(menu, ID_BMWND_EDITSELECTEDBOOKMARKS, menuStatus);
+
+ int r = Menu_TrackPopup(plugin.hwndLibraryParent, menu,
+ TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
+ x, y, hwndDlg, NULL);
+ switch(LOWORD(r))
+ {
+ case ID_BMWND_PLAYSELECTEDFILES:
+ case ID_BMWND_ENQUEUESELECTEDFILES:
+ case ID_BMWND_REMOVESELECTEDBOOKMARKS:
+ case ID_BMWND_EDITSELECTEDBOOKMARKS:
+ case ID_BMWND_SELECTALL:
+ SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(r,0),0);
+ break;
+ default:
+ if (s.mode == 2)
+ {
+ s.menu_id = r;
+ if (SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU) == 0xffffffff)
+ {
+ s.mode=3;
+ s.data_type=ML_TYPE_FILENAMESW;
+
+ //std::vector<wchar_t> sendStr;
+ std::wstring sendStr;
+
+ int l=m_bmlist.GetCount();
+ for(int i=0;i<l;i++)
+ {
+ if (m_bmlist.GetSelected(i))
+ {
+ wchar_t buf[1023] = {0};
+ m_bmlist.GetText(i,1,buf,ARRAYSIZE(buf)-1);
+ // HAKAN: why (len + 1) ?
+ //sendStr.append(buf, wcslen(buf)+1);
+ sendStr.append(buf, wcslen(buf));
+ }
+ }
+ // HAKAN: No need to add trailing zero
+ //sendStr.push_back(0);
+
+ s.data = (void*)sendStr.c_str();
+
+ if(SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&s,IPC_LIBRARY_SENDTOMENU)!=1)
+ {
+ s.mode=3;
+ s.data_type=ML_TYPE_FILENAMES;
+
+ //std::vector<char> sendStrA;
+ std::string sendStrA;
+
+ int l=m_bmlist.GetCount();
+ for(int i=0;i<l;i++)
+ {
+ if (m_bmlist.GetSelected(i))
+ {
+ wchar_t buf[1023] = {0};
+ m_bmlist.GetText(i,1,buf,ARRAYSIZE(buf)-1);
+
+ // HAKAN: why (len + 1) ?
+ //sendStrA.append(AutoCharFn(buf), strlen(AutoCharFn(buf)) + 1);
+ sendStrA.append(AutoCharFn(buf), strlen(AutoCharFn(buf)));
+ }
+ }
+ // HAKAN: No need to add trailing zero
+ //sendStrA.push_back(0);
+
+ s.data = (void*)sendStrA.c_str();
+
+ SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&s,IPC_LIBRARY_SENDTOMENU);
+ }
+ }
+ }
+ break;
+ }
+
+ if (s.mode)
+ {
+ s.mode=4;
+ SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&s,IPC_LIBRARY_SENDTOMENU); // cleanup
+ }
+
+ if (NULL != s.build_hMenu)
+ {
+ DestroyMenu(s.build_hMenu);
+ s.build_hMenu = NULL;
+ }
+
+ Sleep(100);
+ MSG msg;
+ while(PeekMessage(&msg,NULL,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE)); //eat return
+}
+
+static HRGN g_rgnUpdate = NULL;
+static int offsetX = 0, offsetY = 0;
+
+typedef struct _LAYOUT
+{
+ INT id;
+ HWND hwnd;
+ INT x;
+ INT y;
+ INT cx;
+ INT cy;
+ DWORD flags;
+ HRGN rgn;
+}
+LAYOUT, PLAYOUT;
+
+#define SETLAYOUTPOS(_layout, _x, _y, _cx, _cy) { _layout->x=_x; _layout->y=_y;_layout->cx=_cx;_layout->cy=_cy;_layout->rgn=NULL; }
+#define SETLAYOUTFLAGS(_layout, _r) \
+ { \
+ BOOL fVis; \
+ fVis = (WS_VISIBLE & (LONG)GetWindowLongPtr(_layout->hwnd, GWL_STYLE)); \
+ if (_layout->x == _r.left && _layout->y == _r.top) _layout->flags |= SWP_NOMOVE; \
+ if (_layout->cx == (_r.right - _r.left) && _layout->cy == (_r.bottom - _r.top)) _layout->flags |= SWP_NOSIZE; \
+ if ((SWP_HIDEWINDOW & _layout->flags) && !fVis) _layout->flags &= ~SWP_HIDEWINDOW; \
+ if ((SWP_SHOWWINDOW & _layout->flags) && fVis) _layout->flags &= ~SWP_SHOWWINDOW; \
+ }
+
+#define LAYOUTNEEEDUPDATE(_layout) ((SWP_NOMOVE | SWP_NOSIZE) != ((SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_SHOWWINDOW) & _layout->flags))
+
+#define GROUP_MIN 0x1
+#define GROUP_MAX 0x2
+#define GROUP_STATUSBAR 0x1
+#define GROUP_MAIN 0x2
+
+static void LayoutWindows(HWND hwnd, BOOL fRedraw, BOOL fUpdateAll = FALSE)
+{
+ static INT controls[] =
+ {
+ GROUP_STATUSBAR, IDC_BUTTON_PLAY, IDC_BUTTON_ENQUEUE, IDC_BUTTON_CUSTOM, IDC_EDITBOOK, IDC_REMOVEBOOK,
+ GROUP_MAIN, IDC_LIST
+ };
+
+ INT index;
+ RECT rc;
+ RECT rg;
+ RECT ri;
+ LAYOUT layout[sizeof(controls)/sizeof(controls[0])], *pl;
+ BOOL skipgroup;
+ HRGN rgn = NULL;
+
+ GetClientRect(hwnd, &rc);
+ if ( rc.right == rc.left || rc.bottom == rc.top )
+ return;
+
+ if ( rc.right > WASABI_API_APP->getScaleX( 4 ) )
+ rc.right -= WASABI_API_APP->getScaleX( 4 );
+
+ SetRect(&rg, rc.left, rc.top, rc.right, rc.top);
+
+ pl = layout;
+ skipgroup = FALSE;
+
+ InvalidateRect( hwnd, NULL, TRUE );
+
+ for (index = 0; index < sizeof(controls) / sizeof(*controls); index++)
+ {
+ if ( controls[ index ] >= GROUP_MIN && controls[ index ] <= GROUP_MAX ) // group id
+ {
+ skipgroup = FALSE;
+ switch ( controls[ index ] )
+ {
+ case GROUP_STATUSBAR:
+ {
+ wchar_t buffer[ 128 ] = { 0 };
+ WASABI_API_LNGSTRINGW_BUF( IDC_BUTTON_PLAY, buffer, ARRAYSIZE( buffer ) );
+ LRESULT idealSize = MLSkinnedButton_GetIdealSize( GetDlgItem( hwnd, IDC_BUTTON_PLAY ), buffer );
+
+ SetRect( &rg, rc.left + WASABI_API_APP->getScaleX( 1 ),
+ rc.bottom - WASABI_API_APP->getScaleY( HIWORD( idealSize ) ), rc.right, rc.bottom );
+ rc.bottom = rg.top - WASABI_API_APP->getScaleY( 3 );
+ break;
+ }
+ case GROUP_MAIN:
+ SetRect( &rg, rc.left + WASABI_API_APP->getScaleX( 1 ), rc.top, rc.right, rc.bottom );
+ break;
+ }
+ continue;
+ }
+
+ if (skipgroup)
+ continue;
+
+ pl->id = controls[ index ];
+ pl->hwnd = GetDlgItem( hwnd, pl->id );
+ if (!pl->hwnd)
+ continue;
+
+ GetWindowRect(pl->hwnd, &ri);
+ MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT)&ri, 2);
+ pl->flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS;
+
+ switch ( pl->id )
+ {
+ case IDC_BUTTON_PLAY:
+ case IDC_BUTTON_ENQUEUE:
+ case IDC_BUTTON_CUSTOM:
+ case IDC_EDITBOOK:
+ case IDC_REMOVEBOOK:
+ if ( IDC_BUTTON_CUSTOM != pl->id || customAllowed )
+ {
+ if ( groupBtn && pl->id == IDC_BUTTON_PLAY && enqueuedef == 1 )
+ {
+ pl->flags |= SWP_HIDEWINDOW;
+ break;
+ }
+
+ if ( groupBtn && pl->id == IDC_BUTTON_ENQUEUE && enqueuedef != 1 )
+ {
+ pl->flags |= SWP_HIDEWINDOW;
+ break;
+ }
+
+ if ( groupBtn && ( pl->id == IDC_BUTTON_PLAY || pl->id == IDC_BUTTON_ENQUEUE ) && customAllowed )
+ {
+ pl->flags |= SWP_HIDEWINDOW;
+ break;
+ }
+
+ wchar_t buffer[ 128 ] = { 0 };
+ GetWindowTextW( pl->hwnd, buffer, ARRAYSIZE( buffer ) );
+ LRESULT idealSize = MLSkinnedButton_GetIdealSize( pl->hwnd, buffer );
+ LONG width = LOWORD( idealSize ) + WASABI_API_APP->getScaleX( 6 );
+ SETLAYOUTPOS( pl, rg.left, rg.bottom - WASABI_API_APP->getScaleY( HIWORD( idealSize ) ), width, WASABI_API_APP->getScaleY( HIWORD( idealSize ) ) );
+ pl->flags |= ( ( rg.right - rg.left ) > width ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
+ if ( SWP_SHOWWINDOW & pl->flags ) rg.left += ( pl->cx + WASABI_API_APP->getScaleX( 4 ) );
+ }
+ else
+ pl->flags |= SWP_HIDEWINDOW;
+ break;
+ case IDC_LIST:
+ pl->flags |= ( rg.top < rg.bottom ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
+ SETLAYOUTPOS( pl, rg.left, rg.top + WASABI_API_APP->getScaleY( 1 ),
+ rg.right - rg.left + WASABI_API_APP->getScaleY( 1 ),
+ ( rg.bottom - rg.top ) - WASABI_API_APP->getScaleY( 2 ) );
+ break;
+ }
+
+ SETLAYOUTFLAGS(pl, ri);
+ if ( LAYOUTNEEEDUPDATE( pl ) )
+ {
+ if ( SWP_NOSIZE == ( ( SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_NOSIZE ) & pl->flags ) &&
+ ri.left == ( pl->x + offsetX ) && ri.top == ( pl->y + offsetY ) && IsWindowVisible( pl->hwnd ) )
+ {
+ SetRect( &ri, pl->x, pl->y, pl->cx + pl->x, pl->y + pl->cy );
+ ValidateRect( hwnd, &ri );
+ }
+ pl++;
+ }
+ else if ( ( fRedraw || ( !offsetX && !offsetY ) ) && IsWindowVisible( pl->hwnd ) )
+ {
+ ValidateRect( hwnd, &ri );
+ if ( GetUpdateRect( pl->hwnd, NULL, FALSE ) )
+ {
+ if ( !rgn ) rgn = CreateRectRgn( 0, 0, 0, 0 );
+ GetUpdateRgn( pl->hwnd, rgn, FALSE );
+ OffsetRgn( rgn, pl->x, pl->y );
+ InvalidateRgn( hwnd, rgn, FALSE );
+ }
+ }
+ }
+
+ if ( pl != layout )
+ {
+ LAYOUT *pc;
+ HDWP hdwp = BeginDeferWindowPos( (INT)( pl - layout ) );
+ for ( pc = layout; pc < pl && hdwp; pc++ )
+ {
+ hdwp = DeferWindowPos( hdwp, pc->hwnd, NULL, pc->x, pc->y, pc->cx, pc->cy, pc->flags );
+ }
+
+ if ( hdwp )
+ EndDeferWindowPos( hdwp );
+
+ if ( !rgn )
+ rgn = CreateRectRgn( 0, 0, 0, 0 );
+
+ if ( fRedraw )
+ {
+ GetUpdateRgn( hwnd, rgn, FALSE );
+ for ( pc = layout; pc < pl && hdwp; pc++ )
+ {
+ if ( pc->rgn )
+ {
+ OffsetRgn( pc->rgn, pc->x, pc->y );
+ CombineRgn( rgn, rgn, pc->rgn, RGN_OR );
+ }
+ }
+
+ RedrawWindow( hwnd, NULL, rgn, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN );
+ }
+
+ if ( g_rgnUpdate )
+ {
+ GetUpdateRgn( hwnd, g_rgnUpdate, FALSE );
+ for ( pc = layout; pc < pl && hdwp; pc++ )
+ {
+ if ( pc->rgn )
+ {
+ OffsetRgn( pc->rgn, pc->x, pc->y );
+ CombineRgn( g_rgnUpdate, g_rgnUpdate, pc->rgn, RGN_OR );
+ }
+ }
+ }
+
+ for ( pc = layout; pc < pl && hdwp; pc++ )
+ if ( pc->rgn )
+ DeleteObject( pc->rgn );
+ }
+
+ if ( rgn )
+ DeleteObject( rgn );
+
+ ValidateRgn( hwnd, NULL );
+}
+
+static BOOL Bookmark_OnDisplayChange()
+{
+ ListView_SetTextColor(m_bmlist.getwnd(),dialogSkinner.Color(WADLG_ITEMFG));
+ ListView_SetBkColor(m_bmlist.getwnd(),dialogSkinner.Color(WADLG_ITEMBG));
+ ListView_SetTextBkColor(m_bmlist.getwnd(),dialogSkinner.Color(WADLG_ITEMBG));
+ m_bmlist.SetFont(dialogSkinner.GetFont());
+ LayoutWindows(m_hwnd, TRUE);
+ return 0;
+}
+
+static BOOL Bookmark_OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags)
+{
+ if (GetCapture()==hwnd)
+ {
+ POINT p={x,y};
+ ClientToScreen(hwnd,&p);
+
+ if (WindowFromPoint(p) == m_bmlist.getwnd())
+ {
+ SetCursor(hDragNDropCursor);
+ }
+ else
+ {
+ mlDropItemStruct m={0};
+ m.type=ML_TYPE_FILENAMES;
+ m.p=p;
+ pluginHandleIpcMessage(ML_IPC_HANDLEDRAG,(int)&m);
+ }
+ }
+ return FALSE;
+}
+
+static BOOL Bookmark_OnLButtonUp(HWND hwnd, int x, int y, UINT flags)
+{
+ if (GetCapture()==hwnd)
+ {
+ ReleaseCapture();
+ POINT p={x,y};
+ ClientToScreen(hwnd,&p);
+
+ if (WindowFromPoint(p) == m_bmlist.getwnd())
+ {
+ LVHITTESTINFO lvi;
+ lvi.pt=p;
+ ScreenToClient(m_bmlist.getwnd(),&lvi.pt);
+ ListView_HitTest(m_bmlist.getwnd(),&lvi);
+
+ int num_items = m_bmlist.GetCount();
+
+ int destination_position=lvi.iItem;
+ if ((lvi.flags & (LVHT_ONITEM)));
+ else if (lvi.flags & LVHT_ABOVE) destination_position=0;
+ else if (lvi.flags & (LVHT_BELOW|LVHT_NOWHERE )) destination_position=num_items;
+ else return 0;
+
+ int x = 0, dirty=0;
+
+ for (; x < num_items; x ++)
+ {
+ m_bmlist.SetItemParam(x,0);
+ }
+
+ for (x = 0; x < num_items; x ++)
+ {
+ int sel=m_bmlist.GetSelected(x);
+ if (sel && x != destination_position)
+ {
+ wchar_t ft[1024] = {0}, fn[1024] = {0};
+ m_bmlist.GetText(x,0,ft,ARRAYSIZE(ft));
+ m_bmlist.GetText(x,1,fn,ARRAYSIZE(fn));
+ m_bmlist.DeleteItem(x);
+ if (x < destination_position)
+ {
+ x--;
+ }
+
+ if (destination_position >= num_items) destination_position--;
+
+ m_bmlist.InsertItem(destination_position,ft,1);
+ m_bmlist.SetItemText(destination_position,1,fn);
+ // have to do this otherwise first item isn't correctly flagged & reselected
+ m_bmlist.SetItemParam(destination_position,1);
+
+ destination_position++;
+
+ dirty=1;
+ }
+ else if (sel) destination_position++;
+ }
+
+ int w=0;
+ for (x = 0; x < num_items; x ++)
+ {
+ if (m_bmlist.GetParam(x))
+ {
+ if (!w)
+ {
+ w=1;
+ ListView_SetItemState(m_bmlist.getwnd(),x,LVIS_FOCUSED,LVIS_FOCUSED);
+ }
+ m_bmlist.SetSelected(x);
+ }
+ }
+
+ if (dirty) writebookmarks();
+ }
+ else
+ {
+ mlDropItemStruct m={0};
+ m.type=ML_TYPE_FILENAMESW;
+ m.p=p;
+ m.flags=ML_HANDLEDRAG_FLAG_NOCURSOR;
+
+ pluginHandleIpcMessage(ML_IPC_HANDLEDRAG,(int)&m);
+
+ if (m.result>0)
+ {
+ wchar_t *buf=(wchar_t*)calloc(4096, sizeof(wchar_t));
+ size_t buf_size=4096;
+ size_t buf_pos=0;
+
+ int l=m_bmlist.GetCount();
+ for(int i=0;i<l;i++)
+ {
+ if (m_bmlist.GetSelected(i))
+ {
+ wchar_t tbuf[1024]={0};
+ m_bmlist.GetText(i,1,tbuf,ARRAYSIZE(tbuf)-1);
+ tbuf[1023]=0;
+ size_t newsize=buf_pos + wcslen(tbuf) + 1;
+ if (newsize < buf_size)
+ {
+ size_t old_buf_size=buf_size;
+ buf_size=newsize+4096;
+
+ wchar_t *data = (wchar_t*)realloc(buf, (buf_size + 1) * sizeof(wchar_t));
+ if (data)
+ {
+ buf=data;
+ }
+ else
+ {
+ data=(wchar_t*)calloc((buf_size + 1), sizeof(wchar_t));
+ if (data)
+ {
+ memcpy(data, buf, sizeof(wchar_t)*old_buf_size);
+ free(buf);
+ buf=data;
+ }
+ else buf_size = old_buf_size;
+ }
+ }
+ lstrcpynW(buf+buf_pos,tbuf,(int)buf_size);
+ buf_pos=newsize;
+ }
+ }
+ if (buf_pos)
+ {
+ buf[buf_pos]=0;
+ m.flags=0;
+ m.result=0;
+ m.data=(void*)buf;
+ pluginHandleIpcMessage(ML_IPC_HANDLEDROP,(int)&m);
+ }
+ free(buf);
+ }
+ }
+ }
+ return FALSE;
+}
+
+void Bookmark_SelectAll(void)
+{
+ LVITEM item;
+ item.state = LVIS_SELECTED;
+ item.stateMask = LVIS_SELECTED;
+ SendMessageW(m_bmlist.getwnd(), LVM_SETITEMSTATE, -1, (LPARAM)&item);
+}
+
+enum
+{
+ BPM_ECHO_WM_COMMAND = 0x1, // send WM_COMMAND and return value
+ BPM_WM_COMMAND = 0x2, // just send WM_COMMAND
+};
+
+BOOL Bookmark_ButtonPopupMenu( HWND hwndDlg, int buttonId, HMENU menu, int flags = 0 )
+{
+ RECT r;
+ HWND buttonHWND = GetDlgItem( hwndDlg, buttonId );
+ GetWindowRect( buttonHWND, &r );
+ UpdateMenuItems( hwndDlg, menu );
+ MLSkinnedButton_SetDropDownState( buttonHWND, TRUE );
+
+ UINT tpmFlags = TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_BOTTOMALIGN | TPM_LEFTALIGN;
+
+ if ( !( flags & BPM_WM_COMMAND ) )
+ tpmFlags |= TPM_RETURNCMD;
+
+ int x = Menu_TrackPopup( plugin.hwndLibraryParent, menu, tpmFlags, r.left, r.top, hwndDlg, NULL );
+
+ if ( ( flags & BPM_ECHO_WM_COMMAND ) && x )
+ SendMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( x, 0 ), 0 );
+
+ MLSkinnedButton_SetDropDownState( buttonHWND, FALSE );
+
+ return x;
+}
+
+static void Bookmark_Play(HWND hwndDlg, HWND from, UINT idFrom)
+{
+ HMENU listMenu = GetSubMenu(g_context_menus2, 0);
+ int count = GetMenuItemCount(listMenu);
+ if (count > 2)
+ {
+ for (int i = 2; i < count; i++)
+ {
+ DeleteMenu(listMenu, 2, MF_BYPOSITION);
+ }
+ }
+
+ Bookmark_ButtonPopupMenu(hwndDlg, idFrom, listMenu, BPM_WM_COMMAND);
+}
+
+static BOOL Bookmark_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
+{
+ switch(LOWORD(id))
+ {
+ case IDC_BUTTON_PLAY:
+ case ID_BMWND_PLAYSELECTEDFILES:
+ case IDC_BUTTON_ENQUEUE:
+ case ID_BMWND_ENQUEUESELECTEDFILES:
+ case IDC_BUTTON_CUSTOM:
+ {
+ if (codeNotify == MLBN_DROPDOWN)
+ {
+ Bookmark_Play(hwnd, hwndCtl, id);
+ }
+ else
+ {
+ int action;
+ if (LOWORD(id) == IDC_BUTTON_PLAY || LOWORD(id) == ID_BMWND_PLAYSELECTEDFILES)
+ {
+ action = (codeNotify == 1) ? g_config->ReadInt(L"enqueuedef", 0) == 1 : 0;
+ }
+ else if (LOWORD(id) == IDC_BUTTON_ENQUEUE || LOWORD(id) == ID_BMWND_ENQUEUESELECTEDFILES)
+ {
+ action = (codeNotify == 1) ? g_config->ReadInt(L"enqueuedef", 0) != 1 : 1;
+ }
+ else
+ break;
+
+ playFiles(action, 0);
+ }
+ break;
+ }
+ case ID_BMWND_EDITSELECTEDBOOKMARKS:
+ case IDC_EDITBOOK:
+ {
+ int dirty=0;
+ int x=0,l=m_bmlist.GetCount();
+ while (x < l)
+ {
+ if (m_bmlist.GetSelected(x))
+ {
+ dirty=1;
+ wchar_t fn[1024] = {0}, ft[1024] = {0};
+ m_bmlist.GetText(x,0,ft,ARRAYSIZE(ft));
+ m_bmlist.GetText(x,1,fn,ARRAYSIZE(fn));
+ g_bmedit_fn=fn;
+ g_bmedit_ft=ft;
+ WASABI_API_DIALOGBOXW(IDD_EDITBOOKMARK,hwnd,BookMarkEditProc);
+ m_bmlist.SetItemText(x,0,ft);
+ m_bmlist.SetItemText(x,1,fn);
+ }
+ x++;
+ }
+ if (dirty) writebookmarks();
+ }
+ break;
+ case ID_BMWND_REMOVESELECTEDBOOKMARKS:
+ case IDC_REMOVEBOOK: // remove
+ {
+ int dirty=0;
+ int x=0,l=m_bmlist.GetCount();
+ while (x < l)
+ {
+ if (m_bmlist.GetSelected(x))
+ {
+ dirty=1;
+ m_bmlist.DeleteItem(x);
+ l--;
+ }
+ else x++;
+ }
+ if (dirty) writebookmarks();
+ }
+ break;
+ case ID_BMWND_SELECTALL:
+ Bookmark_SelectAll();
+ break;
+ }
+ return FALSE;
+}
+
+static BOOL Bookmark_OnDestroy(HWND hwnd)
+{
+ if (m_bmlist.getwnd())
+ {
+ g_config->WriteInt(L"bm_col_title",m_bmlist.GetColumnWidth(0));
+ g_config->WriteInt(L"bm_col_filename",m_bmlist.GetColumnWidth(1));
+ }
+
+ m_hwnd=0;
+ return FALSE;
+}
+
+static void Bookmark_ManageButtons(HWND hwndDlg)
+{
+ int has_selection = m_bmlist.GetSelectedCount();
+
+ const int buttonids[] = { IDC_BUTTON_PLAY, IDC_BUTTON_ENQUEUE, IDC_BUTTON_CUSTOM, IDC_EDITBOOK, IDC_REMOVEBOOK};
+ for (size_t i = 0; i != sizeof(buttonids)/sizeof(buttonids[0]); i++)
+ {
+ HWND controlHWND = GetDlgItem(hwndDlg, buttonids[i]);
+ EnableWindow(controlHWND, has_selection);
+ }
+}
+
+static BOOL Bookmark_OnNotify( HWND hwnd, NMHDR *notification )
+{
+ if ( notification->idFrom == IDC_LIST )
+ {
+ if ( notification->code == NM_DBLCLK )
+ {
+ playFiles( ( !!( g_config->ReadInt( L"enqueuedef", 0 ) == 1 ) ) ^ ( !!( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) ), 0 );
+ }
+ else if ( notification->code == LVN_BEGINDRAG )
+ {
+ SetCapture( hwnd );
+ }
+ else if ( notification->code == LVN_ITEMCHANGED )
+ {
+ Bookmark_ManageButtons( hwnd );
+ }
+ }
+ return FALSE;
+}
+
+void Bookmark_UpdateButtonText(HWND hwndDlg, int _enqueuedef)
+{
+ if (groupBtn)
+ {
+ switch(_enqueuedef)
+ {
+ case 1:
+ SetDlgItemTextW(hwndDlg, IDC_BUTTON_PLAY, view.enqueue);
+ customAllowed = FALSE;
+ break;
+
+ default:
+ // v5.66+ - re-use the old predixis parts so the button can be used functionally via ml_enqplay
+ // pass the hwnd, button id and plug-in id so the ml plug-in can check things as needed
+ pluginMessage p = {ML_MSG_VIEW_BUTTON_HOOK_IN_USE, (INT_PTR)_enqueuedef, 0, 0};
+
+ wchar_t *pszTextW = (wchar_t *)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p);
+ if (pszTextW && pszTextW[0] != 0)
+ {
+ // set this to be a bit different so we can just use one button and not the
+ // mixable one as well (leaving that to prevent messing with the resources)
+ SetDlgItemTextW(hwndDlg, IDC_BUTTON_PLAY, pszTextW);
+ customAllowed = TRUE;
+ }
+ else
+ {
+ SetDlgItemTextW(hwndDlg, IDC_BUTTON_PLAY, view.play);
+ customAllowed = FALSE;
+ }
+ break;
+ }
+ }
+}
+
+static BOOL Bookmark_OnInitDialog( HWND hwndDlg, HWND hwndFocus, LPARAM lParam )
+{
+ m_hwnd = hwndDlg;
+ m_bmlist.setwnd( GetDlgItem( hwndDlg, IDC_LIST ) );
+
+ HACCEL accel = WASABI_API_LOADACCELERATORSW( IDR_VIEW_BM_ACCELERATORS );
+ if ( accel )
+ WASABI_API_APP->app_addAccelerators( hwndDlg, &accel, 1, TRANSLATE_MODE_CHILD );
+
+ if ( !view.play )
+ {
+ SENDMLIPC( plugin.hwndLibraryParent, ML_IPC_GET_VIEW_BUTTON_TEXT, (WPARAM)&view );
+ }
+
+ // check the column widths and ensure that if <=0 it'll re-show
+ // (based on some forum reports where the width is set to zero somehow)
+ // -> shouldn't annoy anyone but you never know with the users, heh
+ int col_width1 = g_config->ReadInt( L"bm_col_title", 400 );
+ if ( col_width1 <= 0 )
+ col_width1 = 400;
+
+ int col_width2 = g_config->ReadInt( L"bm_col_filename", 240 );
+ if ( col_width2 <= 0 )
+ col_width2 = 240;
+
+ m_bmlist.AddCol( WASABI_API_LNGSTRINGW( IDS_BOOKMARK_TITLE ), col_width1 );
+ m_bmlist.AddCol( WASABI_API_LNGSTRINGW( IDS_BOOKMARK_FN_URL ), col_width2 );
+
+ groupBtn = g_config->ReadInt( L"groupbtn", 1 );
+ enqueuedef = ( g_config->ReadInt( L"enqueuedef", 0 ) == 1 );
+
+ Bookmark_OnDisplayChange();
+
+ m_headerhwnd = ListView_GetHeader( m_bmlist.getwnd() );
+
+ // v5.66+ - re-use the old predixis parts so the button can be used functionally via ml_enqplay
+ // pass the hwnd, button id and plug-in id so the ml plug-in can check things as needed
+ pluginMessage p = { ML_MSG_VIEW_BUTTON_HOOK, (INT_PTR)hwndDlg, (INT_PTR)MAKELONG( IDC_BUTTON_CUSTOM, IDC_BUTTON_ENQUEUE ), (INT_PTR)L"ml_bookmark" };
+ wchar_t *pszTextW = (wchar_t *)SENDMLIPC( plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p );
+ if ( pszTextW && pszTextW[ 0 ] != 0 )
+ {
+ // set this to be a bit different so we can just use one button and not the
+ // mixable one as well (leaving that to prevent messing with the resources)
+ customAllowed = TRUE;
+ SetDlgItemTextW( hwndDlg, IDC_BUTTON_CUSTOM, pszTextW );
+ }
+ else
+ customAllowed = FALSE;
+
+ MLSKINWINDOW m = { 0 };
+ m.skinType = SKINNEDWND_TYPE_DIALOG;
+ m.style = SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT;
+ m.hwndToSkin = hwndDlg;
+ MLSkinWindow( plugin.hwndLibraryParent, &m );
+
+ m.skinType = SKINNEDWND_TYPE_LISTVIEW;
+ m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER | SWLVS_ALTERNATEITEMS;
+ m.hwndToSkin = m_bmlist.getwnd();
+ MLSkinWindow( mediaLibrary.library, &m );
+
+ m.skinType = SKINNEDWND_TYPE_BUTTON;
+ m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | ( groupBtn ? SWBS_SPLITBUTTON : 0 );
+ FLICKERFIX ff = { 0, FFM_ERASEINPAINT };
+ const int buttonids[] = { IDC_BUTTON_PLAY, IDC_BUTTON_ENQUEUE, IDC_BUTTON_CUSTOM };
+ for ( size_t i = 0; i != sizeof( buttonids ) / sizeof( buttonids[ 0 ] ); i++ )
+ {
+ ff.hwnd = m.hwndToSkin = GetDlgItem( hwndDlg, buttonids[ i ] );
+ if ( IsWindow( m.hwndToSkin ) )
+ {
+ MLSkinWindow( plugin.hwndLibraryParent, &m );
+ SENDMLIPC( plugin.hwndLibraryParent, ML_IPC_FLICKERFIX, (WPARAM)&ff );
+ }
+ }
+
+ m.style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS;
+ const int buttonidz[] = { IDC_EDITBOOK, IDC_REMOVEBOOK };
+ for ( size_t i = 0; i != sizeof( buttonidz ) / sizeof( buttonidz[ 0 ] ); i++ )
+ {
+ ff.hwnd = m.hwndToSkin = GetDlgItem( hwndDlg, buttonidz[ i ] );
+ if ( IsWindow( m.hwndToSkin ) )
+ {
+ MLSkinWindow( plugin.hwndLibraryParent, &m );
+ SENDMLIPC( plugin.hwndLibraryParent, ML_IPC_FLICKERFIX, (WPARAM)&ff );
+ }
+ }
+
+ Bookmark_ManageButtons( hwndDlg );
+ Bookmark_UpdateButtonText( hwndDlg, enqueuedef == 1 );
+
+ SetTimer( hwndDlg, 100, 15, NULL );
+
+ return TRUE;
+}
+
+static void Bookmark_OnTimer(HWND hwnd, UINT id)
+{
+ if (id == 100)
+ {
+ KillTimer(hwnd,100);
+ // populate list
+ readbookmarks();
+ }
+}
+
+void Bookmark_DropFiles(HWND hwnd, HDROP hDrop)
+{
+ wchar_t temp[2048] = {0};
+ int y = DragQueryFileW(hDrop, 0xffffffff, temp, 2048);
+
+ for (int x = 0; x < y; x ++)
+ {
+ DragQueryFileW(hDrop, x, temp, 2048);
+ mediaLibrary.AddBookmarkW(temp);
+ }
+}
+
+static BOOL Bookmark_OnMLDropItem(mlDropItemStruct *dis)
+{
+ if (dis)
+ {
+ if (dis->type != ML_TYPE_ITEMRECORDLISTW && dis->type != ML_TYPE_ITEMRECORDLIST &&
+ dis->type != ML_TYPE_FILENAMES && dis->type != ML_TYPE_FILENAMESW &&
+ dis->type != ML_TYPE_STREAMNAMES && dis->type != ML_TYPE_STREAMNAMESW &&
+ dis->type != ML_TYPE_CDTRACKS &&
+ dis->type != ML_TYPE_PLAYLIST && dis->type != ML_TYPE_PLAYLISTS)
+ {
+ dis->result=-1;
+ }
+ else
+ {
+ dis->result=1;
+ if (dis->data)
+ {
+ if (dis->type == ML_TYPE_ITEMRECORDLIST || dis->type == ML_TYPE_CDTRACKS)
+ {
+ itemRecordList *p=(itemRecordList *)dis->data;
+ for (int x = 0; x < p->Size; x ++)
+ mediaLibrary.AddBookmark(p->Items[x].filename);
+ }
+ else if (dis->type == ML_TYPE_ITEMRECORDLISTW)
+ {
+ itemRecordListW *p=(itemRecordListW *)dis->data;
+ for (int x = 0; x < p->Size; x ++)
+ mediaLibrary.AddBookmark(AutoChar(p->Items[x].filename));
+ }
+ else if (dis->type == ML_TYPE_FILENAMES || dis->type == ML_TYPE_STREAMNAMES) // playlist
+ {
+ char *p=(char*)dis->data;
+ while (p && *p)
+ {
+ mediaLibrary.AddBookmark(p);
+ p+=strlen(p)+1;
+ }
+ }
+ else if (dis->type == ML_TYPE_FILENAMESW || dis->type == ML_TYPE_STREAMNAMESW) // playlist
+ {
+ wchar_t *p=(wchar_t*)dis->data;
+ while (p && *p)
+ {
+ mediaLibrary.AddBookmarkW(p);
+ p+=wcslen(p)+1;
+ }
+ }
+ else if(dis->type == ML_TYPE_PLAYLIST)
+ {
+ mediaLibrary.AddBookmarkW((wchar_t*)((mlPlaylist*)dis->data)->filename);
+ }
+ else if(dis->type == ML_TYPE_PLAYLISTS)
+ {
+ mlPlaylist **playlists = (mlPlaylist **)dis->data;
+ while (playlists && *playlists)
+ {
+ mlPlaylist *pl = *playlists;
+ mediaLibrary.AddBookmarkW((wchar_t*)pl->filename);
+ playlists++;
+ }
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+#define HANDLE_ML_DROPITEM(func) case ML_CHILDIPC_DROPITEM: return Bookmark_OnMLDropItem((mlDropItemStruct *)wParam);
+INT_PTR CALLBACK view_bmDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
+{
+ INT_PTR a = dialogSkinner.Handle(hwndDlg, uMsg, wParam, lParam);
+ if (a) return a;
+
+ switch(uMsg)
+ {
+ HANDLE_MSG(hwndDlg, WM_INITDIALOG, Bookmark_OnInitDialog);
+ HANDLE_MSG(hwndDlg, WM_TIMER, Bookmark_OnTimer);
+ HANDLE_MSG(hwndDlg, WM_COMMAND, Bookmark_OnCommand);
+ HANDLE_MSG(hwndDlg, WM_DESTROY, Bookmark_OnDestroy);
+ HANDLE_MSG(hwndDlg, WM_MOUSEMOVE, Bookmark_OnMouseMove);
+ HANDLE_MSG(hwndDlg, WM_LBUTTONUP, Bookmark_OnLButtonUp);
+ HANDLE_MSG(hwndDlg, WM_DROPFILES, Bookmark_DropFiles);
+
+ case WM_WINDOWPOSCHANGED:
+ if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE) & ((WINDOWPOS*)lParam)->flags) ||
+ (SWP_FRAMECHANGED & ((WINDOWPOS*)lParam)->flags))
+ {
+ LayoutWindows(hwndDlg, !(SWP_NOREDRAW & ((WINDOWPOS*)lParam)->flags));
+ }
+ return 0;
+
+ case WM_USER + 0x200:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); // yes, we support no - redraw resize
+ return TRUE;
+
+ case WM_USER + 0x201:
+ offsetX = (short)LOWORD(wParam);
+ offsetY = (short)HIWORD(wParam);
+ g_rgnUpdate = (HRGN)lParam;
+ return TRUE;
+
+ case WM_PAINT:
+ {
+ int tab[] = { IDC_LIST|DCW_SUNKENBORDER};
+ dialogSkinner.Draw(hwndDlg, tab, sizeof(tab) / sizeof(tab[0]));
+ }
+ return 0;
+
+ case WM_INITMENUPOPUP:
+ if (wParam && (HMENU)wParam == s.build_hMenu && s.mode==1)
+ {
+ myMenu = TRUE;
+ if(SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU)==0xffffffff)
+ s.mode=2;
+ myMenu = FALSE;
+ }
+ return 0;
+
+ case WM_DISPLAYCHANGE:
+ return Bookmark_OnDisplayChange();
+
+ case WM_NOTIFY:
+ return Bookmark_OnNotify(hwndDlg, (LPNMHDR)lParam);
+
+ case WM_CONTEXTMENU:
+ bookmarks_contextMenu(hwndDlg, (HWND)wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ return 0;
+
+ case WM_APP + 104:
+ {
+ Bookmark_UpdateButtonText(hwndDlg, (int)wParam);
+ LayoutWindows(hwndDlg, TRUE);
+ return 0;
+ }
+
+ case WM_ML_CHILDIPC:
+ if (lParam == ML_CHILDIPC_DROPITEM && wParam)
+ HANDLE_ML_DROPITEM(Bookmark_OnMLDropItem);
+ }
+ return FALSE;
+} \ No newline at end of file