Remove the feature preventing the screensaver from running when VSFilter is active...
[xy_vsfilter.git] / src / filters / transform / vsfilter / Systray.cpp
blob542abc0b2c3f1d70621ec0b3f4a00d8bab3bce13
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "stdafx.h"
23 #include "resource.h"
24 #include "DirectVobSubFilter.h"
25 #include "../../../DSUtil/DSUtil.h"
27 // hWnd == INVALID_HANDLE_VALUE - get name, hWnd != INVALID_HANDLE_VALUE - show ppage
28 static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd);
30 static HHOOK g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
32 static UINT WM_DVSPREVSUB = RegisterWindowMessage(TEXT("WM_DVSPREVSUB"));
33 static UINT WM_DVSNEXTSUB = RegisterWindowMessage(TEXT("WM_DVSNEXTSUB"));
34 static UINT WM_DVSHIDESUB = RegisterWindowMessage(TEXT("WM_DVSHIDESUB"));
35 static UINT WM_DVSSHOWSUB = RegisterWindowMessage(TEXT("WM_DVSSHOWSUB"));
36 static UINT WM_DVSSHOWHIDESUB = RegisterWindowMessage(TEXT("WM_DVSSHOWHIDESUB"));
37 static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
38 static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
40 LRESULT CALLBACK HookProc(UINT code, WPARAM wParam, LPARAM lParam)
42 MSG* msg = (MSG*)lParam;
44 if(msg->message == WM_KEYDOWN)
46 switch(msg->wParam)
48 case VK_F13: PostMessage(HWND_BROADCAST, WM_DVSPREVSUB, 0, 0); break;
49 case VK_F14: PostMessage(HWND_BROADCAST, WM_DVSNEXTSUB, 0, 0); break;
50 case VK_F15: PostMessage(HWND_BROADCAST, WM_DVSHIDESUB, 0, 0); break;
51 case VK_F16: PostMessage(HWND_BROADCAST, WM_DVSSHOWSUB, 0, 0); break;
52 case VK_F17: PostMessage(HWND_BROADCAST, WM_DVSSHOWHIDESUB, 0, 0); break;
53 default: break;
57 // Always call next hook in chain
58 return CallNextHookEx(g_hHook, code, wParam, lParam);
61 class CSystrayWindow : public CWnd
63 SystrayIconData* m_tbid;
65 void StepSub(int dir)
67 int iSelected, nLangs;
68 if(FAILED(m_tbid->dvs->get_LanguageCount(&nLangs))) return;
69 if(FAILED(m_tbid->dvs->get_SelectedLanguage(&iSelected))) return;
70 if(nLangs > 0) m_tbid->dvs->put_SelectedLanguage((iSelected+dir+nLangs)%nLangs);
73 void ShowSub(bool fShow)
75 m_tbid->dvs->put_HideSubtitles(!fShow);
78 void ToggleSub()
80 bool fShow;
81 if(FAILED(m_tbid->dvs->get_HideSubtitles(&fShow))) return;
82 m_tbid->dvs->put_HideSubtitles(!fShow);
85 public:
86 CSystrayWindow(SystrayIconData* tbid) : m_tbid(tbid) {}
88 protected:
89 DECLARE_MESSAGE_MAP()
91 public:
92 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
93 afx_msg void OnClose();
94 afx_msg void OnDestroy();
95 afx_msg LRESULT OnDVSPrevSub(WPARAM, LPARAM);
96 afx_msg LRESULT OnDVSNextSub(WPARAM, LPARAM);
97 afx_msg LRESULT OnDVSHideSub(WPARAM, LPARAM);
98 afx_msg LRESULT OnDVSShowSub(WPARAM, LPARAM);
99 afx_msg LRESULT OnDVSShowHideSub(WPARAM, LPARAM);
100 afx_msg LRESULT OnTaskBarRestart(WPARAM, LPARAM);
101 afx_msg LRESULT OnNotifyIcon(WPARAM, LPARAM);
104 BEGIN_MESSAGE_MAP(CSystrayWindow, CWnd)
105 ON_WM_CREATE()
106 ON_WM_CLOSE()
107 ON_WM_DESTROY()
108 ON_WM_TIMER()
109 ON_REGISTERED_MESSAGE(WM_DVSPREVSUB, OnDVSPrevSub)
110 ON_REGISTERED_MESSAGE(WM_DVSNEXTSUB, OnDVSNextSub)
111 ON_REGISTERED_MESSAGE(WM_DVSHIDESUB, OnDVSHideSub)
112 ON_REGISTERED_MESSAGE(WM_DVSSHOWSUB, OnDVSShowSub)
113 ON_REGISTERED_MESSAGE(WM_DVSSHOWHIDESUB, OnDVSShowHideSub)
114 ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
115 ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
116 END_MESSAGE_MAP()
118 int CSystrayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
120 if(CWnd::OnCreate(lpCreateStruct) == -1)
121 return -1;
123 if(g_hHook == INVALID_HANDLE_VALUE)
125 AFX_MANAGE_STATE(AfxGetStaticModuleState());
126 // g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc, AfxGetInstanceHandle(), 0);
129 SetTimer(1, 5000, NULL);
131 PostMessage(s_uTaskbarRestart);
133 return 0;
136 void CSystrayWindow::OnClose()
138 DestroyWindow();
141 void CSystrayWindow::OnDestroy()
143 NOTIFYICONDATA tnid;
144 ZeroMemory(&tnid, sizeof(NOTIFYICONDATA));
145 tnid.cbSize = sizeof(NOTIFYICONDATA);
146 tnid.hWnd = m_hWnd;
147 tnid.uID = IDI_ICON1;
148 Shell_NotifyIcon(NIM_DELETE, &tnid);
150 if(g_hHook != INVALID_HANDLE_VALUE)
152 UnhookWindowsHookEx(g_hHook);
153 g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
156 PostQuitMessage(0);
159 LRESULT CSystrayWindow::OnDVSPrevSub(WPARAM, LPARAM)
160 {StepSub(-1); return 0;}
161 LRESULT CSystrayWindow::OnDVSNextSub(WPARAM, LPARAM)
162 {StepSub(+1); return 0;}
163 LRESULT CSystrayWindow::OnDVSHideSub(WPARAM, LPARAM)
164 {ShowSub(false); return 0;}
165 LRESULT CSystrayWindow::OnDVSShowSub(WPARAM, LPARAM)
166 {ShowSub(true); return 0;}
167 LRESULT CSystrayWindow::OnDVSShowHideSub(WPARAM, LPARAM)
168 {ToggleSub(); return 0;}
170 LRESULT CSystrayWindow::OnTaskBarRestart(WPARAM, LPARAM)
172 AFX_MANAGE_STATE(AfxGetStaticModuleState());
174 if(m_tbid->fShowIcon)
176 NOTIFYICONDATA tnid;
177 ZeroMemory(&tnid, sizeof(NOTIFYICONDATA));
178 tnid.cbSize = sizeof(NOTIFYICONDATA);
179 tnid.hWnd = m_hWnd;
180 tnid.uID = IDI_ICON1;
181 tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1));
182 // tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 0, 0, LR_LOADTRANSPARENT);
183 tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
184 tnid.uCallbackMessage = WM_NOTIFYICON;
185 lstrcpyn(tnid.szTip, TEXT("DirectVobSub"), sizeof(tnid.szTip));
187 BOOL res = Shell_NotifyIcon(NIM_ADD, &tnid);
189 if(tnid.hIcon) DestroyIcon(tnid.hIcon);
191 return res?0:-1;
194 return 0;
197 LRESULT CSystrayWindow::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
199 if((UINT)wParam != IDI_ICON1)
200 return -1;
202 HWND hWnd = m_hWnd;
204 switch((UINT)lParam)
206 case WM_LBUTTONDBLCLK:
208 // IMPORTANT: we must not hold the graph at the same time as showing the property page
209 // or else when closing the app the graph doesn't get released and dvobsub's JoinFilterGraph
210 // is never called to close us down.
212 CComPtr<IBaseFilter> pBF2;
214 BeginEnumFilters(m_tbid->graph, pEF, pBF)
216 if(!CComQIPtr<IDirectVobSub>(pBF))
217 continue;
219 if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
221 HWND hwnd;
222 if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
223 || SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
224 hWnd = hwnd;
227 pBF2 = pBF;
229 break;
231 EndEnumFilters
233 if(pBF2)
234 ShowPPage(pBF2, hWnd);
236 break;
238 case WM_RBUTTONDOWN:
240 POINT p;
241 GetCursorPos(&p);
243 CInterfaceArray<IAMStreamSelect> pStreams;
244 CStringArray names;
246 BeginEnumFilters(m_tbid->graph, pEF, pBF)
248 CString name = GetFilterName(pBF);
249 if(name.IsEmpty()) continue;
251 if(CComQIPtr<IAMStreamSelect> pSS = pBF)
253 pStreams.Add(pSS);
254 names.Add(name);
257 EndEnumFilters
259 CMenu popup;
260 popup.CreatePopupMenu();
262 for(int j = 0; j < pStreams.GetCount(); j++)
264 bool fMMSwitcher = !names[j].Compare(_T("Morgan Stream Switcher"));
266 DWORD cStreams = 0;
267 pStreams[j]->Count(&cStreams);
269 DWORD flags, group, prevgroup = -1;
271 for(UINT i = 0; i < cStreams; i++)
273 WCHAR* pName = NULL;
275 if(S_OK == pStreams[j]->Info(i, 0, &flags, 0, &group, &pName, 0, 0))
277 if(prevgroup != group && i > 1)
279 if(fMMSwitcher) {cStreams = i; break;}
280 popup.AppendMenu(MF_SEPARATOR);
282 prevgroup = group;
284 if(pName)
286 popup.AppendMenu(MF_ENABLED|MF_STRING|(flags?MF_CHECKED:MF_UNCHECKED), (1<<15)|(j<<8)|(i), CString(pName));
287 CoTaskMemFree(pName);
292 if(cStreams > 0) popup.AppendMenu(MF_SEPARATOR);
295 int i;
297 TCHAR* str;
298 for(i = 0; str = CallPPage(m_tbid->graph, i, (HWND)INVALID_HANDLE_VALUE); i++)
300 if(_tcsncmp(str, _T("DivX MPEG"), 9) || m_tbid->fRunOnce) // divx3's ppage will crash if the graph hasn't been run at least once yet
301 popup.AppendMenu(MF_ENABLED|MF_STRING|MF_UNCHECKED, (1<<14)|(i), str);
303 delete [] str;
306 SetForegroundWindow();
307 UINT id = popup.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, CWnd::FromHandle(hWnd), 0);
308 PostMessage(WM_NULL);
310 if(id & (1<<15))
312 pStreams[(id>>8)&0x3f]->Enable(id&0xff, AMSTREAMSELECTENABLE_ENABLE);
314 else if(id & (1<<14))
316 if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
318 HWND hwnd;
319 if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
320 || SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
321 hWnd = hwnd;
324 CallPPage(m_tbid->graph, id&0xff, hWnd);
327 break;
329 default:
330 break;
333 return 0;
338 DWORD CALLBACK SystrayThreadProc(void* pParam)
340 AFX_MANAGE_STATE(AfxGetStaticModuleState());
342 CSystrayWindow wnd((SystrayIconData*)pParam);
343 if(!wnd.CreateEx(0, AfxRegisterWndClass(0), _T("DVSWND"), WS_OVERLAPPED, CRect(0, 0, 0, 0), NULL, 0, NULL))
344 return -1;
346 ((SystrayIconData*)pParam)->hSystrayWnd = wnd.m_hWnd;
348 MSG msg;
349 while(GetMessage(&msg, NULL/*wnd.m_hWnd*/, 0, 0))
351 TranslateMessage(&msg);
352 DispatchMessage(&msg);
355 return 0;
358 // TODO: replace this function
360 // hWnd == INVALID_HANDLE_VALUE - get name, hWnd != INVALID_HANDLE_VALUE - show ppage
361 static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd)
363 int i = 0;
364 //bool fFound = false;
366 WCHAR* wstr = NULL;
367 CComPtr<IBaseFilter> pFilter;
368 CAUUID caGUID;
369 caGUID.pElems = NULL;
371 BeginEnumFilters(pGraph, pEF, pBF)
373 CComQIPtr<ISpecifyPropertyPages> pSPS = pBF;
374 if(!pSPS) continue;
376 if(i == idx)
378 pFilter = pBF;
379 pSPS->GetPages(&caGUID);
380 wstr = _wcsdup(CStringW(GetFilterName(pBF))); // double char-wchar conversion happens in the non-unicode build, but anyway... :)
381 break;
384 i++;
386 EndEnumFilters
388 TCHAR* ret = NULL;
390 if(pFilter)
392 if(hWnd != INVALID_HANDLE_VALUE)
394 ShowPPage(pFilter, hWnd);
396 else
398 if(ret = new TCHAR[wcslen(wstr)+1])
399 _tcscpy(ret, CString(wstr));
403 if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
404 if(wstr) free(wstr);
406 return(ret);