mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
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:
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user