]> git.sesse.net Git - vlc/blob - activex/oleobject.cpp
* modules/audio_output/directx.c: backported directx audio output fix from trunk...
[vlc] / activex / oleobject.cpp
1 /*****************************************************************************
2  * oleobject.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 #include "plugin.h"
24 #include "oleobject.h"
25
26 #include "utils.h"
27
28 #include <docobj.h>
29
30 using namespace std;
31
32 VLCOleObject::VLCOleObject(VLCPlugin *p_instance) :
33 _p_clientsite(NULL), _p_instance(p_instance) 
34 {
35     CreateOleAdviseHolder(&_p_advise_holder);
36 };
37
38 VLCOleObject::~VLCOleObject()
39 {
40     SetClientSite(NULL);
41     Close(OLECLOSE_NOSAVE);
42     _p_advise_holder->Release();
43 };
44
45 STDMETHODIMP VLCOleObject::Advise(IAdviseSink *pAdvSink, DWORD *dwConnection)
46 {
47     return _p_advise_holder->Advise(pAdvSink, dwConnection);
48 };
49
50 STDMETHODIMP VLCOleObject::Close(DWORD dwSaveOption)
51 {
52     if( _p_instance->isRunning() )
53     {
54         _p_advise_holder->SendOnClose();
55         return _p_instance->onClose(dwSaveOption);
56     }
57     return S_OK;
58 };
59
60 STDMETHODIMP VLCOleObject::DoVerb(LONG iVerb, LPMSG lpMsg, LPOLECLIENTSITE pActiveSite,
61                                     LONG lIndex, HWND hwndParent, LPCRECT lprcPosRect)
62 {
63     switch( iVerb )
64     {
65         case OLEIVERB_PRIMARY:
66         case OLEIVERB_SHOW:
67         case OLEIVERB_OPEN:
68             // force control to be visible when activating in place
69             _p_instance->setVisible(TRUE);
70         case OLEIVERB_INPLACEACTIVATE:
71             return doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
72
73         case OLEIVERB_HIDE:
74             _p_instance->setVisible(FALSE);
75             return S_OK;
76
77         case OLEIVERB_UIACTIVATE:
78             return doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
79
80         case OLEIVERB_DISCARDUNDOSTATE:
81             return S_OK;
82
83         default:
84             if( iVerb > 0 ) {
85                 _p_instance->setVisible(TRUE);
86                 doInPlaceActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
87                 return OLEOBJ_S_INVALIDVERB;
88             }
89             return E_NOTIMPL;
90     }
91 };
92
93 HRESULT VLCOleObject::doInPlaceActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
94 {
95     RECT posRect;
96     RECT clipRect;
97     LPCRECT lprcClipRect = lprcPosRect;
98
99     if( NULL != pActiveSite )
100     {
101         // check if already activated
102         if( _p_instance->isInPlaceActive() )
103         {
104             // just attempt to show object then
105             if( _p_instance->getVisible() )
106                 pActiveSite->ShowObject();
107             return S_OK;
108         }
109
110         LPOLEINPLACESITE p_inPlaceSite;
111
112         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
113         {
114             if( S_OK != p_inPlaceSite->CanInPlaceActivate() )
115             {
116                 return OLEOBJ_S_CANNOT_DOVERB_NOW;
117             }
118
119             LPOLEINPLACEFRAME p_inPlaceFrame;
120             LPOLEINPLACEUIWINDOW p_inPlaceUIWindow;
121             OLEINPLACEFRAMEINFO oleFrameInfo;
122
123             oleFrameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
124             if( SUCCEEDED(p_inPlaceSite->GetWindowContext(&p_inPlaceFrame, &p_inPlaceUIWindow, &posRect, &clipRect, &oleFrameInfo)) )
125             {
126                 lprcPosRect = &posRect;
127                 lprcClipRect = &clipRect;
128
129                 if( NULL != p_inPlaceFrame )
130                     p_inPlaceFrame->Release();
131                 if( NULL != p_inPlaceUIWindow )
132                     p_inPlaceUIWindow->Release();
133             }
134
135             if( (NULL == hwndParent) && FAILED(p_inPlaceSite->GetWindow(&hwndParent)) )
136             {
137                 p_inPlaceSite->Release();
138                 return OLEOBJ_S_INVALIDHWND;
139             }
140         }
141         else if( NULL == hwndParent )
142         {
143             return OLEOBJ_S_INVALIDHWND;
144         }
145         else if( NULL == lprcPosRect )
146         {
147             SetRect(&posRect, 0, 0, 0, 0);
148             lprcPosRect = &posRect;
149             lprcClipRect = &posRect;
150         }
151
152         if( FAILED(_p_instance->onActivateInPlace(lpMsg, hwndParent, lprcPosRect, lprcClipRect)) )
153         {
154             if( NULL != p_inPlaceSite )
155                 p_inPlaceSite->Release();
156             return OLEOBJ_S_CANNOT_DOVERB_NOW;
157         }
158
159         if( NULL != p_inPlaceSite )
160         {
161             p_inPlaceSite->OnInPlaceActivate();
162             p_inPlaceSite->OnPosRectChange(lprcPosRect);
163             p_inPlaceSite->Release();
164         }
165
166         pActiveSite->ShowObject();
167         _p_instance->setVisible(TRUE);
168
169         if( NULL != lpMsg )
170         {
171             switch( lpMsg->message )
172             {
173                 case WM_LBUTTONDOWN:
174                 case WM_LBUTTONDBLCLK:
175                     doUIActivate(lpMsg, pActiveSite, hwndParent, lprcPosRect);
176                     break;
177                 default:
178                     break;
179             }
180         }
181         return S_OK;
182     }
183     return OLEOBJ_S_CANNOT_DOVERB_NOW;
184 };
185
186 HRESULT VLCOleObject::doUIActivate(LPMSG lpMsg, LPOLECLIENTSITE pActiveSite, HWND hwndParent, LPCRECT lprcPosRect)
187 {
188     if( NULL != pActiveSite )
189     {
190         // check if already activated
191         if( ! _p_instance->isInPlaceActive() )
192             return OLE_E_NOT_INPLACEACTIVE;
193
194         LPOLEINPLACESITE p_inPlaceSite;
195
196         if( SUCCEEDED(pActiveSite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
197         {
198             p_inPlaceSite->OnUIActivate();
199
200             if( NULL != lprcPosRect )
201             {
202                 p_inPlaceSite->OnPosRectChange(lprcPosRect);
203             }
204             p_inPlaceSite->Release();
205         }
206
207         pActiveSite->ShowObject();
208         _p_instance->setVisible(TRUE);
209         _p_instance->setFocus(TRUE);
210
211         return S_OK;
212     }
213     return E_FAIL;
214 };
215
216 STDMETHODIMP VLCOleObject::EnumAdvise(IEnumSTATDATA **ppEnumAdvise)
217 {
218     return _p_advise_holder->EnumAdvise(ppEnumAdvise);
219 };
220
221 STDMETHODIMP VLCOleObject::EnumVerbs(IEnumOleVerb **ppEnumOleVerb)
222 {
223     return OleRegEnumVerbs(_p_instance->getClassID(),
224         ppEnumOleVerb);
225 };
226
227 STDMETHODIMP VLCOleObject::GetClientSite(LPOLECLIENTSITE *ppClientSite)
228 {
229     if( NULL == ppClientSite )
230         return E_POINTER;
231  
232     if( NULL != _p_clientsite )
233         _p_clientsite->AddRef(); 
234
235     *ppClientSite = _p_clientsite;
236     return S_OK;
237 };
238
239 STDMETHODIMP VLCOleObject::GetClipboardData(DWORD dwReserved, LPDATAOBJECT *ppDataObject)
240 {
241     return _p_instance->pUnkOuter->QueryInterface(IID_IDataObject, (void **)ppDataObject);
242 };
243
244 STDMETHODIMP VLCOleObject::GetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
245 {
246     if( NULL == pSizel )
247         return E_POINTER;
248
249     if( dwDrawAspect & DVASPECT_CONTENT )
250     {
251         *pSizel = _p_instance->getExtent();
252         return S_OK;
253     }
254     pSizel->cx= 0L;
255     pSizel->cy= 0L;
256     return E_NOTIMPL;
257 };
258
259 STDMETHODIMP VLCOleObject::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus)
260 {
261     if( NULL == pdwStatus )
262         return E_POINTER;
263
264     switch( dwAspect )
265     {
266         case DVASPECT_CONTENT:
267             *pdwStatus = OLEMISC_RECOMPOSEONRESIZE
268                 | OLEMISC_CANTLINKINSIDE
269                 | OLEMISC_INSIDEOUT
270                 | OLEMISC_ACTIVATEWHENVISIBLE
271                 | OLEMISC_SETCLIENTSITEFIRST;
272             break;
273         default:
274             *pdwStatus = 0;
275     }
276
277     return S_OK;
278 };
279
280 STDMETHODIMP VLCOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppMoniker)
281 {
282     if( NULL != _p_clientsite )
283         return _p_clientsite->GetMoniker(dwAssign,dwWhichMoniker, ppMoniker);
284  
285     return E_UNEXPECTED;
286 };
287
288 STDMETHODIMP VLCOleObject::GetUserClassID(LPCLSID pClsid)
289 {
290     if( NULL == pClsid )
291         return E_POINTER;
292  
293     *pClsid = _p_instance->getClassID(); 
294     return S_OK;
295 };
296
297 STDMETHODIMP VLCOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType)
298 {
299     return OleRegGetUserType(_p_instance->getClassID(),
300         dwFormOfType, pszUserType);
301 };
302
303 STDMETHODIMP VLCOleObject::InitFromData(LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
304 {
305     return E_NOTIMPL;
306 };
307
308 STDMETHODIMP VLCOleObject::IsUpToDate(void)
309 {
310     return S_OK;
311 };
312
313 STDMETHODIMP VLCOleObject::SetClientSite(LPOLECLIENTSITE pClientSite)
314 {
315     if( NULL != _p_clientsite )
316         _p_clientsite->Release();
317
318     _p_clientsite = pClientSite;
319
320     if( NULL != pClientSite )
321     {
322         pClientSite->AddRef();
323         _p_instance->onAmbientChanged(pClientSite, DISPID_UNKNOWN);
324     }
325     return S_OK;
326 };
327
328 STDMETHODIMP VLCOleObject::SetColorScheme(LOGPALETTE *pLogpal)
329 {
330     return E_NOTIMPL;
331 };
332
333 STDMETHODIMP VLCOleObject::SetExtent(DWORD dwDrawAspect, SIZEL *pSizel)
334 {
335     if( NULL == pSizel )
336         return E_POINTER;
337
338
339     if( dwDrawAspect & DVASPECT_CONTENT )
340     {
341         _p_instance->setExtent(*pSizel);
342
343         if( _p_instance->isInPlaceActive() )
344         {
345             LPOLEINPLACESITE p_inPlaceSite;
346
347             if( SUCCEEDED(_p_clientsite->QueryInterface(IID_IOleInPlaceSite, (void**)&p_inPlaceSite)) )
348             {
349                 HWND hwnd;
350
351                 if( SUCCEEDED(p_inPlaceSite->GetWindow(&hwnd)) )
352                 {
353                     // use HIMETRIC to pixel transform 
354                     RECT posRect = _p_instance->getPosRect();
355                     HDC hDC = GetDC(hwnd);
356                     posRect.right = (pSizel->cx*GetDeviceCaps(hDC, LOGPIXELSX)/2540L)+posRect.left;
357                     posRect.bottom = (pSizel->cy*GetDeviceCaps(hDC, LOGPIXELSY)/2540L)+posRect.top;
358                     DeleteDC(hDC);
359                     p_inPlaceSite->OnPosRectChange(&posRect);
360                 }
361                 p_inPlaceSite->Release();
362             }
363         }
364         return S_OK;
365     }
366     return E_NOTIMPL;
367 };
368
369 STDMETHODIMP VLCOleObject::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
370 {
371     return S_OK;
372 };
373
374 STDMETHODIMP VLCOleObject::SetMoniker(DWORD dwWhichMoniker, LPMONIKER pMoniker)
375 {
376     return _p_advise_holder->SendOnRename(pMoniker);
377 };
378
379 STDMETHODIMP VLCOleObject::Unadvise(DWORD dwConnection)
380 {
381     return _p_advise_holder->Unadvise(dwConnection);
382 };
383
384 STDMETHODIMP VLCOleObject::Update(void)
385 {
386     return S_OK;
387 };
388