/*
** Copyright (C) 2006 Kannan Krishnamoorthy.
**
** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held
** liable for any damages arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to
** alter it and redistribute it freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.
** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
**
** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
**
** 3. This notice may not be removed or altered from any source distribution.
**
*/
///////////////////////////////////////////////////////////////////////////////
/// @file streamRipper.cpp
///
/// @author Kannan K
///
/// @brief implementation stramRipper
///
/// @note
/// @verbatim
/// ___________________________________________________________________________
/// Revision History
/// Kannan K 05-Dec-2005 Created.
/// @endverbatim
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <commctrl.h>
#include <atlbase.h>
#include "dsp.h"
#include "resource.h"
#include "wave.h"
#include "wa_ipc.h"
#pragma warning(disable : 4996)
typedef struct tagInfo
{
HWND m_hwnd;
BOOL m_start;
CWave *pWav;
TCHAR strPath[MAX_PATH];
INT m_iPrgbar;
BOOL m_bAuto;
}Info;
// avoid stupid CRT silliness
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}
// module getter.
winampDSPModule *getModule(int which);
//plug-in must implement methods
void config(struct winampDSPModule *this_mod);
int init(struct winampDSPModule *this_mod);
void quit(struct winampDSPModule *this_mod);
int modify_samples(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate);
// for auto mode
WNDPROC prvProc;
// for auto mode
LRESULT CALLBACK winampMainproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
// main window procedure
INT_PTR CALLBACK ConfigProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lpParam);
// Module header, includes version, description, and address of the module retriever function
winampDSPHeader hdr = { DSP_HDRVER, "streamRipper", getModule };
// structure holding all private data
Info data;
// first module
winampDSPModule mod =
{
"streamRipper",
NULL, // hwndParent
NULL, // hDllInstance
config,
init,
modify_samples,
quit
};
#ifdef __cplusplus
extern "C" {
#endif
// this is the only exported symbol. returns our main header.
__declspec( dllexport ) winampDSPHeader *winampDSPGetHeader2()
{
return &hdr;
}
#ifdef __cplusplus
}
#endif
//main method of plugin
winampDSPModule *getModule(int which)
{
switch (which)
{
case 0: return &mod;
default:return NULL;
}
}
char * strAbout = "streamRipper Copyright(C) Kannan Krishnamoorthy\n"
"DSP plug-in to record audio for offline Listening\n"
"Contact Info : \n"
" Kannan.K\n"
" Chennai\n"
" softkannan@gmail.com\n"
" kannan_softdev@yahoo.com\n";
/////////////////////////////////////////////////////////////////////////////////
/// @b config
///
/// @fn void config(struct winampDSPModule *this_mod)
///
/// @brief called when used clicked the plugin config button, here just about window
///
/// @param struct winampDSPModule *this_mod
///
/// @return Nil
///
/// @author Kannan K
/////////////////////////////////////////////////////////////////////////////////
void config(struct winampDSPModule *this_mod)
{
//data.m_hwnd = CreateDialog(this_mod->hDllInstance,MAKEINTRESOURCE(IDD_CONFIG),this_mod->hwndParent,(DLGPROC)ConfigProc);
MessageBox(this_mod->hwndParent,strAbout,
"Configuration/About",MB_OK);
}
/////////////////////////////////////////////////////////////////////////////////
/// @b init
///
/// @fn int init(struct winampDSPModule *this_mod)
///
/// @brief called when winamp loads the plugin
///
/// @param struct winampDSPModule *this_mod
///
/// @return int
///
/// @author Kannan K
/////////////////////////////////////////////////////////////////////////////////
int init(struct winampDSPModule *this_mod)
{
// initialize default values
data.m_start = 0;
data.pWav = NULL;
CRegKey key;
DWORD iTemp = MAX_PATH;
RECT r;
//read settings
if(key.Open(HKEY_LOCAL_MACHINE,"SOFTWARE\\streamRipper") == ERROR_SUCCESS)
{
key.QueryValue(data.strPath,"DefaultPath",&iTemp);
}
else
{
_tcscpy(data.strPath,"C:\\");
}
//initialize the info struct
data.m_iPrgbar = 0;
data.m_bAuto = FALSE;
//create main window
data.m_hwnd = CreateDialog(this_mod->hDllInstance,MAKEINTRESOURCE(IDD_CONFIG),this_mod->hwndParent,(DLGPROC)ConfigProc);
ShowWindow(data.m_hwnd,SW_SHOW);
GetWindowRect(this_mod->hwndParent,&r);
SetWindowPos(data.m_hwnd,0,r.right,r.top,0,0,SWP_NOSIZE | SWP_NOREPOSITION);
prvProc = NULL;
return 0;
}
/////////////////////////////////////////////////////////////////////////////////
/// @b quit
///
/// @fn void quit(struct winampDSPModule *this_mod)
///
/// @brief called before winamp un-loads this plugin
///
/// @param struct winampDSPModule *this_mod
///
/// @return Nil
///
/// @author Kannan K
/////////////////////////////////////////////////////////////////////////////////
void quit(struct winampDSPModule *this_mod)
{
//do clean up work
DestroyWindow(data.m_hwnd);
if(prvProc)
{
SetWindowLong(this_mod->hwndParent,GWL_WNDPROC,(LONG)(prvProc));
}
if(data.pWav)
{
delete data.pWav;
}
}
/////////////////////////////////////////////////////////////////////////////////
/// @b modify_samples
///
/// @fn int modify_samples(struct winampDSPModule *this_mod,
/// short int *samples, int numsamples, int bps, int nch, int srate)
///
/// @brief called whenever the new samples are ready for play
///
/// @param struct winampDSPModule *this_mod, short int *samples,
/// int numsamples, int bps, int nch, int srate
///
/// @return int
///
/// @author Kannan K
/////////////////////////////////////////////////////////////////////////////////
int modify_samples(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate)
{
TCHAR strWave[MAX_PATH] = "streamRipper";
TCHAR strPrg[MAX_PATH] = " - -----------------------------------";
//process first set of samples
if(data.m_start == 1)
{
TCHAR strTitle[MAX_PATH];
BOOL bTitle = FALSE;
INT iTemp;
TCHAR *pTemp;
TCHAR strFilepath[MAX_PATH];
WIN32_FIND_DATA fd;
HANDLE hHandle;
TCHAR strFilename[MAX_PATH];
TCHAR strTemp[MAX_PATH];
SendMessage(this_mod->hwndParent,WM_GETTEXT,MAX_PATH,(LPARAM)strTitle);
SendDlgItemMessage(data.m_hwnd,IDC_DESTFOLDER,WM_GETTEXT,MAX_PATH,(LPARAM)strFilepath);
pTemp = _tcsrchr(strFilepath,'\\');
if(*(pTemp + 1) != 0)
{
iTemp = _tcslen(strFilepath);
strFilepath[iTemp] = '\\';
strFilepath[iTemp + 1] = '\0';
}
if(_tcslen(strTitle) > 1)
{
pTemp = _tcsstr(strTitle,"- Winamp");
if(pTemp)
{
*pTemp = '\0';
}
_tcscat(strTitle,".wav");
bTitle = TRUE;
}
iTemp = 0;
while(1)
{
if(bTitle && data.m_bAuto == FALSE)
{
if(iTemp == 0)
{
wsprintf(strFilename,"%s%s",strFilepath,strTitle);
_tcscpy(strTemp,strTitle);
}
else
{
wsprintf(strTitle,"%.02d-%s",iTemp,strTemp);
//_tcscpy(strTitle,strFilename);
wsprintf(strFilename,"%s%s",strFilepath,strTitle);
}
}
else
{
wsprintf(strFilename,"%s%.02d-Track.wav",strFilepath,iTemp);
wsprintf(strTitle,"%.02d-Track.wav",iTemp);
}
hHandle = FindFirstFile(strFilename,&fd);
if(hHandle == INVALID_HANDLE_VALUE)
{
break;
}
FindClose(hHandle);
iTemp++;
}
SendDlgItemMessage(data.m_hwnd,IDC_FILENAME,WM_SETTEXT,0,(LPARAM)strTitle);
if(data.pWav)
{
TCHAR strFilename[MAX_PATH];
wsprintf(strFilename,"%s%s",strFilepath,strTitle);
data.pWav->buildFormat(nch,srate,bps);
data.pWav->setFilename(strFilename);
data.pWav->addSamples(samples,numsamples);
wsprintf(strWave,"nCh : %d | Freq : %d | nBits : %d | Recording...",nch,srate,bps);
SendDlgItemMessage(data.m_hwnd,IDC_WAVEINFO,WM_SETTEXT,0,(LPARAM)strWave);
}
data.m_iPrgbar = 0;
data.m_start = 2;
}
//process next sequence of data samples
else if(data.m_start == 2)
{
if(data.m_iPrgbar > 37)
data.m_iPrgbar = 3;
strPrg[data.m_iPrgbar] = '*';
data.m_iPrgbar++;
_tcscat(strWave,strPrg);
SendMessage(data.m_hwnd,WM_SETTEXT,0,(LPARAM)strWave);
data.pWav->addSamples(samples,numsamples);
}
return numsamples;
}
/////////////////////////////////////////////////////////////////////////////////
/// @b ConfigProc
///
/// @fn INT_PTR CALLBACK ConfigProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lpParam)
///
/// @brief main window procedure
///
/// @param HWND hwnd,UINT msg,WPARAM wparam,LPARAM lpParam
///
/// @return INT_PTR
///
/// @author Kannan K
/////////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK ConfigProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lpParam)
{
switch(msg)
{
case WM_INITDIALOG:
//init contorls default values
SendDlgItemMessage(hwnd,IDC_DESTFOLDER,WM_SETTEXT,0,(LPARAM)data.strPath);
SendDlgItemMessage(hwnd,IDC_WAVEINFO,WM_SETTEXT,0,(LPARAM)"Welcome to Kannan's ripper");
SendDlgItemMessage(hwnd,IDC_AUTO,BM_SETCHECK,data.m_bAuto,0);
break;
case WM_COMMAND:
//do all button and other contorls events
switch(LOWORD(wparam))
{
case IDC_AUTO:
data.m_bAuto = SendDlgItemMessage(hwnd,IDC_AUTO,BM_GETCHECK,0,0);
if(data.m_bAuto)
{
prvProc = (WNDPROC) SetWindowLong(GetParent(hwnd),GWL_WNDPROC,(LONG)(winampMainproc));
}
else
{
SetWindowLong(GetParent(hwnd),GWL_WNDPROC,(LONG)(prvProc));
}
break;
case IDC_DESTFOLDER:
switch(HIWORD(wparam))
{
case EN_CHANGE:
SendDlgItemMessage(hwnd,IDC_DESTFOLDER,WM_GETTEXT,sizeof(data.strPath),(LPARAM)data.strPath);
{
CRegKey key;
if(key.Create(HKEY_LOCAL_MACHINE,"SOFTWARE\\streamRipper") == ERROR_SUCCESS)
{
key.SetValue(data.strPath,"DefaultPath");
}
}
break;
}
break;
case IDC_RECORD:
//handle record button event
EnableWindow(GetDlgItem(hwnd,IDC_RECORD),FALSE);
EnableWindow(GetDlgItem(hwnd,IDC_STOP),TRUE);
if(data.pWav)
{
delete data.pWav;
data.pWav = NULL;
}
data.pWav = new CWave();
data.m_start = 1;
break;
case IDC_STOP:
//handle stop button event
data.m_start = 0;
EnableWindow(GetDlgItem(hwnd,IDC_STOP),FALSE);
EnableWindow(GetDlgItem(hwnd,IDC_RECORD),TRUE);
SendDlgItemMessage(hwnd,IDC_WAVEINFO,WM_SETTEXT,0,(LPARAM)"Recording Stopped");
SendMessage(hwnd,WM_SETTEXT,0,(LPARAM)"streamRipper");
if(data.pWav)
{
delete data.pWav;
data.pWav = NULL;
}
break;
}
break;
case WM_RBUTTONDOWN:
//handle right click event
MessageBox(hwnd,strAbout,
"Configuration/About",MB_OK);
break;
case WM_DESTROY:
case WM_CLOSE:
EndDialog(hwnd,0);
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////////
/// @b winampMainproc
///
/// @fn LRESULT CALLBACK winampMainproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
///
/// @brief used for auto mode
///
/// @param HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam
///
/// @return LRESULT
///
/// @author Kannan K
/////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK winampMainproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if(data.m_bAuto && data.m_start == 2)
{
switch(msg)
{
// handle winamp-main window firing an event at the end of each file play
case WM_USER + 2:
SendMessage(data.m_hwnd,WM_COMMAND,IDC_STOP,0);
SendMessage(data.m_hwnd,WM_COMMAND,IDC_RECORD,0);
break;
// handle winamp-main window firing an event at the end of each file play
case WM_COMMAND:
switch(wparam)
{
case 40048:
SendMessage(data.m_hwnd,WM_COMMAND,IDC_STOP,0);
SendMessage(data.m_hwnd,WM_COMMAND,IDC_RECORD,0);
break;
}
break;
}
}
return prvProc(hwnd, msg, wparam, lparam);
}