#include "stdafx.h" #include "mswebdvd.h" #include "msdvd.h" #include "ddrawobj.h" // // CDDrawDVD constructor // CDDrawDVD::CDDrawDVD(CMSWebDVD *pDVD) { m_pDVD = pDVD; // Default colors to be used for filling m_VideoKeyColor = RGB(255, 0, 255) ; m_pOverlayCallback = new CComObject ; CComVariant vData; vData.vt = VT_VOID; vData.byref = this; if(m_pOverlayCallback){ m_pOverlayCallback->SetDDrawDVD(vData); } } // // CDDrawDVD destructor // CDDrawDVD::~CDDrawDVD(void) { } /*************************************************************************/ /* Function: SetupDDraw */ /* Description: Creates DDrawObject and Surface */ /*************************************************************************/ HRESULT CDDrawDVD::SetupDDraw(const AMDDRAWGUID* lpDDGUID, HWND hwnd){ // DO NOT CALL TWICE !!! // WILL CRASH OV MIXER DJ HRESULT hr = E_UNEXPECTED; if(!::IsWindow(hwnd)){ return(hr); }/* end of if statement */ m_pDDObject.Release(); hr = ::DirectDrawCreate(lpDDGUID->lpGUID, &m_pDDObject, NULL); if(FAILED(hr)){ return(hr); }/* end of if statement */ hr = m_pDDObject->SetCooperativeLevel(hwnd, DDSCL_NORMAL); if(FAILED(hr)){ m_pDDObject.Release(); return(hr); }/* end of if statement */ DDSURFACEDESC ddsd; ::ZeroMemory(&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; m_pPrimary.Release(); hr = m_pDDObject->CreateSurface(&ddsd, &m_pPrimary, NULL); if(FAILED(hr)){ m_pDDObject.Release(); return(hr); }/* end of if statement */ CComPtr pClipper; hr = m_pDDObject->CreateClipper(0, &pClipper, NULL); if(FAILED(hr)){ m_pPrimary.Release(); m_pDDObject.Release(); return(hr); }/* end of if statement */ hr = pClipper->SetHWnd(0, hwnd); if(FAILED(hr)){ m_pPrimary.Release(); m_pDDObject.Release(); pClipper.Release(); return(hr); }/* end of if statement */ hr = m_pPrimary->SetClipper(pClipper); if (FAILED(hr)){ m_pPrimary.Release(); m_pDDObject.Release(); pClipper.Release(); return(hr); }/* end of if statement */ /* * We release the clipper interface after attaching it to the surface * as we don't need to use it again and the surface holds a reference * to the clipper when its been attached. The clipper will therefore * be released when the surface is released. */ pClipper.Release(); return(hr); }/* end of function SetupDDraw */ /*************************************************************/ /* Name: /* Description: /*************************************************************/ HRESULT CDDrawDVD::SetColorKey(COLORREF colorKey) { m_VideoKeyColor = colorKey; // if 256 color mode, force to set back to magenta HWND hwnd = ::GetDesktopWindow(); HDC hdc = ::GetWindowDC(hwnd); if(NULL == hdc){ return(E_UNEXPECTED); }/* end of if statement */ HRESULT hr = S_OK; if ((::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == RC_PALETTE) { if (m_VideoKeyColor != MAGENTA_COLOR_KEY) { hr = m_pDVD->put_ColorKey(MAGENTA_COLOR_KEY); if (SUCCEEDED(hr)) m_VideoKeyColor = MAGENTA_COLOR_KEY; } } ::ReleaseDC(hwnd, hdc); return hr ; } /*************************************************************/ /* Name: /* Description: /*************************************************************/ COLORREF CDDrawDVD::GetColorKey() { // if 256 color mode, force to set back to magenta HWND hwnd = ::GetDesktopWindow(); HDC hdc = ::GetWindowDC(hwnd); if(NULL == hdc){ return(E_UNEXPECTED); }/* end of if statement */ if ((::GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) == RC_PALETTE) { if (m_VideoKeyColor != MAGENTA_COLOR_KEY) { if (SUCCEEDED(m_pDVD->put_ColorKey(MAGENTA_COLOR_KEY))) m_VideoKeyColor = MAGENTA_COLOR_KEY; } } ::ReleaseDC(hwnd, hdc); return m_VideoKeyColor; } /*************************************************************************/ /* Function: HasOverlay */ /* Description: Tells us if the video card support overlay. */ /*************************************************************************/ HRESULT CDDrawDVD::HasOverlay(){ HRESULT hr = S_OK; if(!m_pDDObject){ return(E_UNEXPECTED); }/* end of if statement */ DDCAPS caps; ::ZeroMemory(&caps, sizeof(DDCAPS)); caps.dwSize = sizeof(DDCAPS); hr = m_pDDObject->GetCaps(&caps, NULL); if(FAILED(hr)){ return(hr); }/* end of if statement */ if(caps.dwMaxVisibleOverlays > 0){ hr = S_OK; } else { hr = S_FALSE; }/* end of if statement */ return(hr); }/* end of function HasOverlay */ /*************************************************************************/ /* Function: HasAvailableOverlay */ /* Description: Tells us if the overlay is used. */ /*************************************************************************/ HRESULT CDDrawDVD::HasAvailableOverlay(){ HRESULT hr = S_OK; if(!m_pDDObject){ return(E_UNEXPECTED); }/* end of if statement */ DDCAPS caps; ::ZeroMemory(&caps, sizeof(DDCAPS)); caps.dwSize = sizeof(DDCAPS); hr = m_pDDObject->GetCaps(&caps, NULL); if(FAILED(hr)){ return(hr); }/* end of if statement */ if((caps.dwMaxVisibleOverlays > 0) && (caps.dwMaxVisibleOverlays > caps.dwCurrVisibleOverlays)){ hr = S_OK; } else { hr = S_FALSE; }/* end of if statement */ return(hr); }/* end of function HasAvailableOverlay */ /*************************************************************************/ /* Function: GetOverlayMaxStretch */ /* Description: Tells us the maximum stretch factors of overlay. */ /*************************************************************************/ HRESULT CDDrawDVD::GetOverlayMaxStretch(DWORD *pdwMaxStretch){ HRESULT hr = S_OK; if(!m_pDDObject){ return(E_UNEXPECTED); }/* end of if statement */ DDCAPS caps; ::ZeroMemory(&caps, sizeof(DDCAPS)); caps.dwSize = sizeof(DDCAPS); hr = m_pDDObject->GetCaps(&caps, NULL); if(FAILED(hr)){ return(hr); }/* end of if statement */ if (caps.dwCaps & DDCAPS_OVERLAYSTRETCH && caps.dwMaxOverlayStretch!=0) { *pdwMaxStretch = caps.dwMaxOverlayStretch/2; } else { #ifdef _DEBUG ::MessageBox(::GetFocus(), TEXT("Overlay can't stretch"), TEXT("Error"), MB_OK) ; #endif } return(hr); }/* end of function GetOverlayMaxStretch */ // convert a RGB color to a pysical color. // we do this by leting GDI SetPixel() do the color matching // then we lock the memory and see what it got mapped to. HRESULT CDDrawDVD::DDColorMatchOffscreen(COLORREF rgb, DWORD* dwColor) { HDC hdc; *dwColor = CLR_INVALID; DDSURFACEDESC ddsd; IDirectDrawSurface* pdds; LPDIRECTDRAW pdd = GetDDrawObj(); HRESULT hr = S_OK; ZeroMemory(&ddsd, sizeof(ddsd)) ; ddsd.dwSize = sizeof(ddsd) ; ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = 8; ddsd.dwHeight = 8; hr = pdd->CreateSurface(&ddsd, &pdds, NULL); if (hr != DD_OK) { return 0; } // use GDI SetPixel to color match for us if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { // set our value SetPixel(hdc, 0, 0, rgb); pdds->ReleaseDC(hdc); } // now lock the surface so we can read back the converted color ZeroMemory(&ddsd, sizeof(ddsd)) ; ddsd.dwSize = sizeof(ddsd) ; while ((hr = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) ; if (hr == DD_OK) { // get DWORD DWORD temp = *(DWORD *)ddsd.lpSurface; // mask it to bpp if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32) temp &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1; pdds->Unlock(NULL); *dwColor = temp; hr = S_OK; } pdds->Release(); return hr; } /*************************************************************/ /* Name: CreateDIBBrush /* Description: /*************************************************************/ HRESULT CDDrawDVD::CreateDIBBrush(COLORREF rgb, HBRUSH *phBrush) { #if 1 HDC hdc; DDSURFACEDESC ddsd; IDirectDrawSurface* pdds; LPDIRECTDRAW pdd = GetDDrawObj(); HRESULT hr = S_OK; ZeroMemory(&ddsd, sizeof(ddsd)) ; ddsd.dwSize = sizeof(ddsd) ; ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = 8; ddsd.dwHeight = 8; hr = pdd->CreateSurface(&ddsd, &pdds, NULL); if (hr != DD_OK) { return 0; } // use GDI SetPixel to color match for us if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK) { // set our value SetPixel(hdc, 0, 0, rgb); pdds->ReleaseDC(hdc); } // now lock the surface so we can read back the converted color ZeroMemory(&ddsd, sizeof(ddsd)) ; ddsd.dwSize = sizeof(ddsd) ; while ((hr = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) ; DWORD temp = CLR_INVALID; if (hr == DD_OK) { // get DWORD temp = *((DWORD *)ddsd.lpSurface); // mask it to bpp if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32) temp &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1; pdds->Unlock(NULL); hr = S_OK; } ::ZeroMemory(&ddsd, sizeof(ddsd)) ; ddsd.dwSize = sizeof(ddsd) ; hr = pdds->GetSurfaceDesc(&ddsd) ; if (! (SUCCEEDED(hr) && (ddsd.dwFlags & DDSD_WIDTH) && (ddsd.dwFlags & DDSD_HEIGHT)) ) { return hr; } if (hr == DD_OK && temp != CLR_INVALID) { DDBLTFX ddBltFx; ::ZeroMemory(&ddBltFx, sizeof(ddBltFx)) ; ddBltFx.dwSize = sizeof(DDBLTFX); ddBltFx.dwFillColor = temp; RECT rc; ::SetRect(&rc, 0, 0, ddsd.dwWidth, ddsd.dwHeight); hr = pdds->Blt(&rc, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddBltFx); if (FAILED(hr)) { return hr; } DWORD dwBitCount = ddsd.ddpfPixelFormat.dwRGBBitCount; DWORD dwWidth = WIDTHBYTES(ddsd.dwWidth*dwBitCount); DWORD dwSizeImage = ddsd.dwHeight*dwWidth; BYTE *packedDIB = new BYTE[sizeof(BITMAPINFOHEADER) + dwSizeImage + 1024]; BITMAPINFOHEADER *lpbmi = (BITMAPINFOHEADER*) packedDIB; ::ZeroMemory(lpbmi, sizeof(BITMAPINFOHEADER)); lpbmi->biSize = sizeof(BITMAPINFOHEADER); lpbmi->biBitCount = (WORD)dwBitCount; lpbmi->biWidth = ddsd.dwWidth; lpbmi->biHeight = ddsd.dwHeight; lpbmi->biPlanes = 1; LPDWORD pdw = (LPDWORD)DibColors(lpbmi); switch (dwBitCount) { case 8: { lpbmi->biCompression = BI_RGB; lpbmi->biClrUsed = 256; for (int i=0; i<(int)lpbmi->biClrUsed/16; i++) { *pdw++ = 0x00000000; // 0000 black *pdw++ = 0x00800000; // 0001 dark red *pdw++ = 0x00008000; // 0010 dark green *pdw++ = 0x00808000; // 0011 mustard *pdw++ = 0x00000080; // 0100 dark blue *pdw++ = 0x00800080; // 0101 purple *pdw++ = 0x00008080; // 0110 dark turquoise *pdw++ = 0x00C0C0C0; // 1000 gray *pdw++ = 0x00808080; // 0111 dark gray *pdw++ = 0x00FF0000; // 1001 red *pdw++ = 0x0000FF00; // 1010 green *pdw++ = 0x00FFFF00; // 1011 yellow *pdw++ = 0x000000FF; // 1100 blue *pdw++ = 0x00FF00FF; // 1101 pink (magenta) *pdw++ = 0x0000FFFF; // 1110 cyan *pdw++ = 0x00FFFFFF; // 1111 white } break; } case 16: lpbmi->biCompression = BI_BITFIELDS; lpbmi->biClrUsed = 3; pdw[0] = ddsd.ddpfPixelFormat.dwRBitMask ; pdw[1] = ddsd.ddpfPixelFormat.dwGBitMask ; pdw[2] = ddsd.ddpfPixelFormat.dwBBitMask ; break; case 24: case 32: lpbmi->biCompression = BI_RGB; lpbmi->biClrUsed = 0; break; } ZeroMemory(&ddsd, sizeof(ddsd)) ; ddsd.dwSize = sizeof(ddsd) ; while ((hr = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) ; if (hr != DD_OK) return hr; BYTE *lpTempSurf = (BYTE *)ddsd.lpSurface; for (DWORD i=0; iUnlock(NULL); *phBrush = ::CreateDIBPatternBrushPt((LPVOID) packedDIB, DIB_RGB_COLORS); } pdds->Release(); #else HRESULT hr = S_OK; typedef struct { BYTE rgb[3]; } RGB; typedef struct { BITMAPINFOHEADER bmiHeader; RGB pBits[8][8]; } PackedDIB; PackedDIB packedDIB; ::ZeroMemory(&packedDIB, sizeof(PackedDIB)); packedDIB.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); packedDIB.bmiHeader.biCompression = BI_RGB; packedDIB.bmiHeader.biBitCount = 24; packedDIB.bmiHeader.biHeight = 8; packedDIB.bmiHeader.biWidth = 8; packedDIB.bmiHeader.biPlanes = 1; for (int i=0; i<8; i++) { for (int j=0; j<8; j++) packedDIB.pBits[i][j] = *((RGB*)&rgb); } *phBrush = ::CreateDIBPatternBrushPt((LPVOID)&packedDIB, DIB_RGB_COLORS); #endif return hr; } /* COverlayCallback */ /*************************************************************/ /* Name: OnUpdateOverlay /* Description: /*************************************************************/ HRESULT STDMETHODCALLTYPE COverlayCallback::OnUpdateOverlay(BOOL bBefore, DWORD dwFlags, BOOL bOldVisible, const RECT *prcSrcOld, const RECT *prcDestOld, BOOL bNewVisible, const RECT *prcSrcNew, const RECT *prcDestNew) { if (bBefore) return S_OK; if(!prcSrcOld || !prcDestOld || !prcSrcNew || !prcDestNew){ return E_POINTER; } CMSWebDVD *pDVD = m_pDDrawDVD->GetDVD(); ATLASSERT(pDVD); if (m_dwWidth != (DWORD)RECTWIDTH(prcDestNew) || m_dwHeight != (DWORD)RECTHEIGHT(prcDestNew) || m_dwARWidth != (DWORD)RECTWIDTH(prcDestNew) || m_dwARHeight != (DWORD)RECTHEIGHT(prcDestNew)) { m_dwWidth = (DWORD)RECTWIDTH(prcDestNew); m_dwHeight = (DWORD)RECTHEIGHT(prcDestNew); m_dwARWidth = (DWORD)RECTWIDTH(prcDestNew); m_dwARHeight = (DWORD)RECTHEIGHT(prcDestNew); return pDVD->UpdateOverlay(); } /* end of if statement */ return S_OK; } /*************************************************************/ /* Name: OnUpdateColorKey /* Description: /*************************************************************/ HRESULT STDMETHODCALLTYPE COverlayCallback::OnUpdateColorKey(COLORKEY const *pKey, DWORD dwColor) { m_pDDrawDVD->SetColorKey(pKey->HighColorValue); return S_OK ; } /*************************************************************/ /* Name: OnUpdateSize /* Description: /*************************************************************/ HRESULT STDMETHODCALLTYPE COverlayCallback::OnUpdateSize(DWORD dwWidth, DWORD dwHeight, DWORD dwARWidth, DWORD dwARHeight) { CMSWebDVD *pDVD = m_pDDrawDVD->GetDVD(); ATLASSERT(pDVD); if (m_dwWidth != dwWidth || m_dwHeight != dwHeight || m_dwARWidth != dwARWidth || m_dwARHeight != dwARHeight) { m_dwWidth = dwWidth; m_dwHeight = dwHeight; m_dwARWidth = dwARWidth; m_dwARHeight = dwARHeight; return pDVD->UpdateOverlay(); } /* end of if statement */ return S_OK; } /*************************************************************/ /* Name: SetDDrawDVD /* Description: /*************************************************************/ STDMETHODIMP COverlayCallback::SetDDrawDVD(VARIANT pDDrawDVD) { switch(pDDrawDVD.vt){ case VT_VOID: { m_pDDrawDVD = static_cast (pDDrawDVD.byref); break; } } /* end of switch statement */ return S_OK; }