2024-09-24 12:54:57 +00:00
# include "main.h"
# include "ml_local.h"
2024-09-29 02:04:03 +00:00
# include <archx.h>
2024-09-24 12:54:57 +00:00
# include "../nu/listview.h"
# include "..\..\General\gen_ml/config.h"
# include "resource.h"
# include <time.h>
# include "..\..\General\gen_ml/ml_ipc.h"
# include "../ml_pmp/pmp.h"
# include "..\..\General\gen_ml/gaystring.h"
# include "../nde/nde.h"
# include "../replicant/nu/AutoWide.h"
# include "../replicant/nu/AutoChar.h"
# include "..\..\General\gen_ml/ml_ipc_0313.h"
# include <math.h>
# include <shlwapi.h>
# include <strsafe.h>
# include "..\..\General\gen_ml/menufucker.h"
# include "api_mldb.h"
# include "../replicant/foundation/error.h"
static wchar_t oldText [ 4096 ] ;
static int IPC_LIBRARY_SENDTOMENU ;
static HINSTANCE cloud_hinst ;
const int ML_MSG_PDXS_STATUS = 0x1001 ;
const int ML_MSG_PDXS_MIX = 0x1002 ;
void RefreshMetadata ( HWND parent ) ;
static HRGN g_rgnUpdate = NULL ;
static int offsetX , offsetY , customAllowed ;
int groupBtn = 1 , enqueuedef = 0 ;
static viewButtons view ;
HWND hwndSearchGlobal = 0 ;
//timers
# define TIMER_RATINGAUTOUNHOVER_ID 65520
# define TIMER_RATINGAUTOUNHOVER_DELAY 200
void FixAmps ( wchar_t * str , size_t len )
{
size_t realSize = 0 ;
size_t extra = 0 ;
wchar_t * itr = str ;
while ( itr & & * itr )
{
if ( itr & & * itr = = L ' & ' )
extra + + ;
itr + + ;
realSize + + ;
}
extra = min ( len - ( realSize + 1 ) , extra ) ;
while ( extra )
{
str [ extra + realSize ] = str [ realSize ] ;
if ( str [ realSize ] = = L ' & ' )
{
extra - - ;
str [ extra + realSize ] = L ' & ' ;
}
realSize - - ;
}
}
void MakeDateString ( __time64_t convertTime , wchar_t * dest , size_t destlen )
{
SYSTEMTIME sysTime ;
tm * newtime = _localtime64 ( & convertTime ) ;
if ( newtime )
{
sysTime . wYear = ( WORD ) ( newtime - > tm_year + 1900 ) ;
sysTime . wMonth = ( WORD ) ( newtime - > tm_mon + 1 ) ;
sysTime . wDayOfWeek = ( WORD ) newtime - > tm_wday ;
sysTime . wDay = ( WORD ) newtime - > tm_mday ;
sysTime . wHour = ( WORD ) newtime - > tm_hour ;
sysTime . wMinute = ( WORD ) newtime - > tm_min ;
sysTime . wSecond = ( WORD ) newtime - > tm_sec ;
sysTime . wMilliseconds = 0 ;
GetDateFormatW ( LOCALE_USER_DEFAULT , DATE_SHORTDATE , & sysTime , NULL , dest , destlen ) ;
size_t dateSize = lstrlenW ( dest ) ;
dest + = dateSize ;
destlen - = dateSize ;
if ( destlen )
{
* dest + + = L ' ' ;
destlen - - ;
}
GetTimeFormatW ( LOCALE_USER_DEFAULT , 0 , & sysTime , NULL , dest , destlen ) ;
//wcsftime(expire_time, 63, L"%b %d, %Y", _localtime64(&convertTime));
}
else
dest [ 0 ] = 0 ;
}
# define MAINTABLE_ID_CLOUD (unsigned char)-1
const unsigned char extra_idsW [ ] =
{
MAINTABLE_ID_ISPODCAST ,
MAINTABLE_ID_PODCASTCHANNEL ,
MAINTABLE_ID_PODCASTPUBDATE ,
MAINTABLE_ID_GRACENOTEFILEID ,
MAINTABLE_ID_GRACENOTEEXTDATA ,
MAINTABLE_ID_LOSSLESS ,
MAINTABLE_ID_CODEC ,
MAINTABLE_ID_DIRECTOR ,
MAINTABLE_ID_PRODUCER ,
MAINTABLE_ID_WIDTH ,
MAINTABLE_ID_HEIGHT ,
MAINTABLE_ID_MIMETYPE ,
0 ,
MAINTABLE_ID_DATEADDED ,
MAINTABLE_ID_CLOUD ,
} ;
const ExtendedFields extended_fields =
{
L " ispodcast " ,
L " podcastchannel " ,
L " podcastpubdate " ,
L " GracenoteFileID " ,
L " GracenoteExtData " ,
L " lossless " ,
L " codec " ,
L " director " ,
L " producer " ,
L " width " ,
L " height " ,
L " mime " ,
L " realsize " ,
L " dateadded " ,
L " cloud " ,
} ;
const wchar_t * extra_strsW [ ] =
{
extended_fields . ispodcast ,
extended_fields . podcastchannel ,
extended_fields . podcastpubdate ,
extended_fields . GracenoteFileID ,
extended_fields . GracenoteExtData ,
extended_fields . lossless ,
extended_fields . codec ,
extended_fields . director ,
extended_fields . producer ,
extended_fields . width ,
extended_fields . height ,
extended_fields . mimetype ,
extended_fields . realsize ,
extended_fields . dateadded ,
extended_fields . cloud ,
} ;
const int NUM_EXTRA_COLSW = sizeof ( extra_idsW ) / sizeof ( * extra_idsW ) ;
bool isMixable ( itemRecordW & song ) ;
static int predixisExist ;
static BOOL g_displaysearch = TRUE ;
static BOOL g_displaycontrols = TRUE ;
nde_scanner_t m_media_scanner = 0 ;
W_ListView resultlist ;
static int resultSkin ;
void fileInfoDialogs ( HWND hwndParent ) ;
void editInfo ( HWND hwndParent ) ;
void customizeColumnsDialog ( HWND hwndParent ) ;
static HWND m_hwnd ;
itemRecordListW itemCache ;
static int bgThread_Kill = 0 ;
static HANDLE bgThread_Handle ;
static bool isMixablePresent = true ;
CloudFiles cloudFiles , cloudUploading ;
typedef struct
{
UINT column_id ;
char * config_name ;
WORD defWidth ;
WORD minWidth ;
WORD maxWidth ;
}
headerColumn ;
# define UNLIMITED_WIDTH ((WORD)-1)
# define COLUMN_DEFMINWIDTH 12
# define COLUMN_DEFMAXWIDTH UNLIMITED_WIDTH
# define MAX_COLUMN_ORDER (MEDIAVIEW_COL_NUMS+1)
static headerColumn columnList [ MAX_COLUMN_ORDER - 1 ] =
{
{ IDS_ARTIST , " mv_col_artist " , 140 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_TITLE , " mv_col_title " , 140 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_ALBUM , " mv_col_album " , 140 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_LENGTH , " mv_col_length " , 55 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_TRACK_NUMBER , " mv_col_track " , 55 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_GENRE , " mv_col_genre " , 75 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_YEAR , " mv_col_year " , 55 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_FILENAME , " mv_col_fn " , 140 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_RATING , " mv_col_rating " , 65 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_PLAY_COUNT , " mv_col_playcount " , 70 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_PLAYED_LAST , " mv_col_lastplay " , 115 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_LAST_UPDATED , " mv_col_lastupd " , 115 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_FILE_TIME , " mv_col_filetime " , 115 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_COMMENT , " mv_col_comment " , 140 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_FILE_SIZE , " mb_col_filesize " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_BITRATE , " mb_col_bitrate " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_TYPE , " mb_col_type " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_DISC , " mb_col_disc " , 55 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_ALBUM_ARTIST , " mb_col_albumartist " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_FILE_PATH , " mb_col_filepath " , 140 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_ALBUM_GAIN , " mb_col_albumgain " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_TRACK_GAIN , " mb_col_trackgain " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_PUBLISHER , " mb_col_publisher " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_COMPOSER , " mb_col_composer " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_EXTENSION , " mb_col_extension " , 55 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_IS_PODCAST , " mb_col_ispodcast " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_PODCAST_CHANNEL , " mb_col_podcastchannel " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_PODCAST_PUBLISH_DATE , " mb_col_podcastpubdate " , 115 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_BPM , " mb_col_bpm " , 55 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_CATEGORY , " mb_col_category " , 75 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_DIRECTOR , " mb_col_director " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_PRODUCER , " mb_col_producer " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_DIMENSION , " mb_col_dimension " , 100 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_DATE_ADDED , " mb_col_dateadded " , 115 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
{ IDS_CLOUD , " mv_col_cloud " , 27 , COLUMN_DEFMINWIDTH , COLUMN_DEFMAXWIDTH } ,
} ;
//default column order
static signed char defColumnOrderCloud [ MAX_COLUMN_ORDER ] =
{
MEDIAVIEW_COL_ARTIST ,
MEDIAVIEW_COL_ALBUM ,
MEDIAVIEW_COL_TRACK ,
MEDIAVIEW_COL_CLOUD ,
MEDIAVIEW_COL_TITLE ,
MEDIAVIEW_COL_LENGTH ,
MEDIAVIEW_COL_GENRE ,
MEDIAVIEW_COL_RATING ,
MEDIAVIEW_COL_PLAYCOUNT ,
MEDIAVIEW_COL_LASTPLAY ,
MEDIAVIEW_COL_YEAR ,
- 1
} ;
static signed char defColumnOrder [ MAX_COLUMN_ORDER ] =
{
MEDIAVIEW_COL_ARTIST ,
MEDIAVIEW_COL_ALBUM ,
MEDIAVIEW_COL_TRACK ,
MEDIAVIEW_COL_TITLE ,
MEDIAVIEW_COL_LENGTH ,
MEDIAVIEW_COL_GENRE ,
MEDIAVIEW_COL_RATING ,
MEDIAVIEW_COL_PLAYCOUNT ,
MEDIAVIEW_COL_LASTPLAY ,
MEDIAVIEW_COL_YEAR ,
- 1
} ;
static signed char columnOrder [ MAX_COLUMN_ORDER ] ;
int WCSCMP_NULLOK ( const wchar_t * pa , const wchar_t * pb )
{
if ( ! pa ) pa = L " " ;
else SKIP_THE_AND_WHITESPACEW ( pa )
if ( ! pb ) pb = L " " ;
else SKIP_THE_AND_WHITESPACEW ( pb )
return CompareStringW ( LOCALE_USER_DEFAULT , NORM_IGNORECASE /*| NORM_IGNORENONSPACE*/ , pa , - 1 , pb , - 1 ) - 2 ;
// return lstrcmpi(pa, pb);
}
int FLOATWCMP_NULLOK ( const wchar_t * pa , const wchar_t * pb )
{
if ( pa ) SKIP_THE_AND_WHITESPACEW ( pa )
if ( pb ) SKIP_THE_AND_WHITESPACEW ( pb )
if ( ( ! pa | | ! * pa ) & & ( ! pb | | ! * pb ) )
return 0 ;
if ( ! pa | | ! * pa )
return 1 ;
if ( ! pb | | ! * pb )
return - 1 ;
_locale_t C_locale = WASABI_API_LNG - > Get_C_NumericLocale ( ) ;
float a = ( float ) _wtof_l ( pa , C_locale ) ;
float b = ( float ) _wtof_l ( pb , C_locale ) ;
if ( a > b )
return 1 ;
else if ( a < b )
return - 1 ;
else
return 0 ;
}
typedef struct
{
resultsniff_funcW cb ;
int user32 ;
}
bgThreadParms ;
static int bg_total_len_s ;
static __int64 bg_total_len_bytes ;
static LARGE_INTEGER querytime ;
static HMENU rate_hmenu = NULL ;
static HMENU cloud_hmenu = NULL ;
static HMENU sendto_hmenu = NULL ;
static librarySendToMenuStruct s ;
static RATINGCOLUMN ratingColumn ;
static WCHAR ratingBackText [ 128 ] ;
# define IDC_LIST2HEADER 2001 // WM_INITDIALOG assign this is to the IDC_LIST2 header
// internal messages
# define IM_SYNCHEADERORDER (WM_USER + 0xFFF0)
static DWORD WINAPI bgThreadQueryProc ( void * tmp )
{
bgThreadParms * p = ( bgThreadParms * ) tmp ;
bg_total_len_s = 0 ;
bg_total_len_bytes = 0 ;
LARGE_INTEGER starttime , endtime ;
QueryPerformanceCounter ( & starttime ) ;
bg_total_len_s = saveQueryToListW ( g_view_metaconf , m_media_scanner , & itemCache ,
& cloudFiles , & cloudUploading , p - > cb , p - > user32 ,
& bgThread_Kill , & bg_total_len_bytes ) ;
QueryPerformanceCounter ( & endtime ) ;
querytime . QuadPart = endtime . QuadPart - starttime . QuadPart ;
if ( ! bgThread_Kill ) PostMessage ( m_hwnd , WM_APP + 3 , 0x69 , 0 ) ;
return 0 ;
}
void bgQuery_Stop ( ) // exported for other people to call since it is useful (eventually
// we should have bgQuery pass the new query info along but I'll do that soon)
{
if ( bgThread_Handle )
{
bgThread_Kill = 1 ;
WaitForSingleObject ( bgThread_Handle , INFINITE ) ;
CloseHandle ( bgThread_Handle ) ;
bgThread_Handle = 0 ;
}
KillTimer ( m_hwnd , 123 ) ;
}
static void bgQuery ( resultsniff_funcW cb = 0 , int user32 = 0 ) // only internal used
{
bgQuery_Stop ( ) ;
SetDlgItemTextW ( m_hwnd , IDC_MEDIASTATUS , WASABI_API_LNGSTRINGW ( IDS_SCANNING ) ) ;
StringCchCopyW ( oldText , 4096 , WASABI_API_LNGSTRINGW ( IDS_SCANNING ) ) ;
SetTimer ( m_hwnd , 123 , 200 , NULL ) ;
DWORD id ;
static bgThreadParms parms ;
parms . cb = cb ;
parms . user32 = user32 ;
bgThread_Kill = 0 ;
bgThread_Handle = CreateThread ( NULL , 0 , bgThreadQueryProc , ( LPVOID ) & parms , 0 , & id ) ;
}
// this thing does not produce a fully valid itemRecordList. be afraid.
static void copyFilesToItemCacheW ( itemRecordListW * obj )
{
if ( bgThread_Handle ) return ;
int cnt = itemCache . Size ;
int i , l = cnt ;
cnt = 0 ;
for ( i = 0 ; i < l ; i + + )
{
if ( resultlist . GetSelected ( i ) ) cnt + + ;
}
obj - > Alloc = obj - > Size = 0 ;
if ( ! cnt ) return ;
allocRecordList ( obj , cnt , 0 ) ;
if ( ! obj - > Items )
{
obj - > Size = obj - > Alloc = 0 ;
return ;
}
for ( i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
obj - > Items [ obj - > Size + + ] = itemCache . Items [ i ] ;
// makes sure that we are providing filesize in kb as
// per spec even if we store it as __int64 internally
obj - > Items [ obj - > Size - 1 ] . filesize / = 1024 ;
}
}
}
void playFiles ( int enqueue , int all )
{
if ( bgThread_Handle ) return ;
int cnt = 0 ;
int l = itemCache . Size ;
int foo_all = 0 ; // all but play the only selected
int foo_selected = - 1 ;
if ( ! enqueue & & ! all & & g_config - > ReadInt ( L " viewplaymode " , 1 ) )
{
int selcnt = 0 ;
for ( int i = 0 ; i < l ; i + + )
{
if ( resultlist . GetSelected ( i ) ) selcnt + + ;
}
if ( selcnt = = 1 )
{
foo_all = - 1 ;
}
}
for ( int i = 0 ; i < l ; i + + )
{
if ( foo_all | | all | | resultlist . GetSelected ( i ) )
{
if ( foo_all & & foo_selected < 0 & & resultlist . GetSelected ( i ) ) foo_selected = i ;
if ( ! cnt )
{
if ( ! enqueue ) SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_DELETE ) ;
cnt + + ;
}
wchar_t title [ 2048 ] = { 0 } ;
TAG_FMT_EXT ( itemCache . Items [ i ] . filename , itemrecordWTagFunc , ndeTagFuncFree , ( void * ) & itemCache . Items [ i ] , title , 2048 , 0 ) ;
enqueueFileWithMetaStructW s ;
s . filename = itemCache . Items [ i ] . filename ;
s . title = title ;
s . ext = NULL ;
s . length = itemCache . Items [ i ] . length ;
# ifndef _DEBUG
ndestring_retain ( itemCache . Items [ i ] . filename ) ;
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_PLAYFILEW_NDE ) ;
# else
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_PLAYFILEW ) ;
# endif
}
}
if ( cnt )
{
if ( foo_selected > = 0 )
{
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , foo_selected , IPC_SETPLAYLISTPOS ) ;
SendMessage ( plugin . hwndWinampParent , WM_COMMAND , 40047 , 0 ) ; // stop button, literally
SendMessage ( plugin . hwndWinampParent , WM_COMMAND , 40045 , 0 ) ; // play button, literally
}
else if ( ! enqueue ) SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_STARTPLAY ) ;
}
}
// out can never be bigger than in+1
static void parsequicksearch ( wchar_t * out , wchar_t * in ) // parses a list into a list of terms that we are searching for
{
int inquotes = 0 , neednull = 0 ;
while ( in & & * in )
{
wchar_t 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 ;
}
void makeQueryStringFromText ( GayStringW * query , wchar_t * text , int nf )
{
int ispar = 0 ;
if ( query - > Get ( ) [ 0 ] )
{
ispar = 1 ;
query - > Append ( L " &( " ) ;
}
if ( ! _wcsnicmp ( text , L " query: " , 6 ) )
query - > Append ( text + 6 ) ; // copy the query as is
else if ( text [ 0 ] = = L ' ? ' )
query - > Append ( text + 1 ) ;
else
{
int isAny = 0 ;
if ( * text = = L ' * ' & & text [ 1 ] = = L ' ' )
{
isAny = 1 ;
text + = 2 ;
}
wchar_t tmpbuf [ 2048 + 32 ] = { 0 } ;
parsequicksearch ( tmpbuf , text ) ;
int x ;
wchar_t * fields [ ] =
{
L " filename " ,
L " title " ,
L " artist " ,
L " album " ,
L " genre " ,
L " albumartist " ,
L " publisher " ,
L " composer " ,
} ;
wchar_t * p = tmpbuf ;
while ( p & & * p )
{
size_t lenp = wcslen ( p ) ;
if ( p = = tmpbuf ) query - > Append ( L " ( " ) ;
else if ( isAny ) query - > Append ( L " )|( " ) ;
else query - > Append ( L " )&( " ) ;
if ( p [ 0 ] = = L ' < ' & & p [ wcslen ( p ) - 1 ] = = L ' > ' & & wcslen ( p ) > 2 )
{
wchar_t * op = p ;
while ( op & & * op )
{
if ( * op = = L ' \' ' ) * op = L ' \" ' ;
op + + ;
}
p [ lenp - 1 ] = 0 ; // remove >
query - > Append ( p + 1 ) ;
}
else
{
for ( x = 0 ; x < ( int ) min ( sizeof ( fields ) / sizeof ( fields [ 0 ] ) , nf ) ; x + + )
{
wchar_t * field = fields [ x ] ;
if ( x ) query - > Append ( L " | " ) ;
query - > Append ( field ) ;
query - > Append ( L " HAS \" " ) ;
GayStringW escaped ;
queryStrEscape ( p , escaped ) ;
query - > Append ( escaped . Get ( ) ) ;
query - > Append ( L " \" " ) ;
}
}
p + = lenp + 1 ;
}
query - > Append ( L " ) " ) ;
}
if ( ispar ) query - > Append ( L " ) " ) ;
}
static void doQuery ( HWND hwndDlg , wchar_t * text , int dobg = 1 )
{
bgQuery_Stop ( ) ;
GayStringW query ;
if ( text [ 0 ] ) makeQueryStringFromText ( & query , text ) ;
wchar_t * parent_query = NULL ;
extern wchar_t * m_query ;
parent_query = m_query ;
SendMessage ( GetParent ( hwndDlg ) , WM_APP + 2 , 0 , ( LPARAM ) & parent_query ) ;
GayStringW q ;
if ( parent_query & & parent_query [ 0 ] )
{
q . Set ( L " ( " ) ;
q . Append ( parent_query ) ;
q . Append ( L " ) " ) ;
}
if ( query . Get ( ) & & query . Get ( ) [ 0 ] )
{
if ( q . Get ( ) [ 0 ] )
{
q . Append ( L " & ( " ) ;
q . Append ( query . Get ( ) ) ;
q . Append ( L " ) " ) ;
}
else q . Set ( query . Get ( ) ) ;
}
EnterCriticalSection ( & g_db_cs ) ;
NDE_Scanner_Query ( m_media_scanner , q . Get ( ) ) ;
LeaveCriticalSection ( & g_db_cs ) ;
if ( dobg ) bgQuery ( ) ;
}
static void RecycleSelectedItems ( )
{
int totalItems = resultlist . GetSelectedCount ( ) ;
if ( ! totalItems )
return ;
SHFILEOPSTRUCTW fileOp ;
fileOp . hwnd = m_hwnd ;
fileOp . wFunc = FO_DELETE ;
fileOp . pFrom = 0 ;
fileOp . pTo = 0 ;
fileOp . fFlags = SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_USES_RECYCLEBIN ) ? FOF_ALLOWUNDO : 0 ;
fileOp . fAnyOperationsAborted = 0 ;
fileOp . hNameMappings = 0 ;
fileOp . lpszProgressTitle = 0 ;
EnterCriticalSection ( & g_db_cs ) ;
nde_scanner_t s = NDE_Table_CreateScanner ( g_table ) ;
int cchLen = totalItems * ( MAX_PATH + 1 ) + 1 ;
wchar_t * files = new wchar_t [ cchLen ] ; // need room for each file name, null terminated. then have to null terminate the whole list
if ( files ) // if malloc succeeded
{
wchar_t * curFile = files ;
for ( int i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
if ( NDE_Scanner_LocateNDEFilename ( s , MAINTABLE_ID_FILENAME , FIRST_RECORD , itemCache . Items [ i ] . filename ) )
{
StringCchCopyW ( curFile , cchLen , itemCache . Items [ i ] . filename ) ;
curFile + = wcslen ( itemCache . Items [ i ] . filename ) + 1 ;
}
}
}
if ( curFile ! = files )
{
curFile [ 0 ] = 0 ; // null terminate
fileOp . pFrom = files ;
fileOp . fAnyOperationsAborted = 0 ;
if ( SHFileOperationW ( & fileOp ) )
{
wchar_t title [ 64 ] = { 0 } ;
MessageBoxW ( m_hwnd , WASABI_API_LNGSTRINGW ( IDS_ERROR_DELETING_FILES ) ,
WASABI_API_LNGSTRINGW_BUF ( IDS_ERROR , title , 64 ) , MB_OK ) ;
}
else
{
// only remove items if deletion was allowed
if ( ! fileOp . fAnyOperationsAborted )
{
for ( int j = 0 ; j < itemCache . Size ; j + + )
{
if ( resultlist . GetSelected ( j ) )
{
if ( NDE_Scanner_LocateNDEFilename ( s , MAINTABLE_ID_FILENAME , FIRST_RECORD , itemCache . Items [ j ] . filename ) )
{
// Wasabi callback event for pre remove
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_REMOVED_PRE , ( size_t ) itemCache . Items [ j ] . filename , 0 ) ;
NDE_Scanner_Delete ( s ) ;
NDE_Scanner_Post ( s ) ;
g_table_dirty + + ;
// Wasabi callback event for post remove
// ToDo: (BigG) Move outside of critical section somehow
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_REMOVED_POST , ( size_t ) itemCache . Items [ j ] . filename , 0 ) ;
}
}
}
}
}
}
delete [ ] files ;
}
else // if malloc failed ... maybe because there's too many items.
{
files = new wchar_t [ MAX_PATH + 1 + 1 ] ; // double null termination
if ( ! files ) // if this malloc failed, just bail out
{
NDE_Table_DestroyScanner ( g_table , s ) ;
LeaveCriticalSection ( & g_db_cs ) ;
return ;
}
fileOp . pFrom = files ;
for ( int i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
if ( NDE_Scanner_LocateNDEFilename ( s , MAINTABLE_ID_FILENAME , FIRST_RECORD , itemCache . Items [ i ] . filename ) )
{
StringCchCopyW ( files , MAX_PATH + 1 + 1 , itemCache . Items [ i ] . filename ) ;
files [ wcslen ( itemCache . Items [ i ] . filename ) + 1 ] = 0 ; // double null terminate
fileOp . fAnyOperationsAborted = 0 ;
if ( SHFileOperationW ( & fileOp ) )
{
wchar_t mes [ 4096 ] = { 0 } ;
StringCchPrintfW ( mes , 4096 , WASABI_API_LNGSTRINGW ( IDS_ERROR_DELETING_X ) , files ) ;
MessageBoxW ( m_hwnd , mes , WASABI_API_LNGSTRINGW ( IDS_ERROR ) , MB_OK ) ;
continue ;
}
if ( ! fileOp . fAnyOperationsAborted )
{
// Wasabi callback event for pre remove
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_REMOVED_PRE , ( size_t ) itemCache . Items [ i ] . filename , 0 ) ;
NDE_Scanner_Delete ( s ) ;
NDE_Scanner_Post ( s ) ;
g_table_dirty + + ;
// Wasabi callback event for post remove
// ToDo: (BigG) Move outside of critical section somehow
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_REMOVED_POST , ( size_t ) itemCache . Items [ i ] . filename , 0 ) ;
}
}
}
delete files ;
}
}
NDE_Table_DestroyScanner ( g_table , s ) ;
if ( g_table_dirty ) NDE_Table_Sync ( g_table ) ;
g_table_dirty = 0 ;
LeaveCriticalSection ( & g_db_cs ) ;
resultlist . Clear ( ) ;
emptyRecordList ( & itemCache ) ;
// this might be gay, refreshing it completely (i.e. the cursor pos gets put back to normal, etc),
// but really it is necessary for the view to be accurate.
SendMessage ( m_hwnd , WM_APP + 1 , 0 , 0 ) ; //refresh current view
}
static void removeSelectedItems ( int physical )
{
if ( physical )
{
RecycleSelectedItems ( ) ;
return ;
}
int hasdel = 0 ;
EnterCriticalSection ( & g_db_cs ) ;
nde_scanner_t s = NDE_Table_CreateScanner ( g_table ) ;
for ( int i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
if ( NDE_Scanner_LocateNDEFilename ( s , MAINTABLE_ID_FILENAME , FIRST_RECORD , itemCache . Items [ i ] . filename ) )
{
wchar_t conf [ 32 ] = { 0 } ;
if ( ! hasdel & & MessageBoxW ( m_hwnd , WASABI_API_LNGSTRINGW ( IDS_SURE_YOU_WANT_TO_REMOVE_SELECTED_FROM_LIBRARY ) ,
WASABI_API_LNGSTRINGW_BUF ( IDS_CONFIRMATION , conf , 32 ) , MB_YESNO | MB_ICONQUESTION ) ! = IDYES )
{
NDE_Table_DestroyScanner ( g_table , s ) ;
LeaveCriticalSection ( & g_db_cs ) ;
return ;
//FUCKO> need to eat the RETURN msg
//MSG msg;
//while(PeekMessage(&msg,m_hwnd,WM_COMMAND,WM_COMMAND,1));
}
if ( ! hasdel ) // stop any background queries
{
bgQuery_Stop ( ) ;
}
// Wasabi callback event for pre remove
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_REMOVED_PRE , ( size_t ) itemCache . Items [ i ] . filename , 0 ) ;
hasdel = 1 ;
NDE_Scanner_Delete ( s ) ;
NDE_Scanner_Post ( s ) ;
g_table_dirty + + ;
// Wasabi callback event for post remove
// ToDo: (BigG) Move this outside of the critical section
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_REMOVED_POST , ( size_t ) itemCache . Items [ i ] . filename , 0 ) ;
}
}
}
NDE_Table_DestroyScanner ( g_table , s ) ;
if ( g_table_dirty ) NDE_Table_Sync ( g_table ) ;
g_table_dirty = 0 ;
LeaveCriticalSection ( & g_db_cs ) ;
if ( ! hasdel ) return ;
resultlist . Clear ( ) ;
emptyRecordList ( & itemCache ) ;
// this might be gay, refreshing it completely (i.e. the cursor pos gets put back to normal, etc),
// but really it is necessary for the view to be accurate.
SendMessage ( m_hwnd , WM_APP + 1 , 0 , 0 ) ; //refresh current view
}
static void exploreItemFolder ( HWND hwndDlg )
{
if ( resultlist . GetSelectionMark ( ) > = 0 )
{
int l = resultlist . GetCount ( ) ;
for ( int i = 0 ; i < l ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
WASABI_API_EXPLORERFINDFILE - > AddFile ( itemCache . Items [ i ] . filename ) ;
}
}
WASABI_API_EXPLORERFINDFILE - > ShowFiles ( ) ;
}
}
static void removeDeadFiles ( HWND hwndDlg )
{
Scan_RemoveFiles ( hwndDlg ) ;
// this might be gay, refreshing it completely (i.e. the cursor pos gets put back to normal, etc),
// but really it is necessary for the view to be accurate.
SendMessage ( m_hwnd , WM_APP + 1 , 0 , 0 ) ; //refresh current view
}
static WNDPROC search_oldWndProc ;
static DWORD WINAPI search_newWndProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
if ( uMsg = = WM_KEYDOWN & & wParam = = VK_DOWN )
{
PostMessageW ( GetParent ( hwndDlg ) , WM_NEXTDLGCTL , ( WPARAM ) resultlist . getwnd ( ) , ( LPARAM ) TRUE ) ;
ListView_SetItemState ( resultlist . getwnd ( ) , 0 , LVIS_FOCUSED | LVIS_SELECTED , LVIS_FOCUSED | LVIS_SELECTED ) ;
}
return CallWindowProcW ( search_oldWndProc , hwndDlg , uMsg , wParam , lParam ) ;
}
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 0x3
# define GROUP_SEARCH 0x1
# define GROUP_STATUSBAR 0x2
# define GROUP_MAIN 0x3
static void LayoutWindows ( HWND hwnd , BOOL fRedraw , BOOL fUpdateAll = FALSE )
{
static INT controls [ ] =
{
GROUP_SEARCH , IDC_SEARCHCAPTION , IDC_CLEAR , IDC_QUICKSEARCH ,
GROUP_STATUSBAR , IDC_BUTTON_PLAY , IDC_BUTTON_ENQUEUE , IDC_BUTTON_MIX , IDC_BUTTON_CREATEPLAYLIST , IDC_BUTTON_INFOTOGGLE , IDC_MIXABLE , IDC_MEDIASTATUS ,
GROUP_MAIN , IDC_LIST2
} ;
INT index ;
RECT rc , rg , ri ;
LAYOUT layout [ sizeof ( controls ) / sizeof ( controls [ 0 ] ) ] , * pl ;
BOOL skipgroup ;
HRGN rgn = NULL ;
GetClientRect ( hwnd , & rc ) ;
if ( rc . bottom = = rc . top | | rc . right = = rc . left ) return ;
SetRect ( & rg , rc . left , rc . top , rc . right , rc . bottom ) ;
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_SEARCH :
if ( g_displaysearch )
{
wchar_t buffer [ 128 ] = { 0 } ;
HWND ctrl = GetDlgItem ( hwnd , IDC_CLEAR ) ;
GetWindowTextW ( ctrl , buffer , ARRAYSIZE ( buffer ) ) ;
LRESULT idealSize = MLSkinnedButton_GetIdealSize ( ctrl , buffer ) ;
SetRect ( & rg , rc . left ,
rc . top + WASABI_API_APP - > getScaleY ( 2 ) ,
rc . right - WASABI_API_APP - > getScaleX ( 2 ) ,
rc . top + WASABI_API_APP - > getScaleY ( HIWORD ( idealSize ) + 1 ) ) ;
rc . top = rg . bottom + WASABI_API_APP - > getScaleY ( 3 ) ;
}
skipgroup = ! g_displaysearch ;
break ;
case GROUP_STATUSBAR :
if ( g_displaycontrols )
{
wchar_t buffer [ 128 ] = { 0 } ;
HWND ctrl = GetDlgItem ( hwnd , IDC_BUTTON_PLAY ) ;
GetWindowTextW ( ctrl , buffer , ARRAYSIZE ( buffer ) ) ;
LRESULT idealSize = MLSkinnedButton_GetIdealSize ( ctrl , 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 ) ;
}
skipgroup = ! g_displaycontrols ;
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_SEARCHCAPTION :
{
wchar_t buffer [ 128 ] = { 0 } ;
GetWindowTextW ( pl - > hwnd , buffer , ARRAYSIZE ( buffer ) ) ;
LRESULT idealSize = MLSkinnedStatic_GetIdealSize ( pl - > hwnd , buffer ) ;
SETLAYOUTPOS ( pl , rg . left + WASABI_API_APP - > getScaleX ( 2 ) ,
rg . top + WASABI_API_APP - > getScaleY ( 1 ) ,
WASABI_API_APP - > getScaleX ( LOWORD ( idealSize ) ) ,
( rg . bottom - rg . top ) ) ;
rg . left + = ( pl - > cx + WASABI_API_APP - > getScaleX ( 4 ) ) ;
break ;
}
case IDC_CLEAR :
{
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 ) ;
pl - > flags | = ( ( ( rg . right - rg . left ) - width ) > WASABI_API_APP - > getScaleX ( 40 ) ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW ;
SETLAYOUTPOS ( pl , rg . right - width , rg . top , width , rg . bottom - rg . top ) ;
if ( SWP_SHOWWINDOW & pl - > flags ) rg . right - = ( pl - > cx + WASABI_API_APP - > getScaleX ( 4 ) ) ;
break ;
}
case IDC_QUICKSEARCH :
pl - > flags | = ( rg . right > rg . left ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW ;
SETLAYOUTPOS ( pl , rg . left , rg . top , rg . right - rg . left - WASABI_API_APP - > getScaleX ( 1 ) ,
( rg . bottom - rg . top ) - WASABI_API_APP - > getScaleY ( 1 ) ) ;
break ;
case IDC_BUTTON_PLAY :
case IDC_BUTTON_ENQUEUE :
case IDC_BUTTON_MIX :
case IDC_BUTTON_CREATEPLAYLIST :
if ( IDC_BUTTON_MIX ! = 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 ;
}
if ( pl - > id = = IDC_BUTTON_CREATEPLAYLIST & & ! AGAVE_API_PLAYLIST_GENERATOR )
{
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_BUTTON_INFOTOGGLE :
switch ( SendMessage ( GetParent ( hwnd ) , WM_USER + 66 , 0 , 0 ) )
{
case 0xFF :
case 0xF0 :
{
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 ) ;
pl - > flags | = ( ( ( rg . right - rg . left ) - ( ri . right - ri . left ) ) > WASABI_API_APP - > getScaleX ( 60 ) ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW ;
SETLAYOUTPOS ( pl , rg . right - width - WASABI_API_APP - > getScaleX ( 2 ) ,
rg . top , width , ( rg . bottom - rg . top ) ) ;
if ( SWP_SHOWWINDOW & pl - > flags ) rg . right - = ( pl - > cx + WASABI_API_APP - > getScaleX ( 4 ) ) ;
break ;
}
}
break ;
case IDC_MIXABLE :
if ( predixisExist & 1 )
{
SETLAYOUTPOS ( pl , rg . right - ( ri . right - ri . left ) , rg . top , ( ri . right - ri . left ) , ( rg . bottom - rg . top ) ) ;
pl - > flags | = ( ( rg . right - rg . left ) - ( ri . right - ri . left ) > WASABI_API_APP - > getScaleX ( 60 ) ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW ;
if ( SWP_SHOWWINDOW & pl - > flags ) rg . right - = ( pl - > cx + WASABI_API_APP - > getScaleX ( 4 ) ) ;
}
break ;
case IDC_MEDIASTATUS :
SETLAYOUTPOS ( pl , rg . left , rg . top , rg . right - rg . left , ( rg . bottom - rg . top ) ) ;
pl - > flags | = ( pl - > cx > WASABI_API_APP - > getScaleX ( 16 ) ) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW ;
break ;
case IDC_LIST2 :
SETLAYOUTPOS ( pl , rg . left , rg . top + 1 , ( rg . right - rg . left ) - WASABI_API_APP - > getScaleX ( 3 ) , ( 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 ) & & ! fUpdateAll & & IsWindowVisible ( pl - > hwnd ) )
{
SetRect ( & ri , pl - > x , pl - > y , pl - > cx + pl - > x , pl - > y + pl - > cy ) ;
ValidateRect ( hwnd , & ri ) ;
}
pl + + ;
}
else if ( ! fUpdateAll & & ( 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 void updateInfoText ( HWND hwndDlg , bool x = false )
{
int a = SendMessage ( GetParent ( hwndDlg ) , WM_USER + 66 , x ? - 1 : 0 , 0 ) ;
if ( a = = 0xff )
SetDlgItemTextW ( hwndDlg , IDC_BUTTON_INFOTOGGLE , WASABI_API_LNGSTRINGW ( IDS_HIDE_INFO ) ) ;
else if ( a = = 0xf0 )
SetDlgItemTextW ( hwndDlg , IDC_BUTTON_INFOTOGGLE , WASABI_API_LNGSTRINGW ( IDS_SHOW_INFO ) ) ;
else ShowWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON_INFOTOGGLE ) , SW_HIDE ) ;
}
static void initColumnsHeader ( HWND hwndList )
{
INT index , sortby ;
LVCOLUMNW lvc = { 0 , } ;
if ( ! hwndList | | ! IsWindow ( hwndList ) ) return ;
SendMessageW ( hwndList , WM_SETREDRAW , FALSE , 0L ) ;
while ( SendMessageW ( hwndList , LVM_DELETECOLUMN , 0 , 0L ) ) ;
sortby = g_view_metaconf - > ReadInt ( L " mv_sort_by " , 1 ) ;
lvc . mask = LVCF_TEXT | LVCF_WIDTH ;
lvc . pszText = L " " ;
lvc . cx = 30 ;
SendMessageW ( hwndList , LVM_INSERTCOLUMNW , 0 , ( LPARAM ) & lvc ) ; // create dummy column
// TODO set to a zero width if not available
MLSkinnedHeader_SetCloudColumn ( ListView_GetHeader ( hwndList ) , - 1 ) ; // reset the cloud status column so it'll be correctly removed
SetPropW ( hwndList , L " pmp_list_info " , ( HANDLE ) - 1 ) ;
for ( index = 0 ; columnOrder [ index ] ! = - 1 ; index + + )
{
headerColumn * cl = & columnList [ columnOrder [ index ] ] ;
lvc . pszText = WASABI_API_LNGSTRINGW ( cl - > column_id ) ;
lvc . cx = g_view_metaconf - > ReadInt ( AutoWide ( cl - > config_name ) , cl - > defWidth ) ;
if ( lvc . cx < cl - > minWidth ) lvc . cx = cl - > minWidth ;
// update position of the cloud column icon
if ( columnOrder [ index ] = = MEDIAVIEW_COL_CLOUD )
{
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 | |
! SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_ACTIVE ) )
{
MLSkinnedHeader_SetCloudColumn ( ListView_GetHeader ( hwndList ) , - 1 ) ;
SetPropW ( hwndList , L " pmp_list_info " , ( HANDLE ) - 1 ) ;
lvc . cx = 0 ;
}
else
{
MLSkinnedHeader_SetCloudColumn ( ListView_GetHeader ( hwndList ) , index ) ;
SetPropW ( hwndList , L " pmp_list_info " , ( HANDLE ) index ) ;
lvc . cx = 27 ;
MLCloudColumn_GetWidth ( plugin . hwndLibraryParent , & lvc . cx ) ;
}
}
SendMessageW ( hwndList , LVM_INSERTCOLUMNW , 0xFFFF , ( LPARAM ) & lvc ) ;
if ( sortby = = columnOrder [ index ] ) MLSkinnedListView_DisplaySort ( hwndList , index , ! g_view_metaconf - > ReadInt ( L " mv_sort_dir " , 0 ) ) ;
}
SendMessageW ( hwndList , LVM_DELETECOLUMN , 0 , 0L ) ; // Delete dummy column
for ( index = 0 ; - 1 ! = columnOrder [ index ] & & MEDIAVIEW_COL_RATING ! = columnOrder [ index ] /* && MEDIAVIEW_COL_CLOUD != columnOrder[index]*/ ; index + + ) ;
if ( - 1 ! = index ) SendMessageW ( hwndList , LVM_SETCOLUMNWIDTH , index , ( LPARAM ) SendMessageW ( hwndList , LVM_GETCOLUMNWIDTH , index , 0L ) ) ;
SendMessageW ( hwndList , WM_SETREDRAW , TRUE , 0L ) ;
}
static int m_last_selitem = - 1 ;
static int m_bgupdinfoviewerflag ;
extern void add_to_library ( HWND wndparent ) ;
static INT_PTR CALLBACK needAddFilesProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
switch ( uMsg )
{
case WM_INITDIALOG :
if ( AGAVE_API_ITUNES_IMPORTER & & AGAVE_API_ITUNES_IMPORTER - > iTunesExists ( ) )
EnableWindow ( GetDlgItem ( hwndDlg , IDC_IMPORT_ITUNES ) , TRUE ) ;
else
EnableWindow ( GetDlgItem ( hwndDlg , IDC_IMPORT_ITUNES ) , FALSE ) ;
SetTimer ( hwndDlg , 1 , 1000 , NULL ) ;
return 1 ;
case WM_COMMAND :
switch ( LOWORD ( wParam ) )
{
case IDOK :
case IDCANCEL :
if ( BN_CLICKED = = HIWORD ( wParam ) )
{
if ( IsDlgButtonChecked ( hwndDlg , IDC_CHECK1 ) ) g_config - > WriteInt ( L " noshowadddlg " , 1 ) ;
EndDialog ( hwndDlg , 0 ) ;
}
break ;
case ID_ADD_FILES :
if ( BN_CLICKED = = HIWORD ( wParam ) )
{
add_to_library ( hwndDlg ) ;
PostMessage ( hwndDlg , WM_TIMER , 1 , 0 ) ;
}
break ;
case IDC_IMPORT_ITUNES :
if ( BN_CLICKED = = HIWORD ( wParam ) )
{
if ( AGAVE_API_ITUNES_IMPORTER )
AGAVE_API_ITUNES_IMPORTER - > ImportFromiTunes ( hwndDlg ) ;
PostMessage ( hwndDlg , WM_TIMER , 1 , 0 ) ;
if ( m_curview_hwnd ) PostMessage ( m_curview_hwnd , WM_APP + 1 , 0 , 0 ) ; //update current view
}
break ;
case IDC_BTN_LINK_PROMO :
if ( BN_CLICKED = = HIWORD ( wParam ) ) ShellExecuteA ( plugin . hwndWinampParent , " open " , " https://help.winamp.com/hc/articles/8105244490772-Player-Overview " , NULL , " . " , 0 ) ;
break ;
}
break ;
case WM_TIMER :
if ( g_table & & NDE_Table_GetRecordsCount ( g_table ) )
{
wchar_t buf [ 512 ] = { 0 } ;
StringCchPrintfW ( buf , 512 , WASABI_API_LNGSTRINGW ( IDS_THERE_ARE_NOW_X_ITEMS_IN_THE_LIBRARY ) , NDE_Table_GetRecordsCount ( g_table ) ) ;
SetDlgItemTextW ( hwndDlg , IDC_TEXT , buf ) ;
SetDlgItemTextW ( hwndDlg , ID_ADD_FILES , WASABI_API_LNGSTRINGW ( IDS_ADD_MORE ) ) ;
}
break ;
case WM_DRAWITEM :
{
DRAWITEMSTRUCT * di = ( DRAWITEMSTRUCT * ) lParam ;
if ( di - > CtlType = = ODT_BUTTON )
{
wchar_t wt [ 123 ] = { 0 } ;
int y ;
RECT r ;
HPEN hPen , hOldPen ;
DWORD style ;
GetDlgItemText ( hwndDlg , ( INT ) wParam , wt , ARRAYSIZE ( wt ) ) ;
style = ( DWORD ) GetWindowLongPtrW ( di - > hwndItem , GWL_STYLE ) ;
// draw text
SetTextColor ( di - > hDC , ( di - > itemState & ODS_SELECTED ) ? RGB ( 220 , 0 , 0 ) : RGB ( 0 , 0 , 220 ) ) ;
memset ( & r , 0 , sizeof ( r ) ) ;
DrawText ( di - > hDC , wt , - 1 , & r , DT_SINGLELINE | DT_CALCRECT ) ;
if ( BS_RIGHT & style ) r . left = max ( di - > rcItem . left + 2 , di - > rcItem . right - r . right - 2 ) ;
else if ( BS_LEFT & style ) r . left = di - > rcItem . left + 2 ;
else r . left = ( ( di - > rcItem . right - di - > rcItem . left - 4 ) - r . right ) / 2 ;
if ( r . left < di - > rcItem . left + 2 )
{
r . left = di - > rcItem . left + 2 ;
r . right = di - > rcItem . right - 2 ;
}
else r . right + = r . left ;
if ( r . right > di - > rcItem . right - 2 ) r . right = di - > rcItem . right - 2 ;
if ( BS_TOP & style ) r . top = di - > rcItem . top ;
else if ( BS_VCENTER & style ) r . top = ( ( di - > rcItem . bottom - di - > rcItem . top - 2 ) - r . bottom ) / 2 ;
else r . top = di - > rcItem . bottom - 2 - r . bottom ;
if ( r . top < di - > rcItem . top )
{
r . top = di - > rcItem . top ;
r . bottom = di - > rcItem . bottom - 2 ;
}
else r . bottom + = r . top ;
if ( r . bottom > di - > rcItem . bottom - 2 ) r . bottom = di - > rcItem . bottom - 2 ;
DrawText ( di - > hDC , wt , - 1 , & r , DT_SINGLELINE | DT_WORD_ELLIPSIS ) ;
// draw underline
y = min ( di - > rcItem . bottom , r . bottom + 1 ) ;
hPen = CreatePen ( PS_SOLID , 0 , ( di - > itemState & ODS_SELECTED ) ? RGB ( 220 , 0 , 0 ) : RGB ( 0 , 0 , 220 ) ) ;
hOldPen = ( HPEN ) SelectObject ( di - > hDC , hPen ) ;
MoveToEx ( di - > hDC , r . left , y , NULL ) ;
LineTo ( di - > hDC , r . right , y ) ;
SelectObject ( di - > hDC , hOldPen ) ;
DeleteObject ( hPen ) ;
}
}
}
return 0 ;
} ;
static void SetStatusText ( HWND hwndStatus , LPCWSTR * ppsz , INT count )
{
WCHAR buffer [ 4096 ] = { 0 } ;
if ( 0 = = count | | ! ppsz )
{
SetWindowText ( hwndStatus , L " " ) ;
return ;
}
buffer [ 0 ] = 0x00 ;
for ( int i = 0 ; i < count ; i + + )
{
StringCchCatW ( buffer , 4096 , ppsz [ i ] ) ;
StringCchCatW ( buffer , 4096 , L " " ) ;
}
SetWindowTextW ( hwndStatus , buffer ) ;
StringCchCopyW ( oldText , 4096 , buffer ) ;
}
static void SetRating ( UINT iItem , INT newRating , HWND hwndList )
{
if ( 0 = = newRating ) newRating = - 1 ;
if ( iItem < ( UINT ) itemCache . Size )
{
if ( g_table & & newRating ! = itemCache . Items [ iItem ] . rating )
{
EnterCriticalSection ( & g_db_cs ) ;
nde_scanner_t s = NDE_Table_CreateScanner ( g_table ) ;
if ( NDE_Scanner_LocateNDEFilename ( s , MAINTABLE_ID_FILENAME , FIRST_RECORD , itemCache . Items [ iItem ] . filename ) )
{
NDE_Scanner_Edit ( s ) ;
db_setFieldInt ( s , MAINTABLE_ID_RATING , newRating ) ;
NDE_Scanner_Post ( s ) ;
itemCache . Items [ iItem ] . rating = newRating ;
if ( g_config - > ReadInt ( L " writeratings " , 0 ) )
{
wchar_t buf [ 64 ] = { 0 } ;
if ( newRating > 0 )
{
wsprintfW ( buf , L " %d " , newRating ) ;
}
else
buf [ 0 ] = 0 ;
updateFileInfo ( itemCache . Items [ iItem ] . filename , DB_FIELDNAME_rating , buf ) ;
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_WRITE_EXTENDED_FILE_INFO ) ;
}
}
NDE_Table_DestroyScanner ( g_table , s ) ;
if ( g_table_dirty )
{
g_table_dirty = 0 ;
NDE_Table_Sync ( g_table ) ;
}
LeaveCriticalSection ( & g_db_cs ) ;
}
if ( newRating = = itemCache . Items [ iItem ] . rating & & hwndList )
{
ratingColumn . hwndList = hwndList ;
ratingColumn . iItem = iItem ;
ratingColumn . iSubItem = 600 ;
MLRatingColumn_Animate ( plugin . hwndLibraryParent , & ratingColumn ) ;
ListView_RedrawItems ( resultlist . getwnd ( ) , iItem , iItem ) ;
// TODO: benski> update the top panes w/o refreshing, if possible
// CUT: PostMessage(GetParent(GetParent(hwndList)), WM_APP + 4, (WPARAM)newRating, (LPARAM)1);
}
}
}
/////////// Header Messages / Notifications
static BOOL Header_OnItemChanging ( HWND hwndDlg , NMHEADERW * phdr , LRESULT * pResult , UINT uMsg )
{
if ( phdr - > pitem & & ( HDI_WIDTH & phdr - > pitem - > mask ) )
{
INT test ;
test = columnList [ columnOrder [ phdr - > iItem ] ] . minWidth ;
if ( phdr - > pitem - > cxy < test ) phdr - > pitem - > cxy = test ;
test = columnList [ columnOrder [ phdr - > iItem ] ] . maxWidth ;
if ( test ! = UNLIMITED_WIDTH & & phdr - > pitem - > cxy > test ) phdr - > pitem - > cxy = test ;
if ( MEDIAVIEW_COL_RATING = = columnOrder [ phdr - > iItem ] )
{
RATINGWIDTH rw ;
rw . fStyle = RCS_DEFAULT ;
rw . width = phdr - > pitem - > cxy ;
if ( MLRatingColumn_GetWidth ( plugin . hwndLibraryParent , & rw ) ) phdr - > pitem - > cxy = rw . width ;
if ( 0 = = phdr - > iItem )
{
RATINGBACKTEXT rbt ;
rbt . pszText = ratingBackText ;
rbt . cchTextMax = sizeof ( ratingBackText ) / sizeof ( WCHAR ) ;
rbt . nColumnWidth = phdr - > pitem - > cxy ;
rbt . fStyle = RCS_DEFAULT ;
MLRatingColumn_FillBackString ( plugin . hwndLibraryParent , & rbt ) ;
}
else ratingBackText [ 0 ] = 0x00 ;
}
else if ( MEDIAVIEW_COL_CLOUD = = columnOrder [ phdr - > iItem ] )
{
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 | |
! SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_ACTIVE ) )
phdr - > pitem - > cxy = 0 ;
else
{
INT width = phdr - > pitem - > cxy ;
if ( MLCloudColumn_GetWidth ( plugin . hwndLibraryParent , & width ) )
{
phdr - > pitem - > cxy = width ;
}
}
}
}
return FALSE ;
}
static BOOL Header_OnEndDrag ( HWND hwndDlg , NMHEADERW * phdr , LRESULT * pResult )
{
PostMessageW ( hwndDlg , IM_SYNCHEADERORDER , 0 , ( LPARAM ) phdr - > hdr . hwndFrom ) ;
return FALSE ;
}
static BOOL Header_OnRightClick ( HWND hwndDlg , NMHDR * pnmh , LRESULT * pResult )
{
HMENU menu = GetSubMenu ( g_context_menus , 4 ) ;
POINT p ;
GetCursorPos ( & p ) ;
int r = DoTrackPopup ( menu , TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON , p . x , p . y , hwndDlg , NULL ) ;
switch ( r )
{
case ID_HEADERWND_CUSTOMIZECOLUMNS :
customizeColumnsDialog ( hwndDlg ) ;
break ;
}
return FALSE ;
}
/////////// ListView Messages / Notifications
static BOOL ListView_OnItemChanged ( HWND hwndDlg , NMLISTVIEW * pnmv )
{
if ( pnmv - > uNewState & LVIS_SELECTED )
{
//if (GetFocus()==resultlist.getwnd())
{
m_last_selitem = pnmv - > iItem ;
KillTimer ( hwndDlg , 6600 ) ;
SetTimer ( hwndDlg , 6600 , 250 , NULL ) ;
}
}
else
{
if ( isMixablePresent )
{
SetDlgItemText ( hwndDlg , IDC_MIXABLE , L " " ) ;
isMixablePresent = false ;
}
}
return FALSE ;
}
static BOOL ListView_OnDoubleClick ( HWND hwndDlg , NMITEMACTIVATE * pnmitem )
{
playFiles ( ( ! ! g_config - > ReadInt ( L " enqueuedef " , 0 ) ) ^ ( ! ! ( GetAsyncKeyState ( VK_SHIFT ) & 0x8000 ) ) , 0 ) ;
return FALSE ;
}
void EatKeyboard ( )
{
Sleep ( 100 ) ;
MSG msg ;
while ( PeekMessage ( & msg , NULL , WM_KEYFIRST , WM_KEYLAST , PM_REMOVE ) ) ; //eat return
}
static void Dialog_OnContextMenu ( HWND hwndDlg , HWND hwndFrom , int x , int y )
{
if ( hwndFrom ! = resultlist . 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 = resultlist . GetNextSelected ( ) ;
if ( selected ! = - 1 ) // if something is selected we'll drop the menu from there
{
resultlist . GetItemRect ( selected , & itemRect ) ;
ClientToScreen ( resultlist . getwnd ( ) , ( POINT * ) & itemRect ) ;
}
else // otherwise we'll drop it from the top-left corner of the listview, adjusting for the header location
{
GetWindowRect ( resultlist . getwnd ( ) , & itemRect ) ;
HWND hHeader = ( HWND ) SNDMSG ( resultlist . getwnd ( ) , 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 ( resultlist . getwnd ( ) , 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 globmenu = WASABI_API_LOADMENU ( IDR_CONTEXTMENUS ) ;
HMENU menu = GetSubMenu ( globmenu , 0 ) ;
int rate_idx = 9 ;
sendto_hmenu = GetSubMenu ( menu , 2 ) ;
rate_hmenu = GetSubMenu ( menu , rate_idx ) ;
ConvertRatingMenuStar ( rate_hmenu , ID_RATE_5 ) ;
ConvertRatingMenuStar ( rate_hmenu , ID_RATE_4 ) ;
ConvertRatingMenuStar ( rate_hmenu , ID_RATE_3 ) ;
ConvertRatingMenuStar ( rate_hmenu , ID_RATE_2 ) ;
ConvertRatingMenuStar ( rate_hmenu , ID_RATE_1 ) ;
s . mode = 0 ;
s . hwnd = 0 ;
s . build_hMenu = 0 ;
IPC_LIBRARY_SENDTOMENU = 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 ) = = ( LRESULT ) - 1 )
{
s . mode = 1 ;
s . hwnd = hwndDlg ;
s . data_type = ML_TYPE_ITEMRECORDLIST ;
s . ctx [ 1 ] = 1 ;
s . build_hMenu = sendto_hmenu ;
}
wchar_t * artist = NULL ;
wchar_t * album = NULL ;
int n = resultlist . GetSelectionMark ( ) ;
if ( n ! = - 1 )
{
artist = itemCache . Items [ n ] . artist ;
album = itemCache . Items [ n ] . album ;
wchar_t str [ 2048 ] = { 0 } , str2 [ 128 ] = { 0 } ;
// (BigG): Check the ini settings for viewing vs playing and create the menu accordingly
// Keeping this here in case we want to use the ini setting:
//StringCchPrintfW(str, 2048, WASABI_API_LNGSTRINGW( (g_viewnotplay != 0) ? IDS_VIEW_ALL_FILES_BY : IDS_PLAY_ALL_FILES_BY), artist ? artist : L"");
int len = lstrlenW ( artist ) ;
if ( len > 39 )
{
StringCchPrintfW ( str2 , 40 , L " %.36s... " , artist ) ; //WASABI_API_LNGSTRINGW(IDS_VIEW_ALL_FILES_BY), artist ? artist : L"");
StringCchPrintfW ( str , 2048 , WASABI_API_LNGSTRINGW ( IDS_VIEW_ALL_FILES_BY ) , str2 ) ;
}
else
{
StringCchPrintfW ( str , 2048 , WASABI_API_LNGSTRINGW ( IDS_VIEW_ALL_FILES_BY ) , artist ? artist : L " " ) ;
}
FixAmps ( str , 2048 ) ;
MENUITEMINFOW mii =
{
sizeof ( MENUITEMINFOW ) ,
MIIM_TYPE | MIIM_ID ,
MFT_STRING ,
MFS_ENABLED ,
0x1234 ,
NULL ,
NULL ,
NULL ,
0 ,
str ,
0 ,
} ;
if ( ! ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 | |
! SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_ACTIVE ) ) )
{
MENUITEMINFOW m = { sizeof ( m ) , MIIM_TYPE | MIIM_ID | MIIM_SUBMENU , MFT_SEPARATOR , 0 } ;
m . wID = CLOUD_SOURCE_MENUS - 1 ;
InsertMenuItemW ( menu , 0 , FALSE , & m ) ;
wchar_t a [ 100 ] = { 0 } ;
m . fType = MFT_STRING ;
m . dwTypeData = WASABI_API_LNGSTRINGW_BUF ( IDS_CLOUD_SOURCES , a , 100 ) ;
m . wID = CLOUD_SOURCE_MENUS ;
m . hSubMenu = cloud_hmenu = CreatePopupMenu ( ) ;
InsertMenuItemW ( menu , 0 , FALSE , & m ) ;
}
if ( artist & & artist [ 0 ] )
{
InsertMenuItemW ( menu , ID_EDITITEMINFOS , FALSE , & mii ) ;
}
// (BigG): Check the ini settings for viewing vs playing and create the menu accordingly
// Keeping this here in case we want to use the ini setting:
len = lstrlenW ( album ) ;
if ( len > 39 )
{
StringCchPrintfW ( str2 , 40 , L " %.36s... " , album ) ;
StringCchPrintfW ( str , 2048 , WASABI_API_LNGSTRINGW ( IDS_VIEW_ALL_FILES_FROM ) , str2 ) ;
}
else
{
StringCchPrintfW ( str , 2048 , WASABI_API_LNGSTRINGW ( IDS_VIEW_ALL_FILES_FROM ) , album ? album : L " " ) ;
}
FixAmps ( str , 2048 ) ;
mii . cch = wcslen ( str ) ;
mii . wID = 0x1235 ;
if ( album & & album [ 0 ] )
{
InsertMenuItemW ( menu , ID_EDITITEMINFOS , FALSE , & mii ) ;
}
{
mii . wID = 0xdeadbeef ;
mii . fType = MFT_SEPARATOR ;
InsertMenuItemW ( menu , ID_EDITITEMINFOS , FALSE , & mii ) ;
}
}
else
{
EnableMenuItem ( menu , ID_MEDIAWND_PLAYSELECTEDFILES , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , ID_MEDIAWND_ENQUEUESELECTEDFILES , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , IDC_REFRESH_METADATA , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , ID_MEDIAWND_REMOVEFROMLIBRARY , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , ID_EDITITEMINFOS , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , ID_MEDIAWND_EXPLOREFOLDER , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , ID_PE_ID3 , MF_BYCOMMAND | MF_GRAYED ) ;
EnableMenuItem ( menu , 2 , MF_BYPOSITION | MF_GRAYED ) ; //grays the "Add to playlist..." menu
EnableMenuItem ( menu , rate_idx , MF_BYPOSITION | MF_GRAYED ) ; //grays the "Rate..." menu
EnableMenuItem ( menu , 13 , MF_BYPOSITION | MF_GRAYED ) ; //grays the "Remove..." menu
}
menufucker_t mf = { sizeof ( mf ) , MENU_MEDIAVIEW , menu , 0x3000 , 0x4000 , 0 } ;
mf . extinf . mediaview . list = resultlist . getwnd ( ) ;
mf . extinf . mediaview . items = & itemCache ;
pluginMessage message_build = { ML_IPC_MENUFUCKER_BUILD , ( intptr_t ) & mf , 0 } ;
SendMessage ( plugin . hwndLibraryParent , WM_ML_IPC , ( WPARAM ) & message_build , ML_IPC_SEND_PLUGIN_MESSAGE ) ;
Menu_SetRatingValue ( rate_hmenu , 0 ) ;
UpdateMenuItems ( hwndDlg , menu , IDR_VIEW_ACCELERATORS ) ;
int r = DoTrackPopup ( menu , TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON , x , y , hwndDlg , NULL ) ;
pluginMessage message_result = { ML_IPC_MENUFUCKER_RESULT , ( intptr_t ) & mf , r , 0 } ;
SendMessage ( plugin . hwndLibraryParent , WM_ML_IPC , ( WPARAM ) & message_result , ML_IPC_SEND_PLUGIN_MESSAGE ) ;
switch ( r )
{
case ID_MEDIAWND_PLAYSELECTEDFILES :
case ID_MEDIAWND_ENQUEUESELECTEDFILES :
playFiles ( ( r = = ID_MEDIAWND_ENQUEUESELECTEDFILES ) , 0 ) ;
break ;
case ID_MEDIAWND_SELECTALL :
{
LVITEM item = { 0 } ;
item . state = LVIS_SELECTED ;
item . stateMask = LVIS_SELECTED ;
SendMessageW ( hwndFrom , LVM_SETITEMSTATE , ( WPARAM ) - 1 , ( LPARAM ) & item ) ;
}
break ;
case ID_MEDIAWND_REMOVEFROMLIBRARY :
removeSelectedItems ( 0 ) ;
break ;
case ID_EDITITEMINFOS :
if ( resultlist . GetSelectedCount ( ) > 0 )
editInfo ( hwndDlg ) ;
break ;
case ID_PE_ID3 :
fileInfoDialogs ( hwndDlg ) ;
PostMessageW ( hwndDlg , WM_NEXTDLGCTL , ( WPARAM ) hwndFrom , ( LPARAM ) TRUE ) ;
break ;
case IDC_REFRESH_METADATA :
RefreshMetadata ( hwndDlg ) ;
break ;
case 0x1234 : // all files from selected artist
{
wchar_t tmp [ 2048 ] = { 0 } ;
GayStringW escaped ;
queryStrEscape ( artist , escaped ) ;
// Keeping this here in case we want to use the ini setting later:
//if ( g_viewnotplay ) // (BigG): Check to see if we should play or view the current tracks
//{
StringCchPrintfW ( tmp , 2048 , L " ?artist = \" %s \" " , escaped . Get ( ) ) ;
SetWindowTextW ( hwndSearchGlobal , tmp ) ;
//}
//else // Otherwise do the old behavior and just play it back
//{
// StringCchPrintfW(tmp, 2048, L"artist = \"%s\"", escaped.Get());
// main_playQuery(g_view_metaconf, tmp, 0);
//}
SetWindowTextW ( hwndSearchGlobal , tmp ) ;
}
break ;
case 0x1235 : // all files from selected album
{
wchar_t tmp [ 2048 ] = { 0 } ;
GayStringW escaped ;
queryStrEscape ( album , escaped ) ;
// Keeping this here in case we want to use the ini setting later:
//if ( g_viewnotplay ) // (BigG): Check to see if we should play or view the current tracks
//{
StringCchPrintfW ( tmp , 2048 , L " ?album = \" %s \" " , escaped . Get ( ) ) ;
SetWindowTextW ( hwndSearchGlobal , tmp ) ;
//}
//else // Otherwise do the old behavior and just play it back
//{
// StringCchPrintfW(tmp, 2048, L"album = \"%s\"", escaped.Get());
// main_playQuery(g_view_metaconf, tmp, 0);
//}
}
break ;
case ID_RATE_1 :
case ID_RATE_2 :
case ID_RATE_3 :
case ID_RATE_4 :
case ID_RATE_5 :
case ID_RATE_0 :
{
int rate = r - ID_RATE_1 + 1 ;
if ( r = = ID_RATE_0 ) rate = 0 ;
int x ;
int has = 0 ;
EnterCriticalSection ( & g_db_cs ) ;
nde_scanner_t s = NDE_Table_CreateScanner ( g_table ) ;
for ( x = 0 ; x < itemCache . Size ; x + + )
{
if ( resultlist . GetSelected ( x ) )
{
if ( NDE_Scanner_LocateNDEFilename ( s , MAINTABLE_ID_FILENAME , FIRST_RECORD , itemCache . Items [ x ] . filename ) )
{
has + + ;
NDE_Scanner_Edit ( s ) ;
db_setFieldInt ( s , MAINTABLE_ID_RATING , rate ) ;
NDE_Scanner_Post ( s ) ;
itemCache . Items [ x ] . rating = rate ;
if ( g_config - > ReadInt ( L " writeratings " , 0 ) )
{
wchar_t buf [ 64 ] = { 0 } ;
if ( rate > 0 )
{
wsprintfW ( buf , L " %d " , rate ) ;
}
else
buf [ 0 ] = 0 ;
updateFileInfo ( itemCache . Items [ x ] . filename , DB_FIELDNAME_rating , buf ) ;
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_WRITE_EXTENDED_FILE_INFO ) ;
}
}
}
}
NDE_Table_DestroyScanner ( g_table , s ) ;
if ( g_table_dirty )
{
g_table_dirty = 0 ;
NDE_Table_Sync ( g_table ) ;
}
LeaveCriticalSection ( & g_db_cs ) ;
if ( has )
{
ListView_RedrawItems ( resultlist . getwnd ( ) , 0 , itemCache . Size - 1 ) ;
PostMessage ( GetParent ( hwndDlg ) , WM_APP + 4 , ( WPARAM ) rate , ( LPARAM ) 0 ) ;
}
}
break ;
case ID_MEDIAWND_EXPLOREFOLDER :
exploreItemFolder ( hwndDlg ) ;
break ;
case ID_MEDIAWND_REMOVE_REMOVEALLDEADFILES :
removeDeadFiles ( hwndDlg ) ;
break ;
case ID_MEDIAWND_REMOVE_PHYSICALLYREMOVESELECTEDITEMS :
RecycleSelectedItems ( ) ;
break ;
default :
{
if ( cloud_hmenu & & ( r > = CLOUD_SOURCE_MENUS & & r < CLOUD_SOURCE_MENUS_UPPER ) ) // deals with cloud specific menus
{
// 0 = no change
// 1 = add cloud
// 2 = add local
// 4 = removed
int mode = 0 ;
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_PROCESS_CLOUD_STATUS , ( intptr_t ) r , ( intptr_t ) & mode ) ;
int n = resultlist . GetSelectionMark ( ) ;
if ( n ! = - 1 )
{
switch ( mode )
{
case 1 :
setCloudValue ( & itemCache . Items [ n ] , L " 5 " ) ;
break ;
case 2 :
setCloudValue ( & itemCache . Items [ n ] , L " 0 " ) ;
break ;
case 4 :
setCloudValue ( & itemCache . Items [ n ] , L " 4 " ) ;
break ;
}
InvalidateRect ( resultlist . getwnd ( ) , NULL , TRUE ) ;
}
break ;
}
if ( s . mode = = 2 )
{
s . menu_id = r ;
if ( SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_LIBRARY_SENDTOMENU ) = = ( LRESULT ) - 1 )
{
// build my data.
s . mode = 3 ;
s . data_type = ML_TYPE_ITEMRECORDLISTW ;
itemRecordListW myObj = { 0 , } ;
copyFilesToItemCacheW ( & myObj ) ; // does not dupe strings
s . data = ( void * ) & myObj ;
LRESULT result = SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_LIBRARY_SENDTOMENU ) ;
if ( result ! = 1 )
{
s . mode = 3 ;
s . data_type = ML_TYPE_ITEMRECORDLIST ;
itemRecordList objA = { 0 , } ;
convertRecordList ( & objA , & myObj ) ;
s . data = ( void * ) & objA ;
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_LIBRARY_SENDTOMENU ) ;
freeRecordList ( & objA ) ;
}
_aligned_free ( myObj . Items ) ;
}
}
break ;
}
}
if ( s . mode )
{
s . mode = 4 ;
SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_LIBRARY_SENDTOMENU ) ; // cleanup
}
sendto_hmenu = 0 ;
DestroyMenu ( cloud_hmenu ) ;
cloud_hmenu = 0 ;
DestroyMenu ( globmenu ) ;
UpdateWindow ( hwndFrom ) ;
EatKeyboard ( ) ;
}
static BOOL ListView_OnFindItem ( HWND hwndDlg , NMLVFINDITEMW * pfi , LRESULT * pResult , UINT uMsg )
{
if ( bgThread_Handle ) return FALSE ;
int i = pfi - > iStart ;
if ( i > = itemCache . Size ) i = 0 ;
int cnt = itemCache . Size - i ;
if ( pfi - > lvfi . flags & LVFI_WRAP ) cnt + = i ;
int by = g_view_metaconf - > ReadInt ( L " mv_sort_by " , MEDIAVIEW_COL_ARTIST ) ;
while ( cnt - - > 0 )
{
itemRecordW * thisitem = itemCache . Items + i ;
wchar_t tmp [ 128 ] = { 0 } ;
wchar_t * name = 0 ;
switch ( by )
{
case MEDIAVIEW_COL_FILENAME :
name = thisitem - > filename + wcslen ( thisitem - > filename ) ;
while ( name > = thisitem - > filename & & * name ! = L ' / ' & & * name ! = L ' \\ ' ) name - - ;
break ;
case MEDIAVIEW_COL_FULLPATH :
name = thisitem - > filename ;
break ;
case MEDIAVIEW_COL_EXTENSION :
name = PathFindExtensionW ( thisitem - > filename ) ;
if ( name & & * name )
name + + ;
break ;
case MEDIAVIEW_COL_TITLE : name = thisitem - > title ; break ;
case MEDIAVIEW_COL_COMMENT : name = thisitem - > comment ; break ;
case MEDIAVIEW_COL_ARTIST : name = thisitem - > artist ; break ;
case MEDIAVIEW_COL_ALBUM : name = thisitem - > album ; break ;
case MEDIAVIEW_COL_GENRE : name = thisitem - > genre ; break ;
case MEDIAVIEW_COL_YEAR :
tmp [ 0 ] = 0 ;
if ( thisitem - > year > = 0 ) StringCchPrintfW ( tmp , 128 , L " %04d " , thisitem - > year ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_TRACK :
tmp [ 0 ] = 0 ;
if ( thisitem - > track > 0 )
{
if ( thisitem - > tracks > 0 ) StringCchPrintfW ( tmp , 128 , L " %d/%d " , thisitem - > track , thisitem - > tracks ) ;
else StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > track ) ;
}
name = tmp ;
break ;
case MEDIAVIEW_COL_LENGTH :
tmp [ 0 ] = 0 ;
if ( thisitem - > length > = 0 ) StringCchPrintfW ( tmp , 128 , L " %d:%02d " , thisitem - > length / 60 , thisitem - > length % 60 ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_RATING :
tmp [ 0 ] = 0 ;
if ( thisitem - > rating > 0 ) StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > rating ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_CLOUD :
{
tmp [ 0 ] = 0 ;
wchar_t * x = getRecordExtendedItem_fast ( thisitem , extended_fields . cloud ) ;
if ( x & & * x ) StringCchPrintfW ( tmp , 128 , L " %d " , x ) ;
name = tmp ;
break ;
}
case MEDIAVIEW_COL_PLAYCOUNT :
tmp [ 0 ] = 0 ;
if ( thisitem - > playcount > 0 ) StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > playcount ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_BITRATE :
if ( thisitem - > bitrate > 0 )
StringCchPrintfW ( name = tmp , 128 , L " %d%s " , thisitem - > bitrate , WASABI_API_LNGSTRINGW ( IDS_KBPS ) ) ;
break ;
case MEDIAVIEW_COL_BPM :
if ( thisitem - > bpm > 0 )
StringCchPrintfW ( name = tmp , 128 , L " %d " , thisitem - > bpm ) ;
break ;
case MEDIAVIEW_COL_TYPE :
name = WASABI_API_LNGSTRINGW ( thisitem - > type ? IDS_VIDEO : IDS_AUDIO ) ;
break ;
case MEDIAVIEW_COL_DISC :
tmp [ 0 ] = 0 ;
if ( thisitem - > disc > 0 )
{
if ( thisitem - > discs > 0 )
StringCchPrintfW ( tmp , 128 , L " %d/%d " , thisitem - > disc , thisitem - > discs ) ;
else
StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > disc ) ;
}
name = tmp ;
break ;
case MEDIAVIEW_COL_ALBUMARTIST :
name = thisitem - > albumartist ;
break ;
case MEDIAVIEW_COL_PUBLISHER :
name = thisitem - > publisher ;
break ;
case MEDIAVIEW_COL_COMPOSER :
name = thisitem - > composer ;
break ;
case MEDIAVIEW_COL_ALBUMGAIN :
name = thisitem - > replaygain_album_gain ;
break ;
case MEDIAVIEW_COL_TRACKGAIN :
name = thisitem - > replaygain_track_gain ;
break ;
case MEDIAVIEW_COL_FILESIZE :
tmp [ 0 ] = 0 ;
if ( thisitem - > filesize > 0 ) StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > filesize ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_FILETIME :
tmp [ 0 ] = 0 ;
if ( thisitem - > filetime > 0 ) StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > filetime ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_LASTUPD :
tmp [ 0 ] = 0 ;
if ( thisitem - > lastupd > 0 ) StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > lastupd ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_DATEADDED :
{
tmp [ 0 ] = 0 ;
wchar_t * x = getRecordExtendedItem_fast ( thisitem , extended_fields . dateadded ) ;
if ( x & & * x ) StringCchPrintfW ( tmp , 128 , L " %d " , x ) ;
name = tmp ;
break ;
}
case MEDIAVIEW_COL_LASTPLAY :
tmp [ 0 ] = 0 ;
if ( thisitem - > lastplay > 0 ) StringCchPrintfW ( tmp , 128 , L " %d " , thisitem - > lastplay ) ;
name = tmp ;
break ;
case MEDIAVIEW_COL_ISPODCAST :
{
wchar_t * t = getRecordExtendedItem_fast ( thisitem , extended_fields . ispodcast ) ;
name = WASABI_API_LNGSTRINGW ( t & & wcscmp ( t , L " 1 " ) ? IDS_PODCAST : IDS_NON_PODCAST ) ;
}
break ;
case MEDIAVIEW_COL_PODCASTCHANNEL :
name = getRecordExtendedItem_fast ( thisitem , extended_fields . podcastchannel ) ;
break ;
case MEDIAVIEW_COL_PODCASTPUBDATE :
{
tmp [ 0 ] = 0 ;
wchar_t * x = getRecordExtendedItem_fast ( thisitem , extended_fields . podcastpubdate ) ;
if ( x & & * x ) StringCchPrintfW ( tmp , 128 , L " %d " , x ) ;
name = tmp ;
}
break ;
case MEDIAVIEW_COL_CATEGORY :
name = thisitem - > category ;
break ;
case MEDIAVIEW_COL_DIRECTOR :
name = getRecordExtendedItem_fast ( thisitem , extended_fields . director ) ;
break ;
case MEDIAVIEW_COL_PRODUCER :
name = getRecordExtendedItem_fast ( thisitem , extended_fields . producer ) ;
break ;
case MEDIAVIEW_COL_DIMENSION :
{
tmp [ 0 ] = 0 ;
wchar_t * w = getRecordExtendedItem_fast ( thisitem , extended_fields . width ) ;
wchar_t * h = getRecordExtendedItem_fast ( thisitem , extended_fields . height ) ;
if ( w & & * w & & h & & * h ) StringCchPrintfW ( tmp , 128 , L " %dx%d " , _wtoi ( w ) , _wtoi ( h ) ) ;
name = tmp ;
break ;
}
}
if ( ! name ) name = L " " ;
else SKIP_THE_AND_WHITESPACEW ( name )
if ( pfi - > lvfi . flags & ( 4 | LVFI_PARTIAL ) )
{
if ( ! StrCmpNIW ( name , pfi - > lvfi . psz , wcslen ( pfi - > lvfi . psz ) ) )
{
* pResult = i ;
return TRUE ;
}
}
else if ( pfi - > lvfi . flags & LVFI_STRING )
{
if ( ! lstrcmpiW ( name , pfi - > lvfi . psz ) )
{
* pResult = i ;
return TRUE ;
}
}
else
{
* pResult = i ;
return TRUE ;
}
if ( + + i = = itemCache . Size ) i = 0 ;
}
* pResult = i ;
return TRUE ;
}
static BOOL ListView_OnGetDispInfo ( HWND hwndDlg , NMLVDISPINFOW * pdi , UINT uMsg )
{
LVITEMW * pItem ;
itemRecordW * pRec ;
pItem = & pdi - > item ;
if ( bgThread_Handle )
{
if ( 0 = = pItem - > iItem & & 0 = = pItem - > iSubItem & & ( LVIF_TEXT & pItem - > mask ) )
{
static char bufpos = 0 ;
static int buflen = 17 ;
static wchar_t buffer [ 64 ] ; //L"Scanning _\0/-\\|";
if ( ! buffer [ 0 ] )
{
WASABI_API_LNGSTRINGW_BUF ( IDS_SCANNING_PLAIN , buffer , 54 ) ;
StringCchCatW ( buffer , 64 , L " _ " ) ;
StringCchCatW ( buffer + ( buflen = lstrlenW ( buffer ) + 1 ) , 64 , L " /- \\ | " ) ;
buflen + = 4 ;
}
int pos = buflen - 5 ; ;
buffer [ pos - 1 ] = buffer [ pos + ( bufpos + + & 3 ) + 1 ] ;
pItem - > pszText = buffer ;
}
return FALSE ;
}
if ( pItem - > iItem < 0 | | pItem - > iItem > = itemCache . Size ) return FALSE ;
pRec = itemCache . Items + pItem - > iItem ;
if ( LVIF_TEXT & pItem - > mask )
{
switch ( columnOrder [ pItem - > iSubItem ] )
{
case MEDIAVIEW_COL_FILENAME : // show filename (Tho we'll show without the path cause paths are gay)
pItem - > pszText = PathFindFileNameW ( pRec - > filename ) ;
break ;
case MEDIAVIEW_COL_FULLPATH : // show filename (Tho we'll show without the path cause paths are gay)
pItem - > pszText = pRec - > filename ;
break ;
case MEDIAVIEW_COL_EXTENSION :
pItem - > pszText = PathFindExtensionW ( pRec - > filename ) ;
if ( pItem - > pszText & & * pItem - > pszText ) pItem - > pszText + + ;
break ;
case MEDIAVIEW_COL_TITLE :
pItem - > pszText = pRec - > title ;
break ;
case MEDIAVIEW_COL_COMMENT :
pItem - > pszText = pRec - > comment ;
break ;
case MEDIAVIEW_COL_ALBUM :
pItem - > pszText = pRec - > album ;
break ;
case MEDIAVIEW_COL_ARTIST :
pItem - > pszText = pRec - > artist ;
break ;
case MEDIAVIEW_COL_TRACK :
if ( pRec - > track > 0 )
{
if ( pRec - > tracks > 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d/%d " , pRec - > track , pRec - > tracks ) ;
else StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d " , pRec - > track ) ;
}
break ;
case MEDIAVIEW_COL_GENRE :
pItem - > pszText = pRec - > genre ;
break ;
case MEDIAVIEW_COL_YEAR :
if ( pRec - > year > = 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %04d " , pRec - > year ) ;
break ;
case MEDIAVIEW_COL_LENGTH :
if ( pRec - > length > = 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d:%02d " , pRec - > length / 60 , pRec - > length % 60 ) ;
break ;
case MEDIAVIEW_COL_RATING :
if ( 0 = = pItem - > iSubItem & & ratingBackText [ 0 ] ) pItem - > pszText = ratingBackText ;
else if ( pRec - > rating > 0 & & pRec - > rating < = 5 ) _itow ( pRec - > rating , pItem - > pszText , 10 ) ;
break ;
case MEDIAVIEW_COL_CLOUD :
{
wchar_t * t = getRecordExtendedItem_fast ( pRec , extended_fields . cloud ) ;
if ( t & & * t ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d " , _wtoi ( t ) ) ;
break ;
}
case MEDIAVIEW_COL_PLAYCOUNT :
if ( pRec - > playcount > = 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d " , pRec - > playcount ) ;
else pItem - > pszText = L " 0 " ;
break ;
case MEDIAVIEW_COL_DISC :
if ( pRec - > disc > 0 )
{
if ( pRec - > discs > 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d/%d " , pRec - > disc , pRec - > discs ) ;
else StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d " , pRec - > disc ) ;
}
break ;
case MEDIAVIEW_COL_ALBUMARTIST :
pItem - > pszText = pRec - > albumartist ;
break ;
case MEDIAVIEW_COL_PUBLISHER :
pItem - > pszText = pRec - > publisher ;
break ;
case MEDIAVIEW_COL_COMPOSER :
pItem - > pszText = pRec - > composer ;
break ;
case MEDIAVIEW_COL_ALBUMGAIN :
pItem - > pszText = pRec - > replaygain_album_gain ;
break ;
case MEDIAVIEW_COL_TRACKGAIN :
pItem - > pszText = pRec - > replaygain_track_gain ;
break ;
case MEDIAVIEW_COL_TYPE :
pItem - > pszText = WASABI_API_LNGSTRINGW ( ( pRec - > type ) ? IDS_VIDEO : IDS_AUDIO ) ;
break ;
case MEDIAVIEW_COL_BITRATE :
if ( pRec - > bitrate > 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d%s " , pRec - > bitrate , WASABI_API_LNGSTRINGW ( IDS_KBPS ) ) ;
break ;
case MEDIAVIEW_COL_BPM :
if ( pRec - > bpm > 0 ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %d " , pRec - > bpm ) ;
break ;
case MEDIAVIEW_COL_FILESIZE :
if ( pRec - > filesize ! = - 1 ) WASABI_API_LNG - > FormattedSizeString ( pItem - > pszText , pItem - > cchTextMax , pRec - > filesize ) ;
break ;
case MEDIAVIEW_COL_FILETIME :
MakeDateString ( pRec - > filetime , pItem - > pszText , pItem - > cchTextMax ) ;
break ;
case MEDIAVIEW_COL_LASTUPD :
MakeDateString ( pRec - > lastupd , pItem - > pszText , pItem - > cchTextMax ) ;
break ;
case MEDIAVIEW_COL_DATEADDED :
{
wchar_t * t = getRecordExtendedItem_fast ( pRec , extended_fields . dateadded ) ;
if ( t & & * t ) MakeDateString ( _wtoi64 ( t ) , pItem - > pszText , pItem - > cchTextMax ) ;
break ;
}
case MEDIAVIEW_COL_LASTPLAY :
if ( pRec - > lastplay > 0 ) MakeDateString ( pRec - > lastplay , pItem - > pszText , pItem - > cchTextMax ) ;
break ;
case MEDIAVIEW_COL_ISPODCAST :
{
wchar_t * t = getRecordExtendedItem_fast ( pRec , extended_fields . ispodcast ) ;
pItem - > pszText = WASABI_API_LNGSTRINGW ( ( t & & t [ 0 ] = = L ' 1 ' & & ! t [ 1 ] ) ? IDS_PODCAST : IDS_NON_PODCAST ) ;
break ;
}
case MEDIAVIEW_COL_PODCASTCHANNEL :
pItem - > pszText = getRecordExtendedItem_fast ( pRec , extended_fields . podcastchannel ) ;
break ;
case MEDIAVIEW_COL_PODCASTPUBDATE :
{
wchar_t * t = getRecordExtendedItem_fast ( pRec , extended_fields . podcastpubdate ) ;
if ( t & & * t ) MakeDateString ( _wtoi64 ( t ) , pItem - > pszText , pItem - > cchTextMax ) ;
break ;
}
case MEDIAVIEW_COL_CATEGORY :
pItem - > pszText = pRec - > category ;
break ;
case MEDIAVIEW_COL_DIRECTOR :
pItem - > pszText = getRecordExtendedItem_fast ( pRec , extended_fields . director ) ;
break ;
case MEDIAVIEW_COL_PRODUCER :
pItem - > pszText = getRecordExtendedItem_fast ( pRec , extended_fields . producer ) ;
break ;
case MEDIAVIEW_COL_DIMENSION :
{
wchar_t * w = getRecordExtendedItem_fast ( pRec , extended_fields . width ) ;
wchar_t * h = getRecordExtendedItem_fast ( pRec , extended_fields . height ) ;
if ( w & & * w & & h & & * h ) StringCchPrintfW ( pItem - > pszText , pItem - > cchTextMax , L " %dx%d " , _wtoi ( w ) , _wtoi ( h ) ) ;
break ;
}
}
if ( ! pItem - > pszText ) pItem - > pszText = L " " ;
}
return FALSE ;
}
static BOOL ListView_OnColumnClick ( HWND hwndDlg , NMLISTVIEW * pnmv )
{
int l_sc = g_view_metaconf - > ReadInt ( L " mv_sort_by " , MEDIAVIEW_COL_ARTIST ) ;
int l_sd = g_view_metaconf - > ReadInt ( L " mv_sort_dir " , 0 ) ;
if ( columnOrder [ pnmv - > iSubItem ] = = l_sc ) l_sd = ! l_sd ;
else
{
/* JF> I like this better when the direction doesnt get reset every
time you choose a new column . To revert to old behavior , uncomment
this line :
l_sd = 0 ;
*/
l_sc = columnOrder [ pnmv - > iSubItem ] ;
}
g_view_metaconf - > WriteInt ( L " mv_sort_by " , l_sc ) ;
g_view_metaconf - > WriteInt ( L " mv_sort_dir " , l_sd ) ;
MLSkinnedListView_DisplaySort ( pnmv - > hdr . hwndFrom , pnmv - > iSubItem , ! l_sd ) ;
sortResults ( g_view_metaconf , & itemCache ) ;
resultlist . SetVirtualCount ( 0 ) ;
resultlist . SetVirtualCount ( itemCache . Size ) ; // TODO: we could set a limit here
ListView_RedrawItems ( pnmv - > hdr . hwndFrom , 0 , itemCache . Size - 1 ) ;
return FALSE ;
}
static BOOL ListView_OnBeginDrag ( HWND hwndDlg , NMLISTVIEW * pnmv )
{
switch ( columnOrder [ pnmv - > iSubItem ] )
{
case MEDIAVIEW_COL_RATING :
ratingColumn . hwndList = pnmv - > hdr . hwndFrom ;
ratingColumn . fStyle = RCS_DEFAULT ;
ratingColumn . iItem = pnmv - > iItem ;
ratingColumn . iSubItem = pnmv - > iSubItem ;
ratingColumn . value = ( ( UINT ) pnmv - > iItem < ( UINT ) itemCache . Size ) ? itemCache . Items [ pnmv - > iItem ] . rating : 0 ;
MLRatingColumn_BeginDrag ( plugin . hwndLibraryParent , & ratingColumn ) ;
break ;
}
SetCapture ( hwndDlg ) ;
return FALSE ;
}
static BOOL ListView_OnReturn ( HWND hwndDlg , NMHDR * pnmh )
{
SendMessage ( hwndDlg , WM_COMMAND , ( ( ! ! ( GetAsyncKeyState ( VK_SHIFT ) & 0x8000 ) ) ^ ( ! ! g_config - > ReadInt ( L " enqueuedef " , 0 ) ) )
? IDC_BUTTON_ENQUEUE : IDC_BUTTON_PLAY , 0 ) ;
return FALSE ;
}
static BOOL ListView_OnCustomDraw ( HWND hwndDlg , NMLVCUSTOMDRAW * plvcd , LRESULT * pResult )
{
static BOOL bDrawFocus ;
static RECT rcView ;
static RATINGCOLUMNPAINT ratingColumnPaint ;
static CLOUDCOLUMNPAINT cloudColumnPaint ;
* pResult = CDRF_DODEFAULT ;
switch ( plvcd - > nmcd . dwDrawStage )
{
case CDDS_PREPAINT :
* pResult | = CDRF_NOTIFYITEMDRAW ;
CopyRect ( & rcView , & plvcd - > nmcd . rc ) ;
ratingColumnPaint . fStyle = RCS_DEFAULT ;
ratingColumnPaint . hwndList = plvcd - > nmcd . hdr . hwndFrom ;
ratingColumnPaint . hdc = plvcd - > nmcd . hdc ;
ratingColumnPaint . prcView = & rcView ;
cloudColumnPaint . hwndList = plvcd - > nmcd . hdr . hwndFrom ;
cloudColumnPaint . hdc = plvcd - > nmcd . hdc ;
cloudColumnPaint . prcView = & rcView ;
return TRUE ;
case CDDS_ITEMPREPAINT :
* pResult | = CDRF_NOTIFYSUBITEMDRAW ;
bDrawFocus = ( CDIS_FOCUS & plvcd - > nmcd . uItemState ) ;
if ( bDrawFocus )
{
plvcd - > nmcd . uItemState & = ~ CDIS_FOCUS ;
* pResult | = CDRF_NOTIFYPOSTPAINT ;
}
return TRUE ;
case CDDS_ITEMPOSTPAINT :
if ( bDrawFocus )
{
RECT rc ;
rc . left = LVIR_BOUNDS ;
SendMessageW ( plvcd - > nmcd . hdr . hwndFrom , LVM_GETITEMRECT , plvcd - > nmcd . dwItemSpec , ( LPARAM ) & rc ) ;
rc . left + = 3 ;
DrawFocusRect ( plvcd - > nmcd . hdc , & rc ) ;
plvcd - > nmcd . uItemState | = CDIS_FOCUS ;
bDrawFocus = FALSE ;
}
* pResult = CDRF_SKIPDEFAULT ;
return TRUE ;
case ( CDDS_SUBITEM | CDDS_ITEMPREPAINT ) :
switch ( columnOrder [ plvcd - > iSubItem ] )
{
case MEDIAVIEW_COL_RATING :
if ( bgThread_Handle | | ( 0 = = plvcd - > iSubItem & & 0 = = plvcd - > nmcd . rc . right ) ) break ;
ratingColumnPaint . iItem = plvcd - > nmcd . dwItemSpec ;
ratingColumnPaint . iSubItem = plvcd - > iSubItem ;
ratingColumnPaint . value = ( plvcd - > nmcd . dwItemSpec > = 0 & & plvcd - > nmcd . dwItemSpec < ( UINT ) itemCache . Size ) ? itemCache . Items [ plvcd - > nmcd . dwItemSpec ] . rating : 0 ;
ratingColumnPaint . prcItem = & plvcd - > nmcd . rc ;
ratingColumnPaint . rgbBk = plvcd - > clrTextBk ;
ratingColumnPaint . rgbFg = plvcd - > clrText ;
if ( MLRatingColumn_Paint ( plugin . hwndLibraryParent , & ratingColumnPaint ) )
{
* pResult = CDRF_SKIPDEFAULT ;
return TRUE ;
}
break ;
case MEDIAVIEW_COL_CLOUD :
if ( bgThread_Handle | | ( 0 = = plvcd - > iSubItem & & 0 = = plvcd - > nmcd . rc . right ) ) break ;
int icon = 4 ;
wchar_t * t = getRecordExtendedItem_fast ( & itemCache . Items [ plvcd - > nmcd . dwItemSpec ] , extended_fields . cloud ) ;
if ( t & & * t ) icon = _wtoi ( t ) ;
cloudColumnPaint . iItem = plvcd - > nmcd . dwItemSpec ;
cloudColumnPaint . iSubItem = plvcd - > iSubItem ;
cloudColumnPaint . value = icon ;
cloudColumnPaint . prcItem = & plvcd - > nmcd . rc ;
cloudColumnPaint . rgbBk = plvcd - > clrTextBk ;
cloudColumnPaint . rgbFg = plvcd - > clrText ;
if ( MLCloudColumn_Paint ( plugin . hwndLibraryParent , & cloudColumnPaint ) )
{
* pResult = CDRF_SKIPDEFAULT ;
return TRUE ;
}
break ;
}
break ;
}
return FALSE ;
}
static BOOL ListView_OnClick ( HWND hwnDlg , NMITEMACTIVATE * pnmitem )
{
if ( bgThread_Handle ) return FALSE ;
if ( pnmitem - > iItem ! = - 1 )
{
switch ( columnOrder [ pnmitem - > iSubItem ] )
{
case MEDIAVIEW_COL_RATING :
ratingColumn . hwndList = pnmitem - > hdr . hwndFrom ;
ratingColumn . ptAction = pnmitem - > ptAction ;
ratingColumn . bRedrawNow = TRUE ;
ratingColumn . fStyle = RCS_DEFAULT ;
if ( ! MLRatingColumn_Click ( plugin . hwndLibraryParent , & ratingColumn ) ) return FALSE ;
SetRating ( ratingColumn . iItem , ratingColumn . value , ratingColumn . hwndList ) ;
break ;
case MEDIAVIEW_COL_CLOUD :
{
RECT itemRect = { 0 } ;
if ( pnmitem - > iSubItem )
ListView_GetSubItemRect ( pnmitem - > hdr . hwndFrom , pnmitem - > iItem , pnmitem - > iSubItem , LVIR_BOUNDS , & itemRect ) ;
else
{
ListView_GetItemRect ( pnmitem - > hdr . hwndFrom , pnmitem - > iItem , & itemRect , LVIR_BOUNDS ) ;
itemRect . right = itemRect . left + ListView_GetColumnWidth ( pnmitem - > hdr . hwndFrom , pnmitem - > iSubItem ) ;
}
MapWindowPoints ( pnmitem - > hdr . hwndFrom , HWND_DESKTOP , ( POINT * ) & itemRect , 2 ) ;
HMENU cloud_menu = CreatePopupMenu ( ) ;
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_GET_CLOUD_STATUS , ( intptr_t ) itemCache . Items [ pnmitem - > iItem ] . filename , ( intptr_t ) & cloud_menu ) ;
if ( cloud_menu )
{
int r = DoTrackPopup ( cloud_menu , TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON , itemRect . right , itemRect . top , pnmitem - > hdr . hwndFrom , NULL ) ;
if ( r > = CLOUD_SOURCE_MENUS & & r < CLOUD_SOURCE_MENUS_UPPER )
{
// 0 = no change
// 1 = adding to cloud
// 2 = added locally
// 4 = removed
int mode = 0 ; // deals with cloud specific menus
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_PROCESS_CLOUD_STATUS , ( intptr_t ) r , ( intptr_t ) & mode ) ;
switch ( mode )
{
case 1 :
setCloudValue ( & itemCache . Items [ pnmitem - > iItem ] , L " 5 " ) ;
break ;
case 2 :
setCloudValue ( & itemCache . Items [ pnmitem - > iItem ] , L " 4 " ) ;
break ;
case 4 :
setCloudValue ( & itemCache . Items [ pnmitem - > iItem ] , L " 4 " ) ;
break ;
}
InvalidateRect ( resultlist . getwnd ( ) , NULL , TRUE ) ;
}
DestroyMenu ( cloud_menu ) ;
}
}
break ;
}
}
return FALSE ;
}
static BOOL ListView_OnHotTrack ( HWND hwndDlg , NMLISTVIEW * pnmlv , LRESULT * pResult )
{
UINT iItem ;
if ( bgThread_Handle )
{
pnmlv - > iItem = - 1 ;
* pResult = TRUE ;
return TRUE ;
}
if ( - 1 = = pnmlv - > iItem & & 0 = = pnmlv - > iSubItem )
{
LVHITTESTINFO lvhit ;
lvhit . pt = pnmlv - > ptAction ;
SendMessageW ( pnmlv - > hdr . hwndFrom , LVM_HITTEST , 0 , ( LPARAM ) & lvhit ) ;
iItem = lvhit . iItem ;
}
else iItem = pnmlv - > iItem ;
switch ( columnOrder [ pnmlv - > iSubItem ] )
{
case MEDIAVIEW_COL_RATING :
ratingColumn . hwndList = pnmlv - > hdr . hwndFrom ;
ratingColumn . fStyle = RCS_DEFAULT ;
ratingColumn . iItem = iItem ;
ratingColumn . iSubItem = pnmlv - > iSubItem ;
ratingColumn . value = ( iItem < ( UINT ) itemCache . Size ) ? itemCache . Items [ iItem ] . rating : 0 ;
ratingColumn . ptAction = pnmlv - > ptAction ;
ratingColumn . bRedrawNow = TRUE ;
MLRatingColumn_Track ( plugin . hwndLibraryParent , & ratingColumn ) ;
break ;
}
// LVS_EX_ONECLICKACTIVATE enabled - make listview select nothing
pnmlv - > iItem = - 1 ;
* pResult = TRUE ;
return TRUE ;
}
/////////// Dialog Messages / Notifications
static void Dialog_OnDisplayChange ( HWND hwndDlg )
{
INT i ;
HWND hwndList = GetDlgItem ( hwndDlg , IDC_LIST2 ) ;
for ( i = 0 ; - 1 ! = columnOrder [ i ] & & MEDIAVIEW_COL_RATING ! = columnOrder [ i ] & & MEDIAVIEW_COL_CLOUD ! = columnOrder [ i ] ; i + + ) ;
if ( - 1 ! = columnOrder [ i ] )
{
if ( hwndList )
{
INT w = ( INT ) SendMessageW ( hwndList , LVM_GETCOLUMNWIDTH , i , 0L ) ;
SendMessageW ( hwndList , LVM_SETCOLUMNWIDTH , i , ( LPARAM ) w ) ;
}
}
LayoutWindows ( hwndDlg , TRUE ) ;
}
static wchar_t tt_buf [ 256 ] = { L " " } ;
static int last_item = - 1 , last_icon = - 1 ;
LRESULT pmp_listview ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam ) {
if ( uMsg = = WM_NOTIFY )
{
LPNMHDR l = ( LPNMHDR ) lParam ;
switch ( l - > code )
{
case TTN_SHOW :
{
LVHITTESTINFO lvh = { 0 } ;
GetCursorPos ( & lvh . pt ) ;
ScreenToClient ( hwnd , & lvh . pt ) ;
ListView_SubItemHitTest ( hwnd , & lvh ) ;
int cloudcol = ( int ) GetPropW ( hwnd , L " pmp_list_info " ) ;
if ( lvh . iItem ! = - 1 & & lvh . iSubItem = = cloudcol )
{
RECT r = { 0 } ;
if ( lvh . iSubItem )
ListView_GetSubItemRect ( hwnd , lvh . iItem , lvh . iSubItem , LVIR_BOUNDS , & r ) ;
else
{
ListView_GetItemRect ( hwnd , lvh . iItem , & r , LVIR_BOUNDS ) ;
r . right = r . left + ListView_GetColumnWidth ( hwnd , cloudcol ) ;
}
MapWindowPoints ( hwnd , HWND_DESKTOP , ( LPPOINT ) & r , 2 ) ;
SetWindowPos ( l - > hwndFrom , HWND_TOPMOST , r . right , r . top + 2 , 0 , 0 , SWP_NOACTIVATE | SWP_NOSIZE ) ;
return 1 ;
}
}
break ;
case TTN_NEEDTEXTW :
{
LVHITTESTINFO lvh = { 0 } ;
GetCursorPos ( & lvh . pt ) ;
ScreenToClient ( hwnd , & lvh . pt ) ;
ListView_SubItemHitTest ( hwnd , & lvh ) ;
int cloudcol = ( int ) GetPropW ( hwnd , L " pmp_list_info " ) ;
if ( lvh . iItem ! = - 1 & & lvh . iSubItem = = cloudcol )
{
LPNMTTDISPINFOW lpnmtdi = ( LPNMTTDISPINFOW ) lParam ;
int icon = 4 ;
wchar_t * t = getRecordExtendedItem_fast ( & itemCache . Items [ lvh . iItem ] , extended_fields . cloud ) ;
if ( t & & * t ) icon = _wtoi ( t ) ;
if ( last_item = = lvh . iItem & & last_icon = = icon )
{
lpnmtdi - > lpszText = tt_buf ;
return 0 ;
}
if ( icon = = 4 )
{
WASABI_API_LNGSTRINGW_BUF ( IDS_UPLOAD_TO_SOURCE , tt_buf , ARRAYSIZE ( tt_buf ) ) ;
}
else if ( icon = = 5 )
{
WASABI_API_LNGSTRINGW_BUF ( IDS_UPLOADING_TO_SOURCE , tt_buf , ARRAYSIZE ( tt_buf ) ) ;
}
else
{
if ( ! cloud_hinst ) cloud_hinst = ( HINSTANCE ) SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_HINST ) ;
if ( cloud_hinst & & cloud_hinst ! = ( HINSTANCE ) 1 )
{
winampMediaLibraryPlugin * ( * gp ) ( ) ;
gp = ( winampMediaLibraryPlugin * ( __cdecl * ) ( void ) ) GetProcAddress ( cloud_hinst , " winampGetMediaLibraryPlugin " ) ;
if ( gp )
{
winampMediaLibraryPlugin * mlplugin = gp ( ) ;
if ( mlplugin & & ( mlplugin - > version > = MLHDR_VER_OLD & & mlplugin - > version < = MLHDR_VER ) )
{
WASABI_API_LNGSTRINGW_BUF ( IDS_TRACK_AVAILABLE , tt_buf , ARRAYSIZE ( tt_buf ) ) ;
nx_string_t * out_devicenames = 0 ;
size_t num_names = mlplugin - > MessageProc ( 0x405 , ( INT_PTR ) itemCache . Items [ lvh . iItem ] . filename , ( INT_PTR ) & out_devicenames , 0 ) ;
if ( num_names > 0 )
{
for ( size_t i = 0 ; i < num_names ; i + + )
{
if ( i > 0 ) StringCchCatW ( tt_buf , ARRAYSIZE ( tt_buf ) , L " , " ) ;
StringCchCatW ( tt_buf , ARRAYSIZE ( tt_buf ) , out_devicenames [ i ] - > string ) ;
}
}
else
{
WASABI_API_LNGSTRINGW_BUF ( IDS_UPLOAD_TO_SOURCE , tt_buf , ARRAYSIZE ( tt_buf ) ) ;
}
if ( out_devicenames )
free ( out_devicenames ) ;
}
}
}
}
last_item = lvh . iItem ;
last_icon = icon ;
lpnmtdi - > lpszText = tt_buf ;
// bit of a fiddle but it allows for multi-line tooltips
//SendMessage(l->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 0);
}
else
return CallWindowProcW ( ( WNDPROC ) GetPropW ( hwnd , L " pmp_list_proc " ) , hwnd , uMsg , wParam , lParam ) ;
}
return 0 ;
}
}
return CallWindowProcW ( ( WNDPROC ) GetPropW ( hwnd , L " pmp_list_proc " ) , hwnd , uMsg , wParam , lParam ) ;
}
void Dialog_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 ;
}
}
}
enum
{
BPM_ECHO_WM_COMMAND = 0x1 , // send WM_COMMAND and return value
BPM_WM_COMMAND = 0x2 , // just send WM_COMMAND
} ;
BOOL Dialog_ButtonPopupMenu ( HWND hwndDlg , int buttonId , HMENU menu , int flags = 0 )
{
RECT r ;
HWND buttonHWND = GetDlgItem ( hwndDlg , buttonId ) ;
GetWindowRect ( buttonHWND , & r ) ;
UpdateMenuItems ( hwndDlg , menu , IDR_VIEW_ACCELERATORS ) ;
MLSkinnedButton_SetDropDownState ( buttonHWND , TRUE ) ;
UINT tpmFlags = TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_BOTTOMALIGN | TPM_LEFTALIGN ;
if ( ! ( flags & BPM_WM_COMMAND ) ) tpmFlags | = TPM_RETURNCMD ;
int x = DoTrackPopup ( 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 Dialog_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 ) ;
}
}
Dialog_ButtonPopupMenu ( hwndDlg , idFrom , listMenu , BPM_WM_COMMAND ) ;
}
static INT_PTR Dialog_OnInit ( HWND hwndDlg , HWND hwndFocus , LPARAM lParam )
{
// benski> this is just going here because it's very likely to get called. will only get compiled in debug mode.
assert ( sizeof ( extra_idsW ) / sizeof ( * extra_idsW ) = = sizeof ( extra_strsW ) / sizeof ( * extra_strsW ) ) ;
g_displaysearch = ! ( BOOL ) lParam ;
// Set the hwnd for the search to a global only if the multipane view hasnt set it yet, as it takes precedence to which box gets populated with the query
//if (!IsWindow(hwndSearchGlobal))
hwndSearchGlobal = GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) ;
HACCEL accel = WASABI_API_LOADACCELERATORSW ( IDR_VIEW_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 ) ;
}
HWND hwndList ;
FLICKERFIX ff ;
INT index ;
INT ffcl [ ] = { IDC_CLEAR ,
IDC_BUTTON_PLAY ,
IDC_BUTTON_ENQUEUE ,
IDC_BUTTON_MIX ,
IDC_BUTTON_INFOTOGGLE ,
IDC_BUTTON_CREATEPLAYLIST ,
IDC_MIXABLE ,
IDC_MEDIASTATUS ,
} ;
m_hwnd = hwndDlg ;
m_bgupdinfoviewerflag = 0 ;
columnOrder [ 0 ] = - 1 ;
last_item = - 1 ;
tt_buf [ 0 ] = 0 ;
if ( ! cloud_hinst ) cloud_hinst = ( HINSTANCE ) SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_HINST ) ;
if ( cloud_hinst & & cloud_hinst ! = ( HINSTANCE ) 1 )
{
winampMediaLibraryPlugin * ( * gp ) ( ) ;
gp = ( winampMediaLibraryPlugin * ( __cdecl * ) ( void ) ) GetProcAddress ( cloud_hinst , " winampGetMediaLibraryPlugin " ) ;
if ( gp )
{
winampMediaLibraryPlugin * mlplugin = gp ( ) ;
if ( mlplugin & & ( mlplugin - > version > = MLHDR_VER_OLD & & mlplugin - > version < = MLHDR_VER ) )
{
int64_t * out_ids = 0 ;
nx_string_t * out_filenames = 0 ;
size_t num_files = mlplugin - > MessageProc ( 0x404 , ( INT_PTR ) & out_filenames , ( INT_PTR ) & out_ids , 0xDEADBEEF ) ;
for ( size_t i = 0 ; i < num_files ; i + + )
{
cloudFiles . push_back ( ( wchar_t * ) out_filenames [ i ] - > string ) ;
}
if ( out_filenames )
{
free ( out_filenames ) ;
out_filenames = 0 ;
}
if ( out_ids )
{
free ( out_ids ) ;
out_ids = 0 ;
}
HWND ml_pmp_window = FindWindowW ( L " ml_pmp_window " , NULL ) ;
if ( IsWindow ( ml_pmp_window ) )
{
SendMessage ( ml_pmp_window , WM_PMP_IPC , ( WPARAM ) & cloudUploading , PMP_IPC_GETCLOUDTRANSFERS ) ;
wchar_t a [ 32 ] = { 0 } ;
StringCchPrintfW ( a , 32 , L " %d " , cloudUploading . size ( ) ) ;
}
}
}
}
EnterCriticalSection ( & g_db_cs ) ;
if ( ! m_media_scanner ) m_media_scanner = NDE_Table_CreateScanner ( g_table ) ;
LeaveCriticalSection ( & g_db_cs ) ;
itemCache . Items = 0 ;
itemCache . Alloc = 0 ;
itemCache . Size = 0 ;
hwndList = GetDlgItem ( hwndDlg , IDC_LIST2 ) ;
if ( IsWindow ( hwndList ) )
{
resultlist . setwnd ( hwndList ) ;
resultlist . ForceUnicode ( ) ;
DWORD styleEx = LVS_EX_DOUBLEBUFFER | LVS_EX_HEADERDRAGDROP | LVS_EX_ONECLICKACTIVATE ; /*LVS_EX_ONECLICKACTIVATE - needed to hottracking work prior WinXp */
SendMessageW ( hwndList , LVM_SETEXTENDEDLISTVIEWSTYLE , styleEx , styleEx ) ;
HWND hwndHeader = ( HWND ) SendMessage ( hwndList , LVM_GETHEADER , 0 , 0L ) ;
if ( IsWindow ( hwndHeader ) ) SetWindowLongPtrW ( hwndHeader , GWLP_ID , IDC_LIST2HEADER ) ;
MLSKINWINDOW skin = { 0 } ;
skin . hwndToSkin = hwndList ;
skin . skinType = SKINNEDWND_TYPE_LISTVIEW ;
skin . style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER | SWLVS_ALTERNATEITEMS ;
MLSkinWindow ( plugin . hwndLibraryParent , & skin ) ;
}
else resultlist . setwnd ( NULL ) ;
ff . mode = FFM_ERASEINPAINT ;
for ( index = 0 ; index < sizeof ( ffcl ) / sizeof ( INT ) ; index + + )
{
ff . hwnd = GetDlgItem ( hwndDlg , ffcl [ index ] ) ;
SENDMLIPC ( plugin . hwndLibraryParent , ML_IPC_FLICKERFIX , ( WPARAM ) & ff ) ;
}
if ( ! g_displaysearch ) // disable search box
{
ShowWindow ( GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) , SW_HIDE ) ;
ShowWindow ( GetDlgItem ( hwndDlg , IDC_CLEAR ) , SW_HIDE ) ;
ShowWindow ( GetDlgItem ( hwndDlg , IDC_SEARCHCAPTION ) , SW_HIDE ) ;
}
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 )
memcpy ( columnOrder , defColumnOrder , sizeof ( defColumnOrder ) ) ;
else
memcpy ( columnOrder , defColumnOrderCloud , sizeof ( defColumnOrderCloud ) ) ;
//Read the column order
Dialog_OnDisplayChange ( hwndDlg ) ;
int cloudcol = - 1 ;
int l = g_view_metaconf - > ReadInt ( L " nbcolumns " , 0 ) ;
if ( l )
{
if ( l > MAX_COLUMN_ORDER - 1 ) l = MAX_COLUMN_ORDER - 1 ;
index = 0 ;
for ( ; index < l ; index + + )
{
wchar_t tmp [ 128 ] = { 0 } ;
StringCchPrintfW ( tmp , 128 , L " column%d " , index ) ;
int v = g_view_metaconf - > ReadInt ( tmp , 0 ) ;
if ( v = = MEDIAVIEW_COL_CLOUD ) cloudcol = index ;
if ( v < 0 | | v > = MEDIAVIEW_COL_NUMS ) v = 0 ;
columnOrder [ index ] = ( BYTE ) v ;
}
columnOrder [ index ] = - 1 ;
}
if ( cloudcol = = - 1 & & ! g_view_metaconf - > ReadInt ( L " cloud " , 1 ) )
{
g_view_metaconf - > WriteInt ( L " cloud " , 1 ) ;
for ( int i = l ; i ! = 0 ; i - - )
{
columnOrder [ i + 1 ] = columnOrder [ i ] ;
if ( i = = 3 )
{
columnOrder [ i ] = MEDIAVIEW_COL_CLOUD ;
break ;
}
}
}
if ( ! GetPropW ( hwndList , L " pmp_list_proc " ) ) {
SetPropW ( hwndList , L " pmp_list_proc " , ( HANDLE ) SetWindowLongPtrW ( hwndList , GWLP_WNDPROC , ( LONG_PTR ) pmp_listview ) ) ;
}
initColumnsHeader ( hwndList ) ;
char * pszTextA = ( g_config - > ReadInt ( L " remembersearch " , 0 ) ) ? g_view_metaconf - > ReadString ( " lastquery_utf8 " , " " ) : " " ;
AutoWide queryUnicode ( pszTextA , CP_UTF8 ) ;
SetDlgItemTextW ( hwndDlg , IDC_QUICKSEARCH , queryUnicode ) ;
KillTimer ( hwndDlg , UPDATE_QUERY_TIMER_ID ) ;
doQuery ( hwndDlg , queryUnicode , 0 ) ;
updateInfoText ( hwndDlg ) ;
search_oldWndProc = ( WNDPROC ) SetWindowLongPtrW ( GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) , GWLP_WNDPROC , ( LONG_PTR ) search_newWndProc ) ;
if ( g_table & & ! NDE_Table_GetRecordsCount ( g_table ) & & ! g_config - > ReadInt ( L " noshowadddlg " , 0 ) )
{
SetTimer ( hwndDlg , 5050 , 1000 , NULL ) ;
}
groupBtn = g_config - > ReadInt ( L " groupbtn " , 1 ) ;
enqueuedef = ( g_config - > ReadInt ( L " enqueuedef " , 0 ) = = 1 ) ;
/// detect predixis
predixisExist = FALSE ;
//predixis out - begin
//pluginMessage p = {ML_MSG_PDXS_STATUS, (INT_PTR)"test", 0, 0};
//pszTextA = (char *)SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_SEND_PLUGIN_MESSAGE, (WPARAM)&p);
//predixisExist = (pszTextA != NULL && pszTextA[0] != 0);
//predixis out - end
// 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_MIX , IDC_BUTTON_ENQUEUE ) , ( INT_PTR ) L " ml_local " } ;
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_MIX , pszTextW ) ;
}
else
customAllowed = FALSE ;
ShowWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON_MIX ) , ( ! customAllowed ? SW_HIDE : SW_SHOW ) ) ;
ShowWindow ( GetDlgItem ( hwndDlg , IDC_MIXABLE ) , ( ! ( predixisExist & 1 ) ? SW_HIDE : SW_SHOW ) ) ;
MLSKINWINDOW m = { 0 } ;
m . hwndToSkin = hwndDlg ;
m . skinType = SKINNEDWND_TYPE_AUTO ;
m . style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWLVS_FULLROWSELECT | SWLVS_DOUBLEBUFFER | SWLVS_ALTERNATEITEMS ;
MLSkinWindow ( plugin . hwndLibraryParent , & m ) ;
m . skinType = SKINNEDWND_TYPE_BUTTON ;
m . style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS | ( groupBtn ? SWBS_SPLITBUTTON : 0 ) ;
const int buttonids [ ] = { IDC_BUTTON_PLAY , IDC_BUTTON_ENQUEUE , IDC_BUTTON_MIX } ;
for ( size_t i = 0 ; i ! = sizeof ( buttonids ) / sizeof ( buttonids [ 0 ] ) ; i + + )
{
m . hwndToSkin = GetDlgItem ( hwndDlg , buttonids [ i ] ) ;
if ( IsWindow ( m . hwndToSkin ) ) MLSkinWindow ( plugin . hwndLibraryParent , & m ) ;
}
m . skinType = SKINNEDWND_TYPE_AUTO ;
m . style = SWS_USESKINFONT | SWS_USESKINCOLORS | SWS_USESKINCURSORS ;
const int buttonidz [ ] = { IDC_SEARCHCAPTION , IDC_QUICKSEARCH , IDC_MEDIASTATUS , IDC_CLEAR , IDC_BUTTON_INFOTOGGLE , IDC_BUTTON_CREATEPLAYLIST , IDC_MIXABLE } ;
for ( size_t i = 0 ; i ! = sizeof ( buttonidz ) / sizeof ( buttonidz [ 0 ] ) ; i + + )
{
m . hwndToSkin = GetDlgItem ( hwndDlg , buttonidz [ i ] ) ;
if ( IsWindow ( m . hwndToSkin ) ) MLSkinWindow ( plugin . hwndLibraryParent , & m ) ;
}
Dialog_UpdateButtonText ( hwndDlg , enqueuedef ) ;
return FALSE ;
}
static BOOL Dialog_OnNotify ( HWND hwndDlg , INT idCtrl , NMHDR * pnmh , LRESULT * pResult )
{
switch ( pnmh - > idFrom )
{
case IDC_LIST2 :
switch ( pnmh - > code )
{
case LVN_ITEMCHANGED : return ListView_OnItemChanged ( hwndDlg , ( NMLISTVIEW * ) pnmh ) ;
case NM_DBLCLK : return ListView_OnDoubleClick ( hwndDlg , ( NMITEMACTIVATE * ) pnmh ) ;
case LVN_ODFINDITEMA :
case LVN_ODFINDITEMW : return ListView_OnFindItem ( hwndDlg , ( NMLVFINDITEMW * ) pnmh , pResult , pnmh - > code ) ;
case LVN_GETDISPINFOA :
case LVN_GETDISPINFOW : return ListView_OnGetDispInfo ( hwndDlg , ( NMLVDISPINFOW * ) pnmh , pnmh - > code ) ;
case LVN_COLUMNCLICK : return ListView_OnColumnClick ( hwndDlg , ( NMLISTVIEW * ) pnmh ) ;
case LVN_BEGINDRAG : return ListView_OnBeginDrag ( hwndDlg , ( NMLISTVIEW * ) pnmh ) ;
case NM_RETURN : return ListView_OnReturn ( hwndDlg , pnmh ) ;
case NM_CUSTOMDRAW : return ListView_OnCustomDraw ( hwndDlg , ( NMLVCUSTOMDRAW * ) pnmh , pResult ) ;
case LVN_HOTTRACK : return ListView_OnHotTrack ( hwndDlg , ( NMLISTVIEW * ) pnmh , pResult ) ;
case NM_CLICK : return ListView_OnClick ( hwndDlg , ( NMITEMACTIVATE * ) pnmh ) ;
}
break ;
case IDC_LIST2HEADER :
switch ( pnmh - > code )
{
case NM_RCLICK : return Header_OnRightClick ( hwndDlg , pnmh , pResult ) ;
case HDN_ENDDRAG : return Header_OnEndDrag ( hwndDlg , ( NMHEADERW * ) pnmh , pResult ) ;
case HDN_ITEMCHANGINGA :
case HDN_ITEMCHANGINGW : return Header_OnItemChanging ( hwndDlg , ( NMHEADERW * ) pnmh , pResult , pnmh - > code ) ;
}
break ;
}
return FALSE ;
}
static void Dialog_OnInitMenuPopup ( HWND hwndDlg , HMENU hMenu , UINT nIndex , BOOL bSysMenu )
{
if ( hMenu & & hMenu = = s . build_hMenu & & s . mode = = 1 )
{
myMenu = TRUE ;
if ( SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , ( WPARAM ) & s , IPC_LIBRARY_SENDTOMENU ) = = ( LRESULT ) - 1 )
s . mode = 2 ;
myMenu = FALSE ;
}
if ( rate_hmenu & & hMenu = = rate_hmenu )
{
int x ;
int sel = 0 ;
for ( x = 0 ; x < itemCache . Size ; x + + )
{
if ( resultlist . GetSelected ( x ) )
{
int s = itemCache . Items [ x ] . rating ;
if ( s = = sel | | ! sel ) sel = s ;
if ( s ! = sel ) break ;
}
}
if ( - 1 = = sel ) sel = 0 ;
Menu_SetRatingValue ( rate_hmenu , sel ) ;
}
if ( cloud_hmenu & & hMenu = = cloud_hmenu )
{
int n = resultlist . GetSelectionMark ( ) ;
if ( n ! = - 1 & & ! GetMenuItemCount ( hMenu ) )
{
WASABI_API_SYSCB - > syscb_issueCallback ( api_mldb : : SYSCALLBACK , api_mldb : : MLDB_FILE_GET_CLOUD_STATUS , ( intptr_t ) itemCache . Items [ n ] . filename , ( intptr_t ) & cloud_hmenu ) ;
}
}
}
static void Dialog_OnMouseMove ( HWND hwndDlg , UINT nFlags , POINTS pts )
{
if ( GetCapture ( ) = = hwndDlg )
{
mlDropItemStruct m = { 0 } ;
POINTSTOPOINT ( m . p , pts ) ;
MapWindowPoints ( hwndDlg , HWND_DESKTOP , ( POINT * ) & m . p , 1 ) ;
if ( MLRatingColumn_Drag ( plugin . hwndLibraryParent , & m . p ) ) return ;
m . type = ML_TYPE_ITEMRECORDLIST ;
pluginHandleIpcMessage ( ML_IPC_HANDLEDRAG , ( WPARAM ) & m ) ;
}
}
static void Dialog_OnLButtonUp ( HWND hwndDlg , UINT nFlags , POINTS pts )
{
if ( GetCapture ( ) = = hwndDlg )
{
mlDropItemStruct m = { 0 } ;
ReleaseCapture ( ) ;
POINTSTOPOINT ( m . p , pts ) ;
MapWindowPoints ( hwndDlg , HWND_DESKTOP , ( POINT * ) & m . p , 1 ) ;
ratingColumn . bCanceled = FALSE ;
ratingColumn . ptAction = m . p ;
ratingColumn . bRedrawNow = TRUE ;
if ( MLRatingColumn_EndDrag ( plugin . hwndLibraryParent , & ratingColumn ) )
{
SetRating ( ratingColumn . iItem , ratingColumn . value , ratingColumn . hwndList ) ;
return ;
}
m . type = ML_TYPE_ITEMRECORDLISTW ;
m . flags = ML_HANDLEDRAG_FLAG_NOCURSOR ;
pluginHandleIpcMessage ( ML_IPC_HANDLEDRAG , ( WPARAM ) & m ) ;
if ( m . result > 0 ) // try itemRecordListW
{
itemRecordListW myObj = { 0 , } ;
copyFilesToItemCacheW ( & myObj ) ;
m . flags = 0 ;
m . result = 0 ;
m . data = ( void * ) & myObj ;
pluginHandleIpcMessage ( ML_IPC_HANDLEDROP , ( WPARAM ) & m ) ;
_aligned_free ( myObj . Items ) ; // DO NOT empty this object, cause it doesnt own its data
}
else // if it didn't work, fall back to itemRecordList
{
m . type = ML_TYPE_ITEMRECORDLIST ;
m . result = 0 ;
pluginHandleIpcMessage ( ML_IPC_HANDLEDRAG , ( WPARAM ) & m ) ;
if ( m . result > 0 )
{
itemRecordListW myObj = { 0 , } ;
copyFilesToItemCacheW ( & myObj ) ;
itemRecordList objA = { 0 , } ;
convertRecordList ( & objA , & myObj ) ;
m . flags = 0 ;
m . result = 0 ;
m . data = ( void * ) & objA ;
pluginHandleIpcMessage ( ML_IPC_HANDLEDROP , ( WPARAM ) & m ) ;
emptyRecordList ( & objA ) ;
freeRecordList ( & objA ) ;
_aligned_free ( myObj . Items ) ; // DO NOT empty this object, cause it doesnt own its data
}
}
}
}
class ItemRecordPlaylist : public ifc_playlist
{
public :
ItemRecordPlaylist ( const itemRecordListW * _list )
{
list = _list ;
}
private :
size_t GetNumItems ( )
{
return list - > Size ;
}
size_t GetItem ( size_t item , wchar_t * filename , size_t filenameCch )
{
if ( item < ( size_t ) list - > Size & & list - > Items [ item ] . filename )
{
StringCchCopyW ( filename , filenameCch , list - > Items [ item ] . filename ) ;
return 1 ;
}
return 0 ;
}
size_t GetItemTitle ( size_t item , wchar_t * title , size_t titleCch )
{
if ( item < ( size_t ) list - > Size & & list - > Items [ item ] . filename )
{
TAG_FMT_EXT ( list - > Items [ item ] . filename , itemrecordWTagFunc , ndeTagFuncFree , ( void * ) & list - > Items [ item ] , title , titleCch , 0 ) ;
return 1 ;
}
return 0 ;
}
int GetItemLengthMilliseconds ( size_t item )
{
if ( item < ( size_t ) list - > Size & & list - > Items [ item ] . length > = 0 )
{
return list - > Items [ item ] . length * 1000 ;
}
return - 1000 ;
}
private :
const itemRecordListW * list ;
protected :
RECVS_DISPATCH ;
} ;
# define CBCLASS ItemRecordPlaylist
START_DISPATCH ;
CB ( IFC_PLAYLIST_GETNUMITEMS , GetNumItems )
CB ( IFC_PLAYLIST_GETITEM , GetItem )
CB ( IFC_PLAYLIST_GETITEMTITLE , GetItemTitle )
CB ( IFC_PLAYLIST_GETITEMLENGTHMILLISECONDS , GetItemLengthMilliseconds )
END_DISPATCH ;
# undef CBCLASS
static void Dialog_OnCommand ( HWND hwndDlg , UINT idCtrl , INT nCode , HWND hwndCtrl )
{
if ( GetFocus ( ) ! = hwndSearchGlobal )
{
switch ( idCtrl )
{
case IDC_CLEAR :
SetDlgItemText ( hwndDlg , IDC_QUICKSEARCH , L " " ) ;
break ;
case IDC_BUTTON_INFOTOGGLE :
updateInfoText ( hwndDlg , TRUE ) ;
UpdateWindow ( hwndDlg ) ;
LayoutWindows ( hwndDlg , TRUE ) ;
break ;
case IDC_QUICKSEARCH :
if ( nCode = = EN_CHANGE )
{
KillTimer ( hwndDlg , UPDATE_QUERY_TIMER_ID ) ;
SetTimer ( hwndDlg , UPDATE_QUERY_TIMER_ID , g_querydelay , NULL ) ;
}
break ;
case ID_AUDIOWND_PLAYSELECTION :
case ID_QUERYWND_PLAYQUERY :
case IDC_BUTTON_PLAY :
case ID_MEDIAWND_PLAYSELECTEDFILES :
case ID_AUDIOWND_ENQUEUESELECTION :
case IDC_BUTTON_ENQUEUE :
case ID_MEDIAWND_ENQUEUESELECTEDFILES :
case IDC_BUTTON_MIX :
{
if ( nCode = = MLBN_DROPDOWN )
{
Dialog_Play ( hwndDlg , hwndCtrl , idCtrl ) ;
}
else
{
int action ;
if ( idCtrl = = IDC_BUTTON_PLAY | | idCtrl = = ID_MEDIAWND_PLAYSELECTEDFILES | | idCtrl = = ID_AUDIOWND_PLAYSELECTION )
{
action = ( nCode = = 1 ) ? g_config - > ReadInt ( L " enqueuedef " , 0 ) = = 1 : 0 ;
}
else if ( idCtrl = = IDC_BUTTON_ENQUEUE | | idCtrl = = ID_MEDIAWND_ENQUEUESELECTEDFILES | | idCtrl = = ID_AUDIOWND_ENQUEUESELECTION )
{
action = ( nCode = = 1 ) ? g_config - > ReadInt ( L " enqueuedef " , 0 ) ! = 1 : 1 ;
}
else
break ;
int i , l = itemCache . Size ;
for ( i = 0 ; i < l ; i + + ) if ( resultlist . GetSelected ( i ) ) break ;
playFiles ( action /*idCtrl == IDC_BUTTON_ENQUEUE*/ , i = = l ) ;
}
}
break ;
case IDC_BUTTON_CREATEPLAYLIST :
#if 0
// TODO consider exposing this option somehow...
if ( AGAVE_API_PLAYLISTMANAGER ) // This is the old Create Playlist button code
{
wchar_t fn [ MAX_PATH ] = { 0 } ;
wchar_t dir [ MAX_PATH ] = { 0 } ;
GetTempPathW ( MAX_PATH , dir ) ;
GetTempFileNameW ( dir , L " ml_playlist " , 0 , fn ) ;
wcscat ( fn , L " .m3u8 " ) ;
ItemRecordPlaylist playlist ( & itemCache ) ;
if ( AGAVE_API_PLAYLISTMANAGER - > Save ( fn , & playlist ) = = PLAYLISTMANAGER_SUCCESS )
{
mlAddPlaylist p = { sizeof ( p ) , NULL , fn , PL_FLAGS_IMPORT , - 1 , - 1 } ;
SendMessage ( plugin . hwndLibraryParent , WM_ML_IPC , ( WPARAM ) & p , ML_IPC_PLAYLIST_ADD ) ;
DeleteFileW ( fn ) ;
}
}
# endif
if ( AGAVE_API_PLAYLIST_GENERATOR )
{
const int number_selected = resultlist . GetSelectedCount ( ) ; // Total selected
if ( number_selected > 0 )
{
itemRecordListW recordList ; // Record list
itemRecordW * records = new itemRecordW [ number_selected ] ; // Array of records
int selectedRecordcounter = 0 ;
for ( int i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) ) // See if the current item is selected or not
{
records [ selectedRecordcounter ] = itemCache . Items [ i ] ; // If its selected then add it to our itemlist
selectedRecordcounter + + ;
}
}
recordList . Size = selectedRecordcounter ; // Set the correct size of the record list
recordList . Items = records ; // Set the array of records to the record list
AGAVE_API_PLAYLIST_GENERATOR - > GeneratePlaylist ( hwndDlg , & recordList ) ; // Call the playlist API with the list of selected records
delete [ ] records ; // Free up the array of records
}
else
{
wchar_t title [ 64 ] = { 0 } ;
MessageBoxW ( m_hwnd , WASABI_API_LNGSTRINGW ( IDS_ERROR_PLG_SELECT_TRACKS ) , WASABI_API_LNGSTRINGW_BUF ( IDS_NULLSOFT_PLAYLIST_GENERATOR , title , 64 ) , MB_OK | MB_ICONINFORMATION ) ;
}
}
break ;
#if 0
case IDC_BUTTON_MIX :
{
itemRecordList list ;
int i ;
int ct = 0 ;
for ( i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
ct + + ;
}
}
ZeroMemory ( & list , sizeof ( itemRecordList ) ) ;
allocRecordList ( & list , ct , 1 ) ;
list . Size = ct ;
ct = 0 ;
for ( i = 0 ; i < itemCache . Size ; i + + )
{
if ( resultlist . GetSelected ( i ) )
{
convertRecord ( & list . Items [ ct ] , & itemCache . Items [ i ] ) ;
ct + + ;
}
}
pluginMessage p = { ML_MSG_PDXS_MIX , ( INT_PTR ) & list , 0 , 0 } ;
SendMessage ( plugin . hwndLibraryParent , WM_ML_IPC , ( WPARAM ) & p , ML_IPC_SEND_PLUGIN_MESSAGE ) ;
emptyRecordList ( & list ) ;
freeRecordList ( & list ) ;
}
break ;
# endif
case ID_MEDIAWND_SELECTALL :
{
LVITEM item = { 0 } ;
item . state = LVIS_SELECTED ;
item . stateMask = LVIS_SELECTED ;
SendMessageW ( resultlist . getwnd ( ) , LVM_SETITEMSTATE , ( WPARAM ) - 1 , ( LPARAM ) & item ) ;
}
break ;
case ID_MEDIAWND_REMOVEFROMLIBRARY :
removeSelectedItems ( 0 ) ;
break ;
case ID_EDITITEMINFOS :
if ( resultlist . GetSelectedCount ( ) > 0 )
editInfo ( hwndDlg ) ;
break ;
case ID_PE_ID3 :
fileInfoDialogs ( hwndDlg ) ;
PostMessageW ( hwndDlg , WM_NEXTDLGCTL , ( WPARAM ) resultlist . getwnd ( ) , ( LPARAM ) TRUE ) ;
break ;
case IDC_REFRESH_METADATA :
RefreshMetadata ( hwndDlg ) ;
break ;
case ID_MEDIAWND_EXPLOREFOLDER :
exploreItemFolder ( hwndDlg ) ;
break ;
}
}
else
{
switch ( idCtrl )
{
case IDC_QUICKSEARCH :
if ( nCode = = EN_CHANGE )
{
KillTimer ( hwndDlg , UPDATE_QUERY_TIMER_ID ) ;
SetTimer ( hwndDlg , UPDATE_QUERY_TIMER_ID , g_querydelay , NULL ) ;
}
break ;
case ID_MEDIAWND_SELECTALL :
SendMessageW ( hwndSearchGlobal , EM_SETSEL , 0 , - 1 ) ;
break ;
case ID_MEDIAWND_REMOVEFROMLIBRARY :
{
DWORD start = - 1 , end = - 1 ;
SendMessageW ( hwndSearchGlobal , EM_GETSEL , ( WPARAM ) & start , ( LPARAM ) & end ) ;
if ( start ! = - 1 )
{
if ( start = = end )
{
SendMessageW ( hwndSearchGlobal , EM_SETSEL , start , end + 1 ) ;
}
SendMessageW ( hwndSearchGlobal , EM_REPLACESEL , TRUE , ( LPARAM ) " " ) ;
SendMessageW ( hwndSearchGlobal , EM_SETSEL , start , start ) ;
}
}
break ;
}
}
}
static void Dialog_OnTimer ( HWND hwndDlg , UINT_PTR idEvent , TIMERPROC fnTimer )
{
switch ( idEvent )
{
case 5050 :
KillTimer ( hwndDlg , 5050 ) ;
WASABI_API_DIALOGBOXW ( IDD_NEEDADDFILES , hwndDlg , needAddFilesProc ) ;
PostMessage ( GetParent ( hwndDlg ) , WM_APP + 1 , ( WPARAM ) 0 , ( LPARAM ) 0 ) ;
break ;
case 6600 :
KillTimer ( hwndDlg , idEvent ) ;
if ( m_last_selitem > = 0 & & m_last_selitem < itemCache . Size )
{
if ( predixisExist & 1 )
{
// Only single seeds are supported currently
if ( resultlist . GetSelectedCount ( ) = = 1 & & isMixable ( itemCache . Items [ m_last_selitem ] ) )
{
SetDlgItemTextW ( hwndDlg , IDC_MIXABLE , WASABI_API_LNGSTRINGW ( IDS_MIXABLE ) ) ;
isMixablePresent = true ;
}
else SetDlgItemText ( hwndDlg , IDC_MIXABLE , L " " ) ;
}
SendMessageW ( GetParent ( hwndDlg ) , WM_SHOWFILEINFO , ( WPARAM ) FALSE , ( LPARAM ) itemCache . Items [ m_last_selitem ] . filename ) ;
m_last_selitem = - 1 ;
}
break ;
case 123 :
if ( bgThread_Handle )
{
HWND hwndList ;
hwndList = resultlist . getwnd ( ) ;
if ( 1 ! = ListView_GetItemCount ( hwndList ) ) ListView_SetItemCountEx ( hwndList , 1 , LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL ) ;
ListView_RedrawItems ( hwndList , 0 , 0 ) ;
//UpdateWindow(hwndList);
}
break ;
case UPDATE_QUERY_TIMER_ID :
{
KillTimer ( hwndDlg , UPDATE_QUERY_TIMER_ID ) ;
wchar_t buf [ 2048 ] = { 0 } ;
GetWindowTextW ( GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) , buf , ARRAYSIZE ( buf ) ) ;
doQuery ( hwndDlg , buf ) ;
}
break ;
case UPDATE_RESULT_LIST_TIMER_ID :
{
ListView_RedrawItems ( resultlist . getwnd ( ) , 0 , resultlist . GetCount ( ) - 1 ) ;
}
break ;
}
}
static void Dialog_OnDestroy ( HWND hwndDlg )
{
HWND hwndList ;
INT i , j ;
wchar_t buf [ 2048 ] = { 0 } ;
bgQuery_Stop ( ) ;
GetDlgItemTextW ( hwndDlg , IDC_QUICKSEARCH , buf , ARRAYSIZE ( buf ) ) ;
g_view_metaconf - > WriteString ( " lastquery_utf8 " , AutoChar ( buf , CP_UTF8 ) ) ;
hwndList = GetDlgItem ( hwndDlg , IDC_LIST2 ) ;
if ( hwndList & & IsWindow ( hwndList ) )
{
for ( i = 0 ; columnOrder [ i ] ! = - 1 ; i + + )
{
headerColumn * cl = & columnList [ columnOrder [ i ] ] ;
g_view_metaconf - > WriteInt ( AutoWide ( cl - > config_name ) , SendMessageW ( hwndList , LVM_GETCOLUMNWIDTH , i , 0L ) ) ;
}
}
//Save the column order
for ( i = 0 ; columnOrder [ i ] ! = - 1 ; i + + ) ;
g_view_metaconf - > WriteInt ( L " nbcolumns " , i ) ;
for ( j = 0 ; j < i ; j + + )
{
wchar_t tmp [ 128 ] = { 0 } ;
StringCchPrintfW ( tmp , 128 , L " column%d " , j ) ;
g_view_metaconf - > WriteInt ( tmp , columnOrder [ j ] ) ;
}
freeRecordList ( & itemCache ) ;
itemCache . Items = 0 ;
itemCache . Alloc = 0 ;
itemCache . Size = 0 ;
cloudFiles . clear ( ) ;
cloudUploading . clear ( ) ;
hwndSearchGlobal = 0 ; // Set the hwnd for the search to a global to null so we know we are not in the single pane view
}
static void Dialog_OnWindowPosChanged ( HWND hwndDlg , WINDOWPOS * pwp )
{
if ( ( SWP_NOSIZE | SWP_NOMOVE ) ! = ( ( SWP_NOSIZE | SWP_NOMOVE ) & pwp - > flags ) | | ( SWP_FRAMECHANGED & pwp - > flags ) )
{
LayoutWindows ( hwndDlg , ! ( SWP_NOREDRAW & pwp - > flags ) , 0 ! = ( SWP_SHOWWINDOW & pwp - > flags ) ) ;
}
}
static void Dialog_OnSyncHeaderOrder ( HWND hwndDlg , HWND hwndHeader )
{
LVCOLUMNW column = { 0 } ;
wchar_t buffer [ 128 ] = { 0 } ;
signed char tempOrder [ MAX_COLUMN_ORDER ] = { 0 } ;
HWND hwndList = GetDlgItem ( hwndDlg , IDC_LIST2 ) ;
if ( ! hwndList ) return ;
CopyMemory ( tempOrder , columnOrder , sizeof ( tempOrder ) / sizeof ( signed char ) ) ;
column . mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_IMAGE ;
column . cchTextMax = sizeof ( buffer ) / sizeof ( wchar_t ) ;
SendMessageW ( hwndList , WM_SETREDRAW , FALSE , 0L ) ;
INT sort = MLSkinnedListView_GetSort ( hwndList ) ;
INT count = ( INT ) SendMessageW ( hwndHeader , HDM_GETITEMCOUNT , 0 , 0L ) ;
if ( count > 0 )
{
INT index = count + 1 , * pOrder = ( INT * ) calloc ( 1 , sizeof ( INT ) * count ) ;
if ( pOrder & & SendMessageW ( hwndList , LVM_GETCOLUMNORDERARRAY , count , ( LPARAM ) pOrder ) )
{
INT order ;
for ( order = 0 ; order < count ; order + + )
{
column . pszText = buffer ;
if ( ! SendMessageW ( hwndList , LVM_GETCOLUMNW , pOrder [ order ] , ( LPARAM ) & column ) ) continue ;
column . iOrder = order ;
// update position of the cloud column icon
if ( tempOrder [ pOrder [ order ] ] = = MEDIAVIEW_COL_CLOUD )
{
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 | |
! SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_ACTIVE ) )
{
MLSkinnedHeader_SetCloudColumn ( ListView_GetHeader ( hwndList ) , - 1 ) ;
SetPropW ( hwndList , L " pmp_list_info " , ( HANDLE ) - 1 ) ;
column . cx = 0 ;
}
else
{
MLSkinnedHeader_SetCloudColumn ( ListView_GetHeader ( hwndList ) , order ) ;
SetPropW ( hwndList , L " pmp_list_info " , ( HANDLE ) order ) ;
column . cx = 27 ;
MLCloudColumn_GetWidth ( plugin . hwndLibraryParent , & column . cx ) ;
}
}
SendMessageW ( hwndList , LVM_INSERTCOLUMNW , index + + , ( LPARAM ) & column ) ;
columnOrder [ order ] = tempOrder [ pOrder [ order ] ] ;
if ( LOWORD ( sort ) = = pOrder [ order ] ) MLSkinnedListView_DisplaySort ( hwndList , order , HIWORD ( sort ) ) ;
}
for ( order = 0 ; order < count ; order + + ) SendMessageW ( hwndList , LVM_DELETECOLUMN , 0 , 0L ) ;
}
for ( index = 0 ; - 1 ! = columnOrder [ index ] & & MEDIAVIEW_COL_RATING ! = columnOrder [ index ] & & MEDIAVIEW_COL_CLOUD ! = columnOrder [ index ] ; index + + ) ;
if ( - 1 ! = columnOrder [ index ] )
{
INT w = ( INT ) SendMessageW ( hwndList , LVM_GETCOLUMNWIDTH , index , 0L ) ;
SendMessageW ( hwndList , LVM_SETCOLUMNWIDTH , index , ( LPARAM ) w ) ;
}
if ( pOrder ) free ( pOrder ) ;
}
SendMessageW ( hwndList , WM_SETREDRAW , TRUE , 0L ) ;
}
static void Window_OnQueryFileInfo ( HWND hwnd )
{
INT index ;
HWND hwndList = GetDlgItem ( hwnd , IDC_LIST2 ) ;
index = ( hwndList ) ? ( INT ) SendMessage ( hwndList , LVM_GETNEXTITEM , ( WPARAM ) - 1 , ( LPARAM ) LVNI_FOCUSED ) : - 1 ;
SendMessageW ( GetParent ( hwnd ) , WM_SHOWFILEINFO , ( WPARAM ) FALSE , ( LPARAM ) ( ( - 1 ! = index & & index < itemCache . Size ) ? itemCache . Items [ index ] . filename : L " " ) ) ;
}
void Window_OnDropFiles ( HWND hwndDlg , HDROP hdrop )
{
wchar_t temp [ 1024 ] = { 0 } ;
int y = DragQueryFileW ( hdrop , 0xffffffff , temp , 1024 ) ;
if ( y > 0 )
{
wchar_t * * paths = ( wchar_t * * ) calloc ( y , sizeof ( wchar_t * ) ) ;
int * guesses = ( int * ) calloc ( y , sizeof ( int ) ) ;
int * metas = ( int * ) calloc ( y , sizeof ( int ) ) ;
int * recs = ( int * ) calloc ( y , sizeof ( int ) ) ;
if ( paths & & guesses & & metas & & recs )
{
size_t count = 0 ;
for ( int x = 0 ; x < y ; x + + )
{
DragQueryFileW ( hdrop , x , temp , 1024 ) ;
int guess = - 1 , meta = - 1 , rec = 1 ;
// do this for normal media drops
PLCallBackW plCB ;
if ( AGAVE_API_PLAYLISTMANAGER & & PLAYLISTMANAGER_SUCCESS ! = AGAVE_API_PLAYLISTMANAGER - > Load ( temp , & plCB ) )
{
autoscan_add_directory ( temp , & guess , & meta , & rec , 0 ) ;
if ( guess = = - 1 ) guess = g_config - > ReadInt ( L " guessmode " , 0 ) ;
if ( meta = = - 1 ) meta = g_config - > ReadInt ( L " usemetadata " , 1 ) ;
paths [ count ] = _wcsdup ( temp ) ;
guesses [ count ] = guess ;
metas [ count ] = meta ;
recs [ count ] = rec ;
count + + ;
}
}
DragFinish ( hdrop ) ;
Scan_ScanFolders ( hwndDlg , count , paths , guesses , metas , recs ) ;
if ( IsWindow ( m_curview_hwnd ) ) SendMessage ( m_curview_hwnd , WM_APP + 1 , 0 , 0 ) ; //update current view
}
else
{
free ( paths ) ;
free ( guesses ) ;
free ( metas ) ;
free ( recs ) ;
}
}
else DragFinish ( hdrop ) ;
}
INT_PTR CALLBACK view_mediaDialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
BOOL a = dialogSkinner . Handle ( hwndDlg , uMsg , wParam , lParam ) ; if ( a ) return a ;
switch ( uMsg )
{
case WM_INITMENUPOPUP : Dialog_OnInitMenuPopup ( hwndDlg , ( HMENU ) wParam , LOWORD ( lParam ) , HIWORD ( lParam ) ) ; break ;
case WM_DISPLAYCHANGE : Dialog_OnDisplayChange ( hwndDlg ) ; break ;
case WM_INITDIALOG : return Dialog_OnInit ( hwndDlg , ( HWND ) wParam , lParam ) ;
case WM_MOUSEMOVE : Dialog_OnMouseMove ( hwndDlg , ( UINT ) wParam , MAKEPOINTS ( lParam ) ) ; break ;
case WM_LBUTTONUP : Dialog_OnLButtonUp ( hwndDlg , ( UINT ) wParam , MAKEPOINTS ( lParam ) ) ; break ;
case WM_DROPFILES : Window_OnDropFiles ( hwndDlg , ( HDROP ) wParam ) ;
case WM_COMMAND : Dialog_OnCommand ( hwndDlg , LOWORD ( wParam ) , HIWORD ( wParam ) , ( HWND ) lParam ) ; break ;
case WM_TIMER : Dialog_OnTimer ( hwndDlg , ( UINT_PTR ) wParam , ( TIMERPROC ) lParam ) ; break ;
case WM_DESTROY : Dialog_OnDestroy ( hwndDlg ) ; break ;
case WM_WINDOWPOSCHANGED : Dialog_OnWindowPosChanged ( hwndDlg , ( WINDOWPOS * ) lParam ) ; break ;
case WM_ERASEBKGND : return 1 ; //handled by WADlg_DrawChildWindowBorders in WM_PAINT
case WM_CONTEXTMENU :
Dialog_OnContextMenu ( hwndDlg , ( HWND ) wParam , GET_X_LPARAM ( lParam ) , GET_Y_LPARAM ( lParam ) ) ;
return 0 ;
case WM_NOTIFY :
{
LRESULT result ;
result = 0L ;
if ( Dialog_OnNotify ( hwndDlg , ( INT ) wParam , ( NMHDR * ) lParam , & result ) )
{
SetWindowLongPtrW ( hwndDlg , DWLP_MSGRESULT , ( LONG_PTR ) result ) ;
return TRUE ;
}
}
break ;
case IM_SYNCHEADERORDER : Dialog_OnSyncHeaderOrder ( hwndDlg , ( HWND ) lParam ) ; break ;
case WM_APP + 3 : // send by bgthread
if ( wParam = = 0x666 ) m_bgupdinfoviewerflag = 1 ;
else if ( wParam = = 0x69 )
{
bgQuery_Stop ( ) ;
resultlist . SetVirtualCount ( 0 ) ;
resultlist . SetVirtualCount ( itemCache . Size ) ; // TODO: we could set a limit here
ListView_RedrawItems ( resultlist . getwnd ( ) , 0 , itemCache . Size - 1 ) ;
UpdateWindow ( resultlist . getwnd ( ) ) ;
__int64 total_len_bytes = bg_total_len_bytes ;
int total_length_s = ( int ) bg_total_len_s & 0x7FFFFFFF ;
wchar_t buffer [ 4 * 64 ] = { 0 } ;
wchar_t * pb [ 4 ] = { 0 } ;
for ( int i = 0 ; i < 4 ; i + + ) pb [ i ] = buffer + i * 64 ;
int index ( 0 ) ;
StringCchPrintfW ( pb [ index ] , 64 , L " %d %s " , itemCache . Size ,
WASABI_API_LNGSTRINGW ( itemCache . Size = = 1 ? IDS_ITEM : IDS_ITEMS ) ) ;
index + + ;
if ( itemCache . Size )
{
int uncert = 0 ; //bg_total_len_s>>31;
if ( total_length_s < 60 * 60 ) StringCchPrintfW ( pb [ index ] , 64 , L " [%s%u:%02u] " , uncert ? L " ~ " : L " " , total_length_s / 60 , total_length_s % 60 ) ;
else if ( total_length_s < 60 * 60 * 24 ) StringCchPrintfW ( pb [ index ] , 64 , L " [%s%u:%02u:%02u] " , uncert ? L " ~ " : L " " , total_length_s / 60 / 60 , ( total_length_s / 60 ) % 60 , total_length_s % 60 ) ;
else
{
wchar_t days [ 16 ] = { 0 } ;
int total_days = total_length_s / ( 60 * 60 * 24 ) ;
total_length_s - = total_days * 60 * 60 * 24 ;
StringCchPrintfW ( pb [ index ] , 64 ,
WASABI_API_LNGSTRINGW ( IDS_LENGTH_DURATION_STRING ) ,
uncert ? L " ~ " : L " " , total_days ,
WASABI_API_LNGSTRINGW_BUF ( total_days = = 1 ? IDS_DAY : IDS_DAYS , days , 16 ) ,
total_length_s / 60 / 60 , ( total_length_s / 60 ) % 60 , total_length_s % 60 ) ;
}
index + + ;
}
if ( total_len_bytes )
{
StringCchCopyW ( pb [ index ] , 64 , L " [ " ) ;
WASABI_API_LNG - > FormattedSizeString ( pb [ index ] + 1 , 64 , total_len_bytes ) ;
StringCchCatW ( pb [ index ] , 64 , L " ] " ) ;
index + + ;
}
unsigned int ms = ( UINT ) ( querytime . QuadPart * 1000 / freq . QuadPart ) ;
StringCchPrintfW ( pb [ index ] , 64 , WASABI_API_LNGSTRINGW ( IDS_IN_X_SEC ) , ms / 1000.0f ) ;
index + + ;
SetStatusText ( GetDlgItem ( hwndDlg , IDC_MEDIASTATUS ) , ( LPCWSTR * ) pb , index ) ;
if ( m_bgupdinfoviewerflag )
{
m_bgupdinfoviewerflag = 0 ;
if ( itemCache . Size > 0 )
{
if ( predixisExist )
{
if ( resultlist . GetSelectedCount ( ) = = 1 & & isMixable ( itemCache . Items [ 0 ] ) )
{
SetDlgItemText ( hwndDlg , IDC_MIXABLE , L " " ) ;
isMixablePresent = true ;
}
else
{
SetDlgItemText ( hwndDlg , IDC_MIXABLE , L " " ) ;
}
}
SendMessageW ( GetParent ( hwndDlg ) , WM_SHOWFILEINFO , ( WPARAM ) FALSE , ( LPARAM ) itemCache . Items [ 0 ] . filename ) ;
}
}
}
break ;
case WM_APP + 1 :
bgQuery ( ( resultsniff_funcW ) wParam , ( int ) lParam ) ;
break ;
case WM_APP + 5 :
{
// TODO
int done = ( HIWORD ( wParam ) = = 1 ) ;
int code = ( LOWORD ( wParam ) ) ;
for ( int i = 0 ; i < itemCache . Size ; i + + )
{
// 0 = no change
// 1 = add cloud
// 2 = add local
// 4 = removed
if ( ! lstrcmpiW ( itemCache . Items [ i ] . filename , ( wchar_t * ) lParam ) )
{
if ( ! done )
{
setCloudValue ( & itemCache . Items [ i ] , L " 5 " ) ;
}
else
{
if ( code = = NErr_Success )
{
// uploaded ok
// TODO if going to another device, will need to alter this
setCloudValue ( & itemCache . Items [ i ] , L " 0 " ) ;
}
else
{
// re-query state
setCloudValue ( & itemCache . Items [ i ] , L " 0 " ) ;
}
}
InvalidateRect ( resultlist . getwnd ( ) , NULL , TRUE ) ;
break ;
}
}
break ;
}
case WM_APP + 6 : // handles the ml_cloud 'first pull' announces so we
{ // can then show the cloud column & update the cache
initColumnsHeader ( resultlist . getwnd ( ) ) ;
bgQuery ( ) ; //(resultsniff_funcW)wParam, (int)lParam);
break ;
}
case WM_APP + 104 :
{
Dialog_UpdateButtonText ( hwndDlg , wParam ) ;
LayoutWindows ( hwndDlg , TRUE ) ;
return 0 ;
}
case WM_PAINT :
{
int tab [ ] = { IDC_LIST2 | DCW_SUNKENBORDER , IDC_QUICKSEARCH | DCW_SUNKENBORDER } ;
dialogSkinner . Draw ( hwndDlg , tab , 1 + ! ! IsWindowVisible ( GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) ) ) ;
}
return 0 ;
case WM_ML_CHILDIPC :
switch ( lParam )
{
case ML_CHILDIPC_GO_TO_SEARCHBAR :
SendDlgItemMessage ( hwndDlg , IDC_QUICKSEARCH , EM_SETSEL , 0 , - 1 ) ;
SetFocus ( GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) ) ;
break ;
case ML_CHILDIPC_REFRESH_SEARCH :
PostMessage ( hwndDlg , WM_COMMAND , MAKEWPARAM ( IDC_QUICKSEARCH , EN_CHANGE ) , ( LPARAM ) GetDlgItem ( hwndDlg , IDC_QUICKSEARCH ) ) ;
break ;
}
break ;
case WM_USER + 0x201 :
offsetX = ( short ) LOWORD ( wParam ) ;
offsetY = ( short ) HIWORD ( wParam ) ;
g_rgnUpdate = ( HRGN ) lParam ;
return TRUE ;
case WM_QUERYFILEINFO : Window_OnQueryFileInfo ( hwndDlg ) ; break ;
}
return FALSE ;
}
//////////////////////////////// Customize columns dialog
static signed char edit_columnOrder [ MAX_COLUMN_ORDER ] ;
static INT_PTR CALLBACK custColumns_dialogProc ( HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
static HWND m_curlistbox_hwnd , m_availlistbox_hwnd ;
switch ( uMsg )
{
case WM_INITDIALOG :
memcpy ( edit_columnOrder , columnOrder , sizeof ( edit_columnOrder ) ) ;
m_curlistbox_hwnd = GetDlgItem ( hwndDlg , IDC_LIST1 ) ;
m_availlistbox_hwnd = GetDlgItem ( hwndDlg , IDC_LIST2 ) ;
if ( NULL ! = WASABI_API_APP )
{
if ( NULL ! = m_curlistbox_hwnd )
WASABI_API_APP - > DirectMouseWheel_EnableConvertToMouseWheel ( m_curlistbox_hwnd , TRUE ) ;
if ( NULL ! = m_availlistbox_hwnd )
WASABI_API_APP - > DirectMouseWheel_EnableConvertToMouseWheel ( m_availlistbox_hwnd , TRUE ) ;
}
case WM_USER + 32 :
{
for ( int i = 0 ; edit_columnOrder [ i ] ! = - 1 ; i + + )
{
int c = edit_columnOrder [ i ] ;
headerColumn * cl = & columnList [ c ] ;
int column_id = cl - > column_id ;
if ( column_id = = IDS_CLOUD | | column_id = = IDS_CLOUD_HIDDEN )
{
// if no cloud support at all then we hide everything
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 ) continue ;
column_id = ( ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 | |
! SendMessageW ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_ACTIVE ) ) ? IDS_CLOUD_HIDDEN : IDS_CLOUD ) ;
}
int r = SendMessageW ( m_curlistbox_hwnd , LB_ADDSTRING , 0 , ( LPARAM ) WASABI_API_LNGSTRINGW ( column_id ) ) ;
SendMessageW ( m_curlistbox_hwnd , LB_SETITEMDATA , r , c ) ;
}
for ( int i = 0 ; i < sizeof ( columnList ) / sizeof ( headerColumn ) ; i + + )
{
headerColumn * cl = & columnList [ i ] ;
int j ;
for ( j = 0 ; edit_columnOrder [ j ] ! = - 1 & & edit_columnOrder [ j ] ! = i ; j + + ) ;
if ( edit_columnOrder [ j ] = = - 1 )
{
int column_id = cl - > column_id ;
if ( column_id = = IDS_CLOUD | | column_id = = IDS_CLOUD_HIDDEN )
{
// if no cloud support at all then we hide everything
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 ) continue ;
column_id = ( ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 | |
! SendMessage ( plugin . hwndWinampParent , WM_WA_IPC , 0 , IPC_GET_CLOUD_ACTIVE ) ) ? IDS_CLOUD_HIDDEN : IDS_CLOUD ) ;
}
int r = SendMessageW ( m_availlistbox_hwnd , LB_ADDSTRING , 0 , ( LPARAM ) WASABI_API_LNGSTRINGW ( column_id ) ) ;
SendMessageW ( m_availlistbox_hwnd , LB_SETITEMDATA , r , i ) ;
}
}
}
break ;
case WM_COMMAND :
switch ( LOWORD ( wParam ) )
{
case IDC_DEFS :
if ( ! cloud_hinst | | cloud_hinst = = ( HINSTANCE ) 1 )
memcpy ( edit_columnOrder , defColumnOrder , sizeof ( defColumnOrder ) ) ;
else
memcpy ( edit_columnOrder , defColumnOrderCloud , sizeof ( defColumnOrderCloud ) ) ;
SendMessage ( m_curlistbox_hwnd , LB_RESETCONTENT , 0 , 0 ) ;
SendMessage ( m_availlistbox_hwnd , LB_RESETCONTENT , 0 , 0 ) ;
SendMessage ( hwndDlg , WM_USER + 32 , 0 , 0 ) ;
break ;
case IDC_LIST2 :
if ( HIWORD ( wParam ) ! = LBN_DBLCLK )
{
if ( HIWORD ( wParam ) = = LBN_SELCHANGE )
{
int r = SendMessage ( m_availlistbox_hwnd , LB_GETSELCOUNT , 0 , 0 ) > 0 ;
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON2 ) , r ) ;
}
return 0 ;
}
case IDC_BUTTON2 :
//add column
{
for ( int i = 0 ; i < SendMessage ( m_availlistbox_hwnd , LB_GETCOUNT , 0 , 0 ) ; i + + )
{
if ( SendMessage ( m_availlistbox_hwnd , LB_GETSEL , i , 0 ) )
{
int c = SendMessage ( m_availlistbox_hwnd , LB_GETITEMDATA , i , 0 ) ;
int j ;
for ( j = 0 ; edit_columnOrder [ j ] ! = - 1 ; j + + ) ;
edit_columnOrder [ j ] = ( BYTE ) c ;
edit_columnOrder [ j + 1 ] = - 1 ;
SendMessage ( m_availlistbox_hwnd , LB_DELETESTRING , i , 0 ) ;
i - - ;
int r = SendMessageW ( m_curlistbox_hwnd , LB_ADDSTRING , 0 , ( LPARAM ) WASABI_API_LNGSTRINGW ( columnList [ c ] . column_id ) ) ;
SendMessageW ( m_curlistbox_hwnd , LB_SETITEMDATA , r , c ) ;
}
}
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON2 ) , 0 ) ;
}
break ;
case IDC_LIST1 :
if ( HIWORD ( wParam ) ! = LBN_DBLCLK )
{
if ( HIWORD ( wParam ) = = LBN_SELCHANGE )
{
int r = SendMessage ( m_curlistbox_hwnd , LB_GETSELCOUNT , 0 , 0 ) > 0 ;
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON3 ) , r ) ;
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON4 ) , r ) ;
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON5 ) , r ) ;
}
return 0 ;
}
case IDC_BUTTON3 :
//remove column
{
for ( int i = 0 ; i < SendMessage ( m_curlistbox_hwnd , LB_GETCOUNT , 0 , 0 ) ; i + + )
{
if ( SendMessage ( m_curlistbox_hwnd , LB_GETSEL , i , 0 ) )
{
int c = edit_columnOrder [ i ] ;
for ( int j = i ; edit_columnOrder [ j ] ! = - 1 ; j + + )
{
edit_columnOrder [ j ] = edit_columnOrder [ j + 1 ] ;
}
SendMessage ( m_curlistbox_hwnd , LB_DELETESTRING , i , 0 ) ;
i - - ;
int r = SendMessageW ( m_availlistbox_hwnd , LB_ADDSTRING , 0 , ( LPARAM ) WASABI_API_LNGSTRINGW ( columnList [ c ] . column_id ) ) ;
SendMessageW ( m_availlistbox_hwnd , LB_SETITEMDATA , r , c ) ;
}
}
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON3 ) , 0 ) ;
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON4 ) , 0 ) ;
EnableWindow ( GetDlgItem ( hwndDlg , IDC_BUTTON5 ) , 0 ) ;
}
break ;
case IDC_BUTTON4 :
//move column up
{
for ( int i = 0 ; i < ( INT ) SendMessage ( m_curlistbox_hwnd , LB_GETCOUNT , 0 , 0 ) ; i + + )
{
if ( i ! = 0 & & ( INT ) SendMessage ( m_curlistbox_hwnd , LB_GETSEL , i , 0 ) )
{
BYTE c = edit_columnOrder [ i - 1 ] ;
edit_columnOrder [ i - 1 ] = edit_columnOrder [ i ] ;
edit_columnOrder [ i ] = c ;
SendMessage ( m_curlistbox_hwnd , LB_DELETESTRING , i - 1 , 0 ) ;
int r = ( INT ) SendMessageW ( m_curlistbox_hwnd , LB_INSERTSTRING , i , ( LPARAM ) WASABI_API_LNGSTRINGW ( columnList [ c ] . column_id ) ) ;
SendMessage ( m_curlistbox_hwnd , LB_SETITEMDATA , r , c ) ;
}
}
}
break ;
case IDC_BUTTON5 :
//move column down
{
int l = SendMessage ( m_curlistbox_hwnd , LB_GETCOUNT , 0 , 0 ) ;
for ( int i = l - 2 ; i > = 0 ; i - - )
{
if ( SendMessage ( m_curlistbox_hwnd , LB_GETSEL , i , 0 ) )
{
BYTE c = edit_columnOrder [ i + 1 ] ;
edit_columnOrder [ i + 1 ] = edit_columnOrder [ i ] ;
edit_columnOrder [ i ] = c ;
SendMessage ( m_curlistbox_hwnd , LB_DELETESTRING , i + 1 , 0 ) ;
int r = ( INT ) SendMessageW ( m_curlistbox_hwnd , LB_INSERTSTRING , i , ( LPARAM ) WASABI_API_LNGSTRINGW ( columnList [ c ] . column_id ) ) ;
SendMessage ( m_curlistbox_hwnd , LB_SETITEMDATA , r , c ) ;
}
}
}
break ;
case IDOK :
{
HWND hwndList = resultlist . getwnd ( ) ;
memcpy ( columnOrder , edit_columnOrder , sizeof ( edit_columnOrder ) ) ;
if ( hwndList )
{
initColumnsHeader ( hwndList ) ;
InvalidateRect ( hwndList , NULL , TRUE ) ;
UpdateWindow ( hwndList ) ;
}
}
case IDCANCEL :
EndDialog ( hwndDlg , 0 ) ;
break ;
}
break ;
case WM_DESTROY :
if ( NULL ! = WASABI_API_APP )
{
if ( NULL ! = m_curlistbox_hwnd )
WASABI_API_APP - > DirectMouseWheel_EnableConvertToMouseWheel ( m_curlistbox_hwnd , FALSE ) ;
if ( NULL ! = m_availlistbox_hwnd )
WASABI_API_APP - > DirectMouseWheel_EnableConvertToMouseWheel ( m_availlistbox_hwnd , FALSE ) ;
WASABI_API_APP - > app_removeAccelerators ( hwndDlg ) ;
}
break ;
}
return FALSE ;
}
void customizeColumnsDialog ( HWND hwndParent )
{
WASABI_API_DIALOGBOXW ( IDD_CUSTCOLUMNS , hwndParent , custColumns_dialogProc ) ;
EatKeyboard ( ) ;
}
bool isMixable ( itemRecordW & song )
{
if ( ! song . filename ) return false ;
AutoChar charFn ( song . filename ) ;
pluginMessage p = { ML_MSG_PDXS_STATUS , ( INT_PTR ) ( char * ) charFn , 0 , 0 } ;
char * text = ( char * ) SendMessage ( plugin . hwndLibraryParent , WM_ML_IPC , ( WPARAM ) & p , ML_IPC_SEND_PLUGIN_MESSAGE ) ;
// Analyzed/Identified = mixable
return text & & ( text [ 0 ] = = ' A ' | | text [ 0 ] = = ' I ' ) ;
}
void AccessingGracenoteHack ( int p )
{
if ( p = = 0 )
{
GetDlgItemTextW ( m_hwnd , IDC_MEDIASTATUS , oldText , 4096 ) ;
SetDlgItemTextW ( m_hwnd , IDC_MEDIASTATUS , L " Accessing Gracenote Database " ) ;
}
else
{
SetDlgItemTextW ( m_hwnd , IDC_MEDIASTATUS , oldText ) ;
}
}