00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include "resource.h"
00024 #include "DirectVobSubFilter.h"
00025 #include "..\..\..\DSUtil\DSUtil.h"
00026
00027
00028 static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd);
00029
00030 static HHOOK g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
00031
00032 static UINT WM_DVSPREVSUB = RegisterWindowMessage(TEXT("WM_DVSPREVSUB"));
00033 static UINT WM_DVSNEXTSUB = RegisterWindowMessage(TEXT("WM_DVSNEXTSUB"));
00034 static UINT WM_DVSHIDESUB = RegisterWindowMessage(TEXT("WM_DVSHIDESUB"));
00035 static UINT WM_DVSSHOWSUB = RegisterWindowMessage(TEXT("WM_DVSSHOWSUB"));
00036 static UINT WM_DVSSHOWHIDESUB = RegisterWindowMessage(TEXT("WM_DVSSHOWHIDESUB"));
00037 static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
00038 static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
00039
00040 LRESULT CALLBACK HookProc(UINT code, WPARAM wParam, LPARAM lParam)
00041 {
00042 MSG* msg = (MSG*)lParam;
00043
00044 if(msg->message == WM_KEYDOWN)
00045 {
00046 switch(msg->wParam)
00047 {
00048 case VK_F13: PostMessage(HWND_BROADCAST, WM_DVSPREVSUB, 0, 0); break;
00049 case VK_F14: PostMessage(HWND_BROADCAST, WM_DVSNEXTSUB, 0, 0); break;
00050 case VK_F15: PostMessage(HWND_BROADCAST, WM_DVSHIDESUB, 0, 0); break;
00051 case VK_F16: PostMessage(HWND_BROADCAST, WM_DVSSHOWSUB, 0, 0); break;
00052 case VK_F17: PostMessage(HWND_BROADCAST, WM_DVSSHOWHIDESUB, 0, 0); break;
00053 default: break;
00054 }
00055 }
00056
00057
00058 return CallNextHookEx(g_hHook, code, wParam, lParam);
00059 }
00060
00061 class CSystrayWindow : public CWnd
00062 {
00063 SystrayIconData* m_tbid;
00064
00065 void StepSub(int dir)
00066 {
00067 int iSelected, nLangs;
00068 if(FAILED(m_tbid->dvs->get_LanguageCount(&nLangs))) return;
00069 if(FAILED(m_tbid->dvs->get_SelectedLanguage(&iSelected))) return;
00070 if(nLangs > 0) m_tbid->dvs->put_SelectedLanguage((iSelected+dir+nLangs)%nLangs);
00071 }
00072
00073 void ShowSub(bool fShow)
00074 {
00075 m_tbid->dvs->put_HideSubtitles(!fShow);
00076 }
00077
00078 void ToggleSub()
00079 {
00080 bool fShow;
00081 if(FAILED(m_tbid->dvs->get_HideSubtitles(&fShow))) return;
00082 m_tbid->dvs->put_HideSubtitles(!fShow);
00083 }
00084
00085 public:
00086 CSystrayWindow(SystrayIconData* tbid) : m_tbid(tbid) {}
00087
00088 protected:
00089 DECLARE_MESSAGE_MAP()
00090
00091 public:
00092 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
00093 afx_msg void OnClose();
00094 afx_msg void OnDestroy();
00095 afx_msg void OnTimer(UINT nIDEvent);
00096 afx_msg LRESULT OnDVSPrevSub(WPARAM, LPARAM);
00097 afx_msg LRESULT OnDVSNextSub(WPARAM, LPARAM);
00098 afx_msg LRESULT OnDVSHideSub(WPARAM, LPARAM);
00099 afx_msg LRESULT OnDVSShowSub(WPARAM, LPARAM);
00100 afx_msg LRESULT OnDVSShowHideSub(WPARAM, LPARAM);
00101 afx_msg LRESULT OnTaskBarRestart(WPARAM, LPARAM);
00102 afx_msg LRESULT OnNotifyIcon(WPARAM, LPARAM);
00103 };
00104
00105 BEGIN_MESSAGE_MAP(CSystrayWindow, CWnd)
00106 ON_WM_CREATE()
00107 ON_WM_CLOSE()
00108 ON_WM_DESTROY()
00109 ON_WM_TIMER()
00110 ON_REGISTERED_MESSAGE(WM_DVSPREVSUB, OnDVSPrevSub)
00111 ON_REGISTERED_MESSAGE(WM_DVSNEXTSUB, OnDVSNextSub)
00112 ON_REGISTERED_MESSAGE(WM_DVSHIDESUB, OnDVSHideSub)
00113 ON_REGISTERED_MESSAGE(WM_DVSSHOWSUB, OnDVSShowSub)
00114 ON_REGISTERED_MESSAGE(WM_DVSSHOWHIDESUB, OnDVSShowHideSub)
00115 ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
00116 ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
00117 END_MESSAGE_MAP()
00118
00119 int CSystrayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
00120 {
00121 if(CWnd::OnCreate(lpCreateStruct) == -1)
00122 return -1;
00123
00124 if(g_hHook == INVALID_HANDLE_VALUE)
00125 {
00126 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00127
00128 }
00129
00130 SetTimer(1, 5000, NULL);
00131
00132 PostMessage(s_uTaskbarRestart);
00133
00134 return 0;
00135 }
00136
00137 void CSystrayWindow::OnClose()
00138 {
00139 DestroyWindow();
00140 }
00141
00142 void CSystrayWindow::OnDestroy()
00143 {
00144 NOTIFYICONDATA tnid;
00145 tnid.cbSize = sizeof(NOTIFYICONDATA);
00146 tnid.hWnd = m_hWnd;
00147 tnid.uID = IDI_ICON1;
00148 Shell_NotifyIcon(NIM_DELETE, &tnid);
00149
00150 if(g_hHook != INVALID_HANDLE_VALUE)
00151 {
00152 UnhookWindowsHookEx(g_hHook);
00153 g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
00154 }
00155
00156 PostQuitMessage(0);
00157 }
00158
00159 void CSystrayWindow::OnTimer(UINT nIDEvent)
00160 {
00161 if(nIDEvent == 1)
00162 {
00163 UINT fScreenSaver = 0;
00164 if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fScreenSaver, 0))
00165 {
00166 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE);
00167 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fScreenSaver, 0, SPIF_SENDWININICHANGE);
00168 }
00169 }
00170
00171 CWnd::OnTimer(nIDEvent);
00172 }
00173
00174 LRESULT CSystrayWindow::OnDVSPrevSub(WPARAM, LPARAM)
00175 {StepSub(-1); return 0;}
00176 LRESULT CSystrayWindow::OnDVSNextSub(WPARAM, LPARAM)
00177 {StepSub(+1); return 0;}
00178 LRESULT CSystrayWindow::OnDVSHideSub(WPARAM, LPARAM)
00179 {ShowSub(false); return 0;}
00180 LRESULT CSystrayWindow::OnDVSShowSub(WPARAM, LPARAM)
00181 {ShowSub(true); return 0;}
00182 LRESULT CSystrayWindow::OnDVSShowHideSub(WPARAM, LPARAM)
00183 {ToggleSub(); return 0;}
00184
00185 LRESULT CSystrayWindow::OnTaskBarRestart(WPARAM, LPARAM)
00186 {
00187 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00188
00189 if(m_tbid->fShowIcon)
00190 {
00191 NOTIFYICONDATA tnid;
00192 tnid.cbSize = sizeof(NOTIFYICONDATA);
00193 tnid.hWnd = m_hWnd;
00194 tnid.uID = IDI_ICON1;
00195 tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1));
00196
00197 tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
00198 tnid.uCallbackMessage = WM_NOTIFYICON;
00199 lstrcpyn(tnid.szTip, TEXT("DirectVobSub"), sizeof(tnid.szTip));
00200
00201 BOOL res = Shell_NotifyIcon(NIM_ADD, &tnid);
00202
00203 if(tnid.hIcon) DestroyIcon(tnid.hIcon);
00204
00205 return res?0:-1;
00206 }
00207
00208 return 0;
00209 }
00210
00211 LRESULT CSystrayWindow::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
00212 {
00213 if((UINT)wParam != IDI_ICON1)
00214 return -1;
00215
00216 HWND hWnd = m_hWnd;
00217
00218 switch((UINT)lParam)
00219 {
00220 case WM_LBUTTONDBLCLK:
00221 {
00222
00223
00224
00225
00226 CComPtr<IBaseFilter> pBF2;
00227
00228 BeginEnumFilters(m_tbid->graph, pEF, pBF)
00229 {
00230 if(!CComQIPtr<IDirectVobSub>(pBF))
00231 continue;
00232
00233 if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
00234 {
00235 HWND hwnd;
00236 if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
00237 || SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
00238 hWnd = hwnd;
00239 }
00240
00241 pBF2 = pBF;
00242
00243 break;
00244 }
00245 EndEnumFilters
00246
00247 if(pBF2)
00248 ShowPPage(pBF2, hWnd);
00249 }
00250 break;
00251
00252 case WM_RBUTTONDOWN:
00253 {
00254 POINT p;
00255 GetCursorPos(&p);
00256
00257 CInterfaceArray<IAMStreamSelect> pStreams;
00258 CStringArray names;
00259
00260 BeginEnumFilters(m_tbid->graph, pEF, pBF)
00261 {
00262 CString name = GetFilterName(pBF);
00263 if(name.IsEmpty()) continue;
00264
00265 if(CComQIPtr<IAMStreamSelect> pSS = pBF)
00266 {
00267 pStreams.Add(pSS);
00268 names.Add(name);
00269 }
00270 }
00271 EndEnumFilters
00272
00273 CMenu popup;
00274 popup.CreatePopupMenu();
00275
00276 for(int j = 0; j < pStreams.GetCount(); j++)
00277 {
00278 bool fMMSwitcher = !names[j].Compare(_T("Morgan Stream Switcher"));
00279
00280 DWORD cStreams = 0;
00281 pStreams[j]->Count(&cStreams);
00282
00283 DWORD flags, group, prevgroup = -1;
00284
00285 for(UINT i = 0; i < cStreams; i++)
00286 {
00287 WCHAR* pName = NULL;
00288
00289 if(S_OK == pStreams[j]->Info(i, 0, &flags, 0, &group, &pName, 0, 0))
00290 {
00291 if(prevgroup != group && i > 1)
00292 {
00293 if(fMMSwitcher) {cStreams = i; break;}
00294 popup.AppendMenu(MF_SEPARATOR);
00295 }
00296 prevgroup = group;
00297
00298 if(pName)
00299 {
00300 popup.AppendMenu(MF_ENABLED|MF_STRING|(flags?MF_CHECKED:MF_UNCHECKED), (1<<15)|(j<<8)|(i), CString(pName));
00301 CoTaskMemFree(pName);
00302 }
00303 }
00304 }
00305
00306 if(cStreams > 0) popup.AppendMenu(MF_SEPARATOR);
00307 }
00308
00309 int i;
00310
00311 TCHAR* str;
00312 for(i = 0; str = CallPPage(m_tbid->graph, i, (HWND)INVALID_HANDLE_VALUE); i++)
00313 {
00314 if(_tcsncmp(str, _T("DivX MPEG"), 9) || m_tbid->fRunOnce)
00315 popup.AppendMenu(MF_ENABLED|MF_STRING|MF_UNCHECKED, (1<<14)|(i), str);
00316
00317 delete [] str;
00318 }
00319
00320 SetForegroundWindow();
00321 UINT id = popup.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, CWnd::FromHandle(hWnd), 0);
00322 PostMessage(WM_NULL);
00323
00324 if(id & (1<<15))
00325 {
00326 pStreams[(id>>8)&0x3f]->Enable(id&0xff, AMSTREAMSELECTENABLE_ENABLE);
00327 }
00328 else if(id & (1<<14))
00329 {
00330 if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
00331 {
00332 HWND hwnd;
00333 if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
00334 || SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
00335 hWnd = hwnd;
00336 }
00337
00338 CallPPage(m_tbid->graph, id&0xff, hWnd);
00339 }
00340 }
00341 break;
00342
00343 default:
00344 break;
00345 }
00346
00347 return 0;
00348 }
00349
00350
00351
00352 DWORD CALLBACK SystrayThreadProc(void* pParam)
00353 {
00354 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00355
00356 CSystrayWindow wnd((SystrayIconData*)pParam);
00357 if(!wnd.CreateEx(0, AfxRegisterWndClass(0), _T("DVSWND"), WS_OVERLAPPED, CRect(0, 0, 0, 0), NULL, 0, NULL))
00358 return -1;
00359
00360 ((SystrayIconData*)pParam)->hSystrayWnd = wnd.m_hWnd;
00361
00362 MSG msg;
00363 while(GetMessage(&msg, NULL, 0, 0))
00364 {
00365 TranslateMessage(&msg);
00366 DispatchMessage(&msg);
00367 }
00368
00369 return 0;
00370 }
00371
00372
00373
00374
00375 static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd)
00376 {
00377 int i = 0;
00378 bool fFound = false;
00379
00380 WCHAR* wstr = NULL;
00381 CComPtr<IBaseFilter> pFilter;
00382 CAUUID caGUID;
00383 caGUID.pElems = NULL;
00384
00385 BeginEnumFilters(pGraph, pEF, pBF)
00386 {
00387 CComQIPtr<ISpecifyPropertyPages> pSPS = pBF;
00388 if(!pSPS) continue;
00389
00390 if(i == idx)
00391 {
00392 pFilter = pBF;
00393 pSPS->GetPages(&caGUID);
00394 wstr = _wcsdup(CStringW(GetFilterName(pBF)));
00395 break;
00396 }
00397
00398 i++;
00399 }
00400 EndEnumFilters
00401
00402 TCHAR* ret = NULL;
00403
00404 if(pFilter)
00405 {
00406 if(hWnd != INVALID_HANDLE_VALUE)
00407 {
00408 ShowPPage(pFilter, hWnd);
00409 }
00410 else
00411 {
00412 if(ret = new TCHAR[wcslen(wstr)+1])
00413 _tcscpy(ret, CString(wstr));
00414 }
00415 }
00416
00417 if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
00418 if(wstr) free(wstr);
00419
00420 return(ret);
00421 }