aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/IVideoD3DOSD.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/IVideoD3DOSD.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/IVideoD3DOSD.cpp')
-rw-r--r--Src/Winamp/IVideoD3DOSD.cpp966
1 files changed, 966 insertions, 0 deletions
diff --git a/Src/Winamp/IVideoD3DOSD.cpp b/Src/Winamp/IVideoD3DOSD.cpp
new file mode 100644
index 00000000..1804a742
--- /dev/null
+++ b/Src/Winamp/IVideoD3DOSD.cpp
@@ -0,0 +1,966 @@
+#include "main.h"
+#include "IVideoD3DOSD.h"
+#include "resource.h"
+
+extern wchar_t FileTitle[];
+static HMODULE d3dx_lib = 0;
+
+// For non-debug builds, comment out DXTraceW debug statements to
+// remove them completely
+//#ifndef _DEBUG
+#define DXTraceW //
+//#endif
+
+typedef HRESULT (WINAPI *D3DXCREATESPRITE)(LPDIRECT3DDEVICE9, LPD3DXSPRITE *);
+typedef HRESULT (WINAPI *D3DXCREATEFONTW)(LPDIRECT3DDEVICE9, INT, UINT, UINT, UINT, BOOL, DWORD, DWORD, DWORD, DWORD, LPCWSTR, LPD3DXFONT *);
+typedef HRESULT (WINAPI *D3DXCREATETEXTUREFROMRESOURCEEXW)(LPDIRECT3DDEVICE9, HMODULE, LPCWSTR, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, DWORD, DWORD, D3DCOLOR, D3DXIMAGE_INFO *, PALETTEENTRY *, LPDIRECT3DTEXTURE9 *);
+D3DXCREATESPRITE pCreateSprite = NULL;
+D3DXCREATEFONTW pCreateFontW = NULL;
+D3DXCREATETEXTUREFROMRESOURCEEXW pCreateTextureFromResourceExW = NULL;
+
+HMODULE FindD3DX9()
+{
+ if (d3dx_lib)
+ return d3dx_lib;
+
+ HMODULE d3dx9 = NULL;
+ HANDLE hFind;
+ WIN32_FIND_DATAW pfiledata;
+ wchar_t systemDir[MAX_PATH] = {0};
+ wchar_t libPath[MAX_PATH] = {0};
+ GetSystemDirectoryW(systemDir, MAX_PATH);
+ StringCchCatW(systemDir, MAX_PATH,L"\\d3dx9_");
+ StringCchCopyW(libPath, MAX_PATH, systemDir);
+ StringCchCatW(systemDir, MAX_PATH,L"*.dll");
+
+ hFind = FindFirstFileW(systemDir,&pfiledata);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ BOOL more = true;
+ int iHighVersion = 0;
+ while (more)
+ {
+ wchar_t *start = wcsrchr(pfiledata.cFileName,L'_') + 1;
+ int version = _wtoi(start);
+ if (version <= 42 && version > iHighVersion)
+ iHighVersion = version;
+ more = FindNextFileW(hFind,&pfiledata);
+ }
+
+ FindClose(hFind);
+ if (iHighVersion >= 24)
+ {
+ wchar_t finalD3DX9LibPath[MAX_PATH] = {0};
+ StringCchPrintfW(finalD3DX9LibPath,MAX_PATH,L"%s%d%s",libPath,iHighVersion,L".dll");
+
+ d3dx9 = LoadLibraryW(finalD3DX9LibPath);
+ }
+ }
+
+ return d3dx9;
+}
+
+IVideoD3DOSD::IVideoD3DOSD(void)
+{
+ osdSprite = NULL;
+ osdAtlasTexture = NULL;
+ osdTimeFont = NULL;
+ osdTitleFont = NULL;
+ streaming = 0;
+ titleFits = false;
+
+ // Texture Src Coordinates for sprite images
+ // Right and Bottom (last two) excluded from image
+ SetRect(&osdBkgrndTextSrcCoords, 38, 534, 647, 635);
+
+ SetRect(&osdPrevButtonNormalSrcCoords, 41, 17, 63, 31);
+ SetRect(&osdPlayButtonNormalSrcCoords, 145, 14, 161, 35);
+ SetRect(&osdPauseButtonNormalSrcCoords, 95, 16, 110, 33);
+ SetRect(&osdStopButtonNormalSrcCoords, 195, 16, 210, 33);
+ SetRect(&osdNextButtonNormalSrcCoords, 242, 17, 264, 31);
+ SetRect(&osdProgressFrameNormalSrcCoords, 41, 226, 606, 235);
+ SetRect(&osdVolumeFrameNormalSrcCoords, 41, 294, 111, 302);
+ SetRect(&osdEndFSButtonNormalSrcCoords, 41, 140, 59, 158);
+ SetRect(&osdMuteButtonNormalSrcCoords, 41, 416, 51, 428);
+ SetRect(&osdProgressSliderNormalSrcCoords, 41, 343, 57, 361);
+ SetRect(&osdVolumeSliderNormalSrcCoords, 41, 343, 57, 361);
+ SetRect(&osdProgressProgressSrcCoords, 41, 274, 606, 282); //hilited progress indicator
+ SetRect(&osdVolumeProgressSrcCoords, 41, 314, 111, 322); //hilited volume indicator
+
+ SetRect(&osdPrevButtonClickSrcCoords, 41, 76, 63, 90);
+ SetRect(&osdPlayButtonClickSrcCoords, 145, 73, 161, 94);
+ SetRect(&osdPauseButtonClickSrcCoords, 95, 75, 110, 92);
+ SetRect(&osdStopButtonClickSrcCoords, 195, 75, 210, 92);
+ SetRect(&osdNextButtonClickSrcCoords, 242, 76, 264, 90);
+ SetRect(&osdEndFSButtonClickSrcCoords, 41, 192, 59, 210);
+ SetRect(&osdProgressSliderClickSrcCoords, 41, 385, 57, 403);
+ SetRect(&osdVolumeSliderClickSrcCoords, 41, 385, 57, 403);
+
+ SetRect(&osdPrevButtonDisabledSrcCoords, 41, 106, 63, 120);
+ SetRect(&osdNextButtonDisabledSrcCoords, 242, 106, 264, 120);
+
+ SetRect(&osdPrevButtonHiliteSrcCoords, 41, 46, 63, 60);
+ SetRect(&osdPlayButtonHiliteSrcCoords, 145, 43, 161, 64);
+ SetRect(&osdPauseButtonHiliteSrcCoords, 95, 45, 110, 62);
+ SetRect(&osdStopButtonHiliteSrcCoords, 195, 45, 210, 62);
+ SetRect(&osdNextButtonHiliteSrcCoords, 242, 46, 264, 60);
+ SetRect(&osdEndFSButtonHiliteSrcCoords, 41, 166, 59, 184);
+ SetRect(&osdProgressSliderHiliteSrcCoords, 41, 363, 57, 381);
+ SetRect(&osdVolumeSliderHiliteSrcCoords, 41, 363, 57, 381);
+
+ xScalingFactor = 1.0f;
+ yScalingFactor = 1.0f;
+
+ for (int i = 0; i < 12; i++)
+ {
+ bState[i] = NORMAL;
+ }
+
+ mouseOver = NO_BUTTON;
+ mouseLastOver = NO_BUTTON;
+ mousePressed = NO_BUTTON;
+ mouseLastPressed = NO_BUTTON;
+ mouseDragging = false;
+
+ displayTitle = NULL;
+ marqueeTitleSrc = NULL;
+ titleRestart = 0;
+ dtFormat = 0;
+
+ isInited = false;
+ isReadyToDraw = false;
+}
+
+RECT IVideoD3DOSD::BuildHitRect(D3DXVECTOR3 position, RECT size)
+{
+ RECT hitRect;
+ // casting float to long since I know the position vector will not be too big.
+ hitRect.left = (long)position.x;
+ hitRect.top = (long)position.y;
+ hitRect.right = (long)position.x + size.right - size.left;
+ hitRect.bottom = (long)position.y + size.bottom - size.top;
+ return hitRect;
+}
+
+IVideoD3DOSD::~IVideoD3DOSD(void)
+{
+ if (osdSprite)
+ {
+ osdSprite->Release();
+ osdSprite = NULL;
+ }
+ if (osdAtlasTexture)
+ {
+ osdAtlasTexture->Release();
+ osdAtlasTexture = NULL;
+ }
+ if (marqueeTitleSrc)
+ {
+ delete [] marqueeTitleSrc;
+ marqueeTitleSrc = NULL;
+ }
+
+ if (displayTitle)
+ {
+ delete [] displayTitle;
+ displayTitle = NULL;
+ }
+
+ //if (d3dx_lib)
+ //{
+ // FreeLibrary(d3dx_lib);
+ // d3dx_lib = NULL;
+ //}
+}
+
+void IVideoD3DOSD::SetScalingFactor(float fx, float fy)
+{
+ xScalingFactor = fx;
+ yScalingFactor = fy;
+}
+
+void IVideoD3DOSD::CreateOSD(IDirect3DDevice9 * device)
+{
+ HRESULT hr;
+
+ d3dx_lib = FindD3DX9();
+ if (!d3dx_lib)
+ return;
+
+ pCreateFontW = (D3DXCREATEFONTW) GetProcAddress(d3dx_lib,"D3DXCreateFontW");
+ pCreateSprite = (D3DXCREATESPRITE) GetProcAddress(d3dx_lib,"D3DXCreateSprite");
+ pCreateTextureFromResourceExW = (D3DXCREATETEXTUREFROMRESOURCEEXW) GetProcAddress(d3dx_lib,"D3DXCreateTextureFromResourceExW");
+
+ if (!pCreateFontW || !pCreateSprite || !pCreateTextureFromResourceExW)
+ return;
+
+ hr = pCreateSprite(device,&osdSprite);
+ if (FAILED(hr))
+ {
+ DXTraceW(__FILE__, __LINE__, hr, L"CreateSprite Error", TRUE);
+ return;
+ }
+
+ int font_size = -12 ;
+ hr = pCreateFontW(
+ device,
+ font_size,
+ 0,
+ FW_NORMAL,
+ 1,
+ 0,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ ANTIALIASED_QUALITY, //DEFAULT_QUALITY,
+ DEFAULT_PITCH,
+ L"Arial",
+ &osdTimeFont);
+ if (FAILED(hr))
+ {
+ DXTraceW(__FILE__, __LINE__, hr, L"CreateFont (Time) Error", TRUE);
+ return;
+ }
+
+ font_size = -16 ;
+ hr = pCreateFontW(
+ device,
+ font_size,
+ 0,
+ FW_NORMAL,
+ 1,
+ 0,
+ DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ ANTIALIASED_QUALITY,//DEFAULT_QUALITY,
+ DEFAULT_PITCH,
+ L"Trebuchet MS",
+ &osdTitleFont);
+ if (FAILED(hr))
+ {
+ DXTraceW(__FILE__, __LINE__, hr, L"CreateFont (Title) Error", TRUE);
+ return;
+ }
+
+ ResetOSD(device);
+
+ isInited = true;
+}
+
+void IVideoD3DOSD::UpdateOSD(HWND hWnd, VideoOutput *adjuster)
+{
+ // Position of sprites in screen coordinates
+ // Center of sprite (where the position is mapped) is left to default to upper left corner
+ // Note the Bkgrnd is positioned and then all other sprites are relative to that
+ RECT clientRect;
+ GetClientRect(hWnd,&clientRect);
+ // Need to adjust the client rect to match the video aspect ration to fit the osd on the video.
+ // adjuster->adjustAspect(clientRect);
+ // width of the client area - width of the bkgrnd / 2 gives the space on each side
+ // add that space to the offset of the left side of the client area.
+ float xPosBkg = clientRect.left +
+ (((clientRect.right - clientRect.left) - (osdBkgrndTextSrcCoords.right - osdBkgrndTextSrcCoords.left))/2.0f);
+ // width of the client area * .95 give the location of the bottom of the osd (i.e. 5% from bottom)
+ // that minus the height of the bkgrnd gives the location of the upper left of background
+ // add that space to the offset of the top of the client area.
+ float yPosBkg = clientRect.top +
+ (((clientRect.bottom - clientRect.top) * 1.0f) - (osdBkgrndTextSrcCoords.bottom - osdBkgrndTextSrcCoords.top));
+ osdBkgrndPosition = D3DXVECTOR3(floor(xPosBkg), floor(yPosBkg), 0.0f);
+
+ osdPrevButtonPosition = osdBkgrndPosition + D3DXVECTOR3(191.0f, 75.0f, 0.0f);
+ osdPlayButtonPosition = osdBkgrndPosition + D3DXVECTOR3(246.0f, 72.0f, 0.0f);
+ osdPauseButtonPosition = osdBkgrndPosition + D3DXVECTOR3(296.0f, 74.0f, 0.0f);
+ osdStopButtonPosition = osdBkgrndPosition + D3DXVECTOR3(345.5f, 74.0f, 0.0f);
+ osdNextButtonPosition = osdBkgrndPosition + D3DXVECTOR3(392.5f, 75.0f, 0.0f);
+ osdProgressFramePosition = osdBkgrndPosition + D3DXVECTOR3(22.0f, 49.0f, 0.0f);
+ osdVolumeFramePosition = osdBkgrndPosition + D3DXVECTOR3(518.0f, 76.0f, 0.0f);
+ osdEndFSButtonPosition = osdBkgrndPosition + D3DXVECTOR3(583.0f, 19.0f, 0.0f);
+ osdMuteButtonPosition = osdVolumeFramePosition + D3DXVECTOR3(-15.0f, -1.0f, 0.0f);
+ osdProgressSliderPosition = osdProgressFramePosition + D3DXVECTOR3(0.0f, 0.0f, 0.0f);
+ osdVolumeSliderPosition = osdVolumeFramePosition + D3DXVECTOR3(0.0f, 0.0f, 0.0f);
+
+ SetRect(&osdTimeRect,
+ (long)osdBkgrndPosition.x + 26,
+ (long)osdBkgrndPosition.y + 76,
+ (long)osdBkgrndPosition.x + 98,
+ (long)osdBkgrndPosition.y + 85);
+
+ SetRect(&osdTitleRect,
+ (long)osdBkgrndPosition.x + 26,
+ (long)osdBkgrndPosition.y + 17,
+ (long)osdBkgrndPosition.x + 503,
+ (long)osdBkgrndPosition.y + 37);
+
+ // Create Hit Test Rects for ui elements that don't move
+ osdPrevButtonHit = BuildHitRect(osdPrevButtonPosition, osdPrevButtonNormalSrcCoords );
+ osdPlayButtonHit = BuildHitRect(osdPlayButtonPosition, osdPlayButtonNormalSrcCoords );
+ osdPauseButtonHit = BuildHitRect(osdPauseButtonPosition, osdPauseButtonNormalSrcCoords );
+ osdStopButtonHit = BuildHitRect(osdStopButtonPosition, osdStopButtonNormalSrcCoords );
+ osdNextButtonHit = BuildHitRect(osdNextButtonPosition, osdNextButtonNormalSrcCoords );
+ osdEndFSButtonHit = BuildHitRect(osdEndFSButtonPosition, osdEndFSButtonNormalSrcCoords);
+ osdProgressFrameHit = BuildHitRect(osdProgressFramePosition, osdProgressFrameNormalSrcCoords);
+ osdVolumeFrameHit = BuildHitRect(osdVolumeFramePosition, osdVolumeFrameNormalSrcCoords);
+
+ streaming = (in_getlength() < 0) || !in_mod || !in_mod->is_seekable;
+ if (streaming)
+ {
+ bState[PREV_BUTTON] = DISABLED;
+ bState[NEXT_BUTTON] = DISABLED;
+ bState[PROGRESS_FRAME] = DISABLED;
+ bState[PROGRESS_SLIDER] = DISABLED;
+ }
+
+ // Find out if the title will fit in the UI space for it
+ RECT tempTitleRect = osdTitleRect;
+ osdTitleFont->DrawTextW(NULL, FileTitle, -1, &tempTitleRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP | DT_CALCRECT, D3DCOLOR_XRGB(255,255,255));
+ if (tempTitleRect.right <= osdTitleRect.right)
+ {
+ // The title fits, just use it
+ titleFits = true;
+ displayTitle = FileTitle;
+ dtFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP;
+ } else
+ {
+ // title will not fit, we need to set up a marquee.
+ //
+ // a string with two copies of the title makes it easier to process
+ // sizeNeeded, in chars, includes one space, five dots,
+ // one space and 1 extra for null.
+ size_t sizeNeeded = (lstrlenW(FileTitle)*2) + 8;
+ marqueeTitleSrc = new wchar_t[sizeNeeded];
+ displayTitle = new wchar_t[sizeNeeded];
+ titleRestart = lstrlenW(FileTitle);
+ StringCchPrintfW(marqueeTitleSrc, sizeNeeded, L"%s ..... %s", FileTitle, FileTitle);
+ titleFits = false;
+ dtFormat = DT_RIGHT | DT_TOP | DT_SINGLELINE;
+ }
+
+ isReadyToDraw = true;
+}
+#ifdef _DEBUG
+#define DRAW_OSD_SET_ERROR(x) draw_osd_error=x
+#else
+#define DRAW_OSD_SET_ERROR(x)
+#endif
+
+void IVideoD3DOSD::DrawOSD(IDirect3DDevice9 * device)
+{
+ HRESULT hr;
+ D3DXVECTOR3 sliderCenter(8.0f, 8.0f, 0.0f);
+
+ const wchar_t *draw_osd_error;
+ hr = osdSprite->Begin(D3DXSPRITE_ALPHABLEND);
+ if (FAILED(hr))
+ {
+
+ DXTraceW(__FILE__, __LINE__, hr, L"Sprite Begin Error", TRUE);
+ return ;
+ }
+
+ // Doing Scaling of sprites here
+ // If we do translations and/or rotations we'll have to do a more
+ // robust hit test (picking) since the current one assumes a rectangular
+ // shape based on screen coordinates. Only scaling is currently handled
+ // in the hit test.
+ //D3DXMATRIX scalingMatrix;
+ //osdSprite->SetTransform(D3DXMatrixScaling(&scalingMatrix, 1.0f /*xScalingFactor*/, 1.0f /*yScalingFactor*/, 0.0f));
+
+ hr = osdSprite->Draw(osdAtlasTexture, &osdBkgrndTextSrcCoords, NULL, &osdBkgrndPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Background Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(PREV_BUTTON), NULL, &osdPrevButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Prev Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(PLAY_BUTTON), NULL, &osdPlayButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Play Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(PAUSE_BUTTON), NULL, &osdPauseButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Pause Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(STOP_BUTTON), NULL, &osdStopButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Stop Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(NEXT_BUTTON), NULL, &osdNextButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Next Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(PROGRESS_FRAME), NULL, &osdProgressFramePosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Progress Frame Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(VOLUME_FRAME), NULL, &osdVolumeFramePosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Volume Frame Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(ENDFS_BUTTON), NULL, &osdEndFSButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"EndFS Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(MUTE_BUTTON), NULL, &osdMuteButtonPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Mute Button Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+
+ if (playing && !streaming && !mouseDragging) // if mouseDragging we may be repositioning the slider, don't set it back till Lmouseup
+ {
+ // calculate the relative position of the slider
+ float ppercent = (in_getouttime() / 1000.0f) / in_getlength();
+ float sizeOfProgFrame = (float)osdProgressFrameHit.right - osdProgressFrameHit.left - 0;
+ // position the progress slider
+ osdProgressSliderPosition.x = osdProgressFramePosition.x + (sizeOfProgFrame * ppercent);
+ // Now build the hit rect based on the new position.
+ osdProgressSliderHit = BuildHitRect(osdProgressSliderPosition + D3DXVECTOR3(0.0f,0.0f,0.0f), osdProgressSliderNormalSrcCoords);
+ }
+
+
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(PROGRESS_SLIDER), &sliderCenter, &osdProgressSliderPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Progress Slider Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+
+ // Build the progress hilite line by drawing only a certain amount (width) of the texture.
+ RECT seekProgress;
+ // The progress hilite line goes on top of progress frame
+ seekProgress = osdProgressProgressSrcCoords;
+ // The width of the progress hilite line is determined by the location of the slider
+ seekProgress.right = seekProgress.left + (osdProgressSliderHit.left - osdProgressFrameHit.left + 0);
+
+ hr = osdSprite->Draw(osdAtlasTexture,
+ &seekProgress,
+ NULL,
+ &osdProgressFramePosition,
+ D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Seek Progress Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+
+ if (!mouseDragging) // if mouseDragging we may be repositioning the slider, don't set it back till Lmouseup
+ {
+ // calculate the relative position of the slider
+ float vpercent = config_volume / 255.0f;
+ float sizeOfVolFrame = (float)osdVolumeFrameHit.right - osdVolumeFrameHit.left - 0;
+ // position the volume slider
+ osdVolumeSliderPosition.x = (osdVolumeFramePosition.x) + (sizeOfVolFrame * vpercent);
+ // Now build the hit rect based on the new position.
+ osdVolumeSliderHit = BuildHitRect(osdVolumeSliderPosition + D3DXVECTOR3(0.0f,0.0f,0.0f), osdVolumeSliderNormalSrcCoords);
+ }
+ hr = osdSprite->Draw(osdAtlasTexture, GetTextCoords(VOLUME_SLIDER), &sliderCenter, &osdVolumeSliderPosition, D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Volume SLider Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+
+ // Build the volume hilite line by drawing only a certain amount (width) of the texture.
+ RECT volProgress;
+ // The volume hilite line goes on top of volume frame
+ volProgress = osdVolumeProgressSrcCoords;
+ // The width of the volume hilite line is determined by the location of the slider
+ volProgress.right = volProgress.left + (osdVolumeSliderHit.left - osdVolumeFrameHit.left + 0);
+
+ hr = osdSprite->Draw(osdAtlasTexture,
+ &volProgress,
+ NULL,
+ &osdVolumeFramePosition,
+ D3DCOLOR_XRGB(255,255,255));
+ if (FAILED(hr))
+ {
+ DRAW_OSD_SET_ERROR(L"Volume Progress Sprite Draw Error");
+ goto DrawOSD_Error;
+ }
+
+
+ if (osdTimeFont)
+ {
+ int seconds_in = in_getouttime() / 1000;
+ int time_to_go = in_getlength();
+
+ wchar_t timerText[256] = {0};
+ if (streaming)
+ StringCbPrintfW(timerText,sizeof(timerText),L"%.2u:%.2u",seconds_in /60,seconds_in % 60);
+ else
+ StringCbPrintfW(timerText,sizeof(timerText),L"%.2u:%.2u / %.2u:%.2u",seconds_in /60,seconds_in % 60,time_to_go / 60, time_to_go % 60);
+ osdTimeFont->DrawTextW(osdSprite, timerText, -1, &osdTimeRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP, D3DCOLOR_XRGB(163,164,167)); // #A3A4A7
+ }
+
+ if (osdTitleFont)
+ {
+ // found possibility that user can pause in full screen and remove items from playlist
+ // This prevents a crash by not trying to display a title.
+ if (lstrlenW(FileTitle) > 0)
+ {
+ if (!titleFits)
+ {
+ // title does not fit, build marquee
+ DWORD now = GetTickCount();
+ static DWORD then;
+ if (now - then > 250) // slow it down so people can read it.
+ {
+ static int charCount = 2; // start with the first char + 1 for null
+ lstrcpynW(displayTitle,marqueeTitleSrc,charCount);
+ charCount++;
+ if (charCount > lstrlenW(marqueeTitleSrc))
+ charCount = lstrlenW(FileTitle);
+ then = now;
+ }
+ }
+
+ osdTitleFont->DrawTextW(osdSprite, displayTitle, -1, &osdTitleRect, dtFormat, D3DCOLOR_XRGB(204,204,204)); // #cccccc
+ }
+ }
+
+ hr = osdSprite->End();
+ if (FAILED(hr))
+ {
+ DXTraceW(__FILE__, __LINE__, hr, L"Sprite End Error", TRUE);
+ return;
+ }
+
+ return;
+DrawOSD_Error:
+ DXTraceW(__FILE__, __LINE__, hr, draw_osd_error, TRUE);
+ osdSprite->End();
+}
+
+RECT *IVideoD3DOSD::GetTextCoords(UI_ELEM item)
+{
+ switch (item)
+ {
+ case PREV_BUTTON :
+ switch (bState[item])
+ {
+ case NORMAL :
+ return &osdPrevButtonNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdPrevButtonClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdPrevButtonHiliteSrcCoords;
+ break;
+ case DISABLED :
+ return &osdPrevButtonDisabledSrcCoords;
+ break;
+ }
+
+ break;
+ case PLAY_BUTTON :
+ switch (bState[item])
+ {
+ case NORMAL :
+ case DISABLED :
+ return &osdPlayButtonNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdPlayButtonClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdPlayButtonHiliteSrcCoords;
+ break;
+ }
+
+ break;
+ case PAUSE_BUTTON :
+ switch (bState[item])
+ {
+ case NORMAL :
+ case DISABLED :
+ return &osdPauseButtonNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdPauseButtonClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdPauseButtonHiliteSrcCoords;
+ break;
+ }
+
+ break;
+ case STOP_BUTTON :
+ switch (bState[item])
+ {
+ case NORMAL :
+ case DISABLED :
+ return &osdStopButtonNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdStopButtonClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdStopButtonHiliteSrcCoords;
+ break;
+ }
+
+ break;
+ case NEXT_BUTTON :
+ switch (bState[item])
+ {
+ case NORMAL :
+ return &osdNextButtonNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdNextButtonClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdNextButtonHiliteSrcCoords;
+ break;
+ case DISABLED :
+ return &osdNextButtonDisabledSrcCoords;
+ break;
+ }
+
+ break;
+ case ENDFS_BUTTON :
+ switch (bState[item])
+ {
+ case NORMAL :
+ case DISABLED :
+ return &osdEndFSButtonNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdEndFSButtonClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdEndFSButtonHiliteSrcCoords;
+ break;
+ }
+
+ break;
+ case MUTE_BUTTON :
+ return &osdMuteButtonNormalSrcCoords;
+ //switch (bState[item])
+ //{
+ //case NORMAL :
+ //case DISABLED :
+ // return &osdMuteButtonNormalSrcCoords;
+ // break;
+ //case CLICKED :
+ // return &osdMuteButtonClickSrcCoords;
+ // break;
+ //case HILITE :
+ // return &osdMuteButtonHiliteSrcCoords;
+ // break;
+ //}
+
+ break;
+ case PROGRESS_FRAME :
+ return &osdProgressFrameNormalSrcCoords;
+
+ break;
+ case VOLUME_FRAME :
+ return &osdVolumeFrameNormalSrcCoords;
+
+ break;
+ case PROGRESS_SLIDER :
+ switch (bState[item])
+ {
+ case NORMAL :
+ case DISABLED :
+ return &osdProgressSliderNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdProgressSliderClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdProgressSliderHiliteSrcCoords;
+ break;
+ }
+
+ break;
+ case VOLUME_SLIDER :
+ switch (bState[item])
+ {
+ case NORMAL :
+ case DISABLED :
+ return &osdVolumeSliderNormalSrcCoords;
+ break;
+ case CLICKED :
+ return &osdVolumeSliderClickSrcCoords;
+ break;
+ case HILITE :
+ return &osdVolumeSliderHiliteSrcCoords;
+ break;
+ }
+
+ break;
+ }
+
+ return NULL;
+}
+
+void IVideoD3DOSD::LostOSD()
+{
+ if (osdSprite)
+ osdSprite->OnLostDevice();
+ if (osdTimeFont)
+ osdTimeFont->OnLostDevice();
+ if (osdTitleFont)
+ osdTitleFont->OnLostDevice();
+ if (osdAtlasTexture)
+ {
+ osdAtlasTexture->Release();
+ osdAtlasTexture = 0;
+ }
+}
+
+void IVideoD3DOSD::ResetOSD(IDirect3DDevice9 * device)
+{
+ if (osdSprite)
+ osdSprite->OnResetDevice();
+ if (osdTimeFont)
+ osdTimeFont->OnResetDevice();
+ if (osdTitleFont)
+ osdTitleFont->OnResetDevice();
+
+ if (device)
+ {
+ HRESULT hr;
+ hr = pCreateTextureFromResourceExW(
+ device,
+ NULL, // HMODULE
+ MAKEINTRESOURCEW(IDB_OSD), // Our texture image atlas
+ D3DX_DEFAULT, // width
+ D3DX_DEFAULT, // height
+ 1, // MIP levels
+ 0, // usage
+ D3DFMT_UNKNOWN, // get format from file
+ D3DPOOL_DEFAULT, // mem pool
+ D3DX_DEFAULT, // filter
+ D3DX_DEFAULT, // MIP filter
+ 0, // transparent color key
+ NULL, // image info struct
+ NULL, // palette
+ &osdAtlasTexture); // the returned texture, if success
+ if (FAILED(hr))
+ {
+ DXTraceW(__FILE__, __LINE__, hr, L"CreateTextureFromFileEx Error", TRUE);
+ return;
+ }
+ }
+
+}
+
+bool IVideoD3DOSD::MouseDown(int xpt, int ypt, WPARAM wParam)
+{
+ Show();
+ // mouseLastPressed is used during mouse up to verify that the up is on the
+ // same UI element as the mouse down.
+ mouseLastPressed = HitTest((float)xpt, (float)ypt);
+ bState[mouseLastPressed] = CLICKED;
+ return false;
+}
+bool IVideoD3DOSD::MouseMove(int ixpt, int iypt, WPARAM wParam)
+{
+ static int saved_ixpt;
+ static int saved_iypt;
+
+ // Need to check whether the mouse cursor is still in the same place.
+ // Evidently, WM_MOUSEMOVE can get triggered for other reasons than
+ // actually moving the mouse, per Microsoft blogs
+ // This code was triggering with IM and EMAIL notifications without
+ // moving the mouse.
+ if (ixpt == saved_ixpt && iypt == saved_iypt)
+ return false;
+
+ saved_ixpt = ixpt;
+ saved_iypt = iypt;
+
+ Show();
+
+ // Change input ints to floats so later calculations are more precise.
+ float xpt = (float)ixpt;
+ float ypt = (float)iypt;
+
+ mouseOver = HitTest((float)xpt, (float)ypt);
+ if (wParam & MK_LBUTTON) //dragging
+ {
+ mouseDragging = true;
+ if (mouseLastPressed == VOLUME_SLIDER)
+ {
+ if (xpt < (osdVolumeFrameHit.left)) xpt = (float) osdVolumeFrameHit.left;
+ else if (xpt > (osdVolumeFrameHit.right) - 0) xpt = (float) osdVolumeFrameHit.right - 0;
+
+ //move the volume slider
+ osdVolumeSliderPosition.x = xpt;
+ // slider uses center as center
+ osdVolumeSliderHit = BuildHitRect(osdVolumeSliderPosition + D3DXVECTOR3(0.0f,0.0f,0.0f),osdVolumeSliderNormalSrcCoords);
+ }
+ else if (mouseLastPressed == PROGRESS_SLIDER)
+ {
+ if (xpt < osdProgressFrameHit.left) xpt = (float)osdProgressFrameHit.left;
+ else if (xpt > (osdProgressFrameHit.right)) xpt = (float)osdProgressFrameHit.right;
+
+ //move the progress slider
+ osdProgressSliderPosition.x = xpt;
+ osdProgressSliderHit = BuildHitRect(osdProgressSliderPosition + D3DXVECTOR3(0.0f,0.0f,0.0f),osdProgressSliderNormalSrcCoords);
+ }
+ } else // no click, just mousemove
+ {
+ mouseDragging = false;
+ if (mouseLastOver != mouseOver)
+ {
+ if (bState[mouseLastOver] == HILITE)
+ bState[mouseLastOver] = NORMAL;
+ if (bState[mouseOver] == NORMAL)
+ bState[mouseOver] = HILITE;
+ mouseLastOver = mouseOver;
+ }
+ }
+
+ return false;
+}
+
+bool IVideoD3DOSD::MouseUp(int xpt, int ypt, WPARAM wParam)
+{
+ mousePressed = HitTest((float)xpt, (float)ypt);
+
+ bState[mouseLastPressed] = NORMAL;
+
+ if (bState[mousePressed] == HILITE)
+ bState[mousePressed] = NORMAL;
+
+ mouseDragging = false;
+
+ switch (mousePressed)
+ {
+ case ENDFS_BUTTON :
+ if (mouseLastPressed == ENDFS_BUTTON)
+ return true; // end full screen
+ break;
+ case PREV_BUTTON :
+ if (mouseLastPressed == PREV_BUTTON)
+ PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON1, 0);
+ break;
+ case PLAY_BUTTON :
+ if (mouseLastPressed == PLAY_BUTTON)
+ PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON2, 0);
+ break;
+ case PAUSE_BUTTON :
+ if (mouseLastPressed == PAUSE_BUTTON)
+ PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON3, 0);
+ break;
+ case STOP_BUTTON :
+ if (mouseLastPressed == STOP_BUTTON)
+ PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON4, 0);
+ break;
+ case NEXT_BUTTON :
+ if (mouseLastPressed == NEXT_BUTTON)
+ PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON5, 0);
+ break;
+ default :
+ {
+ // If not a button, check the sliders
+ // The successful use of the sliders should not depend on
+ // releasing the mouse inside the frame, which may be very small.
+ switch (mouseLastPressed)
+ {
+ case PROGRESS_SLIDER :
+ case PROGRESS_FRAME :
+ {
+ float xIntoFrame = (float)xpt - osdProgressFrameHit.left;
+ // -8 is half the width of the slider
+ float rightMaxOfFrame = (float)osdProgressFrameHit.right - 0;
+ float leftMinOfFrame = (float)osdProgressFrameHit.left;
+ float sizeOfFrame = rightMaxOfFrame - leftMinOfFrame;
+ float t = xIntoFrame / sizeOfFrame;
+ if (t < 0)
+ t = 0;
+ if (t > 1)
+ t = 1;
+
+ int len = in_getlength();
+ in_seek((int)(t*len*1000));
+ }
+ break;
+ case VOLUME_SLIDER :
+ case VOLUME_FRAME :
+ {
+ float xIntoFrame = (float)xpt - (osdVolumeFrameHit.left);
+ // -8 is half the width of the slider
+ float rightMaxOfFrame = (float)osdVolumeFrameHit.right - 0;
+ float leftMinOfFrame = (float)osdVolumeFrameHit.left;
+ float sizeOfFrame = rightMaxOfFrame - leftMinOfFrame;
+ float t = xIntoFrame / sizeOfFrame;
+
+ if (t < 0)
+ t = 0;
+ if (t > 1)
+ t = 1;
+
+ unsigned char v = (unsigned char)(t * 255);
+
+ config_volume = v;
+
+ in_setvol(v);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ mouseLastPressed = NO_BUTTON;
+ return false;
+}
+
+IVideoD3DOSD::UI_ELEM IVideoD3DOSD::HitTest(float xpt, float ypt)
+{
+ if (PointInRect(xpt, ypt, osdPrevButtonHit))
+ return PREV_BUTTON;
+ else if (PointInRect(xpt, ypt, osdPlayButtonHit))
+ return PLAY_BUTTON;
+ else if (PointInRect(xpt, ypt, osdPauseButtonHit))
+ return PAUSE_BUTTON;
+ else if (PointInRect(xpt, ypt, osdStopButtonHit))
+ return STOP_BUTTON;
+ else if (PointInRect(xpt, ypt, osdNextButtonHit))
+ return NEXT_BUTTON;
+ else if (PointInRect(xpt, ypt, osdEndFSButtonHit))
+ return ENDFS_BUTTON;
+ else if (PointInRect(xpt, ypt, osdVolumeSliderHit))
+ return VOLUME_SLIDER;
+ else if (PointInRect(xpt, ypt, osdProgressSliderHit))
+ return PROGRESS_SLIDER;
+ else if (PointInRect(xpt, ypt, osdProgressFrameHit))
+ return PROGRESS_FRAME;
+ else if (PointInRect(xpt, ypt, osdVolumeFrameHit))
+ return VOLUME_FRAME;
+ else
+ return NO_BUTTON;
+}
+
+bool IVideoD3DOSD::PointInRect(float x, float y, RECT testRect)
+{
+ if ((x >= testRect.left) && (x <= testRect.right) &&
+ (y >= testRect.top) && (y <= testRect.bottom))
+ return true;
+ else
+ return false;
+}