MusicMod: Preparation for adding music modification

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1735 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson
2009-01-02 23:54:39 +00:00
parent 2e0269ae39
commit 55db229929
87 changed files with 20765 additions and 0 deletions
@@ -0,0 +1,363 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "AddDirectory.h"
#include "Playlist.h"
#include "Main.h"
#include "InputPlugin.h"
#include <stdio.h>
#include <shlobj.h>
#include <vector>
#include <algorithm>
using namespace std;
HWND WindowBrowse = NULL;
void SearchFolder( TCHAR * szPath );
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
LPITEMIDLIST GetCurrentFolder()
{
/*
How To Convert a File Path to an ITEMIDLIST
http://support.microsoft.com/default.aspx?scid=kb;en-us;132750
*/
LPITEMIDLIST pidl;
LPSHELLFOLDER pDesktopFolder;
TCHAR szPath[ MAX_PATH ];
#ifndef PA_UNICODE
OLECHAR olePath[ MAX_PATH ];
#endif
ULONG chEaten;
ULONG dwAttributes;
HRESULT hr;
//
// Get the path we need to convert.
//
GetCurrentDirectory( MAX_PATH, szPath );
//
// Get a pointer to the Desktop's IShellFolder interface.
//
if( SUCCEEDED( SHGetDesktopFolder( &pDesktopFolder ) ) )
{
//
// IShellFolder::ParseDisplayName requires the file name be in
// Unicode.
//
#ifndef PA_UNICODE
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, MAX_PATH );
#endif
//
// Convert the path to an ITEMIDLIST.
//
// hr = pDesktopFolder->lpVtbl->ParseDisplayName(
hr = pDesktopFolder->ParseDisplayName(
( HWND__ * )pDesktopFolder,
NULL,
#ifndef PA_UNICODE
olePath,
#else
szPath,
#endif
&chEaten,
&pidl,
&dwAttributes
);
if( FAILED( hr ) )
{
// Handle error.
return NULL;
}
//
// pidl now contains a pointer to an ITEMIDLIST for .\readme.txt.
// This ITEMIDLIST needs to be freed using the IMalloc allocator
// returned from SHGetMalloc().
//
// release the desktop folder object
// pDesktopFolder->lpVtbl->Release();
pDesktopFolder->Release();
return pidl;
}
else
{
return NULL;
}
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lp )
{
TCHAR szClassName[ 8 ] = TEXT( "\0" );
HWND * hFirstFoundStatic = ( ( HWND * )lp );
if( GetClassName( hwnd, szClassName, 7 ) )
{
if( !_tcscmp( szClassName, TEXT( "Static" ) ) )
{
if( *hFirstFoundStatic )
{
// Both found
RECT r1;
GetWindowRect( *hFirstFoundStatic, &r1 );
RECT r2;
GetWindowRect( hwnd, &r2 );
// First must be taller one
if( r1.bottom - r1.top < r2.bottom - r2.top )
{
// Swap
RECT r = r1;
HWND h = *hFirstFoundStatic;
r1 = r2;
*hFirstFoundStatic = hwnd;
r2 = r;
hwnd = h;
}
POINT xy2 = { r2.left, r2.top };
ScreenToClient( WindowBrowse, &xy2 );
SetWindowPos(
*hFirstFoundStatic,
NULL,
0,
0,
r2.right - r2.left,
r2.bottom - r2.top,
SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER
);
SetWindowPos(
hwnd,
NULL,
xy2.x,
xy2.y + ( r2.bottom - r2.top ) - ( r1.bottom - r1.top ),
r1.right - r1.left,
r1.bottom - r1.top,
SWP_NOOWNERZORDER | SWP_NOZORDER
);
return FALSE; // Stop
}
else
{
// First found
*hFirstFoundStatic = hwnd;
}
}
}
return TRUE; // Continue
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
int CALLBACK BrowseCallbackProc( HWND hwnd, UINT message, LPARAM lp, LPARAM wp )
{
switch( message )
{
case BFFM_INITIALIZED:
{
WindowBrowse = hwnd;
// Init with curdir
SendMessage( hwnd, BFFM_SETSELECTION, FALSE, ( LPARAM )GetCurrentFolder() );
// Swap static dimensions
HWND hFirstFoundStatic = NULL;
EnumChildWindows( hwnd, EnumChildProc, ( LPARAM )&hFirstFoundStatic );
break;
}
case BFFM_SELCHANGED:
{
TCHAR szPath[ MAX_PATH ] = TEXT( "\0" );
SHGetPathFromIDList( ( LPITEMIDLIST )lp, szPath );
SendMessage( hwnd, BFFM_SETSTATUSTEXT, 0, ( LPARAM )szPath );
break;
}
case BFFM_VALIDATEFAILED:
return TRUE;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// Shows a Browse-For-Folder dialog and recursively adds supported files
/// to the playlist. Files are sorted by full filaname before being added.
////////////////////////////////////////////////////////////////////////////////
void AddDirectory()
{
TCHAR szPath[ MAX_PATH ];
BROWSEINFO bi = { 0 };
bi.hwndOwner = WindowMain;
bi.pidlRoot = NULL; // Desktop folder
bi.lpszTitle = TEXT( "Please select a directory:" );
bi.ulFlags = BIF_VALIDATE | BIF_STATUSTEXT;
bi.lpfn = BrowseCallbackProc;
LPITEMIDLIST pidl = SHBrowseForFolder( &bi );
if( !pidl ) return;
// Get path
SHGetPathFromIDList( pidl, szPath );
// Search
SearchFolder( szPath );
// Stay here
SetCurrentDirectory( szPath );
// Free memory used
IMalloc * imalloc = 0;
if( SUCCEEDED( SHGetMalloc( &imalloc ) ) )
{
imalloc->Free( pidl );
imalloc->Release();
}
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
void SearchFolder( TCHAR * szPath )
{
// Remove trailing backslash
int iPathLen = ( int )_tcslen( szPath );
if( iPathLen < 1 ) return;
if( szPath[ iPathLen - 1 ] == TEXT( '\\' ) )
{
iPathLen--;
}
// Init working buffer
TCHAR szFullpath[ MAX_PATH ];
memcpy( szFullpath, szPath, iPathLen * sizeof( TCHAR ) );
szFullpath[ iPathLen ] = TEXT( '\\' );
szFullpath[ iPathLen + 1 ] = TEXT( '\0' );
// Make pattern
_tcscpy( szFullpath + iPathLen + 1, TEXT( "*" ) );
// Find
vector <TCHAR *> Files;
vector <TCHAR *> Dirs;
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFile( szFullpath, &FindFileData );
if( hFind == INVALID_HANDLE_VALUE ) return;
do
{
// Skip "." and ".."
if( !_tcscmp( FindFileData.cFileName, TEXT( "." ) ) ||
!_tcscmp( FindFileData.cFileName, TEXT( ".." ) ) ) continue;
// Make full path
_tcscpy( szFullpath + iPathLen + 1, FindFileData.cFileName );
// Is directory?
TCHAR * szPartname = new TCHAR[ MAX_PATH ];
_tcscpy( szPartname, FindFileData.cFileName );
if( SetCurrentDirectory( szFullpath ) )
{
// New dir
Dirs.push_back( szPartname );
continue;
}
// Search "."
const int iFilenameLen = ( int )_tcslen( FindFileData.cFileName );
TCHAR * szExt = FindFileData.cFileName + iFilenameLen - 1;
while( ( szExt > FindFileData.cFileName ) && ( *szExt != TEXT( '.' ) ) ) szExt--;
if( *szExt != TEXT( '.' ) ) continue;
szExt++;
// Check extension
map <TCHAR *, InputPlugin *, TextCompare>::iterator iter = ext_map.find( szExt );
if( iter == ext_map.end() ) continue;
// New file
Files.push_back( szPartname );
}
while( FindNextFile( hFind, &FindFileData ) );
FindClose( hFind );
vector <TCHAR *>::iterator iter;
// Sort and recurse directories
sort( Dirs.begin(), Dirs.end(), TextCompare() );
iter = Dirs.begin();
while( iter != Dirs.end() )
{
TCHAR * szWalk = *iter;
_tcscpy( szFullpath + iPathLen + 1, szWalk );
SearchFolder( szFullpath );
iter++;
}
// Sort and add files
sort( Files.begin(), Files.end(), TextCompare() );
iter = Files.begin();
while( iter != Files.end() )
{
TCHAR * szWalk = *iter;
TCHAR * szKeep = new TCHAR[ MAX_PATH ];
memcpy( szKeep, szFullpath, ( iPathLen + 1 ) * sizeof( TCHAR ) );
_tcscpy( szKeep + iPathLen + 1, szWalk );
playlist->PushBack( szKeep );
iter++;
}
}
@@ -0,0 +1,26 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_ADD_DIRECTORY_H
#define PA_ADD_DIRECTORY_H
#include "Global.h"
void AddDirectory();
#endif // PA_ADD_DIRECTORY_H
+181
View File
@@ -0,0 +1,181 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "AddFiles.h"
#include "InputPlugin.h"
#include "Main.h"
#include "Playlist.h"
#include <commdlg.h>
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
void AddFiles()
{
int total = 0;
int iFilterLen = 0;
InputPlugin * input;
vector <InputPlugin *>::iterator iter;
// Get len
// if( input_plugins.empty() ) return;
iter = input_plugins.begin();
while( iter != input_plugins.end() )
{
input = *iter;
if( !input ) iter++;
iFilterLen += input->iFiltersLen;
iter++;
}
// if( !iFilterLen ) return;
iFilterLen += 40 + 29 + ( int )ext_map.size() * ( 2 + 4 + 1 ) + 7;
TCHAR * szFilters = new TCHAR[ iFilterLen ];
TCHAR * walk = szFilters;
// ..................1.........1....\....\.1.........1........\.1...
memcpy( walk, TEXT( "All files (*.*)\0*.*\0All supported types\0" ), 40 * sizeof( TCHAR ) );
walk += 40;
// Add all extensions as ";*.ext"
// if( ext_map.empty() ) return;
map <TCHAR *, InputPlugin *, TextCompare>::iterator iter_ext = ext_map.begin();
bool bFirst = true;
while( iter_ext != ext_map.end() )
{
if( !bFirst )
{
memcpy( walk, TEXT( ";*." ), 3 * sizeof( TCHAR ) );
walk += 3;
}
else
{
memcpy( walk, TEXT( "*." ), 2 * sizeof( TCHAR ) );
walk += 2;
bFirst = false;
}
TCHAR * szExt = iter_ext->first;
int uLen = ( int )_tcslen( szExt );
memcpy( walk, szExt, uLen * sizeof( TCHAR ) );
walk += uLen;
iter_ext++;
}
// *walk = TEXT( '\0' );
// walk++;
// ..................1..........1...
memcpy( walk, TEXT( ";*.m3u\0" ), 7 * sizeof( TCHAR ) );
walk += 7;
// ..................1.........1.........1...........1...
memcpy( walk, TEXT( "Playlist files (*.M3U)\0*.m3u\0" ), 29 * sizeof( TCHAR ) );
walk += 29;
// Copy filters
iter = input_plugins.begin();
while( iter != input_plugins.end() )
{
input = *iter;
if( !input ) iter++;
memcpy( walk, input->szFilters, input->iFiltersLen * sizeof( TCHAR ) );
walk += input->iFiltersLen;
iter++;
}
*walk = TEXT( '\0' );
walk++;
////////////////////////////////////////////////////////////////////////////////
static TCHAR szFilenames[ 20001 ];
*szFilenames = TEXT( '\0' ); // Each time!
OPENFILENAME ofn;
memset( &ofn, 0, sizeof( OPENFILENAME ) );
ofn.lStructSize = sizeof( OPENFILENAME );
ofn.hwndOwner = WindowMain;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = szFilters; // "MPEG Layer 3\0*.mp3\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 2;
ofn.lpstrFile = szFilenames;
ofn.nMaxFile = 20000;
ofn.Flags = OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.nMaxFileTitle = 0, // NULL;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = TEXT( "Add files" );
if( !GetOpenFileName( &ofn ) ) return;
int uDirLen = ( int )_tcslen( szFilenames );
TCHAR * szDir = szFilenames;
TCHAR * szFileWalk = szDir + uDirLen + 1;
if( *szFileWalk == TEXT( '\0' ) ) // "\0\0" or just "\0"?
{
// \0\0 -> Single file
if( !_tcsncmp( szDir + uDirLen - 3, TEXT( "m3u" ), 3 ) )
{
// Playlist file
Playlist::AppendPlaylistFile( szDir );
}
else
{
// Music file
TCHAR * szKeep = new TCHAR[ uDirLen + 1 ];
memcpy( szKeep, szDir, uDirLen * sizeof( TCHAR ) );
szKeep[ uDirLen ] = TEXT( '\0' );
playlist->PushBack( szKeep );
}
}
else
{
// \0 -> Several files
int iFileLen;
while( *szFileWalk != TEXT( '\0' ) )
{
iFileLen = ( int )_tcslen( szFileWalk );
if( !iFileLen ) return;
TCHAR * szKeep = new TCHAR[ uDirLen + 1 + iFileLen + 1 ];
memcpy( szKeep, szDir, uDirLen * sizeof( TCHAR ) );
szKeep[ uDirLen ] = TEXT( '\\' );
memcpy( szKeep + uDirLen + 1, szFileWalk, iFileLen * sizeof( TCHAR ) );
szKeep[ uDirLen + 1 + iFileLen ] = TEXT( '\0' );
if( !_tcsncmp( szKeep + uDirLen + 1 + iFileLen - 3, TEXT( "m3u" ), 3 ) )
{
// Playlist file
Playlist::AppendPlaylistFile( szKeep );
delete [] szKeep;
}
else
{
// Music file
playlist->PushBack( szKeep );
}
szFileWalk += iFileLen + 1;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_ADD_FILES_H
#define PA_ADD_FILES_H
#include "Global.h"
void AddFiles();
#endif // PA_ADD_FILES_H
File diff suppressed because it is too large Load Diff
+236
View File
@@ -0,0 +1,236 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_CONFIG_H
#define PA_CONFIG_H
#include "Global.h"
#include "OutputPlugin.h"
namespace Conf
{
void Init( HINSTANCE hInstance );
void Write();
};
enum ConfMode
{
CONF_MODE_INTERNAL, // Will not be shown to the user
CONF_MODE_PUBLIC
};
class ConfVar;
typedef void ( * ConfCallback )( ConfVar * var );
struct BandInfo
{
int m_iIndex;
int m_iWidth;
bool m_bBreak;
bool m_bVisible;
};
////////////////////////////////////////////////////////////////////////////////
/// Config container
////////////////////////////////////////////////////////////////////////////////
class ConfVar
{
public:
ConfVar( TCHAR * szKey, ConfMode mode );
ConfVar( const TCHAR * szKey, ConfMode mode );
~ConfVar();
protected:
TCHAR * m_szKey; ///< Unique identifier
ConfMode m_Mode; ///< Mode/visibility
bool m_bRead; ///< Initilization flag
virtual void Read() = 0;
virtual void Write() = 0;
// virtual void Backup() = 0; ///< Creates a backup and deletes old backup if it exists
// virtual void Restore() = 0; ///< Restores settings from backup and destroys the backup
private:
bool m_bCopyKey; ///< Keyname is copy (has to be freed on destruction)
friend void Conf::Init( HINSTANCE hInstance );
friend void Conf::Write();
};
////////////////////////////////////////////////////////////////////////////////
/// Boolean config container
////////////////////////////////////////////////////////////////////////////////
class ConfBool : public ConfVar
{
public:
ConfBool( bool * pbData, TCHAR * szKey, ConfMode mode, bool bDefault );
ConfBool( bool * pbData, const TCHAR * szKey, ConfMode mode, bool bDefault );
private:
bool * m_pbData; ///< Target
bool m_bDefault; ///< Default value
void Read();
void Write();
friend OutputPlugin::OutputPlugin( TCHAR * szDllpath, bool bKeepLoaded );
};
////////////////////////////////////////////////////////////////////////////////
/// Integer config container
////////////////////////////////////////////////////////////////////////////////
class ConfInt : public ConfVar
{
public:
ConfInt( int * piData, TCHAR * szKey, ConfMode mode, int iDefault );
ConfInt( int * piData, const TCHAR * szKey, ConfMode mode, int iDefault );
protected:
int * m_piData;
int m_iDefault;
void Read();
void Write();
};
////////////////////////////////////////////////////////////////////////////////
/// Integer config container with restricted range
////////////////////////////////////////////////////////////////////////////////
class ConfIntMinMax : public ConfInt
{
public:
ConfIntMinMax( int * piData, TCHAR * szKey, ConfMode mode, int iDefault, int iMin, int iMax );
ConfIntMinMax( int * piData, const TCHAR * szKey, ConfMode mode, int iDefault, int iMin, int iMax );
// bool IsValid() { return ( ( *m_piData >= m_iMin ) && ( *m_piData <= m_iMax ) ); }
inline bool IsMin() { return ( *m_piData == m_iMin ); }
inline bool IsMax() { return ( *m_piData == m_iMax ); }
inline void MakeValidDefault() { if( ( *m_piData < m_iMin ) || ( *m_piData > m_iMax ) ) *m_piData = m_iDefault; }
inline void MakeValidPull() { if( *m_piData < m_iMin ) *m_piData = m_iMin; else if( *m_piData > m_iMax ) *m_piData = m_iMax; }
private:
int m_iMin;
int m_iMax;
void Read() { ConfInt::Read(); MakeValidPull(); }
};
////////////////////////////////////////////////////////////////////////////////
/// Window placement config container
///
/// The callback funtion is called on write()
/// so the data written is up to date.
////////////////////////////////////////////////////////////////////////////////
class ConfWinPlaceCallback : public ConfVar
{
public:
ConfWinPlaceCallback( WINDOWPLACEMENT * pwpData, TCHAR * szKey, RECT * prDefault, ConfCallback fpCallback );
ConfWinPlaceCallback( WINDOWPLACEMENT * pwpData, const TCHAR * szKey, RECT * prDefault, ConfCallback fpCallback );
inline void TriggerCallback() { if( m_fpCallback ) m_fpCallback( this ); }
inline void RemoveCallback() { m_fpCallback = NULL; }
private:
WINDOWPLACEMENT * m_pwpData;
RECT * m_prDefault;
ConfCallback m_fpCallback;
void Read();
void Write();
};
////////////////////////////////////////////////////////////////////////////////
/// Rebar band info config container
///
/// The callback funtion is called on write()
/// so the data written is up to date.
////////////////////////////////////////////////////////////////////////////////
class ConfBandInfoCallback : public ConfVar
{
public:
ConfBandInfoCallback( BandInfo * pbiData, TCHAR * szKey, BandInfo * pbiDefault, ConfCallback fpCallback );
ConfBandInfoCallback( BandInfo * pbiData, const TCHAR * szKey, BandInfo * pbiDefault, ConfCallback fpCallback );
inline void TriggerCallback() { if( m_fpCallback ) m_fpCallback( this ); }
inline void RemoveCallback() { m_fpCallback = NULL; }
bool Apply( HWND hRebar, int iBandId );
private:
BandInfo * m_pbiData;
BandInfo * m_pbiDefault;
ConfCallback m_fpCallback;
void Read();
void Write();
};
////////////////////////////////////////////////////////////////////////////////
/// String config container
////////////////////////////////////////////////////////////////////////////////
class ConfString : public ConfVar
{
public:
ConfString( TCHAR * szData, TCHAR * szKey, ConfMode mode, TCHAR * szDefault, int iMaxLen );
ConfString( TCHAR * szData, const TCHAR * szKey, ConfMode mode, TCHAR * szDefault, int iMaxLen );
protected:
TCHAR * m_szData;
int m_iMaxLen;
TCHAR * m_szDefault;
void Read();
void Write();
};
////////////////////////////////////////////////////////////////////////////////
/// Current directory config container
////////////////////////////////////////////////////////////////////////////////
class ConfCurDir : public ConfString
{
public:
ConfCurDir( TCHAR * szData, TCHAR * szKey );
ConfCurDir( TCHAR * szData, const TCHAR * szKey );
private:
void Read();
void Write();
};
#endif // PA_CONFIG_H
+228
View File
@@ -0,0 +1,228 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "Console.h"
#include "Font.h"
#include "Main.h"
#include "Config.h"
#include <time.h>
HWND WindowConsole = NULL; // extern
int iNext = 0;
const int iMaxEntries = 10000;
WNDPROC WndprocConsoleBackup = NULL;
LRESULT CALLBACK WndprocConsole( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
bool bConsoleVisible;
WINDOWPLACEMENT WinPlaceConsole;
void WinPlaceConsoleCallback( ConfVar * var )
{
if( !IsWindow( WindowConsole ) ) return;
GetWindowPlacement( WindowConsole, &WinPlaceConsole );
// MSDN: If the window identified by the hWnd parameter
// is maximized, the showCmd member is SW_SHOWMAXIMIZED.
// If the window is minimized, showCmd is SW_SHOWMINIMIZED.
// Otherwise, it is SW_SHOWNORMAL.
if( !bConsoleVisible )
{
WinPlaceConsole.showCmd = SW_HIDE;
}
}
RECT rConsoleDefault = { 50, 400, 450, 700 };
ConfWinPlaceCallback cwpcWinPlaceConsole(
&WinPlaceConsole,
TEXT( "WinPlaceConsole" ),
&rConsoleDefault,
WinPlaceConsoleCallback
);
////////////////////////////////////////////////////////////////////////////////
/// Creates the console window.
/// Size and visibility is used from config.
///
/// @return Success flag
////////////////////////////////////////////////////////////////////////////////
bool Console::Create()
{
WindowConsole = CreateWindowEx(
WS_EX_TOOLWINDOW | // DWORD dwExStyle
WS_EX_CLIENTEDGE, //
TEXT( "LISTBOX" ), // LPCTSTR lpClassName
TEXT( "Console" ), // LPCTSTR lpWindowName
WS_VSCROLL | // DWORD dwStyle
LBS_DISABLENOSCROLL | //
LBS_EXTENDEDSEL | //
LBS_HASSTRINGS | //
LBS_NOTIFY | //
LBS_NOINTEGRALHEIGHT | //
WS_POPUP | //
WS_OVERLAPPEDWINDOW, //
rConsoleDefault.left, // int x
rConsoleDefault.top, // int y
rConsoleDefault.right - rConsoleDefault.left, // int nWidth
rConsoleDefault.bottom - rConsoleDefault.top, // int nHeight
WindowMain, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
if( !WindowConsole ) return false;
// A blank line at the bottom will give us more space
SendMessage( WindowConsole, LB_INSERTSTRING, 0, ( LPARAM )TEXT( "" ) );
Font::Apply( WindowConsole );
bConsoleVisible = ( WinPlaceConsole.showCmd != SW_HIDE );
SetWindowPlacement( WindowConsole, &WinPlaceConsole );
// Exchange window procedure
WndprocConsoleBackup = ( WNDPROC )GetWindowLong( WindowConsole, GWL_WNDPROC );
if( WndprocConsoleBackup != NULL )
{
SetWindowLong( WindowConsole, GWL_WNDPROC, ( LONG )WndprocConsole );
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// Destroys the console window.
///
/// @return Success flag
////////////////////////////////////////////////////////////////////////////////
bool Console::Destroy()
{
if( !WindowConsole ) return false;
DestroyWindow( WindowConsole );
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// Pops up the console window.
///
/// @return Success flag
////////////////////////////////////////////////////////////////////////////////
bool Console::Popup()
{
if( !WindowConsole ) return false;
if( !IsWindowVisible( WindowConsole ) )
{
ShowWindow( WindowConsole, SW_SHOW );
}
SetActiveWindow( WindowConsole );
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// Adds a new entry at the end/bottom
///
/// @param szText Log entry
/// @return Success flag
////////////////////////////////////////////////////////////////////////////////
bool Console::Append( TCHAR * szText )
{
if( !WindowConsole ) return false;
if( iNext > iMaxEntries - 1 )
{
SendMessage(
WindowConsole,
LB_DELETESTRING,
0,
0
);
iNext--;
}
const int uTextLen = ( int )_tcslen( szText );
TCHAR * szBuffer = new TCHAR[ 11 + uTextLen + 1 ];
time_t now_time_t = time( NULL );
struct tm * now_tm = localtime( &now_time_t );
_tcsftime( szBuffer, 12, TEXT( "%H:%M:%S " ), now_tm );
memcpy( szBuffer + 11, szText, uTextLen * sizeof( TCHAR ) );
szBuffer[ 11 + uTextLen ] = TEXT( '\0' );
SendMessage( WindowConsole, LB_INSERTSTRING, iNext, ( LPARAM )szBuffer );
SendMessage( WindowConsole, LB_SETSEL, FALSE, -1 );
SendMessage( WindowConsole, LB_SETSEL, TRUE, iNext );
SendMessage( WindowConsole, LB_SETTOPINDEX, iNext, 0 );
iNext++;
delete [] szBuffer;
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndprocConsole( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
switch( message )
{
/*
case WM_CTLCOLORLISTBOX:
if( ( HWND )lp == WindowConsole )
{
SetBkColor (( HDC )wp, GetSysColor(COLOR_3DFACE));
return ( LRESULT )GetSysColorBrush(COLOR_3DFACE);
}
break;
*/
case WM_SYSCOMMAND:
// Hide instead of closing
if( ( wp & 0xFFF0 ) == SC_CLOSE )
{
ShowWindow( hwnd, SW_HIDE );
return 0;
}
break;
case WM_DESTROY:
cwpcWinPlaceConsole.TriggerCallback();
cwpcWinPlaceConsole.RemoveCallback();
break;
case WM_SHOWWINDOW:
bConsoleVisible = ( wp == TRUE );
break;
}
return CallWindowProc( WndprocConsoleBackup, hwnd, message, wp, lp );
}
+40
View File
@@ -0,0 +1,40 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_CONSOLE_H
#define PA_CONSOLE_H
#include "Global.h"
extern HWND WindowConsole;
////////////////////////////////////////////////////////////////////////////////
/// Logging console window
////////////////////////////////////////////////////////////////////////////////
namespace Console
{
bool Create();
bool Destroy();
bool Popup();
bool Append( TCHAR * szText );
}
#endif // PA_CONSOLE_H
+136
View File
@@ -0,0 +1,136 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "DspModule.h"
#include "Unicode.h"
DspModule ** active_dsp_mods = NULL; // extern
int active_dsp_count = 0; // extern
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
DspModule::DspModule( char * szName, int iIndex, winampDSPModule * mod, DspPlugin * plugin )
{
iArrayIndex = -1;
iNameLen = ( int )strlen( szName );
this->szName = new TCHAR[ iNameLen + 1 ];
ToTchar( this->szName, szName, iNameLen );
this->szName[ iNameLen ] = TEXT( '\0' );
this->iIndex = iIndex;
this->mod = mod;
this->plugin = plugin;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool DspModule::Start( int iIndex )
{
if( !mod ) return false;
if( iArrayIndex != -1 ) return false;
if( !mod->Init ) return false;
if( mod->Init( mod ) != 0 ) return false;
////////////////////////////////////////////////////////////////////////////////
DspLock.Enter();
////////////////////////////////////////////////////////////////////////////////
if( !active_dsp_count )
{
active_dsp_mods = new DspModule * [ 1 ];
active_dsp_mods[ 0 ] = this;
iArrayIndex = 0;
}
else
{
if( iIndex < 0 )
iIndex = 0;
else if( iIndex > active_dsp_count )
iIndex = active_dsp_count;
DspModule ** new_active_dsp_mods = new DspModule * [ active_dsp_count + 1 ];
memcpy( new_active_dsp_mods, active_dsp_mods, iIndex * sizeof( DspModule * ) );
memcpy( new_active_dsp_mods + iIndex + 1, active_dsp_mods + iIndex, ( active_dsp_count - iIndex ) * sizeof( DspModule * ) );
for( int i = iIndex + 1; i < active_dsp_count + 1; i++ )
{
new_active_dsp_mods[ i ]->iArrayIndex = i;
}
new_active_dsp_mods[ iIndex ] = this;
iArrayIndex = iIndex;
delete [] active_dsp_mods;
active_dsp_mods = new_active_dsp_mods;
}
active_dsp_count++;
////////////////////////////////////////////////////////////////////////////////
DspLock.Leave();
////////////////////////////////////////////////////////////////////////////////
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool DspModule::Stop()
{
if( !mod ) return false;
if( iArrayIndex == -1 ) return false;
if( !mod->Quit ) return true;
////////////////////////////////////////////////////////////////////////////////
DspLock.Enter();
////////////////////////////////////////////////////////////////////////////////
for( int i = iArrayIndex; i < active_dsp_count - 1; i++ )
{
active_dsp_mods[ i ] = active_dsp_mods[ i + 1 ];
active_dsp_mods[ i ]->iArrayIndex = i;
}
active_dsp_count--;
////////////////////////////////////////////////////////////////////////////////
DspLock.Leave();
////////////////////////////////////////////////////////////////////////////////
mod->Quit( mod );
iArrayIndex = -1;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool DspModule::Config()
{
if( !mod ) return false;
if( iArrayIndex == -1 ) return false;
if( !mod->Config ) return false;
mod->Config( mod );
return true;
}
+67
View File
@@ -0,0 +1,67 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_DSP_MODULE_H
#define PA_DSP_MODULE_H
#include "Global.h"
#include "DspPlugin.h"
#include "Winamp/Dsp.h"
class DspModule;
class DspPlugin;
extern DspModule ** active_dsp_mods;
extern int active_dsp_count;
////////////////////////////////////////////////////////////////////////////////
/// Winamp DSP module wrapper
////////////////////////////////////////////////////////////////////////////////
class DspModule
{
public:
inline bool IsActive() { return ( iArrayIndex != -1 ); }
inline TCHAR * GetName() { return szName; }
inline int GetNameLen() { return iNameLen; }
DspModule( char * szName, int iIndex, winampDSPModule * mod, DspPlugin * plugin );
// DspModule( wchar_t * szName, int iIndex, winampVisModule * mod, VisPlugin * plugin );
bool Start( int iIndex );
bool Stop();
bool Config();
private:
int iArrayIndex;
TCHAR * szName;
int iNameLen;
int iIndex;
winampDSPModule * mod;
DspPlugin * plugin;
friend int dsp_dosamples( short int * samples, int numsamples, int bps, int nch, int srate );
};
#endif // PA_DSP_MODULE_H
+185
View File
@@ -0,0 +1,185 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "DspPlugin.h"
#include "Main.h"
#include "Unicode.h"
#include "Console.h"
vector <DspPlugin *> dsp_plugins; // extern
Lock DspLock = Lock( TEXT( "PLAINAMP_DSP_LOCK" ) ); // extern
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
DspPlugin::DspPlugin( TCHAR * szDllpath, bool bKeepLoaded ) : Plugin( szDllpath )
{
header = NULL;
if( !Load() )
{
return;
}
if( !bKeepLoaded )
{
Unload();
}
dsp_plugins.push_back( this );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool DspPlugin::Load()
{
if( IsLoaded() ) return true;
// (1) Load DLL
hDLL = LoadLibrary( GetFullpath() );
if( !hDLL ) return false;
// (2) Find export
WINAMP_DSP_GETTER winampGetDSPHeader2 =
( WINAMP_DSP_GETTER )GetProcAddress( hDLL, "winampDSPGetHeader2" );
if( winampGetDSPHeader2 == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (3) Get header
header = winampGetDSPHeader2();
if( header == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Forget old modules or we get them twice
if( !modules.empty() )
{
modules.clear();
}
////////////////////////////////////////////////////////////////////////////////
if( !szName )
{
// Note: The prefix is not removed to hide their
// origin at Nullsoft! It just reads easier.
if( !strnicmp( header->description, "nullsoft ", 9 ) )
{
header->description += 9;
}
iNameLen = ( int )strlen( header->description );
szName = new TCHAR[ iNameLen + 1 ];
ToTchar( szName, header->description, iNameLen );
szName[ iNameLen ] = TEXT( '\0' );
}
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Loading <%s>, %s" ), GetFilename(), szName );
Console::Append( szBuffer );
// (4) Get modules
winampDSPModule * mod;
int iFound = 0;
while( true )
{
mod = header->getModule( iFound );
if( !mod ) break;
// (4a) Modify module
mod->hDllInstance = hDLL;
mod->hwndParent = WindowMain;
// (4b) Add module to list
DspModule * dspmod = new DspModule(
mod->description, // char * szName
iFound, // UINT uIndex
mod, // winampDspModule * mod
this // DspPlugin * plugin
);
modules.push_back( dspmod );
iFound++;
_stprintf( szBuffer, TEXT( " %s" ), dspmod->GetName() );
Console::Append( szBuffer );
}
Console::Append( TEXT( " " ) );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool DspPlugin::Unload()
{
if( !IsLoaded() ) return true;
if( IsActive() ) return false;
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Unloading <%s>" ), GetFilename() );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
header = NULL;
/*
TODO
DspModule * walk;
vector <DspModule *>::iterator iter = modules.begin();
while( iter != modules.end() )
{
walk = *iter;
delete [] walk->szName;
delete walk;
iter++;
}
*/
FreeLibrary( hDLL );
hDLL = NULL;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool DspPlugin::IsActive()
{
vector <DspModule *>::iterator iter = modules.begin();
while( iter != modules.end() )
{
if( ( *iter )->IsActive() ) return true;
iter++;
}
return false;
}
+69
View File
@@ -0,0 +1,69 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_DSP_PLUGIN_H
#define PA_DSP_PLUGIN_H
#include "Global.h"
#include "Plugin.h"
#include "Winamp/Dsp.h"
#include "Lock.h"
#include "DspModule.h"
#include <vector>
using namespace std;
typedef winampDSPHeader * ( * WINAMP_DSP_GETTER )( void );
class DspModule;
class DspPlugin;
extern vector <DspPlugin *> dsp_plugins;
extern Lock DspLock;
////////////////////////////////////////////////////////////////////////////////
/// Winamp DSP plugin wrapper
////////////////////////////////////////////////////////////////////////////////
class DspPlugin : public Plugin
{
public:
DspPlugin( TCHAR * szDllpath, bool bKeepLoaded );
bool Load();
bool Unload();
TCHAR * GetTypeString() { return TEXT( "DSP" ); }
int GetTypeStringLen() { return 3; }
PluginType GetType() { return PLUGIN_TYPE_DSP; }
bool IsActive();
private:
winampDSPHeader * header;
vector<DspModule *> modules;
friend class DspModule;
friend void ContextMenuDsp( DspPlugin * dsp, POINT * p );
};
#endif // PA_DSP_PLUGIN_H
@@ -0,0 +1,455 @@
/*//////////////////////////////////////////////////////////////////////////////
// ExtraMessageBox
//
// Copyright © 2006 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
//////////////////////////////////////////////////////////////////////////////*/
/*
TODO
* realign/recenter after height change
* tab stop order when adding buttons
* offer extra callback?
* auto click timer (one button after XXX seconds)
* allow several checkboxes? radio buttons?
MB_YESNO
MB_YESNOCANCEL
--> MB_YESNOALL
--> MB_YESNOCANCELALL
--> MB_DEFBUTTON5
--> IDNOALL
--> IDYESALL
*/
#include "Emabox.h"
#define FUNCTION_NORMAL 0
#define FUNCTION_EXTENDED 1
#define FUNCTION_INDIRECT 2
const int SPACE_UNDER_CHECKBOX = 10;
const int SPACE_EXTRA_BOTTOM = 4;
TCHAR * const szNeverAgain = TEXT( "Do not show again" );
TCHAR * const szRememberChoice = TEXT( "Remember my choice" );
DWORD dwTlsSlot = TLS_OUT_OF_INDEXES;
#ifdef EMA_AUTOINIT
int bEmaInitDone = 0;
#endif
struct StructEmaBoxData
{
int * bCheckState;
HHOOK hCBT; /* CBT hook handle */
WNDPROC WndprocMsgBoxBackup; /* Old wndproc */
UINT uType; /* Message box type */
HWND hCheck; /* Checkbox handle */
};
typedef struct StructEmaBoxData EmaBoxData;
void RectScreenToClient( const HWND h, RECT * const r )
{
POINT p;
RECT after;
p.x = r->left;
p.y = r->top;
ScreenToClient( h, &p );
after.left = p.x;
after.right = p.x + r->right - r->left;
after.top = p.y;
after.bottom = p.y + r->bottom - r->top;
memcpy( r, &after, sizeof( RECT ) );
}
LRESULT CALLBACK WndprocMsgBox( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
/* Find data */
EmaBoxData * const data = ( EmaBoxData * )TlsGetValue( dwTlsSlot );
switch( message )
{
case WM_COMMAND:
if( HIWORD( wp ) == BN_CLICKED )
{
if( !data->hCheck || ( ( HWND )lp != data->hCheck ) ) break;
{
const LRESULT res = SendMessage( ( HWND )lp, BM_GETSTATE, 0, 0 );
const int bCheckedAfter = ( ( res & BST_CHECKED ) == 0 );
/* Update external variable */
*( data->bCheckState ) = bCheckedAfter ? 1 : 0;
SendMessage( ( HWND )lp, BM_SETCHECK, ( bCheckedAfter ) ? BST_CHECKED : 0, 0 );
}
}
break;
case WM_INITDIALOG:
{
/* Add checkbox */
if( ( data->uType & MB_CHECKMASC ) != 0 )
{
int SPACE_OVER_CHECKBOX;
HDC hdc;
RECT rw; /* Window rect */
RECT rc; /* Client rect */
HWND hText; /* Message handle */
RECT rt; /* Message rect */
int iLabelHeight;
TCHAR * szCheckboxLabel; /* Checkbox label */
int iWindowWidthBefore;
int iWindowHeightBefore;
int iClientWidthBefore;
int iClientHeightBefore;
int iNeverAgainWidth;
int iNeverAgainHeight;
/* Get original window dimensions */
GetWindowRect( hwnd, &rw );
iWindowWidthBefore = rw.right - rw.left;
iWindowHeightBefore = rw.bottom - rw.top;
GetClientRect( hwnd, &rc );
iClientWidthBefore = rc.right - rc.left;
iClientHeightBefore = rc.bottom - rc.top;
{
/* Find handle of the text label */
HWND hFirstStatic;
HWND hSecondStatic;
hFirstStatic = FindWindowEx( hwnd, NULL, TEXT( "STATIC" ), NULL );
if( !hFirstStatic ) break;
hSecondStatic = FindWindowEx( hwnd, hFirstStatic, TEXT( "STATIC" ), NULL );
if( !hSecondStatic )
{
/* Only one static means no icon. */
/* So hFirstStatic must be the text window. */
hText = hFirstStatic;
}
else
{
TCHAR szBuf[ 2 ] = TEXT( "" );
if( !GetWindowText( hSecondStatic, szBuf, 2 ) ) break;
if( *szBuf != TEXT( '\0' ) )
{
/* Has text so it must be the label */
hText = hSecondStatic;
}
else
{
hText = hFirstStatic;
}
}
}
GetWindowRect( hText, &rt );
RectScreenToClient( hwnd, &rt );
iLabelHeight = rt.bottom - rt.top;
{
/* Get distance between label and the buttons */
HWND hAnyButton;
RECT rab;
hAnyButton = FindWindowEx( hwnd, NULL, TEXT( "BUTTON" ), NULL );
if( !hAnyButton ) break;
GetWindowRect( hAnyButton, &rab );
RectScreenToClient( hwnd, &rab );
SPACE_OVER_CHECKBOX = rab.top - rt.bottom;
}
szCheckboxLabel = ( data->uType & MB_CHECKNEVERAGAIN )
? EMA_TEXT_NEVER_AGAIN
: EMA_TEXT_REMEMBER_CHOICE;
/* Add checkbox */
data->hCheck = CreateWindow(
TEXT( "BUTTON" ),
szCheckboxLabel,
WS_CHILD |
WS_VISIBLE |
WS_TABSTOP |
BS_VCENTER |
BS_CHECKBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
hwnd,
NULL,
GetModuleHandle( NULL ),
NULL
);
/* Set initial check state */
SendMessage( data->hCheck, BM_SETCHECK, *( data->bCheckState ) ? BST_CHECKED : 0, 0 );
{
/* Apply default font */
const int cyMenuSize = GetSystemMetrics( SM_CYMENUSIZE );
const int cxMenuSize = GetSystemMetrics( SM_CXMENUSIZE );
const HFONT hNewFont = ( HFONT )GetStockObject( DEFAULT_GUI_FONT );
HFONT hOldFont;
SIZE size;
SendMessage( data->hCheck, WM_SETFONT, ( WPARAM )hNewFont, ( LPARAM )TRUE );
hdc = GetDC( data->hCheck );
hOldFont = ( HFONT )SelectObject( hdc, GetStockObject( DEFAULT_GUI_FONT ) );
GetTextExtentPoint32( hdc, szCheckboxLabel, _tcslen( szCheckboxLabel ), &size );
SelectObject( hdc, hOldFont );
ReleaseDC( data->hCheck, hdc );
iNeverAgainWidth = cxMenuSize + size.cx + 1;
iNeverAgainHeight = ( cyMenuSize > size.cy ) ? cyMenuSize : size.cy;
}
MoveWindow(
data->hCheck,
( iClientWidthBefore - ( iNeverAgainWidth ) ) / 2,
rt.top + iLabelHeight + SPACE_OVER_CHECKBOX,
iNeverAgainWidth,
iNeverAgainHeight,
FALSE
);
{
/* Move all buttons down (except the checkbox) */
const int iDistance = iNeverAgainHeight + SPACE_UNDER_CHECKBOX;
HWND hLastButton = NULL;
RECT rb;
for( ; ; )
{
hLastButton = FindWindowEx( hwnd, hLastButton, TEXT( "BUTTON" ), NULL );
if( !hLastButton ) break;
if( hLastButton == data->hCheck ) continue;
GetWindowRect( hLastButton, &rb );
RectScreenToClient( hwnd, &rb );
MoveWindow( hLastButton, rb.left, rb.top + iDistance, rb.right - rb.left, rb.bottom - rb.top, FALSE );
}
/* Enlarge dialog */
MoveWindow( hwnd, rw.left, rw.top, iWindowWidthBefore, iWindowHeightBefore + iDistance + SPACE_EXTRA_BOTTOM, FALSE );
}
}
else
{
data->hCheck = NULL;
}
/* Modify close button */
switch( data->uType & MB_CLOSEMASK )
{
case MB_DISABLECLOSE:
{
const HMENU hSysMenu = GetSystemMenu( hwnd, FALSE );
EnableMenuItem( hSysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED );
}
break;
case MB_NOCLOSE:
{
const LONG style = GetWindowLong( hwnd, GWL_STYLE );
if( ( style & WS_SYSMENU ) == 0 ) break;
SetWindowLong( hwnd, GWL_STYLE, ( LONG )( style - WS_SYSMENU ) );
}
break;
}
}
break;
}
return CallWindowProc( data->WndprocMsgBoxBackup, hwnd, message, wp, lp );
}
/* int bFound = 0; */
LRESULT CALLBACK HookprocMsgBox( int code, WPARAM wp, LPARAM lp )
{
/* Get hook handle */
EmaBoxData * const data = ( EmaBoxData * )TlsGetValue( dwTlsSlot );
if( code == HCBT_CREATEWND )
{
/* MSDN says WE CANNOT TRUST "CBT_CREATEWND" */
/* so we use only the window handle */
/* and get the class name using "GetClassName". (-> Q106079) */
HWND hwnd = ( HWND )wp;
/* Check windowclass */
TCHAR szClass[ 7 ] = TEXT( "" );
GetClassName( hwnd, szClass, 7 );
if( !_tcscmp( szClass, TEXT( "#32770" ) ) )
{
/*
if( bFound )
{
return CallNextHookEx( hCBT, code, wp, lp );
}
bFound = 1;
*/
/* Exchange window procedure */
data->WndprocMsgBoxBackup = ( WNDPROC )GetWindowLong( hwnd, GWL_WNDPROC );
if( data->WndprocMsgBoxBackup != NULL )
{
SetWindowLong( hwnd, GWL_WNDPROC, ( LONG )WndprocMsgBox );
}
}
}
return CallNextHookEx( data->hCBT, code, wp, lp );
}
int ExtraAllTheSame( const HWND hWnd, const LPCTSTR lpText, const LPCTSTR lpCaption, const UINT uType, const WORD wLanguageId, const LPMSGBOXPARAMS lpMsgBoxParams, int * const pbCheckRes, const int iFunction )
{
EmaBoxData * data;
HHOOK hCBT;
int res;
#ifdef EMA_AUTOINIT
if( !bEmaInitDone )
{
EmaBoxLive();
bEmaInitDone = 1;
}
#endif
/* Create thread data */
data = ( EmaBoxData * )LocalAlloc( NONZEROLPTR, sizeof( EmaBoxData ) );
TlsSetValue( dwTlsSlot, data );
data->bCheckState = pbCheckRes;
data->uType = ( iFunction != FUNCTION_INDIRECT ) ? uType : lpMsgBoxParams->dwStyle;
/* Setup this-thread-only hook */
hCBT = SetWindowsHookEx( WH_CBT, &HookprocMsgBox, GetModuleHandle( NULL ), GetCurrentThreadId() );
switch( iFunction )
{
case FUNCTION_NORMAL:
res = MessageBox( hWnd, lpText, lpCaption, uType );
break;
case FUNCTION_EXTENDED:
res = MessageBoxEx( hWnd, lpText, lpCaption, uType, wLanguageId );
break;
case FUNCTION_INDIRECT:
res = MessageBoxIndirect( lpMsgBoxParams );
break;
}
/* Remove hook */
if( hCBT != NULL ) UnhookWindowsHookEx( hCBT );
/* Destroy thread data */
LocalFree( ( HLOCAL )data );
return res;
}
int EmaBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int * pbCheckRes )
{
/* Check extra flags */
if( ( uType & MB_EXTRAMASC ) == 0 )
{
/* No extra */
return MessageBox( hWnd, lpText, lpCaption, uType );
}
return ExtraAllTheSame( hWnd, lpText, lpCaption, uType, 0, NULL, pbCheckRes, FUNCTION_NORMAL );
}
int EmaBoxEx( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, WORD wLanguageId, int * pbCheckRes )
{
/* Check extra flags */
if( ( uType & MB_EXTRAMASC ) == 0 )
{
/* No extra */
return MessageBoxEx( hWnd, lpText, lpCaption, uType, wLanguageId );
}
return ExtraAllTheSame( hWnd, lpText, lpCaption, uType, wLanguageId, NULL, pbCheckRes, FUNCTION_EXTENDED );
}
int EmaBoxIndirect( const LPMSGBOXPARAMS lpMsgBoxParams, int * pbCheckRes )
{
/* Check extra flags */
if( ( lpMsgBoxParams->dwStyle & MB_EXTRAMASC ) == 0 )
{
/* No extra */
return MessageBoxIndirect( lpMsgBoxParams );
}
return ExtraAllTheSame( NULL, NULL, NULL, 0, 0, lpMsgBoxParams, pbCheckRes, FUNCTION_INDIRECT );
}
int EmaBoxLive()
{
dwTlsSlot = TlsAlloc();
if( dwTlsSlot == TLS_OUT_OF_INDEXES ) return 0;
return 1;
}
int EmaBoxDie()
{
if( dwTlsSlot == TLS_OUT_OF_INDEXES ) return 0;
TlsFree( dwTlsSlot );
return 1;
}
@@ -0,0 +1,138 @@
/*//////////////////////////////////////////////////////////////////////////////
// ExtraMessageBox
//
// Copyright © 2006 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef EXTRA_MESSAGE_BOX_H
#define EXTRA_MESSAGE_BOX_H 1
#include "EmaboxConfig.h"
#include <windows.h>
#include <tchar.h>
/*
== TYPE =============================================================================
#define MB_TYPEMASK 15 1111
#define MB_OK 0 0000
#define MB_OKCANCEL 1 0001
#define MB_ABORTRETRYIGNORE 2 0010
#define MB_YESNOCANCEL 3 0011
#define MB_YESNO 4 0100
#define MB_RETRYCANCEL 5 0101
#define MB_CANCELTRYCONTINUE 6 0110
*/
#define MB_YESNOCANCELALL 7 /* 0111 */
#define MB_YESNOALL 8 /* 1000 */
/*
== ICON =============================================================================
#define MB_ICONMASK 240 11110000
#define MB_ICONERROR 16 00010000
#define MB_ICONHAND 16 00010000
#define MB_ICONSTOP 16 00010000
#define MB_ICONQUESTION 32 00100000
#define MB_ICONEXCLAMATION 0x30 00110000
#define MB_ICONWARNING 0x30 00110000
#define MB_ICONINFORMATION 64 01000000
#define MB_ICONASTERISK 64 01000000
#define MB_USERICON 128 10000000
== DEFAULT BUTTON ===================================================================
#define MB_DEFMASK 3840 111100000000
#define MB_DEFBUTTON1 0 000000000000
#define MB_DEFBUTTON2 256 000100000000
#define MB_DEFBUTTON3 512 001000000000
#define MB_DEFBUTTON4 0x300 001100000000
*/
#define MB_DEFBUTTON5 1024 /* 010000000000 */
#define MB_DEFBUTTON6 1280 /* 010100000000 */
/*
== MODE =============================================================================
#define MB_MODEMASK 0x00003000 11000000000000
#define MB_APPLMODAL 0 00000000000000
#define MB_SYSTEMMODAL 4096 01000000000000
#define MB_TASKMODAL 0x2000 10000000000000
== MISC =============================================================================
#define MB_MISCMASK 0x0000C000 1100000000000000
#define MB_HELP 0x4000 0100000000000000
#define MB_NOFOCUS 0x00008000 1000000000000000
== FLAGS ============================================================================
#define MB_SETFOREGROUND 0x10000 10000000000000000
#define MB_DEFAULT_DESKTOP_ONLY 0x20000 100000000000000000
#define MB_TOPMOST 0x40000 1000000000000000000
#define MB_SERVICE_NOTIFICATION_NT3X 0x00040000 1000000000000000000
#define MB_SERVICE_NOTIFICATION 0x00040000 1000000000000000000
#define MB_TOPMOST 0x40000 1000000000000000000
#define MB_RIGHT 0x80000 10000000000000000000
#define MB_RTLREADING 0x100000 100000000000000000000
#define MB_SERVICE_NOTIFICATION 0x00200000 1000000000000000000000
== EXTRA FLAGS ======================================================================
*/
#define MB_EXTRAMASC 0xF0000000 /* 11110000000000000000000000000000 */
#define MB_CHECKMASC 0xC0000000 /* 11000000000000000000000000000000 */
#define MB_CHECKNONE 0 /* 00000000000000000000000000000000 */
#define MB_CHECKNEVERAGAIN 0x40000000 /* 01000000000000000000000000000000 */
#define MB_CHECKREMEMBERCHOICE 0x80000000 /* 10000000000000000000000000000000 */
#define MB_CLOSEMASK 0x30000000 /* 00110000000000000000000000000000 */
#define MB_NORMALCLOSE 0 /* 00000000000000000000000000000000 */
#define MB_DISABLECLOSE 0x10000000 /* 00010000000000000000000000000000 */
#define MB_NOCLOSE 0x20000000 /* 00100000000000000000000000000000 */
/* Function aliases */
#define ExtraMessageBoxLive EmaBoxLive
#define ExtraMessageBoxDie EmaBoxDie
#define ExtraMessageBox EmaBox
#define ExtraMessageBoxEx EmaBoxEx
#define ExtraMessageBoxIndirect EmaBoxIndirect
int EmaBoxLive();
int EmaBoxDie();
int EmaBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType,
int * pbCheckRes
);
int EmaBoxEx(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType,
WORD wLanguageId,
int * pbCheckRes
);
int EmaBoxIndirect(
const LPMSGBOXPARAMS lpMsgBoxParams,
int * pbCheckRes
);
#endif /* EXTRA_MESSAGE_BOX_H */
@@ -0,0 +1,32 @@
/*//////////////////////////////////////////////////////////////////////////////
// ExtraMessageBox
//
// Copyright © 2006 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef EXTRA_MESSAGE_BOX_CONFIG_H
#define EXTRA_MESSAGE_BOX_CONFIG_H 1
/* Allow laziness */
#define EMA_AUTOINIT
/* Allow overwriting message text */
#ifndef EMA_TEXT_NEVER_AGAIN
# define EMA_TEXT_NEVER_AGAIN szNeverAgain
#endif
#ifndef EMA_TEXT_REMEMBER_CHOICE
# define EMA_TEXT_REMEMBER_CHOICE szRememberChoice
#endif
#endif /* EXTRA_MESSAGE_BOX_CONFIG_H */
+233
View File
@@ -0,0 +1,233 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "Embed.h"
#include "Console.h"
#define CLASSNAME_EMBED TEXT( "Winamp Gen" )
#define TITLE_EMBED TEXT( "Embed target" )
#define EMBED_WIDTH 320
#define EMBED_HEIGHT 240
const TCHAR * const szEmbedTitle = TITLE_EMBED;
bool bEmbedClassRegistered = false;
LRESULT CALLBACK WndprocEmbed( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
////////////////////////////////////////////////////////////////////////////////
/// Creates a new embed window.
///
/// @param ews Embed window state
/// @return New embed window handle
////////////////////////////////////////////////////////////////////////////////
HWND Embed::Embed( embedWindowState * ews )
{
// Register class
if ( !bEmbedClassRegistered )
{
WNDCLASS wc = {
0, // UINT style
WndprocEmbed, // WNDPROC lpfnWndProc
0, // int cbClsExtra
0, // int cbWndExtra
g_hInstance, // HINSTANCE hInstance
NULL, // HICON hIcon
LoadCursor( NULL, IDC_ARROW ), // HCURSOR hCursor
( HBRUSH )COLOR_WINDOW, // HBRUSH hbrBackground
NULL, // LPCTSTR lpszMenuName
CLASSNAME_EMBED // LPCTSTR lpszClassName
};
if( !RegisterClass( &wc ) ) return NULL;
bEmbedClassRegistered = true;
}
// Create window
HWND WindowEmbed = CreateWindowEx(
WS_EX_WINDOWEDGE | // DWORD dwExStyle
WS_EX_TOOLWINDOW, //
CLASSNAME_EMBED, // LPCTSTR lpClassName
szEmbedTitle, // LPCTSTR lpWindowName
WS_OVERLAPPED | // DWORD dwStyle
WS_CLIPCHILDREN | //
WS_BORDER | //
WS_CAPTION | //
WS_SYSMENU | //
WS_THICKFRAME | //
WS_MINIMIZEBOX | //
WS_MAXIMIZEBOX, //
10, // int x
10, // int y
EMBED_WIDTH, // int nWidth
EMBED_HEIGHT, // int nHeight
NULL, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
Console::Append( TEXT( "Embed window born" ) );
Console::Append( TEXT( " " ) );
if( !ews || !ews->me ) return WindowEmbed;
SetParent( ews->me, WindowEmbed );
return WindowEmbed;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
inline bool SameThread( HWND hOther )
{
const DWORD dwOtherThreadId = GetWindowThreadProcessId( hOther, NULL );
const DWORD dwThisThreadId = GetCurrentThreadId();
return ( dwOtherThreadId == dwThisThreadId );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndprocEmbed( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
// static bool bAllowSizeMove = false;
switch( message )
{
case WM_PARENTNOTIFY:
switch( LOWORD( wp ) )
{
case WM_DESTROY:
{
const HWND hChild = GetWindow( hwnd, GW_CHILD );
if( !SameThread( hChild ) )
{
// Vis plugin
DestroyWindow( hwnd );
}
break;
}
}
break;
case WM_SIZE:
{
const HWND hChild = GetWindow( hwnd, GW_CHILD );
if( !hChild ) break;
MoveWindow( hChild, 0, 0, LOWORD( lp ), HIWORD( lp ), TRUE );
break;
}
/*
case WM_ENTERSIZEMOVE:
bAllowSizeMove = true;
break;
case WM_EXITSIZEMOVE:
bAllowSizeMove = false;
break;
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS * pos = ( WINDOWPOS * )lp;
// Update child
if( IsWindow( WindowEmbedChild = GetWindow( WindowEmbed, GW_CHILD ) ) )
{
RECT r;
GetClientRect( WindowEmbed, &r );
MoveWindow( WindowEmbedChild, 0, 0, r.right, r.bottom, TRUE );
}
if( !bAllowSizeMove )
{
// Force SWP_NOMOVE
if( ( pos->flags & SWP_NOMOVE ) == 0 )
{
pos->flags |= SWP_NOMOVE;
}
// Force SWP_NOSIZE
if( ( pos->flags & SWP_NOSIZE ) == 0 )
{
pos->flags |= SWP_NOSIZE;
}
return 0;
}
break;
}
*/
case WM_SHOWWINDOW:
{
const HWND hChild = GetWindow( hwnd, GW_CHILD );
if( wp ) // Shown
{
// Update child size
RECT r;
GetClientRect( hwnd, &r );
MoveWindow( hChild, 0, 0, r.right, r.bottom, TRUE );
}
else // Hidden
{
ShowWindow( hChild, SW_HIDE );
DestroyWindow( hChild );
}
break;
}
case WM_SYSCOMMAND:
if( ( wp & 0xFFF0 ) == SC_CLOSE )
{
const HWND hChild = GetWindow( hwnd, GW_CHILD );
if( SameThread( hChild ) )
{
// Not a vis plugin
ShowWindow( hwnd, SW_HIDE );
return 0;
}
}
break;
case WM_DESTROY:
{
const HWND hChild = GetWindow( hwnd, GW_CHILD );
if( hChild && SameThread( hChild ) )
{
DestroyWindow( hChild );
}
Console::Append( TEXT( "Embed window dead" ) );
Console::Append( TEXT( " " ) );
break;
}
}
return DefWindowProc( hwnd, message, wp, lp );
}
+36
View File
@@ -0,0 +1,36 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_EMBED_H
#define PA_EMBED_H
#include "Global.h"
#include "Winamp/wa_ipc.h"
////////////////////////////////////////////////////////////////////////////////
/// Embed window service.
/// Winamp provides embed windows so plugins don't have to take care
/// of window skinning. A plugin let's Winamp create an embed window
/// and uses this new window as parent for its own window.
////////////////////////////////////////////////////////////////////////////////
namespace Embed
{
HWND Embed( embedWindowState * ews );
};
#endif // PA_EMBED_H
+83
View File
@@ -0,0 +1,83 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "Font.h"
HFONT hFont = NULL;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Font::Create()
{
hFont = CreateFont(
-11, // int nHeight
0, // int nWidth
0, // int nEscapement
0, // int nOrientation
FW_REGULAR, // int fnWeight
FALSE, // DWORD fdwItalic
FALSE, // DWORD fdwUnderline
FALSE, // DWORD fdwStrikeOut
ANSI_CHARSET, // DWORD fdwCharSet
OUT_TT_PRECIS, // DWORD fdwOutputPrecision
CLIP_DEFAULT_PRECIS, // DWORD fdwClipPrecision
ANTIALIASED_QUALITY, // DWORD fdwQuality
FF_DONTCARE | DEFAULT_PITCH, // DWORD fdwPitchAndFamily
TEXT( "Verdana" ) // LPCTSTR lpszFace
);
return ( hFont != NULL );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Font::Destroy()
{
if( !hFont ) return false;
DeleteObject( hFont );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Font::Apply( HWND hwnd )
{
if( !hFont ) return false;
SendMessage(
hwnd,
WM_SETFONT,
( WPARAM )hFont,
FALSE
);
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
HFONT Font::Get()
{
return hFont;
}
+34
View File
@@ -0,0 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#ifndef PA_FONT_H
#define PA_FONT_H
#include "Global.h"
namespace Font
{
bool Create();
bool Destroy();
bool Apply( HWND hwnd );
HFONT Get();
};
#endif // PA_FONT_H
+198
View File
@@ -0,0 +1,198 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "GenPlugin.h"
#include "Main.h"
#include "Unicode.h"
#include "Console.h"
#include <string.h>
vector <GenPlugin *> gen_plugins; // extern
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
GenPlugin::GenPlugin( TCHAR * szDllpath, bool bKeepLoaded ) : Plugin( szDllpath )
{
iHookerIndex = -1;
plugin = NULL;
if( !Load() )
{
return;
}
gen_plugins.push_back( this );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool GenPlugin::Load()
{
if( IsLoaded() ) return true;
// (1) Load DLL
hDLL = LoadLibrary( GetFullpath() );
if( !hDLL ) return false;
// (2) Find export
WINAMP_GEN_GETTER winampGetGeneralPurposePlugin =
( WINAMP_GEN_GETTER )GetProcAddress( hDLL, "winampGetGeneralPurposePlugin" );
if( winampGetGeneralPurposePlugin == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (3) Get module
plugin = winampGetGeneralPurposePlugin();
if( !plugin )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (4) Process module
plugin->hDllInstance = hDLL;
plugin->hwndParent = WindowMain;
// Note: Some plugins (mainly old ones) set description in init.
// Therefore we init first and copy the name after.
// (5) Init
if( plugin->init )
{
const WNDPROC WndprocBefore = ( WNDPROC )GetWindowLong( WindowMain, GWL_WNDPROC );
plugin->init();
const WNDPROC WndprocAfter = ( WNDPROC )GetWindowLong( WindowMain, GWL_WNDPROC );
if( WndprocBefore != WndprocAfter )
{
WndprocBackup = WndprocBefore;
iHookerIndex = iWndprocHookCounter++;
}
}
if( !szName )
{
// Note: The prefix is not removed to hide their
// origin at Nullsoft! It just reads easier.
if( !strnicmp( plugin->description, "nullsoft ", 9 ) )
{
plugin->description += 9;
}
// Get rid of " (xxx.dll)" postfix
char * walk = plugin->description + strlen( plugin->description ) - 5;
while( true )
{
if( ( walk <= plugin->description ) || strnicmp( walk, ".dll)", 5 ) ) break;
while( ( walk > plugin->description ) && ( *walk != '(' ) ) walk--;
if( walk <= plugin->description ) break;
walk--;
if( ( walk <= plugin->description ) || ( *walk != ' ' ) ) break;
*walk = '\0';
}
iNameLen = ( int )strlen( plugin->description );
szName = new TCHAR[ iNameLen + 1 ];
ToTchar( szName, plugin->description, iNameLen );
szName[ iNameLen ] = TEXT( '\0' );
}
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Loading <%s>, %s" ), GetFilename(), szName );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
// Note: Plugins that use a wndproc hook need
// to be unloaded in the inverse loading order.
// This is due to the nature of wndproc hooking.
if( iHookerIndex != -1 )
{
Console::Append( TEXT( "Wndproc hook added (by plugin)" ) );
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool GenPlugin::Unload()
{
if( !IsLoaded() ) return true;
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Unloading <%s>" ), GetFilename() );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
// Quit
if( plugin )
{
if( plugin->quit ) plugin->quit();
plugin = NULL;
}
// Remove wndproc hook
if( ( iHookerIndex != -1 ) && ( iHookerIndex == iWndprocHookCounter - 1 ) )
{
// If we don't restore it the plugins wndproc will
// still be called which is not there anymore -> crash
SetWindowLong( WindowMain, GWL_WNDPROC, ( LONG )WndprocBackup );
Console::Append( TEXT( "Wndproc hook removed (by host)" ) );
Console::Append( TEXT( " " ) );
iHookerIndex = -1;
iWndprocHookCounter--;
}
FreeLibrary( hDLL );
hDLL = NULL;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool GenPlugin::Config()
{
if( !IsLoaded() ) return false;
if( !plugin ) return false;
if( !plugin->config ) return false;
plugin->config();
return true;
}

Some files were not shown because too many files have changed in this diff Show More