/** * * 女医ハック DirectShowフィルタ * Copyright (C) 2008 id:yuaaaa * * $Id$ */ #pragma warning(disable: 4793 4819 4996) #include "main.h" using namespace System::Drawing; #pragma unmanaged const AMOVIESETUP_MEDIATYPE sudPinTypes = { &MEDIATYPE_Video // clsMajorType , &MEDIASUBTYPE_RGB24 }; // clsMinorType const AMOVIESETUP_PIN psudPins[] = { { L"Input" // strName , FALSE // bRendered , FALSE // bOutput , FALSE // bZero , FALSE // bMany , &CLSID_NULL // clsConnectsToFilter , L"Output" // strConnectsToPin , 1 // nTypes , &sudPinTypes // lpTypes } , { L"Output" // strName , FALSE // bRendered , TRUE // bOutput , FALSE // bZero , FALSE // bMany , &CLSID_NULL // clsConnectsToFilter , L"Input" // strConnectsToPin , 1 // nTypes , &sudPinTypes // lpTypes } }; const AMOVIESETUP_FILTER sudDirectJoyHack = { &CLSID_DirectJoyHack // class id #ifdef _DEBUG , L"DirectJoyHack (debug)" // strName #else , L"DirectJoyHack" // strName #endif , MERIT_DO_NOT_USE // dwMerit , 2 // nPins , psudPins // lpPin }; // Needed for the CreateInstance mechanism CFactoryTemplate g_Templates[]= { { L"DirectJoyHack" , &CLSID_DirectJoyHack , CDirectJoyHack::CreateInstance , NULL , &sudDirectJoyHack } , { L"DirectJoyHack Property Page" , &CLSID_DirectJoyHackProp , CDirectJoyHackProperties::CreateInstance } }; int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]); int CDirectJoyHack::m_nInstanceCount = 0; #pragma managed CDirectJoyHack::CDirectJoyHack(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) : CTransInPlaceFilter (tszName, punk, CLSID_DirectJoyHack, phr) , CPersistStream(punk, phr) , pMediaPosition ( NULL ) , m_Immediate ( false ) , m_utf8 ( false ) , m_HideSub ( false ) , m_DebugOut ( false ) , m_Delay ( 0 ) , m_Locking ( false ) { m_nThisInstance = ++m_nInstanceCount; wcsncpy( m_filename, _T(""), MAX_PATH ); joyhack = gcnew JHDrawLib::DrawJoyHack(1, 1); this->errorstr = ""; mywrap = gcnew delegateWrapper( this ); this->fswatch = gcnew System::IO::FileSystemWatcher(); this->fswatch->NotifyFilter = System::IO::NotifyFilters::LastWrite | System::IO::NotifyFilters::Size; this->fswatch->IncludeSubdirectories = false; this->fswatch->Changed += gcnew System::IO::FileSystemEventHandler( (delegateWrapper ^)mywrap, &delegateWrapper::Do ); //GdiplusStartupInput gdiplusStartupInput; //GdiplusStartup(&this->gdiplusToken, &gdiplusStartupInput, NULL); return; } CDirectJoyHack::~CDirectJoyHack() { if ( this->pMediaPosition ) { this->pMediaPosition->Release(); } //GdiplusShutdown(this->gdiplusToken); } CUnknown * WINAPI CDirectJoyHack::CreateInstance(LPUNKNOWN punk, HRESULT *phr) { CDirectJoyHack *pNewObject = new CDirectJoyHack(NAME("DirectJoyHack Filter"), punk, phr); if (pNewObject == NULL) { if (phr) *phr = E_OUTOFMEMORY; } return pNewObject; } STDMETHODIMP CDirectJoyHack::NonDelegatingQueryInterface(REFIID riid, void **ppv) { CheckPointer(ppv,E_POINTER); if (riid == IID_IDirectJoyHack) { return GetInterface((IDirectJoyHack *) this, ppv); } else if (riid == IID_ISpecifyPropertyPages) { return GetInterface((ISpecifyPropertyPages *) this, ppv); } else if (riid == IID_IPersistStream) { return GetInterface((IPersistStream *) this, ppv); } else { // Pass the buck return CTransformFilter::NonDelegatingQueryInterface(riid, ppv); } } STDMETHODIMP CDirectJoyHack::GetClassID(CLSID *pClsid) { CheckPointer(pClsid,E_POINTER); *pClsid = CLSID_DirectJoyHack; return NOERROR; } int GetPosition( int x, int y, int stride ) { return (y*stride)+(x*3); } #pragma managed HRESULT CDirectJoyHack::Transform(IMediaSample *pSample) { if ( this->m_HideSub ) { return S_OK; } HRESULT hr; if ( this->pMediaPosition == NULL ) { hr = CBaseFilter::m_pGraph->QueryInterface ( IID_IMediaPosition, (void**)&this->pMediaPosition ); if ( FAILED ( hr) ) { return hr; } } CheckPointer( pSample, E_POINTER ); BYTE *pframe; pSample->GetPointer(&pframe); CheckPointer( pframe, E_POINTER ); Bitmap^ bmp = gcnew Bitmap (width, height, stride, Imaging::PixelFormat::Format24bppRgb, (System::IntPtr)pframe); bmp->RotateFlip(RotateFlipType::RotateNoneFlipY); Graphics ^g/*_v*/ = Graphics::FromImage(bmp); //Bitmap ^bmp0 = gcnew Bitmap(width, height, Imaging::PixelFormat::Format32bppArgb); //Graphics ^g = Graphics::FromImage(bmp0); if ( /* this->m_DebugOut && */ ! System::String::IsNullOrEmpty(this->errorstr) ) { g->DrawString( gcnew System::String("[Error] ") + this->errorstr, gcnew Font(FontFamily::GenericMonospace, 16 ), Brushes::Red, System::Drawing::RectangleF(0,0,this->width,this->height)); } else { //REFTIME reft; //hr = this->pMediaPosition->get_CurrentPosition( &reft ); // 困ったときの DirectVobSubFilter.cpp (line 155) REFERENCE_TIME rtStart, rtStop; pSample->GetTime(&rtStart, &rtStop); if ( FAILED(hr) ) { return hr; } REFERENCE_TIME curstar = m_pInput->CurrentStartTime(); while(m_Locking) { Sleep(1); } //Hmm... //joyhack->drawENT( g, /*(__int64)(reft*1000)*/ (curstar + rtStart)/10000 ); JoyHack::Timecode ^fixedtime = joyhack->getFixedTimecode(JoyHack::Timecode::FromMillisecond((curstar + rtStart)/10000)); System::Collections::Generic::List ^phrlist; System::Int32 nowphrpos = joyhack->getDrawPhraseList(fixedtime, phrlist ); if ( phrlist != nullptr ) { for each ( JHDrawLib::DrawPhraseCond phrc in phrlist ) { if ( phrc.phr == nullptr ) { continue; } joyhack->drawPhraseUsingCache( g, phrc, fixedtime); } } } bmp->RotateFlip(RotateFlipType::RotateNoneFlipY); /*g_v->DrawImage( bmp0, Point(0,0) );*/ Imaging::BitmapData^ bdata; bdata = bmp->LockBits( System::Drawing::Rectangle(0,0,width,height),Imaging::ImageLockMode::ReadOnly,Imaging::PixelFormat::Format24bppRgb); memcpy(pframe, bdata->Scan0.ToPointer(), min(pSample->GetActualDataLength() , bdata->Stride*bdata->Height) ); pSample->SetActualDataLength( min(pSample->GetActualDataLength() , bdata->Stride*bdata->Height) ); return S_OK; } /* HRESULT CDirectJoyHack::Transform(IMediaSample *pSample) { CheckPointer( pSample, E_POINTER ); BYTE *pframe; pSample->GetPointer(&pframe); CheckPointer( pframe, E_POINTER ); Bitmap^ bmp = gcnew Bitmap (width, height, stride, Imaging::PixelFormat::Format24bppRgb, (System::IntPtr)pframe); Bitmap ^bmp0 = gcnew Bitmap(width, height, Imaging::PixelFormat::Format32bppArgb); Graphics ^g = Graphics::FromImage(bmp0); Font ^fnt = gcnew Font("MS UI Gothic", 80); Drawing2D::GraphicsPath ^path = gcnew Drawing2D::GraphicsPath(); path->AddString(gcnew System::String("STRING STRING"), fnt->FontFamily, (int)fnt->Style, fnt->Size, Point(30, 60), gcnew StringFormat() ); g->DrawPath( gcnew Pen(Color::Blue, 5), path); g->FillPath(Brushes::Pink,path); Graphics ^g2 = Graphics::FromImage(bmp0); CRefTime cref; HRESULT hr = this->StreamTime( cref ); if ( FAILED(hr) ) { return hr; } g2->Clip = gcnew Region(System::Drawing::Rectangle(0, 0, (int)(width * ((( cref.Millisecs() ) % 5000) / 5000.0)), height)); g2->DrawPath( gcnew Pen(Color::White, 5), path); g2->FillPath(Brushes::Blue,path); bmp0->RotateFlip(RotateFlipType::RotateNoneFlipY); Graphics^ g3 = Graphics::FromImage(bmp); g3->DrawImage(bmp0, Point(0,0) ); Imaging::BitmapData^ bdata; bdata = bmp->LockBits( System::Drawing::Rectangle(0,0,width,height),Imaging::ImageLockMode::ReadWrite,Imaging::PixelFormat::Format24bppRgb); memcpy(pframe, bdata->Scan0.ToPointer(), min(pSample->GetActualDataLength() , bdata->Stride*bdata->Height) ); pSample->SetActualDataLength( min(pSample->GetActualDataLength() , bdata->Stride*bdata->Height) ); return S_OK; } */ HRESULT CDirectJoyHack::CheckInputType(const CMediaType *pmt) { CheckPointer(pmt,E_POINTER); VIDEOINFOHEADER *pvih = (VIDEOINFOHEADER *) pmt->pbFormat; CheckPointer(pvih, VFW_E_TYPE_NOT_ACCEPTED); // Reject non-Audio types. // if (pmt->majortype != MEDIATYPE_Video) { return VFW_E_TYPE_NOT_ACCEPTED; } if (pmt->subtype != MEDIASUBTYPE_RGB24) { return VFW_E_TYPE_NOT_ACCEPTED; } // Reject invalid format blocks // if (pmt->formattype != FORMAT_VideoInfo) return VFW_E_TYPE_NOT_ACCEPTED; if (pvih->bmiHeader.biBitCount != 24) return VFW_E_TYPE_NOT_ACCEPTED; if (pvih->bmiHeader.biCompression != 0){ return VFW_E_TYPE_NOT_ACCEPTED; } return NOERROR; } /* HRESULT CDirectJoyHack::GetMediaType(int iPosition, CMediaType *pMediaType) { CheckPointer( pMediaType, E_POINTER ); if ( iPosition < 0 ) { return E_INVALIDARG; } if ( iPosition > 0 ) { return VFW_S_NO_MORE_ITEMS; } pMediaType->AllocFormatBuffer( sizeof( VIDEOINFOHEADER ) ); VIDEOINFOHEADER *pvih = (VIDEOINFOHEADER *) pMediaType->pbFormat; pMediaType->majortype = MEDIATYPE_Video; pMediaType->subtype = MEDIASUBTYPE_RGB24; pMediaType->formattype = FORMAT_VideoInfo; pvih->dwBitRate return S_OK; } */ #pragma managed HRESULT CDirectJoyHack::SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt) { //TODO if ( direction != PINDIR_INPUT ) { return NO_ERROR; } CheckPointer(pmt,E_POINTER); if (pmt->formattype != FORMAT_VideoInfo) return VFW_E_TYPE_NOT_ACCEPTED; VIDEOINFOHEADER *pvih = (VIDEOINFOHEADER *) pmt->pbFormat; CheckPointer(pvih, VFW_E_TYPE_NOT_ACCEPTED); width = pvih->bmiHeader.biWidth; height = pvih->bmiHeader.biHeight; stride = width * 3; //this->put_FileName(_T("G:\\CD-rips\\[田村ゆかり]\\DVDs\\SMW_A_08_1.VOB.txt")); joyhack->width = width; joyhack->height = height; this->reload_File(); return NO_ERROR; } HRESULT CDirectJoyHack::get_FileName( WCHAR* fn ){ wcsncpy( fn, m_filename, MAX_PATH ); return S_OK; } HRESULT CDirectJoyHack::put_FileName( WCHAR* fn ){ wcsncpy( m_filename, fn, MAX_PATH ); this->fswatch->EnableRaisingEvents = false; HRESULT hr = this->reload_File(); try { System::IO::FileInfo ^finfo = gcnew System::IO::FileInfo( gcnew System::String(m_filename) ); this->fswatch->Path = finfo->DirectoryName; this->fswatch->Filter = finfo->Name; this->fswatch->EnableRaisingEvents = this->m_Immediate; } catch (System::Exception ^e ) { this->fswatch->EnableRaisingEvents = false; return E_FAIL; } return hr; } HRESULT CDirectJoyHack::reload_File( ){ this->errorstr = ""; if ( wcslen( this->m_filename ) == 0 ) { //this->errorstr = "Filename is Empty"; return E_FAIL; } m_Locking = true; try{ if ( this->m_utf8 ) { joyhack->load_data( gcnew System::String( this->m_filename ), System::Text::Encoding::UTF8 ); } else { joyhack->load_data( gcnew System::String( this->m_filename ) ); } } catch ( System::Exception ^e ) { this->errorstr = e->Message; return E_FAIL; } __finally { m_Locking = false; } CPersistStream::SetDirty(TRUE); return S_OK; } HRESULT CDirectJoyHack::get_ChangeImmediate( bool* fImmediate ){ *fImmediate = m_Immediate; return S_OK; } HRESULT CDirectJoyHack::put_ChangeImmediate( bool fImmediate ){ m_Immediate = fImmediate; this->fswatch->EnableRaisingEvents = this->m_Immediate; return S_OK; } HRESULT CDirectJoyHack::get_UseUTF8( bool* futf8 ){ *futf8 = m_utf8; return S_OK; } HRESULT CDirectJoyHack::put_UseUTF8( bool futf8 ){ m_utf8 = futf8; return S_OK; } HRESULT CDirectJoyHack::get_HideSubtitles( bool* fHideSubtitles ){ *fHideSubtitles = m_HideSub; return S_OK; } HRESULT CDirectJoyHack::put_HideSubtitles( bool fHideSubtitles ){ m_HideSub = fHideSubtitles; CPersistStream::SetDirty(TRUE); return S_OK; } HRESULT CDirectJoyHack::get_Delay( __int32* fDelay ){ *fDelay = m_Delay; return S_OK; } HRESULT CDirectJoyHack::put_Delay( __int32 fDelay ){ m_Delay = fDelay; joyhack->timeUserFix = m_Delay; CPersistStream::SetDirty(TRUE); return S_OK; } HRESULT CDirectJoyHack::get_DebugOutput( bool* fDebugOut ){ *fDebugOut = m_DebugOut; return S_OK; } HRESULT CDirectJoyHack::put_DebugOutput( bool fDebugOut ){ m_DebugOut = fDebugOut; joyhack->debug = fDebugOut; CPersistStream::SetDirty(TRUE); return S_OK; } //temp HRESULT CDirectJoyHack::get_DisableCache( bool* fdcache ){ *fdcache = joyhack->disable_cache; return S_OK; } HRESULT CDirectJoyHack::put_DisableCache( bool fdcache ){ joyhack->disable_cache = fdcache; CPersistStream::SetDirty(TRUE); return S_OK; } void CDirectJoyHack::file_Change(System::Object ^sender, System::IO::FileSystemEventArgs ^e) { this->reload_File(); } //GetPages STDMETHODIMP CDirectJoyHack::GetPages(CAUUID * pPages) { CheckPointer(pPages,E_POINTER); pPages->cElems = 1; pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID)); if (pPages->pElems == NULL) { return E_OUTOFMEMORY; } *(pPages->pElems) = CLSID_DirectJoyHackProp; return NOERROR; } #pragma unmanaged //DLL STDAPI DllRegisterServer() { return AMovieDllRegisterServer2( TRUE ); } STDAPI DllUnregisterServer() { return AMovieDllRegisterServer2( FALSE ); } // // DllEntryPoint // extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved); }