diff options
Diffstat (limited to 'Src/Winamp/VideoOSD.cpp')
-rw-r--r-- | Src/Winamp/VideoOSD.cpp | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/Src/Winamp/VideoOSD.cpp b/Src/Winamp/VideoOSD.cpp new file mode 100644 index 00000000..aedb7df0 --- /dev/null +++ b/Src/Winamp/VideoOSD.cpp @@ -0,0 +1,537 @@ +#include "Main.h" +#include "VideoOSD.h" + +#include "resource.h" + + +#include "draw.h" + +#include "../nu/AutoChar.h" +#define OSD_TEXT_R 192 +#define OSD_TEXT_G 192 +#define OSD_TEXT_B 192 +#define OSD_TEXT_R_HILITE 255 +#define OSD_TEXT_G_HILITE 255 +#define OSD_TEXT_B_HILITE 255 +#define OSD_VOL_COL_R 0 +#define OSD_VOL_COL_G 0 +#define OSD_VOL_COL_B 192 +#define OSD_VOL_BKCOL_R 0 +#define OSD_VOL_BKCOL_G 0 +#define OSD_VOL_BKCOL_B 64 + +#define CTRL_PROGRESSTEXT 0 +#define CTRL_PROGRESS 1 +#define CTRL_PROGRESSSPACER 2 +#define CTRL_REW 3 +#define CTRL_PLAY 4 +#define CTRL_PAUSE 5 +#define CTRL_STOP 6 +#define CTRL_FFWD 7 +#define CTRL_VOLSPACER 8 +#define CTRL_VOLTEXT 9 +#define CTRL_VOL 10 + +#define CTRLTYPE_SYMBOL 0 +#define CTRLTYPE_TEXT 1 +#define CTRLTYPE_PROGRESS 2 +#define CTRLTYPE_SPACER 3 + +IVideoOSD *temp; + +int g_ctrl_type[ NUM_WIDGETS ] = +{ + CTRLTYPE_TEXT, + CTRLTYPE_PROGRESS, + CTRLTYPE_SPACER, + CTRLTYPE_SYMBOL, + CTRLTYPE_SYMBOL, + CTRLTYPE_SYMBOL, + CTRLTYPE_SYMBOL, + CTRLTYPE_SYMBOL, + CTRLTYPE_SPACER, + CTRLTYPE_TEXT, + CTRLTYPE_PROGRESS +}; + + +#define SHOW_STREAM_TITLE_AT_TOP 1 + +char progStr[64] = {0}, volStr[64] = {0}; +const char *g_ctrl_text[NUM_WIDGETS] = + { + progStr/*"Progress "*/, + "", + "", + "7", // rew + "4", // play + ";", // pause + "<", // stop + "8", // ffwd + "", + volStr/*"Volume "*/, + "" + }; + + +int g_ctrl_force_width[NUM_WIDGETS] = + { + 0, + 256/*96*/, // progress bar width + 32, // spacer width + 0, // rew + 0, // play + 0, // pause + 0, // stop + 0, // ffwd + 32, // spacer width + 0, + 96/*64*/ // volume bar width + }; + +IVideoOSD::IVideoOSD() + : ctrlrects_ready(0), parent(0) +{ + temp = this; + + getString(IDS_OSD_PROGRESS_TEXT,progStr,64); + getString(IDS_OSD_VOLUME_TEXT,volStr,64); + + last_close_height = 0; + last_close_width = 0; + osdMemBMW = 0; + osdMemBMH = 0; + osdLastMouseX = -1; + osdLastMouseY = -1; + ignore_mousemove_count = 0; + osdLastClickItem = 0; + show_osd = false; + + for (int i = 0; i < NUM_WIDGETS; i++) + SetRect(&ctrlrect[i], 0, 0, 0, 0); +} + +IVideoOSD::~IVideoOSD() +{ + KillTimer(parent, (UINT_PTR)this); +} + +bool IVideoOSD::Showing() +{ + return show_osd; +} + +bool IVideoOSD::Ready() +{ + return !!ctrlrects_ready; +} + +int IVideoOSD::GetBarHeight() +{ + return (/*show_osd && */ctrlrects_ready) ? (ctrlrect_all.bottom - ctrlrect_all.top) : 0; +} + +void IVideoOSD::HitTest(int x, int y, int dragging) +{ + if (!show_osd) return ; + + // dragging == -1: just a mousemove (no clicking) + // dragging == 0: user clicked + // dragging == 1: user clicked before, and is now dragging/moving mouse + + if (dragging < 1) + osdLastClickItem = -1; + + // transform (x,y) from screen coords into coords relative to the memDC + RECT lastfsrect; + getViewport(&lastfsrect, parent, 1, NULL); + y = y - ((lastfsrect.bottom - lastfsrect.top) - (ctrlrect_all.bottom - ctrlrect_all.top)); + + int i0 = 0; + int i1 = NUM_WIDGETS; + if (dragging == 1) + { + i0 = osdLastClickItem; + i1 = osdLastClickItem + 1; + } + + for (int i = i0; i < i1; i++) + { + if (dragging == 1 || (x >= ctrlrect[i].left && x <= ctrlrect[i].right && y >= ctrlrect[i].top && y <= ctrlrect[i].bottom)) + { + float t = (x - ctrlrect[i].left) / (float)(ctrlrect[i].right - ctrlrect[i].left); + if (t < 0) t = 0; + if (t > 1) t = 1; + if (dragging < 1) + osdLastClickItem = i; + + switch (i) + { + case CTRL_VOL: + if (dragging >= 0) + { + int v = (int)(t * 255); + config_volume = v; + in_setvol(v); + draw_volumebar(config_volume, 0); + } + return ; + case CTRL_PROGRESS: + + if (dragging >= 0) + { + int len = in_getlength(); + if (len > 0 && !PlayList_ishidden(PlayList_getPosition())) + { + if (in_seek((int)(t*len*1000)) < 0) + SendMessageW(hMainWindow, WM_WA_MPEG_EOF, 0, 0); + } + } + return ; + case CTRL_PAUSE: + if (dragging == 0) + { + PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON3, 0); + } + return ; + case CTRL_PLAY: + if (dragging == 0) + { + PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON2, 0); + } + return ; + case CTRL_STOP: + if (dragging == 0) + { + PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON4, 0); + } + return ; + case CTRL_REW: + case CTRL_FFWD: + if (dragging == 0) + { + if (i == CTRL_REW) + PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON1, 0); + else + PostMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON5, 0); + } + return ; + default: + if (dragging < 1) + osdLastClickItem = -1; + break; + } + } + } +} + +void IVideoOSD::Show() +{ + if (!show_osd) + { + + show_osd = true; + SetCursor(LoadCursor(NULL, IDC_ARROW)); + RECT r; + GetClientRect(parent, &r); + r.bottom = r.top + GetBarHeight(); + InvalidateRect(parent, &r, TRUE); + GetClientRect(parent, &r); + r.top = r.bottom - GetBarHeight(); + InvalidateRect(parent, &r, TRUE); + + PostMessageW(parent, WM_USER + 0x888, 0, 0); + } + + KillTimer(parent, (UINT_PTR)this); + SetTimer(parent, (UINT_PTR)this, 3000, IVideoOSD::TimerCallback); + +// Draw(); +} + +void CALLBACK IVideoOSD::TimerCallback(HWND /*hwnd*/, UINT /*uMsg*/, UINT_PTR idEvent, DWORD/* dwTime*/) +{ + IVideoOSD *videoOSD = (IVideoOSD *)idEvent; + videoOSD->Hide(); +} + +void IVideoOSD::Hide() +{ + + + RECT r; + GetClientRect(parent, &r); + r.bottom = r.top + GetBarHeight(); + InvalidateRect(parent, &r, TRUE); + GetClientRect(parent, &r); + r.top = r.bottom - GetBarHeight(); + InvalidateRect(parent, &r, TRUE); + + PostMessageW(parent, WM_USER + 0x888, 0, 0); + + if (show_osd) + { + //MessageBeep(0xFFFFFFFF); + show_osd = false; + KillTimer(parent, (UINT_PTR)this); + SetCursor(NULL); + } + //ctrlrects_ready = 0; +} + + +void IVideoOSD::Draw() +{ + HDC hdc = GetDC(parent); + if (show_osd) + { + HGDIOBJ osdProgressBrushBg = CreateSolidBrush(RGB(OSD_VOL_BKCOL_R, OSD_VOL_BKCOL_G, OSD_VOL_BKCOL_B)); + HGDIOBJ osdProgressBrushFg = CreateSolidBrush(RGB(OSD_VOL_COL_R, OSD_VOL_COL_G, OSD_VOL_COL_B)); + HGDIOBJ osdProgressPenBg = CreatePen(PS_SOLID, 0, RGB(OSD_TEXT_R, OSD_TEXT_G, OSD_TEXT_B)); + HGDIOBJ osdProgressPenFg = CreatePen(PS_NULL, 0, RGB(0, 0, 0)); + HGDIOBJ osdProgressPenBgHilite = CreatePen(PS_SOLID, 0, RGB(OSD_TEXT_R_HILITE, OSD_TEXT_G_HILITE, OSD_TEXT_B_HILITE)); + HGDIOBJ osdBlackBrush = CreateSolidBrush(RGB(0, 0, 0)); //OV_COL_R,OV_COL_G,OV_COL_B)); + HFONT osdFontSymbol = CreateFontA(OSD_TEXT_SIZE, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, "Webdings"); + + HDC osdMemDC = CreateCompatibleDC(hdc); + HBITMAP osdMemBM = 0; // memory bitmap (for memDC) + HBITMAP osdOldBM = 0; // old bitmap (from memDC) + + + COLORREF fg = GetTextColor(osdMemDC); + COLORREF bg = GetBkColor(osdMemDC); + SetTextColor(osdMemDC, RGB(OSD_TEXT_R, OSD_TEXT_G, OSD_TEXT_B)); + SetBkColor(osdMemDC, RGB(0, 0, 0)); //OV_COL_R,OV_COL_G,OV_COL_B)); + + HGDIOBJ oldfont = SelectObject(osdMemDC, osdFontText); + HGDIOBJ oldbrush = SelectObject(osdMemDC, osdProgressBrushBg); + HGDIOBJ oldpen = SelectObject(osdMemDC, osdProgressPenBg); + + RECT fullr; + GetClientRect(parent, &fullr); + + /* ClientToScreen(parent, (LPPOINT)&fullr); + ClientToScreen(parent, ((LPPOINT)&fullr) + 1); + // transform coords from windows desktop coords (where 0,0==upper-left corner of the primary monitor) + // to the coords for the monitor we're displaying on: + fullr.top -= m_mon_y; + fullr.left -= m_mon_x; + fullr.right -= m_mon_x; + fullr.bottom -= m_mon_y; + */ + int streaming = (in_getlength() < 0) || !in_mod || !in_mod->is_seekable; + + if (ctrlrects_ready != streaming + 1) + { + ctrlrects_ready = streaming + 1; + + int net_width = 0; + int max_height = 0; + int i; + for (i = 0; i < NUM_WIDGETS; i++) + { + SetRect(&ctrlrect[i], 0, 0, 0, 0); + if (streaming && (i == CTRL_PROGRESS || i == CTRL_PROGRESSTEXT || i == CTRL_PROGRESSSPACER || i == CTRL_FFWD || i == CTRL_REW)) + { + // disable progress bar + seek arrows when the NSV is a stream + ctrlrect[i].right = -1; + continue; + } + else if (g_ctrl_force_width[i] != 0) + { + SetRect(&ctrlrect[i], 0, 0, g_ctrl_force_width[i], 0); + } + else + { + SelectObject(osdMemDC, (g_ctrl_type[i] == CTRLTYPE_SYMBOL) ? osdFontSymbol : osdFontText); + SetRect(&ctrlrect[i], 0, 0, 256, 256); + ctrlrect[i].bottom = DrawTextA(osdMemDC, g_ctrl_text[i], -1, &ctrlrect[i], DT_SINGLELINE | DT_CALCRECT); + } + net_width += ctrlrect[i].right - ctrlrect[i].left; + max_height = max(max_height, ctrlrect[i].bottom - ctrlrect[i].top); + } + + // now we know the size of all the controls; now place them. + int x = (fullr.right + fullr.left) / 2 - net_width / 2; + SetRect(&ctrlrect_all, 0, 0, 0, 0); + for (i = 0; i < NUM_WIDGETS; i++) + { + if (ctrlrect[i].right >= 0) // if control is not disabled... + { + int this_width = ctrlrect[i].right - ctrlrect[i].left; + int this_height = ctrlrect[i].bottom - ctrlrect[i].top ; + if (this_height == 0) this_height = max_height * 2 / 3; // progress bars + ctrlrect[i].top = max_height / 2 - this_height / 2; + ctrlrect[i].bottom = max_height / 2 + this_height / 2; + ctrlrect[i].left = x; + ctrlrect[i].right = x + this_width; + if (ctrlrect_all.bottom == 0) + { + ctrlrect_all.top = ctrlrect[i].top ; + ctrlrect_all.bottom = ctrlrect[i].bottom; + } + else + { + ctrlrect_all.top = min(ctrlrect_all.top , ctrlrect[i].top); + ctrlrect_all.bottom = max(ctrlrect_all.bottom, ctrlrect[i].bottom); + } + x += this_width; + } + } + } + + int w = fullr.right - fullr.left; + int h = ctrlrect_all.bottom - ctrlrect_all.top; + if (!osdMemBM || osdMemBMW != w || osdMemBMH != h) + { + if (osdMemBM) + { + SelectObject(osdMemDC, osdOldBM); + DeleteObject(osdMemBM); + } + osdMemBM = CreateCompatibleBitmap(hdc, w, h); + osdOldBM = (HBITMAP)SelectObject(osdMemDC, osdMemBM); + osdMemBMW = w; + osdMemBMH = h; + } + + RECT temp; + SetRect(&temp, 0, 0, w, h); + FillRect(osdMemDC, &temp, (HBRUSH)osdBlackBrush); + + for (int i = 0; i < NUM_WIDGETS; i++) + { + if (g_ctrl_type[i] == CTRLTYPE_PROGRESS) + { + int progress = 0; + int max_progress = ctrlrect[i].right - ctrlrect[i].left; + switch (i) + { + case CTRL_VOL: + progress = config_volume * max_progress / 255; + break; + case CTRL_PROGRESS: + if (playing) + { + int len = in_getlength(); + if (len > 0) progress = (in_getouttime() / 1000) * max_progress / len; + } + if (progress > max_progress) progress = max_progress; + break; + } + + SelectObject(osdMemDC, osdProgressBrushBg); + SelectObject(osdMemDC, (i == osdLastClickItem) ? osdProgressPenBgHilite : osdProgressPenBg); + RoundRect(osdMemDC, ctrlrect[i].left, ctrlrect[i].top, ctrlrect[i].right, ctrlrect[i].bottom, 3, 3); + SelectObject(osdMemDC, osdProgressBrushFg); + SelectObject(osdMemDC, osdProgressPenFg); + Rectangle(osdMemDC, ctrlrect[i].left + 1, ctrlrect[i].top + 1, ctrlrect[i].left + progress, ctrlrect[i].bottom); + } + else if (g_ctrl_type[i] == CTRLTYPE_SYMBOL || + g_ctrl_type[i] == CTRLTYPE_TEXT) + { + SelectObject(osdMemDC, (g_ctrl_type[i] == CTRLTYPE_SYMBOL) ? osdFontSymbol : osdFontText); + SetTextColor(osdMemDC, (i == osdLastClickItem) ? RGB(OSD_TEXT_R_HILITE, OSD_TEXT_G_HILITE, OSD_TEXT_B_HILITE) : RGB(OSD_TEXT_R, OSD_TEXT_G, OSD_TEXT_B)); + DrawTextA(osdMemDC, g_ctrl_text[i], -1, &ctrlrect[i], DT_SINGLELINE); + } + } + + int x0 = fullr.left; + int y0 = fullr.bottom - (ctrlrect_all.bottom - ctrlrect_all.top); + BitBlt(hdc, x0, y0, w, h, osdMemDC, 0, 0, SRCCOPY); + + // display stream title @ the top: +#if (SHOW_STREAM_TITLE_AT_TOP) + if (1) + { + RECT temp; + SetRect(&temp, 0, 0, w, h); + FillRect(osdMemDC, &temp, (HBRUSH)osdBlackBrush); + + SelectObject(osdMemDC, osdFontText); + SetTextColor(osdMemDC, RGB(OSD_TEXT_R, OSD_TEXT_G, OSD_TEXT_B)); + AutoChar narrowTitle(FileTitle); + wchar_t buf[FILETITLE_SIZE+32] = {0}; + + StringCchPrintfW(buf, sizeof(buf)/sizeof(*buf), L"%s (%d %s)", FileTitle ? FileTitle : L"", g_brate, getStringW(IDS_KBPS,NULL,0)); + if ((config_fixtitles&2)) + { + wchar_t *p = buf; + while (p && *p) + { + if (*p == '_') // replace _ with space + *p = ' '; + p = CharNextW(p); + } + } + DrawTextW(osdMemDC, buf, -1, &temp, DT_SINGLELINE | DT_CENTER); + + SelectObject(osdMemDC, osdFontSymbol); + DrawTextW(osdMemDC, L"2", -1, &temp, DT_SINGLELINE | DT_RIGHT); + RECT rr = {0, 0, w, h}; + DrawTextW(osdMemDC, L"2", -1, &rr, DT_SINGLELINE | DT_RIGHT | DT_CALCRECT); + last_close_height = rr.bottom - rr.top; + last_close_width = rr.right - rr.left; + + + int x0 = fullr.left; + int y0 = fullr.top; + BitBlt(hdc, x0, y0, w, h, osdMemDC, 0, 0, SRCCOPY); + } + + SelectObject(osdMemDC, oldpen); + SelectObject(osdMemDC, oldbrush); + SelectObject(osdMemDC, oldfont); + SetTextColor(osdMemDC, fg); + SetBkColor(osdMemDC, bg); + + DeleteObject(osdProgressBrushBg); + DeleteObject(osdProgressBrushFg); + DeleteObject(osdBlackBrush); + DeleteObject(osdProgressPenBg); + DeleteObject(osdProgressPenFg); + DeleteObject(osdProgressPenBgHilite); + DeleteObject(osdFontSymbol); + if (osdMemDC) + { + SelectObject(osdMemDC, osdOldBM); // delete our doublebuffer + DeleteDC(osdMemDC); + } + if (osdMemBM) DeleteObject(osdMemBM); + } +#endif + ReleaseDC(parent, hdc); +} + +bool IVideoOSD::CloseHitTest(int x, int y) +{ + RECT r; + GetClientRect(parent, &r); + return (x > r.right - last_close_width && y < last_close_height); +} + +bool IVideoOSD::Mouse(int x, int y, WPARAM wParam, bool moving) +{ + if (wParam & MK_LBUTTON) + { + Show(); + if (CloseHitTest(x, y)) + return true; + ignore_mousemove_count = 2; + HitTest(x, y, moving ? 1 : 0); + } + else + { + if (((osdLastMouseX - x) || (osdLastMouseY - y)) && (ignore_mousemove_count--)) + { + Show(); + HitTest(x, y, moving ? -1 : 0); + ignore_mousemove_count = 2; + } + } + + osdLastMouseX = x; + osdLastMouseY = y; + return false; +} + |