/** * * SoundTouch for 女医ハックHack * 作成者: id:yuaaaa * ほんとはGPLっていわなきゃいけない * * $Id$ */ #include "main.h" LPCTSTR CSoundTouch_AutoJoy::Str_WndProp_OrgProc = _T("SoundTouch_JoyHack_OrgProc"); CSoundTouch_AutoJoy::CSoundTouch_AutoJoy(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) : joyhackWindow(NULL), hookWindow(NULL), speed(10), failed_subclass(false), CSoundTouch(tszName,punk, phr) { } CUnknown * WINAPI CSoundTouch_AutoJoy::CreateInstance(LPUNKNOWN punk, HRESULT *phr) { ASSERT(phr); //MessageBox(NULL,_T("TEST"),NULL,0); CSoundTouch_AutoJoy *pNewObject = new CSoundTouch_AutoJoy(NAME("SoundTouch Filter (auto-JoyHack version)"), punk, phr); if (pNewObject == NULL) { if (phr) *phr = E_OUTOFMEMORY; } return pNewObject; } //from DirectVobSubFilter.cpp HRESULT CSoundTouch_AutoJoy::CheckConnect(PIN_DIRECTION dir, IPin* pPin) { PIN_INFO pi; if(FAILED(pPin->QueryPinInfo(&pi))) return E_FAIL; ISoundTouch *pst = NULL; pi.pFilter->QueryInterface(IID_ISoundTouch, (LPVOID *)&pst); if ( pst != NULL ) { pst->Release(); return E_FAIL; } return __super::CheckConnect(dir, pPin); } BOOL CALLBACK CSoundTouch_AutoJoy::EnumChildWindowProc(HWND hwnd , LPARAM lp) { TCHAR buf[256]; GetClassName( hwnd, buf, 256 ); //XP: ATL:07565367 //Vista: ATL:66717E08 if ( buf[0] == _T('A') && buf[1] == _T('T') && buf[2] == _T('L') && buf[3] == _T(':') ) { ((CSoundTouch_AutoJoy*)lp)->hookWindow = hwnd; return FALSE; } return TRUE; } BOOL CALLBACK CSoundTouch_AutoJoy::EnumWindowProc(HWND hwnd , LPARAM lp) { DWORD pid; GetWindowThreadProcessId( hwnd, &pid ); if ( pid != GetCurrentProcessId() ) { return TRUE; } EnumChildWindows( hwnd, &CSoundTouch_AutoJoy::EnumChildWindowProc, lp ); if ( ((CSoundTouch_AutoJoy*)lp)->hookWindow != NULL ) { ((CSoundTouch_AutoJoy*)lp)->joyhackWindow = hwnd; return FALSE; } return TRUE; } HRESULT CSoundTouch_AutoJoy::JoinFilterGraph(IFilterGraph* pGraph, LPCWSTR pName) { if ( FAILED ( this->CheckAutoLoad() ) ) { return E_FAIL; } if(pGraph) { IEnumFilters *pEnum; pGraph->EnumFilters(&pEnum); IBaseFilter *pBF = NULL; while( pEnum->Next(1, &pBF, NULL) == S_OK) { ISoundTouch *pst = NULL; pBF->QueryInterface(IID_ISoundTouch, (LPVOID *)&pst); if( pst != NULL ) { pst->Release(); if ( pBF != (IBaseFilter*)this ) { pEnum->Release(); return E_FAIL; } } } pEnum->Release(); } else { //フィルタ グラフから離れた } return __super::JoinFilterGraph(pGraph, pName); } HRESULT CSoundTouch_AutoJoy::CheckAutoLoad (void) { TCHAR szPath[MAX_PATH+1]; DWORD ret = GetModuleFileName(NULL, szPath, sizeof(szPath)); LPTSTR exefile = PathFindFileName(szPath); if ( _tcscmp( exefile, _T("HackENT.exe" ) ) == 0 ) { return S_OK; } return VFW_E_TYPE_NOT_ACCEPTED; } HRESULT CSoundTouch_AutoJoy::CheckInputType(const CMediaType* mtIn) { HRESULT hr = __super::CheckInputType(mtIn); if(FAILED(hr) || m_pInput->IsConnected()) return hr; return this->CheckAutoLoad(); } //static LRESULT CALLBACK CSoundTouch_AutoJoy::SubProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { CSoundTouch_AutoJoy *filter = (CSoundTouch_AutoJoy *)GetProp( hWnd, CSoundTouch_AutoJoy::Str_WndProp_OrgProc ); if ( filter == NULL ) { return DefWindowProc(hWnd, uMsg, wParam, lParam); } int nowkey; filter->get_TouchKey( &nowkey ); switch ( uMsg ) { case WM_KEYDOWN: break; case WM_KEYUP: if ( wParam == 'Z' ) { if (GetKeyState(VK_SHIFT) < 0) { if (GetKeyState(VK_CONTROL) < 0) { filter->SetupSpeed( filter->speed +5); } else { filter->SetupSpeed( filter->speed +1); } } else { filter->put_TouchKey( nowkey +1 ); } filter->JoyDrawStatus(); } else if ( wParam == 'X' ) { if (GetKeyState(VK_SHIFT) < 0) { filter->SetupSpeed( 10 ); } else { filter->put_TouchKey( 0 ); } filter->JoyDrawStatus(); } else if ( wParam == 'C' ) { if (GetKeyState(VK_SHIFT) < 0) { if (GetKeyState(VK_CONTROL) < 0) { filter->SetupSpeed( filter->speed -5); } else { filter->SetupSpeed( filter->speed -1); } } else { filter->put_TouchKey( nowkey -1 ); } filter->JoyDrawStatus(); } else if ( wParam == 'W' ) { filter->JoyDrawStatus(); } else if ( wParam == 'Q' ) { if ( filter->m_pGraph == NULL ) { return FALSE; } IMediaControl *pMC; filter->m_pGraph->QueryInterface(&pMC); if ( pMC ) { OAFilterState st; if ( SUCCEEDED( pMC->GetState( 100, &st ) ) ) { if ( st == State_Running ) { pMC->Pause(); } else if ( st == State_Paused ) { pMC->Run(); } pMC->Release(); filter->JoyDrawStatus(); } } } break; } if ( filter->hookWndOrgProc == &CSoundTouch_AutoJoy::SubProc) { //TODO: FIXME: BUG... filter->failed_subclass = true; return DefWindowProc(hWnd, uMsg, wParam, lParam); } return CallWindowProc( filter->hookWndOrgProc, hWnd, uMsg, wParam, lParam); } HRESULT CSoundTouch_AutoJoy::SetupSpeed ( int newspd ) { if ( newspd < 5 || 20 < newspd ) { return E_INVALIDARG; } this->speed = newspd; this->put_Speed ( this->speed * 0.1f ); return this->Setup_GraphRate(); } void CSoundTouch_AutoJoy::JoyDrawStatus ( void ) { HWND dwin = GetWindow ( GetWindow( this->joyhackWindow ,GW_ENABLEDPOPUP ), GW_CHILD ); if ( dwin != NULL ) { TCHAR buf[256]; StringCchPrintf( buf, 256, _T("キー: %+d 速度: %3d%%"), this->m_Key, this->speed*10 ); IMediaControl *pMC; if ( this->m_pGraph ) { this->m_pGraph->QueryInterface(&pMC); if ( pMC ) { OAFilterState st; if ( SUCCEEDED( pMC->GetState( 100, &st ) ) ) { if ( st == State_Paused ) { StringCchCat( buf, 256, _T(" ") ); } } pMC->Release(); } } TCHAR spacebuf[256]; StringCchPrintf( spacebuf, 256, _T("%50s"), _T("") ); HDC hdc = GetDC(dwin); size_t slen; StringCchLength( spacebuf, 256, &slen ); TextOut( hdc, 10, 10, spacebuf, slen ); StringCchLength( buf, 256, &slen ); TextOut( hdc, 10, 10, buf, slen ); if ( this->failed_subclass ) { TCHAR fsbuf[256] = _T("サブクラス化の解除に失敗しています。アプリケーションを再起動してください"); StringCchLength( fsbuf, 256, &slen ); TextOut( hdc, 10, 30, fsbuf, slen ); } ReleaseDC(dwin, hdc ); } } void CSoundTouch_AutoJoy::SetSubclass() { EnumWindows( &CSoundTouch_AutoJoy::EnumWindowProc, (LPARAM)this ); this->hookWndOrgProc = (WNDPROC)GetWindowLong(this->hookWindow , GWL_WNDPROC); if (this->hookWndOrgProc != &CSoundTouch_AutoJoy::SubProc) { SetProp( this->hookWindow, CSoundTouch_AutoJoy::Str_WndProp_OrgProc, (HANDLE)this ); SetWindowLong( this->hookWindow, GWL_WNDPROC, (LONG)&CSoundTouch_AutoJoy::SubProc ); } else { ASSERT(false); } } HRESULT CSoundTouch_AutoJoy::Run(REFERENCE_TIME tStart) { if ( this->hookWindow == NULL ) { OutputDebugString(_T("サブクラス化されようとしている in Run()\n")); this->SetSubclass(); } this->JoyDrawStatus(); return __super::Run(tStart); } HRESULT CSoundTouch_AutoJoy::Pause() { if ( this->hookWindow == NULL ) { OutputDebugString(_T("サブクラス化されようとしている in Pause()\n")); this->SetSubclass(); } return __super::Pause(); } HRESULT CSoundTouch_AutoJoy::Stop() { if ( this->hookWindow != NULL ) { RemoveProp( this->hookWindow, CSoundTouch_AutoJoy::Str_WndProp_OrgProc ); OutputDebugString(_T("サブクラス化が解除されようとしている in Stop()\n")); SetWindowLong( this->hookWindow, GWL_WNDPROC, (LONG)(this->hookWndOrgProc) ); this->hookWindow = NULL; this->joyhackWindow = NULL; this->hookWndOrgProc = NULL; } return __super::Stop(); }