Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
144
Src/Plugins/General/gen_ml/ml_ex/ex.rc
Normal file
144
Src/Plugins/General/gen_ml/ml_ex/ex.rc
Normal file
|
@ -0,0 +1,144 @@
|
|||
//Microsoft Developer Studio 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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_VIEW_EX DIALOG DISCARDABLE 0, 0, 291, 274
|
||||
STYLE DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CONTROL "List4",IDC_LIST,"SysListView32",LVS_REPORT |
|
||||
LVS_SHOWSELALWAYS | LVS_OWNERDATA | WS_TABSTOP,0,13,289,
|
||||
246
|
||||
LTEXT "",IDC_STATUS,41,262,248,8
|
||||
LTEXT "Search:",IDC_STATIC,0,1,26,8
|
||||
EDITTEXT IDC_QUICKSEARCH,26,1,263,10,ES_AUTOHSCROLL | NOT
|
||||
WS_BORDER
|
||||
CONTROL "Config",IDC_BUTTON_CONFIG,"Button",BS_OWNERDRAW |
|
||||
WS_TABSTOP,2,261,35,11
|
||||
END
|
||||
|
||||
IDD_CONFIG DIALOG DISCARDABLE 0, 0, 200, 97
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Ex Configuration"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,75,76,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,143,76,50,14
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO DISCARDABLE
|
||||
BEGIN
|
||||
IDD_VIEW_EX, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 289
|
||||
END
|
||||
|
||||
IDD_CONFIG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 193
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 90
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// French (France) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_FRENCH, SUBLANG_FRENCH
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDR_CONTEXTMENUS MENU DISCARDABLE
|
||||
BEGIN
|
||||
POPUP "TreeItemContext"
|
||||
BEGIN
|
||||
MENUITEM "About Ex..", ID_ABOUT
|
||||
MENUITEM "Ex Configuration...", ID_CONFIG
|
||||
END
|
||||
END
|
||||
|
||||
#endif // French (France) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
152
Src/Plugins/General/gen_ml/ml_ex/ml_ex.dsp
Normal file
152
Src/Plugins/General/gen_ml/ml_ex/ml_ex.dsp
Normal file
|
@ -0,0 +1,152 @@
|
|||
# Microsoft Developer Studio Project File - Name="ml_ex" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=ml_ex - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ml_ex.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "ml_ex.mak" CFG="ml_ex - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "ml_ex - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "ml_ex - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "ml_ex - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ML_ex_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ML_ex_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "NDEBUG"
|
||||
# ADD RSC /l 0x40c /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /machine:I386 /out:"c:\progra~1\winamp\plugins\ml_ex.dll" /opt:nowin98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "ml_ex - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ML_ex_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ML_ex_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x40c /d "_DEBUG"
|
||||
# ADD RSC /l 0x40c /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"c:\progra~1\winamp\plugins\ml_ex.dll" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "ml_ex - Win32 Release"
|
||||
# Name "ml_ex - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\itemlist.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\listview.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ml_lib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\view_ex.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\childwnd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\winamp\ipc_pe.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\itemlist.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\listview.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\ml.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\winamp\wa_dlg.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\winamp\wa_ipc.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ex.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
29
Src/Plugins/General/gen_ml/ml_ex/ml_ex.dsw
Normal file
29
Src/Plugins/General/gen_ml/ml_ex/ml_ex.dsw
Normal file
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "ml_ex"=.\ml_ex.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
62
Src/Plugins/General/gen_ml/ml_ex/resource.h
Normal file
62
Src/Plugins/General/gen_ml/ml_ex/resource.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by ex.rc
|
||||
//
|
||||
#define IDD_DIALOG1 101
|
||||
#define IDR_CONTEXTMENUS 102
|
||||
#define IDD_SEND_FILES 103
|
||||
#define IDD_CONFIG 104
|
||||
#define IDD_EDIT_INFO 105
|
||||
#define IDD_VIEW_IPOD 221
|
||||
#define IDD_VIEW_NJB 221
|
||||
#define IDD_VIEW_EX 221
|
||||
#define IDD_INIT 222
|
||||
#define IDC_PROGRESS1 1000
|
||||
#define IDC_STATUS 1001
|
||||
#define IDC_EDIT_ARTIST 1002
|
||||
#define IDC_PROGRESS2 1002
|
||||
#define IDC_CHECK_ARTIST 1003
|
||||
#define IDC_CHECK_TITLE 1004
|
||||
#define IDC_CHECK_ALBUM 1005
|
||||
#define IDC_QUICKSEARCH 1006
|
||||
#define IDC_CHECK_TRACK 1006
|
||||
#define IDC_CHECK_GENRE 1007
|
||||
#define IDC_CHECK_YEAR 1008
|
||||
#define IDC_EDIT_TITLE 1009
|
||||
#define IDC_EDIT_ALBUM 1010
|
||||
#define IDC_BUTTON_AUTODETECT 1010
|
||||
#define IDC_EDIT_TRACK 1011
|
||||
#define IDC_CHECK1 1011
|
||||
#define IDC_EDIT_GENRE 1012
|
||||
#define IDC_DETECTDUPS 1012
|
||||
#define IDC_EDIT_YEAR 1013
|
||||
#define IDC_CURTRACKNAME 1013
|
||||
#define IDC_BUTTON_PLAY 1016
|
||||
#define IDC_BUTTON_ENQUEUE 1017
|
||||
#define IDC_BUTTON_REFRESH 1018
|
||||
#define IDC_BUTTON_CONFIG 1018
|
||||
#define IDC_IPODSTATUS 1030
|
||||
#define IDC_LIST 1031
|
||||
#define IDC_COMBO1 1032
|
||||
#define IDC_COMBO2 1033
|
||||
#define IDC_TEXT_GENRE 1039
|
||||
#define IDC_TEXT_BITRATE 1040
|
||||
#define ID_IPODWND_REMOVEFROMIPOD 40001
|
||||
#define ID_IPODTREEITEMCONTEXT_ABOUTIPOD 40002
|
||||
#define ID_ABOUT 40002
|
||||
#define ID_IPODTREEITEMCONTEXT_IPODCONFIGURATION 40003
|
||||
#define ID_CONFIG 40003
|
||||
#define ID_IPODWND_EDITITEMSINFORMATIONS 40004
|
||||
#define ID_IPODWND_PLAYSELECTEDFILES 40013
|
||||
#define ID_IPODWND_ENQUEUESELECTEDFILES 40014
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 106
|
||||
#define _APS_NEXT_COMMAND_VALUE 40005
|
||||
#define _APS_NEXT_CONTROL_VALUE 1014
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
888
Src/Plugins/General/gen_ml/ml_ex/view_ex.cpp
Normal file
888
Src/Plugins/General/gen_ml/ml_ex/view_ex.cpp
Normal file
|
@ -0,0 +1,888 @@
|
|||
/*
|
||||
** 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 <windowsx.h>
|
||||
#include <stdio.h>
|
||||
#include "../ml.h"
|
||||
#include "resource.h"
|
||||
#include "../listview.h"
|
||||
|
||||
#include "../childwnd.h"
|
||||
#include "../../winamp/wa_dlg.h"
|
||||
|
||||
#include "../itemlist.h"
|
||||
|
||||
|
||||
// configuration section in winamp.ini
|
||||
#define CONFIG_SEC "ml_ex"
|
||||
|
||||
|
||||
// columns in our big treeview
|
||||
#define COL_ARTIST 0
|
||||
#define COL_TITLE 1
|
||||
#define COL_ALBUM 2
|
||||
#define COL_LENGTH 3
|
||||
#define COL_TRACK 4
|
||||
#define COL_GENRE 5
|
||||
#define COL_YEAR 6
|
||||
#define COL_FILENAME 7
|
||||
|
||||
// makes a NULL char * an empty string
|
||||
#define MAKESAFE(x) ((x)?(x):"")
|
||||
|
||||
|
||||
// yes, we could easily use an itemRecord / itemRecordList here instead of 'Song's, but the point of this example
|
||||
// is to show how to integrate with some other native structure
|
||||
typedef struct
|
||||
{
|
||||
char *artist;
|
||||
char *title;
|
||||
char *album;
|
||||
int songlen; // seconds?
|
||||
int track_nr;
|
||||
char *genre;
|
||||
int year;
|
||||
char *filename;
|
||||
} Song;
|
||||
|
||||
|
||||
// our leading crap reduction agent for use with sorting/etc
|
||||
#define SKIP_THE_AND_WHITESPACE(x) { while (!isalnum(*x) && *x) x++; if (!_strnicmp(x,"the ",4)) x+=4; while (*x == ' ') x++; }
|
||||
|
||||
|
||||
extern winampMediaLibraryPlugin plugin;
|
||||
static int myParam; // param of our tree item
|
||||
static C_ItemList m_songs, *m_songs_sorted;
|
||||
static W_ListView m_list;
|
||||
static HWND m_hwnd;
|
||||
static HMENU m_context_menus;
|
||||
static int m_skinlistview_handle;
|
||||
|
||||
|
||||
void config(HWND parent);
|
||||
void sortResults();
|
||||
|
||||
static void deleteSongPtr(Song *song)
|
||||
{
|
||||
free(song->album);
|
||||
free(song->artist);
|
||||
free(song->title);
|
||||
free(song->genre);
|
||||
free(song->filename);
|
||||
free(song);
|
||||
}
|
||||
|
||||
static void clearSongList()
|
||||
{
|
||||
int i=m_songs.GetSize();
|
||||
while (i>0)
|
||||
{
|
||||
Song *song=(Song *)m_songs.Get(--i);
|
||||
deleteSongPtr(song);
|
||||
m_songs.Del(i);
|
||||
}
|
||||
}
|
||||
|
||||
// this doesnt actually alloc the memory for all the strings, just references them (so it is only temporarily valid at best)
|
||||
void SongsToItemList(itemRecordList *p, int all)
|
||||
{
|
||||
if (!m_hwnd) all=1;
|
||||
|
||||
p->Alloc=p->Size=0;
|
||||
p->Items=0;
|
||||
|
||||
C_ItemList *list=(C_ItemList *)m_songs_sorted;
|
||||
if (!list) { list=&m_songs; all=1; }
|
||||
|
||||
int x,l=list->GetSize();
|
||||
for (x = 0 ; x < l; x ++)
|
||||
{
|
||||
if (!all && !m_list.GetSelected(x)) continue;
|
||||
|
||||
allocRecordList(p,p->Size+1,256);
|
||||
if (!p->Items) break;
|
||||
|
||||
Song *s=(Song *)list->Get(x);
|
||||
|
||||
memset(&p->Items[p->Size],0,sizeof(itemRecord));
|
||||
p->Items[p->Size].album=s->album;
|
||||
p->Items[p->Size].artist=s->artist;
|
||||
p->Items[p->Size].title=s->title;
|
||||
p->Items[p->Size].genre=s->genre;
|
||||
p->Items[p->Size].filename=s->filename;
|
||||
p->Items[p->Size].track=s->track_nr;
|
||||
p->Items[p->Size].year=s->year;
|
||||
p->Items[p->Size].length=s->songlen;
|
||||
p->Size++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void playFiles(int enqueue, int all)
|
||||
{
|
||||
if (!m_songs_sorted) return;
|
||||
if (!m_hwnd && !all) return;
|
||||
|
||||
itemRecordList obj={0,};
|
||||
SongsToItemList(&obj,all);
|
||||
if (obj.Size)
|
||||
{
|
||||
mlSendToWinampStruct s={ML_TYPE_ITEMRECORDLIST,(void*)&obj,!!enqueue};
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&s,ML_IPC_SENDTOWINAMP);
|
||||
}
|
||||
free(obj.Items);
|
||||
}
|
||||
|
||||
|
||||
void addItemListToSongs(itemRecordList *p)
|
||||
{
|
||||
if (p) for (int x = 0 ; x < p->Size; x ++)
|
||||
{
|
||||
Song *s=(Song *)calloc(1,sizeof(Song));
|
||||
if (p->Items[x].album) s->album=_strdup(p->Items[x].album);
|
||||
if (p->Items[x].artist) s->artist=_strdup(p->Items[x].artist);
|
||||
if (p->Items[x].title) s->title=_strdup(p->Items[x].title);
|
||||
if (p->Items[x].genre) s->genre=_strdup(p->Items[x].genre);
|
||||
if (p->Items[x].filename) s->filename=_strdup(p->Items[x].filename);
|
||||
s->track_nr=p->Items[x].track;
|
||||
s->year=p->Items[x].year;
|
||||
s->songlen=p->Items[x].length;
|
||||
m_songs.Add((void*)s);
|
||||
}
|
||||
}
|
||||
|
||||
char *conf_file;
|
||||
int init() {
|
||||
mlAddTreeItemStruct mla={
|
||||
0, // if you used 0, it would put it on top level, or ML_TREEVIEW_ID_DEVICES
|
||||
"Item Cache Example",
|
||||
1,
|
||||
};
|
||||
conf_file=(char*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GETINIFILE); // get winamp.ini name :)
|
||||
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&mla,ML_IPC_ADDTREEITEM);
|
||||
myParam=mla.this_id;
|
||||
|
||||
m_context_menus=LoadMenu(plugin.hDllInstance,MAKEINTRESOURCE(IDR_CONTEXTMENUS));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
clearSongList();
|
||||
}
|
||||
|
||||
void loadSongList()
|
||||
{
|
||||
clearSongList();
|
||||
|
||||
// populate m_songs from whatever source we have
|
||||
Song *p=(Song *)calloc(sizeof(Song),1);
|
||||
p->filename = _strdup("http://www.firehose.net/~deadbeef/media/Misc/music/030223%20-%20pervert-in-a-satellite.mp3");
|
||||
p->album=_strdup("SEP");
|
||||
p->artist=_strdup("Nullsoft Band");
|
||||
p->genre=_strdup("Shit");
|
||||
p->songlen = 666;
|
||||
p->track_nr=1;
|
||||
p->title=_strdup("Pervert In A Satellite");
|
||||
p->year=2003;
|
||||
|
||||
m_songs.Add((void*)p);
|
||||
}
|
||||
|
||||
|
||||
// this is uberadvancedsearchtechnology[tm]
|
||||
static void parsequicksearch(char *out, char *in) // parses a list into a list of terms that we are searching for
|
||||
{
|
||||
int inquotes=0, neednull=0;
|
||||
while (*in)
|
||||
{
|
||||
char c=*in++;
|
||||
if (c != ' ' && c != '\t' && c != '\"')
|
||||
{
|
||||
neednull=1;
|
||||
*out++=c;
|
||||
}
|
||||
else if (c == '\"')
|
||||
{
|
||||
inquotes=!inquotes;
|
||||
if (!inquotes)
|
||||
{
|
||||
*out++=0;
|
||||
neednull=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inquotes) *out++=c;
|
||||
else if (neednull)
|
||||
{
|
||||
*out++=0;
|
||||
neednull=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*out++=0;
|
||||
*out++=0;
|
||||
}
|
||||
|
||||
static int in_string(char *string, char *substring)
|
||||
{
|
||||
if (!string) return 0;
|
||||
if (!*substring) return 1;
|
||||
int l=strlen(substring);
|
||||
while (string[0]) if (!_strnicmp(string++,substring,l)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void updateList()
|
||||
{
|
||||
if(!m_hwnd) return;
|
||||
|
||||
char filterstr[256],filteritems[300];
|
||||
GetDlgItemText(m_hwnd,IDC_QUICKSEARCH,filterstr,sizeof(filterstr)-1);
|
||||
parsequicksearch(filteritems,filterstr);
|
||||
|
||||
delete m_songs_sorted;
|
||||
m_songs_sorted=new C_ItemList;
|
||||
unsigned int totallen=0,filterlen=0,filterval=0;
|
||||
for(int i=0;i<m_songs.GetSize();i++)
|
||||
{
|
||||
Song *s=(Song *)m_songs.Get(i);
|
||||
totallen+=s->songlen;
|
||||
char year[32]="";
|
||||
if (s->year < 5000 && s->year > 0) sprintf(year,"%d",s->year);
|
||||
char *p=filteritems;
|
||||
if (*p)
|
||||
{
|
||||
while (*p)
|
||||
{
|
||||
// search for 'p' in the song
|
||||
if (!in_string(s->album,p) && !in_string(s->artist,p) && !in_string(s->title,p) && !in_string(s->genre,p) && !in_string(year,p))
|
||||
break;
|
||||
|
||||
p+=strlen(p)+1;
|
||||
}
|
||||
if (*p) continue;
|
||||
}
|
||||
filterval++;
|
||||
filterlen+=s->songlen;
|
||||
m_songs_sorted->Add((void *)s);
|
||||
}
|
||||
|
||||
sortResults();
|
||||
|
||||
char tmp[512];
|
||||
if (m_songs.GetSize() != m_songs_sorted->GetSize())
|
||||
wsprintf(tmp,"Found: %d items [%d:%02d:%02d]",
|
||||
m_songs_sorted->GetSize(),filterval,
|
||||
filterlen/3600,(filterlen/60)%60,filterlen%60);
|
||||
else
|
||||
wsprintf(tmp,"%d items [%d:%02d:%02d]",m_songs.GetSize(),totallen/3600,(totallen/60)%60,totallen%60);
|
||||
|
||||
SetDlgItemText(m_hwnd,IDC_STATUS,tmp);
|
||||
}
|
||||
|
||||
|
||||
static ChildWndResizeItem resize_rlist[]={
|
||||
{IDC_QUICKSEARCH,0x0010},
|
||||
{IDC_LIST,0x0011},
|
||||
{IDC_BUTTON_CONFIG,0x0101},
|
||||
{IDC_STATUS,0x0111}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int g_sortcol, g_sortdir;
|
||||
static int STRCMP_NULLOK(const char *pa, const char *pb)
|
||||
{
|
||||
if (!pa) pa="";
|
||||
else SKIP_THE_AND_WHITESPACE(pa)
|
||||
|
||||
if (!pb) pb="";
|
||||
else SKIP_THE_AND_WHITESPACE(pb)
|
||||
|
||||
return _stricmp(pa,pb);
|
||||
}
|
||||
|
||||
static int sortFunc(const void *elem1, const void *elem2)
|
||||
{
|
||||
Song *a=(Song *)*(void **)elem1;
|
||||
Song *b=(Song *)*(void **)elem2;
|
||||
|
||||
int use_by=g_sortcol;
|
||||
int use_dir=g_sortdir;
|
||||
|
||||
#define RETIFNZ(v) if ((v)<0) return use_dir?1:-1; if ((v)>0) return use_dir?-1:1;
|
||||
|
||||
// this might be too slow, but it'd be nice
|
||||
int x;
|
||||
for (x = 0; x < 4; x ++)
|
||||
{
|
||||
if (use_by == COL_YEAR) // year -> artist -> album -> track
|
||||
{
|
||||
int v1=a->year;
|
||||
int v2=b->year;
|
||||
if (v1<0)v1=0;
|
||||
if (v2<0)v2=0;
|
||||
RETIFNZ(v1-v2)
|
||||
use_by=COL_ARTIST;
|
||||
}
|
||||
else if (use_by == COL_TITLE) // title -> artist -> album -> track
|
||||
{
|
||||
int v=STRCMP_NULLOK(a->title,b->title);
|
||||
RETIFNZ(v)
|
||||
use_by=COL_ARTIST;
|
||||
}
|
||||
else if (use_by == COL_ARTIST) // artist -> album -> track -> title
|
||||
{
|
||||
int v=STRCMP_NULLOK(a->artist,b->artist);
|
||||
RETIFNZ(v)
|
||||
use_by=COL_ALBUM;
|
||||
}
|
||||
else if (use_by == COL_ALBUM) // album -> track -> title -> artist
|
||||
{
|
||||
int v=STRCMP_NULLOK(a->album,b->album);
|
||||
RETIFNZ(v)
|
||||
use_dir=0;
|
||||
use_by=COL_TRACK;
|
||||
}
|
||||
else if (use_by == COL_GENRE) // genre -> artist -> album -> track
|
||||
{
|
||||
int v=STRCMP_NULLOK(a->genre,b->genre);
|
||||
RETIFNZ(v)
|
||||
use_by=COL_ARTIST;
|
||||
}
|
||||
else if (use_by == COL_TRACK) // track -> title -> artist -> album
|
||||
{
|
||||
int v1=a->track_nr;
|
||||
int v2=b->track_nr;
|
||||
if (v1<0)v1=0;
|
||||
if (v2<0)v2=0;
|
||||
RETIFNZ(v1-v2)
|
||||
use_by=COL_TITLE;
|
||||
}
|
||||
else if (use_by == COL_LENGTH) // length -> artist -> album -> track
|
||||
{
|
||||
int v1=a->songlen;
|
||||
int v2=b->songlen;
|
||||
if (v1<0)v1=0;
|
||||
if (v2<0)v2=0;
|
||||
RETIFNZ(v1-v2)
|
||||
use_by=COL_ARTIST;
|
||||
}
|
||||
else break; // no sort order?
|
||||
}
|
||||
#undef RETIFNZ
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sortResults()
|
||||
{
|
||||
if (!m_songs_sorted) return;
|
||||
qsort(m_songs_sorted->GetAll(),m_songs_sorted->GetSize(),sizeof(void*),sortFunc);
|
||||
|
||||
ListView_SetItemCount(m_list.getwnd(),0);
|
||||
ListView_SetItemCount(m_list.getwnd(),m_songs_sorted->GetSize());
|
||||
ListView_RedrawItems(m_list.getwnd(),0,m_songs_sorted->GetSize()-1);
|
||||
}
|
||||
|
||||
int (*wad_getColor)(int idx);
|
||||
int (*wad_handleDialogMsgs)(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
void (*wad_DrawChildWindowBorders)(HWND hwndDlg, int *tab, int tabsize);
|
||||
void (*cr_init)(HWND hwndDlg, ChildWndResizeItem *list, int num);
|
||||
void (*cr_resize)(HWND hwndDlg, ChildWndResizeItem *list, int num);
|
||||
|
||||
|
||||
static BOOL CALLBACK dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
if (wad_handleDialogMsgs)
|
||||
{
|
||||
BOOL a=wad_handleDialogMsgs(hwndDlg,uMsg,wParam,lParam); if (a) return a;
|
||||
}
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_DISPLAYCHANGE:
|
||||
ListView_SetTextColor(m_list.getwnd(),wad_getColor?wad_getColor(WADLG_ITEMFG):RGB(0xff,0xff,0xff));
|
||||
ListView_SetBkColor(m_list.getwnd(),wad_getColor?wad_getColor(WADLG_ITEMBG):RGB(0x00,0x00,0x00));
|
||||
ListView_SetTextBkColor(m_list.getwnd(),wad_getColor?wad_getColor(WADLG_ITEMBG):RGB(0x00,0x00,0x00));
|
||||
m_list.refreshFont();
|
||||
return 0;
|
||||
case WM_INITDIALOG:
|
||||
m_hwnd=hwndDlg;
|
||||
|
||||
*(void **)&wad_getColor=(void*)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,1,ML_IPC_SKIN_WADLG_GETFUNC);
|
||||
*(void **)&wad_handleDialogMsgs=(void*)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,2,ML_IPC_SKIN_WADLG_GETFUNC);
|
||||
*(void **)&wad_DrawChildWindowBorders=(void*)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,3,ML_IPC_SKIN_WADLG_GETFUNC);
|
||||
|
||||
*(void **)&cr_init=(void*)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,32,ML_IPC_SKIN_WADLG_GETFUNC);
|
||||
// woof: *(void **)&cr_resize=(void*)SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,33,ML_IPC_SKIN_WADLG_GETFUNC);
|
||||
|
||||
if (cr_init) cr_init(hwndDlg,resize_rlist,sizeof(resize_rlist)/sizeof(resize_rlist[0]));
|
||||
|
||||
m_list.setLibraryParentWnd(plugin.hwndLibraryParent);
|
||||
m_list.setwnd(GetDlgItem(hwndDlg,IDC_LIST));
|
||||
m_list.AddCol("Artist",200);
|
||||
m_list.AddCol("Title",200);
|
||||
m_list.AddCol("Album",200);
|
||||
m_list.AddCol("Length",64);
|
||||
m_list.AddCol("Track #",64);
|
||||
m_list.AddCol("Genre",100);
|
||||
m_list.AddCol("Year",64);
|
||||
m_list.AddCol("Filename",80);
|
||||
ListView_SetTextColor(m_list.getwnd(),wad_getColor?wad_getColor(WADLG_ITEMFG):RGB(0xff,0xff,0xff));
|
||||
ListView_SetBkColor(m_list.getwnd(),wad_getColor?wad_getColor(WADLG_ITEMBG):RGB(0x00,0x00,0x00));
|
||||
ListView_SetTextBkColor(m_list.getwnd(),wad_getColor?wad_getColor(WADLG_ITEMBG):RGB(0x00,0x00,0x00));
|
||||
|
||||
g_sortdir=GetPrivateProfileInt(CONFIG_SEC,"sortdir",0,conf_file);
|
||||
g_sortcol=GetPrivateProfileInt(CONFIG_SEC,"sortcol",g_sortcol,conf_file);
|
||||
|
||||
m_skinlistview_handle=SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(int)m_list.getwnd(),ML_IPC_SKIN_LISTVIEW);
|
||||
|
||||
SetTimer(hwndDlg,32,50,NULL);
|
||||
|
||||
return 0;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPNMHDR l=(LPNMHDR)lParam;
|
||||
if (l->idFrom==IDC_LIST)
|
||||
{
|
||||
if (l->code == NM_DBLCLK)
|
||||
{
|
||||
playFiles(!!(GetAsyncKeyState(VK_SHIFT)&0x8000),0);
|
||||
}
|
||||
else if (l->code == LVN_BEGINDRAG)
|
||||
{
|
||||
SetCapture(hwndDlg);
|
||||
}
|
||||
else if (l->code == LVN_ODFINDITEM) // yay we find an item (for kb shortcuts)
|
||||
{
|
||||
NMLVFINDITEM *t = (NMLVFINDITEM *)lParam;
|
||||
int i=t->iStart;
|
||||
if (i >= m_songs_sorted->GetSize()) i=0;
|
||||
|
||||
int cnt=m_songs_sorted->GetSize()-i;
|
||||
if (t->lvfi.flags & LVFI_WRAP) cnt+=i;
|
||||
|
||||
while (cnt-->0)
|
||||
{
|
||||
Song *thissong = (Song *)m_songs_sorted->Get(i);
|
||||
char tmp[128];
|
||||
char *name=0;
|
||||
|
||||
switch (g_sortcol)
|
||||
{
|
||||
case COL_ARTIST: name=thissong->artist; break;
|
||||
case COL_TITLE: name=thissong->title; break;
|
||||
case COL_ALBUM: name=thissong->album; break;
|
||||
case COL_LENGTH:
|
||||
wsprintf(tmp,"%d:%02d",thissong->songlen/60,(thissong->songlen)%60); name=tmp;
|
||||
break;
|
||||
case COL_TRACK: if (thissong->track_nr > 0 && thissong->track_nr < 1000) { wsprintf(tmp,"%d",thissong->track_nr); name=tmp; } break;
|
||||
case COL_GENRE: name=thissong->genre; break;
|
||||
case COL_YEAR: if (thissong->year < 5000 && thissong->year > 0) { wsprintf(tmp,"%d",thissong->year); name=tmp; } break;
|
||||
case COL_FILENAME: name=thissong->filename; break;
|
||||
}
|
||||
|
||||
|
||||
if (!name) name="";
|
||||
else SKIP_THE_AND_WHITESPACE(name)
|
||||
|
||||
if (t->lvfi.flags & (4|LVFI_PARTIAL))
|
||||
{
|
||||
if (!_strnicmp(name,t->lvfi.psz,strlen(t->lvfi.psz)))
|
||||
{
|
||||
SetWindowLong(hwndDlg,DWL_MSGRESULT,i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (t->lvfi.flags & LVFI_STRING)
|
||||
{
|
||||
if (!_stricmp(name,t->lvfi.psz))
|
||||
{
|
||||
SetWindowLong(hwndDlg,DWL_MSGRESULT,i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowLong(hwndDlg,DWL_MSGRESULT,-1);
|
||||
return 1;
|
||||
}
|
||||
if (++i == m_songs_sorted->GetSize()) i=0;
|
||||
}
|
||||
SetWindowLong(hwndDlg,DWL_MSGRESULT,-1);
|
||||
return 1;
|
||||
}
|
||||
else if (l->code == LVN_GETDISPINFO)
|
||||
{
|
||||
NMLVDISPINFO *lpdi = (NMLVDISPINFO*) lParam;
|
||||
int item=lpdi->item.iItem;
|
||||
|
||||
if (item < 0 || item >= m_songs_sorted->GetSize()) return 0;
|
||||
|
||||
Song *thissong = (Song *)m_songs_sorted->Get(item);
|
||||
|
||||
if (lpdi->item.mask & (LVIF_TEXT|/*LVIF_IMAGE*/0)) // we can always do images too :)
|
||||
{
|
||||
if (lpdi->item.mask & LVIF_TEXT)
|
||||
{
|
||||
char tmpbuf[128];
|
||||
char *nameptr=0;
|
||||
switch (lpdi->item.iSubItem)
|
||||
{
|
||||
case COL_ARTIST: nameptr=thissong->artist; break;
|
||||
case COL_TITLE: nameptr=thissong->title; break;
|
||||
case COL_ALBUM: nameptr=thissong->album; break;
|
||||
case COL_LENGTH:
|
||||
wsprintf(tmpbuf,"%d:%02d",thissong->songlen/60,(thissong->songlen)%60); nameptr=tmpbuf;
|
||||
break;
|
||||
case COL_TRACK: if (thissong->track_nr > 0 && thissong->track_nr < 1000) { wsprintf(tmpbuf,"%d",thissong->track_nr); nameptr=tmpbuf; } break;
|
||||
case COL_GENRE: nameptr=thissong->genre; break;
|
||||
case COL_YEAR: if (thissong->year>0 && thissong->year<5000) { wsprintf(tmpbuf,"%d",thissong->year); nameptr=tmpbuf; } break;
|
||||
case COL_FILENAME: nameptr=thissong->filename; break;
|
||||
}
|
||||
if (nameptr) lstrcpyn(lpdi->item.pszText,nameptr,lpdi->item.cchTextMax);
|
||||
else lpdi->item.pszText[0]=0;
|
||||
}
|
||||
// if(lpdi->item.mask & LVIF_IMAGE)
|
||||
} // bother
|
||||
return 0;
|
||||
} // LVN_GETDISPINFO
|
||||
else if (l->code == LVN_COLUMNCLICK)
|
||||
{
|
||||
NMLISTVIEW *p=(NMLISTVIEW*)lParam;
|
||||
if (p->iSubItem == g_sortcol) g_sortdir=!g_sortdir;
|
||||
else g_sortcol=p->iSubItem;
|
||||
|
||||
char str[32];
|
||||
sprintf(str,"%d",g_sortdir);
|
||||
WritePrivateProfileString(CONFIG_SEC,"sortdir",str,conf_file);
|
||||
sprintf(str,"%d",g_sortcol);
|
||||
WritePrivateProfileString(CONFIG_SEC,"sortcol",str,conf_file);
|
||||
|
||||
sortResults();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_BUTTON_CONFIG:
|
||||
config(hwndDlg);
|
||||
break;
|
||||
case IDC_QUICKSEARCH:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
{
|
||||
KillTimer(hwndDlg,500);
|
||||
SetTimer(hwndDlg,500,150,NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_TIMER:
|
||||
if (wParam == 500)
|
||||
{
|
||||
KillTimer(hwndDlg,500);
|
||||
char buf[256];
|
||||
GetDlgItemText(hwndDlg,IDC_QUICKSEARCH,buf,sizeof(buf));
|
||||
buf[255]=0;
|
||||
WritePrivateProfileString(CONFIG_SEC,"lastfilter",buf,conf_file);
|
||||
updateList();
|
||||
}
|
||||
else if (wParam == 32)
|
||||
{
|
||||
KillTimer(hwndDlg,32);
|
||||
if (!m_songs.GetSize()) loadSongList();
|
||||
char buf[256];
|
||||
GetPrivateProfileString(CONFIG_SEC,"lastfilter","",buf,sizeof(buf),conf_file);
|
||||
SetDlgItemText(hwndDlg,IDC_QUICKSEARCH,buf); // automatically updates the list via EN_CHANGE
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
#if 0 // BP:
|
||||
if (wParam != SIZE_MINIMIZED)
|
||||
{
|
||||
if (cr_resize) cr_resize(hwndDlg,resize_rlist,sizeof(resize_rlist)/sizeof(resize_rlist[0]));
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{
|
||||
if (wad_DrawChildWindowBorders)
|
||||
{
|
||||
int tab[] = { IDC_QUICKSEARCH|DCW_SUNKENBORDER, IDC_LIST|DCW_SUNKENBORDER};
|
||||
wad_DrawChildWindowBorders(hwndDlg,tab,2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
//clearSongList();
|
||||
m_hwnd=NULL;
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,m_skinlistview_handle,ML_IPC_UNSKIN_LISTVIEW);
|
||||
return 0;
|
||||
case WM_ML_CHILDIPC:
|
||||
if (lParam == ML_CHILDIPC_DROPITEM && wParam)
|
||||
{
|
||||
mlDropItemStruct *t=(mlDropItemStruct*)wParam;
|
||||
if (t->type == ML_TYPE_ITEMRECORDLIST) t->result=1;
|
||||
if (t->data)
|
||||
{
|
||||
if (t->type == ML_TYPE_ITEMRECORDLIST) // we got a drag&drop to our window, hot!
|
||||
{
|
||||
addItemListToSongs((itemRecordList*)t->data);
|
||||
updateList();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WM_LBUTTONUP:
|
||||
if (GetCapture() == hwndDlg)
|
||||
{
|
||||
ReleaseCapture();
|
||||
|
||||
POINT p;
|
||||
p.x=GET_X_LPARAM(lParam);
|
||||
p.y=GET_Y_LPARAM(lParam);
|
||||
ClientToScreen(hwndDlg,&p);
|
||||
|
||||
HWND h=WindowFromPoint(p);
|
||||
if (h != hwndDlg && !IsChild(hwndDlg,h))
|
||||
{
|
||||
mlDropItemStruct m={ML_TYPE_ITEMRECORDLIST,NULL,0};
|
||||
m.p=p;
|
||||
m.flags=ML_HANDLEDRAG_FLAG_NOCURSOR;
|
||||
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDRAG);
|
||||
|
||||
if (m.result>0)
|
||||
{
|
||||
itemRecordList o={0,};
|
||||
SongsToItemList(&o,0);
|
||||
if (o.Size)
|
||||
{
|
||||
//fill in this itemCacheObject if you want to provide drag&drop out of the window
|
||||
m.flags=0;
|
||||
m.result=0;
|
||||
m.data=(void*)&o;
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDROP);
|
||||
}
|
||||
free(o.Items);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
if (GetCapture()==hwndDlg)
|
||||
{
|
||||
POINT p;
|
||||
p.x=GET_X_LPARAM(lParam);
|
||||
p.y=GET_Y_LPARAM(lParam);
|
||||
ClientToScreen(hwndDlg,&p);
|
||||
mlDropItemStruct m={ML_TYPE_ITEMRECORDLIST,NULL,0};
|
||||
m.p=p;
|
||||
HWND h=WindowFromPoint(p);
|
||||
if (!h || h == hwndDlg || IsChild(hwndDlg,h))
|
||||
{
|
||||
SetCursor(LoadCursor(NULL,IDC_NO));
|
||||
}
|
||||
else
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDRAG);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK config_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
return 0;
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDOK:
|
||||
// save combo box
|
||||
case IDCANCEL:
|
||||
EndDialog(hwndDlg,LOWORD(wParam) == IDOK);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void config(HWND parent)
|
||||
{
|
||||
DialogBox(plugin.hDllInstance,MAKEINTRESOURCE(IDD_CONFIG),parent,config_dlgproc);
|
||||
}
|
||||
|
||||
int onTreeItemClick(int param, int action, HWND hwndParent) // if param is not yours, return 0
|
||||
{
|
||||
if (action == ML_ACTION_RCLICK)
|
||||
{
|
||||
POINT p;
|
||||
GetCursorPos(&p);
|
||||
int r=TrackPopupMenu(GetSubMenu(m_context_menus,0),TPM_RETURNCMD|TPM_RIGHTBUTTON|TPM_LEFTBUTTON|TPM_NONOTIFY,p.x,p.y,0,hwndParent,NULL);
|
||||
switch (r)
|
||||
{
|
||||
case ID_ABOUT:
|
||||
MessageBox(hwndParent,"ml_ex!!!","About ml_ex!!!",MB_OK);
|
||||
break;
|
||||
case ID_CONFIG:
|
||||
config(hwndParent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int onTreeItemDropTarget(int param, int type, void *obj)
|
||||
{
|
||||
if (type != ML_TYPE_ITEMRECORDLIST) return -1;
|
||||
|
||||
if (!obj) return 1;
|
||||
|
||||
// do somethihng with the itemCache object. do not free it however, since the caller owns it
|
||||
addItemListToSongs((itemRecordList*)obj);
|
||||
|
||||
updateList();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int onTreeItemDrag(int param, POINT p, int *type)
|
||||
{
|
||||
HWND h=WindowFromPoint(p);
|
||||
if (h && (h == m_hwnd || IsChild(m_hwnd,h))) return -1; // prevent from dropping into ourselves
|
||||
|
||||
|
||||
// if we wanted to be able to drag&drop our tree item to other people, we'd
|
||||
// return 1 and set type to ML_TYPE_ITEMRECORDLIST or ML_TYPE_FILENAMES etc.
|
||||
|
||||
// *type = ML_TYPE_ITEMRECORDLIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int onTreeItemDrop(int param, POINT p) // you should send the appropriate ML_IPC_HANDLEDROP if you support it
|
||||
{
|
||||
HWND h=WindowFromPoint(p);
|
||||
if (h && (h == m_hwnd || IsChild(m_hwnd,h))) return -1; // prevent from dropping into ourselves
|
||||
|
||||
// if we wanted to be able to drag&drop our tree item to other people, we'd
|
||||
// create an itemCacheObject or a doublenull terminated list (depending on what we want),
|
||||
// and send it back to the media library so it can route it to the appropriate destination:
|
||||
//
|
||||
// itemCacheObject o={0,};
|
||||
// fillInMyObject(&o);
|
||||
// mlDropItemStruct m={0,};
|
||||
// m.type = ML_TYPE_ITEMRECORDLIST;
|
||||
// m.data = (void*)&o;
|
||||
// m.p=p;
|
||||
// SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDROP);
|
||||
// freeMyObject(&o);
|
||||
|
||||
// or this:
|
||||
itemRecordList o={0,};
|
||||
SongsToItemList(&o,1);
|
||||
if (o.Size)
|
||||
{
|
||||
mlDropItemStruct m={0,};
|
||||
m.type = ML_TYPE_ITEMRECORDLIST;
|
||||
m.data = (void*)&o;
|
||||
m.p=p;
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&m,ML_IPC_HANDLEDROP);
|
||||
}
|
||||
free(o.Items);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int PluginMessageProc(int message_type, int param1, int param2, int param3)
|
||||
{
|
||||
// check for any global messages here
|
||||
|
||||
if (message_type >= ML_MSG_TREE_BEGIN && message_type <= ML_MSG_TREE_END)
|
||||
{
|
||||
if (param1 != myParam) return 0;
|
||||
// local messages for a tree item
|
||||
|
||||
switch (message_type)
|
||||
{
|
||||
case ML_MSG_TREE_ONCREATEVIEW:
|
||||
return (int)CreateDialog(plugin.hDllInstance,MAKEINTRESOURCE(IDD_VIEW_EX),(HWND)param2,dlgproc);
|
||||
case ML_MSG_TREE_ONCLICK:
|
||||
return onTreeItemClick(param1,param2,(HWND)param3);
|
||||
case ML_MSG_TREE_ONDROPTARGET:
|
||||
return onTreeItemDropTarget(param1,param2,(void*)param3);
|
||||
case ML_MSG_TREE_ONDRAG:
|
||||
return onTreeItemDrag(param1,*(POINT*)param2,(int*)param3);
|
||||
case ML_MSG_TREE_ONDROP:
|
||||
return onTreeItemDrop(param1,*(POINT*)param2);
|
||||
}
|
||||
}
|
||||
else if (message_type == ML_MSG_ONSENDTOBUILD)
|
||||
{
|
||||
if (param1 == ML_TYPE_ITEMRECORDLIST)
|
||||
{
|
||||
mlAddToSendToStruct s;
|
||||
s.context=param2;
|
||||
s.desc="ItemCacheEx";
|
||||
s.user32=(int)PluginMessageProc;
|
||||
SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&s,ML_IPC_ADDTOSENDTO);
|
||||
}
|
||||
}
|
||||
else if (message_type == ML_MSG_ONSENDTOSELECT)
|
||||
{
|
||||
if (param1 == ML_TYPE_ITEMRECORDLIST && param2 && param3 == (int)PluginMessageProc)
|
||||
{
|
||||
addItemListToSongs((itemRecordList*)param2);
|
||||
updateList();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
winampMediaLibraryPlugin plugin =
|
||||
{
|
||||
MLHDR_VER,
|
||||
"ml_ex v0.1",
|
||||
init,
|
||||
quit,
|
||||
PluginMessageProc,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
__declspec( dllexport ) winampMediaLibraryPlugin * winampGetMediaLibraryPlugin()
|
||||
{
|
||||
return &plugin;
|
||||
}
|
||||
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue