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