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

View File

@ -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++;
}
}

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_DIRECTORY_H
#define PA_ADD_DIRECTORY_H
#include "Global.h"
void AddDirectory();
#endif // PA_ADD_DIRECTORY_H

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;
}
}
}

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

View File

@ -0,0 +1,632 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Config.h"
#include "Console.h"
#include <map>
using namespace std;
map<TCHAR *, ConfVar *> * conf_map = NULL;
TCHAR * szIniPath = NULL;
const TCHAR * SECTION = TEXT( "Plainamp" );
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfVar::ConfVar( TCHAR * szKey, ConfMode mode )
{
// MessageBox( 0, TEXT( "no const @ ConfVar" ), TEXT( "" ), 0 );
// Init
const int iLen = ( int )_tcslen( szKey );
m_szKey = new TCHAR[ iLen + 1 ];
memcpy( m_szKey, szKey, iLen * sizeof( TCHAR ) );
m_szKey[ iLen ] = TEXT( '\0' );
m_bCopyKey = true;
m_Mode = mode;
m_bRead = false;
// Register
if( !conf_map ) conf_map = new map<TCHAR *, ConfVar *>;
conf_map->insert( pair<TCHAR *, ConfVar *>( m_szKey, this ) );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfVar::ConfVar( const TCHAR * szKey, ConfMode mode )
{
// Init
m_szKey = ( TCHAR * )szKey;
m_bCopyKey = false;
m_Mode = mode;
m_bRead = false;
// Register
if( !conf_map ) conf_map = new map<TCHAR *, ConfVar *>;
conf_map->insert( pair<TCHAR *, ConfVar *>( m_szKey, this ) );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfVar::~ConfVar()
{
if( m_bCopyKey && m_szKey ) delete [] m_szKey;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfBool::ConfBool( bool * pbData, TCHAR * szKey, ConfMode mode, bool bDefault ) : ConfVar( szKey, mode )
{
// MessageBox( 0, TEXT( "no const @ ConfBool" ), TEXT( "" ), 0 );
m_pbData = pbData;
m_bDefault = bDefault;
// *pbData = bDefault;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfBool::ConfBool( bool * pbData, const TCHAR * szKey, ConfMode mode, bool bDefault ) : ConfVar( szKey, mode )
{
m_pbData = pbData;
m_bDefault = bDefault;
// *pbData = bDefault;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfBool::Read()
{
if( m_bRead || !szIniPath ) return;
*m_pbData = ( GetPrivateProfileInt( SECTION, m_szKey, ( int )m_bDefault, szIniPath ) != 0 );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfBool::Write()
{
WritePrivateProfileString( SECTION, m_szKey, *m_pbData ? TEXT( "1" ) : TEXT( "0" ), szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfInt::ConfInt( int * piData, TCHAR * szKey, ConfMode mode, int iDefault ) : ConfVar( szKey, mode )
{
MessageBox( 0, TEXT( "no const" ), TEXT( "" ), 0 );
m_piData = piData;
m_iDefault = iDefault;
// *piData = iDefault;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfInt::ConfInt( int * piData, const TCHAR * szKey, ConfMode mode, int iDefault ) : ConfVar( szKey, mode )
{
m_piData = piData;
m_iDefault = iDefault;
// *piData = iDefault;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfInt::Read()
{
if( m_bRead || !szIniPath ) return;
*m_piData = GetPrivateProfileInt( SECTION, m_szKey, m_iDefault, szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfInt::Write()
{
TCHAR szNumber[ 12 ] = TEXT( "" );
_stprintf( szNumber, TEXT( "%i" ), *m_piData );
WritePrivateProfileString( SECTION, m_szKey, szNumber, szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfIntMinMax::ConfIntMinMax( int * piData, TCHAR * szKey, ConfMode mode, int iDefault, int iMin, int iMax ) : ConfInt( piData, szKey, mode, iDefault )
{
MessageBox( 0, TEXT( "no const" ), TEXT( "" ), 0 );
m_iMin = iMin;
m_iMax = iMax;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfIntMinMax::ConfIntMinMax( int * piData, const TCHAR * szKey, ConfMode mode, int iDefault, int iMin, int iMax ) : ConfInt( piData, szKey, mode, iDefault )
{
m_iMin = iMin;
m_iMax = iMax;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfWinPlaceCallback::ConfWinPlaceCallback( WINDOWPLACEMENT * pwpData, TCHAR * szKey, RECT * prDefault, ConfCallback fpCallback ) : ConfVar( szKey, CONF_MODE_INTERNAL )
{
MessageBox( 0, TEXT( "no const" ), TEXT( "" ), 0 );
m_pwpData = pwpData;
m_prDefault = prDefault;
m_fpCallback = fpCallback;
pwpData->length = sizeof( WINDOWPLACEMENT );
pwpData->flags = 0;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfWinPlaceCallback::ConfWinPlaceCallback( WINDOWPLACEMENT * pwpData, const TCHAR * szKey, RECT * prDefault, ConfCallback fpCallback ) : ConfVar( szKey, CONF_MODE_INTERNAL )
{
m_pwpData = pwpData;
m_prDefault = prDefault;
m_fpCallback = fpCallback;
pwpData->length = sizeof( WINDOWPLACEMENT );
pwpData->flags = 0;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfWinPlaceCallback::Read()
{
if( m_bRead || !szIniPath ) return;
POINT ptMinPosition = { -1, -1 };
POINT ptMaxPosition = { -GetSystemMetrics( SM_CXBORDER ), -GetSystemMetrics( SM_CYBORDER ) };
m_pwpData->length = sizeof( WINDOWPLACEMENT );
m_pwpData->flags = 0;
m_pwpData->ptMinPosition = ptMinPosition;
m_pwpData->ptMaxPosition = ptMaxPosition;
TCHAR szOut[ 111 ] = TEXT( "" );
int iChars = GetPrivateProfileString( SECTION, m_szKey, TEXT( "" ), szOut, 110, szIniPath );
bool bApplyDefault = true;
if( iChars )
{
int iFields = _stscanf(
szOut,
TEXT( "(%u,(%i,%i,%i,%i))" ),
&m_pwpData->showCmd,
&m_pwpData->rcNormalPosition.left,
&m_pwpData->rcNormalPosition.top,
&m_pwpData->rcNormalPosition.right,
&m_pwpData->rcNormalPosition.bottom
);
if( iFields == 5 )
{
bApplyDefault = false;
}
}
if( bApplyDefault )
{
m_pwpData->showCmd = SW_SHOWNORMAL;
m_pwpData->rcNormalPosition = *m_prDefault;
}
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfWinPlaceCallback::Write()
{
// Refresh data
if( m_fpCallback ) m_fpCallback( this );
TCHAR szData[ 111 ] = TEXT( "" );
_stprintf(
szData,
TEXT( "(%u,(%i,%i,%i,%i))" ),
m_pwpData->showCmd,
m_pwpData->rcNormalPosition.left,
m_pwpData->rcNormalPosition.top,
m_pwpData->rcNormalPosition.right,
m_pwpData->rcNormalPosition.bottom
);
WritePrivateProfileString( SECTION, m_szKey, szData, szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfBandInfoCallback::ConfBandInfoCallback( BandInfo * pbiData, TCHAR * szKey, BandInfo * pbiDefault, ConfCallback fpCallback ) : ConfVar( szKey, CONF_MODE_INTERNAL )
{
MessageBox( 0, TEXT( "no const" ), TEXT( "" ), 0 );
m_pbiData = pbiData;
m_pbiDefault = pbiDefault;
m_fpCallback = fpCallback;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfBandInfoCallback::ConfBandInfoCallback( BandInfo * pbiData, const TCHAR * szKey, BandInfo * pbiDefault, ConfCallback fpCallback ) : ConfVar( szKey, CONF_MODE_INTERNAL )
{
m_pbiData = pbiData;
m_pbiDefault = pbiDefault;
m_fpCallback = fpCallback;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfBandInfoCallback::Read()
{
if( m_bRead || !szIniPath ) return;
int iBreak;
int iVisible;
TCHAR szOut[ 91 ] = TEXT( "" );
int iChars = GetPrivateProfileString( SECTION, m_szKey, TEXT( "" ), szOut, 90, szIniPath );
bool bApplyDefault = true;
if( iChars )
{
int iFields = _stscanf(
szOut,
TEXT( "(%i,%i,%i,%i)" ),
&m_pbiData->m_iIndex,
&m_pbiData->m_iWidth,
&iBreak,
&iVisible
);
if( iFields == 4 )
{
m_pbiData->m_bBreak = ( iBreak != 0 );
m_pbiData->m_bVisible = ( iVisible != 0 );
bApplyDefault = false;
}
}
if( bApplyDefault )
{
*m_pbiData = *m_pbiDefault;
}
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfBandInfoCallback::Write()
{
// Refresh data
if( m_fpCallback ) m_fpCallback( this );
TCHAR szData[ 91 ] = TEXT( "" );
_stprintf(
szData,
TEXT( "(%i,%i,%i,%i)" ),
m_pbiData->m_iIndex,
m_pbiData->m_iWidth,
( int )m_pbiData->m_bBreak,
( int )m_pbiData->m_bVisible
);
WritePrivateProfileString( SECTION, m_szKey, szData, szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool ConfBandInfoCallback::Apply( HWND hRebar, int iBandId )
{
const int iOldIndex = ( int )SendMessage( hRebar, RB_IDTOINDEX, iBandId, 0 );
if( iOldIndex == -1 ) return false;
int & iNewIndex = m_pbiData->m_iIndex;
if( iOldIndex != iNewIndex )
{
// Move band
if( !SendMessage( hRebar, RB_MOVEBAND, iOldIndex, iNewIndex ) )
{
return false;
}
}
REBARBANDINFO rbbi;
rbbi.cbSize = sizeof( REBARBANDINFO );
rbbi.fMask = RBBIM_STYLE;
// Get current info
if( !SendMessage( hRebar, RB_GETBANDINFO, iNewIndex, ( LPARAM )&rbbi ) )
{
return false;
}
rbbi.fMask = RBBIM_SIZE | RBBIM_STYLE;
rbbi.cx = m_pbiData->m_iWidth;
if( ( rbbi.fStyle & RBBS_BREAK ) == RBBS_BREAK )
{
if( !m_pbiData->m_bBreak ) rbbi.fStyle -= RBBS_BREAK;
}
else
{
if( m_pbiData->m_bBreak ) rbbi.fStyle |= RBBS_BREAK;
}
// Update info
if( !SendMessage( hRebar, RB_SETBANDINFO, iNewIndex, ( LPARAM )&rbbi ) )
{
return false;
}
// Show/hide band
if( !SendMessage( hRebar, RB_SHOWBAND, iNewIndex, m_pbiData->m_bVisible ? TRUE : FALSE ) )
{
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfString::ConfString( TCHAR * szData, TCHAR * szKey, ConfMode mode, TCHAR * szDefault, int iMaxLen ) : ConfVar( szKey, mode )
{
MessageBox( 0, TEXT( "no const" ), TEXT( "" ), 0 );
m_szData = szData;
m_szDefault = szDefault;
m_iMaxLen = iMaxLen;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfString::ConfString( TCHAR * szData, const TCHAR * szKey, ConfMode mode, TCHAR * szDefault, int iMaxLen ) : ConfVar( szKey, mode )
{
m_szData = szData;
m_szDefault = szDefault;
m_iMaxLen = iMaxLen;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfString::Read()
{
if( m_bRead || !szIniPath ) return;
GetPrivateProfileString( SECTION, m_szKey, m_szDefault, m_szData, m_iMaxLen, szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfString::Write()
{
WritePrivateProfileString( SECTION, m_szKey, m_szData, szIniPath );
m_bRead = true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfCurDir::ConfCurDir( TCHAR * szData, TCHAR * szKey ) : ConfString( szData, szKey, CONF_MODE_INTERNAL, TEXT( "C:\\" ), MAX_PATH )
{
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
ConfCurDir::ConfCurDir( TCHAR * szData, const TCHAR * szKey ) : ConfString( szData, szKey, CONF_MODE_INTERNAL, TEXT( "C:\\" ), MAX_PATH )
{
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfCurDir::Read()
{
ConfString::Read();
// MessageBox( 0, m_szData, TEXT( "CurDir" ), 0 );
// Apply
SetCurrentDirectory( m_szData );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ConfCurDir::Write()
{
// Refresh
GetCurrentDirectory( MAX_PATH, m_szData ); // Note: without trailing slash
// MessageBox( 0, m_szData, TEXT( "CurDir" ), 0 );
ConfString::Write();
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Conf::Init( HINSTANCE hInstance )
{
if( szIniPath ) return;
// Long filename
szIniPath = new TCHAR[ _MAX_PATH ];
TCHAR szFull[ _MAX_PATH ] = TEXT( "" );
TCHAR szDrive[ _MAX_DRIVE ] = TEXT( "" );
TCHAR szDir[ _MAX_DIR ] = TEXT( "" );
GetModuleFileName( hInstance, szFull, _MAX_PATH );
_tsplitpath( szFull, szDrive, szDir, NULL, NULL );
// Convert short to long path
GetLongPathName( szDir, szDir, _MAX_DIR );
// Convert short to long file
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile( szFull, &fd );
// Search last dot
TCHAR * szSearch = fd.cFileName + _tcslen( fd.cFileName ) - 1;
while( ( *szSearch != TEXT( '.' ) ) && ( szSearch > fd.cFileName ) )
{
szSearch--;
}
// Replace extension
_tcscpy( szSearch, TEXT( ".ini" ) );
// Copy full filename
_sntprintf( szIniPath, _MAX_PATH, TEXT( "%s%s%s" ), szDrive, szDir, fd.cFileName );
// Read all
map<TCHAR *, ConfVar *>::iterator iter = conf_map->begin();
while( iter != conf_map->end() )
{
iter->second->Read();
iter++;
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Conf::Write()
{
if( !szIniPath ) return;
map<TCHAR *, ConfVar *>::iterator iter = conf_map->begin();
while( iter != conf_map->end() )
{
iter->second->Write();
iter++;
}
}

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

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 );
}

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

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;
}

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

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;
}

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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

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 );
}

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

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;
}

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

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;
}

View File

@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////////
// 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_GEN_PLUGIN_H
#define PA_GEN_PLUGIN_H
#include "Global.h"
#include "Plugin.h"
#include "Winamp/Gen.h"
#include <vector>
using namespace std;
typedef winampGeneralPurposePlugin * ( * WINAMP_GEN_GETTER )( void );
class GenPlugin;
extern vector <GenPlugin *> gen_plugins;
////////////////////////////////////////////////////////////////////////////////
/// Winamp general purpose plugin wrapper
////////////////////////////////////////////////////////////////////////////////
class GenPlugin : public Plugin
{
public:
GenPlugin( TCHAR * szDllpath, bool bKeepLoaded );
bool Load();
bool Unload();
TCHAR * GetTypeString() { return TEXT( "General" ); }
int GetTypeStringLen() { return 7; }
PluginType GetType() { return PLUGIN_TYPE_GEN; }
inline bool IsActive() { return IsLoaded(); }
bool Config();
inline bool AllowRuntimeUnload() { return ( iHookerIndex == -1 ) || ( iHookerIndex == iWndprocHookCounter - 1 ); }
private:
winampGeneralPurposePlugin * plugin;
};
#endif // PA_GEN_PLUGIN_H

View File

@ -0,0 +1,117 @@
////////////////////////////////////////////////////////////////////////////////
// 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_GLOBAL_H
#define PA_GLOBAL_H
// #include "ide_devcpp/Plainamp_Private.h"
#ifdef UNICODE
# define PA_UNICODE
#else
# ifdef _UNICODE
# define PA_UNICODE
# endif
#endif
// For GetLongPathName
#if _WIN32_WINDOWS < 0x0410
# undef _WIN32_WINDOWS
# define _WIN32_WINDOWS 0x0410
#endif
#define WIN32_LEAN_AND_MEAN
/*
#ifndef WINVER
# define WINVER 0x0500
#else
# if (WINVER < 0x0500)
# undef WINVER
# define WINVER 0x0500
# endif
#endif
*/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#ifndef _WIN32_IE
# define _WIN32_IE 0x0400
#else
# if (_WIN32_IE < 0x0400)
# undef _WIN32_IE
# define _WIN32_IE 0x0400
# endif
#endif
#include <commctrl.h>
extern HINSTANCE g_hInstance;
extern TCHAR * szHomeDir;
extern int iHomeDirLen;
extern TCHAR * szPluginDir;
extern int iPluginDirLen;
/*
inline int abs( int x )
{
return ( x < 0 ) ? -x : x;
}
*/
inline int MIN( int a, int b )
{
return ( a < b ) ? a : b;
}
inline int MAX( int a, int b )
{
return ( a > b ) ? a : b;
}
// Typo help
#define UNIT UINT
#define UINT_PRT UINT_PTR
struct TextCompare
{
bool operator()( const TCHAR * a, const TCHAR * b ) const
{
return _tcscmp( a, b ) < 0;
}
};
#endif // PA_GLOBAL_H

View File

@ -0,0 +1,28 @@
////////////////////////////////////////////////////////////////////////////////
// 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_GLOBAL_VERSION_H
#define PA_GLOBAL_VERSION_H
#define FILE_DESCRIPTION "Plainamp"
#define VER_STRING "0.2.3.1"
#define PLAINAMP_TITLE TEXT( FILE_DESCRIPTION )
#define PLAINAMP_VERSION TEXT( VER_STRING )
#define PLAINAMP_LONG_TITLE PLAINAMP_TITLE TEXT( " " ) PLAINAMP_VERSION
#endif // PA_GLOBAL_VERSION_H

View File

@ -0,0 +1,477 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Input.h"
#include "Console.h"
#include "Status.h"
#include "Playback.h"
#include "InputPlugin.h"
#include "VisPlugin.h"
#include "DspPlugin.h"
#include "VisCache.h"
#include "Output.h"
/*
#define FIXED_POINT 16
#include "kiss_fft/kiss_fftr.h"
*/
#include "fftw3/fftw3.h"
#include <math.h>
// #define SKIPPY
#ifndef SKIPPY
# define MAX_DATA_FPS ( 1000 / 12 ) // in_mp3 gives new vis data every 13 ms, so 12 leaves a little space
#else
# define MAX_DATA_FPS ( 1000 / 24 ) // will skip every second frame
#endif
#ifdef SKIPPY
bool bLastSkipped = true;
#endif
int iSpecChannels = 2;
int iWaveChannels = 2;
/*
kiss_fft_cfg kiss = { 0 };
bool bKissInitDone = false;
*/
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int dsp_isactive()
{
////////////////////////////////////////////////////////////////////////////////
DspLock.Enter();
////////////////////////////////////////////////////////////////////////////////
int res = ( active_dsp_count > 0 );
////////////////////////////////////////////////////////////////////////////////
DspLock.Leave();
////////////////////////////////////////////////////////////////////////////////
return res;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int dsp_dosamples( short int * samples, int numsamples, int bps, int nch, int srate )
{
int num = numsamples;
////////////////////////////////////////////////////////////////////////////////
DspLock.Enter();
////////////////////////////////////////////////////////////////////////////////
for( int i = 0; i < active_dsp_count; i++ )
{
// Process
num = active_dsp_mods[ i ]->mod->ModifySamples(
active_dsp_mods[ i ]->mod,
samples,
numsamples,
bps,
nch,
srate
);
}
////////////////////////////////////////////////////////////////////////////////
DspLock.Leave();
////////////////////////////////////////////////////////////////////////////////
return num;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void SAVSAInit( int maxlatency_in_ms, int srate )
{
////////////////////////////////////////////////////////////////////////////////
VisCache::Create();
VisCache::EnsureLatency( maxlatency_in_ms );
VisCache::EnsureDataFps( MAX_DATA_FPS );
VisCache::Clean();
////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void SAVSADeInit()
{
// TODO
// Console::Append( TEXT( "SAVSADeInit" ) );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void SAAddPCMData( void * PCMData, int nch, int bps, int timestamp )
{
// TODO
// Console::Append( TEXT( "SAAddPCMData" ) );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int SAGetMode()
{
// TODO
// Console::Append( TEXT( "SAGetMode" ) );
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void SAAdd( void * data, int timestamp, int csa )
{
// TODO
// Console::Append( TEXT( "SAAdd" ) );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VSAAddPCMData( void * PCMData, int nch, int bps, int timestamp )
{
// TODO
// Console::Append( TEXT( "VSAAddPCMData" ) );
#ifdef SKIPPY
if( bLastSkipped )
bLastSkipped = false;
else
{
// Skip
bLastSkipped = true;
return;
}
#endif
////////////////////////////////////////////////////////////////////////////////
bool bVisLockLeft = false;
VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
if( active_vis_count )
{
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
bVisLockLeft = true;
////////////////////////////////////////////////////////////////////////////////
VisCache::NextFrame();
VisCache::SetWriteTime( timestamp );
VisCache::SetReadTime( active_input_plugin->plugin->GetOutputTime() );
short * source = ( short * )PCMData;
// Waveform
static unsigned char wave_left[ 576 ];
static unsigned char wave_right[ 576 ];
if( nch < 2 )
{
// Mono
for( int i = 0; i < 576; i++ )
{
wave_left[ i ] = ( source[ i ] >> 8 );
}
VisCache::PutWaveLeft( wave_left );
}
else
{
int i;
// Stereo or more
for( i = 0; i < 576; i++ )
{
wave_left [ i ] = ( source[ i * nch ] >> 8 );
wave_right[ i ] = ( source[ i * nch + 1 ] >> 8 );
}
VisCache::PutWaveLeft( wave_left );
VisCache::PutWaveRight( wave_right );
}
// TODO: Much to optimize!
// Spectrum
static unsigned char spec_left[ 576 ];
static unsigned char spec_right[ 576 ];
static fftw_complex * in = NULL;
static fftw_complex * out = NULL;
if( !in )
{
in = ( fftw_complex * )fftw_malloc( 576 * sizeof( fftw_complex ) );
out = ( fftw_complex * )fftw_malloc( 576 * sizeof( fftw_complex ) );
}
static const double factor = 1.0 / 65536.0 / sqrt( 2.0 );
// Put left
int index = 0;
for( int i = 0; i < 576; i++ )
{
in[ i ][ 0 ] = source[ index += nch ];
in[ i ][ 1 ] = 0.0;
}
// Init FFT
fftw_plan p = fftw_plan_dft_1d( 576, in, out, FFTW_FORWARD, FFTW_ESTIMATE );
// Run left
fftw_execute( p );
// Get left
for( int i = 0; i < 576; i++ )
{
if( i & 1 )
{
spec_left [ i ] = spec_left [ i - 1 ];
continue;
}
const double re = out[ i >> 1 ][ 0 ];
const double im = out[ i >> 1 ][ 1 ];
const double root = sqrt( re*re + im*im );
const double final = 160.0 * log10( 1.0 + root * factor );
spec_left[ i ] = ( final < 255.0 ) ? ( unsigned char )final : 255;
}
VisCache::PutSpecLeft( spec_left );
if( nch > 1 )
{
// Put right
index = 1;
for( int i = 0; i < 576; i++ )
{
in[ i ][ 0 ] = source[ index += nch ];
}
// Run right
fftw_execute( p );
// Get right
for( int i = 0; i < 576; i++ )
{
if( i & 1 )
{
spec_right[ i ] = spec_right[ i - 1 ];
continue;
}
const double re = out[ i >> 1 ][ 0 ];
const double im = out[ i >> 1 ][ 1 ];
const double root = sqrt( re*re + im*im );
const double final = 160.0 * log10( 1.0 + root * factor );
spec_right[ i ] = ( final < 255.0 ) ? ( unsigned char )final : 255;
}
VisCache::PutSpecRight( spec_right );
}
// Cleanup FFT
fftw_destroy_plan( p );
// fftw_free(in);
// fftw_free(out);
}
////////////////////////////////////////////////////////////////////////////////
if( bVisLockLeft ) VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
for( int i = 0; i < active_vis_count; i++ )
{
active_vis_mods[ i ]->bAllowRender = true;
}
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int VSAGetMode( int * specNch, int * waveNch )
{
iSpecChannels = 0;
iWaveChannels = 0;
////////////////////////////////////////////////////////////////////////////////
VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
for( int i = 0; i < active_vis_count; i++ )
{
const int iSpec = active_vis_mods[ i ]->mod->spectrumNch;
const int iWave = active_vis_mods[ i ]->mod->waveformNch;
if( iSpec > iSpecChannels ) iSpecChannels = iSpec;
if( iWave > iWaveChannels ) iWaveChannels = iWave;
}
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
*specNch = iSpecChannels;
*waveNch = iWaveChannels;
return 1;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VSAAdd( void * data, int timestamp )
{
#ifdef SKIPPY
if( bLastSkipped )
bLastSkipped = false;
else
{
// Skip
bLastSkipped = true;
return;
}
#endif
////////////////////////////////////////////////////////////////////////////////
bool bVisLockLeft = false;
VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
if( active_vis_count )
{
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
bVisLockLeft = true;
////////////////////////////////////////////////////////////////////////////////
VisCache::NextFrame();
VisCache::SetWriteTime( timestamp );
VisCache::SetReadTime( active_input_plugin->plugin->GetOutputTime() );
unsigned char * source = ( unsigned char * )data;
if( iSpecChannels > 0 )
{
VisCache::PutSpecLeft( source );
source += 576;
}
if( iSpecChannels > 1 )
{
VisCache::PutSpecRight( source );
source += 576;
}
if( iWaveChannels > 0 )
{
VisCache::PutWaveLeft( source );
source += 576;
}
if( iWaveChannels > 1 )
{
VisCache::PutWaveRight( source );
}
}
////////////////////////////////////////////////////////////////////////////////
if( bVisLockLeft ) VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
for( int i = 0; i < active_vis_count; i++ )
{
active_vis_mods[ i ]->bAllowRender = true;
}
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VSASetInfo( int nch, int srate )
{
// TODO
////////////////////////////////////////////////////////////////////////////////
VisCache::Create();
VisCache::EnsureDataFps( MAX_DATA_FPS );
VisCache::Clean();
////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void SetInfo( int bitrate, int srate, int stereo, int synched )
{
// TODO
static int last_valid_srate = 0;
if( bitrate < 0 ) return;
if( srate < 0 )
srate = last_valid_srate;
else
last_valid_srate = srate;
TCHAR szBuffer[ 5000 ] = TEXT( "" );
_stprintf( szBuffer, TEXT( " %i kbps, %i kHz" ), bitrate, srate );
StatusUpdate( szBuffer );
}

View File

@ -0,0 +1,28 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Global.h"
int dsp_isactive();
int dsp_dosamples( short int * samples, int numsamples, int bps, int nch, int srate );
void SAVSAInit( int maxlatency_in_ms, int srate );
void SAVSADeInit();
void SAAddPCMData( void * PCMData, int nch, int bps, int timestamp );
int SAGetMode();
void SAAdd(void * data, int timestamp, int csa );
void VSAAddPCMData( void * PCMData, int nch, int bps, int timestamp );
int VSAGetMode( int * specNch, int * waveNch );
void VSAAdd( void * data, int timestamp );
void VSASetInfo( int nch, int srate );
void SetInfo( int bitrate, int srate, int stereo, int synched );

View File

@ -0,0 +1,374 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "InputPlugin.h"
#include "Console.h"
#include "Main.h"
#include "Input.h"
#include "Unicode.h"
map <TCHAR *, InputPlugin *, TextCompare> ext_map; // extern
vector <InputPlugin *> input_plugins; // extern
InputPlugin * active_input_plugin = NULL; // extern
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
InputPlugin::InputPlugin( TCHAR * szDllpath, bool bKeepLoaded ) : Plugin( szDllpath )
{
iHookerIndex = -1;
szFilters = NULL;
iFiltersLen = 0;
plugin = NULL;
if( !Load() )
{
return;
}
if( !bKeepLoaded )
{
Unload();
}
input_plugins.push_back( this );
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
InputPlugin::~InputPlugin()
{
if( szFilters ) delete [] szFilters;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
bool InputPlugin::Load()
{
if( IsLoaded() ) return true;
// (1) Load DLL
hDLL = LoadLibrary( GetFullpath() );
if( !hDLL ) return false;
// (2) Find export
WINAMP_INPUT_GETTER winampGetInModule2 =
( WINAMP_INPUT_GETTER )GetProcAddress( hDLL, "winampGetInModule2" );
if( winampGetInModule2 == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (3) Get module
plugin = winampGetInModule2();
if( plugin == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (4) Process module
plugin->hDllInstance = hDLL;
plugin->hMainWindow = WindowMain;
plugin->SAVSAInit = SAVSAInit;
plugin->SAVSADeInit = SAVSADeInit;
plugin->SAAddPCMData = SAAddPCMData;
plugin->SAGetMode = SAGetMode;
plugin->SAAdd = SAAdd;
plugin->VSAAddPCMData = VSAAddPCMData;
plugin->VSAGetMode = VSAGetMode;
plugin->VSAAdd = VSAAdd;
plugin->VSASetInfo = VSASetInfo;
plugin->dsp_dosamples = dsp_dosamples;
plugin->dsp_isactive = dsp_isactive;
plugin->SetInfo = SetInfo;
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;
if( !strnicmp( plugin->description, "mpeg(layer1-3/ct aac+/dolby aac) ", 33 ) )
{
plugin->description += ( 33 - 5 );
memcpy( plugin->description, "MPEG", 4 * sizeof( char ) );
}
}
iNameLen = ( int )strlen( plugin->description );
szName = new TCHAR[ iNameLen + 1 ];
ToTchar( szName, plugin->description, iNameLen );
szName[ iNameLen ] = TEXT( '\0' );
}
// (5) 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++;
}
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Loading <%s>, %s" ), GetFilename(), szName );
Console::Append( szBuffer );
Integrate();
// 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 InputPlugin::Integrate()
{
if( !IsLoaded() ) return false;
// (6) Build filter
// (6a) First pass: get needed buffer length
int needed = 0;
int len = 0;
bool even = false;
char * walk = plugin->FileExtensions;
while( ( len = ( int )strlen( walk ) ) > 0 )
{
len++; // For '\0'
if( even )
{
// Extensions e.g. "mp3;mp2;mp1"
// Worst case "a;b;c" (5) --> "*.a;*.b;*.c" (11)
needed += ( 3 * len );
}
else
{
// Filter name e.g. "MPEG audio files"
needed += len;
}
even = !even;
walk += len;
}
szFilters = new TCHAR[ needed + 1 ];
TCHAR * walk_out = szFilters;
// (6b) Once again with copy
walk = plugin->FileExtensions;
even = false;
while( true )
{
// Check extensions
char * start_filter = walk;
const int len_filter = ( int )strlen( walk );
if( len_filter == 0 )
{
// End reached
break;
}
walk += len_filter + 1;
// Check filter name
char * start_display = walk;
int len_display = ( int )strlen( walk );
if( len_display == 0 )
{
break;
}
walk += ++len_display;
// Append filter name
ToTchar( walk_out, start_display, len_display );
TCHAR szBuffer[ 5000 ];
*(walk_out + len_display) = TEXT( '\0' );
_stprintf( szBuffer, TEXT( " %s" ), walk_out );
Console::Append( szBuffer );
walk_out += len_display;
// Convert and append extensions
char * walk_filter = start_filter;
char * last_filter = start_filter;
int len;
while( true )
{
if( ( *walk_filter == ';' ) || ( *walk_filter == '\0' ) )
{
len = ( walk_filter - last_filter );
if( len < 1 )
{
break;
}
// Add extension to map
TCHAR * szExt = new TCHAR[ len + 1 ];
ToTchar( szExt, last_filter, len );
szExt[ len ] = TEXT( '\0' );
_tcslwr( szExt );
ext_map.insert( pair<TCHAR *, InputPlugin *>( szExt, this ) );
// Append extension as "*.ext[;\0]"
len++; // Also copy ';' and '\0'
memcpy( walk_out, TEXT( "*." ), 2 * sizeof( TCHAR ) );
walk_out += 2;
ToTchar( walk_out, last_filter, len );
walk_out += len;
// Any more extensions?
if( *walk_filter == '\0' )
{
break;
}
last_filter = walk_filter + 1;
}
walk_filter++;
}
if( *walk == '\0' )
{
*walk_out = TEXT( '\0' );
iFiltersLen = walk_out - szFilters;
break;
}
}
Console::Append( TEXT( " " ) );
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
bool InputPlugin::DisIntegrate()
{
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
bool InputPlugin::Unload()
{
if( !IsLoaded() ) return true;
DisIntegrate();
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Unloading <%s>" ), GetFilename() );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
// Quit
if( plugin )
{
if( plugin->Quit ) plugin->Quit();
plugin->outMod = NULL;
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 InputPlugin::About( HWND hParent )
{
if( !plugin ) return false;
if( !plugin->About ) return false;
plugin->About( hParent );
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
bool InputPlugin::Config( HWND hParent )
{
if( !plugin ) return false;
if( !plugin->Config ) return false;
plugin->Config( hParent );
// TODO: File extension could have changed (e.g. in_mp3)
// So we have to process ext_map here...
return true;
}

View File

@ -0,0 +1,94 @@
////////////////////////////////////////////////////////////////////////////////
// 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_INPUT_PLUGIN_H
#define PA_INPUT_PLUGIN_H
#include "Global.h"
#include "Plugin.h"
#include "Playback.h"
#include "Playlist.h"
#include "Winamp/In2.h"
#include <map>
#include <vector>
using namespace std;
typedef In_Module * ( * WINAMP_INPUT_GETTER )( void );
class InputPlugin;
extern map <TCHAR *, InputPlugin *, TextCompare> ext_map;
extern vector <InputPlugin *> input_plugins;
extern InputPlugin * active_input_plugin;
////////////////////////////////////////////////////////////////////////////////
/// Winamp input plugin wrapper
////////////////////////////////////////////////////////////////////////////////
class InputPlugin : public Plugin
{
public:
InputPlugin( TCHAR * szDllpath, bool bKeepLoaded );
~InputPlugin();
bool Load();
bool Unload();
TCHAR * GetTypeString() { return TEXT( "Input" ); }
int GetTypeStringLen() { return 5; }
PluginType GetType() { return PLUGIN_TYPE_INPUT; }
inline bool IsActive() { return false; }
bool About( HWND hParent );
bool Config( HWND hParent );
private:
TCHAR * szFilters;
int iFiltersLen;
In_Module * plugin;
bool Integrate();
bool DisIntegrate();
// TODO
friend bool OpenPlay( TCHAR * szFilename, int iNumber );
friend bool Playback_PrevOrNext( bool bPrevOrNext );
friend bool Playback::Play();
friend bool Playback::Pause();
friend bool Playback::Stop();
friend bool Playback::UpdateSeek();
friend int Playback::PercentToMs( float fPercent );
friend bool Playback::SeekPercent( float fPercent );
friend bool SeekRelative( int ms );
friend void Playback_Volume_Set( int iVol );
friend bool Playback::Pan::Set( int iPan );
friend void Playback_Eq_Set( int iPresetIndex );
friend void AddFiles();
friend void VSAAdd( void * data, int timestamp );
friend void VSAAddPCMData( void * PCMData, int nch, int bps, int timestamp );
friend int Playlist::GetTitle( int iIndex, char * szAnsiTitle, int iChars );
};
#endif // PA_INPUT_PLUGIN_H

View File

@ -0,0 +1,16 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Lock.h"
// Code moved to <Lock.h> for inlining!

View File

@ -0,0 +1,111 @@
////////////////////////////////////////////////////////////////////////////////
// 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_LOCK_H
#define PA_LOCK_H
#include "Global.h"
// INFO: http://www.devarticles.com/c/a/Cplusplus/Multithreading-in-C/3/
// #define LOCK_USES_MUTEX
////////////////////////////////////////////////////////////////////////////////
/// Lock for thread synchronization
////////////////////////////////////////////////////////////////////////////////
class Lock
{
public:
Lock( TCHAR * szName );
~Lock();
void Enter();
void Leave();
private:
#ifndef LOCK_USES_MUTEX
CRITICAL_SECTION * m_pCrit;
#else
HANDLE hLock;
#endif
};
////////////////////////////////////////////////////////////////////////////////
/// Creates a new named lock.
/// Note: Don't use the same name for several locks
////////////////////////////////////////////////////////////////////////////////
inline Lock::Lock( TCHAR * szName )
{
#ifndef LOCK_USES_MUTEX
m_pCrit = new CRITICAL_SECTION;
InitializeCriticalSection( m_pCrit );
#else
hLock = CreateMutex( NULL, TRUE, szName );
ReleaseMutex( hLock );
#endif
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
inline Lock::~Lock()
{
#ifndef LOCK_USES_MUTEX
DeleteCriticalSection( m_pCrit );
delete [] m_pCrit;
#else
CloseHandle( hLock );
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Closes lock.
////////////////////////////////////////////////////////////////////////////////
inline void Lock::Enter()
{
#ifndef LOCK_USES_MUTEX
EnterCriticalSection( m_pCrit );
#else
WaitForSingleObject( hLock, INFINITE );
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Opens lock.
////////////////////////////////////////////////////////////////////////////////
inline void Lock::Leave()
{
#ifndef LOCK_USES_MUTEX
LeaveCriticalSection( m_pCrit );
#else
ReleaseMutex( hLock );
#endif
}
#endif // PA_LOCK_H

View File

@ -0,0 +1,757 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Main.h"
#include "GlobalVersion.h"
#include "Playlist.h"
#include "Console.h"
#include "Status.h"
#include "Rebar.h"
#include "Playback.h"
#include "PluginManager.h"
#include "DspModule.h"
#include "VisModule.h"
#include "InputPlugin.h"
#include "OutputPlugin.h"
#include "InputPlugin.h"
#include "AddDirectory.h"
#include "AddFiles.h"
#include "Winamp.h"
#include "Winamp/wa_ipc.h"
#include "Config.h"
#include <shellapi.h>
#define CLASSNAME_MAIN TEXT( "Winamp v1.x" )
#define MAIN_TITLE PLAINAMP_LONG_TITLE
#define MAIN_WIDTH 731
#define MAIN_HEIGHT 562
HWND WindowMain = NULL; // extern
HMENU main_context_menu = NULL; // extern
HMENU play_context_menu = NULL;
HMENU opts_context_menu = NULL;
HMENU playback_context_menu = NULL;
LRESULT CALLBACK WndprocMain( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
WINDOWPLACEMENT WinPlaceMain;
void WinPlaceMainCallback( ConfVar * var )
{
if( !IsWindow( WindowMain ) ) return;
GetWindowPlacement( WindowMain, &WinPlaceMain );
}
const int cxScreen = GetSystemMetrics( SM_CXFULLSCREEN );
const int cyScreen = GetSystemMetrics( SM_CYFULLSCREEN );
RECT rMainDefault = {
( cxScreen - MAIN_WIDTH ) / 2,
( cyScreen - MAIN_HEIGHT ) / 2,
( cxScreen - MAIN_WIDTH ) / 2 + MAIN_WIDTH,
( cyScreen - MAIN_HEIGHT ) / 2 + MAIN_HEIGHT
};
ConfWinPlaceCallback cwpcWinPlaceMain(
&WinPlaceMain,
TEXT( "WinPlaceMain" ),
&rMainDefault,
WinPlaceMainCallback
);
bool bMinimizeToTray;
ConfBool cbMinimizeToTray( &bMinimizeToTray, TEXT( "MinimizeToTray" ), CONF_MODE_PUBLIC, true );
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool BuildMainWindow()
{
// Register class
WNDCLASS wc = {
0, // UINT style
WndprocMain, // WNDPROC lpfnWndProc
0, // int cbClsExtra
0, // int cbWndExtra
g_hInstance, // HINSTANCE hInstance
LoadIcon( g_hInstance, TEXT( "IDI_ICON1" ) ), // HICON hIcon
LoadCursor( NULL, IDC_ARROW ), // HCURSOR hCursor
( HBRUSH )COLOR_WINDOW, // HBRUSH hbrBackground
NULL, // LPCTSTR lpszMenuName
CLASSNAME_MAIN // LPCTSTR lpszClassName
};
if( !RegisterClass( &wc ) ) return false;
// Create window
WindowMain = CreateWindowEx(
WS_EX_WINDOWEDGE, // DWORD dwExStyle
CLASSNAME_MAIN, // LPCTSTR lpClassName
MAIN_TITLE, // LPCTSTR lpWindowName
WS_OVERLAPPED | // DWORD dwStyle
// WS_VISIBLE | //
WS_CLIPCHILDREN | //
WS_BORDER | //
WS_SYSMENU | //
WS_THICKFRAME | //
WS_MINIMIZEBOX | //
WS_MAXIMIZEBOX, //
rMainDefault.left, // int x
rMainDefault.top, // int y
rMainDefault.right - rMainDefault.left, // int nWidth
rMainDefault.bottom - rMainDefault.top, // int nHeight
NULL, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
if( !WindowMain )
{
UnregisterClass( CLASSNAME_MAIN, g_hInstance );
return false;
}
// Build context menu
HMENU main_menu = CreateMenu();
HMENU plainamp_menu = CreatePopupMenu();
HMENU playback_menu = CreatePopupMenu();
HMENU playlist_menu = CreatePopupMenu();
HMENU windows_menu = CreatePopupMenu();
// Plainamp
AppendMenu( plainamp_menu, MF_STRING, WINAMP_OPTIONS_PREFS, TEXT( "Preferences \tCtrl+P" ) );
AppendMenu( plainamp_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
AppendMenu( plainamp_menu, MF_STRING, WINAMP_HELP_ABOUT, TEXT( "&About\tCtrl+F1" ) );
AppendMenu( plainamp_menu, MF_STRING, WINAMP_FILE_QUIT, TEXT( "&Exit \tAlt+F4" ) );
// Playback
AppendMenu( playback_menu, MF_STRING, WINAMP_BUTTON1, TEXT( "Pre&vious \tZ" ) );
AppendMenu( playback_menu, MF_STRING, WINAMP_BUTTON2, TEXT( "&Play\tX" ) );
AppendMenu( playback_menu, MF_STRING, WINAMP_BUTTON3, TEXT( "P&ause\tC" ) );
AppendMenu( playback_menu, MF_STRING, WINAMP_BUTTON4, TEXT( "&Stop\tV" ) );
AppendMenu( playback_menu, MF_STRING, WINAMP_BUTTON5, TEXT( "&Next\tB" ) );
// Playlist
AppendMenu( playlist_menu, MF_STRING, ID_PE_OPEN, TEXT( "&Open\tCtrl+O" ) );
AppendMenu( playlist_menu, MF_STRING, ID_PE_SAVEAS, TEXT( "&Save as\tCtrl+S" ) );
AppendMenu( playlist_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
AppendMenu( playlist_menu, MF_STRING, WINAMP_FILE_PLAY, TEXT( "Add &files\tL" ) );
AppendMenu( playlist_menu, MF_STRING, WINAMP_FILE_DIR, TEXT( "Add &directory\tShift+L" ) );
AppendMenu( playlist_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
AppendMenu( playlist_menu, MF_STRING, PLAINAMP_PL_REM_SEL, TEXT( "Remove selected\tDel" ) );
AppendMenu( playlist_menu, MF_STRING, PLAINAMP_PL_REM_CROP, TEXT( "Remove unselected \tCtrl+Del" ) );
AppendMenu( playlist_menu, MF_STRING, ID_PE_CLEAR, TEXT( "Remove all\tCtrl+Shift+Del" ) );
AppendMenu( playlist_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
AppendMenu( playlist_menu, MF_STRING, ID_PE_SELECTALL, TEXT( "Select &all\tCtrl+A" ) );
AppendMenu( playlist_menu, MF_STRING, ID_PE_NONE, TEXT( "Select &zero\tCtrl+Shift+A" ) );
AppendMenu( playlist_menu, MF_STRING, ID_PE_INVERT, TEXT( "Select &invert\tCtrl+I" ) );
// Windows
AppendMenu( windows_menu, MF_STRING, MENU_MAIN_WINDOWS_CONSOLE, TEXT( "&Console" ) );
AppendMenu( windows_menu, MF_STRING, MENU_MAIN_WINDOWS_MANAGER, TEXT( "Plugin &Manager" ) );
// Main
AppendMenu( main_menu, MF_STRING | MF_POPUP, ( UINT_PTR )plainamp_menu, TEXT( "&Plainamp" ) );
AppendMenu( main_menu, MF_STRING | MF_POPUP, ( UINT_PTR )playback_menu, TEXT( "Play&back" ) );
AppendMenu( main_menu, MF_STRING | MF_POPUP, ( UINT_PTR )playlist_menu, TEXT( "Play&list" ) );
AppendMenu( main_menu, MF_STRING | MF_POPUP, ( UINT_PTR )windows_menu, TEXT( "&Windows" ) );
SetMenu( WindowMain, main_menu );
////////////////////////////////////////////////////////////////////////////////
main_context_menu = CreatePopupMenu();
AppendMenu( main_context_menu, MF_STRING, WINAMP_HELP_ABOUT, TEXT( "Plainamp" ) );
AppendMenu( main_context_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
play_context_menu = CreatePopupMenu();
AppendMenu( play_context_menu, MF_STRING, WINAMP_FILE_PLAY, TEXT( "Files \tL" ) );
AppendMenu( play_context_menu, MF_STRING, WINAMP_FILE_DIR, TEXT( "Folder \tShift+L" ) );
AppendMenu( main_context_menu, MF_STRING | MF_POPUP, ( UINT_PTR )play_context_menu, TEXT( "Play" ) );
AppendMenu( main_context_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
AppendMenu( main_context_menu, MF_STRING | MF_DISABLED | MF_GRAYED | MF_CHECKED, WINAMP_MAIN_WINDOW, TEXT( "Main Window\tAlt+W" ) );
AppendMenu( main_context_menu, MF_STRING | MF_DISABLED | MF_GRAYED | MF_CHECKED, WINAMP_OPTIONS_PLEDIT, TEXT( "Playlist Editor\tAlt+E" ) );
AppendMenu( main_context_menu, MF_STRING | MF_DISABLED | MF_GRAYED, WINAMP_OPTIONS_EQ, TEXT( "Equalizer\tAlt+G" ) );
AppendMenu( main_context_menu, MF_STRING | MF_DISABLED | MF_GRAYED, WINAMP_OPTIONS_VIDEO, TEXT( "Video\tAlt+V" ) );
AppendMenu( main_context_menu, MF_STRING, PLAINAMP_TOGGLE_CONSOLE, TEXT( "Console" ) );
AppendMenu( main_context_menu, MF_STRING, PLAINAMP_TOGGLE_MANAGER, TEXT( "Plugin Manager" ) );
/*
AppendMenu( main_context_menu, MF_STRING | MF_DISABLED | MF_GRAYED, MENU_MAIN_CONTEXT_MANAGER, TEXT( "Plugin Manager" ) );
AppendMenu( main_context_menu, MF_STRING | MF_DISABLED | MF_GRAYED, MENU_MAIN_CONTEXT_CONSOLE, TEXT( "Console" ) );
*/
AppendMenu( main_context_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
opts_context_menu = CreatePopupMenu();
AppendMenu( opts_context_menu, MF_STRING, WINAMP_OPTIONS_PREFS, TEXT( "Preferences \tCtrl+P" ) );
AppendMenu( main_context_menu, MF_STRING | MF_POPUP, ( UINT_PTR )opts_context_menu, TEXT( "Options" ) );
playback_context_menu = CreatePopupMenu();
AppendMenu( playback_context_menu, MF_STRING, WINAMP_BUTTON1, TEXT( "Previous \tZ" ) );
AppendMenu( playback_context_menu, MF_STRING, WINAMP_BUTTON2, TEXT( "Play\tX" ) );
AppendMenu( playback_context_menu, MF_STRING, WINAMP_BUTTON3, TEXT( "Pause\tC" ) );
AppendMenu( playback_context_menu, MF_STRING, WINAMP_BUTTON4, TEXT( "Stop\tV" ) );
AppendMenu( playback_context_menu, MF_STRING, WINAMP_BUTTON5, TEXT( "Next\tB" ) );
AppendMenu( main_context_menu, MF_STRING | MF_POPUP, ( UINT_PTR )playback_context_menu, TEXT( "Playback" ) );
AppendMenu( main_context_menu, MF_SEPARATOR | MF_DISABLED | MF_GRAYED, ( UINT_PTR )-1, NULL );
AppendMenu( main_context_menu, MF_STRING, WINAMP_FILE_QUIT, TEXT( "Exit" ) );
Toolbar::Create();
BuildMainStatus();
Playlist::Create();
SetWindowPlacement( WindowMain, &WinPlaceMain );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void About( HWND hParent )
{
// For info goto
// http://predef.sourceforge.net/precomp.html
TCHAR szBuildDetails[ 1000 ] = "";
#ifdef __GNUC__
_stprintf( szBuildDetails,
TEXT( "\n\n\nGNU GCC " __VERSION__ "\n" __DATE__ )
);
#else
# ifdef _MSC_VER
_stprintf(
szBuildDetails,
TEXT( "\n\n\nMicrosoft Visual C++ %i.%i\n" __DATE__ ),
_MSC_VER / 100 - 6,
( _MSC_VER % 100 ) / 10
);
# endif
#endif
TCHAR szBuffer[ 1000 ];
_stprintf(
szBuffer,
PLAINAMP_LONG_TITLE TEXT( "\n"
"\n"
"Copyright © 2005 Sebastian Pipping \n"
"<webmaster@hartwork.org>\n"
"\n"
"--> http://www.hartwork.org"
"%s"
),
szBuildDetails
);
MessageBox(
hParent,
szBuffer,
TEXT( "About" ),
MB_ICONINFORMATION
);
}
#define TRAY_MAIN_ID 13
#define TRAY_MSG ( WM_USER + 1 )
NOTIFYICONDATA nid;
bool AddTrayIcon( HWND hwnd )
{
ZeroMemory( &nid, sizeof( NOTIFYICONDATA ) );
nid.cbSize = sizeof( NOTIFYICONDATA );
nid.hWnd = hwnd;
nid.uID = TRAY_MAIN_ID;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.uCallbackMessage = TRAY_MSG;
nid.hIcon = LoadIcon( g_hInstance, TEXT( "IDI_ICON1" ) );
_tcscpy( nid.szTip, TEXT( "Plainamp" ) );
return ( Shell_NotifyIcon( NIM_ADD, &nid ) != 0 );
}
void RemoveTrayIcon()
{
Shell_NotifyIcon( NIM_DELETE, &nid );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndprocMain( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
// Tool windows are hidden on minimize/re-shown on restore
static bool bConsoleTodo = false;
static bool bManagerTodo = false;
static bool bRemoveIcon = false;
switch( message )
{
case WM_SETFOCUS:
// To re-"blue"
SetFocus( WindowPlaylist );
break;
case WM_CREATE:
// Note: [WindowMain] is not valid yet but [hwnd] is!
Console::Create();
PluginManager::Build();
break;
case WM_NOTIFY:
{
NMHDR * hdr = ( NMHDR * )lp;
switch( hdr->code )
{
case LVN_GETDISPINFO:
{
LV_DISPINFO * lpdi = ( LV_DISPINFO * )lp;
playlist->Fill( lpdi->item );
}
return 0;
/*
case LVN_ODCACHEHINT:
{
LPNMLVCACHEHINT lpCacheHint = (LPNMLVCACHEHINT)lParam;
/
This sample doesn't use this notification, but this is sent when the
ListView is about to ask for a range of items. On this notification,
you should load the specified items into your local cache. It is still
possible to get an LVN_GETDISPINFO for an item that has not been cached,
therefore, your application must take into account the chance of this
occurring.
/
}
return 0;
case LVN_ODFINDITEM:
{
LPNMLVFINDITEM lpFindItem = (LPNMLVFINDITEM)lParam;
/
This sample doesn't use this notification, but this is sent when the
ListView needs a particular item. Return -1 if the item is not found.
/
}
return 0;
*/
case NM_CUSTOMDRAW:
{
NMLVCUSTOMDRAW * custom = ( NMLVCUSTOMDRAW * )lp;
switch( custom->nmcd.dwDrawStage )
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
return CDRF_NOTIFYSUBITEMDRAW;
case ( CDDS_SUBITEM | CDDS_ITEMPREPAINT ):
{
// This is the prepaint stage for an item. Here's where we set the
// item's text color. Our return value will tell Windows to draw the
// item itself, but it will use the new color we set here.
// We'll cycle the colors through red, green, and light blue.
if( custom->nmcd.dwItemSpec == playlist->GetCurIndex() )
{
custom->clrTextBk = RGB( 225, 225, 225 );
}
else
{
if( custom->nmcd.dwItemSpec & 1 )
custom->clrTextBk = RGB( 245, 248, 250 );
else
custom->clrTextBk = RGB( 255, 255, 255 );
}
if( custom->iSubItem == 0 )
custom->clrText = RGB( 255, 0, 0 );
else
custom->clrText = RGB( 0, 0, 0 );
/*
if ( (custom->nmcd.dwItemSpec % 3) == 0 )
crText = RGB(255,0,0);
else if ( (custom->nmcd.dwItemSpec % 3) == 1 )
crText = RGB(0,255,0);
else
crText = RGB(128,128,255);
// Store the color back in the NMLVCUSTOMDRAW struct.
custom->clrText = crText;
*/
// Tell Windows to paint the control itself.
}
/*
custom->clrText = RGB( 190, 190, 190 );
custom->clrTextBk = RGB( 255, 0, 0 );*/
return CDRF_DODEFAULT;
}
break;
}
/*
case RBN_CHILDSIZE:
{
NMREBARCHILDSIZE * chs = ( NMREBARCHILDSIZE * )lp;
const int width_client = chs->rcChild.right - chs->rcChild.left;
int diff = width_client - 120;
if( diff > 0 )
{
const int width_band = chs->rcBand.right - chs->rcBand.left;
// chs->rcChild.right = chs->rcChild.left + 120;
DEBUGF( 1000, "CHILDSIZE [%i] [%i]", chs->uBand, width_band );
const int client_band_diff = width_band - width_client;
chs->rcBand.right = chs->rcBand.left + 120 + client_band_diff;
// chs->uBand
REBARBANDINFO rbbi;
rbbi.cbSize = sizeof( REBARBANDINFO );
rbbi.fMask = RBBIM_SIZE;
rbbi.cx = 154; //width_band + diff;
LRESULT lResult = SendMessage(
rebar,
RB_SETBANDINFO,
chs->uBand,
( LPARAM )( REBARBANDINFO * )&rbbi
);
}
break;
}
*/
case RBN_HEIGHTCHANGE:
{
const int iRebarHeightBefore = iRebarHeight;
RECT r;
GetWindowRect( WindowRebar, &r );
iRebarHeight = r.bottom - r.top;
InvalidateRect( WindowRebar, NULL, TRUE );
InvalidateRect( WindowPlaylist, NULL, TRUE );
RECT client;
GetClientRect( WindowMain, &client );
PostMessage(
hwnd,
WM_SIZE,
SIZE_RESTORED,
( client.right - client.left ) << 16 |
( client.bottom - client.top )
);
break;
}
}
break;
}
case WM_SYSKEYDOWN:
switch( wp ) // [Alt]+[...]
{
case VK_UP:
case VK_DOWN:
SetFocus( WindowPlaylist );
SendMessage( WindowPlaylist, message, wp, lp );
break;
}
break;
case WM_KEYDOWN:
case WM_KEYUP:
SetFocus( WindowPlaylist );
SendMessage( WindowPlaylist, message, wp, lp );
break;
case WM_COMMAND:
{
const int code = HIWORD( wp );
switch( code )
{
case 1: // also == CBN_SELCHANGE
{
if( ( HWND )lp == WindowOrder )
{
LRESULT res = SendMessage( WindowOrder, CB_GETCURSEL, 0, 0 );
if( res == CB_ERR ) break;
Playback::Order::SetMode( ( int )res );
}
else if( ( HWND )lp == WindowEq )
{
LRESULT res = SendMessage( WindowEq, CB_GETCURSEL, 0, 0 );
if( res == CB_ERR ) break;
Playback::Eq::SetIndex( ( int )( res - 1 ) );
}
return WndprocWinamp( hwnd, message, wp, lp );
}
case 0:
{
// Menu
const int id = LOWORD( wp );
switch( id )
{
case MENU_MAIN_WINDOWS_CONSOLE:
Console::Popup();
break;
case MENU_MAIN_WINDOWS_MANAGER:
PluginManager::Popup();
break;
}
/*
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "default 1 id = <%i>" ), id );
MessageBox( 0, szBuffer, "", 0 );
*/
return WndprocWinamp( hwnd, message, wp, lp );
}
default:
return WndprocWinamp( hwnd, message, wp, lp );
}
break;
}
case WM_GETMINMAXINFO:
{
MINMAXINFO * mmi = ( MINMAXINFO * )lp;
mmi->ptMinTrackSize.x = 400;
mmi->ptMinTrackSize.y = 300;
return 0;
}
case WM_SIZE:
{
// Resize children
RECT client;
GetClientRect( WindowMain, &client );
const int iClientWidth = client.right - client.left;
const int iClientHeight = client.bottom - client.top;
const int iPlaylistHeight = iClientHeight - iRebarHeight - iStatusHeight;
if( WindowRebar )
MoveWindow( WindowRebar, 0, 0, iClientWidth, iRebarHeight, TRUE );
if( WindowPlaylist )
{
MoveWindow( WindowPlaylist, 0, iRebarHeight, iClientWidth, iPlaylistHeight, TRUE );
playlist->Resize( WindowMain );
}
if( WindowStatus )
MoveWindow( WindowStatus, 0, iRebarHeight + iPlaylistHeight, iClientWidth, iStatusHeight, TRUE );
break;
}
case WM_TIMER:
Playback::UpdateSeek();
break;
case WM_CONTEXTMENU:
PostMessage( hwnd, WM_COMMAND, WINAMP_MAINMENU, 0 );
break;
case WM_CLOSE:
{
// Clean shutdown
// Stop
Playback::Stop();
// Dsp
DspLock.Enter();
for( int d = active_dsp_count - 1; d >= 0; d-- )
{
DspLock.Leave();
active_dsp_mods[ d ]->Stop();
DspLock.Enter();
}
DspLock.Leave();
// Vis
VisLock.Enter();
for( int v = active_vis_count - 1; v >= 0; v-- )
{
VisLock.Leave();
active_vis_mods[ v ]->Stop();
VisLock.Enter();
}
VisLock.Leave();
}
break;
case WM_DESTROY:
{
// Save playlist
TCHAR * szPlaylistMind = new TCHAR[ iHomeDirLen + 12 + 1 ];
memcpy( szPlaylistMind, szHomeDir, iHomeDirLen * sizeof( TCHAR ) );
memcpy( szPlaylistMind + iHomeDirLen, TEXT( "Plainamp.m3u" ), 12 * sizeof( TCHAR ) );
szPlaylistMind[ iHomeDirLen + 12 ] = TEXT( '\0' );
Playlist::ExportPlaylistFile( szPlaylistMind );
delete [] szPlaylistMind;
cwpcWinPlaceMain.TriggerCallback();
cwpcWinPlaceMain.RemoveCallback();
Console::Destroy();
PluginManager::Destroy();
if( bRemoveIcon )
{
RemoveTrayIcon();
bRemoveIcon = false;
}
PostQuitMessage( 0 );
return 0;
}
case WM_ACTIVATEAPP:
{
if( wp != TRUE ) break;
// Also bring console/manager to front
const bool bConsoleVisible = ( IsWindowVisible( WindowConsole ) == TRUE );
const bool bManagerVisible = ( IsWindowVisible( WindowManager ) == TRUE );
const bool bMainTodo = ( bConsoleVisible || bManagerVisible );
if( bConsoleVisible ) BringWindowToTop( WindowConsole );
if( bManagerVisible ) BringWindowToTop( WindowManager );
if( bMainTodo ) BringWindowToTop( WindowMain );
break;
}
case WM_SYSCOMMAND:
switch( ( wp & 0xFFF0 ) )
{
case SC_CLOSE:
if( !SendMessage( WindowMain, WM_WA_IPC, 0, IPC_HOOK_OKTOQUIT ) )
{
return 0;
}
break;
case SC_MINIMIZE:
{
// Hide console/manager on minimize
bConsoleTodo = ( IsWindowVisible( WindowConsole ) == TRUE );
if( bConsoleTodo ) ShowWindow( WindowConsole, SW_HIDE );
bManagerTodo = ( IsWindowVisible( WindowManager ) == TRUE );
if( bManagerTodo ) ShowWindow( WindowManager, SW_HIDE );
if( bMinimizeToTray )
{
if( !bRemoveIcon )
{
bRemoveIcon = AddTrayIcon( hwnd );
}
ShowWindow( hwnd, FALSE );
return 0;
}
break;
}
case SC_RESTORE:
{
const LRESULT res = DefWindowProc( hwnd, message, wp, lp );
// Unhide console/manager
const bool bMainTodo = ( bConsoleTodo || bManagerTodo );
if( bConsoleTodo ) ShowWindow( WindowConsole, SW_SHOW );
if( bManagerTodo ) ShowWindow( WindowManager, SW_SHOW );
if( bMainTodo ) BringWindowToTop( WindowMain );
return res;
}
}
break;
case TRAY_MSG:
switch( lp )
{
case WM_RBUTTONDOWN: // TODO: context menu instead
case WM_LBUTTONDOWN:
if( IsWindowVisible( hwnd ) == FALSE )
{
ShowWindow( hwnd, TRUE );
}
break;
case WM_RBUTTONUP: // TODO: context menu instead
case WM_LBUTTONUP:
if( bRemoveIcon )
{
RemoveTrayIcon();
bRemoveIcon = false;
}
break;
}
return 0;
default:
return WndprocWinamp( hwnd, message, wp, lp );
}
return DefWindowProc( hwnd, message, wp, lp );
}

View File

@ -0,0 +1,51 @@
////////////////////////////////////////////////////////////////////////////////
// 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_MAIN_H
#define PA_MAIN_H
#include "Global.h"
#include "Winamp/wa_msgids.h"
// TODO
#define MENU_MAIN_WINDOWS_CONSOLE 41
#define MENU_MAIN_WINDOWS_MANAGER 42
#define MENU_MAIN_CONTEXT_MANAGER WINAMP_MAIN_WINDOW // first window, for gen_dl
#define MENU_MAIN_CONTEXT_CONSOLE WINAMP_OPTIONS_VIDEO // last window, for gen_template
#define PLAINAMP_TOGGLE_CONSOLE 50001
#define PLAINAMP_TOGGLE_MANAGER 50002
extern HWND WindowMain;
extern HMENU main_context_menu;
bool BuildMainWindow();
void About( HWND hParent );
LRESULT CALLBACK WndprocMain( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
#endif // PA_MAIN_H

View File

@ -0,0 +1,367 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Output.h"
#include "OutputPlugin.h"
#include "Console.h"
#include <time.h>
int iNullSampleRate;
int iNullSumBytesPerSample;
int iNullWrittenMillis;
bool bNullPlaying;
int bNullPaused;
DWORD dwNullOpenTimestamp;
DWORD dwNullPauseTimestamp;
const int NULL_DEFAULT_LATENCY = 1000;
int Output_Open( int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms );
void Output_Close();
int Output_Write( char * buf, int len );
int Output_CanWrite();
int Output_IsPlaying();
int Output_Pause( int pause );
void Output_SetVolume( int volume );
void Output_SetPan( int pan );
void Output_Flush( int t );
int Output_GetOutputTime();
int Output_GetWrittenTime();
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
Out_Module output_server = {
OUT_VER, // int version
"Plainamp Output Server", // char * description;
0x7fffffff, // int id
NULL, // HWND hMainWindow
NULL, // HINSTANCE hDllInstance
NULL, // void (*Config)(HWND hwndParent);
NULL, // void (*About)(HWND hwndParent);
NULL, // void (*Init)();
NULL, // void (*Quit)();
Output_Open, // int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
Output_Close, // void (*Close)();
Output_Write, // int (*Write)(char *buf, int len);
Output_CanWrite, // int (*CanWrite)();
Output_IsPlaying, // int (*IsPlaying)();
Output_Pause, // int (*Pause)(int pause);
Output_SetVolume, // void (*SetVolume)(int volume);
Output_SetPan, // void (*SetPan)(int pan);
Output_Flush, // void (*Flush)(int t);
Output_GetOutputTime, // int (*GetOutputTime)();
Output_GetWrittenTime, // int (*GetWrittenTime)();
};
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Output_Open( int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms )
{
if( active_output_count > 0 )
{
// Maximum
int res = 0;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->Open( samplerate, numchannels, bitspersamp, bufferlenms, prebufferms );
if( res_temp > res ) res = res_temp;
}
return res;
}
else
{
iNullSampleRate = samplerate;
iNullSumBytesPerSample = numchannels * ( bitspersamp / 8 );
iNullWrittenMillis = 0;
bNullPlaying = false;
bNullPaused = 0;
dwNullOpenTimestamp = GetTickCount();
return NULL_DEFAULT_LATENCY;
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Output_Close()
{
if( active_output_count > 0 )
{
for( int i = 0; i < active_output_count; i++ )
{
active_output_plugins[ i ]->plugin->Close();
}
}
else
{
bNullPlaying = false;
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Output_Write( char * buf, int len )
{
if( active_output_count > 0 )
{
// Maximum
int res = 0;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->Write( buf, len );
if( res_temp > res ) res = res_temp;
}
return res;
}
else
{
if( iNullWrittenMillis == 0 )
{
dwNullOpenTimestamp = GetTickCount();
bNullPlaying = true;
}
iNullWrittenMillis += ( len / iNullSumBytesPerSample ) * 1000 / iNullSampleRate;
return 0; // 0 == Success
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Output_CanWrite()
{
if( active_output_count > 0 )
{
// Minimum
int res = 0x7fffffff;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->CanWrite();
if( res_temp < res ) res = res_temp;
}
return res;
}
else
{
const int diff = Output_GetWrittenTime() - Output_GetOutputTime();
if( diff >= NULL_DEFAULT_LATENCY )
{
return 0;
}
else
{
return ( NULL_DEFAULT_LATENCY - diff ) * iNullSumBytesPerSample * iNullSampleRate / 1000;
}
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Output_IsPlaying()
{
if( active_output_count > 0 )
{
// Maximum
int res = 0;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->IsPlaying();
if( res_temp > res ) res = res_temp;
}
return res;
}
else
{
return ( Output_GetOutputTime() < Output_GetWrittenTime() ) ? 1 : 0;
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Output_Pause( int pause )
{
if( active_output_count > 0 )
{
// Maximum
int res = 0;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->Pause( pause );
if( res_temp > res ) res = res_temp;
}
return res;
}
else
{
int res = bNullPaused;
if( pause && !bNullPaused )
{
// Playback should be paused
dwNullPauseTimestamp = GetTickCount();
bNullPaused = 1;
}
else if( !pause && bNullPaused )
{
// Playback should be continued
// Add the gap length to the open timestamp like no gap exists
dwNullOpenTimestamp += ( GetTickCount() - dwNullPauseTimestamp );
bNullPaused = 0;
}
return res; // Previous state
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Output_SetVolume( int volume )
{
for( int i = 0; i < active_output_count; i++ )
{
active_output_plugins[ i ]->plugin->SetVolume( volume );
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Output_SetPan( int pan )
{
for( int i = 0; i < active_output_count; i++ )
{
active_output_plugins[ i ]->plugin->SetPan( pan );
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Output_Flush( int t )
{
if( active_output_count > 0 )
{
for( int i = 0; i < active_output_count; i++ )
{
active_output_plugins[ i ]->plugin->Flush( t );
}
}
else
{
dwNullOpenTimestamp = GetTickCount() - t;
iNullWrittenMillis = t;
}
}
////////////////////////////////////////////////////////////////////////////////
/// Returns the number of milliseconds the song would be at
/// if we had zero latency. This value is never bigger than
/// the one returned by Output_GetWrittenTime().
////////////////////////////////////////////////////////////////////////////////
int Output_GetOutputTime() // <= GetWrittenTime()
{
if( active_output_count > 0 )
{
// Minimum
int res = 0x7fffffff;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->GetOutputTime();
if( res_temp < res ) res = res_temp;
}
return res;
}
else
{
if( bNullPlaying )
{
int res;
if( bNullPaused )
{
res = dwNullPauseTimestamp - dwNullOpenTimestamp;
}
else
{
res = GetTickCount() - dwNullOpenTimestamp;
}
return MIN( res, iNullWrittenMillis );
}
else
{
return 0;
}
}
}
////////////////////////////////////////////////////////////////////////////////
/// Returns the number of milliseconds already written.
/// Due to latency this value is always bigger than
/// the value returned by Output_GetOutputTime().
////////////////////////////////////////////////////////////////////////////////
int Output_GetWrittenTime()
{
if( active_output_count > 0 )
{
// Maximum
int res = 0;
int res_temp;
for( int i = 0; i < active_output_count; i++ )
{
res_temp = active_output_plugins[ i ]->plugin->GetWrittenTime();
if( res_temp > res ) res = res_temp;
}
return res;
}
else
{
return iNullWrittenMillis;
}
}

View File

@ -0,0 +1,27 @@
////////////////////////////////////////////////////////////////////////////////
// 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_OUTPUT_H
#define PA_OUTPUT_H
#include "Global.h"
#include "Winamp/Out.h"
extern Out_Module output_server;
#endif // PA_OUTPUT_H

View File

@ -0,0 +1,296 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "OutputPlugin.h"
#include "Main.h"
#include "Unicode.h"
#include "Console.h"
#include "Config.h"
#include "Playback.h"
vector <OutputPlugin *> output_plugins; // extern
OutputPlugin ** active_output_plugins = NULL; // extern
int active_output_count = 0; // extern
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
OutputPlugin::OutputPlugin( TCHAR * szDllpath, bool bKeepLoaded ) : Plugin( szDllpath )
{
iHookerIndex = -1;
bActive = false;
iArrayIndex = -1;
plugin = NULL;
if( !Load() )
{
return;
}
////////////////////////////////////////////////////////////////////////////////
// Quick hack!!!
TCHAR * szBuffer = new TCHAR[ 500 ]; // NOT LOCAL!!!
_stprintf( szBuffer, TEXT( "OutputPluginActive___%s" ), GetFilename() );
ConfBool * cbActive = new ConfBool( &bActive, szBuffer, CONF_MODE_INTERNAL, false );
cbActive->Read();
if( bActive )
{
bActive = false;
Start();
}
else
{
if( !bKeepLoaded )
{
// Note: out_ds seems to do weird things
// when unloaded here!?
// So out_ds keeps loaded for now.
if( _tcscmp( GetFilename(), TEXT( "out_ds.dll" ) ) )
{
Unload();
}
}
}
// Quick hack!!!
////////////////////////////////////////////////////////////////////////////////
output_plugins.push_back( this );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool OutputPlugin::Load()
{
if( IsLoaded() ) return true;
// (1) Load DLL
hDLL = LoadLibrary( GetFullpath() );
if( !hDLL ) return false;
// (2) Find export
WINAMP_OUTPUT_GETTER winampGetOutModule =
( WINAMP_OUTPUT_GETTER )GetProcAddress( hDLL, "winampGetOutModule" );
if( winampGetOutModule == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (3) Get module
plugin = winampGetOutModule();
if( !plugin )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (4) Process module
plugin->hDllInstance = hDLL;
plugin->hMainWindow = WindowMain;
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;
}
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( " " ) );
if( plugin->Init )
{
// 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++;
}
// 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 OutputPlugin::Unload()
{
if( !IsLoaded() ) return true;
if( bActive && Playback::IsPlaying() ) return false;
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 OutputPlugin::About( HWND hParent )
{
if( !IsLoaded() ) return false;
if( !plugin ) return false;
if( !plugin->About ) return false;
plugin->About( hParent );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool OutputPlugin::Config( HWND hParent )
{
if( !IsLoaded() ) return false;
if( !plugin ) return false;
if( !plugin->Config ) return false;
plugin->Config( hParent );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool OutputPlugin::Start()
{
if( !IsLoaded() ) return false;
if( bActive ) return true;
if( active_output_count )
{
active_output_plugins = ( OutputPlugin ** )realloc( active_output_plugins, ( active_output_count + 1 ) * sizeof( OutputPlugin * ) );
active_output_plugins[ active_output_count ] = this;
iArrayIndex = active_output_count;
active_output_count++;
}
else
{
active_output_plugins = ( OutputPlugin ** )malloc( sizeof( OutputPlugin * ) );
active_output_plugins[ 0 ] = this;
iArrayIndex = 0;
active_output_count = 1;
}
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Output plugin <%s> activated" ), GetFilename() );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
bActive = true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool OutputPlugin::Stop()
{
if( !IsLoaded() ) return true;
if( !bActive ) return true;
const int iMaxIndex = active_output_count - 1;
if( iArrayIndex < iMaxIndex )
{
active_output_plugins[ iArrayIndex ] = active_output_plugins[ iMaxIndex ];
active_output_plugins[ iArrayIndex ]->iArrayIndex = iArrayIndex;
}
iArrayIndex = -1;
active_output_count--;
// TODO Flush?
// TODO Close?
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Output plugin <%s> deactivated" ), GetFilename() );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
bActive = false;
return true;
}

View File

@ -0,0 +1,85 @@
////////////////////////////////////////////////////////////////////////////////
// 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_OUTPUT_PLUGIN_H
#define PA_OUTPUT_PLUGIN_H
#include "Global.h"
#include "Plugin.h"
#include "Winamp/Out.h"
#include <vector>
using namespace std;
typedef Out_Module * ( * WINAMP_OUTPUT_GETTER )( void );
class OutputPlugin;
extern vector <OutputPlugin *> output_plugins;
extern OutputPlugin ** active_output_plugins;
extern int active_output_count;
////////////////////////////////////////////////////////////////////////////////
/// Winamp output plugin wrapper
////////////////////////////////////////////////////////////////////////////////
class OutputPlugin : public Plugin
{
public:
OutputPlugin( TCHAR * szDllpath, bool bKeepLoaded );
bool Load();
bool Unload();
TCHAR * GetTypeString() { return TEXT( "Output" ); }
int GetTypeStringLen() { return 6; }
PluginType GetType() { return PLUGIN_TYPE_OUTPUT; }
inline bool IsActive() { return bActive; }
bool About( HWND hParent );
bool Config( HWND hParent );
bool Start();
bool Stop();
private:
bool bActive;
int iArrayIndex;
Out_Module * plugin;
// TODO
friend bool OpenPlay( TCHAR * szFilename, int iNumber );
friend int Output_Open( int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms );
friend void Output_Close();
friend int Output_Write( char * buf, int len );
friend int Output_CanWrite();
friend int Output_IsPlaying();
friend int Output_Pause( int pause );
friend void Output_SetVolume( int volume );
friend void Output_SetPan( int pan );
friend void Output_Flush( int t );
friend int Output_GetOutputTime();
friend int Output_GetWrittenTime();
};
#endif // PA_OUTPUT_PLUGIN_H

View File

@ -0,0 +1,243 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Path.h"
#include <ctype.h>
#include <vector>
using namespace std;
////////////////////////////////////////////////////////////////////////////////
/// Applies a virtual root to a filename
///
/// Example:
/// Rootpath: "C:\111\222\333\"
/// Filename before: "C:\111\444\test.mp3"
/// Filename after: "..\..\444\test.mp3"
////////////////////////////////////////////////////////////////////////////////
bool ApplyRootToFilename( TCHAR * szRootpath, TCHAR * szFilename )
{
// returns modified flag
int iFilenameLen = ( int )_tcslen( szFilename );
int iRootLen = ( int )_tcslen( szRootpath );
// Too short?
if( ( iRootLen < 2 ) || ( iFilenameLen < 4 ) )
{
return false;
}
// Ensure trailing backslash
bool bDelOnRet = false;
TCHAR * szFinalRoot;
TCHAR * szFinalRootBackup;
if( szRootpath[ iRootLen - 1 ] != TEXT( '\\' ) )
{
szFinalRoot = new TCHAR[ iRootLen + 2 ];
memcpy( szFinalRoot, szRootpath, iRootLen * sizeof( TCHAR ) );
memcpy( szFinalRoot + iRootLen, TEXT( "\\\0" ), 2 * sizeof( TCHAR ) );
iRootLen++;
szFinalRootBackup = szFinalRoot;
bDelOnRet = true;
}
else
{
szFinalRoot = szRootpath;
szFinalRootBackup = NULL;
bDelOnRet = false;
}
// Different drives?
if( _totlower( *szFilename ) != _totlower( *szFinalRoot ) )
{
if( bDelOnRet ) delete [] szFinalRootBackup;
return false;
}
// Skip drive
if( _tcsnicmp( szFilename, szFinalRoot, 3 ) )
{
szFinalRoot += 3;
iRootLen -= 3;
memmove( szFilename, szFilename + 3, ( iFilenameLen - 2 ) * sizeof( TCHAR ) ); // Plus \0
iFilenameLen -=3;
}
int iBackslashLast = -1;
int iCompLen; // Maximum chars to compare
if( iRootLen > iFilenameLen )
iCompLen = iFilenameLen;
else
iCompLen = iRootLen;
// Walk while equal
int i = 0;
while( i < iCompLen )
{
if( ( szFilename[ i ] == TEXT( '\\' ) ) && ( szFinalRoot[ i ] == TEXT( '\\' ) ) )
{
iBackslashLast = i;
i++;
}
else if( _totlower( szFilename[ i ] ) == _totlower( szFinalRoot[ i ] ) )
{
i++;
}
else
{
break;
}
}
// Does the filename contain the full root?
int iLevelDiff = 0;
if( i != iCompLen )
{
// Calculate level difference
for( i = iBackslashLast + 1; i < iRootLen; i++ )
{
if( szFinalRoot[ i ] == TEXT( '\\' ) )
{
iLevelDiff++;
}
}
}
if( iBackslashLast == -1 )
{
if( bDelOnRet ) delete [] szFinalRootBackup;
return false;
}
TCHAR * szSource = szFilename + iBackslashLast + 1;
if( iLevelDiff > 0 )
{
const int iExtraCharsForPrefix = ( 3 * iLevelDiff ) - iBackslashLast - 1;
const int iCharsToMove = iFilenameLen - iBackslashLast; // One more for '\0'
memmove( szSource + iExtraCharsForPrefix, szSource, sizeof( TCHAR ) * iCharsToMove );
TCHAR * szWalk = szFilename;
while( iLevelDiff-- )
{
memcpy( szWalk, TEXT( "..\\" ), 3 * sizeof( TCHAR ) );
szWalk += 3;
}
}
else
{
const int iCharsToMove = iFilenameLen - iBackslashLast; // One more for '\0'
memmove( szFilename, szSource, sizeof( TCHAR ) * iCharsToMove );
}
if( bDelOnRet ) delete [] szFinalRootBackup;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// Compresses filenames (inplace)
///
/// Example:
/// Before "C:\111\222\..\333\.\444\..\..\test.mp3"
/// After "C:\111\test.mp3"
////////////////////////////////////////////////////////////////////////////////
bool UnbloatFilename( TCHAR * szFullpath, bool bFixTooDeep )
{
int iLen = ( int )_tcslen( szFullpath );
bool bModified = false;
// Exclude drive letter from conversion "C:\"
if( ( iLen > 3 ) && !_tcsnicmp( szFullpath + 1, TEXT( ":\\" ), 2 ) )
{
szFullpath += 3;
iLen -= 3;
}
vector< TCHAR * > after_backslash;
TCHAR * end = szFullpath + iLen;
TCHAR * szWalk = szFullpath;
while( true )
{
if( !_tcsnicmp( szWalk, TEXT( "..\\" ), 3 ) )
{
TCHAR * szAfterBackslashLast;
if( after_backslash.empty() )
{
// Getting here means we go deeper than root level e.g. "../test"
if( bFixTooDeep )
{
szAfterBackslashLast = szWalk;
}
else
{
break;
}
}
else
{
szAfterBackslashLast = after_backslash.back();
after_backslash.pop_back();
}
const int iBytesToCopy = end - szWalk - ( 3 * sizeof( TCHAR ) );
const int iBytesLess = szWalk + ( 3 * sizeof( TCHAR ) ) - szAfterBackslashLast;
memmove( szAfterBackslashLast, szWalk + 3, iBytesToCopy );
char * byte_end = ( char * )end;
byte_end -= iBytesLess;
end = byte_end;
*end = TEXT( '\0' );
szWalk = szAfterBackslashLast;
bModified = true;
}
else if( !_tcsnicmp( szWalk, TEXT( ".\\" ), 2 ) )
{
const int iBytesToCopy = end - szWalk - ( 2 * sizeof( TCHAR ) );
memmove( szWalk, szWalk + 2, iBytesToCopy );
end -= 2;
*end = TEXT( '\0' );
bModified = true;
}
else
{
if( szWalk >= end ) break;
after_backslash.push_back( szWalk );
// Jump after next backslash
while( ( szWalk < end ) && ( *szWalk != TEXT( '\\' ) ) ) szWalk++;
szWalk++;
}
}
return bModified;
}

View File

@ -0,0 +1,31 @@
////////////////////////////////////////////////////////////////////////////////
// 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_PATH_H
#define PA_PATH_H
#ifndef PLAINAMP_TESTING
# include "Global.h"
#else
# include "../Testing/GlobalTest.h"
#endif
bool ApplyRootToFilename( TCHAR * szRootpath, TCHAR * szFilename );
bool UnbloatFilename( TCHAR * szFullpath, bool bFixTooDeep );
#endif // PA_PATH_H

View File

@ -0,0 +1,695 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Playback.h"
#include "InputPlugin.h"
#include "Output.h"
#include "Playlist.h"
#include "Console.h"
#include "Unicode.h"
#include "Rebar.h"
#include "Main.h"
#include "Config.h"
#include "Status.h"
int iCurVol = 255;
ConfIntMinMax ciCurVol( &iCurVol, TEXT( "Volume" ), CONF_MODE_INTERNAL, 255, 0, 255 );
int iCurPan = 0;
ConfIntMinMax ciCurPan( &iCurPan, TEXT( "Panning" ), CONF_MODE_INTERNAL, 0, -127, 127 );
#define VOLUME_STEP ( 255 / 10 )
bool bPlaying = false;
bool bPaused = false;
bool bTimerRunning = false;
// Only for reference comparison!!!
TCHAR * szCurrentFilename = NULL;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void EnableTimer( bool bEnabled )
{
if( bEnabled == bTimerRunning ) return;
if( bEnabled )
{
SetTimer( WindowMain, TIMER_SEEK_UPDATE, 1000, NULL );
}
else
{
KillTimer( WindowMain, TIMER_SEEK_UPDATE );
StatusReset();
}
bTimerRunning = bEnabled;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool OpenPlay( TCHAR * szFilename, int iNumber )
{
// TODO: cleanup!!!
if( !szFilename ) return false;
szCurrentFilename = szFilename;
// TODO: non-file support
// Get extension
const int iLen = ( int )_tcslen( szFilename );
TCHAR * walk = szFilename + iLen - 1;
while( ( walk >= szFilename ) && ( *walk != TEXT( '.' ) ) ) walk--;
walk++;
const int iExtLen = ( int )_tcslen( walk );
TCHAR * szExt = new TCHAR[ iExtLen + 1 ];
memcpy( szExt, walk, iExtLen * sizeof( TCHAR ) );
szExt[ iExtLen ] = TEXT( '\0' );
// Get input plugin from extension map
map <TCHAR *, InputPlugin *, TextCompare>::iterator iter =
ext_map.find( szExt );
delete [] szExt;
if( iter == ext_map.end() )
{
Console::Append( TEXT( "ERROR: Extension not supported" ) );
Console::Append( " " );
return false;
}
InputPlugin * old_input = active_input_plugin;
active_input_plugin = iter->second;
if( old_input )
{
// if( active_input_plugin != old_input ) ----> TODO unload old plugin
// Some output plugins require a call to Close() before each
// call to Open(). Calling Input::Stop() will make the input plugin
// call Output::Close() and thus solve this problem.
old_input->plugin->Stop();
}
if( !active_input_plugin->plugin )
{
Console::Append( TEXT( "ERROR: Input plugin is NULL" ) );
Console::Append( " " );
return false;
}
// Connect
active_input_plugin->plugin->outMod = &output_server; // output->plugin;
// Re-apply volume and panning
active_input_plugin->plugin->SetVolume( iCurVol );
active_input_plugin->plugin->SetPan( iCurPan );
Playback::Eq::Reapply();
// Play
#ifdef PA_UNICODE
// Filename
const int iFilenameLen = _tcslen( szFilename );
char * szTemp = new char[ iFilenameLen + 1 ];
ToAnsi( szTemp, szFilename, iFilenameLen );
szTemp[ iFilenameLen ] = '\0';
// Ansi Title
char szAnsiTitle[ 2000 ] = "\0";
int length_in_ms;
active_input_plugin->plugin->GetFileInfo( szTemp, szAnsiTitle, &length_in_ms );
const int iAnsiTitleLen = strlen( szAnsiTitle );
// Unicode title
TCHAR szTitle[ 2000 ];
ToTchar( szTitle, szAnsiTitle, iFilenameLen, iAnsiTitleLen );
szTitle[ iAnsiTitleLen ] = TEXT( "\0" );
active_input_plugin->plugin->Play( szTemp );
delete [] szTemp;
#else
// Title
TCHAR szTitle[ 2000 ] = TEXT( "\0" );
int length_in_ms;
active_input_plugin->plugin->GetFileInfo( szFilename, szTitle, &length_in_ms );
active_input_plugin->plugin->Play( szFilename );
#endif
bPlaying = true;
bPaused = false;
// Title
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "%i. %s - Plainamp" ), iNumber, szTitle );
SetWindowText( WindowMain, szBuffer );
/*
TCHAR * szBasename = szFilename + uLen - 1;
while( ( szBasename > szFilename ) && ( *szBasename != TEXT( '\\' ) ) ) szBasename--;
szBasename++;
*/
// Timer ON
EnableTimer( true );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback_PrevOrNext( bool bPrevOrNext )
{
// todo: prev/next in pause mode?
if( !active_input_plugin ) return false;
if( !active_input_plugin->plugin ) return false;
int iNextIndex = playlist->GetCurIndex();
int iMaxIndex = playlist->GetMaxIndex();
if( iMaxIndex < 0 || iNextIndex < 0 ) return false;
bool res;
if( bPrevOrNext )
res = Playback::Order::Prev( iNextIndex, iMaxIndex );
else
res = Playback::Order::Next( iNextIndex, iMaxIndex );
if( res )
{
if( bPlaying )
{
// NOT TWICE active_input_plugin->plugin->Stop();
bPlaying = false;
bPaused = false;
// Timer OFF
EnableTimer( false );
}
TCHAR * szFilename = Playlist::GetFilename( iNextIndex );
if( !szFilename ) return false;
playlist->SetCurIndex( iNextIndex );
return OpenPlay( szFilename, iNextIndex + 1 );
}
else
{
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Prev()
{
return Playback_PrevOrNext( true );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Play()
{
static int iLastIndex = -1;
if( bPlaying )
{
if( !active_input_plugin ) return false;
if( !active_input_plugin->plugin ) return false;
const int iIndex = playlist->GetCurIndex();
if( iIndex < 0 ) return false;
/*
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "OLD [%i] NEW [%i]" ), iLastIndex, iIndex );
SetWindowText( WindowMain, szBuffer );
*/
// Same track/file as before?
TCHAR * szFilename = Playlist::GetFilename( iIndex );
if( szFilename != szCurrentFilename )
{
// New track!
// Stop
// NOT TWICE active_input_plugin->plugin->Stop();
// Timer OFF
EnableTimer( false );
// Get filename
if( !szFilename )
{
Console::Append( TEXT( "ERROR: Could not resolve filename" ) );
Console::Append( " " );
return false;
}
// Play
iLastIndex = iIndex;
bPlaying = OpenPlay( szFilename, iIndex + 1 );
bPaused = false;
}
else
{
// Same track!
if( bPaused )
{
// Unpause
active_input_plugin->plugin->UnPause();
bPaused = false;
// Timer ON
EnableTimer( true );
}
else
{
// Restart at beginning
active_input_plugin->plugin->SetOutputTime( 0 );
}
}
}
else
{
const int iIndex = playlist->GetCurIndex();
if( iIndex < 0 ) return false;
// Get filename
TCHAR * szFilename = Playlist::GetFilename( iIndex );
if( !szFilename )
{
Console::Append( TEXT( "ERROR: Could not resolve filename" ) );
Console::Append( " " );
return false;
}
// Play
iLastIndex = iIndex;
bPlaying = OpenPlay( szFilename, iIndex + 1 );
bPaused = false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Pause()
{
if( !bPlaying ) return false;
if( !active_input_plugin ) return false;
if( !active_input_plugin->plugin ) return false;
if( bPaused )
{
// Unpause
active_input_plugin->plugin->UnPause();
bPaused = false;
// Timer ON
EnableTimer( true );
}
else
{
// Pause
active_input_plugin->plugin->Pause();
bPaused = true;
// Timer OFF
EnableTimer( false );
}
// Console::Append( TEXT( "Playback::Pause" ) );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Stop()
{
if( !bPlaying ) return false;
// Stop
if( active_input_plugin && active_input_plugin->plugin )
{
active_input_plugin->plugin->Stop();
}
active_input_plugin = NULL; // QUICK FIX
bPlaying = false;
bPaused = false;
// Timer OFF
EnableTimer( false );
// Reset seekbar
Playback::UpdateSeek();
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Next()
{
return Playback_PrevOrNext( false );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::IsPlaying()
{
return bPlaying;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::IsPaused()
{
return bPaused;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::UpdateSeek()
{
static bool bSliderEnabledBefore = false;
bool bSliderEnabledAfter;
if( !WindowSeek ) return false;
int iVal = 0;
if( !active_input_plugin || !active_input_plugin->plugin )
{
if( bSliderEnabledBefore )
{
// Update slider
PostMessage( WindowSeek, TBM_SETPOS, ( WPARAM )( TRUE ), iVal );
// Disable slider
EnableWindow( WindowSeek, FALSE );
bSliderEnabledBefore = false;
}
}
else
{
const int ms_len = active_input_plugin->plugin->GetLength();
if( ms_len )
{
const int ms_cur = active_input_plugin->plugin->GetOutputTime();
iVal = ( ms_cur * 1000 ) / ms_len;
if( iVal > 1000 ) iVal = 0;
}
if( !bSliderEnabledBefore )
{
EnableWindow( WindowSeek, TRUE );
bSliderEnabledBefore = true;
}
// Update slider
PostMessage( WindowSeek, TBM_SETPOS, ( WPARAM )( TRUE ), iVal );
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Playback::PercentToMs( float fPercent )
{
if( !active_input_plugin ) return -1;
if( !active_input_plugin->plugin ) return -1;
const int ms_len = active_input_plugin->plugin->GetLength();
const int ms_res = ( int )( ms_len * fPercent / 100.0f );
return ms_res;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::SeekPercent( float fPercent )
{
// TODO update slider, NOT HERE!!!
if( !bPlaying ) return false;
if( bPaused ) return false; // TODO: apply seek when unpausing
if( !active_input_plugin ) return false;
if( !active_input_plugin->plugin ) return false;
if( fPercent < 0.0f )
fPercent = 0.0f;
else if( fPercent > 100.0f )
fPercent = 100.0f;
const int ms_len = active_input_plugin->plugin->GetLength();
const int ms_cur = ( int )( ms_len * fPercent / 100.0f );
active_input_plugin->plugin->SetOutputTime( ms_cur );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool SeekRelative( int ms )
{
if( !bPlaying ) return false;
if( bPaused ) return false; // TODO: apply seek when unpausing
if( !active_input_plugin ) return false;
if( !active_input_plugin->plugin ) return false;
const int ms_len = active_input_plugin->plugin->GetLength();
const int ms_old = active_input_plugin->plugin->GetOutputTime();
int ms_new = ms_old + ms;
if( ms_new < 0 )
ms_new = 0;
else if( ms_new > ms_len )
ms_new = ms_len;
if( ms_new == ms_old ) return true;
active_input_plugin->plugin->SetOutputTime( ms_new );
/*
// PROGRESS
// PostMessage( hwnd, PBM_SETPOS , ( WPARAM )( iVal ), 0 );
// TARCKBAR
PostMessage( wnd_pos, TBM_SETPOS, ( WPARAM )( TRUE ), ms_cur * 1000 / ms_len );
*/
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Forward()
{
return SeekRelative( 5000 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Rewind()
{
return SeekRelative( -5000 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void Playback::NotifyTrackEnd()
{
bPlaying = false;
bPaused = false;
// Timer
EnableTimer( false );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Playback::Volume::Get()
{
return iCurVol;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
inline void Playback_Volume_Set( int iVol )
{
if( active_input_plugin && active_input_plugin->plugin )
{
active_input_plugin->plugin->SetVolume( iVol );
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Volume::Set( int iVol )
{
const int iCurVolBackup = iCurVol;
iCurVol = iVol;
ciCurVol.MakeValidPull();
if( iCurVol != iCurVolBackup )
{
Playback_Volume_Set( iCurVol );
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Volume::Up()
{
if( ciCurVol.IsMax() ) return true;
const int iCurVolBackup = iCurVol;
iCurVol += VOLUME_STEP;
ciCurVol.MakeValidPull();
if( iCurVol != iCurVolBackup )
{
Console::Append( TEXT( "Volume UP" ) );
Playback_Volume_Set( iCurVol );
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Volume::Down()
{
if( ciCurVol.IsMin() ) return true;
const int iCurVolBackup = iCurVol;
iCurVol -= VOLUME_STEP;
ciCurVol.MakeValidPull();
if( iCurVol != iCurVolBackup )
{
Console::Append( TEXT( "Volume DOWN" ) );
Playback_Volume_Set( iCurVol );
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Playback::Pan::Get()
{
return iCurPan;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Pan::Set( int iPan )
{
const int iCurPanBackup = iCurPan;
iCurPan = iPan;
ciCurPan.MakeValidPull();
if( ( iCurPan != iCurPanBackup ) && active_input_plugin && active_input_plugin->plugin )
{
active_input_plugin->plugin->SetPan( iCurPan );
}
return true;
}

View File

@ -0,0 +1,106 @@
////////////////////////////////////////////////////////////////////////////////
// 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_PLAYBACK_H
#define PA_PLAYBACK_H
#include "Global.h"
#define ORDER_SINGLE 0
#define ORDER_SINGLE_REPEAT 1
#define ORDER_NORMAL 2
#define ORDER_NORMAL_REPEAT 3
#define ORDER_INVERSE 4
#define ORDER_INVERSE_REPEAT 5
#define ORDER_RANDOM 6
#define ORDER_FIRST ORDER_SINGLE
#define ORDER_LAST ORDER_RANDOM
#define ORDER_DEFAULT ORDER_NORMAL_REPEAT
#define TIMER_SEEK_UPDATE 1
typedef bool ( * PresetCallback )( TCHAR * );
namespace Playback
{
bool Prev();
bool Play();
bool Pause();
bool Stop();
bool Next();
bool IsPlaying();
bool IsPaused();
bool UpdateSeek();
int PercentToMs( float fPercent );
bool SeekPercent( float fPercent );
bool Forward();
bool Rewind();
void NotifyTrackEnd();
namespace Volume
{
int Get();
bool Set( int iVol );
bool Up();
bool Down();
};
namespace Pan
{
int Get();
bool Set( int iPan );
};
namespace Order
{
int GetCurMode();
bool SetMode( int iMode );
TCHAR * GetModeName( int iMode );
// int GetModeNameLen( int iMode );
bool Next( int & iCur, int iMax );
bool Prev( int & iCur, int iMax );
};
namespace Eq
{
// 63 -> -12db
// 31 -> 0
// 0 -> +12db
// bool Get( char * eq_data );
// bool Set( bool bOn, char * pData, int iPreamp );
int GetCurIndex();
bool SetIndex( int iPresetIndex );
bool Reapply();
bool ReadPresets( PresetCallback AddPreset );
};
};
#endif // PA_PLAYBACK_H

View File

@ -0,0 +1,223 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Playback.h"
#include "InputPlugin.h"
#include "Console.h"
#include "Config.h"
#include <vector>
using namespace std;
vector <char *> eq_vec;
// Note: CurPresetFixed will be renamed to CurPreset when
// custom presets are implemented. This hopefully avoids
// migration trouble.
int iCurPreset; // -1 means EQ off
ConfInt ciCurPreset( &iCurPreset, TEXT( "CurPresetFixed" ), CONF_MODE_INTERNAL, -1 );
bool bPreventDistortion; // Automatic preamp adjustment
ConfBool cbPreventDistortion( &bPreventDistortion, TEXT( "PreventDistortion" ), CONF_MODE_PUBLIC, true );
////////////////////////////////////////////////////////////////////////////////
// PRE valid index
////////////////////////////////////////////////////////////////////////////////
void Playback_Eq_Set( int iPresetIndex )
{
if( active_input_plugin && active_input_plugin->plugin )
{
if( iPresetIndex == -1 ) // == EQ disabled
{
char data[ 10 ] = { 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 };
active_input_plugin->plugin->EQSet( 0, data, 31 );
}
else
{
char data[ 10 ];
memcpy( data, eq_vec[ iPresetIndex ], sizeof( char ) * 10 );
if( bPreventDistortion )
{
// Search minimum (most amplifying band)
int iMin = 63;
int i;
for( i = 0; i < 10; i++ )
{
if( data[ i ] < iMin ) iMin = data[ i ];
}
if( iMin < 31 ) // Possible distortion
{
// Adjust preamp to prevent distortion
active_input_plugin->plugin->EQSet( 1, data, 31 + ( 31 - iMin ) );
}
else
{
if( iMin > 31 ) // Lower than necessary
{
// Push to zero level so we get
// more volume without distortion
const int iSub = iMin - 31;
for( i = 0; i < 10; i++ )
{
data[ i ] -= iSub;
}
}
active_input_plugin->plugin->EQSet( 1, data, 31 );
}
}
else
{
active_input_plugin->plugin->EQSet( 1, data, 31 );
}
}
}
}
/*
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Eq::Set( bool bOn, char * pData, int iPreamp )
{
if( active_input_plugin && active_input_plugin->plugin )
{
char data[ 10 ];
memcpy( data, pData, sizeof( char ) * 10 );
active_input_plugin->plugin->EQSet( bOn ? 1 : 0, data, iPreamp );
}
return true;
}
*/
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Playback::Eq::GetCurIndex()
{
return iCurPreset;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Eq::SetIndex( int iPresetIndex )
{
if( iPresetIndex >= ( int )eq_vec.size() ) return false;
Playback_Eq_Set( iPresetIndex );
iCurPreset = iPresetIndex;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Eq::Reapply()
{
Playback_Eq_Set( iCurPreset );
return true;
}
// Note: Most of these are the exact presets used in Winamp.
// I do not expect any legal trouble with this but
// in case I am wrong please let me know and I will
// remove them.
char eq_classical [ 10 ] = { 31, 31, 31, 31, 31, 31, 44, 44, 44, 48 };
char eq_club [ 10 ] = { 31, 31, 26, 22, 22, 22, 26, 31, 31, 31 };
char eq_dance [ 10 ] = { 16, 20, 28, 32, 32, 42, 44, 44, 32, 32 };
char eq_full_bass [ 10 ] = { 16, 16, 16, 22, 29, 39, 46, 49, 50, 50 };
char eq_full_bass_treble[ 10 ] = { 20, 22, 31, 44, 40, 29, 18, 14, 12, 12 };
char eq_full_treble [ 10 ] = { 48, 48, 48, 39, 27, 14, 6, 6, 6, 4 };
char eq_headphones [ 10 ] = { 24, 14, 23, 38, 36, 29, 24, 16, 11, 8 };
char eq_laptop [ 10 ] = { 24, 14, 23, 38, 36, 29, 24, 16, 11, 8 };
char eq_large_hall [ 10 ] = { 15, 15, 22, 22, 31, 40, 40, 40, 31, 31 };
char eq_live [ 10 ] = { 40, 31, 25, 23, 22, 22, 25, 27, 27, 28 };
char eq_more_bass [ 10 ] = { 22, 22, 22, 22, 22, 22, 26, 31, 31, 31 };
char eq_party [ 10 ] = { 20, 20, 31, 31, 31, 31, 31, 31, 20, 20 };
char eq_pop [ 10 ] = { 35, 24, 20, 19, 23, 34, 36, 36, 35, 35 };
char eq_reggae [ 10 ] = { 31, 31, 33, 42, 31, 21, 21, 31, 31, 31 };
char eq_rock [ 10 ] = { 19, 24, 41, 45, 38, 25, 17, 14, 14, 14 };
char eq_ska [ 10 ] = { 36, 40, 39, 33, 25, 22, 17, 16, 14, 16 };
char eq_soft [ 10 ] = { 24, 29, 34, 36, 34, 25, 18, 16, 14, 12 };
char eq_soft_rock [ 10 ] = { 25, 25, 28, 33, 39, 41, 38, 33, 27, 17 };
char eq_techno [ 10 ] = { 19, 22, 31, 41, 40, 31, 19, 16, 16, 17 };
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Eq::ReadPresets( PresetCallback AddPreset )
{
if( AddPreset == NULL ) return false;
eq_vec.push_back( eq_classical ); AddPreset( TEXT( "Classical" ) );
eq_vec.push_back( eq_club ); AddPreset( TEXT( "Club" ) );
eq_vec.push_back( eq_dance ); AddPreset( TEXT( "Dance" ) );
eq_vec.push_back( eq_full_bass ); AddPreset( TEXT( "Full Bass" ) );
eq_vec.push_back( eq_full_bass_treble ); AddPreset( TEXT( "Full Bass & Treble" ) );
eq_vec.push_back( eq_full_treble ); AddPreset( TEXT( "Full Treble" ) );
eq_vec.push_back( eq_headphones ); AddPreset( TEXT( "Headphones" ) );
eq_vec.push_back( eq_laptop ); AddPreset( TEXT( "Laptop Speakers" ) );
eq_vec.push_back( eq_large_hall ); AddPreset( TEXT( "Large Hall" ) );
eq_vec.push_back( eq_live ); AddPreset( TEXT( "Live" ) );
eq_vec.push_back( eq_more_bass ); AddPreset( TEXT( "More Bass" ) );
eq_vec.push_back( eq_party ); AddPreset( TEXT( "Party" ) );
eq_vec.push_back( eq_pop ); AddPreset( TEXT( "Pop" ) );
eq_vec.push_back( eq_reggae ); AddPreset( TEXT( "Reggae" ) );
eq_vec.push_back( eq_rock ); AddPreset( TEXT( "Rock" ) );
eq_vec.push_back( eq_ska ); AddPreset( TEXT( "Ska" ) );
eq_vec.push_back( eq_soft ); AddPreset( TEXT( "Soft" ) );
eq_vec.push_back( eq_soft_rock ); AddPreset( TEXT( "Soft Rock" ) );
eq_vec.push_back( eq_techno ); AddPreset( TEXT( "Techno" ) );
// Fix invalid indices
if( iCurPreset < -1 )
{
iCurPreset = -1;
}
else
{
const int iLen = ( int )eq_vec.size();
if( iCurPreset >= iLen )
{
iCurPreset = iLen - 1;
}
}
// TODO load/save eqf files
// GPL eqf loading from koders.com
// equalizer.c / xmms2 A Gtk2 port of xmms.(xmms2)
// equalizer.c / Digital Disco System(dds)
return true;
}

View File

@ -0,0 +1,205 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Playback.h"
#include "Config.h"
#include <time.h>
#include <stdlib.h>
int iCurOrder = ORDER_DEFAULT;
ConfIntMinMax ciCurOrder( &iCurOrder, TEXT( "Order" ), CONF_MODE_INTERNAL, ORDER_DEFAULT, ORDER_FIRST, ORDER_LAST );
bool bRandomReady = false;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int Playback::Order::GetCurMode()
{
return iCurOrder;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Order::SetMode( int iMode )
{
iCurOrder = iMode;
ciCurOrder.MakeValidDefault();
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
TCHAR * Playback::Order::GetModeName( int iMode )
{
switch( iMode )
{
case ORDER_SINGLE: return TEXT( " Single" );
case ORDER_SINGLE_REPEAT: return TEXT( " Single + Repeat" );
case ORDER_NORMAL: return TEXT( " Normal" );
case ORDER_NORMAL_REPEAT: return TEXT( " Normal + Repeat" );
case ORDER_INVERSE: return TEXT( " Inverse" );
case ORDER_INVERSE_REPEAT: return TEXT( " Inverse + Repeat" );
case ORDER_RANDOM: return TEXT( " Random" );
default: return NULL;
}
}
/*
int Playback::Order::GetModeNameLen( int iMode )
{
switch( uMode )
{
case ORDER_SINGLE: return 7;
case ORDER_SINGLE_REPEAT: return 16;
case ORDER_NORMAL: return 7;
case ORDER_NORMAL_REPEAT: return 16;
case ORDER_INVERSE: return 8;
case ORDER_INVERSE_REPEAT: return 17;
case ORDER_RANDOM: return 7;
default: return 0;
}
}
*/
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool NextNormal( int & iCur, int iMax )
{
if( iCur >= iMax ) return false;
iCur++;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool NextNormalRepeat( int & iCur, int iMax )
{
if( iCur >= iMax )
iCur = 0;
else
iCur++;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool NextInverse( int & iCur, int iMax )
{
if( iCur <= 0 ) return false;
iCur--;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool NextInverseRepeat( int & iCur, int iMax )
{
if( iCur <= 0 )
iCur = iMax;
else
iCur--;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool NextRandom( int & iCur, int iMax )
{
if( iMax < 2 ) return false;
if( !bRandomReady )
{
srand( ( unsigned )time( NULL ) );
bRandomReady = true;
}
const int iNew = ( int )( rand() / ( float )RAND_MAX * iMax );
if( iNew != iCur )
iCur = iNew;
else
{
if( iCur >= iMax )
iCur = 0;
else
iCur++;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Order::Next( int & iCur, int iMax )
{
switch( iCurOrder )
{
case ORDER_SINGLE: return false;
case ORDER_SINGLE_REPEAT: return true;
case ORDER_NORMAL: return NextNormal( iCur, iMax );
case ORDER_NORMAL_REPEAT: return NextNormalRepeat( iCur, iMax );
case ORDER_INVERSE: return NextInverse( iCur, iMax );
case ORDER_INVERSE_REPEAT: return NextInverseRepeat( iCur, iMax );
case ORDER_RANDOM: return NextRandom( iCur, iMax );
default: return false;
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Playback::Order::Prev( int & iCur, int iMax )
{
switch( iCurOrder )
{
case ORDER_SINGLE: return false;
case ORDER_SINGLE_REPEAT: return true;
case ORDER_NORMAL: return NextInverse( iCur, iMax );
case ORDER_NORMAL_REPEAT: return NextInverseRepeat( iCur, iMax );
case ORDER_INVERSE: return NextNormal( iCur, iMax );
case ORDER_INVERSE_REPEAT: return NextNormalRepeat( iCur, iMax );
case ORDER_RANDOM: return NextRandom( iCur, iMax );
default: return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
////////////////////////////////////////////////////////////////////////////////
// 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_PLAYLIST_H
#define PA_PLAYLIST_H
#include "Global.h"
#include "PlaylistControler.h"
#include "PlaylistView.h"
#define PLAINAMP_PL_REM_SEL 50004
#define PLAINAMP_PL_REM_CROP 50005
extern HWND WindowPlaylist;
extern PlaylistControler * playlist;
namespace Playlist
{
bool Create();
/*
int GetCurIndex();
int GetMaxIndex();
bool SetCurIndex( int iIndex );
*/
TCHAR * GetFilename( int iIndex );
int GetFilename( int iIndex, char * szAnsiFilename, int iChars );
int GetTitle( int iIndex, char * szAnsiTitle, int iChars );
bool DialogOpen();
bool DialogSaveAs();
bool AppendPlaylistFile( TCHAR * szFilename );
bool ExportPlaylistFile( TCHAR * szFilename );
/*
bool Append( TCHAR * szDisplay, TCHAR * szFilename );
bool Add( int iIndex, TCHAR * szDisplay, TCHAR * szFilename );
bool Clear(); // aka RemoveAll()
bool RemoveSelected();
bool Crop(); // aka RemoveUnselected
bool SelectZero();
bool SelectAll();
*/
};
#endif // PA_PLAYLIST_H

View File

@ -0,0 +1,451 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "PlaylistControler.h"
#include "Config.h"
#include "Font.h"
bool bPlaylistFollow;
ConfBool cbPlaylistFollow( &bPlaylistFollow, TEXT( "PlaylistFollow" ), CONF_MODE_PUBLIC, true );
void PlaylistControler::MoveSelected( int iDistance )
{
if( iDistance == -1 )
{
if( ListView_GetItemState( _hView, 0, LVIS_SELECTED ) )
{
// Cannot move upwards
return;
}
}
else if( iDistance == 1 )
{
if( ListView_GetItemState( _hView, _database.GetMaxIndex(), LVIS_SELECTED ) )
{
// Cannot move downwards
return;
}
}
else
{
// More distance maybe later
return;
}
const int iFocus = ListView_GetNextItem( _hView, ( UINT )-1, LVIS_FOCUSED );
// Negative is to the top
LRESULT iBefore = 0;
LRESULT iAfter = -2; // Extra value to check after big for-loop
for( ; ; )
{
// Count
LRESULT iAfter = ListView_GetNextItem( _hView, iBefore - 1, LVNI_SELECTED );
if( iAfter == -1 ) break; // No more selections selected
LRESULT iFirst = iAfter;
// Search end of selection block
iBefore = iAfter + 1;
for( ; ; )
{
iAfter = ListView_GetNextItem( _hView, iBefore - 1, LVNI_SELECTED );
if( iAfter == iBefore )
{
// Keep searching
iBefore++;
}
else
{
// End found (iBefore is the first not selected)
const int iSelSize = iBefore - iFirst;
if( iDistance == -1 )
{
// Updwards
const int iOldIndex = iFirst - 1;
const int iNewIndex = iOldIndex + iSelSize;
TCHAR * szData = ( TCHAR * )_database.Get( iOldIndex );
_database.Erase( iOldIndex );
_database.Insert( iNewIndex, szData );
ListView_SetItemState( _hView, iOldIndex, LVIS_SELECTED, LVIS_SELECTED );
ListView_SetItemState( _hView, iNewIndex, 0, LVIS_SELECTED );
ListView_RedrawItems( _hView, iOldIndex, iNewIndex );
}
else
{
// Downwards
const int iOldIndex = iFirst + iSelSize;
const int iNewIndex = iFirst;
TCHAR * szData = ( TCHAR * )_database.Get( iOldIndex );
_database.Erase( iOldIndex );
_database.Insert( iNewIndex, szData );
ListView_SetItemState( _hView, iOldIndex, LVIS_SELECTED, LVIS_SELECTED );
ListView_SetItemState( _hView, iNewIndex, 0, LVIS_SELECTED );
ListView_RedrawItems( _hView, iNewIndex, iOldIndex );
}
iBefore++;
break;
}
}
}
if( iAfter != -2 ) return; // Nothing was selected so nothing was moved
ListView_SetItemState( _hView, iFocus + iDistance, LVIS_FOCUSED, LVIS_FOCUSED );
Refresh();
}
int PlaylistControler::GetCurIndex()
{
return _database.GetCurIndex();
}
int PlaylistControler::GetMaxIndex()
{
return _database.GetMaxIndex();
}
int PlaylistControler::GetSize()
{
return _database.GetSize();
}
void PlaylistControler::SetCurIndex( int iIndex )
{
const int iCurIndexBefore = _database.GetCurIndex();
_database.SetCurIndex( iIndex );
if( bPlaylistFollow )
{
ListView_SetItemState( _hView, ( UINT )-1, 0, LVIS_SELECTED | LVIS_FOCUSED );
ListView_SetItemState( _hView, iIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
}
if( iCurIndexBefore != -1 )
ListView_RedrawItems( _hView, iCurIndexBefore, iCurIndexBefore );
ListView_RedrawItems( _hView, iIndex, iIndex );
}
// Returns <true> on digit count change
bool PlaylistControler::FixDigitsMore()
{
const int iCountAfter = _database.GetSize();
const int iDigitsBefore = _iDigits;
while( iCountAfter > _iDigitMax )
{
_iDigitMin *= 10; // 10 -> 100
_iDigitMax = _iDigitMax * 10 + 9; // 99 -> 999
_iDigits++; // 2 -> 3
}
return ( ( _iDigits != iDigitsBefore )
|| ( iCountAfter == 1 ) ); // Force update when first item is inserted
}
// Returns <true> on digit count change
bool PlaylistControler::FixDigitsLess()
{
const int iCountAfter = _database.GetSize();
const int iDigitsBefore = _iDigits;
while( ( iCountAfter < _iDigitMin ) && ( _iDigits > 1 ) )
{
_iDigitMin /= 10; // 999 -> 99
_iDigitMax /= 10; // 100 -> 10
_iDigits--; // 3 -> 2
}
return ( _iDigits != iDigitsBefore );
}
void PlaylistControler::Refresh()
{
AutosizeColumns();
const int iFirst = ListView_GetTopIndex( _hView );
const int iLast = iFirst + ListView_GetCountPerPage( _hView );
ListView_RedrawItems( _hView, iFirst, iLast );
}
PlaylistControler::PlaylistControler( HWND hView, bool bEnableZeroPadding, int * piIndexSlave )
{
_hView = hView;
_bZeroPadding = bEnableZeroPadding;
_iDigits = 1;
_iDigitMin = 1;
_iDigitMax = 9;
_database.SetCurIndexSlave( piIndexSlave );
Refresh();
// TODO clear list view here???
}
void PlaylistControler::PushBack( TCHAR * szText )
{
const int iSize = _database.GetMaxIndex();
_database.PushBack( szText );
ListView_SetItemCount( _hView, _database.GetSize() );
if( FixDigitsMore() ) Refresh();
}
void PlaylistControler::Insert( int i, TCHAR * szText )
{
const int iSize = _database.GetMaxIndex();
_database.Insert( i, szText );
ListView_SetItemCount( _hView, _database.GetSize() );
if( FixDigitsMore() ) Refresh();
}
void PlaylistControler::RemoveAll()
{
_database.Clear();
ListView_DeleteAllItems( _hView );
if( FixDigitsLess() ) Refresh();
}
void PlaylistControler::RemoveSelected( bool bPositive )
{
SendMessage( _hView, WM_SETREDRAW, FALSE, 0 );
if( bPositive )
{
LRESULT iWalk = 0;
for( ; ; )
{
// MSDN: The specified item itself is excluded from the search.
iWalk = ListView_GetNextItem( _hView, iWalk - 1, LVNI_SELECTED );
if( iWalk != -1 )
{
_database.Erase( iWalk );
ListView_DeleteItem( _hView, iWalk );
}
else
{
break;
}
}
}
else
{
LRESULT iBefore = 0;
LRESULT iAfter = 0;
for( ; ; )
{
// MSDN: The specified item itself is excluded from the search.
iAfter = ListView_GetNextItem( _hView, iBefore - 1, LVNI_SELECTED );
if( iAfter != -1 )
{
// <iAfter> is the first selected
// so we delete all before and restart
// at the beginning
const int iDelIndex = iBefore;
for( int i = iBefore; i < iAfter; i++ )
{
_database.Erase( iDelIndex );
ListView_DeleteItem( _hView, iDelIndex );
}
iBefore++; // Exclude the one we found selected right before
}
else
{
if( iBefore == 0 )
{
// All selected
_database.Clear();
ListView_DeleteAllItems( _hView );
}
else
{
const int iSize = _database.GetSize();
const int iDelIndex = iBefore;
for( int i = iBefore; i < iSize; i++ )
{
_database.Erase( iDelIndex );
ListView_DeleteItem( _hView, iDelIndex );
}
}
break;
}
}
}
bool bRefresh = FixDigitsLess();
SendMessage( _hView, WM_SETREDRAW, TRUE, 0 );
if( bRefresh ) Refresh();
}
void PlaylistControler::SelectAll( bool bPositive )
{
ListView_SetItemState( _hView, ( UINT )-1, bPositive ? LVIS_SELECTED : 0, LVIS_SELECTED );
}
void PlaylistControler::SelectInvert()
{
SendMessage( _hView, WM_SETREDRAW, FALSE, 0 );
const int iOneTooMuch = _database.GetSize();
for( int i = 0; i < iOneTooMuch; i++ )
{
ListView_SetItemState(
_hView,
i,
( ListView_GetItemState( _hView, i, LVIS_SELECTED ) == LVIS_SELECTED )
? 0
: LVIS_SELECTED,
LVIS_SELECTED
);
}
SendMessage( _hView, WM_SETREDRAW, TRUE, 0 );
}
const TCHAR * PlaylistControler::Get( int i )
{
return _database.Get( i );
}
void PlaylistControler::Fill( LVITEM & request )
{
if( ( request.mask & LVIF_TEXT ) == 0 ) return;
if( request.iSubItem )
{
// Text
_sntprintf( request.pszText, request.cchTextMax, TEXT( "%s" ), _database.Get( request.iItem ) );
}
else
{
// Number
if( _bZeroPadding )
{
TCHAR szFormat[ 6 ];
_stprintf( szFormat, TEXT( "%%0%dd" ), _iDigits );
_sntprintf( request.pszText, request.cchTextMax, szFormat, request.iItem + 1 );
}
else
{
_sntprintf( request.pszText, request.cchTextMax, TEXT( "%d" ), request.iItem + 1 );
}
}
}
void PlaylistControler::EnableZeroPadding( bool bActive )
{
if( bActive == _bZeroPadding ) return;
LVCOLUMN col;
memset( &col, 0, sizeof( LVCOLUMN ) );
col.mask = LVCF_FMT;
if( bActive )
{
// TODO recalculation yes/no?
/*
int iSize = _database.GetSize();
if( iSize != 0 )
{
int iDigits = 0;
while( iSize > 0 )
{
iSize /= 10;
iDigits++;
}
_iDigits = iSize;
_iDigitMin = 1;
_iDigitMax = 9;
while( iSize-- > 0 )
{
_iDigitMin *= 10;
_iDigitMax = _iDigitMax * 10 + 9;
}
}
else
{
_iDigits = 1;
_iDigitMin = 1;
_iDigitMax = 9;
}
*/
col.fmt = LVCFMT_LEFT;
ListView_SetColumn( _hView, 0, &col );
Refresh();
}
else
{
col.fmt = LVCFMT_RIGHT;
ListView_SetColumn( _hView, 0, &col );
Refresh();
}
_bZeroPadding = bActive;
}
void PlaylistControler::AutosizeColumns()
{
RECT r;
if( !GetClientRect( _hView, &r ) ) return;
if( _bZeroPadding )
{
ListView_SetColumnWidth( _hView, 0, LVSCW_AUTOSIZE );
const int iWidth = ListView_GetColumnWidth( _hView, 0 );
ListView_SetColumnWidth( _hView, 1, r.right - r.left - iWidth );
}
else
{
HDC hdc = GetDC( _hView );
const HFONT hOldFont = ( HFONT )SelectObject( hdc, Font::Get() );
SIZE size;
BOOL res = GetTextExtentPoint32( hdc, TEXT( "0" ), 1, &size );
SelectObject( hdc, hOldFont );
ReleaseDC( _hView, hdc );
const int iWidth = res ? ( int )( size.cx * ( _iDigits + 0.25f ) ) : 120;
ListView_SetColumnWidth( _hView, 0, iWidth );
ListView_SetColumnWidth( _hView, 1, r.right - r.left - iWidth );
}
}
void PlaylistControler::Resize( HWND hParent )
{
/*
RECT rc;
GetClientRect( hParent, &rc );
MoveWindow( _hView, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE );
*/
AutosizeColumns();
}

View File

@ -0,0 +1,65 @@
////////////////////////////////////////////////////////////////////////////////
// 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 PLAYLIST_CONTROLER_H
#define PLAYLIST_CONTROLER_H 1
#include <tchar.h>
#include <windows.h>
#include <commctrl.h>
#include "PlaylistModel.h"
// TODO: column width update on scrollbar show/hide
class PlaylistControler
{
PlaylistModel _database;
HWND _hView;
bool _bZeroPadding;
int _iDigits; // 3
int _iDigitMin; // 100
int _iDigitMax; // 999
private:
bool FixDigitsMore();
bool FixDigitsLess();
void Refresh();
void AutosizeColumns();
public:
PlaylistControler( HWND hView, bool bEnableZeroPadding, int * piIndexSlave );
void MoveSelected( int iDistance );
int GetCurIndex();
int GetMaxIndex();
int GetSize();
void SetCurIndex( int iIndex );
void PushBack( TCHAR * szText );
void Insert( int i, TCHAR * szText );
void RemoveAll();
void RemoveSelected( bool bPositive );
void SelectAll( bool bPositive );
void SelectInvert();
const TCHAR * Get( int i );
void Fill( LVITEM & request );
void EnableZeroPadding( bool bActive );
void Resize( HWND hParent );
};
#endif // PLAYLIST_CONTROLER_H

View File

@ -0,0 +1,103 @@
////////////////////////////////////////////////////////////////////////////////
// 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 PLAYLIST_MODEL_H
#define PLAYLIST_MODEL_H 1
#include <windows.h>
#include <tchar.h>
#include <vector>
using namespace std;
class PlaylistModel
{
vector<TCHAR *> _database;
int _iCurIndex;
int * _piCurIndex;
public:
PlaylistModel()
{
_piCurIndex = &_iCurIndex;
}
PlaylistModel( int * piIndexSlave )
{
_piCurIndex = piIndexSlave;
}
void SetCurIndexSlave( int * piIndexSlave )
{
// *piIndexSlave = *_piCurIndex;
_piCurIndex = piIndexSlave;
}
void PushBack( TCHAR * szText )
{
_database.push_back( szText );
}
void Insert( int i, TCHAR * szText )
{
if( i <= *_piCurIndex ) ( *_piCurIndex )++;
_database.insert( _database.begin() + i, szText );
}
void Erase( int i )
{
if( i < *_piCurIndex ) ( *_piCurIndex )--;
_database.erase( _database.begin() + i );
}
const TCHAR * Get( int i )
{
if( 0 > i || i >= ( int )_database.size() )
{
static const TCHAR * szError = TEXT( "INDEX OUT OF RANGE" );
return szError;
}
return _database[ i ];
}
void Clear()
{
_database.clear();
*_piCurIndex = -1;
}
int GetMaxIndex()
{
return _database.size() - 1;
}
int GetCurIndex()
{
return *_piCurIndex;
}
void SetCurIndex( int iIndex )
{
if( 0 > iIndex || iIndex >= ( int )_database.size() ) return;
*_piCurIndex = iIndex;
}
int GetSize()
{
return _database.size();
}
};
#endif // PLAYLIST_MODEL_H

View File

@ -0,0 +1,772 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Playlist.h"
#include "Main.h"
#include "Status.h"
#include "Rebar.h"
#include "Playback.h"
#include "Config.h"
#include "Util.h"
WNDPROC WndprocPlaylistBackup = NULL;
LRESULT CALLBACK WndprocPlaylist( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
PlaylistControler * playlist = NULL; // extern
bool bPlaylistEntryNumberZeroPadding;
ConfBool cbPlaylistEntryNumberZeroPadding( &bPlaylistEntryNumberZeroPadding, TEXT( "PlaylistEntryNumberZeroPadding" ), CONF_MODE_PUBLIC, true );
int iCurPlaylistPosition;
ConfInt ciCurPlaylistPosition( &iCurPlaylistPosition, TEXT( "CurPlaylistPosition" ), CONF_MODE_INTERNAL, -1 );
bool bInfinitePlaylist;
ConfBool cbInfinitePlaylist( &bInfinitePlaylist, TEXT( "InfinitePlaylist" ), CONF_MODE_PUBLIC, false );
void PlaylistView::Create()
{
RECT ClientMain;
GetClientRect( WindowMain, &ClientMain );
const int iClientHeight = ClientMain.bottom - ClientMain.top;
const int iClientWidth = ClientMain.right - ClientMain.left;
const int iPlaylistHeight = iClientHeight - iRebarHeight - iStatusHeight;
LoadCommonControls();
DWORD dwStyle;
// HWND WindowPlaylist;
BOOL bSuccess = TRUE;
dwStyle = WS_TABSTOP |
WS_CHILD |
WS_BORDER |
WS_VISIBLE |
LVS_AUTOARRANGE | // TODO
LVS_REPORT |
LVS_OWNERDATA |
LVS_NOCOLUMNHEADER ;
WindowPlaylist = CreateWindowEx( WS_EX_CLIENTEDGE, // ex style
WC_LISTVIEW, // class name - defined in commctrl.h
TEXT( "" ), // dummy text
dwStyle, // style
0,
iRebarHeight, // + -2,
iClientWidth,
iPlaylistHeight,
WindowMain, // parent
NULL, // ID
g_hInstance, // instance
NULL); // no extra data
if(!WindowPlaylist) return; // TODO
playlist = new PlaylistControler( WindowPlaylist, bPlaylistEntryNumberZeroPadding, &iCurPlaylistPosition );
// Exchange window procedure
WndprocPlaylistBackup = ( WNDPROC )GetWindowLong( WindowPlaylist, GWL_WNDPROC );
if( WndprocPlaylistBackup != NULL )
{
SetWindowLong( WindowPlaylist, GWL_WNDPROC, ( LONG )WndprocPlaylist );
}
ListView_SetExtendedListViewStyle( WindowPlaylist, LVS_EX_FULLROWSELECT ); // | LVS_EX_GRIDLINES );
playlist->Resize( WindowMain );
/*
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/listview/structures/lvcolumn.asp
*
* Remarks:
* If a column is added to a list-view control with index 0 (the leftmost column)
* and with LVCFMT_RIGHT or LVCFMT_CENTER specified, the text is not right-aligned
* or centered. The text in the index 0 column is left-aligned. Therefore if you
* keep inserting columns with index 0, the text in all columns are left-aligned.
* If you want the first column to be right-aligned or centered you can make a dummy
* column, then insert one or more columns with index 1 or higher and specify the
* alignment you require. Finally delete the dummy column.
*/
LV_COLUMN lvColumn;
memset( &lvColumn, 0, sizeof( LV_COLUMN ) );
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
// Number column (with dummy hack)
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 0;
lvColumn.pszText = TEXT( "" );
ListView_InsertColumn( WindowPlaylist, 0, &lvColumn );
lvColumn.fmt = LVCFMT_RIGHT;
lvColumn.cx = 120;
lvColumn.pszText = TEXT( "" );
ListView_InsertColumn( WindowPlaylist, 1, &lvColumn );
ListView_DeleteColumn( WindowPlaylist, 0 );
// Entry
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 120;
lvColumn.pszText = TEXT( "Filename" );
ListView_InsertColumn(WindowPlaylist, 1, &lvColumn);
/*
stupid test code
SCROLLINFO scrollinfo;
ZeroMemory( &scrollinfo, sizeof( SCROLLINFO ) );
scrollinfo.cbSize = sizeof( SCROLLINFO );
scrollinfo.fMask = 0; // SIF_DISABLENOSCROLL;
if( !GetScrollInfo( WindowPlaylist, SB_VERT, &scrollinfo ) )
{
MessageBox( 0, "ERROR", "", 0 );
}
else
{
MessageBox( 0, "OKAY", "", 0 );
scrollinfo.fMask = SIF_DISABLENOSCROLL;
SetScrollInfo( WindowPlaylist, SB_VERT, &scrollinfo, TRUE );
}
if( !ShowScrollBar( WindowPlaylist, SB_VERT, TRUE ) )
{
MessageBox( 0, "ERROR ShowScrollBar", "", 0 );
}
SCROLLBARINFO scrollbarinfo;
scrollbarinfo.cbSize = sizeof( SCROLLBARINFO );
if( !GetScrollBarInfo( WindowPlaylist, OBJID_VSCROLL, &scrollbarinfo ) )
{
MessageBox( 0, "ERROR GetScrollBarInfo", "", 0 );
}
*/
}
// Dragging
static int iItemHeight = 15;
static int iDragStartY = 0;
static bool bDragging = false;
// Liquid selection
static bool bLiquidSelecting = false;
static int iLastTouched = -1;
// Liquid or range selection
static int iSelAnchor = -1;
LRESULT CALLBACK WndprocPlaylist( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
/*
* Click, click and click
*
* [Alt] [Ctrl] [Shift] Action
* -------+---------+---------+-----------------------
* X | X | X |
* X | X | |
* X | | X |
* X | | |
* | X | X | Range selection
* | X | | Toggle selection
* | | X | Range selection
* | | | Single selection
*
*
* Click, hold and move
*
* [Alt] [Ctrl] [Shift] Action
* -------+---------+---------+-----------------------
* X | X | X | Selection move
* X | X | | Selection move
* X | | X | Selection move
* X | | | Selection move
* | X | X |
* | X | |
* | | X |
* | | | Liquid selection
*/
static bool bCapturing = true;
switch( message )
{
/*
case WM_CAPTURECHANGED:
if( bCapturing && ( GetCapture() != WindowPlaylist ) )
{
MessageBox( 0, TEXT( "Capture stolen" ), TEXT( "" ), 0 );
}
break;
*/
case WM_MOUSEMOVE:
if( bLiquidSelecting )
{
LVHITTESTINFO hittest;
memset( &hittest, 0, sizeof( LVHITTESTINFO ) );
hittest.pt.x = LOWORD( lp );
hittest.pt.y = HIWORD( lp );
const int iIndex = ( int )ListView_HitTest( WindowPlaylist, &hittest );
if( iIndex == -1 ) return 0;
if( iIndex == iLastTouched ) return 0;
// Note: Update this as early as possible!
// We cannot be sure this code is
// not called two or three times at the
// same time without losing much speed
// but this at least lowers the chance
const int iLastTouchedBackup = iLastTouched;
iLastTouched = iIndex;
const bool bControl = ( ( GetKeyState( VK_CONTROL ) & 0x8000 ) != 0 );
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVIS_FOCUSED );
ListView_SetItemState( WindowPlaylist, iIndex, LVIS_FOCUSED, LVIS_FOCUSED );
// Below anchor?
if( iIndex > iSelAnchor )
{
if( iIndex > iLastTouchedBackup )
{
// iSelAnchor
// ..
// iLastTouchedBackup
// ..
// >> iIndex <<
if( iLastTouchedBackup > iSelAnchor )
{
// Select downwards
for( int i = iLastTouchedBackup + 1; i <= iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
// iLastTouchedBackup
// ..
// iSelAnchor
// ..
// >> iIndex <<
else
{
// Unselect downwards
for( int i = iLastTouchedBackup; i < iSelAnchor; i++ )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
// Select downwards
for( int i = iSelAnchor + 1; i <= iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
}
else // iIndex < iLastTouchedBackup
{
// iSelAnchor
// ..
// >> iIndex <<
// ..
// iLastTouchedBackup
// Unselect upwards
for( int i = iLastTouchedBackup; i > iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
// Above anchor?
else if( iIndex < iSelAnchor )
{
if( iIndex < iLastTouchedBackup )
{
// >> iIndex <<
// ..
// iSelAnchor
// ..
// iLastTouchedBackup
if( iIndex < iLastTouchedBackup )
{
// Unselect upwards
for( int i = iLastTouchedBackup; i > iSelAnchor; i-- )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
// Select upwards
for( int i = iSelAnchor - 1; i >= iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
// >> iIndex <<
// ..
// iLastTouchedBackup
// ..
// iSelAnchor
else // iIndex < iLastTouchedBackup
{
// Select upwards
for( int i = iLastTouchedBackup - 1; i >= iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
}
else // iIndex > iLastTouchedBackup
{
// iLastTouchedBackup
// ..
// >> iIndex <<
// ..
// iSelAnchor
// Unselect downwards
for( int i = iLastTouchedBackup; i < iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
// At anchor
else // iIndex == iSelAnchor
{
if( iIndex < iLastTouchedBackup )
{
// iSelAnchor / >> iIndex <<
// ..
// iLastTouchedBackup
// Unselect upwards
for( int i = iLastTouchedBackup; i > iSelAnchor; i-- )
{
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
else // iIndex > iLastTouchedBackup
{
// iLastTouchedBackup
// ..
// iSelAnchor / >> iIndex <<
// Unselect downwards
for( int i = iLastTouchedBackup; i < iSelAnchor; i++ )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
}
else if( bDragging )
{
static bool bMoveLock = false;
if( bMoveLock ) return 0;
bMoveLock = true;
const int y = HIWORD( lp );
const int diff = y - iDragStartY;
if( abs( diff ) > iItemHeight / 2 )
{
iDragStartY += ( ( diff > 0 ) ? iItemHeight : -iItemHeight );
playlist->MoveSelected( ( diff > 0 ) ? +1 : -1 );
}
bMoveLock = false;
}
return 0;
case WM_LBUTTONDOWN:
{
static int iLastClicked = -1;
static bool bLastClickNoneOrShift = true;
SetFocus( hwnd ); // TODO monitor focus loss
LVHITTESTINFO hittest;
memset( &hittest, 0, sizeof( LVHITTESTINFO ) );
GetCursorPos( &hittest.pt );
ScreenToClient( hwnd, &hittest.pt );
const int iIndex = ( int )ListView_HitTest( WindowPlaylist, &hittest );
if( iIndex == -1 ) return 0;
const bool bShift = ( ( GetKeyState( VK_SHIFT ) & 0x8000 ) != 0 );
const bool bControl = ( ( GetKeyState( VK_CONTROL ) & 0x8000 ) != 0 );
const bool bAlt = ( ( GetKeyState( VK_MENU ) & 0x8000 ) != 0 );
// [Shift] or [Shift]+[Ctrl]?
if( bShift )
{
if( bAlt ) return 0;
// Last click usable as selection anchor?
if( !bLastClickNoneOrShift )
{
// Treat as normal click
iSelAnchor = iIndex;
iLastClicked = iIndex;
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVIS_SELECTED | LVIS_FOCUSED );
ListView_SetItemState( WindowPlaylist, iIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
bLiquidSelecting = true;
bLastClickNoneOrShift = true;
return 0;
}
if( iIndex != iLastClicked )
{
// Below anchor?
if( iIndex > iSelAnchor )
{
// Below last click?
if( iIndex > iLastClicked )
{
// Other side of anchor?
if( iLastClicked < iSelAnchor )
{
// Unselect downwards
for( int i = iLastClicked; i < iSelAnchor; i++ )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
// Select downwards
for( int i = iSelAnchor; i <= iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
// Same side of anchor?
else
{
// Select downwards
for( int i = iLastClicked + 1; i <= iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
}
// Above last click?
else // iIndex < iLastClicked
{
// Unselect upwards
for( int i = iLastClicked; i > iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
// Above anchor?
else if( iIndex < iSelAnchor )
{
// Above last clicked?
if( iIndex < iLastClicked )
{
// Other side of anchor?
if( iLastClicked > iSelAnchor )
{
// Unselect upwards
for( int i = iLastClicked; i > iSelAnchor; i-- )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
// Select upwards
for( int i = iSelAnchor; i >= iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
// Same side of anchor?
else
{
// Select upwards
for( int i = iLastClicked - 1; i >= iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, LVIS_SELECTED, LVIS_SELECTED );
}
}
// Below last clicked?
else // iIndex > iLastClicked
{
// Unselect downwards
for( int i = iLastClicked; i < iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
// At anchor
else // iIndex == iSelAnchor
{
if( iLastClicked < iSelAnchor )
{
// Unselect downwards
for( int i = iLastClicked; i < iIndex; i++ )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
else if( iLastClicked > iSelAnchor )
{
// Unselect upwards
for( int i = iLastClicked; i > iIndex; i-- )
ListView_SetItemState( WindowPlaylist, i, 0, LVIS_SELECTED );
}
}
iLastClicked = iIndex;
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVIS_FOCUSED );
ListView_SetItemState( WindowPlaylist, iIndex, LVIS_FOCUSED, LVIS_FOCUSED );
}
bLastClickNoneOrShift = true;
}
// [Ctrl]?
else if( bControl )
{
if( bAlt ) return 0;
iLastTouched = iIndex;
// Toggle selection
const bool bSelected = ( ListView_GetItemState( WindowPlaylist, iIndex, LVIS_SELECTED ) == LVIS_SELECTED );
ListView_SetItemState( WindowPlaylist, iIndex, bSelected ? 0 : LVIS_SELECTED, LVIS_SELECTED );
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVIS_FOCUSED );
ListView_SetItemState( WindowPlaylist, iIndex, LVIS_FOCUSED, LVIS_FOCUSED );
bLastClickNoneOrShift = false;
}
// [Alt]?
else if( bAlt )
{
// Update item height
RECT rc;
GetClientRect( WindowPlaylist, &rc );
const int iItemsPerPage = ListView_GetCountPerPage( WindowPlaylist );
iItemHeight = ( rc.bottom - rc.top ) / iItemsPerPage;
iDragStartY = hittest.pt.y;
bDragging = true;
bCapturing = true;
SetCapture( WindowPlaylist );
}
// No modifiers?
else
{
iSelAnchor = iIndex;
iLastClicked = iIndex;
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVIS_SELECTED | LVIS_FOCUSED );
ListView_SetItemState( WindowPlaylist, iIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
bLiquidSelecting = true;
bLastClickNoneOrShift = true;
bCapturing = true;
SetCapture( WindowPlaylist );
}
}
return 0;
case WM_LBUTTONUP:
bLiquidSelecting = false;
bDragging = false;
bCapturing = false;
ReleaseCapture();
return 0;
case WM_SYSKEYDOWN:
switch( wp ) // [Alt]+[...]
{
case VK_UP:
playlist->MoveSelected( -1 );
break;
case VK_DOWN:
playlist->MoveSelected( +1 );
break;
}
break;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
case WM_CHAR:
case WM_KEYUP:
// SMALL LETTERS!!!!!!
switch( wp )
{
case 'z':
case 'y':
case 'x':
case 'c':
case 'v':
case 'b':
case 'l':
return 0;
}
break;
case WM_KEYDOWN:
{
const bool bShift = ( ( GetKeyState( VK_SHIFT ) & 0x8000 ) != 0 );
const bool bControl = ( ( GetKeyState( VK_CONTROL ) & 0x8000 ) != 0 );
// Note: [Alt] goes to WM_SYSKEYDOWN instead
// const bool bAlt = ( ( GetKeyState( VK_MENU ) & 0x8000 ) != 0 );
switch( wp )
{
case VK_LEFT:
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_REW5S, 0 );
return 0;
case VK_RIGHT:
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_FFWD5S, 0 );
return 0;
case VK_UP:
if( bInfinitePlaylist )
{
// First item has focus?
if( ListView_GetNextItem( WindowPlaylist, ( UINT )-1, LVNI_FOCUSED ) != 0 ) break;
if( bControl && !bShift )
{
// Move caret only
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVNI_FOCUSED );
ListView_SetItemState( WindowPlaylist, playlist->GetMaxIndex(), LVNI_FOCUSED, LVNI_FOCUSED );
return 0;
}
else
{
// Move Caret and selection
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVNI_FOCUSED );
ListView_SetItemState( WindowPlaylist, playlist->GetMaxIndex() - 1, LVNI_FOCUSED, LVNI_FOCUSED );
wp = VK_DOWN;
}
}
break;
case VK_DOWN:
if( bInfinitePlaylist )
{
// Last item has focus?
if( ListView_GetNextItem( WindowPlaylist, playlist->GetMaxIndex() - 1, LVNI_FOCUSED ) == -1 ) break;
if( bControl && !bShift )
{
// Move caret only
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVNI_FOCUSED );
ListView_SetItemState( WindowPlaylist, 0, LVNI_FOCUSED, LVNI_FOCUSED );
return 0;
}
else
{
// Workaround
ListView_SetItemState( WindowPlaylist, ( UINT )-1, 0, LVNI_FOCUSED );
ListView_SetItemState( WindowPlaylist, 1, LVNI_FOCUSED, LVNI_FOCUSED );
wp = VK_UP;
}
}
break;
case VK_DELETE:
{
if( bShift ) break;
if( bControl )
playlist->RemoveSelected( false );
else
playlist->RemoveSelected( true );
break;
}
case VK_RETURN:
playlist->SetCurIndex( ListView_GetNextItem( WindowPlaylist, ( UINT )-1, LVIS_FOCUSED ) );
SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON2, 0 );
return 0;
case 'Y':
case 'Z':
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON1, 0 );
return 0;
case 'X':
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON2, 0 );
return 0;
case 'C':
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON3, 0 );
return 0;
case 'V':
// Todo modifiers pressed? -> fadeout/...
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON4, 0 );
return 0;
case 'B':
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON5, 0 );
return 0;
/*
case 'J':
if( bShift || bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, WINAMP_JUMPFILE, 0 );
return 0;
*/
case 'L':
if( bControl ) return 0;
SendMessage( WindowMain, WM_COMMAND, bShift ? WINAMP_FILE_DIR : WINAMP_FILE_PLAY, 0 );
return 0;
}
break;
}
case WM_LBUTTONDBLCLK:
// iCurIndex = Playlist_MouseToIndex();
LVHITTESTINFO hittest;
memset( &hittest, 0, sizeof( LVHITTESTINFO ) );
GetCursorPos( &hittest.pt );
ScreenToClient( hwnd, &hittest.pt );
const int iIndex = ( int )ListView_HitTest( WindowPlaylist, &hittest );
if( iIndex == -1 ) break;
playlist->SetCurIndex( iIndex );
Playback::Play();
Playback::UpdateSeek();
break;
}
return CallWindowProc( WndprocPlaylistBackup, hwnd, message, wp, lp );
}

View File

@ -0,0 +1,27 @@
////////////////////////////////////////////////////////////////////////////////
// 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 PLAYLIST_VIEW_H
#define PLAYLIST_VIEW_H 1
#include "Global.h"
namespace PlaylistView
{
void Create();
};
#endif // PLAYLIST_VIEW_H

View File

@ -0,0 +1,63 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Plugin.h"
#include "InputPlugin.h"
#include "OutputPlugin.h"
#include "VisPlugin.h"
#include "DspPlugin.h"
#include "GenPlugin.h"
vector<Plugin *> plugins; // extern
int Plugin::iWndprocHookCounter = 0;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
Plugin::Plugin( TCHAR * szDllpath )
{
hDLL = NULL;
szName = NULL;
iNameLen = 0;
iFullpathLen = ( int )_tcslen( szDllpath );
szFullpath = new TCHAR[ iFullpathLen + 1 ];
memcpy( szFullpath, szDllpath, iFullpathLen * sizeof( TCHAR ) );
szFullpath[ iFullpathLen ] = TEXT( '\0' );
TCHAR * walk = szFullpath + iFullpathLen - 1;
while( ( *walk != TEXT( '\\') ) && ( walk >= szFullpath ) ) walk--;
if( *walk == TEXT( '\\') ) walk++;
szFilename = walk;
iFilenameLen = iFullpathLen - ( walk - szFullpath );
_tcslwr( szFilename );
plugins.push_back( this );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
Plugin::~Plugin()
{
if( szFullpath ) delete [] szFullpath;
if( szName ) delete [] szName;
}

View File

@ -0,0 +1,142 @@
////////////////////////////////////////////////////////////////////////////////
// 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_PLUGIN_H
#define PA_PLUGIN_H
#include "Global.h"
#include <vector>
using namespace std;
class Plugin;
extern vector<Plugin *> plugins;
enum PluginType
{
PLUGIN_TYPE_INPUT,
PLUGIN_TYPE_OUTPUT,
PLUGIN_TYPE_VIS,
PLUGIN_TYPE_DSP,
PLUGIN_TYPE_GEN
};
////////////////////////////////////////////////////////////////////////////////
/// Winamp plugin wrapper
////////////////////////////////////////////////////////////////////////////////
class Plugin
{
public:
Plugin( TCHAR * szDllpath );
~Plugin();
virtual bool Load() = 0;
virtual bool Unload() = 0;
virtual TCHAR * GetTypeString() = 0;
virtual int GetTypeStringLen() = 0;
virtual PluginType GetType() = 0;
// void AllowUnload( bool bAllow ) { bAllowUnload = bAllow; }
inline bool IsLoaded() { return ( hDLL != NULL ); }
virtual bool IsActive() = 0;
inline TCHAR * GetFullpath() { return szFullpath; }
// inline int GetFullpathLen() { return iFilenameLen; }
inline TCHAR * GetFilename() { return szFilename; }
inline int GetFilenameLen() { return iFilenameLen; }
inline TCHAR * GetName() { return szName; }
inline int GetNameLen() { return iNameLen; }
template< class PluginKind >
static bool FindAll( TCHAR * szPath, TCHAR * szPattern, bool bKeepLoaded );
protected:
HINSTANCE hDLL; ///< Library handle
TCHAR * szName; ///< Name
int iNameLen; ///< Length of name (in characters)
BOOL iHookerIndex; ///< Window hook index (0..HC-1). Only last can be unloaded
WNDPROC WndprocBackup; ///< Window procedure backup. Is restored when unloading. Only valid for <iHookerIndex != -1>
static int iWndprocHookCounter; ///< Number of window hooks (=HC)
private:
TCHAR * szFullpath; ///< Full path e.g. "C:\test.dll"
TCHAR * szFilename; ///< Filename e.g. "test.dll"
int iFullpathLen; ///< Length of full path (in characters)
int iFilenameLen; ///< Length of filename (in characters)
};
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
template< class PluginKind >
bool Plugin::FindAll( TCHAR * szPath, TCHAR * szPattern, bool bKeepLoaded )
{
const int uPathLen = ( int )_tcslen( szPath );
const int uPatternLen = ( int )_tcslen( szPattern );
TCHAR * szFullPattern = new TCHAR[ uPathLen + 1 + uPatternLen + 1 ];
memcpy( szFullPattern, szPath, uPathLen * sizeof( TCHAR ) );
szFullPattern[ uPathLen ] = TEXT( '\\' );
memcpy( szFullPattern + uPathLen + 1, szPattern, uPatternLen * sizeof( TCHAR ) );
szFullPattern[ uPathLen + 1 + uPatternLen ] = TEXT( '\0' );
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile( szFullPattern, &fd );
if( hFind == INVALID_HANDLE_VALUE )
{
delete [] szFullPattern;
return false;
}
do
{
const int iFilenameLen = ( int )_tcslen( fd.cFileName );
TCHAR * szFullpath = new TCHAR[ uPathLen + 1 + iFilenameLen + 1 ];
memcpy( szFullpath, szPath, uPathLen * sizeof( TCHAR ) );
szFullpath[ uPathLen ] = TEXT( '\\' );
memcpy( szFullpath + uPathLen + 1, fd.cFileName, iFilenameLen * sizeof( TCHAR ) );
szFullpath[ uPathLen + 1 + iFilenameLen ] = TEXT( '\0' );
////////////////////////////////////////////////////////////////////////////////
new PluginKind( szFullpath, bKeepLoaded );
////////////////////////////////////////////////////////////////////////////////
delete [] szFullpath;
}
while( FindNextFile( hFind, &fd ) );
FindClose( hFind );
delete [] szFullPattern;
return true;
}
#endif // PA_PLUGIN_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
////////////////////////////////////////////////////////////////////////////////
// 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_PLUGIN_MANAGER_H
#define PA_PLUGIN_MANAGER_H
#include "Global.h"
#include "Plugin.h"
extern HWND WindowManager;
void UpdatePluginStatus( Plugin * plugin, bool bLoaded, bool bActive );
namespace PluginManager
{
bool Build();
bool Fill();
bool Destroy();
bool Popup();
};
#endif // PA_PLUGIN_MANAGER_H

View File

@ -0,0 +1,565 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Prefs.h"
#include "Util.h"
#include "Font.h"
#include "Console.h"
#include <map>
using namespace std;
#define CLASSNAME_PREFS TEXT( "CLASSNAME_PREFS" )
#define TITLE_PREFS TEXT( "Preferences" )
#define PAGE_WIDTH 409
#define PAGE_HEIGHT 400
#define GAP_LEFT 4
#define GAP_RIGHT 5
#define GAP_TOP 4
#define GAP_BOTTOM 5
#define SPLITTER_WIDTH 6
#define SPLITTER_HEIGHT 6
#define BOTTOM_SPACE 36
#define BUTTON_WIDTH 80
#define PREFS_WIDTH 606
#define PREFS_HEIGHT ( GAP_TOP + PAGE_HEIGHT + BOTTOM_SPACE )
struct PrefRecCompare
{
bool operator()( const prefsDlgRec * a, const prefsDlgRec * b ) const
{
if( a->hInst < b->hInst ) return true;
if( a->dlgID < b->dlgID ) return true;
return strcmp( a->name, b->name ) < 0;
}
};
map<prefsDlgRec *, HTREEITEM, PrefRecCompare> rec_to_item;
struct AllWeNeed
{
prefsDlgRec * PageData;
HWND hwnd;
};
HWND WindowPrefs = NULL;
HWND WindowPage = NULL;
HWND WindowTree = NULL;
HWND ButtonClose = NULL;
HTREEITEM root = NULL;
HWND hCurrentPage = NULL;
// bool bKeepFocus = false;
LRESULT CALLBACK WndprocPrefs( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
LRESULT CALLBACK WndprocTree( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
WNDPROC WndprocTreeBackup = NULL;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Prefs::Create()
{
if( WindowPrefs ) return false;
// Register class
WNDCLASS wc = {
0, // UINT style
WndprocPrefs, // 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_PREFS // LPCTSTR lpszClassName
};
if( !RegisterClass( &wc ) ) return false;
const int cxScreen = GetSystemMetrics( SM_CXFULLSCREEN );
const int cyScreen = GetSystemMetrics( SM_CYFULLSCREEN );
// Create window
WindowPrefs = CreateWindowEx(
WS_EX_WINDOWEDGE | // DWORD dwExStyle
WS_EX_TOOLWINDOW, //
CLASSNAME_PREFS, // LPCTSTR lpClassName
TITLE_PREFS, // LPCTSTR lpWindowName
WS_OVERLAPPED | // DWORD dwStyle
// WS_VISIBLE | //
WS_CLIPCHILDREN | //
WS_SYSMENU, //
( cxScreen - PREFS_WIDTH ) / 2, // int x
( cyScreen - PREFS_HEIGHT ) / 2, // int y
PREFS_WIDTH, // int nWidth
PREFS_HEIGHT, // int nHeight
NULL, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
if( !WindowPrefs )
{
UnregisterClass( CLASSNAME_PREFS, g_hInstance );
return false;
}
RECT r;
GetClientRect( WindowPrefs, &r );
////////////////////////////////////////////////////////////////////////////////
const int iWidth = PREFS_WIDTH * 2 - r.right;
const int iHeight = PREFS_HEIGHT * 2 - r.bottom;
SetWindowPos(
WindowPrefs,
NULL,
( cxScreen - iWidth ) / 2,
( cyScreen - iHeight ) / 2,
iWidth,
iHeight,
SWP_NOZORDER
);
GetClientRect( WindowPrefs, &r );
////////////////////////////////////////////////////////////////////////////////
LoadCommonControls();
const int iTreeWidth = ( r.right - r.left ) - PAGE_WIDTH - GAP_LEFT - GAP_RIGHT - SPLITTER_WIDTH;
WindowTree = CreateWindowEx(
WS_EX_CLIENTEDGE, // DWORD dwExStyle
WC_TREEVIEW, // LPCTSTR lpClassName
NULL, // LPCTSTR lpWindowName
WS_VSCROLL | // DWORD dwStyle
WS_VISIBLE | //
WS_CHILD | //
WS_TABSTOP | //
TVS_HASLINES | //
TVS_LINESATROOT | //
TVS_HASBUTTONS | //
TVS_SHOWSELALWAYS | //
TVS_DISABLEDRAGDROP | //
TVS_NONEVENHEIGHT, //
GAP_LEFT, // int x
GAP_TOP, // int y
iTreeWidth, // int nWidth
PAGE_HEIGHT, // int nHeight
WindowPrefs, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
if( !WindowTree )
{
; //...
}
Font::Apply( WindowTree );
// Exchange window procedure
WndprocTreeBackup = ( WNDPROC )GetWindowLong( WindowTree, GWL_WNDPROC );
if( WndprocTreeBackup != NULL )
{
SetWindowLong( WindowTree, GWL_WNDPROC, ( LONG )WndprocTree );
}
const int iPageLeft = GAP_LEFT + iTreeWidth + SPLITTER_WIDTH;
WindowPage = CreateWindowEx(
0, // DWORD dwExStyle
TEXT( "Static" ), // LPCTSTR lpClassName
TEXT( "Nothing to see here" ), // LPCTSTR lpWindowName
WS_TABSTOP | // DWORD dwStyle
WS_VISIBLE | //
WS_CHILD | //
SS_CENTER | //
SS_CENTERIMAGE, //
iPageLeft, // int x
GAP_TOP, // int y
PAGE_WIDTH, // int nWidth
PAGE_HEIGHT, // int nHeight
WindowPrefs, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
if( !WindowPage )
{
; //...
}
Font::Apply( WindowPage );
const int iButtonLeft = ( r.right - r.left ) - GAP_RIGHT - BUTTON_WIDTH - 1;
const int iButtonTop = ( r.bottom - r.top ) - BOTTOM_SPACE + SPLITTER_HEIGHT;
ButtonClose = CreateWindowEx(
0, // DWORD dwExStyle
TEXT( "Button" ), // LPCTSTR lpClassName
TEXT( "Close" ), // LPCTSTR lpWindowName
WS_TABSTOP | // DWORD dwStyle
WS_VISIBLE | //
WS_CHILD | //
BS_PUSHBUTTON | //
BS_TEXT | //
BS_VCENTER, //
iButtonLeft, // int x
iButtonTop, // int y
BUTTON_WIDTH, // int nWidth
BOTTOM_SPACE - SPLITTER_HEIGHT - GAP_BOTTOM, // int nHeight
WindowPrefs, // HWND hWndParent
NULL, // HMENU hMenu
g_hInstance, // HINSTANCE hInstance
NULL // LPVOID lpParam
);
Font::Apply( ButtonClose );
AllWeNeed * awn_root = new AllWeNeed;
// memset( &awn_root->PageData, 0, sizeof( prefsDlgRec ) );
awn_root->PageData = NULL;
awn_root->hwnd = NULL;
TV_INSERTSTRUCT tvi = {
root, // HTREEITEM hParent
TVI_SORT, // HTREEITEM hInsertAfter
{
TVIF_PARAM | TVIF_STATE | TVIF_TEXT, // UINT mask
NULL, // HTREEITEM hItem
TVIS_EXPANDED | TVIS_SELECTED, // UINT state
0, // UINT stateMask
TEXT( "General" ), // LPSTR pszText
8, // int cchTextMax
0, // int iImage
0, // int iSelectedImage
0, // int cChildren
( LPARAM )awn_root // LPARAM lParam
}
};
root = TreeView_InsertItem( WindowTree, &tvi );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Prefs::Destroy()
{
if( !WindowPrefs ) return false;
DestroyWindow( WindowPrefs );
UnregisterClass( CLASSNAME_PREFS, g_hInstance );
WindowPrefs = NULL;
DestroyWindow( WindowTree );
WindowTree = NULL;
DestroyWindow( WindowPage );
WindowPage = NULL;
DestroyWindow( ButtonClose );
ButtonClose = NULL;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Prefs_Show( HTREEITEM item )
{
if( !WindowPrefs ) return false;
// Select and load associated page
TreeView_SelectItem( WindowTree, item );
if( !IsWindowVisible( WindowPrefs ) )
{
ShowWindow( WindowPrefs, SW_SHOW );
}
SetActiveWindow( WindowPrefs );
SetFocus( WindowTree );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Prefs::Show()
{
return Prefs_Show( root );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Prefs::Show( prefsDlgRec * PageData )
{
map<prefsDlgRec *, HTREEITEM, PrefRecCompare>::iterator iter = rec_to_item.find( PageData );
if( iter != rec_to_item.end() )
{
return Prefs_Show( iter->second );
}
else
{
return Prefs_Show( root );
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool Prefs::AddPage( prefsDlgRec * PageData )
{
// TODO unicode!
if( !WindowPrefs ) return false;
// Backup
char * NameBackup = new char[ strlen( PageData->name ) + 1 ];
strcpy( NameBackup, PageData->name );
prefsDlgRec * PageDataBackup = new prefsDlgRec;
memcpy( PageDataBackup, PageData, sizeof( prefsDlgRec ) );
PageDataBackup->name = NameBackup;
AllWeNeed * awn = new AllWeNeed;
awn->PageData = PageDataBackup;
awn->hwnd = NULL;
TV_INSERTSTRUCT tvi = {
root, // HTREEITEM hParent
TVI_SORT, // HTREEITEM hInsertAfter
{ //
TVIF_PARAM | TVIF_STATE | TVIF_TEXT, // UINT mask
NULL, // HTREEITEM hItem
TVIS_EXPANDED | TVIS_SELECTED, // UINT state
0, // UINT stateMask
PageDataBackup->name, // LPSTR pszText
( int )strlen( PageDataBackup->name ) + 1, // int cchTextMax
0, // int iImage
0, // int iSelectedImage
0, // int cChildren
( LPARAM )awn // LPARAM lParam
}
};
HTREEITEM new_item = TreeView_InsertItem( WindowTree, &tvi );
TreeView_Expand( WindowTree, root, TVE_EXPAND );
rec_to_item.insert( pair<prefsDlgRec *, HTREEITEM>( PageDataBackup, new_item ) );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndprocPrefs( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
switch( message )
{
case WM_NOTIFY:
{
NMHDR * nmhdr = ( NMHDR * )lp;
if( ( nmhdr->hwndFrom == WindowTree ) && ( nmhdr->code == TVN_SELCHANGING ) )
{
NMTREEVIEW * nmtv = ( NMTREEVIEW * )lp;
TVITEM * OldPage = &nmtv->itemOld;
TVITEM * NewPage = &nmtv->itemNew;
// Destroy old window
AllWeNeed * old_awn = ( AllWeNeed * )OldPage->lParam;
if( old_awn && old_awn->hwnd && IsWindow( old_awn->hwnd ) )
{
DestroyWindow( old_awn->hwnd );
old_awn->hwnd = NULL;
}
// Create new window
AllWeNeed * new_awn = ( AllWeNeed * )NewPage->lParam;
if( new_awn )
{
prefsDlgRec * PageData = new_awn->PageData;
if( PageData && PageData->hInst ) // root has NULL here
{
if( !PageData->proc )
{
MessageBox( 0, TEXT( "proc NULL" ), TEXT( "" ), 0 );
PageData->proc = ( void * )WndprocPrefs;
}
/*
RECT r;
GetWindowRect( WindowPage, &r );
const int iWidth = r.right - r.left;
const int iHeight = r.bottom - r.top;
POINT p = { r.left, r.top };
ScreenToClient( WindowPrefs, &p );
MoveWindow( WindowPage, p.x, p.y, iWidth - 10, iHeight - 10, FALSE );
*/
// bKeepFocus = true;
HWND hPage = CreateDialog(
PageData->hInst, // HINSTANCE hInstance,
( LPCTSTR )PageData->dlgID, // LPCTSTR lpTemplate,
WindowPage, // HWND hWndParent,
( DLGPROC )PageData->proc // DLGPROC lpDialogFunc
);
new_awn->hwnd = hPage;
// MoveWindow( WindowPage, p.x, p.y, iWidth, iHeight, FALSE );
ShowWindow( hPage, SW_SHOW );
UpdateWindow( hPage );
SetFocus( WindowTree );
/*
SetActiveWindow( hPage );
SetActiveWindow( hwnd );
*/
hCurrentPage = hPage;
// bKeepFocus = false;
}
/*
else
{
MessageBox( 0, TEXT( "hInst NULL" ), TEXT( "" ), 0 );
}
*/
}
else
{
MessageBox( 0, TEXT( "awn NULL" ), TEXT( "" ), 0 );
}
}
break;
}
case WM_COMMAND:
switch( HIWORD( wp ) )
{
case BN_CLICKED:
if( ( HWND )lp == ButtonClose )
{
PostMessage( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
}
break;
}
break;
case WM_SYSCOMMAND:
if( ( wp & 0xFFF0 ) == SC_CLOSE )
{
ShowWindow( hwnd, SW_HIDE );
// Destroy current page so the settings are saved
// (currently be selecting the empty page
TreeView_SelectItem( WindowTree, root );
/*
if( hCurrentPage && IsWindow( hCurrentPage ) )
{
DestroyWindow( hCurrentPage );
hCurrentPage = NULL;
}
*/
return 0;
}
break;
case WM_KEYDOWN:
switch( wp )
{
case VK_ESCAPE:
PostMessage( WindowPrefs, WM_SYSCOMMAND, SC_CLOSE, 0 );
break;
}
break;
/*
case WM_KILLFOCUS:
if( bKeepFocus )
{
return 1;
}
break;
*/
}
return DefWindowProc( hwnd, message, wp, lp );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndprocTree( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
switch( message )
{
case WM_KEYDOWN:
switch( wp )
{
case VK_ESCAPE:
PostMessage( WindowPrefs, WM_SYSCOMMAND, SC_CLOSE, 0 );
break;
}
break;
}
return CallWindowProc( WndprocTreeBackup, hwnd, message, wp, lp );
}

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_PREFS_H
#define PA_PREFS_H
#include "Global.h"
#include "Winamp/wa_ipc.h"
namespace Prefs
{
bool Create();
bool Destroy();
bool Show();
bool Show( prefsDlgRec * PageData );
bool AddPage( prefsDlgRec * PageData );
};
#endif // PA_PREFS_H

File diff suppressed because it is too large Load Diff

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_TOOLBAR_H
#define PA_TOOLBAR_H
#include "Global.h"
extern HWND WindowRebar;
extern HWND WindowOrder;
extern HWND WindowEq;
extern HWND WindowSeek;
extern HWND WindowVis;
extern int iRebarHeight;
namespace Toolbar
{
bool Create();
};
#endif // PA_TOOLBAR_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

View File

@ -0,0 +1,17 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by resrc1.rc
//
#define IDB_BITMAP1 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,131 @@
// Microsoft Visual C++ generated resource script.
//
#include "resrc1.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "resource.h"
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
#ifdef _WIN32
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "Plainamp.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,2,3,1
PRODUCTVERSION 0,2,3,1
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "CompanyName", "Hartwork Project (http://www.hartwork.org)"
VALUE "FileDescription", "Plainamp"
VALUE "FileVersion", "0, 2, 3, 1"
VALUE "InternalName", "Plainamp"
VALUE "LegalCopyright", "Copyright (C) 2005 Sebastian Pipping"
VALUE "ProductName", "Plainamp"
VALUE "ProductVersion", "0, 2, 3, 1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_BITMAP1 BITMAP "Buttons.bmp"
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// German (Germany) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
#ifdef _WIN32
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resrc1.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""resource.h""\r\n"
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // German (Germany) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,80 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Status.h"
#include "Main.h"
#include "Util.h"
#include "GlobalVersion.h"
int iStatusHeight = 40; // extern
HWND WindowStatus = NULL; // extern
const TCHAR * const szStatusDefault = TEXT( " " ) PLAINAMP_LONG_TITLE;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool BuildMainStatus()
{
LoadCommonControls();
WindowStatus = CreateWindowEx(
0,
STATUSCLASSNAME,
szStatusDefault,
WS_CHILD |
WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
WindowMain,
NULL,
g_hInstance,
NULL
);
if( !WindowStatus ) return false;
RECT r = { 0, 0, 0, 0 };
GetWindowRect( WindowStatus, &r );
iStatusHeight = r.bottom - r.top;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool StatusUpdate( TCHAR * szText )
{
if( !WindowStatus ) return false;
SetWindowText( WindowStatus, szText );
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void StatusReset()
{
if( !WindowStatus ) return;
SetWindowText( WindowStatus, szStatusDefault );
}

View File

@ -0,0 +1,33 @@
////////////////////////////////////////////////////////////////////////////////
// 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_STATUS_H
#define PA_STATUS_H
#include "Global.h"
extern int iStatusHeight;
extern HWND WindowStatus;
bool BuildMainStatus();
bool StatusUpdate( TCHAR * szText );
void StatusReset();
#endif // PA_STATUS_H

View File

@ -0,0 +1,77 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Unicode.h"
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ToAnsi( char * szDest, wchar_t * szSource, int iLen )
{
char * const szBytesource = ( char * )szSource;
for( int i = 0; i < iLen; i++ )
{
szDest[ i ] = szBytesource[ 2 * i + 1 ];
}
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
/*
void ToUnicode( wchar_t * szDest, char * szSource, int iLen )
{
for( int i = 0; i < iLen; i++ )
{
szDest[ i ] = ( wchar_t )szSource[ i ];
}
}
*/
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ToTchar( TCHAR * szDest, wchar_t * szSource, int iLen )
{
#ifdef PA_UNICODE
memcpy( szDest, szSource, 2 * iLen );
#else
char * const stByteSource = ( TCHAR * )szSource;
for( int i = 0; i < iLen; i++ )
{
szDest[ i ] = stByteSource[ 2 * i + 1 ];
}
#endif
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void ToTchar( TCHAR * szDest, char * szSource, int iLen )
{
#ifdef PA_UNICODE
for( int i = 0; i < iLen; i++ )
{
szDest[ i ] = szSource[ 2 * i + 1 ];
}
#else
memcpy( szDest, szSource, iLen );
#endif
}

View File

@ -0,0 +1,29 @@
////////////////////////////////////////////////////////////////////////////////
// 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_UNICODE_H
#define PA_UNICODE_H
#include "Global.h"
void ToAnsi( char * szDest, wchar_t * szSource, int iLen );
// void ToUnicode( wchar_t * szDest, char * szSource, int iLen )
void ToTchar( TCHAR * szDest, wchar_t * szSource, int iLen );
void ToTchar( TCHAR * szDest, char * szSource, int iLen );
#endif // PA_UNICODE_H

View File

@ -0,0 +1,48 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Util.h"
#ifndef ICC_STANDARD_CLASSES
# define ICC_STANDARD_CLASSES 0x00004000
#endif
bool bLoaded = false;
bool bAvailable = false;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool LoadCommonControls()
{
if( bLoaded ) return bAvailable;
INITCOMMONCONTROLSEX icce = {
sizeof( INITCOMMONCONTROLSEX ),
ICC_BAR_CLASSES | // Statusbar, trackbar, toolbar
ICC_COOL_CLASSES | // Rebar
ICC_LISTVIEW_CLASSES | // Listview
ICC_STANDARD_CLASSES | //
ICC_TREEVIEW_CLASSES // Treeview
};
bLoaded = true;
bAvailable = ( InitCommonControlsEx( &icce ) == TRUE );
return bAvailable;
}

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_UTIL_H
#define PA_UTIL_H
#include "Global.h"
bool LoadCommonControls();
#endif // PA_UTIL_H

View File

@ -0,0 +1,303 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "VisCache.h"
#include "Console.h"
#include "malloc.h"
unsigned char * SpecCacheLeft;
unsigned char * SpecCacheRight;
unsigned char * WaveCacheLeft;
unsigned char * WaveCacheRight;
int iWritePos;
int iWriteOffset; // == iWritePos * 576
int iVisLatency;
int iDataFps;
int iCacheLen;
bool bReady = false;
int iReadTimeMs = 0;
int iWriteTimeMs = 0;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache_Resize( int iLatency, int iFps )
{
// if( !bReady ) return;
const int iNewCacheLen = ( iFps * iLatency ) / 1000 + 1;
/*
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "RESIZE ( %i * %i ) / 1000 + 1 === %i" ), iFps, iLatency, iNewCacheLen );
Console::Append( szBuffer );
*/
const int iByteNewCacheLen = iNewCacheLen * 576;
if( !iCacheLen )
{
// First time
SpecCacheLeft = ( unsigned char * )malloc( iByteNewCacheLen );
// memset( SpecCacheLeft, 0, iByteNewCacheLen );
SpecCacheRight = ( unsigned char * )malloc( iByteNewCacheLen );
// memset( SpecCacheRight, 0, iByteNewCacheLen );
WaveCacheLeft = ( unsigned char * )malloc( iByteNewCacheLen );
// memset( WaveCacheLeft, 0, iByteNewCacheLen );
WaveCacheRight = ( unsigned char * )malloc( iByteNewCacheLen );
// memset( WaveCacheRight, 0, iByteNewCacheLen );
}
else if( iNewCacheLen > iCacheLen )
{
// Grow
const int iByteCacheLen = iCacheLen * 576;
const int iByteClearLen = ( iNewCacheLen - iCacheLen ) * 576;
SpecCacheLeft = ( unsigned char * )realloc( SpecCacheLeft, iByteNewCacheLen );
// memset( SpecCacheLeft + iByteCacheLen, 0, iByteClearLen );
SpecCacheRight = ( unsigned char * )realloc( SpecCacheRight, iByteNewCacheLen );
// memset( SpecCacheRight + iByteCacheLen, 0, iByteClearLen );
WaveCacheLeft = ( unsigned char * )realloc( WaveCacheLeft, iByteNewCacheLen );
// memset( WaveCacheLeft + iByteCacheLen, 0, iByteClearLen );
WaveCacheRight = ( unsigned char * )realloc( WaveCacheRight, iByteNewCacheLen );
// memset( WaveCacheRight + iByteCacheLen, 0, iByteClearLen );
}
iCacheLen = iNewCacheLen;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::Create()
{
if( bReady ) return;
iWritePos = 0;
iWriteOffset = 0;
iVisLatency = 50;
iDataFps = 40;
iCacheLen = 0;
bReady = true;
VisCache_Resize( iVisLatency, iDataFps );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::Destroy()
{
if( !bReady ) return;
if( SpecCacheLeft ) free( SpecCacheLeft );
if( SpecCacheRight ) free( SpecCacheRight );
if( WaveCacheLeft ) free( WaveCacheLeft );
if( WaveCacheRight ) free( WaveCacheRight );
bReady = false;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::EnsureLatency( int iLatency )
{
if( !bReady ) return;
if( iLatency <= iVisLatency ) return;
VisCache_Resize(
iLatency,
iDataFps
);
iVisLatency = iLatency;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::EnsureDataFps( int iFps )
{
if( !bReady ) return;
if( iFps <= iDataFps ) return;
VisCache_Resize(
iVisLatency,
iFps
);
iDataFps = iFps;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::Clean()
{
if( !bReady ) return;
const int iByteCacheLen = iCacheLen * 576;
memset( SpecCacheLeft, 0, iByteCacheLen );
memset( SpecCacheRight, 0, iByteCacheLen );
memset( WaveCacheLeft, 0, iByteCacheLen );
memset( WaveCacheRight, 0, iByteCacheLen );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::SetReadTime( int ms )
{
iReadTimeMs = ms;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::SetWriteTime( int ms )
{
iWriteTimeMs = ms;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int VisCache::LatencyToOffset( int iLatency )
{
int iFrame = iWritePos - 1 - ( ( iWriteTimeMs - iReadTimeMs - iLatency ) * iDataFps ) / 1000;
if( iFrame < 0 ) iFrame += iCacheLen;
return iFrame * 576;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::NextFrame()
{
iWritePos++;
if( iWritePos >= iCacheLen ) iWritePos = 0;
iWriteOffset = iWritePos * 576;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::PutSpecLeft( unsigned char * data )
{
if( !bReady ) return;
memcpy( SpecCacheLeft + iWriteOffset, data, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::PutSpecRight( unsigned char * data )
{
if( !bReady ) return;
memcpy( SpecCacheRight + iWriteOffset, data, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::PutWaveLeft( unsigned char * data )
{
if( !bReady ) return;
memcpy( WaveCacheLeft + iWriteOffset, data, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::PutWaveRight( unsigned char * data )
{
if( !bReady ) return;
memcpy( WaveCacheRight + iWriteOffset, data, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::GetSpecLeft( unsigned char * dest, int iOffset )
{
if( !bReady ) return;
memcpy( dest, SpecCacheLeft + iOffset, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::GetSpecRight( unsigned char * dest, int iOffset )
{
if( !bReady ) return;
memcpy( dest, SpecCacheRight + iOffset, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::GetWaveLeft( unsigned char * dest, int iOffset )
{
if( !bReady ) return;
memcpy( dest, WaveCacheLeft + iOffset, 576 );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void VisCache::GetWaveRight( unsigned char * dest, int iOffset )
{
if( !bReady ) return;
memcpy( dest, WaveCacheRight + iOffset, 576 );
}

View File

@ -0,0 +1,50 @@
////////////////////////////////////////////////////////////////////////////////
// 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_VIS_CACHE_H
#define PA_VIS_CACHE_H
#include "Global.h"
namespace VisCache
{
void Create();
void Destroy();
void EnsureLatency( int iLatency ); // TODO
void EnsureDataFps( int iFps ); // TODO
void Clean();
void SetReadTime( int ms );
void SetWriteTime( int ms );
int LatencyToOffset( int iLatency );
void NextFrame();
void PutSpecLeft( unsigned char * data );
void PutSpecRight( unsigned char * data );
void PutWaveLeft( unsigned char * data );
void PutWaveRight( unsigned char * data );
void GetSpecLeft( unsigned char * dest, int iOffset );
void GetSpecRight( unsigned char * dest, int iOffset );
void GetWaveLeft( unsigned char * dest, int iOffset );
void GetWaveRight( unsigned char * dest, int iOffset );
};
#endif // PA_VIS_CACHE_H

View File

@ -0,0 +1,358 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "VisModule.h"
#include "Console.h"
#include "Unicode.h"
#include "Playback.h"
#include "VisCache.h"
#include "PluginManager.h"
#include <process.h>
VisModule ** active_vis_mods = NULL; // extern
int active_vis_count = 0; // extern
/*
BOOL CALLBACK EnumThreadWndProc( HWND hwnd, LPARAM lp )
{
// MessageBox( 0, "EnumThreadWndProc", "", 0 );
DestroyWindow( hwnd );
}
*/
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
void PlugThread( PVOID pvoid )
{
// TODO: cleanup!!!
Console::Append( TEXT( "Visualization thread born" ) );
Console::Append( " " );
VisModule * mod = ( VisModule * )pvoid;
if( !mod ) return;
if( mod->mod->Init( mod->mod ) != 0 ) return;
VisCache::Create();
////////////////////////////////////////////////////////////////////////////////
VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
active_vis_count++;
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
bool bKeepItGoing = true;
bool bQuitCalled = false;
int iLast = GetTickCount();
// Message loop
MSG msg;
msg.message = WM_QUIT + 1; // Must be != WM_QUIT
do
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
////////////////////////////////////////////////////////////////////////////////
// Stop
if( !bQuitCalled )
{
mod->mod->Quit( mod->mod );
bQuitCalled = true;
}
////////////////////////////////////////////////////////////////////////////////
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
if( msg.message == WM_CLOSE || ( ( msg.message == WM_SYSCOMMAND ) && ( msg.wParam == SC_CLOSE ) ) )
{
////////////////////////////////////////////////////////////////////////////////
// Stop
if( !bQuitCalled )
{
mod->mod->Quit( mod->mod );
bQuitCalled = true;
}
////////////////////////////////////////////////////////////////////////////////
}
}
if( bKeepItGoing )
{
// Variant A
const int iNow = GetTickCount();
if( iNow - iLast > mod->mod->delayMs )
{
if( Playback::IsPlaying() )
{
if( mod->bAllowRender )
{
mod->bAllowRender = false;
const int iOffset = VisCache::LatencyToOffset( mod->mod->latencyMs );
switch( mod->mod->spectrumNch )
{
case 2:
VisCache::GetSpecRight( mod->mod->spectrumData[ 1 ], iOffset );
case 1:
VisCache::GetSpecLeft( mod->mod->spectrumData[ 0 ], iOffset );
}
switch( mod->mod->waveformNch )
{
case 2:
VisCache::GetWaveRight( mod->mod->waveformData[ 1 ], iOffset );
case 1:
VisCache::GetWaveLeft( mod->mod->waveformData[ 0 ], iOffset );
}
if( mod->mod->Render( mod->mod ) != 0 )
{
////////////////////////////////////////////////////////////////////////////////
// Stop
if( !bQuitCalled )
{
// TODO: milkdrop doesn#t save window position
// when quit using manual plugin stop
mod->mod->Quit( mod->mod );
bQuitCalled = true;
}
////////////////////////////////////////////////////////////////////////////////
/*
// Destroy all windows belonging to this thread
// This will lead to WM_QUIT automatically
EnumThreadWindows( GetCurrentThreadId(), EnumThreadWndProc, 0 );
bKeepItGoing = false;
*/
}
iLast = iNow;
}
}
else
{
if( mod->mod->Render( mod->mod ) != 0 )
{
////////////////////////////////////////////////////////////////////////////////
// Stop
if( !bQuitCalled )
{
mod->mod->Quit( mod->mod );
bQuitCalled = true;
}
////////////////////////////////////////////////////////////////////////////////
/*
// Destroy all windows belonging to this thread
// This will lead to WM_QUIT automatically
EnumThreadWindows( GetCurrentThreadId(), EnumThreadWndProc, 0 );
bKeepItGoing = false;
*/
}
iLast = iNow;
}
}
////////////////////////////////////////////////////////////////////////////////
bool bVisLockLeft = false;
VisLock.Enter();
////////////////////////////////////////////////////////////////////////////////
if( mod->bShouldQuit )
{
////////////////////////////////////////////////////////////////////////////////
VisLock.Leave();
bVisLockLeft = true;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Stop
if( !bQuitCalled )
{
mod->mod->Quit( mod->mod );
bQuitCalled = true;
}
////////////////////////////////////////////////////////////////////////////////
/*
// Destroy all windows belonging to this thread
// This will lead to WM_QUIT automatically
EnumThreadWindows( GetCurrentThreadId(), EnumThreadWndProc, 0 );
bKeepItGoing = false;
*/
}
////////////////////////////////////////////////////////////////////////////////
if( !bVisLockLeft )
{
VisLock.Leave();
}
////////////////////////////////////////////////////////////////////////////////
}
Sleep( 1 );
}
while( msg.message != WM_QUIT );
mod->bShouldQuit = false;
////////////////////////////////////////////////////////////////////////////////
VisLock.Enter();
if( ( active_vis_count > 1 ) && ( mod->iArrayIndex < active_vis_count - 1 ) )
{
active_vis_mods[ mod->iArrayIndex ] = active_vis_mods[ active_vis_count - 1 ];
active_vis_mods[ mod->iArrayIndex ]->iArrayIndex = mod->iArrayIndex;
}
active_vis_count--;
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
mod->iArrayIndex = -1;
/*
// Stop
mod->mod->Quit( mod->mod );
*/
////////////////////////////////////////////////////////////////////////////////
VisLock.Enter();
mod->bActive = false;
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
UpdatePluginStatus( mod->plugin, true, mod->plugin->IsActive() );
Console::Append( TEXT( "Visualization thread dead" ) );
Console::Append( " " );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
VisModule::VisModule( char * szName, int iIndex, winampVisModule * mod, VisPlugin * plugin )
{
iArrayIndex = -1;
bActive = false;
bShouldQuit = false;
bAllowRender = false;
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 VisModule::Start()
{
if( !mod ) return false;
if( bActive ) return false;
if( plugin->IsActive() ) return false;
////////////////////////////////////////////////////////////////////////////////
VisLock.Enter();
if( !active_vis_count )
{
active_vis_mods = new VisModule * [ 1 ];
active_vis_mods[ 0 ] = this;
}
else
{
VisModule ** new_active_vis_mods = new VisModule * [ active_vis_count + 1 ];
memcpy( new_active_vis_mods, active_vis_mods, active_vis_count * sizeof( VisModule * ) );
new_active_vis_mods[ active_vis_count ] = this;
delete [] active_vis_mods;
active_vis_mods = new_active_vis_mods;
}
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
iArrayIndex = active_vis_count;
// Start
_beginthread( PlugThread, 1024 * 1024, ( PVOID )this );
bActive = true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool VisModule::Stop()
{
if( !mod ) return false;
if( !bActive ) return false;
if( !plugin->IsActive() ) return false;
////////////////////////////////////////////////////////////////////////////////
VisLock.Enter();
bShouldQuit = true;
VisLock.Leave();
////////////////////////////////////////////////////////////////////////////////
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool VisModule::Config()
{
if( !mod ) return false;
if( !mod->Config ) return false;
mod->Config( mod );
return true;
}

View File

@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////////////////////
// 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_VIS_MODULE_H
#define PA_VIS_MODULE_H
#include "Global.h"
#include "VisPlugin.h"
#include <Process.h>
class VisModule;
class VisPlugin;
extern VisModule ** active_vis_mods;
extern int active_vis_count;
////////////////////////////////////////////////////////////////////////////////
/// Winamp visualization module wrapper
////////////////////////////////////////////////////////////////////////////////
class VisModule
{
public:
VisModule( char * szName, int iIndex, winampVisModule * mod, VisPlugin * plugin );
bool Start();
bool Config();
bool Stop();
inline bool IsActive() { return bActive; }
inline TCHAR * GetName() { return szName; }
inline int GetNameLen() { return iNameLen; }
private:
int iArrayIndex;
bool bActive;
bool bShouldQuit;
bool bAllowRender;
TCHAR * szName;
int iNameLen;
int iIndex;
winampVisModule * mod;
VisPlugin * plugin;
friend void PlugThread( PVOID pvoid );
friend void VSAAdd( void * data, int timestamp );
friend void VSAAddPCMData( void * PCMData, int nch, int bps, int timestamp );
friend int VSAGetMode( int * specNch, int * waveNch );
};
#endif // PA_VIS_MODULE_H

View File

@ -0,0 +1,188 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "VisPlugin.h"
#include "Unicode.h"
#include "Console.h"
#include "Main.h"
vector <VisPlugin *> vis_plugins; // extern
Lock VisLock = Lock( TEXT( "PLAINAMP_VIS_LOCK" ) ); // extern
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
VisPlugin::VisPlugin( TCHAR * szDllpath, bool bKeepLoaded ) : Plugin( szDllpath )
{
header = NULL;
if( !Load() )
{
return;
}
if( !bKeepLoaded )
{
Unload();
}
vis_plugins.push_back( this );
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool VisPlugin::Load()
{
// (1) Load DLL
hDLL = LoadLibrary( GetFullpath() );
if( !hDLL ) return false;
// (2) Find export
WINAMP_VIS_GETTER winampGetVisHeader =
( WINAMP_VIS_GETTER )GetProcAddress( hDLL, "winampVisGetHeader" );
if( winampGetVisHeader == NULL )
{
FreeLibrary( hDLL );
hDLL = NULL;
return false;
}
// (3) Get header
header = winampGetVisHeader();
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
winampVisModule * mod;
int iFound = 0;
while( true )
{
mod = header->getModule( iFound );
if( !mod ) break;
// (4a) Modify module
mod->hDllInstance = hDLL;
mod->hwndParent = WindowMain;
mod->sRate = 44100; // TODO
mod->nCh = 2; // TODO
// (4b) Add module to list
VisModule * vismod = new VisModule(
mod->description, // char * szName
iFound, // UINT uIndex
mod, // winampVisModule * mod
this // VisPlugin * plugin
);
modules.push_back( vismod );
iFound++;
_stprintf( szBuffer, TEXT( " %s" ), vismod->GetName() );
Console::Append( szBuffer );
}
Console::Append( TEXT( " " ) );
if( !iFound ) return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool VisPlugin::Unload()
{
if( !IsLoaded() ) return true;
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Unloading <%s>" ), GetFilename() );
Console::Append( szBuffer );
Console::Append( TEXT( " " ) );
header = NULL;
/*
TODO
VisModule * walk;
vector <VisModule *>::iterator iter = modules.begin();
while( iter != modules.end() )
{
walk = *iter;
delete [] walk->szName;
delete walk;
iter++;
}
*/
FreeLibrary( hDLL );
hDLL = NULL;
return true;
}
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
bool VisPlugin::IsActive()
{
vector <VisModule *>::iterator iter = modules.begin();
while( iter != modules.end() )
{
if( ( *iter )->IsActive() ) return true;
iter++;
}
return false;
}

View File

@ -0,0 +1,68 @@
////////////////////////////////////////////////////////////////////////////////
// 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_VIS_PLUGIN_H
#define PA_VIS_PLUGIN_H
#include "Global.h"
#include "Plugin.h"
#include "Winamp/Vis.h"
#include "VisModule.h"
#include "Lock.h"
#include <vector>
using namespace std;
typedef winampVisHeader * ( * WINAMP_VIS_GETTER )( void );
class VisModule;
class VisPlugin;
extern vector <VisPlugin *> vis_plugins;
extern Lock VisLock;
////////////////////////////////////////////////////////////////////////////////
/// Winamp visualization plugin wrapper
////////////////////////////////////////////////////////////////////////////////
class VisPlugin : public Plugin
{
public:
VisPlugin( TCHAR * szDllpath, bool bKeepLoaded );
bool Load();
bool Unload();
TCHAR * GetTypeString() { return TEXT( "Visual" ); }
int GetTypeStringLen() { return 6; }
PluginType GetType() { return PLUGIN_TYPE_VIS; }
bool IsActive();
private:
winampVisHeader * header;
vector<VisModule *> modules;
friend void ContextMenuVis( VisPlugin * vis, POINT * p );
};
#endif // PA_VIS_PLUGIN_H

View File

@ -0,0 +1,985 @@
////////////////////////////////////////////////////////////////////////////////
// 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 "Winamp.h"
#include "Playback.h"
#include "Playlist.h"
#include "Console.h"
#include "Main.h"
#include "Winamp/wa_ipc.h"
#include "Winamp/wa_msgids.h"
#include "AddDirectory.h"
#include "AddFiles.h"
#include "Prefs.h"
#include "PluginManager.h"
#include "Embed.h"
#include "Unicode.h"
#include "zlib/zlib.h"
#include "Rebar.h"
int IPC_GENHOTKEYS_ADD = 0;
int ID_DYNAMICLIBRARY = 0;
int IPC_GETPLAINBARTARGET = 0;
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndprocWinamp( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
switch( message )
{
case WM_COMMAND:
/*
{
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "WM_COMMAND <%i> <%i>" ), wp, lp );
Console::Append( szBuffer );
}
*/
switch( LOWORD( wp ) )
{
case WINAMP_FILE_QUIT:
PostMessage( WindowMain, WM_SYSCOMMAND, SC_CLOSE, 0 );
break;
case WINAMP_OPTIONS_PREFS:
Prefs::Show();
break;
/*
case WINAMP_OPTIONS_AOT: break;
case WINAMP_FILE_REPEAT: break;
case WINAMP_FILE_SHUFFLE: break;
case WINAMP_HIGH_PRIORITY: break;
*/
case WINAMP_FILE_PLAY:
AddFiles();
break;
/*
case WINAMP_OPTIONS_EQ: break;
case WINAMP_OPTIONS_ELAPSED: break;
case WINAMP_OPTIONS_REMAINING: break;
case WINAMP_OPTIONS_PLEDIT: break;
*/
case WINAMP_HELP_ABOUT:
About( hwnd );
break;
case WINAMP_MAINMENU:
{
POINT p;
GetCursorPos( &p );
CheckMenuItem(
main_context_menu,
PLAINAMP_TOGGLE_CONSOLE,
IsWindowVisible( WindowConsole ) ? MF_CHECKED : MF_UNCHECKED
);
CheckMenuItem(
main_context_menu,
PLAINAMP_TOGGLE_MANAGER,
IsWindowVisible( WindowManager ) ? MF_CHECKED : MF_UNCHECKED
);
TrackPopupMenu(
main_context_menu,
TPM_LEFTALIGN |
TPM_TOPALIGN |
TPM_RIGHTBUTTON,
p.x,
p.y,
0,
hwnd,
NULL
);
break;
}
case WINAMP_BUTTON1:
Playback::Prev();
Playback::UpdateSeek();
break;
case WINAMP_BUTTON2:
Playback::Play();
Playback::UpdateSeek();
break;
case WINAMP_BUTTON3:
Playback::Pause();
Playback::UpdateSeek();
break;
case WINAMP_BUTTON4:
Playback::Stop();
Playback::UpdateSeek();
break;
case WINAMP_BUTTON5:
Playback::Next();
Playback::UpdateSeek();
break;
/*
case WINAMP_BUTTON1_SHIFT: break;
case WINAMP_BUTTON2_SHIFT: break;
case WINAMP_BUTTON3_SHIFT: break;
case WINAMP_BUTTON4_SHIFT: break;
case WINAMP_BUTTON5_SHIFT: break;
case WINAMP_BUTTON1_CTRL: break;
case WINAMP_BUTTON2_CTRL: break;
case WINAMP_BUTTON3_CTRL: break;
case WINAMP_BUTTON4_CTRL: break;
case WINAMP_BUTTON5_CTRL: break;
*/
case WINAMP_VOLUMEUP:
Playback::Volume::Up();
// TODO Update slider
break;
case WINAMP_VOLUMEDOWN:
Playback::Volume::Down();
// TODO Update slider
break;
case WINAMP_FFWD5S:
Playback::Forward();
Playback::UpdateSeek();
break;
case WINAMP_REW5S:
Playback::Rewind();
Playback::UpdateSeek();
break;
/*
case WINAMP_NEXT_WINDOW: break;
case WINAMP_OPTIONS_WINDOWSHADE: break;
case WINAMP_OPTIONS_DSIZE: break;
case IDC_SORT_FILENAME: break;
case IDC_SORT_FILETITLE: break;
case IDC_SORT_ENTIREFILENAME: break;
case IDC_SELECTALL: break;
case IDC_SELECTNONE: break;
case IDC_SELECTINV: break;
case IDM_EQ_LOADPRE: break;
case IDM_EQ_LOADMP3: break;
case IDM_EQ_LOADDEFAULT: break;
case IDM_EQ_SAVEPRE: break;
case IDM_EQ_SAVEMP3: break;
case IDM_EQ_SAVEDEFAULT: break;
case IDM_EQ_DELPRE: break;
case IDM_EQ_DELMP3: break;
case IDC_PLAYLIST_PLAY: break;
case WINAMP_FILE_LOC: break;
case WINAMP_OPTIONS_EASYMOVE: break;
*/
case WINAMP_FILE_DIR:
AddDirectory();
break;
/*
case WINAMP_EDIT_ID3: break;
case WINAMP_TOGGLE_AUTOSCROLL: break;
case WINAMP_VISSETUP: break;
case WINAMP_PLGSETUP: break;
case WINAMP_VISPLUGIN: break;
case WINAMP_JUMP: break;
case WINAMP_JUMPFILE: break;
case WINAMP_JUMP10FWD: break;
case WINAMP_JUMP10BACK: break;
case WINAMP_PREVSONG: break;
case WINAMP_OPTIONS_EXTRAHQ: break;
*/
case ID_PE_NEW:
playlist->RemoveAll();
break;
case ID_PE_OPEN:
Playlist::DialogOpen();
break;
/*
case ID_PE_SAVE: break;
*/
case ID_PE_SAVEAS:
Playlist::DialogSaveAs();
break;
case ID_PE_SELECTALL:
playlist->SelectAll( true );
break;
case ID_PE_INVERT:
playlist->SelectInvert();
break;
case ID_PE_NONE:
playlist->SelectAll( false );
break;
/*
case ID_PE_ID3: break;
case ID_PE_S_TITLE: break;
case ID_PE_S_FILENAME: break;
case ID_PE_S_PATH: break;
case ID_PE_S_RANDOM: break;
case ID_PE_S_REV: break;
*/
case ID_PE_CLEAR:
playlist->RemoveAll();
break;
/*
case ID_PE_MOVEUP: break;
case ID_PE_MOVEDOWN: break;
case WINAMP_SELSKIN: break;
case WINAMP_VISCONF: break;
case ID_PE_NONEXIST: break;
case ID_PE_DELETEFROMDISK: break;
case ID_PE_CLOSE: break;
case WINAMP_VIS_SETOSC: break;
case WINAMP_VIS_SETANA: break;
case WINAMP_VIS_SETOFF: break;
case WINAMP_VIS_DOTSCOPE: break;
case WINAMP_VIS_LINESCOPE: break;
case WINAMP_VIS_SOLIDSCOPE: break;
case WINAMP_VIS_NORMANA: break;
case WINAMP_VIS_FIREANA: break;
case WINAMP_VIS_LINEANA: break;
case WINAMP_VIS_NORMVU: break;
case WINAMP_VIS_SMOOTHVU: break;
case WINAMP_VIS_FULLREF: break;
case WINAMP_VIS_FULLREF2: break;
case WINAMP_VIS_FULLREF3: break;
case WINAMP_VIS_FULLREF4: break;
case WINAMP_OPTIONS_TOGTIME: break;
case EQ_ENABLE: break;
case EQ_AUTO: break;
case EQ_PRESETS: break;
case WINAMP_VIS_FALLOFF0: break;
case WINAMP_VIS_FALLOFF1: break;
case WINAMP_VIS_FALLOFF2: break;
case WINAMP_VIS_FALLOFF3: break;
case WINAMP_VIS_FALLOFF4: break;
case WINAMP_VIS_PEAKS: break;
case ID_LOAD_EQF: break;
case ID_SAVE_EQF: break;
case ID_PE_ENTRY: break;
case ID_PE_SCROLLUP: break;
case ID_PE_SCROLLDOWN: break;
case WINAMP_MAIN_WINDOW: break;
case WINAMP_VIS_PFALLOFF0: break;
case WINAMP_VIS_PFALLOFF1: break;
case WINAMP_VIS_PFALLOFF2: break;
case WINAMP_VIS_PFALLOFF3: break;
case WINAMP_VIS_PFALLOFF4: break;
case ID_PE_TOP: break;
case ID_PE_BOTTOM: break;
case WINAMP_OPTIONS_WINDOWSHADE_PL: break;
case EQ_INC1: break;
case EQ_INC2: break;
case EQ_INC3: break;
case EQ_INC4: break;
case EQ_INC5: break;
case EQ_INC6: break;
case EQ_INC7: break;
case EQ_INC8: break;
case EQ_INC9: break;
case EQ_INC10: break;
case EQ_INCPRE: break;
case EQ_DECPRE: break;
case EQ_DEC1: break;
case EQ_DEC2: break;
case EQ_DEC3: break;
case EQ_DEC4: break;
case EQ_DEC5: break;
case EQ_DEC6: break;
case EQ_DEC7: break;
case EQ_DEC8: break;
case EQ_DEC9: break;
case EQ_DEC10: break;
case ID_PE_SCUP: break;
case ID_PE_SCDOWN: break;
case WINAMP_REFRESHSKIN: break;
case ID_PE_PRINT: break;
case ID_PE_EXTINFO: break;
case WINAMP_PLAYLIST_ADVANCE: break;
case WINAMP_VIS_LIN: break;
case WINAMP_VIS_BAR: break;
case WINAMP_OPTIONS_MINIBROWSER: break;
case MB_FWD: break;
case MB_BACK: break;
case MB_RELOAD: break;
case MB_OPENMENU: break;
case MB_OPENLOC: break;
case WINAMP_NEW_INSTANCE: break;
case MB_UPDATE: break;
case WINAMP_OPTIONS_WINDOWSHADE_EQ: break;
case EQ_PANLEFT: break;
case EQ_PANRIGHT: break;
case WINAMP_GETMORESKINS: break;
case WINAMP_VIS_OPTIONS: break;
case WINAMP_PE_SEARCH: break;
case ID_PE_BOOKMARK: break;
case WINAMP_EDIT_BOOKMARKS: break;
case WINAMP_MAKECURBOOKMARK: break;
case ID_MAIN_PLAY_BOOKMARK_NONE: break;
case ID_MAIN_PLAY_AUDIOCD: break;
case ID_MAIN_PLAY_AUDIOCD2: break;
case ID_MAIN_PLAY_AUDIOCD3: break;
case ID_MAIN_PLAY_AUDIOCD4: break;
case WINAMP_OPTIONS_VIDEO: break;
case ID_VIDEOWND_ZOOMFULLSCREEN: break;
case ID_VIDEOWND_ZOOM100: break;
case ID_VIDEOWND_ZOOM200: break;
case ID_VIDEOWND_ZOOM50: break;
case ID_VIDEOWND_VIDEOOPTIONS: break;
case WINAMP_MINIMIZE: break;
case ID_PE_FONTBIGGER: break;
case ID_PE_FONTSMALLER: break;
case WINAMP_VIDEO_TOGGLE_FS: break;
case WINAMP_VIDEO_TVBUTTON: break;
case WINAMP_LIGHTNING_CLICK: break;
case ID_FILE_ADDTOLIBRARY: break;
case ID_HELP_HELPTOPICS: break;
case ID_HELP_GETTINGSTARTED: break;
case ID_HELP_WINAMPFORUMS: break;
*/
case ID_PLAY_VOLUMEUP:
Playback::Volume::Up();
// TODO Update slider
break;
case ID_PLAY_VOLUMEDOWN:
Playback::Volume::Down();
// TODO Update slider
break;
/*
case ID_PEFILE_OPENPLAYLISTFROMLIBRARY_NOPLAYLISTSINLIBRARY: break;
case ID_PEFILE_ADDFROMLIBRARY: break;
case ID_PEFILE_CLOSEPLAYLISTEDITOR: break;
case ID_PEPLAYLIST_PLAYLISTPREFERENCES: break;
case ID_MLFILE_NEWPLAYLIST: break;
case ID_MLFILE_LOADPLAYLIST: break;
case ID_MLFILE_SAVEPLAYLIST: break;
case ID_MLFILE_ADDMEDIATOLIBRARY: break;
case ID_MLFILE_CLOSEMEDIALIBRARY: break;
case ID_MLVIEW_NOWPLAYING: break;
case ID_MLVIEW_LOCALMEDIA_ALLMEDIA: break;
case ID_MLVIEW_LOCALMEDIA_AUDIO: break;
case ID_MLVIEW_LOCALMEDIA_VIDEO: break;
case ID_MLVIEW_PLAYLISTS_NOPLAYLISTINLIBRARY: break;
case ID_MLVIEW_INTERNETRADIO: break;
case ID_MLVIEW_INTERNETTV: break;
case ID_MLVIEW_LIBRARYPREFERENCES: break;
case ID_MLVIEW_DEVICES_NOAVAILABLEDEVICE: break;
case ID_MLFILE_IMPORTCURRENTPLAYLIST: break;
case ID_MLVIEW_MEDIA: break;
case ID_MLVIEW_PLAYLISTS: break;
case ID_MLVIEW_MEDIA_ALLMEDIA: break;
case ID_MLVIEW_DEVICES: break;
case ID_FILE_SHOWLIBRARY: break;
case ID_FILE_CLOSELIBRARY: break;
case ID_POST_PLAY_PLAYLIST: break;
case ID_VIS_NEXT: break;
case ID_VIS_PREV: break;
case ID_VIS_RANDOM: break;
case ID_MANAGEPLAYLISTS: break;
case ID_PREFS_SKIN_SWITCHTOSKIN: break;
case ID_PREFS_SKIN_DELETESKIN: break;
case ID_PREFS_SKIN_RENAMESKIN: break;
case ID_VIS_FS: break;
case ID_VIS_CFG: break;
case ID_VIS_MENU: break;
case ID_VIS_SET_FS_FLAG: break;
case ID_PE_SHOWPLAYING: break;
case ID_HELP_REGISTERWINAMPPRO: break;
case ID_PE_MANUAL_ADVANCE: break;
case WA_SONG_5_STAR_RATING: break;
case WA_SONG_4_STAR_RATING: break;
case WA_SONG_3_STAR_RATING: break;
case WA_SONG_2_STAR_RATING: break;
case WA_SONG_1_STAR_RATING: break;
case WA_SONG_NO_RATING: break;
case PL_SONG_5_STAR_RATING: break;
case PL_SONG_4_STAR_RATING: break;
case PL_SONG_3_STAR_RATING: break;
case PL_SONG_2_STAR_RATING: break;
case PL_SONG_1_STAR_RATING: break;
case PL_SONG_NO_RATING: break;
case AUDIO_TRACK_ONE: break;
case VIDEO_TRACK_ONE: break;
case ID_SWITCH_COLOURTHEME: break;
case ID_GENFF_LIMIT: break;
*/
case PLAINAMP_TOGGLE_CONSOLE:
ShowWindow( WindowConsole, IsWindowVisible( WindowConsole ) ? SW_HIDE : SW_SHOW );
break;
case PLAINAMP_TOGGLE_MANAGER:
ShowWindow( WindowManager, IsWindowVisible( WindowManager ) ? SW_HIDE : SW_SHOW );
break;
case PLAINAMP_PL_REM_SEL:
playlist->RemoveSelected( true );
break;
case PLAINAMP_PL_REM_CROP:
playlist->RemoveSelected( false );
break;
default:
{
/*
if( wp == ID_DYNAMICLIBRARY )
{
// Stupid dnylib workaround
PostMessage( hwnd, WM_COMMAND, ID_DYNAMICLIBRARY | ( 1 << 16 ), 0 );
}
*/
if( LOWORD( wp ) < 40001 ) break;
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "WM_COMMAND <%i> <%i>" ), wp, lp );
Console::Append( szBuffer );
Console::Append( TEXT( "NOT handled" ) );
Console::Append( " " );
}
}
break;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
case WM_WA_IPC:
/*
{
TCHAR szBuffer[ 5000 ];
if( lp != 2006 )
{
_stprintf( szBuffer, TEXT( "WM_WA_IPC <%i> <%i>" ), wp, lp );
}
else
{
// Hotkey sent as strings!
// Idea: make stl map
_stprintf( szBuffer, TEXT( "WM_WA_IPC <%s> <%i>" ), ( char * )wp, lp );
}
Console::Append( szBuffer );
}
*/
switch( lp )
{
case IPC_GETVERSION:
return 0x5010; // 5.10
/*
case IPC_GETREGISTEREDVERSION: break;
case IPC_PLAYFILE: break;
case IPC_ENQUEUEFILE: break;
*/
case IPC_DELETE:
playlist->RemoveAll();
break;
/*
case IPC_DELETE_INT: break;
*/
case IPC_STARTPLAY:
Playback::Play();
Playback::UpdateSeek();
break;
/*
case IPC_STARTPLAY_INT: break;
case IPC_CHDIR: break;
*/
case IPC_ISPLAYING: // untested
return ( Playback::IsPlaying() ? ( Playback::IsPaused() ? 3 : 1 ) : 0 );
/*
case IPC_GETOUTPUTTIME: break;
case IPC_JUMPTOTIME: break;
case IPC_GETMODULENAME: break;
case IPC_EX_ISRIGHTEXE: break;
case IPC_WRITEPLAYLIST: break;
*/
case IPC_SETPLAYLISTPOS:
playlist->SetCurIndex( ( int )wp );
break;
case IPC_SETVOLUME: break;
Playback::Volume::Set( ( int )wp );
// TODO Update slider
break;
case IPC_SETPANNING: break;
Playback::Pan::Set( ( int )wp );
// TODO Update slider
break;
case IPC_GETLISTLENGTH:
return playlist->GetSize();
case IPC_GETLISTPOS:
return playlist->GetCurIndex();
/*
case IPC_GETINFO: break;
case IPC_GETEQDATA: break;
// TODO
case IPC_SETEQDATA: break;
// TODO
case IPC_ADDBOOKMARK: break;
case IPC_INSTALLPLUGIN: break;
case IPC_RESTARTWINAMP: break;
case IPC_ISFULLSTOP: break;
case IPC_INETAVAILABLE: break;
case IPC_UPDTITLE: break;
case IPC_REFRESHPLCACHE: break;
case IPC_GET_SHUFFLE: break;
case IPC_GET_REPEAT: break;
case IPC_SET_SHUFFLE: break;
case IPC_SET_REPEAT: break;
case IPC_ENABLEDISABLE_ALL_WINDOWS: break;
*/
case IPC_GETWND:
{
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "IPC_GETWND <%i>" ), wp );
Console::Append( szBuffer );
Console::Append( " " );
}
switch( wp )
{
case IPC_GETWND_EQ: break;
case IPC_GETWND_PE: return ( LRESULT )WindowMain;
case IPC_GETWND_MB: break;
case IPC_GETWND_VIDEO: break;
}
return ( LRESULT )NULL;
case IPC_ISWNDVISIBLE:
{
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "IPC_ISWNDVISIBLE <%i>" ), wp );
Console::Append( szBuffer );
Console::Append( " " );
}
switch( wp )
{
case IPC_GETWND_EQ: break;
case IPC_GETWND_PE: return 1;
case IPC_GETWND_MB: break;
case IPC_GETWND_VIDEO: break;
}
return 0;
/*
case IPC_SETSKIN: break;
case IPC_GETSKIN: break;
case IPC_EXECPLUG: break;
*/
case IPC_GETPLAYLISTFILE:
{
static char szAnsiFilename[ 2000 ] = "\0";
Playlist::GetFilename( ( int )wp, szAnsiFilename, 1999 );
return ( LRESULT )szAnsiFilename;
}
case IPC_GETPLAYLISTTITLE:
{
static char szAnsiTitle[ 2000 ] = "\0";
Playlist::GetTitle( ( int )wp, szAnsiTitle, 1999 );
return ( LRESULT )szAnsiTitle;
}
/*
case IPC_GETHTTPGETTER: break;
case IPC_MBOPEN: break;
case IPC_CHANGECURRENTFILE: break;
case IPC_GETMBURL: break;
case IPC_MBBLOCK: break;
case IPC_MBOPENREAL: break;
case IPC_ADJUST_OPTIONSMENUPOS: break;
*/
case IPC_GET_HMENU:
{
switch( wp )
{
case 0:
return ( LRESULT )main_context_menu;
/*
case 1: break;
case 2: break;
case 3: break;
case 4: break;
*/
}
return ( LRESULT )NULL;
}
case IPC_GET_EXTENDED_FILE_INFO:
Console::Append( "IPC_GET_EXTENDED_FILE_INFO" );
Console::Append( TEXT( "NOT handled" ) );
Console::Append( " " );
break;
/*
case IPC_GET_EXTENDED_FILE_INFO_HOOKABLE: break;
case IPC_GET_BASIC_FILE_INFO: break;
*/
case IPC_GET_EXTLIST:
// TODO
return ( LRESULT )GlobalAlloc( GMEM_ZEROINIT, 2 ); // "\0\0"
/*
case IPC_INFOBOX: break;
case IPC_SET_EXTENDED_FILE_INFO: break;
case IPC_WRITE_EXTENDED_FILE_INFO: break;
case IPC_FORMAT_TITLE: break;
*/
case IPC_GETUNCOMPRESSINTERFACE:
if( wp == 0x10100000 )
{
Console::Append( "IPC_GETUNCOMPRESSINTERFACE @ wa_inflate_struct" );
Console::Append( TEXT( "NOT handled" ) );
Console::Append( " " );
}
else
{
Console::Append( "IPC_GETUNCOMPRESSINTERFACE @ zlib" );
Console::Append( " " );
return ( LRESULT )uncompress;
}
break;
case IPC_ADD_PREFS_DLG:
Prefs::AddPage( ( prefsDlgRec * )wp );
break;
/*
case IPC_REMOVE_PREFS_DLG: break;
*/
case IPC_OPENPREFSTOPAGE:
Prefs::Show( ( prefsDlgRec * )wp );
break;
case IPC_GETINIFILE:
{
static char szWinampInipath[ MAX_PATH ] = "";
if( *szWinampInipath == '\0' )
{
GetModuleFileNameA( NULL, szWinampInipath, MAX_PATH - 1 );
char * szWalk = szWinampInipath + strlen( szWinampInipath ) - 1;
while( ( szWalk > szWinampInipath ) && ( *szWalk != '.' ) ) szWalk--;
szWalk++;
strcpy( szWalk, "ini" );
}
return ( LRESULT )szWinampInipath;
}
case IPC_GETINIDIRECTORY:
{
// TODO: trailing slash or not???
static char szPluginInipath[ MAX_PATH ] = "";
if( *szPluginInipath == '\0' )
{
GetModuleFileNameA( NULL, szPluginInipath, MAX_PATH - 1 );
char * szWalk = szPluginInipath + strlen( szPluginInipath ) - 1;
while( ( szWalk > szPluginInipath ) && ( *szWalk != '\\' ) ) szWalk--;
szWalk++;
strcpy( szWalk, TEXT( "Plugins" ) );
}
return ( LRESULT )szPluginInipath;
}
/*
case IPC_SPAWNBUTTONPOPUP: break;
case IPC_OPENURLBOX: break;
*/
case IPC_OPENFILEBOX:
AddFiles();
break;
case IPC_OPENDIRBOX:
AddDirectory();
break;
case IPC_GET_GENSKINBITMAP:
{
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "IPC_GET_GENSKINBITMAP <%i>" ), wp );
Console::Append( szBuffer );
switch( wp )
{
case 0:
{
// TODO: make it work
// Gen.bmp?
static HBITMAP hBitmap = NULL;
static BYTE * image = NULL;
if( !hBitmap )
{
const int iWidth = 200; // 194;
const int iHeight = 300; // 109;
const int bpp = 24;
int bytes_per_row = iWidth * ( bpp / 8 );
const int diff = bytes_per_row % 4;
if( diff ) bytes_per_row += ( 4 - diff );
const int size_in_bytes = bytes_per_row * iHeight;
image = new BYTE[ size_in_bytes ];
hBitmap = CreateBitmap(
iWidth, // int nWidth
iHeight, // int nHeight
1, // UINT cPlanes
bpp, // UINT cBitsPerPel
image // CONST VOID * lpvBits
);
memset( image, 255, size_in_bytes );
}
return ( LRESULT )hBitmap;
}
default:
{
Console::Append( TEXT( "NOT handled" ) );
}
}
Console::Append( TEXT( " " ) );
break;
}
case IPC_GET_EMBEDIF:
// TODO
if( !wp )
{
return ( LRESULT )Embed::Embed;
}
else
{
return ( LRESULT )Embed::Embed( ( embedWindowState * )wp );
}
break;
/*
case IPC_EMBED_ENUM: break;
case IPC_EMBED_ISVALID: break;
case IPC_CONVERTFILE: break;
case IPC_CONVERTFILE_END: break;
case IPC_CONVERT_CONFIG: break;
case IPC_CONVERT_CONFIG_END: break;
case IPC_GETSADATAFUNC: break;
case IPC_ISMAINWNDVISIBLE: break;
case IPC_SETPLEDITCOLORS: break;
case IPC_SPAWNEQPRESETMENU: break;
case IPC_SPAWNFILEMENU: break;
case IPC_SPAWNOPTIONSMENU: break;
case IPC_SPAWNWINDOWSMENU: break;
case IPC_SPAWNHELPMENU: break;
case IPC_SPAWNPLAYMENU: break;
case IPC_SPAWNPEFILEMENU: break;
case IPC_SPAWNPEPLAYLISTMENU: break;
case IPC_SPAWNPESORTMENU: break;
case IPC_SPAWNPEHELPMENU: break;
case IPC_SPAWNMLFILEMENU: break;
case IPC_SPAWNMLVIEWMENU: break;
case IPC_SPAWNMLHELPMENU: break;
case IPC_SPAWNPELISTOFPLAYLISTS: break;
case WM_WA_SYSTRAY: break;
case IPC_IS_PLAYING_VIDEO: break;
case IPC_GET_IVIDEOOUTPUT: break;
*/
case IPC_CB_ONSHOWWND:
case IPC_CB_ONHIDEWND:
case IPC_CB_GETTOOLTIP:
case IPC_CB_MISC:
case IPC_CB_CONVERT_STATUS:
case IPC_CB_CONVERT_DONE:
break;
/*
case IPC_ADJUST_FFWINDOWSMENUPOS: break;
case IPC_ISDOUBLESIZE: break;
case IPC_ADJUST_FFOPTIONSMENUPOS: break;
*/
case IPC_GETTIMEDISPLAYMODE:
return 0; // == elapsed time
/*
case IPC_SETVISWND: break;
case IPC_GETVISWND: break;
case IPC_ISVISRUNNING: break;
*/
case IPC_CB_VISRANDOM: break;
/*
case IPC_SETIDEALVIDEOSIZE: break;
case IPC_GETSTOPONVIDEOCLOSE: break;
case IPC_SETSTOPONVIDEOCLOSE: break;
*/
case IPC_TRANSLATEACCELERATOR:
Console::Append( TEXT( "IPC_TRANSLATEACCELERATOR" ) );
Console::Append( TEXT( "NOT handled" ) );
Console::Append( TEXT( " " ) );
break;
case IPC_CB_ONTOGGLEAOT: break;
/*
case IPC_GETPREFSWND: break;
case IPC_SET_PE_WIDTHHEIGHT: break;
case IPC_GETLANGUAGEPACKINSTANCE: break;
*/
case IPC_CB_PEINFOTEXT:
case IPC_CB_OUTPUTCHANGED:
break;
/*
case IPC_GETOUTPUTPLUGIN: break;
case IPC_SETDRAWBORDERS: break;
case IPC_DISABLESKINCURSORS: break;
*/
case IPC_CB_RESETFONT: break;
/*
case IPC_IS_FULLSCREEN: break;
case IPC_SET_VIS_FS_FLAG: break;
case IPC_SHOW_NOTIFICATION: break;
case IPC_GETSKININFO: break;
case IPC_GET_MANUALPLADVANCE: break;
case IPC_SET_MANUALPLADVANCE: break;
case IPC_GET_NEXT_PLITEM: break;
case IPC_GET_PREVIOUS_PLITEM: break;
case IPC_IS_WNDSHADE: break;
case IPC_SETRATING: break;
case IPC_GETRATING: break;
case IPC_GETNUMAUDIOTRACKS: break;
case IPC_GETNUMVIDEOTRACKS: break;
case IPC_GETAUDIOTRACK: break;
case IPC_GETVIDEOTRACK: break;
case IPC_SETAUDIOTRACK: break;
case IPC_SETVIDEOTRACK: break;
case IPC_PUSH_DISABLE_EXIT: break;
case IPC_POP_DISABLE_EXIT: break;
case IPC_IS_EXIT_ENABLED: break;
case IPC_IS_AOT: break;
case IPC_PLCMD: break;
case IPC_MBCMD: break;
case IPC_VIDCMD: break;
case IPC_MBURL: break;
case IPC_MBGETCURURL: break;
case IPC_MBGETDESC: break;
case IPC_MBCHECKLOCFILE: break;
case IPC_MBREFRESH: break;
case IPC_MBGETDEFURL: break;
case IPC_STATS_LIBRARY_ITEMCNT: break;
case IPC_FF_FIRST: break;
case IPC_FF_LAST: break;
case IPC_GETDROPTARGET: break;
case IPC_PLAYLIST_MODIFIED: break;
case IPC_PLAYING_FILE: break;
case IPC_FILE_TAG_MAY_HAVE_UPDATED: break;
case IPC_ALLOW_PLAYTRACKING: break;
*/
case IPC_HOOK_OKTOQUIT:
return 1; // Okay
/*
case IPC_WRITECONFIG: break;
*/
case IPC_REGISTER_WINAMP_IPCMESSAGE:
{
// TODO convert to TCHAR????
UINT res = RegisterWindowMessage( ( LPCTSTR )wp );
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Message \"%s\" registered as #%i" ), wp, res );
Console::Append( szBuffer );
Console::Append( " " );
if( !stricmp( ( char * )wp, "GenHotkeysAdd" ) )
{
IPC_GENHOTKEYS_ADD = res;
}
else if( !stricmp( ( char * )wp, "Dynamic Library" ) )
{
ID_DYNAMICLIBRARY = res;
}
else if( !stricmp( ( char * )wp, "IPC_GETPLAINBARTARGET" ) )
{
IPC_GETPLAINBARTARGET = res;
}
return res;
}
case 2006: // undocumented, name IPC_CB_HOTKEY or so later and ask to add this to sdk
{
// Hotkey sent as strings!
// Idea: make stl map
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "Hotkey \"%s\" detected" ), wp );
Console::Append( szBuffer );
Console::Append( " " );
return 1; // Accept???
}
default:
{
if( lp == IPC_GENHOTKEYS_ADD )
{
break;
}
else if( lp == IPC_GETPLAINBARTARGET )
{
return ( LRESULT )( IsWindowVisible( WindowVis ) ? WindowVis : NULL );
}
TCHAR szBuffer[ 5000 ];
_stprintf( szBuffer, TEXT( "WM_WA_IPC <%i> <%i>" ), wp, lp );
Console::Append( szBuffer );
Console::Append( TEXT( "NOT handled" ) );
Console::Append( " " );
}
}
break;
case WM_WA_MPEG_EOF:
Playback::NotifyTrackEnd();
Playback::Next();
break;
case WM_COPYDATA:
{
if( !lp ) return FALSE;
COPYDATASTRUCT * cds = ( COPYDATASTRUCT * )lp;
switch( cds->dwData )
{
case IPC_PLAYFILE:
{
const int iLen = cds->cbData;
if( !iLen ) return FALSE;
TCHAR * szKeep = new TCHAR[ iLen + 1 ];
ToTchar( szKeep, ( char * )cds->lpData, iLen );
szKeep[ iLen ] = TEXT( '\0' );
playlist->PushBack( szKeep );
return TRUE;
}
}
return FALSE;
}
}
return DefWindowProc( hwnd, message, wp, lp );
}

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_WINAMP_H
#define PA_WINAMP_H
#include "Global.h"
LRESULT CALLBACK WndprocWinamp( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
#endif // PA_WINAMP_H

View File

@ -0,0 +1,47 @@
#ifndef WINAMP_DSP_H
#define WINAMP_DSP_H
#include <windows.h>
// DSP plugin interface
// notes:
// any window that remains in foreground should optimally pass unused
// keystrokes to the parent (winamp's) window, so that the user
// can still control it. As for storing configuration,
// Configuration data should be stored in <dll directory>\plugin.ini
// (look at the vis plugin for configuration code)
typedef struct winampDSPModule {
char *description; // description
HWND hwndParent; // parent window (filled in by calling app)
HINSTANCE hDllInstance; // instance handle to this DLL (filled in by calling app)
void (*Config)(struct winampDSPModule *this_mod); // configuration dialog (if needed)
int (*Init)(struct winampDSPModule *this_mod); // 0 on success, creates window, etc (if needed)
// modify waveform samples: returns number of samples to actually write
// (typically numsamples, but no more than twice numsamples, and no less than half numsamples)
// numsamples should always be at least 128. should, but I'm not sure
int (*ModifySamples)(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate);
void (*Quit)(struct winampDSPModule *this_mod); // called when unloading
void *userData; // user data, optional
} winampDSPModule;
typedef struct {
int version; // DSP_HDRVER
char *description; // description of library
winampDSPModule* (*getModule)(int); // module retrieval function
} winampDSPHeader;
// exported symbols
typedef winampDSPHeader* (*winampDSPGetHeaderType)();
// header version: 0x20 == 0.20 == winamp 2.0
#define DSP_HDRVER 0x20
#endif // WINAMP_DSP_H

View File

@ -0,0 +1,28 @@
#ifndef WINAMP_GEN_H
#define WINAMP_GEN_H
#define GPPHDR_VER 0x10
typedef struct {
int version;
char *description;
int (*init)();
void (*config)();
void (*quit)();
HWND hwndParent;
HINSTANCE hDllInstance;
} winampGeneralPurposePlugin;
typedef winampGeneralPurposePlugin * ( * winampGeneralPurposePluginGetter )();
// extern winampGeneralPurposePlugin * gen_plugins[ 256 ];
#endif // WINAMP_GEN_H

View File

@ -0,0 +1,119 @@
#ifndef WINAMP_IN_H
#define WINAMP_IN_H
#include <windows.h>
#include "out.h"
// note: exported symbol is now winampGetInModule2.
#define IN_VER 0x100
// Changed
// void (*VSASetInfo)(int nch, int srate);
// to
// void (*VSASetInfo)(int srate, int nch);
// since the old one is wrong!
//
// Otherwise in_mp3 is the problem!?...
typedef struct
{
int version; // module type (IN_VER)
char *description; // description of module, with version string
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
// May be altered from Config, so the user can select what they want
int is_seekable; // is this stream seekable?
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Init)(); // called at program init
void (*Quit)(); // called at program quit
void (*GetFileInfo)(char *file, char *title, int *length_in_ms); // if file == NULL, current playing is used
int (*InfoBox)(char *file, HWND hwndParent);
int (*IsOurFile)(char *fn); // called before extension checks, to allow detection of mms://, etc
// playback stuff
int (*Play)(char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
void (*Pause)(); // pause stream
void (*UnPause)(); // unpause stream
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
void (*Stop)(); // stop (unload) stream
// time stuff
int (*GetLength)(); // get length in ms
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush()..
// volume stuff
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
// in-window builtin vis stuff
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
// call after opening audio device with max latency in ms and samplerate
void (*SAVSADeInit)(); // call in Stop()
// simple vis supplying mode
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
// sets the spec data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
// use when calling SAAdd()
void (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
// vis stuff (plug-in)
// simple vis supplying mode
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
// quick and easy way to get vis working :)
// needs at least 576 samples :)
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
void (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
// call this in Play() to tell the vis plug-ins the current output params.
void (*VSASetInfo)(int srate, int nch);
// dsp plug-in processing:
// (filled in by winamp, called by input plug)
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
// could be greater than went in.. Use it to estimate if you'll have enough room in the
// output buffer
int (*dsp_isactive)();
// returns number of samples to output. This can be as much as twice numsamples.
// be sure to allocate enough buffer for samples, then.
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
// eq stuff
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
// info setting (filled in by winamp)
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
Out_Module *outMod; // filled in by winamp, optionally used :)
} In_Module;
#endif // WINAMP_IN_H

View File

@ -0,0 +1,69 @@
#ifndef WINAMP_OUT_H
#define WINAMP_OUT_H
#include <windows.h>
// [ids]
// waveout 32
// disk 33
// dsound 38
// xfade 63
// gapless 64
// null 65
// mm2 69
#define OUT_VER 0x10
typedef struct
{
int version; // module version (OUT_VER)
char *description; // description of module, with version string
int id; // module id. each input module gets its own. non-nullsoft modules should
// be >= 65536.
HWND hMainWindow; // winamp's main window (filled in by winamp)
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
void (*Config)(HWND hwndParent); // configuration dialog
void (*About)(HWND hwndParent); // about dialog
void (*Init)(); // called when loaded
void (*Quit)(); // called when unloaded
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
// returns >=0 on success, <0 on failure
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
// ... so don't expect the max latency returned to be what you asked for.
// returns max latency in ms (0 for diskwriters, etc)
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
// prebufferms must be <= bufferlenms
void (*Close)(); // close the ol' output device.
int (*Write)(char *buf, int len);
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
// 1 returns not able to write (yet). Non-blocking, always.
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
// Never will decrease unless you call Write (or Close, heh)
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
int (*Pause)(int pause); // returns previous pause state
void (*SetVolume)(int volume); // volume is 0-255
void (*SetPan)(int pan); // pan is -128 to 128
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
// (used for seeking)
int (*GetOutputTime)(); // returns played time in MS
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
} Out_Module;
#endif // WINAMP_OUT_H

View File

@ -0,0 +1,57 @@
#ifndef WINAMP_VIS_H
#define WINAMP_VIS_H
// notes:
// any window that remains in foreground should optimally pass
// keystrokes to the parent (winamp's) window, so that the user
// can still control it. unless escape is hit, or some option
// key specific to the vis is hit. As for storing configuration,
// Configuration data should be stored in <dll directory>\plugin.ini
// Look at the example plugin for a framework.
// ints are 32 bits, and structure members are aligned on the default 8 byte boundaries
// tested with VC++ 4.2 and 5.0
#include <windows.h>
typedef struct winampVisModule {
char *description; // description of module
HWND hwndParent; // parent window (filled in by calling app)
HINSTANCE hDllInstance; // instance handle to this DLL (filled in by calling app)
int sRate; // sample rate (filled in by calling app)
int nCh; // number of channels (filled in...)
int latencyMs; // latency from call of RenderFrame to actual drawing
// (calling app looks at this value when getting data)
int delayMs; // delay between calls in ms
// the data is filled in according to the respective Nch entry
int spectrumNch;
int waveformNch;
unsigned char spectrumData[2][576];
unsigned char waveformData[2][576];
void (*Config)(struct winampVisModule *this_mod); // configuration dialog
int (*Init)(struct winampVisModule *this_mod); // 0 on success, creates window, etc
int (*Render)(struct winampVisModule *this_mod); // returns 0 if successful, 1 if vis should end
void (*Quit)(struct winampVisModule *this_mod); // call when done
void *userData; // user data, optional
} winampVisModule;
typedef struct {
int version; // VID_HDRVER
char *description; // description of library
winampVisModule* (*getModule)(int);
} winampVisHeader;
// exported symbols
typedef winampVisHeader* (*winampVisGetHeaderType)();
// version of current module (0x101 == 1.01)
#define VIS_HDRVER 0x101
#endif // WINAMP_VIS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,297 @@
/*
** wa_msgids.h (created 14/04/2004 12:23:19 PM)
** Created from wa_ipc.h and resource.h from the language sdk
** by Darren Owen aka DrO
**
** This a simple header file which defines the message ids to allow you to control
** Winamp in keeping with the old frontend.h (R.I.P.)
**
**
** Version History:
**
** v1.0 :: intial version with ids for Winamp 5.02+
** v1.0a :: fixed the file to work on compile
** v1.1 :: added the msg id for 'Manual Playlist Advance'
** v1.2 :: added in song rating menu items
**
**
** How to use:
**
** To send these, use the format:
**
** SendMessage(hwnd_winamp, WM_COMMAND,command_name,0);
**
** For other languages such as Visual Basic, Pascal, etc you will need to use
** the equivalent calling SendMessage(..) calling convention
**
**
** Notes:
**
** IDs 42000 to 45000 are reserved for gen_ff
** IDs from 45000 to 57000 are reserved for library
**
*/
#ifndef _WA_MSGIDS_H_
#define _WA_MSGIDS_H_
#define WINAMP_FILE_QUIT 40001
#define WINAMP_OPTIONS_PREFS 40012 // pops up the preferences
#define WINAMP_OPTIONS_AOT 40019 // toggles always on top
#define WINAMP_FILE_REPEAT 40022
#define WINAMP_FILE_SHUFFLE 40023
#define WINAMP_HIGH_PRIORITY 40025
#define WINAMP_FILE_PLAY 40029 // pops up the load file(s) box
#define WINAMP_OPTIONS_EQ 40036 // toggles the EQ window
#define WINAMP_OPTIONS_ELAPSED 40037
#define WINAMP_OPTIONS_REMAINING 40038
#define WINAMP_OPTIONS_PLEDIT 40040 // toggles the playlist window
#define WINAMP_HELP_ABOUT 40041 // pops up the about box :)
#define WINAMP_MAINMENU 40043
/* the following are the five main control buttons, with optionally shift
** or control pressed
** (for the exact functions of each, just try it out)
*/
#define WINAMP_BUTTON1 40044
#define WINAMP_BUTTON2 40045
#define WINAMP_BUTTON3 40046
#define WINAMP_BUTTON4 40047
#define WINAMP_BUTTON5 40048
#define WINAMP_BUTTON1_SHIFT 40144
#define WINAMP_BUTTON2_SHIFT 40145
#define WINAMP_BUTTON3_SHIFT 40146
#define WINAMP_BUTTON4_SHIFT 40147
#define WINAMP_BUTTON5_SHIFT 40148
#define WINAMP_BUTTON1_CTRL 40154
#define WINAMP_BUTTON2_CTRL 40155
#define WINAMP_BUTTON3_CTRL 40156
#define WINAMP_BUTTON4_CTRL 40157
#define WINAMP_BUTTON5_CTRL 40158
#define WINAMP_VOLUMEUP 40058 // turns the volume up a little
#define WINAMP_VOLUMEDOWN 40059 // turns the volume down a little
#define WINAMP_FFWD5S 40060 // fast forwards 5 seconds
#define WINAMP_REW5S 40061 // rewinds 5 seconds
#define WINAMP_NEXT_WINDOW 40063
#define WINAMP_OPTIONS_WINDOWSHADE 40064
#define WINAMP_OPTIONS_DSIZE 40165
#define IDC_SORT_FILENAME 40166
#define IDC_SORT_FILETITLE 40167
#define IDC_SORT_ENTIREFILENAME 40168
#define IDC_SELECTALL 40169
#define IDC_SELECTNONE 40170
#define IDC_SELECTINV 40171
#define IDM_EQ_LOADPRE 40172
#define IDM_EQ_LOADMP3 40173
#define IDM_EQ_LOADDEFAULT 40174
#define IDM_EQ_SAVEPRE 40175
#define IDM_EQ_SAVEMP3 40176
#define IDM_EQ_SAVEDEFAULT 40177
#define IDM_EQ_DELPRE 40178
#define IDM_EQ_DELMP3 40180
#define IDC_PLAYLIST_PLAY 40184
#define WINAMP_FILE_LOC 40185
#define WINAMP_OPTIONS_EASYMOVE 40186
#define WINAMP_FILE_DIR 40187 // pops up the load directory box
#define WINAMP_EDIT_ID3 40188
#define WINAMP_TOGGLE_AUTOSCROLL 40189
#define WINAMP_VISSETUP 40190
#define WINAMP_PLGSETUP 40191
#define WINAMP_VISPLUGIN 40192
#define WINAMP_JUMP 40193
#define WINAMP_JUMPFILE 40194
#define WINAMP_JUMP10FWD 40195
#define WINAMP_JUMP10BACK 40197
#define WINAMP_PREVSONG 40198
#define WINAMP_OPTIONS_EXTRAHQ 40200
#define ID_PE_NEW 40201
#define ID_PE_OPEN 40202
#define ID_PE_SAVE 40203
#define ID_PE_SAVEAS 40204
#define ID_PE_SELECTALL 40205
#define ID_PE_INVERT 40206
#define ID_PE_NONE 40207
#define ID_PE_ID3 40208
#define ID_PE_S_TITLE 40209
#define ID_PE_S_FILENAME 40210
#define ID_PE_S_PATH 40211
#define ID_PE_S_RANDOM 40212
#define ID_PE_S_REV 40213
#define ID_PE_CLEAR 40214
#define ID_PE_MOVEUP 40215
#define ID_PE_MOVEDOWN 40216
#define WINAMP_SELSKIN 40219
#define WINAMP_VISCONF 40221
#define ID_PE_NONEXIST 40222
#define ID_PE_DELETEFROMDISK 40223
#define ID_PE_CLOSE 40224
#define WINAMP_VIS_SETOSC 40226
#define WINAMP_VIS_SETANA 40227
#define WINAMP_VIS_SETOFF 40228
#define WINAMP_VIS_DOTSCOPE 40229
#define WINAMP_VIS_LINESCOPE 40230
#define WINAMP_VIS_SOLIDSCOPE 40231
#define WINAMP_VIS_NORMANA 40233
#define WINAMP_VIS_FIREANA 40234
#define WINAMP_VIS_LINEANA 40235
#define WINAMP_VIS_NORMVU 40236
#define WINAMP_VIS_SMOOTHVU 40237
#define WINAMP_VIS_FULLREF 40238
#define WINAMP_VIS_FULLREF2 40239
#define WINAMP_VIS_FULLREF3 40240
#define WINAMP_VIS_FULLREF4 40241
#define WINAMP_OPTIONS_TOGTIME 40242
#define EQ_ENABLE 40244
#define EQ_AUTO 40245
#define EQ_PRESETS 40246
#define WINAMP_VIS_FALLOFF0 40247
#define WINAMP_VIS_FALLOFF1 40248
#define WINAMP_VIS_FALLOFF2 40249
#define WINAMP_VIS_FALLOFF3 40250
#define WINAMP_VIS_FALLOFF4 40251
#define WINAMP_VIS_PEAKS 40252
#define ID_LOAD_EQF 40253
#define ID_SAVE_EQF 40254
#define ID_PE_ENTRY 40255
#define ID_PE_SCROLLUP 40256
#define ID_PE_SCROLLDOWN 40257
#define WINAMP_MAIN_WINDOW 40258
#define WINAMP_VIS_PFALLOFF0 40259
#define WINAMP_VIS_PFALLOFF1 40260
#define WINAMP_VIS_PFALLOFF2 40261
#define WINAMP_VIS_PFALLOFF3 40262
#define WINAMP_VIS_PFALLOFF4 40263
#define ID_PE_TOP 40264
#define ID_PE_BOTTOM 40265
#define WINAMP_OPTIONS_WINDOWSHADE_PL 40266
#define EQ_INC1 40267
#define EQ_INC2 40268
#define EQ_INC3 40269
#define EQ_INC4 40270
#define EQ_INC5 40271
#define EQ_INC6 40272
#define EQ_INC7 40273
#define EQ_INC8 40274
#define EQ_INC9 40275
#define EQ_INC10 40276
#define EQ_INCPRE 40277
#define EQ_DECPRE 40278
#define EQ_DEC1 40279
#define EQ_DEC2 40280
#define EQ_DEC3 40281
#define EQ_DEC4 40282
#define EQ_DEC5 40283
#define EQ_DEC6 40284
#define EQ_DEC7 40285
#define EQ_DEC8 40286
#define EQ_DEC9 40287
#define EQ_DEC10 40288
#define ID_PE_SCUP 40289
#define ID_PE_SCDOWN 40290
#define WINAMP_REFRESHSKIN 40291
#define ID_PE_PRINT 40292
#define ID_PE_EXTINFO 40293
#define WINAMP_PLAYLIST_ADVANCE 40294
#define WINAMP_VIS_LIN 40295
#define WINAMP_VIS_BAR 40296
#define WINAMP_OPTIONS_MINIBROWSER 40298
#define MB_FWD 40299
#define MB_BACK 40300
#define MB_RELOAD 40301
#define MB_OPENMENU 40302
#define MB_OPENLOC 40303
#define WINAMP_NEW_INSTANCE 40305
#define MB_UPDATE 40309
#define WINAMP_OPTIONS_WINDOWSHADE_EQ 40310
#define EQ_PANLEFT 40313
#define EQ_PANRIGHT 40314
#define WINAMP_GETMORESKINS 40316
#define WINAMP_VIS_OPTIONS 40317
#define WINAMP_PE_SEARCH 40318
#define ID_PE_BOOKMARK 40319
#define WINAMP_EDIT_BOOKMARKS 40320
#define WINAMP_MAKECURBOOKMARK 40321
#define ID_MAIN_PLAY_BOOKMARK_NONE 40322
#define ID_MAIN_PLAY_AUDIOCD 40323 // starts playing the audio CD in the first CD reader
#define ID_MAIN_PLAY_AUDIOCD2 40324 // plays the 2nd
#define ID_MAIN_PLAY_AUDIOCD3 40325 // plays the 3rd
#define ID_MAIN_PLAY_AUDIOCD4 40326 // plays the 4th
#define WINAMP_OPTIONS_VIDEO 40328
#define ID_VIDEOWND_ZOOMFULLSCREEN 40329
#define ID_VIDEOWND_ZOOM100 40330
#define ID_VIDEOWND_ZOOM200 40331
#define ID_VIDEOWND_ZOOM50 40332
#define ID_VIDEOWND_VIDEOOPTIONS 40333
#define WINAMP_MINIMIZE 40334
#define ID_PE_FONTBIGGER 40335
#define ID_PE_FONTSMALLER 40336
#define WINAMP_VIDEO_TOGGLE_FS 40337
#define WINAMP_VIDEO_TVBUTTON 40338
#define WINAMP_LIGHTNING_CLICK 40339
#define ID_FILE_ADDTOLIBRARY 40344
#define ID_HELP_HELPTOPICS 40347
#define ID_HELP_GETTINGSTARTED 40348
#define ID_HELP_WINAMPFORUMS 40349
#define ID_PLAY_VOLUMEUP 40351
#define ID_PLAY_VOLUMEDOWN 40352
#define ID_PEFILE_OPENPLAYLISTFROMLIBRARY_NOPLAYLISTSINLIBRARY 40355
#define ID_PEFILE_ADDFROMLIBRARY 40356
#define ID_PEFILE_CLOSEPLAYLISTEDITOR 40357
#define ID_PEPLAYLIST_PLAYLISTPREFERENCES 40358
#define ID_MLFILE_NEWPLAYLIST 40359
#define ID_MLFILE_LOADPLAYLIST 40360
#define ID_MLFILE_SAVEPLAYLIST 40361
#define ID_MLFILE_ADDMEDIATOLIBRARY 40362
#define ID_MLFILE_CLOSEMEDIALIBRARY 40363
#define ID_MLVIEW_NOWPLAYING 40364
#define ID_MLVIEW_LOCALMEDIA_ALLMEDIA 40366
#define ID_MLVIEW_LOCALMEDIA_AUDIO 40367
#define ID_MLVIEW_LOCALMEDIA_VIDEO 40368
#define ID_MLVIEW_PLAYLISTS_NOPLAYLISTINLIBRARY 40369
#define ID_MLVIEW_INTERNETRADIO 40370
#define ID_MLVIEW_INTERNETTV 40371
#define ID_MLVIEW_LIBRARYPREFERENCES 40372
#define ID_MLVIEW_DEVICES_NOAVAILABLEDEVICE 40373
#define ID_MLFILE_IMPORTCURRENTPLAYLIST 40374
#define ID_MLVIEW_MEDIA 40376
#define ID_MLVIEW_PLAYLISTS 40377
#define ID_MLVIEW_MEDIA_ALLMEDIA 40377
#define ID_MLVIEW_DEVICES 40378
#define ID_FILE_SHOWLIBRARY 40379
#define ID_FILE_CLOSELIBRARY 40380
#define ID_POST_PLAY_PLAYLIST 40381
#define ID_VIS_NEXT 40382
#define ID_VIS_PREV 40383
#define ID_VIS_RANDOM 40384
#define ID_MANAGEPLAYLISTS 40385
#define ID_PREFS_SKIN_SWITCHTOSKIN 40386
#define ID_PREFS_SKIN_DELETESKIN 40387
#define ID_PREFS_SKIN_RENAMESKIN 40388
#define ID_VIS_FS 40389
#define ID_VIS_CFG 40390
#define ID_VIS_MENU 40391
#define ID_VIS_SET_FS_FLAG 40392
#define ID_PE_SHOWPLAYING 40393
#define ID_HELP_REGISTERWINAMPPRO 40394
#define ID_PE_MANUAL_ADVANCE 40395
#define WA_SONG_5_STAR_RATING 40396
#define WA_SONG_4_STAR_RATING 40397
#define WA_SONG_3_STAR_RATING 40398
#define WA_SONG_2_STAR_RATING 40399
#define WA_SONG_1_STAR_RATING 40400
#define WA_SONG_NO_RATING 40401
#define PL_SONG_5_STAR_RATING 40402
#define PL_SONG_4_STAR_RATING 40403
#define PL_SONG_3_STAR_RATING 40404
#define PL_SONG_2_STAR_RATING 40405
#define PL_SONG_1_STAR_RATING 40406
#define PL_SONG_NO_RATING 40407
#define AUDIO_TRACK_ONE 40408
#define VIDEO_TRACK_ONE 40424
#define ID_SWITCH_COLOURTHEME 44500
#define ID_GENFF_LIMIT 45000
#endif

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.
////////////////////////////////////////////////////////////////////////////////
#include "Global.h"
#include "Font.h"
#include "InputPlugin.h"
#include "OutputPlugin.h"
#include "VisPlugin.h"
#include "DspPlugin.h"
#include "GenPlugin.h"
#include "Main.h"
#include "Rebar.h"
#include "Playlist.h"
#include "Status.h"
#include "PluginManager.h"
#include "Prefs.h"
#include "Config.h"
#include "Emabox/Emabox.h"
#define PLUS_ALT ( FVIRTKEY | FALT )
#define PLUS_CONTROL ( FVIRTKEY | FCONTROL )
#define PLUS_CONTROL_ALT ( FVIRTKEY | FCONTROL | FALT )
#define PLUS_CONTROL_SHIFT ( FVIRTKEY | FCONTROL | FSHIFT )
#define PLUS_SHIFT ( FVIRTKEY | FSHIFT )
HINSTANCE g_hInstance = NULL; // extern
TCHAR * szHomeDir = NULL; // extern
int iHomeDirLen = 0; // extern
TCHAR * szPluginDir = NULL; // extern
int iPluginDirLen = 0; // extern
TCHAR szCurDir[ MAX_PATH + 1 ] = TEXT( "" );
ConfCurDir ccdCurDir( szCurDir, TEXT( "CurDir" ) );
bool bWarnPluginsMissing;
ConfBool cbWarnPluginsMissing( &bWarnPluginsMissing, TEXT( "WarnPluginsMissing" ), CONF_MODE_PUBLIC, true );
////////////////////////////////////////////////////////////////////////////////
///
////////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow )
{
g_hInstance = hInstance;
// Load full config
Conf::Init( hInstance );
// Get home dir
szHomeDir = new TCHAR[ MAX_PATH + 1 ];
iHomeDirLen = GetModuleFileName( NULL, szHomeDir, MAX_PATH );
if( !iHomeDirLen ) return 1;
TCHAR * walk = szHomeDir + iHomeDirLen - 1;
while( ( walk > szHomeDir ) && ( *walk != TEXT( '\\' ) ) ) walk--;
walk++;
*walk = TEXT( '\0' );
iHomeDirLen = walk - szHomeDir;
// Get plugins dir
szPluginDir = new TCHAR[ MAX_PATH + 1 ];
memcpy( szPluginDir, szHomeDir, iHomeDirLen * sizeof( TCHAR ) );
memcpy( szPluginDir + iHomeDirLen, TEXT( "Plugins" ), 7 * sizeof( TCHAR ) );
szPluginDir[ iHomeDirLen + 7 ] = TEXT( '\0' );
Font::Create();
BuildMainWindow();
Prefs::Create();
// Show window
ShowWindow( WindowMain, SW_SHOW );
SetForegroundWindow( WindowMain );
SetFocus( WindowMain );
Plugin::FindAll<InputPlugin> ( szPluginDir, TEXT( "in_*.dll" ), true );
Plugin::FindAll<OutputPlugin>( szPluginDir, TEXT( "out_*.dll" ), false );
Plugin::FindAll<VisPlugin> ( szPluginDir, TEXT( "vis_*.dll" ), false );
Plugin::FindAll<DspPlugin> ( szPluginDir, TEXT( "dsp_*.dll" ), false );
Plugin::FindAll<GenPlugin> ( szPluginDir, TEXT( "gen_*.dll" ), true );
PluginManager::Fill();
// Check plugin presence
// One msgbox maximum
if( bWarnPluginsMissing )
{
if( input_plugins.empty() )
{
// No input plugins
TCHAR szBuffer[ 5000 ];
_stprintf(
szBuffer,
TEXT(
"No input plugins were found.\n"
"\n"
"Please install at least one Winamp input plugin to \n"
"%s "
),
szPluginDir
);
int iNeverAgain = bWarnPluginsMissing ? 0 : 1;
EmaBox( 0, szBuffer, TEXT( "Input plugins missing" ), MB_ICONEXCLAMATION | MB_CHECKNEVERAGAIN, &iNeverAgain );
bWarnPluginsMissing = ( iNeverAgain == 0 );
}
else if( output_plugins.empty() )
{
// No output plugins
TCHAR szBuffer[ 5000 ];
_stprintf(
szBuffer,
TEXT(
"No output plugins were found.\n"
"\n"
"Please install at least one Winamp output plugin to \n"
"%s "
),
szPluginDir
);
int iNeverAgain = bWarnPluginsMissing ? 0 : 1;
EmaBox( 0, szBuffer, TEXT( "Output plugins missing" ), MB_ICONEXCLAMATION | MB_CHECKNEVERAGAIN, &iNeverAgain );
bWarnPluginsMissing = ( iNeverAgain == 0 );
}
}
// Todo: all the rest...
ACCEL accels[] = {
{ PLUS_CONTROL, 'A', ID_PE_SELECTALL }, // [Ctrl] + [A]
{ PLUS_CONTROL, 'I', ID_PE_INVERT }, // [Ctrl] + [I]
{ PLUS_CONTROL, 'N', ID_PE_NEW }, // [Ctrl] + [N]
{ PLUS_CONTROL, 'O', ID_PE_OPEN }, // [Ctrl] + [O]
{ PLUS_CONTROL, 'P', WINAMP_OPTIONS_PREFS }, // [Ctrl] + [P]
{ PLUS_CONTROL, 'S', ID_PE_SAVEAS }, // [Ctrl] + [S]
{ PLUS_CONTROL, VK_F1, WINAMP_HELP_ABOUT }, // [Ctrl] + [F1]
{ PLUS_CONTROL_SHIFT, 'A', ID_PE_NONE }, // [Ctrl] + [Shift] + [A]
{ PLUS_CONTROL_SHIFT, VK_DELETE, ID_PE_CLEAR }, // [Ctrl] + [Shift] + [Del]
{ PLUS_ALT, 'F', WINAMP_MAINMENU }, // [Alt] + [F]
{ PLUS_ALT, VK_F4, WINAMP_FILE_QUIT } // [Alt] + [F4]
};
HACCEL hAccel = CreateAcceleratorTable( accels, sizeof( accels ) / sizeof( ACCEL ) );
if( !hAccel )
{
MessageBox( 0, TEXT( "Accelerator table error" ), TEXT( "" ), 0 );
}
// Message loop
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
{
// Note: Keys without [Alt] or [Ctrl] not everywhere!
if( ( ( msg.hwnd == WindowMain ) || IsChild( WindowMain, msg.hwnd ) ) &&
TranslateAccelerator( WindowMain, hAccel, &msg ) )
{
// MessageBox( 0, TEXT( "Trans" ), TEXT( "" ), 0 );
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
DestroyAcceleratorTable( hAccel );
// Input
vector <InputPlugin *>::iterator iter_input = input_plugins.begin();
while( iter_input != input_plugins.end() )
{
( *iter_input )->Unload();
iter_input++;
}
// Output
vector <OutputPlugin *>::iterator iter_output = output_plugins.begin();
while( iter_output != output_plugins.end() )
{
( *iter_output )->Unload();
iter_output++;
}
// General
vector <GenPlugin *>::iterator iter_gen = gen_plugins.begin();
while( iter_gen != gen_plugins.end() )
{
( *iter_gen )->Unload();
iter_gen++;
}
// TODO: create main::destroy
// UnregisterClass( PA_CLASSNAME, g_hInstance );
Prefs::Destroy();
Font::Destroy();
/*
delete [] szPluginDir;
delete [] szHomeDir;
*/
Conf::Write();
return 0;
}

View File

@ -0,0 +1,276 @@
/*
* Copyright (c) 2003 Matteo Frigo
* Copyright (c) 2003 Massachusetts Institute of Technology
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* header file for fftw3 */
/* $Id: fftw3.h,v 1.1 2005/10/28 19:01:21 hartwork Exp $ */
#ifndef FFTW3_H
#define FFTW3_H
#if defined(__ICC) || defined(_MSC_VER)
#pragma comment ( lib, "fftw3" )
#endif
#include <stdio.h>
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* If <complex.h> is included, use the C99 complex type. Otherwise
define a type bit-compatible with C99 complex */
#ifdef _Complex_I
# define FFTW_DEFINE_COMPLEX(R, C) typedef R _Complex C
#else
# define FFTW_DEFINE_COMPLEX(R, C) typedef R C[2]
#endif
#define FFTW_CONCAT(prefix, name) prefix ## name
#define FFTW_MANGLE_DOUBLE(name) FFTW_CONCAT(fftw_, name)
#define FFTW_MANGLE_FLOAT(name) FFTW_CONCAT(fftwf_, name)
#define FFTW_MANGLE_LONG_DOUBLE(name) FFTW_CONCAT(fftwl_, name)
enum fftw_r2r_kind_do_not_use_me {
FFTW_R2HC=0, FFTW_HC2R=1, FFTW_DHT=2,
FFTW_REDFT00=3, FFTW_REDFT01=4, FFTW_REDFT10=5, FFTW_REDFT11=6,
FFTW_RODFT00=7, FFTW_RODFT01=8, FFTW_RODFT10=9, FFTW_RODFT11=10
};
struct fftw_iodim_do_not_use_me {
int n; /* dimension size */
int is; /* input stride */
int os; /* output stride */
};
/*
huge second-order macro that defines prototypes for all API
functions. We expand this macro for each supported precision
X: name-mangling macro
R: real data type
C: complex data type
*/
#define FFTW_DEFINE_API(X, R, C) \
\
FFTW_DEFINE_COMPLEX(R, C); \
\
typedef struct X(plan_s) *X(plan); \
\
typedef struct fftw_iodim_do_not_use_me X(iodim); \
\
typedef enum fftw_r2r_kind_do_not_use_me X(r2r_kind); \
\
void X(execute)(const X(plan) p); \
\
X(plan) X(plan_dft)(int rank, const int *n, \
C *in, C *out, int sign, unsigned flags); \
\
X(plan) X(plan_dft_1d)(int n, C *in, C *out, int sign, \
unsigned flags); \
X(plan) X(plan_dft_2d)(int nx, int ny, \
C *in, C *out, int sign, unsigned flags); \
X(plan) X(plan_dft_3d)(int nx, int ny, int nz, \
C *in, C *out, int sign, unsigned flags); \
\
X(plan) X(plan_many_dft)(int rank, const int *n, \
int howmany, \
C *in, const int *inembed, \
int istride, int idist, \
C *out, const int *onembed, \
int ostride, int odist, \
int sign, unsigned flags); \
\
X(plan) X(plan_guru_dft)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
C *in, C *out, \
int sign, unsigned flags); \
X(plan) X(plan_guru_split_dft)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
R *ri, R *ii, R *ro, R *io, \
unsigned flags); \
\
void X(execute_dft)(const X(plan) p, C *in, C *out); \
void X(execute_split_dft)(const X(plan) p, R *ri, R *ii, R *ro, R *io); \
\
X(plan) X(plan_many_dft_r2c)(int rank, const int *n, \
int howmany, \
R *in, const int *inembed, \
int istride, int idist, \
C *out, const int *onembed, \
int ostride, int odist, \
unsigned flags); \
\
X(plan) X(plan_dft_r2c)(int rank, const int *n, \
R *in, C *out, unsigned flags); \
\
X(plan) X(plan_dft_r2c_1d)(int n,R *in,C *out,unsigned flags); \
X(plan) X(plan_dft_r2c_2d)(int nx, int ny, \
R *in, C *out, unsigned flags); \
X(plan) X(plan_dft_r2c_3d)(int nx, int ny, \
int nz, \
R *in, C *out, unsigned flags); \
\
\
X(plan) X(plan_many_dft_c2r)(int rank, const int *n, \
int howmany, \
C *in, const int *inembed, \
int istride, int idist, \
R *out, const int *onembed, \
int ostride, int odist, \
unsigned flags); \
\
X(plan) X(plan_dft_c2r)(int rank, const int *n, \
C *in, R *out, unsigned flags); \
\
X(plan) X(plan_dft_c2r_1d)(int n,C *in,R *out,unsigned flags); \
X(plan) X(plan_dft_c2r_2d)(int nx, int ny, \
C *in, R *out, unsigned flags); \
X(plan) X(plan_dft_c2r_3d)(int nx, int ny, \
int nz, \
C *in, R *out, unsigned flags); \
\
X(plan) X(plan_guru_dft_r2c)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
R *in, C *out, \
unsigned flags); \
X(plan) X(plan_guru_dft_c2r)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
C *in, R *out, \
unsigned flags); \
\
X(plan) X(plan_guru_split_dft_r2c)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
R *in, R *ro, R *io, \
unsigned flags); \
X(plan) X(plan_guru_split_dft_c2r)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
R *ri, R *ii, R *out, \
unsigned flags); \
\
void X(execute_dft_r2c)(const X(plan) p, R *in, C *out); \
void X(execute_dft_c2r)(const X(plan) p, C *in, R *out); \
\
void X(execute_split_dft_r2c)(const X(plan) p, R *in, R *ro, R *io); \
void X(execute_split_dft_c2r)(const X(plan) p, R *ri, R *ii, R *out); \
\
X(plan) X(plan_many_r2r)(int rank, const int *n, \
int howmany, \
R *in, const int *inembed, \
int istride, int idist, \
R *out, const int *onembed, \
int ostride, int odist, \
const X(r2r_kind) *kind, unsigned flags); \
\
X(plan) X(plan_r2r)(int rank, const int *n, R *in, R *out, \
const X(r2r_kind) *kind, unsigned flags); \
\
X(plan) X(plan_r2r_1d)(int n, R *in, R *out, \
X(r2r_kind) kind, unsigned flags); \
X(plan) X(plan_r2r_2d)(int nx, int ny, R *in, R *out, \
X(r2r_kind) kindx, X(r2r_kind) kindy, \
unsigned flags); \
X(plan) X(plan_r2r_3d)(int nx, int ny, int nz, \
R *in, R *out, X(r2r_kind) kindx, \
X(r2r_kind) kindy, X(r2r_kind) kindz, \
unsigned flags); \
\
X(plan) X(plan_guru_r2r)(int rank, const X(iodim) *dims, \
int howmany_rank, \
const X(iodim) *howmany_dims, \
R *in, R *out, \
const X(r2r_kind) *kind, unsigned flags); \
void X(execute_r2r)(const X(plan) p, R *in, R *out); \
\
void X(destroy_plan)(X(plan) p); \
void X(forget_wisdom)(void); \
void X(cleanup)(void); \
\
void X(plan_with_nthreads)(int nthreads); \
int X(init_threads)(void); \
void X(cleanup_threads)(void); \
\
void X(export_wisdom_to_file)(FILE *output_file); \
char *X(export_wisdom_to_string)(void); \
void X(export_wisdom)(void (*write_char)(char c, void *), void *data); \
int X(import_system_wisdom)(void); \
int X(import_wisdom_from_file)(FILE *input_file); \
int X(import_wisdom_from_string)(const char *input_string); \
int X(import_wisdom)(int (*read_char)(void *), void *data); \
\
void X(fprint_plan)(const X(plan) p, FILE *output_file); \
void X(print_plan)(const X(plan) p); \
\
void *X(malloc)(size_t n); \
void X(free)(void *p); \
\
void X(flops)(const X(plan) p, double *add, double *mul, double *fma); \
\
extern const char X(version)[]; \
extern const char X(cc)[]; \
extern const char X(codelet_optim)[];
/* end of FFTW_DEFINE_API macro */
FFTW_DEFINE_API(FFTW_MANGLE_DOUBLE, double, fftw_complex)
FFTW_DEFINE_API(FFTW_MANGLE_FLOAT, float, fftwf_complex)
FFTW_DEFINE_API(FFTW_MANGLE_LONG_DOUBLE, long double, fftwl_complex)
#define FFTW_FORWARD (-1)
#define FFTW_BACKWARD (+1)
/* documented flags */
#define FFTW_MEASURE (0U)
#define FFTW_DESTROY_INPUT (1U << 0)
#define FFTW_UNALIGNED (1U << 1)
#define FFTW_CONSERVE_MEMORY (1U << 2)
#define FFTW_EXHAUSTIVE (1U << 3) /* NO_EXHAUSTIVE is default */
#define FFTW_PRESERVE_INPUT (1U << 4) /* cancels FFTW_DESTROY_INPUT */
#define FFTW_PATIENT (1U << 5) /* IMPATIENT is default */
#define FFTW_ESTIMATE (1U << 6)
/* undocumented beyond-guru flags */
#define FFTW_ESTIMATE_PATIENT (1U << 7)
#define FFTW_BELIEVE_PCOST (1U << 8)
#define FFTW_DFT_R2HC_ICKY (1U << 9)
#define FFTW_NONTHREADED_ICKY (1U << 10)
#define FFTW_NO_BUFFERING (1U << 11)
#define FFTW_NO_INDIRECT_OP (1U << 12)
#define FFTW_ALLOW_LARGE_GENERIC (1U << 13) /* NO_LARGE_GENERIC is default */
#define FFTW_NO_RANK_SPLITS (1U << 14)
#define FFTW_NO_VRANK_SPLITS (1U << 15)
#define FFTW_NO_VRECURSE (1U << 16)
#define FFTW_NO_SIMD (1U << 17)
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* FFTW3_H */

View File

@ -0,0 +1,259 @@
////////////////////////////////////////////////////////////////////////////////
// Plainamp Toolbar Vis Plugin
//
// 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.
////////////////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "../Winamp/vis.h"
#include "../Winamp/wa_ipc.h"
#define PLUGIN_NAME "Plainamp Toolbar Vis Plugin"
#define PLUGIN_VERSION "v0.5"
#define PLUGIN_DESC PLUGIN_NAME " " PLUGIN_VERSION
static char * szClassName = "PlainbarClass";
winampVisModule * getModule( int which );
void config( struct winampVisModule * this_mod );
int init( struct winampVisModule * this_mod );
int render_spec( struct winampVisModule * this_mod );
void quit( struct winampVisModule * this_mod );
// Double buffering data
HDC memDC = NULL; // Memory device context
HBITMAP memBM = NULL; // Memory bitmap (for memDC)
HBITMAP oldBM = NULL; // Old bitmap (from memDC)
HWND hRender = NULL;
int width = 0;
int height = 0;
bool bRunning = false;
HPEN pen = NULL;
WNDPROC WndprocTargetBackup = NULL;
LRESULT CALLBACK WndprocTarget( HWND hwnd, UINT message, WPARAM wp, LPARAM lp );
winampVisHeader hdr = {
VIS_HDRVER,
PLUGIN_DESC,
getModule
};
winampVisModule mod_spec =
{
"Default",
NULL, // hwndParent
NULL, // hDllInstance
0, // sRate
0, // nCh
25, // latencyMS
25, // delayMS
2, // spectrumNch
0, // waveformNch
{ 0, }, // spectrumData
{ 0, }, // waveformData
config,
init,
render_spec,
quit
};
#ifdef __cplusplus
extern "C" {
#endif
__declspec( dllexport ) winampVisHeader * winampVisGetHeader()
{
return &hdr;
}
#ifdef __cplusplus
}
#endif
winampVisModule * getModule( int which )
{
return which ? NULL : &mod_spec;
}
void config( struct winampVisModule * this_mod )
{
MessageBox(
this_mod->hwndParent,
PLUGIN_DESC "\n"
"\n"
"Copyright © 2006 Sebastian Pipping \n"
"<webmaster@hartwork.org>\n"
"\n"
"--> http://www.hartwork.org",
"About",
MB_ICONINFORMATION
);
}
LRESULT CALLBACK WndprocTarget( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
switch( message )
{
case WM_SIZE:
width = LOWORD( lp );
height = HIWORD( lp );
break;
case WM_DESTROY:
bRunning = false;
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hwnd, message, wp, lp );
}
int init( struct winampVisModule * this_mod )
{
if( !this_mod ) return 1;
// Register message
const int IPC_GETPLAINBARTARGET = ( int )SendMessage( this_mod->hwndParent, WM_WA_IPC, ( WPARAM )"IPC_GETPLAINBARTARGET", IPC_REGISTER_WINAMP_IPCMESSAGE );
if( IPC_GETPLAINBARTARGET <= 0 ) return 1;
// Get render parent
HWND hRenderParent = ( HWND )SendMessage( this_mod->hwndParent, WM_WA_IPC, 0, IPC_GETPLAINBARTARGET );
if( !IsWindow( hRenderParent ) ) return 1;
// Plug our child in
WNDCLASS wc;
ZeroMemory( &wc, sizeof( WNDCLASS ) );
wc.lpfnWndProc = WndprocTarget;
wc.hInstance = this_mod->hDllInstance;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.lpszClassName = szClassName;
if( !RegisterClass( &wc ) ) return 1;
RECT r;
GetClientRect( hRenderParent, &r );
width = r.right - r.left;
height = r.bottom - r.top;
hRender = CreateWindowEx(
0,
szClassName,
"",
WS_CHILD | WS_VISIBLE,
0,
0,
width,
height,
hRenderParent,
NULL,
this_mod->hDllInstance,
0
);
if( !hRender )
{
UnregisterClass( szClassName, this_mod->hDllInstance );
return 1;
}
// Create doublebuffer
const HDC hdc = GetDC( hRender );
memDC = CreateCompatibleDC( hdc );
memBM = CreateCompatibleBitmap( hdc, 576, 256 );
oldBM = ( HBITMAP )SelectObject( memDC, memBM );
ReleaseDC( hRender, hdc );
pen = CreatePen( PS_SOLID, 0, GetSysColor( COLOR_APPWORKSPACE ) );
bRunning = true;
return 0;
}
int render_spec( struct winampVisModule * this_mod )
{
// Clear background
RECT rect = { 0, 0, 576, 256 };
FillRect(memDC, &rect, ( HBRUSH )( COLOR_3DFACE + 1 ) );
// Draw analyser
SelectObject( memDC, pen );
for( int x = 0; x < 576; x++ )
{
int val = 0;
for( int y = 0; y < this_mod->nCh; y++ )
{
if( this_mod->spectrumData[ y ][ x ] > val )
{
val = this_mod->spectrumData[ y ][ x ];
}
}
MoveToEx( memDC, x, 256, NULL );
LineTo( memDC, x, 256 - val );
}
// Copy doublebuffer to window
HDC hdc = GetDC( hRender );
StretchBlt( hdc, 0, 0, width, height, memDC, 0, 0, 576, 256, SRCCOPY );
ReleaseDC( hRender, hdc );
return bRunning ? 0 : 1;
}
void quit( struct winampVisModule * this_mod )
{
if( bRunning )
{
DestroyWindow( hRender );
}
UnregisterClass( szClassName, this_mod->hDllInstance );
// Delete doublebuffer
SelectObject( memDC, oldBM );
DeleteObject( memDC );
DeleteObject( memBM );
DeleteObject( pen );
}

View File

@ -0,0 +1,332 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: zconf.h,v 1.1 2005/10/10 21:08:30 hartwork Exp $ */
#ifndef ZCONF_H
#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
*/
#ifdef Z_PREFIX
# define deflateInit_ z_deflateInit_
# define deflate z_deflate
# define deflateEnd z_deflateEnd
# define inflateInit_ z_inflateInit_
# define inflate z_inflate
# define inflateEnd z_inflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateSetDictionary z_deflateSetDictionary
# define deflateCopy z_deflateCopy
# define deflateReset z_deflateReset
# define deflateParams z_deflateParams
# define deflateBound z_deflateBound
# define deflatePrime z_deflatePrime
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32
# define get_crc_table z_get_crc_table
# define zError z_zError
# define alloc_func z_alloc_func
# define free_func z_free_func
# define in_func z_in_func
# define out_func z_out_func
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef
# define charf z_charf
# define intf z_intf
# define uIntf z_uIntf
# define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(__OS400__)
# define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

File diff suppressed because it is too large Load Diff