Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiltergraph.c
Go to the documentation of this file.
00001 /* DirectShow FilterGraph object (QUARTZ.DLL) 00002 * 00003 * Copyright 2002 Lionel Ulmer 00004 * Copyright 2004 Christian Costa 00005 * 00006 * This file contains the (internal) driver registration functions, 00007 * driver enumeration APIs and DirectDraw creation functions. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 #include "config.h" 00025 #include <stdarg.h> 00026 00027 #define COBJMACROS 00028 00029 #include "windef.h" 00030 #include "winbase.h" 00031 #include "winuser.h" 00032 #include "winreg.h" 00033 #include "shlwapi.h" 00034 #include "dshow.h" 00035 #include "wine/debug.h" 00036 #include "quartz_private.h" 00037 #include "ole2.h" 00038 #include "olectl.h" 00039 #include "strmif.h" 00040 #include "vfwmsgs.h" 00041 #include "evcode.h" 00042 #include "wine/unicode.h" 00043 00044 00045 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 00046 00047 typedef struct { 00048 HWND hWnd; /* Target window */ 00049 UINT msg; /* User window message */ 00050 LONG_PTR instance; /* User data */ 00051 int disabled; /* Disabled messages posting */ 00052 } WndNotify; 00053 00054 typedef struct { 00055 LONG lEventCode; /* Event code */ 00056 LONG_PTR lParam1; /* Param1 */ 00057 LONG_PTR lParam2; /* Param2 */ 00058 } Event; 00059 00060 /* messages ring implementation for queuing events (taken from winmm) */ 00061 #define EVENTS_RING_BUFFER_INCREMENT 64 00062 typedef struct { 00063 Event* messages; 00064 int ring_buffer_size; 00065 int msg_tosave; 00066 int msg_toget; 00067 CRITICAL_SECTION msg_crst; 00068 HANDLE msg_event; /* Signaled for no empty queue */ 00069 } EventsQueue; 00070 00071 static int EventsQueue_Init(EventsQueue* omr) 00072 { 00073 omr->msg_toget = 0; 00074 omr->msg_tosave = 0; 00075 omr->msg_event = CreateEventW(NULL, TRUE, FALSE, NULL); 00076 omr->ring_buffer_size = EVENTS_RING_BUFFER_INCREMENT; 00077 omr->messages = CoTaskMemAlloc(omr->ring_buffer_size * sizeof(Event)); 00078 ZeroMemory(omr->messages, omr->ring_buffer_size * sizeof(Event)); 00079 00080 InitializeCriticalSection(&omr->msg_crst); 00081 omr->msg_crst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": EventsQueue.msg_crst"); 00082 return TRUE; 00083 } 00084 00085 static int EventsQueue_Destroy(EventsQueue* omr) 00086 { 00087 CloseHandle(omr->msg_event); 00088 CoTaskMemFree(omr->messages); 00089 omr->msg_crst.DebugInfo->Spare[0] = 0; 00090 DeleteCriticalSection(&omr->msg_crst); 00091 return TRUE; 00092 } 00093 00094 static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt) 00095 { 00096 EnterCriticalSection(&omr->msg_crst); 00097 if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))) 00098 { 00099 int old_ring_buffer_size = omr->ring_buffer_size; 00100 omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT; 00101 TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size); 00102 omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event)); 00103 /* Now we need to rearrange the ring buffer so that the new 00104 buffers just allocated are in between omr->msg_tosave and 00105 omr->msg_toget. 00106 */ 00107 if (omr->msg_tosave < omr->msg_toget) 00108 { 00109 memmove(&(omr->messages[omr->msg_toget + EVENTS_RING_BUFFER_INCREMENT]), 00110 &(omr->messages[omr->msg_toget]), 00111 sizeof(Event)*(old_ring_buffer_size - omr->msg_toget) 00112 ); 00113 omr->msg_toget += EVENTS_RING_BUFFER_INCREMENT; 00114 } 00115 } 00116 omr->messages[omr->msg_tosave] = *evt; 00117 SetEvent(omr->msg_event); 00118 omr->msg_tosave = (omr->msg_tosave + 1) % omr->ring_buffer_size; 00119 LeaveCriticalSection(&omr->msg_crst); 00120 return TRUE; 00121 } 00122 00123 static int EventsQueue_GetEvent(EventsQueue* omr, Event* evt, LONG msTimeOut) 00124 { 00125 if (WaitForSingleObject(omr->msg_event, msTimeOut) != WAIT_OBJECT_0) 00126 return FALSE; 00127 00128 EnterCriticalSection(&omr->msg_crst); 00129 00130 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */ 00131 { 00132 LeaveCriticalSection(&omr->msg_crst); 00133 return FALSE; 00134 } 00135 00136 *evt = omr->messages[omr->msg_toget]; 00137 omr->msg_toget = (omr->msg_toget + 1) % omr->ring_buffer_size; 00138 00139 /* Mark the buffer as empty if needed */ 00140 if (omr->msg_toget == omr->msg_tosave) /* buffer empty ? */ 00141 ResetEvent(omr->msg_event); 00142 00143 LeaveCriticalSection(&omr->msg_crst); 00144 return TRUE; 00145 } 00146 00147 #define MAX_ITF_CACHE_ENTRIES 3 00148 typedef struct _ITF_CACHE_ENTRY { 00149 const IID* riid; 00150 IBaseFilter* filter; 00151 IUnknown* iface; 00152 } ITF_CACHE_ENTRY; 00153 00154 typedef struct _IFilterGraphImpl { 00155 const IFilterGraph2Vtbl *IFilterGraph2_vtbl; 00156 const IMediaControlVtbl *IMediaControl_vtbl; 00157 const IMediaSeekingVtbl *IMediaSeeking_vtbl; 00158 const IBasicAudioVtbl *IBasicAudio_vtbl; 00159 const IBasicVideo2Vtbl *IBasicVideo_vtbl; 00160 const IVideoWindowVtbl *IVideoWindow_vtbl; 00161 const IMediaEventExVtbl *IMediaEventEx_vtbl; 00162 const IMediaFilterVtbl *IMediaFilter_vtbl; 00163 const IMediaEventSinkVtbl *IMediaEventSink_vtbl; 00164 const IGraphConfigVtbl *IGraphConfig_vtbl; 00165 const IMediaPositionVtbl *IMediaPosition_vtbl; 00166 const IUnknownVtbl * IInner_vtbl; 00167 /* IAMGraphStreams */ 00168 /* IAMStats */ 00169 /* IFilterChain */ 00170 /* IFilterMapper2 */ 00171 /* IGraphVersion */ 00172 /* IQueueCommand */ 00173 /* IRegisterServiceProvider */ 00174 /* IResourceMananger */ 00175 /* IServiceProvider */ 00176 /* IVideoFrameStep */ 00177 00178 LONG ref; 00179 IUnknown *punkFilterMapper2; 00180 IFilterMapper2 * pFilterMapper2; 00181 IBaseFilter ** ppFiltersInGraph; 00182 LPWSTR * pFilterNames; 00183 int nFilters; 00184 int filterCapacity; 00185 LONG nameIndex; 00186 IReferenceClock *refClock; 00187 EventsQueue evqueue; 00188 HANDLE hEventCompletion; 00189 int CompletionStatus; 00190 WndNotify notif; 00191 int nRenderers; 00192 int EcCompleteCount; 00193 int HandleEcComplete; 00194 int HandleEcRepaint; 00195 int HandleEcClockChanged; 00196 OAFilterState state; 00197 CRITICAL_SECTION cs; 00198 ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES]; 00199 int nItfCacheEntries; 00200 IUnknown * pUnkOuter; 00201 BOOL bUnkOuterValid; 00202 BOOL bAggregatable; 00203 GUID timeformatseek; 00204 LONGLONG start_time; 00205 LONGLONG position; 00206 LONGLONG stop_position; 00207 LONG recursioncount; 00208 } IFilterGraphImpl; 00209 00210 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This, 00211 REFIID riid, LPVOID * ppv); 00212 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This); 00213 static ULONG Filtergraph_Release(IFilterGraphImpl *This); 00214 00215 static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface, 00216 REFIID riid, 00217 LPVOID *ppvObj) { 00218 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); 00219 TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj); 00220 00221 if (This->bAggregatable) 00222 This->bUnkOuterValid = TRUE; 00223 00224 if (IsEqualGUID(&IID_IUnknown, riid)) { 00225 *ppvObj = &(This->IInner_vtbl); 00226 TRACE(" returning IUnknown interface (%p)\n", *ppvObj); 00227 } else if (IsEqualGUID(&IID_IFilterGraph, riid) || 00228 IsEqualGUID(&IID_IFilterGraph2, riid) || 00229 IsEqualGUID(&IID_IGraphBuilder, riid)) { 00230 *ppvObj = &(This->IFilterGraph2_vtbl); 00231 TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj); 00232 } else if (IsEqualGUID(&IID_IMediaControl, riid)) { 00233 *ppvObj = &(This->IMediaControl_vtbl); 00234 TRACE(" returning IMediaControl interface (%p)\n", *ppvObj); 00235 } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) { 00236 *ppvObj = &(This->IMediaSeeking_vtbl); 00237 TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj); 00238 } else if (IsEqualGUID(&IID_IBasicAudio, riid)) { 00239 *ppvObj = &(This->IBasicAudio_vtbl); 00240 TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj); 00241 } else if (IsEqualGUID(&IID_IBasicVideo, riid) || 00242 IsEqualGUID(&IID_IBasicVideo2, riid)) { 00243 *ppvObj = &(This->IBasicVideo_vtbl); 00244 TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj); 00245 } else if (IsEqualGUID(&IID_IVideoWindow, riid)) { 00246 *ppvObj = &(This->IVideoWindow_vtbl); 00247 TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj); 00248 } else if (IsEqualGUID(&IID_IMediaEvent, riid) || 00249 IsEqualGUID(&IID_IMediaEventEx, riid)) { 00250 *ppvObj = &(This->IMediaEventEx_vtbl); 00251 TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj); 00252 } else if (IsEqualGUID(&IID_IMediaFilter, riid) || 00253 IsEqualGUID(&IID_IPersist, riid)) { 00254 *ppvObj = &(This->IMediaFilter_vtbl); 00255 TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj); 00256 } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) { 00257 *ppvObj = &(This->IMediaEventSink_vtbl); 00258 TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj); 00259 } else if (IsEqualGUID(&IID_IGraphConfig, riid)) { 00260 *ppvObj = &(This->IGraphConfig_vtbl); 00261 TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj); 00262 } else if (IsEqualGUID(&IID_IMediaPosition, riid)) { 00263 *ppvObj = &(This->IMediaPosition_vtbl); 00264 TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj); 00265 } else if (IsEqualGUID(&IID_IFilterMapper, riid)) { 00266 TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj); 00267 return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj); 00268 } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) { 00269 *ppvObj = This->pFilterMapper2; 00270 TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj); 00271 } else { 00272 *ppvObj = NULL; 00273 FIXME("unknown interface %s\n", debugstr_guid(riid)); 00274 return E_NOINTERFACE; 00275 } 00276 00277 IUnknown_AddRef((IUnknown *)(*ppvObj)); 00278 return S_OK; 00279 } 00280 00281 static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) { 00282 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); 00283 ULONG ref = InterlockedIncrement(&This->ref); 00284 00285 TRACE("(%p)->(): new ref = %d\n", This, ref); 00286 00287 return ref; 00288 } 00289 00290 static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) 00291 { 00292 ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); 00293 ULONG ref = InterlockedDecrement(&This->ref); 00294 00295 TRACE("(%p)->(): new ref = %d\n", This, ref); 00296 00297 if (ref == 0) { 00298 int i; 00299 00300 This->ref = 1; /* guard against reentrancy (aggregation). */ 00301 00302 IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl)); 00303 00304 while (This->nFilters) 00305 IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]); 00306 00307 if (This->refClock) 00308 IReferenceClock_Release(This->refClock); 00309 00310 for (i = 0; i < This->nItfCacheEntries; i++) 00311 { 00312 if (This->ItfCacheEntries[i].iface) 00313 IUnknown_Release(This->ItfCacheEntries[i].iface); 00314 } 00315 00316 /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 interface below. 00317 00318 * NOTE: Filtergraph_AddRef isn't suitable, because bUnkOuterValid may be FALSE but punkOuter non-NULL 00319 * and already passed as punkOuter to filtermapper in FilterGraph_create - this will happen in case of 00320 * CoCreateInstance of filtergraph with non-null pUnkOuter and REFIID other than IID_Unknown that is 00321 * cleaning up after error. */ 00322 if (This->pUnkOuter) IUnknown_AddRef(This->pUnkOuter); 00323 else IUnknown_AddRef((IUnknown*)&This->IInner_vtbl); 00324 00325 IFilterMapper2_Release(This->pFilterMapper2); 00326 IUnknown_Release(This->punkFilterMapper2); 00327 00328 CloseHandle(This->hEventCompletion); 00329 EventsQueue_Destroy(&This->evqueue); 00330 This->cs.DebugInfo->Spare[0] = 0; 00331 DeleteCriticalSection(&This->cs); 00332 CoTaskMemFree(This->ppFiltersInGraph); 00333 CoTaskMemFree(This->pFilterNames); 00334 CoTaskMemFree(This); 00335 } 00336 return ref; 00337 } 00338 00339 00340 /*** IUnknown methods ***/ 00341 static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, 00342 REFIID riid, 00343 LPVOID*ppvObj) { 00344 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00345 00346 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 00347 return Filtergraph_QueryInterface(This, riid, ppvObj); 00348 } 00349 00350 static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) { 00351 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00352 00353 TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface); 00354 00355 return Filtergraph_AddRef(This); 00356 } 00357 00358 static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) { 00359 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00360 00361 TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface); 00362 00363 return Filtergraph_Release(This); 00364 } 00365 00366 /*** IFilterGraph methods ***/ 00367 static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, 00368 IBaseFilter *pFilter, 00369 LPCWSTR pName) { 00370 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00371 HRESULT hr; 00372 int i,j; 00373 WCHAR* wszFilterName = NULL; 00374 int duplicate_name = FALSE; 00375 00376 TRACE("(%p/%p)->(%p, %s (%p))\n", This, iface, pFilter, debugstr_w(pName), pName); 00377 00378 if (!pFilter) 00379 return E_POINTER; 00380 00381 wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) ); 00382 00383 if (pName) 00384 { 00385 /* Check if name already exists */ 00386 for(i = 0; i < This->nFilters; i++) 00387 if (!strcmpW(This->pFilterNames[i], pName)) 00388 { 00389 duplicate_name = TRUE; 00390 break; 00391 } 00392 } 00393 00394 /* If no name given or name already existing, generate one */ 00395 if (!pName || duplicate_name) 00396 { 00397 static const WCHAR wszFmt1[] = {'%','s',' ','%','0','4','d',0}; 00398 static const WCHAR wszFmt2[] = {'%','0','4','d',0}; 00399 00400 for (j = 0; j < 10000 ; j++) 00401 { 00402 /* Create name */ 00403 if (pName) 00404 sprintfW(wszFilterName, wszFmt1, pName, This->nameIndex); 00405 else 00406 sprintfW(wszFilterName, wszFmt2, This->nameIndex); 00407 TRACE("Generated name %s\n", debugstr_w(wszFilterName)); 00408 00409 /* Check if the generated name already exists */ 00410 for(i = 0; i < This->nFilters; i++) 00411 if (!strcmpW(This->pFilterNames[i], wszFilterName)) 00412 break; 00413 00414 /* Compute next index and exit if generated name is suitable */ 00415 if (This->nameIndex++ == 10000) 00416 This->nameIndex = 1; 00417 if (i == This->nFilters) 00418 break; 00419 } 00420 /* Unable to find a suitable name */ 00421 if (j == 10000) 00422 { 00423 CoTaskMemFree(wszFilterName); 00424 return VFW_E_DUPLICATE_NAME; 00425 } 00426 } 00427 else 00428 memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR)); 00429 00430 if (This->nFilters + 1 > This->filterCapacity) 00431 { 00432 int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1; 00433 IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*)); 00434 LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR)); 00435 memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*)); 00436 memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR)); 00437 if (This->filterCapacity) 00438 { 00439 CoTaskMemFree(This->ppFiltersInGraph); 00440 CoTaskMemFree(This->pFilterNames); 00441 } 00442 This->ppFiltersInGraph = ppNewFilters; 00443 This->pFilterNames = pNewNames; 00444 This->filterCapacity = newCapacity; 00445 } 00446 00447 hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)This, wszFilterName); 00448 00449 if (SUCCEEDED(hr)) 00450 { 00451 IBaseFilter_AddRef(pFilter); 00452 This->ppFiltersInGraph[This->nFilters] = pFilter; 00453 This->pFilterNames[This->nFilters] = wszFilterName; 00454 This->nFilters++; 00455 IBaseFilter_SetSyncSource(pFilter, This->refClock); 00456 } 00457 else 00458 CoTaskMemFree(wszFilterName); 00459 00460 if (SUCCEEDED(hr) && duplicate_name) 00461 return VFW_S_DUPLICATE_NAME; 00462 00463 return hr; 00464 } 00465 00466 static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter) 00467 { 00468 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00469 int i; 00470 HRESULT hr = E_FAIL; 00471 00472 TRACE("(%p/%p)->(%p)\n", This, iface, pFilter); 00473 00474 /* FIXME: check graph is stopped */ 00475 00476 for (i = 0; i < This->nFilters; i++) 00477 { 00478 if (This->ppFiltersInGraph[i] == pFilter) 00479 { 00480 IEnumPins *penumpins = NULL; 00481 FILTER_STATE state; 00482 00483 TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i])); 00484 IBaseFilter_GetState(pFilter, 0, &state); 00485 if (state == State_Running) 00486 IBaseFilter_Pause(pFilter); 00487 if (state != State_Stopped) 00488 IBaseFilter_Stop(pFilter); 00489 00490 hr = IBaseFilter_EnumPins(pFilter, &penumpins); 00491 if (SUCCEEDED(hr)) { 00492 IPin *ppin; 00493 while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) 00494 { 00495 IPin *victim = NULL; 00496 HRESULT h; 00497 IPin_ConnectedTo(ppin, &victim); 00498 if (victim) 00499 { 00500 h = IPin_Disconnect(victim); 00501 TRACE("Disconnect other side: %08x\n", h); 00502 if (h == VFW_E_NOT_STOPPED) 00503 { 00504 PIN_INFO pinfo; 00505 IPin_QueryPinInfo(victim, &pinfo); 00506 00507 IBaseFilter_GetState(pinfo.pFilter, 0, &state); 00508 if (state == State_Running) 00509 IBaseFilter_Pause(pinfo.pFilter); 00510 IBaseFilter_Stop(pinfo.pFilter); 00511 IBaseFilter_Release(pinfo.pFilter); 00512 h = IPin_Disconnect(victim); 00513 TRACE("Disconnect retry: %08x\n", h); 00514 } 00515 IPin_Release(victim); 00516 } 00517 h = IPin_Disconnect(ppin); 00518 TRACE("Disconnect 2: %08x\n", h); 00519 00520 IPin_Release(ppin); 00521 } 00522 IEnumPins_Release(penumpins); 00523 } 00524 00525 hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]); 00526 if (SUCCEEDED(hr)) 00527 { 00528 IBaseFilter_SetSyncSource(pFilter, NULL); 00529 IBaseFilter_Release(pFilter); 00530 CoTaskMemFree(This->pFilterNames[i]); 00531 memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i)); 00532 memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i)); 00533 This->nFilters--; 00534 /* Invalidate interfaces in the cache */ 00535 for (i = 0; i < This->nItfCacheEntries; i++) 00536 if (pFilter == This->ItfCacheEntries[i].filter) 00537 { 00538 IUnknown_Release(This->ItfCacheEntries[i].iface); 00539 This->ItfCacheEntries[i].iface = NULL; 00540 This->ItfCacheEntries[i].filter = NULL; 00541 } 00542 return S_OK; 00543 } 00544 break; 00545 } 00546 } 00547 00548 return hr; /* FIXME: check this error code */ 00549 } 00550 00551 static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, 00552 IEnumFilters **ppEnum) { 00553 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00554 00555 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); 00556 00557 return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum); 00558 } 00559 00560 static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, 00561 LPCWSTR pName, 00562 IBaseFilter **ppFilter) { 00563 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00564 int i; 00565 00566 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter); 00567 00568 if (!ppFilter) 00569 return E_POINTER; 00570 00571 for (i = 0; i < This->nFilters; i++) 00572 { 00573 if (!strcmpW(pName, This->pFilterNames[i])) 00574 { 00575 *ppFilter = This->ppFiltersInGraph[i]; 00576 IBaseFilter_AddRef(*ppFilter); 00577 return S_OK; 00578 } 00579 } 00580 00581 *ppFilter = NULL; 00582 return VFW_E_NOT_FOUND; 00583 } 00584 00585 /* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case. 00586 * A circular connection will be formed if from the filter of the output pin, the input pin can be reached 00587 */ 00588 static HRESULT CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in) 00589 { 00590 #if 1 00591 HRESULT hr; 00592 PIN_INFO info_out, info_in; 00593 00594 hr = IPin_QueryPinInfo(out, &info_out); 00595 if (FAILED(hr)) 00596 return hr; 00597 if (info_out.dir != PINDIR_OUTPUT) 00598 { 00599 IBaseFilter_Release(info_out.pFilter); 00600 return E_UNEXPECTED; 00601 } 00602 00603 hr = IPin_QueryPinInfo(in, &info_in); 00604 if (SUCCEEDED(hr)) 00605 IBaseFilter_Release(info_in.pFilter); 00606 if (FAILED(hr)) 00607 goto out; 00608 if (info_in.dir != PINDIR_INPUT) 00609 { 00610 hr = E_UNEXPECTED; 00611 goto out; 00612 } 00613 00614 if (info_out.pFilter == info_in.pFilter) 00615 hr = VFW_E_CIRCULAR_GRAPH; 00616 else 00617 { 00618 IEnumPins *enumpins; 00619 IPin *test; 00620 00621 hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins); 00622 if (FAILED(hr)) 00623 goto out; 00624 00625 IEnumPins_Reset(enumpins); 00626 while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK) 00627 { 00628 PIN_DIRECTION dir = PINDIR_OUTPUT; 00629 IPin_QueryDirection(test, &dir); 00630 if (dir == PINDIR_INPUT) 00631 { 00632 IPin *victim = NULL; 00633 IPin_ConnectedTo(test, &victim); 00634 if (victim) 00635 { 00636 hr = CheckCircularConnection(This, victim, in); 00637 IPin_Release(victim); 00638 if (FAILED(hr)) 00639 { 00640 IPin_Release(test); 00641 break; 00642 } 00643 } 00644 } 00645 IPin_Release(test); 00646 } 00647 IEnumPins_Release(enumpins); 00648 } 00649 00650 out: 00651 IBaseFilter_Release(info_out.pFilter); 00652 if (FAILED(hr)) 00653 ERR("Checking filtergraph returned %08x, something's not right!\n", hr); 00654 return hr; 00655 #else 00656 /* Debugging filtergraphs not enabled */ 00657 return S_OK; 00658 #endif 00659 } 00660 00661 00662 /* NOTE: despite the implication, it doesn't matter which 00663 * way round you put in the input and output pins */ 00664 static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, 00665 IPin *ppinIn, 00666 IPin *ppinOut, 00667 const AM_MEDIA_TYPE *pmt) { 00668 PIN_DIRECTION dir; 00669 HRESULT hr; 00670 00671 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00672 00673 TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt); 00674 00675 /* FIXME: check pins are in graph */ 00676 00677 if (TRACE_ON(quartz)) 00678 { 00679 PIN_INFO PinInfo; 00680 00681 hr = IPin_QueryPinInfo(ppinIn, &PinInfo); 00682 if (FAILED(hr)) 00683 return hr; 00684 00685 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter); 00686 IBaseFilter_Release(PinInfo.pFilter); 00687 00688 hr = IPin_QueryPinInfo(ppinOut, &PinInfo); 00689 if (FAILED(hr)) 00690 return hr; 00691 00692 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter); 00693 IBaseFilter_Release(PinInfo.pFilter); 00694 } 00695 00696 hr = IPin_QueryDirection(ppinIn, &dir); 00697 if (SUCCEEDED(hr)) 00698 { 00699 if (dir == PINDIR_INPUT) 00700 { 00701 hr = CheckCircularConnection(This, ppinOut, ppinIn); 00702 if (SUCCEEDED(hr)) 00703 hr = IPin_Connect(ppinOut, ppinIn, pmt); 00704 } 00705 else 00706 { 00707 hr = CheckCircularConnection(This, ppinIn, ppinOut); 00708 if (SUCCEEDED(hr)) 00709 hr = IPin_Connect(ppinIn, ppinOut, pmt); 00710 } 00711 } 00712 00713 return hr; 00714 } 00715 00716 static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, 00717 IPin *ppin) { 00718 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00719 IPin *pConnectedTo = NULL; 00720 HRESULT hr; 00721 PIN_DIRECTION pindir; 00722 00723 IPin_QueryDirection(ppin, &pindir); 00724 hr = IPin_ConnectedTo(ppin, &pConnectedTo); 00725 if (FAILED(hr)) { 00726 TRACE("Querying connected to failed: %x\n", hr); 00727 return hr; 00728 } 00729 IPin_Disconnect(ppin); 00730 IPin_Disconnect(pConnectedTo); 00731 if (pindir == PINDIR_INPUT) 00732 hr = IPin_Connect(pConnectedTo, ppin, NULL); 00733 else 00734 hr = IPin_Connect(ppin, pConnectedTo, NULL); 00735 IPin_Release(pConnectedTo); 00736 if (FAILED(hr)) 00737 WARN("Reconnecting pins failed, pins are not connected now..\n"); 00738 TRACE("(%p->%p) -- %p %p -> %x\n", iface, This, ppin, pConnectedTo, hr); 00739 return hr; 00740 } 00741 00742 static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin) 00743 { 00744 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00745 00746 TRACE("(%p/%p)->(%p)\n", This, iface, ppin); 00747 00748 if (!ppin) 00749 return E_POINTER; 00750 00751 return IPin_Disconnect(ppin); 00752 } 00753 00754 static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) { 00755 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00756 IReferenceClock *pClock = NULL; 00757 HRESULT hr; 00758 00759 TRACE("(%p/%p)->() semi-stub\n", iface, This); 00760 00761 hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock); 00762 00763 if (SUCCEEDED(hr)) 00764 { 00765 hr = IMediaFilter_SetSyncSource((IMediaFilter*)&(This->IMediaFilter_vtbl), pClock); 00766 IReferenceClock_Release(pClock); 00767 } 00768 00769 return hr; 00770 } 00771 00772 static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar) 00773 { 00774 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; 00775 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; 00776 IPropertyBag * pPropBagCat = NULL; 00777 HRESULT hr; 00778 00779 VariantInit(pvar); 00780 00781 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat); 00782 00783 if (SUCCEEDED(hr)) 00784 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL); 00785 00786 if (SUCCEEDED(hr)) 00787 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid); 00788 00789 VariantClear(pvar); 00790 00791 if (SUCCEEDED(hr)) 00792 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL); 00793 00794 if (SUCCEEDED(hr)) 00795 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal))); 00796 00797 if (pPropBagCat) 00798 IPropertyBag_Release(pPropBagCat); 00799 00800 return hr; 00801 } 00802 00803 static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPin*** pppins, ULONG* pnb) 00804 { 00805 HRESULT hr; 00806 ULONG nb = 0; 00807 00808 TRACE("(%p, %p, %p, %p)\n", pfilter, pinputpin, pppins, pnb); 00809 hr = IPin_QueryInternalConnections(pinputpin, NULL, &nb); 00810 if (hr == S_OK) { 00811 /* Rendered input */ 00812 } else if (hr == S_FALSE) { 00813 *pppins = CoTaskMemAlloc(sizeof(IPin*)*nb); 00814 hr = IPin_QueryInternalConnections(pinputpin, *pppins, &nb); 00815 if (hr != S_OK) { 00816 WARN("Error (%x)\n", hr); 00817 } 00818 } else if (hr == E_NOTIMPL) { 00819 /* Input connected to all outputs */ 00820 IEnumPins* penumpins; 00821 IPin* ppin; 00822 int i = 0; 00823 TRACE("E_NOTIMPL\n"); 00824 hr = IBaseFilter_EnumPins(pfilter, &penumpins); 00825 if (FAILED(hr)) { 00826 WARN("filter Enumpins failed (%x)\n", hr); 00827 return hr; 00828 } 00829 i = 0; 00830 /* Count output pins */ 00831 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) { 00832 PIN_DIRECTION pindir; 00833 IPin_QueryDirection(ppin, &pindir); 00834 if (pindir == PINDIR_OUTPUT) 00835 i++; 00836 IPin_Release(ppin); 00837 } 00838 *pppins = CoTaskMemAlloc(sizeof(IPin*)*i); 00839 /* Retrieve output pins */ 00840 IEnumPins_Reset(penumpins); 00841 i = 0; 00842 while(IEnumPins_Next(penumpins, 1, &ppin, &nb) == S_OK) { 00843 PIN_DIRECTION pindir; 00844 IPin_QueryDirection(ppin, &pindir); 00845 if (pindir == PINDIR_OUTPUT) 00846 (*pppins)[i++] = ppin; 00847 else 00848 IPin_Release(ppin); 00849 } 00850 IEnumPins_Release(penumpins); 00851 nb = i; 00852 if (FAILED(hr)) { 00853 WARN("Next failed (%x)\n", hr); 00854 return hr; 00855 } 00856 } else if (FAILED(hr)) { 00857 WARN("Cannot get internal connection (%x)\n", hr); 00858 return hr; 00859 } 00860 00861 *pnb = nb; 00862 return S_OK; 00863 } 00864 00865 /*** IGraphBuilder methods ***/ 00866 static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn) 00867 { 00868 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 00869 HRESULT hr; 00870 AM_MEDIA_TYPE* mt = NULL; 00871 IEnumMediaTypes* penummt = NULL; 00872 ULONG nbmt; 00873 IEnumPins* penumpins; 00874 IEnumMoniker* pEnumMoniker; 00875 GUID tab[2]; 00876 ULONG nb; 00877 IMoniker* pMoniker; 00878 ULONG pin; 00879 PIN_INFO PinInfo; 00880 CLSID FilterCLSID; 00881 PIN_DIRECTION dir; 00882 00883 TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn); 00884 00885 if (TRACE_ON(quartz)) 00886 { 00887 hr = IPin_QueryPinInfo(ppinIn, &PinInfo); 00888 if (FAILED(hr)) 00889 return hr; 00890 00891 TRACE("Filter owning first pin => %p\n", PinInfo.pFilter); 00892 IBaseFilter_Release(PinInfo.pFilter); 00893 00894 hr = IPin_QueryPinInfo(ppinOut, &PinInfo); 00895 if (FAILED(hr)) 00896 return hr; 00897 00898 TRACE("Filter owning second pin => %p\n", PinInfo.pFilter); 00899 IBaseFilter_Release(PinInfo.pFilter); 00900 } 00901 00902 EnterCriticalSection(&This->cs); 00903 ++This->recursioncount; 00904 if (This->recursioncount >= 5) 00905 { 00906 WARN("Recursion count has reached %d\n", This->recursioncount); 00907 hr = VFW_E_CANNOT_CONNECT; 00908 goto out; 00909 } 00910 00911 hr = IPin_QueryDirection(ppinOut, &dir); 00912 if (FAILED(hr)) 00913 goto out; 00914 00915 if (dir == PINDIR_INPUT) 00916 { 00917 IPin *temp; 00918 00919 temp = ppinIn; 00920 ppinIn = ppinOut; 00921 ppinOut = temp; 00922 } 00923 00924 hr = CheckCircularConnection(This, ppinOut, ppinIn); 00925 if (FAILED(hr)) 00926 goto out; 00927 00928 /* Try direct connection first */ 00929 hr = IPin_Connect(ppinOut, ppinIn, NULL); 00930 if (SUCCEEDED(hr)) 00931 goto out; 00932 00933 TRACE("Direct connection failed, trying to render using extra filters\n"); 00934 00935 hr = IPin_QueryPinInfo(ppinIn, &PinInfo); 00936 if (FAILED(hr)) 00937 goto out; 00938 00939 hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID); 00940 IBaseFilter_Release(PinInfo.pFilter); 00941 if (FAILED(hr)) 00942 goto out; 00943 00944 /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream 00945 * filter to the minor mediatype of input pin of the renderer */ 00946 hr = IPin_EnumMediaTypes(ppinOut, &penummt); 00947 if (FAILED(hr)) 00948 { 00949 WARN("EnumMediaTypes (%x)\n", hr); 00950 goto out; 00951 } 00952 00953 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt); 00954 if (FAILED(hr)) { 00955 WARN("IEnumMediaTypes_Next (%x)\n", hr); 00956 goto out; 00957 } 00958 00959 if (!nbmt) 00960 { 00961 WARN("No media type found!\n"); 00962 hr = VFW_E_INVALIDMEDIATYPE; 00963 goto out; 00964 } 00965 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype)); 00966 TRACE("SubType %s\n", debugstr_guid(&mt->subtype)); 00967 00968 /* Try to find a suitable filter that can connect to the pin to render */ 00969 tab[0] = mt->majortype; 00970 tab[1] = mt->subtype; 00971 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); 00972 if (FAILED(hr)) { 00973 WARN("Unable to enum filters (%x)\n", hr); 00974 goto out; 00975 } 00976 00977 hr = VFW_E_CANNOT_RENDER; 00978 while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) 00979 { 00980 VARIANT var; 00981 GUID clsid; 00982 IPin** ppins; 00983 IPin* ppinfilter = NULL; 00984 IBaseFilter* pfilter = NULL; 00985 00986 hr = GetFilterInfo(pMoniker, &clsid, &var); 00987 IMoniker_Release(pMoniker); 00988 if (FAILED(hr)) { 00989 WARN("Unable to retrieve filter info (%x)\n", hr); 00990 goto error; 00991 } 00992 00993 if (IsEqualGUID(&clsid, &FilterCLSID)) { 00994 /* Skip filter (same as the one the output pin belongs to) */ 00995 goto error; 00996 } 00997 00998 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter); 00999 if (FAILED(hr)) { 01000 WARN("Unable to create filter (%x), trying next one\n", hr); 01001 goto error; 01002 } 01003 01004 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal)); 01005 if (FAILED(hr)) { 01006 WARN("Unable to add filter (%x)\n", hr); 01007 IBaseFilter_Release(pfilter); 01008 pfilter = NULL; 01009 goto error; 01010 } 01011 01012 VariantClear(&var); 01013 01014 hr = IBaseFilter_EnumPins(pfilter, &penumpins); 01015 if (FAILED(hr)) { 01016 WARN("Enumpins (%x)\n", hr); 01017 goto error; 01018 } 01019 01020 hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin); 01021 IEnumPins_Release(penumpins); 01022 01023 if (FAILED(hr)) { 01024 WARN("Obtaining next pin: (%x)\n", hr); 01025 goto error; 01026 } 01027 if (pin == 0) { 01028 WARN("Cannot use this filter: no pins\n"); 01029 goto error; 01030 } 01031 01032 hr = IPin_Connect(ppinOut, ppinfilter, NULL); 01033 if (FAILED(hr)) { 01034 TRACE("Cannot connect to filter (%x), trying next one\n", hr); 01035 goto error; 01036 } 01037 TRACE("Successfully connected to filter, follow chain...\n"); 01038 01039 /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */ 01040 hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb); 01041 01042 if (SUCCEEDED(hr)) { 01043 unsigned int i; 01044 if (nb == 0) { 01045 IPin_Disconnect(ppinfilter); 01046 IPin_Disconnect(ppinOut); 01047 goto error; 01048 } 01049 TRACE("pins to consider: %d\n", nb); 01050 for(i = 0; i < nb; i++) 01051 { 01052 LPWSTR pinname = NULL; 01053 01054 TRACE("Processing pin %u\n", i); 01055 01056 hr = IPin_QueryId(ppins[i], &pinname); 01057 if (SUCCEEDED(hr)) 01058 { 01059 if (pinname[0] == '~') 01060 { 01061 TRACE("Pinname=%s, skipping\n", debugstr_w(pinname)); 01062 hr = E_FAIL; 01063 } 01064 else 01065 hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn); 01066 CoTaskMemFree(pinname); 01067 } 01068 01069 if (FAILED(hr)) { 01070 TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr); 01071 } 01072 IPin_Release(ppins[i]); 01073 if (SUCCEEDED(hr)) break; 01074 } 01075 while (++i < nb) IPin_Release(ppins[i]); 01076 CoTaskMemFree(ppins); 01077 IPin_Release(ppinfilter); 01078 IBaseFilter_Release(pfilter); 01079 if (FAILED(hr)) 01080 { 01081 IPin_Disconnect(ppinfilter); 01082 IPin_Disconnect(ppinOut); 01083 IFilterGraph2_RemoveFilter(iface, pfilter); 01084 continue; 01085 } 01086 break; 01087 } 01088 01089 error: 01090 VariantClear(&var); 01091 if (ppinfilter) IPin_Release(ppinfilter); 01092 if (pfilter) { 01093 IFilterGraph2_RemoveFilter(iface, pfilter); 01094 IBaseFilter_Release(pfilter); 01095 } 01096 } 01097 01098 out: 01099 if (penummt) 01100 IEnumMediaTypes_Release(penummt); 01101 if (mt) 01102 DeleteMediaType(mt); 01103 --This->recursioncount; 01104 LeaveCriticalSection(&This->cs); 01105 TRACE("--> %08x\n", hr); 01106 return SUCCEEDED(hr) ? S_OK : hr; 01107 } 01108 01109 static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut) 01110 { 01111 /* This pin has been connected now, try to call render on all pins that aren't connected */ 01112 IPin *to = NULL; 01113 PIN_INFO info; 01114 IEnumPins *enumpins = NULL; 01115 BOOL renderany = FALSE; 01116 BOOL renderall = TRUE; 01117 01118 IPin_QueryPinInfo(ppinOut, &info); 01119 01120 IBaseFilter_EnumPins(info.pFilter, &enumpins); 01121 /* Don't need to hold a reference, IEnumPins does */ 01122 IBaseFilter_Release(info.pFilter); 01123 01124 IEnumPins_Reset(enumpins); 01125 while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK) 01126 { 01127 PIN_DIRECTION dir = PINDIR_INPUT; 01128 01129 IPin_QueryDirection(to, &dir); 01130 01131 if (dir == PINDIR_OUTPUT) 01132 { 01133 IPin *out = NULL; 01134 01135 IPin_ConnectedTo(to, &out); 01136 if (!out) 01137 { 01138 HRESULT hr; 01139 hr = IFilterGraph2_Render((IFilterGraph2 *)&This->IFilterGraph2_vtbl, to); 01140 if (SUCCEEDED(hr)) 01141 renderany = TRUE; 01142 else 01143 renderall = FALSE; 01144 } 01145 else 01146 IPin_Release(out); 01147 } 01148 01149 IPin_Release(to); 01150 } 01151 01152 IEnumPins_Release(enumpins); 01153 01154 if (renderall) 01155 return S_OK; 01156 01157 if (renderany) 01158 return VFW_S_PARTIAL_RENDER; 01159 01160 return VFW_E_CANNOT_RENDER; 01161 } 01162 01163 /* Ogg hates me if I create a direct rendering method 01164 * 01165 * It can only connect to a pin properly once, so use a recursive method that does 01166 * 01167 * +----+ --- (PIN 1) (Render is called on this pin) 01168 * | | 01169 * +----+ --- (PIN 2) 01170 * 01171 * Enumerate possible renderers that EXACTLY match the requested type 01172 * 01173 * If none is available, try to add intermediate filters that can connect to the input pin 01174 * then call Render on that intermediate pin's output pins 01175 * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed, 01176 * and another filter that can connect to the input pin is tried 01177 * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER 01178 * It's recursive, but fun! 01179 */ 01180 01181 static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut) 01182 { 01183 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01184 IEnumMediaTypes* penummt; 01185 AM_MEDIA_TYPE* mt; 01186 ULONG nbmt; 01187 HRESULT hr; 01188 01189 IEnumMoniker* pEnumMoniker; 01190 GUID tab[4]; 01191 ULONG nb; 01192 IMoniker* pMoniker; 01193 INT x; 01194 01195 TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut); 01196 01197 if (TRACE_ON(quartz)) 01198 { 01199 PIN_INFO PinInfo; 01200 01201 hr = IPin_QueryPinInfo(ppinOut, &PinInfo); 01202 if (FAILED(hr)) 01203 return hr; 01204 01205 TRACE("Filter owning pin => %p\n", PinInfo.pFilter); 01206 IBaseFilter_Release(PinInfo.pFilter); 01207 } 01208 01209 /* Try to find out if there is a renderer for the specified subtype already, and use that 01210 */ 01211 EnterCriticalSection(&This->cs); 01212 for (x = 0; x < This->nFilters; ++x) 01213 { 01214 IEnumPins *enumpins = NULL; 01215 IPin *pin = NULL; 01216 01217 hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins); 01218 01219 if (FAILED(hr) || !enumpins) 01220 continue; 01221 01222 IEnumPins_Reset(enumpins); 01223 while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK) 01224 { 01225 IPin *to = NULL; 01226 PIN_DIRECTION dir = PINDIR_OUTPUT; 01227 01228 IPin_QueryDirection(pin, &dir); 01229 if (dir != PINDIR_INPUT) 01230 { 01231 IPin_Release(pin); 01232 continue; 01233 } 01234 IPin_ConnectedTo(pin, &to); 01235 01236 if (to == NULL) 01237 { 01238 hr = IPin_Connect(ppinOut, pin, NULL); 01239 if (SUCCEEDED(hr)) 01240 { 01241 TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr); 01242 IPin_Release(pin); 01243 01244 hr = FilterGraph2_RenderRecurse(This, pin); 01245 if (FAILED(hr)) 01246 { 01247 IPin_Disconnect(ppinOut); 01248 IPin_Disconnect(pin); 01249 continue; 01250 } 01251 IEnumPins_Release(enumpins); 01252 LeaveCriticalSection(&This->cs); 01253 return hr; 01254 } 01255 WARN("Could not connect!\n"); 01256 } 01257 else 01258 IPin_Release(to); 01259 01260 IPin_Release(pin); 01261 } 01262 IEnumPins_Release(enumpins); 01263 } 01264 01265 LeaveCriticalSection(&This->cs); 01266 01267 hr = IPin_EnumMediaTypes(ppinOut, &penummt); 01268 if (FAILED(hr)) { 01269 WARN("EnumMediaTypes (%x)\n", hr); 01270 return hr; 01271 } 01272 01273 IEnumMediaTypes_Reset(penummt); 01274 01275 /* Looks like no existing renderer of the kind exists 01276 * Try adding new ones 01277 */ 01278 tab[0] = tab[1] = GUID_NULL; 01279 while (SUCCEEDED(hr)) 01280 { 01281 hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt); 01282 if (FAILED(hr)) { 01283 WARN("IEnumMediaTypes_Next (%x)\n", hr); 01284 break; 01285 } 01286 if (!nbmt) 01287 { 01288 hr = VFW_E_CANNOT_RENDER; 01289 break; 01290 } 01291 else 01292 { 01293 TRACE("MajorType %s\n", debugstr_guid(&mt->majortype)); 01294 TRACE("SubType %s\n", debugstr_guid(&mt->subtype)); 01295 01296 /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */ 01297 if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[1], &mt->subtype)) 01298 { 01299 DeleteMediaType(mt); 01300 continue; 01301 } 01302 01303 /* Try to find a suitable renderer with the same media type */ 01304 tab[0] = mt->majortype; 01305 tab[1] = mt->subtype; 01306 hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); 01307 if (FAILED(hr)) 01308 { 01309 WARN("Unable to enum filters (%x)\n", hr); 01310 break; 01311 } 01312 } 01313 hr = E_FAIL; 01314 01315 while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) 01316 { 01317 VARIANT var; 01318 GUID clsid; 01319 IPin* ppinfilter; 01320 IBaseFilter* pfilter = NULL; 01321 IEnumPins* penumpins = NULL; 01322 ULONG pin; 01323 01324 hr = GetFilterInfo(pMoniker, &clsid, &var); 01325 IMoniker_Release(pMoniker); 01326 if (FAILED(hr)) { 01327 WARN("Unable to retrieve filter info (%x)\n", hr); 01328 goto error; 01329 } 01330 01331 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter); 01332 if (FAILED(hr)) 01333 { 01334 WARN("Unable to create filter (%x), trying next one\n", hr); 01335 goto error; 01336 } 01337 01338 hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal)); 01339 if (FAILED(hr)) { 01340 WARN("Unable to add filter (%x)\n", hr); 01341 IBaseFilter_Release(pfilter); 01342 pfilter = NULL; 01343 goto error; 01344 } 01345 01346 hr = IBaseFilter_EnumPins(pfilter, &penumpins); 01347 if (FAILED(hr)) { 01348 WARN("Splitter Enumpins (%x)\n", hr); 01349 goto error; 01350 } 01351 01352 while ((hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin)) == S_OK) 01353 { 01354 PIN_DIRECTION dir; 01355 01356 if (pin == 0) { 01357 WARN("No Pin\n"); 01358 hr = E_FAIL; 01359 goto error; 01360 } 01361 01362 hr = IPin_QueryDirection(ppinfilter, &dir); 01363 if (FAILED(hr)) { 01364 IPin_Release(ppinfilter); 01365 WARN("QueryDirection failed (%x)\n", hr); 01366 goto error; 01367 } 01368 if (dir != PINDIR_INPUT) { 01369 IPin_Release(ppinfilter); 01370 continue; /* Wrong direction */ 01371 } 01372 01373 /* Connect the pin to the "Renderer" */ 01374 hr = IPin_Connect(ppinOut, ppinfilter, NULL); 01375 IPin_Release(ppinfilter); 01376 01377 if (FAILED(hr)) { 01378 WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr); 01379 goto error; 01380 } 01381 TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal))); 01382 01383 VariantClear(&var); 01384 01385 hr = FilterGraph2_RenderRecurse(This, ppinfilter); 01386 if (FAILED(hr)) { 01387 WARN("Unable to connect recursively (%x)\n", hr); 01388 goto error; 01389 } 01390 IBaseFilter_Release(pfilter); 01391 break; 01392 } 01393 if (SUCCEEDED(hr)) { 01394 IEnumPins_Release(penumpins); 01395 break; /* out of IEnumMoniker_Next loop */ 01396 } 01397 01398 /* IEnumPins_Next failed, all other failure case caught by goto error */ 01399 WARN("IEnumPins_Next (%x)\n", hr); 01400 /* goto error */ 01401 01402 error: 01403 VariantClear(&var); 01404 if (penumpins) 01405 IEnumPins_Release(penumpins); 01406 if (pfilter) { 01407 IFilterGraph2_RemoveFilter(iface, pfilter); 01408 IBaseFilter_Release(pfilter); 01409 } 01410 if (SUCCEEDED(hr)) DebugBreak(); 01411 } 01412 01413 IEnumMoniker_Release(pEnumMoniker); 01414 if (nbmt) 01415 DeleteMediaType(mt); 01416 if (SUCCEEDED(hr)) 01417 break; 01418 hr = S_OK; 01419 } 01420 01421 IEnumMediaTypes_Release(penummt); 01422 return hr; 01423 } 01424 01425 static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, 01426 LPCWSTR lpcwstrFile, 01427 LPCWSTR lpcwstrPlayList) 01428 { 01429 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01430 static const WCHAR string[] = {'R','e','a','d','e','r',0}; 01431 IBaseFilter* preader = NULL; 01432 IPin* ppinreader = NULL; 01433 IEnumPins* penumpins = NULL; 01434 HRESULT hr; 01435 BOOL partial = FALSE; 01436 HRESULT any = FALSE; 01437 01438 TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList)); 01439 01440 if (lpcwstrPlayList != NULL) 01441 return E_INVALIDARG; 01442 01443 hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader); 01444 if (FAILED(hr)) 01445 return hr; 01446 01447 if (SUCCEEDED(hr)) 01448 hr = IBaseFilter_EnumPins(preader, &penumpins); 01449 if (SUCCEEDED(hr)) 01450 { 01451 while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK) 01452 { 01453 PIN_DIRECTION dir; 01454 01455 IPin_QueryDirection(ppinreader, &dir); 01456 if (dir == PINDIR_OUTPUT) 01457 { 01458 INT i; 01459 01460 hr = IFilterGraph2_Render(iface, ppinreader); 01461 TRACE("Render %08x\n", hr); 01462 01463 for (i = 0; i < This->nFilters; ++i) 01464 TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i])); 01465 01466 if (SUCCEEDED(hr)) 01467 any = TRUE; 01468 if (hr != S_OK) 01469 partial = TRUE; 01470 } 01471 IPin_Release(ppinreader); 01472 } 01473 IEnumPins_Release(penumpins); 01474 01475 if (!any) 01476 hr = VFW_E_CANNOT_RENDER; 01477 else if (partial) 01478 hr = VFW_S_PARTIAL_RENDER; 01479 else 01480 hr = S_OK; 01481 } 01482 IBaseFilter_Release(preader); 01483 01484 TRACE("--> %08x\n", hr); 01485 return hr; 01486 } 01487 01488 /* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */ 01489 static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter) 01490 { 01491 static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0}; 01492 HRESULT hr = S_OK; 01493 HKEY extkey; 01494 LONG lRet; 01495 01496 lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey); 01497 hr = HRESULT_FROM_WIN32(lRet); 01498 01499 if (SUCCEEDED(hr)) 01500 { 01501 static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0}; 01502 WCHAR *ext = PathFindExtensionW(pszFileName); 01503 WCHAR clsid_key[39]; 01504 GUID clsid; 01505 DWORD size = sizeof(clsid_key); 01506 HKEY pathkey; 01507 01508 if (!ext) 01509 { 01510 CloseHandle(extkey); 01511 return E_FAIL; 01512 } 01513 01514 lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey); 01515 hr = HRESULT_FROM_WIN32(lRet); 01516 CloseHandle(extkey); 01517 if (FAILED(hr)) 01518 return hr; 01519 01520 lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size); 01521 hr = HRESULT_FROM_WIN32(lRet); 01522 CloseHandle(pathkey); 01523 if (FAILED(hr)) 01524 return hr; 01525 01526 CLSIDFromString(clsid_key, &clsid); 01527 01528 TRACE("CLSID: %s\n", debugstr_guid(&clsid)); 01529 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter); 01530 if (SUCCEEDED(hr)) 01531 { 01532 IFileSourceFilter *source = NULL; 01533 hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source); 01534 if (SUCCEEDED(hr)) 01535 IFileSourceFilter_Release(source); 01536 else 01537 IBaseFilter_Release(*filter); 01538 } 01539 } 01540 if (FAILED(hr)) 01541 *filter = NULL; 01542 return hr; 01543 } 01544 01545 static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, 01546 LPCWSTR lpcwstrFileName, 01547 LPCWSTR lpcwstrFilterName, 01548 IBaseFilter **ppFilter) { 01549 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01550 HRESULT hr; 01551 IBaseFilter* preader; 01552 IFileSourceFilter* pfile = NULL; 01553 AM_MEDIA_TYPE mt; 01554 WCHAR* filename; 01555 01556 TRACE("(%p/%p)->(%s, %s, %p)\n", This, iface, debugstr_w(lpcwstrFileName), debugstr_w(lpcwstrFilterName), ppFilter); 01557 01558 /* Try from file name first, then fall back to default asynchronous reader */ 01559 hr = GetFileSourceFilter(lpcwstrFileName, &preader); 01560 01561 if (FAILED(hr)) 01562 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader); 01563 if (FAILED(hr)) { 01564 WARN("Unable to create file source filter (%x)\n", hr); 01565 return hr; 01566 } 01567 01568 hr = IFilterGraph2_AddFilter(iface, preader, lpcwstrFilterName); 01569 if (FAILED(hr)) { 01570 WARN("Unable add filter (%x)\n", hr); 01571 IBaseFilter_Release(preader); 01572 return hr; 01573 } 01574 01575 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile); 01576 if (FAILED(hr)) { 01577 WARN("Unable to get IFileSourceInterface (%x)\n", hr); 01578 goto error; 01579 } 01580 01581 /* Load the file in the file source filter */ 01582 hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL); 01583 if (FAILED(hr)) { 01584 WARN("Load (%x)\n", hr); 01585 goto error; 01586 } 01587 01588 IFileSourceFilter_GetCurFile(pfile, &filename, &mt); 01589 if (FAILED(hr)) { 01590 WARN("GetCurFile (%x)\n", hr); 01591 goto error; 01592 } 01593 01594 TRACE("File %s\n", debugstr_w(filename)); 01595 TRACE("MajorType %s\n", debugstr_guid(&mt.majortype)); 01596 TRACE("SubType %s\n", debugstr_guid(&mt.subtype)); 01597 01598 if (ppFilter) 01599 *ppFilter = preader; 01600 IFileSourceFilter_Release(pfile); 01601 01602 return S_OK; 01603 01604 error: 01605 if (pfile) 01606 IFileSourceFilter_Release(pfile); 01607 IFilterGraph2_RemoveFilter(iface, preader); 01608 IBaseFilter_Release(preader); 01609 01610 return hr; 01611 } 01612 01613 static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, 01614 DWORD_PTR hFile) { 01615 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01616 01617 TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile); 01618 01619 return S_OK; 01620 } 01621 01622 static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) { 01623 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01624 01625 TRACE("(%p/%p)->(): stub !!!\n", This, iface); 01626 01627 return S_OK; 01628 } 01629 01630 static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) { 01631 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01632 01633 TRACE("(%p/%p)->(): stub !!!\n", This, iface); 01634 01635 return S_OK; 01636 } 01637 01638 /*** IFilterGraph2 methods ***/ 01639 static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface, 01640 IMoniker *pMoniker, 01641 IBindCtx *pCtx, 01642 LPCWSTR lpcwstrFilterName, 01643 IBaseFilter **ppFilter) { 01644 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01645 01646 TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter); 01647 01648 return S_OK; 01649 } 01650 01651 static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, 01652 IPin *ppin, 01653 const AM_MEDIA_TYPE *pmt) { 01654 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01655 01656 TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt); 01657 01658 return S_OK; 01659 } 01660 01661 static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, 01662 IPin *pPinOut, 01663 DWORD dwFlags, 01664 DWORD *pvContext) { 01665 ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); 01666 01667 TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext); 01668 01669 return S_OK; 01670 } 01671 01672 01673 static const IFilterGraph2Vtbl IFilterGraph2_VTable = 01674 { 01675 FilterGraph2_QueryInterface, 01676 FilterGraph2_AddRef, 01677 FilterGraph2_Release, 01678 FilterGraph2_AddFilter, 01679 FilterGraph2_RemoveFilter, 01680 FilterGraph2_EnumFilters, 01681 FilterGraph2_FindFilterByName, 01682 FilterGraph2_ConnectDirect, 01683 FilterGraph2_Reconnect, 01684 FilterGraph2_Disconnect, 01685 FilterGraph2_SetDefaultSyncSource, 01686 FilterGraph2_Connect, 01687 FilterGraph2_Render, 01688 FilterGraph2_RenderFile, 01689 FilterGraph2_AddSourceFilter, 01690 FilterGraph2_SetLogFile, 01691 FilterGraph2_Abort, 01692 FilterGraph2_ShouldOperationContinue, 01693 FilterGraph2_AddSourceFilterForMoniker, 01694 FilterGraph2_ReconnectEx, 01695 FilterGraph2_RenderEx 01696 }; 01697 01698 /*** IUnknown methods ***/ 01699 static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, 01700 REFIID riid, 01701 LPVOID*ppvObj) { 01702 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01703 01704 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 01705 01706 return Filtergraph_QueryInterface(This, riid, ppvObj); 01707 } 01708 01709 static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) { 01710 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01711 01712 TRACE("(%p/%p)->()\n", This, iface); 01713 01714 return Filtergraph_AddRef(This); 01715 } 01716 01717 static ULONG WINAPI MediaControl_Release(IMediaControl *iface) { 01718 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01719 01720 TRACE("(%p/%p)->()\n", This, iface); 01721 01722 return Filtergraph_Release(This); 01723 01724 } 01725 01726 /*** IDispatch methods ***/ 01727 static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, 01728 UINT*pctinfo) { 01729 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01730 01731 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); 01732 01733 return S_OK; 01734 } 01735 01736 static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, 01737 UINT iTInfo, 01738 LCID lcid, 01739 ITypeInfo**ppTInfo) { 01740 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01741 01742 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); 01743 01744 return S_OK; 01745 } 01746 01747 static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, 01748 REFIID riid, 01749 LPOLESTR*rgszNames, 01750 UINT cNames, 01751 LCID lcid, 01752 DISPID*rgDispId) { 01753 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01754 01755 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); 01756 01757 return S_OK; 01758 } 01759 01760 static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, 01761 DISPID dispIdMember, 01762 REFIID riid, 01763 LCID lcid, 01764 WORD wFlags, 01765 DISPPARAMS*pDispParams, 01766 VARIANT*pVarResult, 01767 EXCEPINFO*pExepInfo, 01768 UINT*puArgErr) { 01769 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01770 01771 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 01772 01773 return S_OK; 01774 } 01775 01776 typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data); 01777 01778 static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data) 01779 { 01780 HRESULT hr; 01781 IPin* pInputPin; 01782 IPin** ppPins; 01783 ULONG nb; 01784 ULONG i; 01785 PIN_INFO PinInfo; 01786 01787 TRACE("%p %p\n", pGraph, pOutputPin); 01788 PinInfo.pFilter = NULL; 01789 01790 hr = IPin_ConnectedTo(pOutputPin, &pInputPin); 01791 01792 if (SUCCEEDED(hr)) 01793 { 01794 hr = IPin_QueryPinInfo(pInputPin, &PinInfo); 01795 if (SUCCEEDED(hr)) 01796 hr = GetInternalConnections(PinInfo.pFilter, pInputPin, &ppPins, &nb); 01797 IPin_Release(pInputPin); 01798 } 01799 01800 if (SUCCEEDED(hr)) 01801 { 01802 if (nb == 0) 01803 { 01804 TRACE("Reached a renderer\n"); 01805 /* Count renderers for end of stream notification */ 01806 pGraph->nRenderers++; 01807 } 01808 else 01809 { 01810 for(i = 0; i < nb; i++) 01811 { 01812 /* Explore the graph downstream from this pin 01813 * FIXME: We should prevent exploring from a pin more than once. This can happens when 01814 * several input pins are connected to the same output (a MUX for instance). */ 01815 ExploreGraph(pGraph, ppPins[i], FoundFilter, data); 01816 IPin_Release(ppPins[i]); 01817 } 01818 01819 CoTaskMemFree(ppPins); 01820 } 01821 TRACE("Doing stuff with filter %p\n", PinInfo.pFilter); 01822 01823 FoundFilter(PinInfo.pFilter, data); 01824 } 01825 01826 if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter); 01827 return hr; 01828 } 01829 01830 static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data) 01831 { 01832 LONGLONG time = 0; 01833 IReferenceClock *clock = NULL; 01834 01835 IBaseFilter_GetSyncSource(pFilter, &clock); 01836 if (clock) 01837 { 01838 IReferenceClock_GetTime(clock, &time); 01839 if (time) 01840 /* Add 50 ms */ 01841 time += 500000; 01842 if (time < 0) 01843 time = 0; 01844 IReferenceClock_Release(clock); 01845 } 01846 01847 return IBaseFilter_Run(pFilter, time); 01848 } 01849 01850 static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data) 01851 { 01852 return IBaseFilter_Pause(pFilter); 01853 } 01854 01855 static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data) 01856 { 01857 return IBaseFilter_Stop(pFilter); 01858 } 01859 01860 static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data) 01861 { 01862 FILTER_STATE state; 01863 DWORD time_end = data; 01864 DWORD time_now = GetTickCount(); 01865 LONG wait; 01866 01867 if (time_end == INFINITE) 01868 { 01869 wait = INFINITE; 01870 } 01871 else if (time_end > time_now) 01872 { 01873 wait = time_end - time_now; 01874 } 01875 else 01876 wait = 0; 01877 01878 return IBaseFilter_GetState(pFilter, wait, &state); 01879 } 01880 01881 01882 static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter, DWORD_PTR data) 01883 { 01884 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01885 int i; 01886 IBaseFilter* pfilter; 01887 IEnumPins* pEnum; 01888 HRESULT hr; 01889 IPin* pPin; 01890 DWORD dummy; 01891 PIN_DIRECTION dir; 01892 TRACE("(%p/%p)->()\n", This, iface); 01893 01894 /* Explorer the graph from source filters to renderers, determine renderers 01895 * number and run filters from renderers to source filters */ 01896 This->nRenderers = 0; 01897 ResetEvent(This->hEventCompletion); 01898 01899 for(i = 0; i < This->nFilters; i++) 01900 { 01901 BOOL source = TRUE; 01902 pfilter = This->ppFiltersInGraph[i]; 01903 hr = IBaseFilter_EnumPins(pfilter, &pEnum); 01904 if (hr != S_OK) 01905 { 01906 WARN("Enum pins failed %x\n", hr); 01907 continue; 01908 } 01909 /* Check if it is a source filter */ 01910 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK) 01911 { 01912 IPin_QueryDirection(pPin, &dir); 01913 IPin_Release(pPin); 01914 if (dir == PINDIR_INPUT) 01915 { 01916 source = FALSE; 01917 break; 01918 } 01919 } 01920 if (source) 01921 { 01922 TRACE("Found a source filter %p\n", pfilter); 01923 IEnumPins_Reset(pEnum); 01924 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK) 01925 { 01926 /* Explore the graph downstream from this pin */ 01927 ExploreGraph(This, pPin, FoundFilter, data); 01928 IPin_Release(pPin); 01929 } 01930 FoundFilter(pfilter, data); 01931 } 01932 IEnumPins_Release(pEnum); 01933 } 01934 01935 return S_FALSE; 01936 } 01937 01938 /*** IMediaControl methods ***/ 01939 static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) { 01940 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01941 TRACE("(%p/%p)->()\n", This, iface); 01942 01943 if (This->state == State_Running) return S_OK; 01944 01945 EnterCriticalSection(&This->cs); 01946 if (This->state == State_Stopped) 01947 This->EcCompleteCount = 0; 01948 01949 if (This->refClock) 01950 { 01951 IReferenceClock_GetTime(This->refClock, &This->start_time); 01952 This->start_time += 500000; 01953 } 01954 else This->position = This->start_time = 0; 01955 01956 SendFilterMessage(iface, SendRun, 0); 01957 This->state = State_Running; 01958 LeaveCriticalSection(&This->cs); 01959 return S_FALSE; 01960 } 01961 01962 static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) { 01963 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01964 TRACE("(%p/%p)->()\n", This, iface); 01965 01966 if (This->state == State_Paused) return S_OK; 01967 01968 EnterCriticalSection(&This->cs); 01969 if (This->state == State_Stopped) 01970 This->EcCompleteCount = 0; 01971 01972 if (This->state == State_Running && This->refClock) 01973 { 01974 LONGLONG time = This->start_time; 01975 IReferenceClock_GetTime(This->refClock, &time); 01976 This->position += time - This->start_time; 01977 } 01978 01979 SendFilterMessage(iface, SendPause, 0); 01980 This->state = State_Paused; 01981 LeaveCriticalSection(&This->cs); 01982 return S_FALSE; 01983 } 01984 01985 static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) { 01986 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 01987 TRACE("(%p/%p)->()\n", This, iface); 01988 01989 if (This->state == State_Stopped) return S_OK; 01990 01991 EnterCriticalSection(&This->cs); 01992 if (This->state == State_Running && This->refClock) 01993 { 01994 LONGLONG time = This->start_time; 01995 IReferenceClock_GetTime(This->refClock, &time); 01996 This->position += time - This->start_time; 01997 } 01998 01999 if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0); 02000 SendFilterMessage(iface, SendStop, 0); 02001 This->state = State_Stopped; 02002 LeaveCriticalSection(&This->cs); 02003 return S_OK; 02004 } 02005 02006 static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, 02007 LONG msTimeout, 02008 OAFilterState *pfs) { 02009 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 02010 DWORD end; 02011 02012 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs); 02013 02014 if (!pfs) 02015 return E_POINTER; 02016 02017 EnterCriticalSection(&This->cs); 02018 02019 *pfs = This->state; 02020 if (msTimeout > 0) 02021 { 02022 end = GetTickCount() + msTimeout; 02023 } 02024 else if (msTimeout < 0) 02025 { 02026 end = INFINITE; 02027 } 02028 else 02029 { 02030 end = 0; 02031 } 02032 if (end) 02033 SendFilterMessage(iface, SendGetState, end); 02034 02035 LeaveCriticalSection(&This->cs); 02036 02037 return S_OK; 02038 } 02039 02040 static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, 02041 BSTR strFilename) { 02042 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 02043 02044 FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename); 02045 02046 return S_OK; 02047 } 02048 02049 static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, 02050 BSTR strFilename, 02051 IDispatch **ppUnk) { 02052 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 02053 02054 FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk); 02055 02056 return S_OK; 02057 } 02058 02059 static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, 02060 IDispatch **ppUnk) { 02061 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 02062 02063 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk); 02064 02065 return S_OK; 02066 } 02067 02068 static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, 02069 IDispatch **ppUnk) { 02070 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 02071 02072 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk); 02073 02074 return S_OK; 02075 } 02076 02077 static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) { 02078 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); 02079 02080 FIXME("(%p/%p)->(): stub !!!\n", This, iface); 02081 02082 return S_OK; 02083 } 02084 02085 02086 static const IMediaControlVtbl IMediaControl_VTable = 02087 { 02088 MediaControl_QueryInterface, 02089 MediaControl_AddRef, 02090 MediaControl_Release, 02091 MediaControl_GetTypeInfoCount, 02092 MediaControl_GetTypeInfo, 02093 MediaControl_GetIDsOfNames, 02094 MediaControl_Invoke, 02095 MediaControl_Run, 02096 MediaControl_Pause, 02097 MediaControl_Stop, 02098 MediaControl_GetState, 02099 MediaControl_RenderFile, 02100 MediaControl_AddSourceFilter, 02101 MediaControl_get_FilterCollection, 02102 MediaControl_get_RegFilterCollection, 02103 MediaControl_StopWhenReady 02104 }; 02105 02106 02107 /*** IUnknown methods ***/ 02108 static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, 02109 REFIID riid, 02110 LPVOID*ppvObj) { 02111 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02112 02113 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 02114 02115 return Filtergraph_QueryInterface(This, riid, ppvObj); 02116 } 02117 02118 static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) { 02119 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02120 02121 TRACE("(%p/%p)->()\n", This, iface); 02122 02123 return Filtergraph_AddRef(This); 02124 } 02125 02126 static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) { 02127 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02128 02129 TRACE("(%p/%p)->()\n", This, iface); 02130 02131 return Filtergraph_Release(This); 02132 } 02133 02134 typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg); 02135 02136 static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) { 02137 BOOL allnotimpl = TRUE; 02138 int i; 02139 IBaseFilter* pfilter; 02140 IEnumPins* pEnum; 02141 HRESULT hr, hr_return = S_OK; 02142 IPin* pPin; 02143 DWORD dummy; 02144 PIN_DIRECTION dir; 02145 02146 TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg); 02147 /* Send a message to all renderers, they are responsible for broadcasting it further */ 02148 02149 for(i = 0; i < This->nFilters; i++) 02150 { 02151 BOOL renderer = TRUE; 02152 pfilter = This->ppFiltersInGraph[i]; 02153 hr = IBaseFilter_EnumPins(pfilter, &pEnum); 02154 if (hr != S_OK) 02155 { 02156 WARN("Enum pins failed %x\n", hr); 02157 continue; 02158 } 02159 /* Check if it is a source filter */ 02160 while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK) 02161 { 02162 IPin_QueryDirection(pPin, &dir); 02163 IPin_Release(pPin); 02164 if (dir != PINDIR_INPUT) 02165 { 02166 renderer = FALSE; 02167 break; 02168 } 02169 } 02170 IEnumPins_Release(pEnum); 02171 if (renderer) 02172 { 02173 IMediaSeeking *seek = NULL; 02174 IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek); 02175 if (!seek) 02176 continue; 02177 02178 hr = FoundSeek(This, seek, arg); 02179 02180 IMediaSeeking_Release(seek); 02181 if (hr_return != E_NOTIMPL) 02182 allnotimpl = FALSE; 02183 if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return))) 02184 hr_return = hr; 02185 } 02186 } 02187 02188 if (allnotimpl) 02189 return E_NOTIMPL; 02190 return hr_return; 02191 } 02192 02193 static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pcaps) 02194 { 02195 HRESULT hr; 02196 DWORD caps = 0; 02197 02198 hr = IMediaSeeking_GetCapabilities(seek, &caps); 02199 if (FAILED(hr)) 02200 return hr; 02201 02202 /* Only add common capabilities everything supports */ 02203 *(DWORD*)pcaps &= caps; 02204 02205 return hr; 02206 } 02207 02208 /*** IMediaSeeking methods ***/ 02209 static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, 02210 DWORD *pCapabilities) { 02211 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02212 HRESULT hr; 02213 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities); 02214 02215 if (!pCapabilities) 02216 return E_POINTER; 02217 02218 EnterCriticalSection(&This->cs); 02219 *pCapabilities = 0xffffffff; 02220 02221 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities); 02222 LeaveCriticalSection(&This->cs); 02223 02224 return hr; 02225 } 02226 02227 static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, 02228 DWORD *pCapabilities) { 02229 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02230 DWORD originalcaps; 02231 HRESULT hr; 02232 TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities); 02233 02234 if (!pCapabilities) 02235 return E_POINTER; 02236 02237 EnterCriticalSection(&This->cs); 02238 originalcaps = *pCapabilities; 02239 hr = all_renderers_seek(This, FoundCapabilities, (DWORD_PTR)pCapabilities); 02240 LeaveCriticalSection(&This->cs); 02241 02242 if (FAILED(hr)) 02243 return hr; 02244 02245 if (!*pCapabilities) 02246 return E_FAIL; 02247 if (*pCapabilities != originalcaps) 02248 return S_FALSE; 02249 return S_OK; 02250 } 02251 02252 static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, 02253 const GUID *pFormat) { 02254 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02255 02256 if (!pFormat) 02257 return E_POINTER; 02258 02259 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat)); 02260 02261 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat)) 02262 { 02263 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat)); 02264 return S_FALSE; 02265 } 02266 02267 return S_OK; 02268 } 02269 02270 static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, 02271 GUID *pFormat) { 02272 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02273 02274 if (!pFormat) 02275 return E_POINTER; 02276 02277 FIXME("(%p/%p)->(%p): semi-stub !!!\n", This, iface, pFormat); 02278 memcpy(pFormat, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID)); 02279 02280 return S_OK; 02281 } 02282 02283 static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, 02284 GUID *pFormat) { 02285 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02286 02287 if (!pFormat) 02288 return E_POINTER; 02289 02290 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat); 02291 memcpy(pFormat, &This->timeformatseek, sizeof(GUID)); 02292 02293 return S_OK; 02294 } 02295 02296 static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, 02297 const GUID *pFormat) { 02298 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02299 02300 TRACE("(%p/%p)->(%p)\n", This, iface, pFormat); 02301 if (!pFormat) 02302 return E_POINTER; 02303 02304 if (memcmp(pFormat, &This->timeformatseek, sizeof(GUID))) 02305 return S_FALSE; 02306 02307 return S_OK; 02308 } 02309 02310 static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, 02311 const GUID *pFormat) { 02312 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02313 02314 if (!pFormat) 02315 return E_POINTER; 02316 02317 TRACE("(%p/%p)->(%s)\n", This, iface, debugstr_guid(pFormat)); 02318 02319 if (This->state != State_Stopped) 02320 return VFW_E_WRONG_STATE; 02321 02322 if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, pFormat)) 02323 { 02324 FIXME("Unhandled time format %s\n", debugstr_guid(pFormat)); 02325 return E_INVALIDARG; 02326 } 02327 02328 return S_OK; 02329 } 02330 02331 static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pduration) 02332 { 02333 HRESULT hr; 02334 LONGLONG duration = 0, *pdur = (LONGLONG*)pduration; 02335 02336 hr = IMediaSeeking_GetDuration(seek, &duration); 02337 if (FAILED(hr)) 02338 return hr; 02339 02340 /* FIXME: Minimum or maximum duration? Assuming minimum */ 02341 if (duration > 0 && *pdur < duration) 02342 *pdur = duration; 02343 02344 return hr; 02345 } 02346 02347 static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, 02348 LONGLONG *pDuration) { 02349 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02350 HRESULT hr; 02351 02352 TRACE("(%p/%p)->(%p)\n", This, iface, pDuration); 02353 02354 if (!pDuration) 02355 return E_POINTER; 02356 02357 EnterCriticalSection(&This->cs); 02358 *pDuration = -1; 02359 hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration); 02360 LeaveCriticalSection(&This->cs); 02361 02362 TRACE("--->%08x\n", hr); 02363 return hr; 02364 } 02365 02366 static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, 02367 LONGLONG *pStop) { 02368 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02369 HRESULT hr = S_OK; 02370 02371 TRACE("(%p/%p)->(%p)\n", This, iface, pStop); 02372 02373 if (!pStop) 02374 return E_POINTER; 02375 02376 EnterCriticalSection(&This->cs); 02377 if (This->stop_position < 0) 02378 /* Stop position not set, use duration instead */ 02379 hr = IMediaSeeking_GetDuration(iface, pStop); 02380 else 02381 *pStop = This->stop_position; 02382 02383 LeaveCriticalSection(&This->cs); 02384 02385 return hr; 02386 } 02387 02388 static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, 02389 LONGLONG *pCurrent) { 02390 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02391 LONGLONG time = 0; 02392 02393 if (!pCurrent) 02394 return E_POINTER; 02395 02396 EnterCriticalSection(&This->cs); 02397 if (This->state == State_Running && This->refClock) 02398 { 02399 IReferenceClock_GetTime(This->refClock, &time); 02400 if (time) 02401 time += This->position - This->start_time; 02402 if (time < This->position) 02403 time = This->position; 02404 *pCurrent = time; 02405 } 02406 else 02407 *pCurrent = This->position; 02408 LeaveCriticalSection(&This->cs); 02409 02410 TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000)); 02411 02412 return S_OK; 02413 } 02414 02415 static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, 02416 LONGLONG *pTarget, 02417 const GUID *pTargetFormat, 02418 LONGLONG Source, 02419 const GUID *pSourceFormat) { 02420 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02421 02422 FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget, 02423 pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat); 02424 02425 return S_OK; 02426 } 02427 02428 struct pos_args { 02429 LONGLONG* current, *stop; 02430 DWORD curflags, stopflags; 02431 }; 02432 02433 static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *seek, DWORD_PTR pargs) 02434 { 02435 struct pos_args *args = (void*)pargs; 02436 02437 return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags); 02438 } 02439 02440 static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, 02441 LONGLONG *pCurrent, 02442 DWORD dwCurrentFlags, 02443 LONGLONG *pStop, 02444 DWORD dwStopFlags) { 02445 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02446 HRESULT hr = S_OK; 02447 FILTER_STATE state; 02448 struct pos_args args; 02449 02450 TRACE("(%p/%p)->(%p, %08x, %p, %08x)\n", This, iface, pCurrent, dwCurrentFlags, pStop, dwStopFlags); 02451 02452 EnterCriticalSection(&This->cs); 02453 state = This->state; 02454 TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN"))); 02455 02456 if ((dwCurrentFlags & 0x7) == AM_SEEKING_AbsolutePositioning) 02457 { 02458 This->position = *pCurrent; 02459 } 02460 else if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning) 02461 FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7); 02462 02463 if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning) 02464 This->stop_position = *pStop; 02465 else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning) 02466 FIXME("Stop position not handled yet!\n"); 02467 02468 args.current = pCurrent; 02469 args.stop = pStop; 02470 args.curflags = dwCurrentFlags; 02471 args.stopflags = dwStopFlags; 02472 hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args); 02473 02474 if (This->refClock && ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)) 02475 { 02476 /* Update start time, prevents weird jumps */ 02477 IReferenceClock_GetTime(This->refClock, &This->start_time); 02478 } 02479 LeaveCriticalSection(&This->cs); 02480 02481 return hr; 02482 } 02483 02484 static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, 02485 LONGLONG *pCurrent, 02486 LONGLONG *pStop) { 02487 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02488 HRESULT hr; 02489 02490 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop); 02491 hr = IMediaSeeking_GetCurrentPosition(iface, pCurrent); 02492 if (SUCCEEDED(hr)) 02493 hr = IMediaSeeking_GetStopPosition(iface, pStop); 02494 02495 return hr; 02496 } 02497 02498 static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, 02499 LONGLONG *pEarliest, 02500 LONGLONG *pLatest) { 02501 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02502 02503 FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest); 02504 02505 return S_OK; 02506 } 02507 02508 static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, 02509 double dRate) { 02510 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02511 02512 FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate); 02513 02514 return S_OK; 02515 } 02516 02517 static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, 02518 double *pdRate) { 02519 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02520 02521 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate); 02522 02523 return S_OK; 02524 } 02525 02526 static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, 02527 LONGLONG *pllPreroll) { 02528 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); 02529 02530 FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll); 02531 02532 return S_OK; 02533 } 02534 02535 02536 static const IMediaSeekingVtbl IMediaSeeking_VTable = 02537 { 02538 MediaSeeking_QueryInterface, 02539 MediaSeeking_AddRef, 02540 MediaSeeking_Release, 02541 MediaSeeking_GetCapabilities, 02542 MediaSeeking_CheckCapabilities, 02543 MediaSeeking_IsFormatSupported, 02544 MediaSeeking_QueryPreferredFormat, 02545 MediaSeeking_GetTimeFormat, 02546 MediaSeeking_IsUsingTimeFormat, 02547 MediaSeeking_SetTimeFormat, 02548 MediaSeeking_GetDuration, 02549 MediaSeeking_GetStopPosition, 02550 MediaSeeking_GetCurrentPosition, 02551 MediaSeeking_ConvertTimeFormat, 02552 MediaSeeking_SetPositions, 02553 MediaSeeking_GetPositions, 02554 MediaSeeking_GetAvailable, 02555 MediaSeeking_SetRate, 02556 MediaSeeking_GetRate, 02557 MediaSeeking_GetPreroll 02558 }; 02559 02560 static inline IFilterGraphImpl *impl_from_IMediaPosition( IMediaPosition *iface ) 02561 { 02562 return (IFilterGraphImpl *)((char*)iface - FIELD_OFFSET(IFilterGraphImpl, IMediaPosition_vtbl)); 02563 } 02564 02565 /*** IUnknown methods ***/ 02566 static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID riid, void** ppvObj) 02567 { 02568 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02569 02570 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 02571 return Filtergraph_QueryInterface(This, riid, ppvObj); 02572 } 02573 02574 static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface) 02575 { 02576 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02577 02578 TRACE("(%p/%p)->()\n", This, iface); 02579 return Filtergraph_AddRef(This); 02580 } 02581 02582 static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface) 02583 { 02584 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02585 02586 TRACE("(%p/%p)->()\n", This, iface); 02587 return Filtergraph_Release(This); 02588 } 02589 02590 /*** IDispatch methods ***/ 02591 static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){ 02592 FIXME("(%p) stub!\n", iface); 02593 return E_NOTIMPL; 02594 } 02595 02596 static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){ 02597 FIXME("(%p) stub!\n", iface); 02598 return E_NOTIMPL; 02599 } 02600 02601 static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){ 02602 FIXME("(%p) stub!\n", iface); 02603 return E_NOTIMPL; 02604 } 02605 02606 static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){ 02607 FIXME("(%p) stub!\n", iface); 02608 return E_NOTIMPL; 02609 } 02610 02611 /*** IMediaPosition methods ***/ 02612 static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength) 02613 { 02614 LONGLONG duration; 02615 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02616 HRESULT hr = IMediaSeeking_GetDuration( (IMediaSeeking *)&This->IMediaSeeking_vtbl, &duration ); 02617 if (SUCCEEDED(hr)) *plength = duration; 02618 return hr; 02619 } 02620 02621 static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime) 02622 { 02623 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02624 LONGLONG reftime = llTime; 02625 02626 return IMediaSeeking_SetPositions((IMediaSeeking *)&This->IMediaSeeking_vtbl, 02627 &reftime, AM_SEEKING_AbsolutePositioning, 02628 NULL, AM_SEEKING_NoPositioning); 02629 } 02630 02631 static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime) 02632 { 02633 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02634 LONGLONG pos; 02635 HRESULT hr = IMediaSeeking_GetCurrentPosition( (IMediaSeeking *)&This->IMediaSeeking_vtbl, &pos ); 02636 if (SUCCEEDED(hr)) *pllTime = pos; 02637 return hr; 02638 } 02639 02640 static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime) 02641 { 02642 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02643 LONGLONG pos; 02644 HRESULT hr = IMediaSeeking_GetStopPosition( (IMediaSeeking *)&This->IMediaSeeking_vtbl, &pos ); 02645 if (SUCCEEDED(hr)) *pllTime = pos; 02646 return hr; 02647 } 02648 02649 static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime) 02650 { 02651 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02652 LONGLONG reftime = llTime; 02653 02654 return IMediaSeeking_SetPositions((IMediaSeeking *)&This->IMediaSeeking_vtbl, 02655 NULL, AM_SEEKING_NoPositioning, 02656 &reftime, AM_SEEKING_AbsolutePositioning); 02657 } 02658 02659 static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){ 02660 FIXME("(%p)->(%p) stub!\n", iface, pllTime); 02661 return E_NOTIMPL; 02662 } 02663 02664 static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){ 02665 FIXME("(%p)->(%f) stub!\n", iface, llTime); 02666 return E_NOTIMPL; 02667 } 02668 02669 static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate) 02670 { 02671 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02672 return IMediaSeeking_SetRate((IMediaSeeking *)&This->IMediaSeeking_vtbl, dRate); 02673 } 02674 02675 static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate) 02676 { 02677 IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); 02678 return IMediaSeeking_GetRate((IMediaSeeking *)&This->IMediaSeeking_vtbl, pdRate); 02679 } 02680 02681 static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){ 02682 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward); 02683 return E_NOTIMPL; 02684 } 02685 02686 static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){ 02687 FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward); 02688 return E_NOTIMPL; 02689 } 02690 02691 02692 static const IMediaPositionVtbl IMediaPosition_VTable = 02693 { 02694 MediaPosition_QueryInterface, 02695 MediaPosition_AddRef, 02696 MediaPosition_Release, 02697 MediaPosition_GetTypeInfoCount, 02698 MediaPosition_GetTypeInfo, 02699 MediaPosition_GetIDsOfNames, 02700 MediaPosition_Invoke, 02701 MediaPosition_get_Duration, 02702 MediaPosition_put_CurrentPosition, 02703 MediaPosition_get_CurrentPosition, 02704 MediaPosition_get_StopTime, 02705 MediaPosition_put_StopTime, 02706 MediaPosition_get_PrerollTime, 02707 MediaPosition_put_PrerollTime, 02708 MediaPosition_put_Rate, 02709 MediaPosition_get_Rate, 02710 MediaPosition_CanSeekForward, 02711 MediaPosition_CanSeekBackward 02712 }; 02713 02714 static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj) 02715 { 02716 HRESULT hr = E_NOINTERFACE; 02717 int i; 02718 int entry; 02719 02720 /* Check if the interface type is already registered */ 02721 for (entry = 0; entry < pGraph->nItfCacheEntries; entry++) 02722 if (riid == pGraph->ItfCacheEntries[entry].riid) 02723 { 02724 if (pGraph->ItfCacheEntries[entry].iface) 02725 { 02726 /* Return the interface if available */ 02727 *ppvObj = pGraph->ItfCacheEntries[entry].iface; 02728 return S_OK; 02729 } 02730 break; 02731 } 02732 02733 if (entry >= MAX_ITF_CACHE_ENTRIES) 02734 { 02735 FIXME("Not enough space to store interface in the cache\n"); 02736 return E_OUTOFMEMORY; 02737 } 02738 02739 /* Find a filter supporting the requested interface */ 02740 for (i = 0; i < pGraph->nFilters; i++) 02741 { 02742 hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj); 02743 if (hr == S_OK) 02744 { 02745 pGraph->ItfCacheEntries[entry].riid = riid; 02746 pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i]; 02747 pGraph->ItfCacheEntries[entry].iface = *ppvObj; 02748 if (entry >= pGraph->nItfCacheEntries) 02749 pGraph->nItfCacheEntries++; 02750 return S_OK; 02751 } 02752 if (hr != E_NOINTERFACE) 02753 return hr; 02754 } 02755 02756 return hr; 02757 } 02758 02759 /*** IUnknown methods ***/ 02760 static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, 02761 REFIID riid, 02762 LPVOID*ppvObj) { 02763 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02764 02765 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 02766 02767 return Filtergraph_QueryInterface(This, riid, ppvObj); 02768 } 02769 02770 static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) { 02771 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02772 02773 TRACE("(%p/%p)->()\n", This, iface); 02774 02775 return Filtergraph_AddRef(This); 02776 } 02777 02778 static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) { 02779 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02780 02781 TRACE("(%p/%p)->()\n", This, iface); 02782 02783 return Filtergraph_Release(This); 02784 } 02785 02786 /*** IDispatch methods ***/ 02787 static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, 02788 UINT*pctinfo) { 02789 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02790 IBasicAudio* pBasicAudio; 02791 HRESULT hr; 02792 02793 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo); 02794 02795 EnterCriticalSection(&This->cs); 02796 02797 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02798 02799 if (hr == S_OK) 02800 hr = IBasicAudio_GetTypeInfoCount(pBasicAudio, pctinfo); 02801 02802 LeaveCriticalSection(&This->cs); 02803 02804 return hr; 02805 } 02806 02807 static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, 02808 UINT iTInfo, 02809 LCID lcid, 02810 ITypeInfo**ppTInfo) { 02811 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02812 IBasicAudio* pBasicAudio; 02813 HRESULT hr; 02814 02815 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo); 02816 02817 EnterCriticalSection(&This->cs); 02818 02819 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02820 02821 if (hr == S_OK) 02822 hr = IBasicAudio_GetTypeInfo(pBasicAudio, iTInfo, lcid, ppTInfo); 02823 02824 LeaveCriticalSection(&This->cs); 02825 02826 return hr; 02827 } 02828 02829 static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, 02830 REFIID riid, 02831 LPOLESTR*rgszNames, 02832 UINT cNames, 02833 LCID lcid, 02834 DISPID*rgDispId) { 02835 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02836 IBasicAudio* pBasicAudio; 02837 HRESULT hr; 02838 02839 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); 02840 02841 EnterCriticalSection(&This->cs); 02842 02843 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02844 02845 if (hr == S_OK) 02846 hr = IBasicAudio_GetIDsOfNames(pBasicAudio, riid, rgszNames, cNames, lcid, rgDispId); 02847 02848 LeaveCriticalSection(&This->cs); 02849 02850 return hr; 02851 } 02852 02853 static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, 02854 DISPID dispIdMember, 02855 REFIID riid, 02856 LCID lcid, 02857 WORD wFlags, 02858 DISPPARAMS*pDispParams, 02859 VARIANT*pVarResult, 02860 EXCEPINFO*pExepInfo, 02861 UINT*puArgErr) { 02862 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02863 IBasicAudio* pBasicAudio; 02864 HRESULT hr; 02865 02866 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 02867 02868 EnterCriticalSection(&This->cs); 02869 02870 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02871 02872 if (hr == S_OK) 02873 hr = IBasicAudio_Invoke(pBasicAudio, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 02874 02875 LeaveCriticalSection(&This->cs); 02876 02877 return hr; 02878 } 02879 02880 /*** IBasicAudio methods ***/ 02881 static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, 02882 LONG lVolume) { 02883 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02884 IBasicAudio* pBasicAudio; 02885 HRESULT hr; 02886 02887 TRACE("(%p/%p)->(%d)\n", This, iface, lVolume); 02888 02889 EnterCriticalSection(&This->cs); 02890 02891 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02892 02893 if (hr == S_OK) 02894 hr = IBasicAudio_put_Volume(pBasicAudio, lVolume); 02895 02896 LeaveCriticalSection(&This->cs); 02897 02898 return hr; 02899 } 02900 02901 static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, 02902 LONG *plVolume) { 02903 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02904 IBasicAudio* pBasicAudio; 02905 HRESULT hr; 02906 02907 TRACE("(%p/%p)->(%p)\n", This, iface, plVolume); 02908 02909 EnterCriticalSection(&This->cs); 02910 02911 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02912 02913 if (hr == S_OK) 02914 hr = IBasicAudio_get_Volume(pBasicAudio, plVolume); 02915 02916 LeaveCriticalSection(&This->cs); 02917 02918 return hr; 02919 } 02920 02921 static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, 02922 LONG lBalance) { 02923 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02924 IBasicAudio* pBasicAudio; 02925 HRESULT hr; 02926 02927 TRACE("(%p/%p)->(%d)\n", This, iface, lBalance); 02928 02929 EnterCriticalSection(&This->cs); 02930 02931 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02932 02933 if (hr == S_OK) 02934 hr = IBasicAudio_put_Balance(pBasicAudio, lBalance); 02935 02936 LeaveCriticalSection(&This->cs); 02937 02938 return hr; 02939 } 02940 02941 static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, 02942 LONG *plBalance) { 02943 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); 02944 IBasicAudio* pBasicAudio; 02945 HRESULT hr; 02946 02947 TRACE("(%p/%p)->(%p)\n", This, iface, plBalance); 02948 02949 EnterCriticalSection(&This->cs); 02950 02951 hr = GetTargetInterface(This, &IID_IBasicAudio, (LPVOID*)&pBasicAudio); 02952 02953 if (hr == S_OK) 02954 hr = IBasicAudio_get_Balance(pBasicAudio, plBalance); 02955 02956 LeaveCriticalSection(&This->cs); 02957 02958 return hr; 02959 } 02960 02961 static const IBasicAudioVtbl IBasicAudio_VTable = 02962 { 02963 BasicAudio_QueryInterface, 02964 BasicAudio_AddRef, 02965 BasicAudio_Release, 02966 BasicAudio_GetTypeInfoCount, 02967 BasicAudio_GetTypeInfo, 02968 BasicAudio_GetIDsOfNames, 02969 BasicAudio_Invoke, 02970 BasicAudio_put_Volume, 02971 BasicAudio_get_Volume, 02972 BasicAudio_put_Balance, 02973 BasicAudio_get_Balance 02974 }; 02975 02976 /*** IUnknown methods ***/ 02977 static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, 02978 REFIID riid, 02979 LPVOID*ppvObj) { 02980 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 02981 02982 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 02983 02984 return Filtergraph_QueryInterface(This, riid, ppvObj); 02985 } 02986 02987 static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) { 02988 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 02989 02990 TRACE("(%p/%p)->()\n", This, iface); 02991 02992 return Filtergraph_AddRef(This); 02993 } 02994 02995 static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) { 02996 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 02997 02998 TRACE("(%p/%p)->()\n", This, iface); 02999 03000 return Filtergraph_Release(This); 03001 } 03002 03003 /*** IDispatch methods ***/ 03004 static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, 03005 UINT*pctinfo) { 03006 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03007 IBasicVideo* pBasicVideo; 03008 HRESULT hr; 03009 03010 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo); 03011 03012 EnterCriticalSection(&This->cs); 03013 03014 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03015 03016 if (hr == S_OK) 03017 hr = IBasicVideo_GetTypeInfoCount(pBasicVideo, pctinfo); 03018 03019 LeaveCriticalSection(&This->cs); 03020 03021 return hr; 03022 } 03023 03024 static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, 03025 UINT iTInfo, 03026 LCID lcid, 03027 ITypeInfo**ppTInfo) { 03028 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03029 IBasicVideo* pBasicVideo; 03030 HRESULT hr; 03031 03032 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo); 03033 03034 EnterCriticalSection(&This->cs); 03035 03036 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03037 03038 if (hr == S_OK) 03039 hr = IBasicVideo_GetTypeInfo(pBasicVideo, iTInfo, lcid, ppTInfo); 03040 03041 LeaveCriticalSection(&This->cs); 03042 03043 return hr; 03044 } 03045 03046 static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, 03047 REFIID riid, 03048 LPOLESTR*rgszNames, 03049 UINT cNames, 03050 LCID lcid, 03051 DISPID*rgDispId) { 03052 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03053 IBasicVideo* pBasicVideo; 03054 HRESULT hr; 03055 03056 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); 03057 03058 EnterCriticalSection(&This->cs); 03059 03060 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03061 03062 if (hr == S_OK) 03063 hr = IBasicVideo_GetIDsOfNames(pBasicVideo, riid, rgszNames, cNames, lcid, rgDispId); 03064 03065 LeaveCriticalSection(&This->cs); 03066 03067 return hr; 03068 } 03069 03070 static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, 03071 DISPID dispIdMember, 03072 REFIID riid, 03073 LCID lcid, 03074 WORD wFlags, 03075 DISPPARAMS*pDispParams, 03076 VARIANT*pVarResult, 03077 EXCEPINFO*pExepInfo, 03078 UINT*puArgErr) { 03079 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03080 IBasicVideo* pBasicVideo; 03081 HRESULT hr; 03082 03083 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 03084 03085 EnterCriticalSection(&This->cs); 03086 03087 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03088 03089 if (hr == S_OK) 03090 hr = IBasicVideo_Invoke(pBasicVideo, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 03091 03092 LeaveCriticalSection(&This->cs); 03093 03094 return hr; 03095 } 03096 03097 /*** IBasicVideo methods ***/ 03098 static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, 03099 REFTIME *pAvgTimePerFrame) { 03100 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03101 IBasicVideo* pBasicVideo; 03102 HRESULT hr; 03103 03104 TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame); 03105 03106 EnterCriticalSection(&This->cs); 03107 03108 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03109 03110 if (hr == S_OK) 03111 hr = IBasicVideo_get_AvgTimePerFrame(pBasicVideo, pAvgTimePerFrame); 03112 03113 LeaveCriticalSection(&This->cs); 03114 03115 return hr; 03116 } 03117 03118 static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, 03119 LONG *pBitRate) { 03120 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03121 IBasicVideo* pBasicVideo; 03122 HRESULT hr; 03123 03124 TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate); 03125 03126 EnterCriticalSection(&This->cs); 03127 03128 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03129 03130 if (hr == S_OK) 03131 hr = IBasicVideo_get_BitRate(pBasicVideo, pBitRate); 03132 03133 LeaveCriticalSection(&This->cs); 03134 03135 return hr; 03136 } 03137 03138 static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, 03139 LONG *pBitErrorRate) { 03140 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03141 IBasicVideo* pBasicVideo; 03142 HRESULT hr; 03143 03144 TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate); 03145 03146 EnterCriticalSection(&This->cs); 03147 03148 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03149 03150 if (hr == S_OK) 03151 hr = IBasicVideo_get_BitErrorRate(pBasicVideo, pBitErrorRate); 03152 03153 LeaveCriticalSection(&This->cs); 03154 03155 return hr; 03156 } 03157 03158 static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, 03159 LONG *pVideoWidth) { 03160 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03161 IBasicVideo* pBasicVideo; 03162 HRESULT hr; 03163 03164 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth); 03165 03166 EnterCriticalSection(&This->cs); 03167 03168 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03169 03170 if (hr == S_OK) 03171 hr = IBasicVideo_get_VideoWidth(pBasicVideo, pVideoWidth); 03172 03173 LeaveCriticalSection(&This->cs); 03174 03175 return hr; 03176 } 03177 03178 static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, 03179 LONG *pVideoHeight) { 03180 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03181 IBasicVideo* pBasicVideo; 03182 HRESULT hr; 03183 03184 TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight); 03185 03186 EnterCriticalSection(&This->cs); 03187 03188 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03189 03190 if (hr == S_OK) 03191 hr = IBasicVideo_get_VideoHeight(pBasicVideo, pVideoHeight); 03192 03193 LeaveCriticalSection(&This->cs); 03194 03195 return hr; 03196 } 03197 03198 static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, 03199 LONG SourceLeft) { 03200 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03201 IBasicVideo* pBasicVideo; 03202 HRESULT hr; 03203 03204 TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft); 03205 03206 EnterCriticalSection(&This->cs); 03207 03208 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03209 03210 if (hr == S_OK) 03211 hr = IBasicVideo_put_SourceLeft(pBasicVideo, SourceLeft); 03212 03213 LeaveCriticalSection(&This->cs); 03214 03215 return hr; 03216 } 03217 03218 static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, 03219 LONG *pSourceLeft) { 03220 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03221 IBasicVideo* pBasicVideo; 03222 HRESULT hr; 03223 03224 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft); 03225 03226 EnterCriticalSection(&This->cs); 03227 03228 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03229 03230 if (hr == S_OK) 03231 hr = IBasicVideo_get_SourceLeft(pBasicVideo, pSourceLeft); 03232 03233 LeaveCriticalSection(&This->cs); 03234 03235 return hr; 03236 } 03237 03238 static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, 03239 LONG SourceWidth) { 03240 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03241 IBasicVideo* pBasicVideo; 03242 HRESULT hr; 03243 03244 TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth); 03245 03246 EnterCriticalSection(&This->cs); 03247 03248 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03249 03250 if (hr == S_OK) 03251 hr = IBasicVideo_put_SourceWidth(pBasicVideo, SourceWidth); 03252 03253 LeaveCriticalSection(&This->cs); 03254 03255 return hr; 03256 } 03257 03258 static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, 03259 LONG *pSourceWidth) { 03260 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03261 IBasicVideo* pBasicVideo; 03262 HRESULT hr; 03263 03264 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth); 03265 03266 EnterCriticalSection(&This->cs); 03267 03268 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03269 03270 if (hr == S_OK) 03271 hr = IBasicVideo_get_SourceWidth(pBasicVideo, pSourceWidth); 03272 03273 LeaveCriticalSection(&This->cs); 03274 03275 return hr; 03276 } 03277 03278 static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, 03279 LONG SourceTop) { 03280 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03281 IBasicVideo* pBasicVideo; 03282 HRESULT hr; 03283 03284 TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop); 03285 03286 EnterCriticalSection(&This->cs); 03287 03288 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03289 03290 if (hr == S_OK) 03291 hr = IBasicVideo_put_SourceTop(pBasicVideo, SourceTop); 03292 03293 LeaveCriticalSection(&This->cs); 03294 03295 return hr; 03296 } 03297 03298 static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, 03299 LONG *pSourceTop) { 03300 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03301 IBasicVideo* pBasicVideo; 03302 HRESULT hr; 03303 03304 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop); 03305 03306 EnterCriticalSection(&This->cs); 03307 03308 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03309 03310 if (hr == S_OK) 03311 hr = IBasicVideo_get_SourceTop(pBasicVideo, pSourceTop); 03312 03313 LeaveCriticalSection(&This->cs); 03314 03315 return hr; 03316 } 03317 03318 static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, 03319 LONG SourceHeight) { 03320 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03321 IBasicVideo* pBasicVideo; 03322 HRESULT hr; 03323 03324 TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight); 03325 03326 EnterCriticalSection(&This->cs); 03327 03328 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03329 03330 if (hr == S_OK) 03331 hr = IBasicVideo_put_SourceHeight(pBasicVideo, SourceHeight); 03332 03333 LeaveCriticalSection(&This->cs); 03334 03335 return hr; 03336 } 03337 03338 static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, 03339 LONG *pSourceHeight) { 03340 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03341 IBasicVideo* pBasicVideo; 03342 HRESULT hr; 03343 03344 TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight); 03345 03346 EnterCriticalSection(&This->cs); 03347 03348 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03349 03350 if (hr == S_OK) 03351 hr = IBasicVideo_get_SourceHeight(pBasicVideo, pSourceHeight); 03352 03353 LeaveCriticalSection(&This->cs); 03354 03355 return hr; 03356 } 03357 03358 static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, 03359 LONG DestinationLeft) { 03360 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03361 IBasicVideo* pBasicVideo; 03362 HRESULT hr; 03363 03364 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft); 03365 03366 EnterCriticalSection(&This->cs); 03367 03368 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03369 03370 if (hr == S_OK) 03371 hr = IBasicVideo_put_DestinationLeft(pBasicVideo, DestinationLeft); 03372 03373 LeaveCriticalSection(&This->cs); 03374 03375 return hr; 03376 } 03377 03378 static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, 03379 LONG *pDestinationLeft) { 03380 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03381 IBasicVideo* pBasicVideo; 03382 HRESULT hr; 03383 03384 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft); 03385 03386 EnterCriticalSection(&This->cs); 03387 03388 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03389 03390 if (hr == S_OK) 03391 hr = IBasicVideo_get_DestinationLeft(pBasicVideo, pDestinationLeft); 03392 03393 LeaveCriticalSection(&This->cs); 03394 03395 return hr; 03396 } 03397 03398 static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, 03399 LONG DestinationWidth) { 03400 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03401 IBasicVideo* pBasicVideo; 03402 HRESULT hr; 03403 03404 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth); 03405 03406 EnterCriticalSection(&This->cs); 03407 03408 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03409 03410 if (hr == S_OK) 03411 hr = IBasicVideo_put_DestinationWidth(pBasicVideo, DestinationWidth); 03412 03413 LeaveCriticalSection(&This->cs); 03414 03415 return hr; 03416 } 03417 03418 static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, 03419 LONG *pDestinationWidth) { 03420 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03421 IBasicVideo* pBasicVideo; 03422 HRESULT hr; 03423 03424 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth); 03425 03426 EnterCriticalSection(&This->cs); 03427 03428 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03429 03430 if (hr == S_OK) 03431 hr = IBasicVideo_get_DestinationWidth(pBasicVideo, pDestinationWidth); 03432 03433 LeaveCriticalSection(&This->cs); 03434 03435 return hr; 03436 } 03437 03438 static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, 03439 LONG DestinationTop) { 03440 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03441 IBasicVideo* pBasicVideo; 03442 HRESULT hr; 03443 03444 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop); 03445 03446 EnterCriticalSection(&This->cs); 03447 03448 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03449 03450 if (hr == S_OK) 03451 hr = IBasicVideo_put_DestinationTop(pBasicVideo, DestinationTop); 03452 03453 LeaveCriticalSection(&This->cs); 03454 03455 return hr; 03456 } 03457 03458 static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, 03459 LONG *pDestinationTop) { 03460 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03461 IBasicVideo* pBasicVideo; 03462 HRESULT hr; 03463 03464 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop); 03465 03466 EnterCriticalSection(&This->cs); 03467 03468 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03469 03470 if (hr == S_OK) 03471 hr = IBasicVideo_get_DestinationTop(pBasicVideo, pDestinationTop); 03472 03473 LeaveCriticalSection(&This->cs); 03474 03475 return hr; 03476 } 03477 03478 static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, 03479 LONG DestinationHeight) { 03480 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03481 IBasicVideo* pBasicVideo; 03482 HRESULT hr; 03483 03484 TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight); 03485 03486 EnterCriticalSection(&This->cs); 03487 03488 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03489 03490 if (hr == S_OK) 03491 hr = IBasicVideo_put_DestinationHeight(pBasicVideo, DestinationHeight); 03492 03493 LeaveCriticalSection(&This->cs); 03494 03495 return hr; 03496 } 03497 03498 static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface, 03499 LONG *pDestinationHeight) { 03500 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03501 IBasicVideo* pBasicVideo; 03502 HRESULT hr; 03503 03504 TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight); 03505 03506 EnterCriticalSection(&This->cs); 03507 03508 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03509 03510 if (hr == S_OK) 03511 hr = IBasicVideo_get_DestinationHeight(pBasicVideo, pDestinationHeight); 03512 03513 LeaveCriticalSection(&This->cs); 03514 03515 return hr; 03516 } 03517 03518 static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, 03519 LONG Left, 03520 LONG Top, 03521 LONG Width, 03522 LONG Height) { 03523 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03524 IBasicVideo* pBasicVideo; 03525 HRESULT hr; 03526 03527 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); 03528 03529 EnterCriticalSection(&This->cs); 03530 03531 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03532 03533 if (hr == S_OK) 03534 hr = IBasicVideo_SetSourcePosition(pBasicVideo, Left, Top, Width, Height); 03535 03536 LeaveCriticalSection(&This->cs); 03537 03538 return hr; 03539 } 03540 03541 static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, 03542 LONG *pLeft, 03543 LONG *pTop, 03544 LONG *pWidth, 03545 LONG *pHeight) { 03546 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03547 IBasicVideo* pBasicVideo; 03548 HRESULT hr; 03549 03550 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); 03551 03552 EnterCriticalSection(&This->cs); 03553 03554 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03555 03556 if (hr == S_OK) 03557 hr = IBasicVideo_GetSourcePosition(pBasicVideo, pLeft, pTop, pWidth, pHeight); 03558 03559 LeaveCriticalSection(&This->cs); 03560 03561 return hr; 03562 } 03563 03564 static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) { 03565 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03566 IBasicVideo* pBasicVideo; 03567 HRESULT hr; 03568 03569 TRACE("(%p/%p)->()\n", This, iface); 03570 03571 EnterCriticalSection(&This->cs); 03572 03573 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03574 03575 if (hr == S_OK) 03576 hr = IBasicVideo_SetDefaultSourcePosition(pBasicVideo); 03577 03578 LeaveCriticalSection(&This->cs); 03579 03580 return hr; 03581 } 03582 03583 static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, 03584 LONG Left, 03585 LONG Top, 03586 LONG Width, 03587 LONG Height) { 03588 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03589 IBasicVideo* pBasicVideo; 03590 HRESULT hr; 03591 03592 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); 03593 03594 EnterCriticalSection(&This->cs); 03595 03596 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03597 03598 if (hr == S_OK) 03599 hr = IBasicVideo_SetDestinationPosition(pBasicVideo, Left, Top, Width, Height); 03600 03601 LeaveCriticalSection(&This->cs); 03602 03603 return hr; 03604 } 03605 03606 static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, 03607 LONG *pLeft, 03608 LONG *pTop, 03609 LONG *pWidth, 03610 LONG *pHeight) { 03611 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03612 IBasicVideo* pBasicVideo; 03613 HRESULT hr; 03614 03615 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); 03616 03617 EnterCriticalSection(&This->cs); 03618 03619 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03620 03621 if (hr == S_OK) 03622 hr = IBasicVideo_GetDestinationPosition(pBasicVideo, pLeft, pTop, pWidth, pHeight); 03623 03624 LeaveCriticalSection(&This->cs); 03625 03626 return hr; 03627 } 03628 03629 static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface) { 03630 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03631 IBasicVideo* pBasicVideo; 03632 HRESULT hr; 03633 03634 TRACE("(%p/%p)->()\n", This, iface); 03635 03636 EnterCriticalSection(&This->cs); 03637 03638 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03639 03640 if (hr == S_OK) 03641 hr = IBasicVideo_SetDefaultDestinationPosition(pBasicVideo); 03642 03643 LeaveCriticalSection(&This->cs); 03644 03645 return hr; 03646 } 03647 03648 static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, 03649 LONG *pWidth, 03650 LONG *pHeight) { 03651 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03652 IBasicVideo* pBasicVideo; 03653 HRESULT hr; 03654 03655 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); 03656 03657 EnterCriticalSection(&This->cs); 03658 03659 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03660 03661 if (hr == S_OK) 03662 hr = IBasicVideo_GetVideoSize(pBasicVideo, pWidth, pHeight); 03663 03664 LeaveCriticalSection(&This->cs); 03665 03666 return hr; 03667 } 03668 03669 static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, 03670 LONG StartIndex, 03671 LONG Entries, 03672 LONG *pRetrieved, 03673 LONG *pPalette) { 03674 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03675 IBasicVideo* pBasicVideo; 03676 HRESULT hr; 03677 03678 TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette); 03679 03680 EnterCriticalSection(&This->cs); 03681 03682 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03683 03684 if (hr == S_OK) 03685 hr = IBasicVideo_GetVideoPaletteEntries(pBasicVideo, StartIndex, Entries, pRetrieved, pPalette); 03686 03687 LeaveCriticalSection(&This->cs); 03688 03689 return hr; 03690 } 03691 03692 static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, 03693 LONG *pBufferSize, 03694 LONG *pDIBImage) { 03695 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03696 IBasicVideo* pBasicVideo; 03697 HRESULT hr; 03698 03699 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage); 03700 03701 EnterCriticalSection(&This->cs); 03702 03703 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03704 03705 if (hr == S_OK) 03706 hr = IBasicVideo_GetCurrentImage(pBasicVideo, pBufferSize, pDIBImage); 03707 03708 LeaveCriticalSection(&This->cs); 03709 03710 return hr; 03711 } 03712 03713 static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) { 03714 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03715 IBasicVideo* pBasicVideo; 03716 HRESULT hr; 03717 03718 TRACE("(%p/%p)->()\n", This, iface); 03719 03720 EnterCriticalSection(&This->cs); 03721 03722 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03723 03724 if (hr == S_OK) 03725 hr = IBasicVideo_IsUsingDefaultSource(pBasicVideo); 03726 03727 LeaveCriticalSection(&This->cs); 03728 03729 return hr; 03730 } 03731 03732 static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) { 03733 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03734 IBasicVideo* pBasicVideo; 03735 HRESULT hr; 03736 03737 TRACE("(%p/%p)->()\n", This, iface); 03738 03739 EnterCriticalSection(&This->cs); 03740 03741 hr = GetTargetInterface(This, &IID_IBasicVideo, (LPVOID*)&pBasicVideo); 03742 03743 if (hr == S_OK) 03744 hr = IBasicVideo_IsUsingDefaultDestination(pBasicVideo); 03745 03746 LeaveCriticalSection(&This->cs); 03747 03748 return hr; 03749 } 03750 03751 static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX, LONG *plAspectY) { 03752 ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); 03753 IBasicVideo2 *pBasicVideo2; 03754 HRESULT hr; 03755 03756 TRACE("(%p/%p)->()\n", This, iface); 03757 03758 EnterCriticalSection(&This->cs); 03759 03760 hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2); 03761 03762 if (hr == S_OK) 03763 hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY); 03764 03765 LeaveCriticalSection(&This->cs); 03766 03767 return hr; 03768 } 03769 03770 static const IBasicVideo2Vtbl IBasicVideo_VTable = 03771 { 03772 BasicVideo_QueryInterface, 03773 BasicVideo_AddRef, 03774 BasicVideo_Release, 03775 BasicVideo_GetTypeInfoCount, 03776 BasicVideo_GetTypeInfo, 03777 BasicVideo_GetIDsOfNames, 03778 BasicVideo_Invoke, 03779 BasicVideo_get_AvgTimePerFrame, 03780 BasicVideo_get_BitRate, 03781 BasicVideo_get_BitErrorRate, 03782 BasicVideo_get_VideoWidth, 03783 BasicVideo_get_VideoHeight, 03784 BasicVideo_put_SourceLeft, 03785 BasicVideo_get_SourceLeft, 03786 BasicVideo_put_SourceWidth, 03787 BasicVideo_get_SourceWidth, 03788 BasicVideo_put_SourceTop, 03789 BasicVideo_get_SourceTop, 03790 BasicVideo_put_SourceHeight, 03791 BasicVideo_get_SourceHeight, 03792 BasicVideo_put_DestinationLeft, 03793 BasicVideo_get_DestinationLeft, 03794 BasicVideo_put_DestinationWidth, 03795 BasicVideo_get_DestinationWidth, 03796 BasicVideo_put_DestinationTop, 03797 BasicVideo_get_DestinationTop, 03798 BasicVideo_put_DestinationHeight, 03799 BasicVideo_get_DestinationHeight, 03800 BasicVideo_SetSourcePosition, 03801 BasicVideo_GetSourcePosition, 03802 BasicVideo_SetDefaultSourcePosition, 03803 BasicVideo_SetDestinationPosition, 03804 BasicVideo_GetDestinationPosition, 03805 BasicVideo_SetDefaultDestinationPosition, 03806 BasicVideo_GetVideoSize, 03807 BasicVideo_GetVideoPaletteEntries, 03808 BasicVideo_GetCurrentImage, 03809 BasicVideo_IsUsingDefaultSource, 03810 BasicVideo_IsUsingDefaultDestination, 03811 BasicVideo2_GetPreferredAspectRatio 03812 }; 03813 03814 03815 /*** IUnknown methods ***/ 03816 static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, 03817 REFIID riid, 03818 LPVOID*ppvObj) { 03819 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03820 03821 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 03822 03823 return Filtergraph_QueryInterface(This, riid, ppvObj); 03824 } 03825 03826 static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) { 03827 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03828 03829 TRACE("(%p/%p)->()\n", This, iface); 03830 03831 return Filtergraph_AddRef(This); 03832 } 03833 03834 static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) { 03835 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03836 03837 TRACE("(%p/%p)->()\n", This, iface); 03838 03839 return Filtergraph_Release(This); 03840 } 03841 03842 /*** IDispatch methods ***/ 03843 static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, 03844 UINT*pctinfo) { 03845 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03846 IVideoWindow* pVideoWindow; 03847 HRESULT hr; 03848 03849 TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo); 03850 03851 EnterCriticalSection(&This->cs); 03852 03853 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03854 03855 if (hr == S_OK) 03856 hr = IVideoWindow_GetTypeInfoCount(pVideoWindow, pctinfo); 03857 03858 LeaveCriticalSection(&This->cs); 03859 03860 return hr; 03861 } 03862 03863 static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, 03864 UINT iTInfo, 03865 LCID lcid, 03866 ITypeInfo**ppTInfo) { 03867 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03868 IVideoWindow* pVideoWindow; 03869 HRESULT hr; 03870 03871 TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo); 03872 03873 EnterCriticalSection(&This->cs); 03874 03875 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03876 03877 if (hr == S_OK) 03878 hr = IVideoWindow_GetTypeInfo(pVideoWindow, iTInfo, lcid, ppTInfo); 03879 03880 LeaveCriticalSection(&This->cs); 03881 03882 return hr; 03883 } 03884 03885 static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, 03886 REFIID riid, 03887 LPOLESTR*rgszNames, 03888 UINT cNames, 03889 LCID lcid, 03890 DISPID*rgDispId) { 03891 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03892 IVideoWindow* pVideoWindow; 03893 HRESULT hr; 03894 03895 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); 03896 03897 EnterCriticalSection(&This->cs); 03898 03899 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03900 03901 if (hr == S_OK) 03902 hr = IVideoWindow_GetIDsOfNames(pVideoWindow, riid, rgszNames, cNames, lcid, rgDispId); 03903 03904 LeaveCriticalSection(&This->cs); 03905 03906 return hr; 03907 } 03908 03909 static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, 03910 DISPID dispIdMember, 03911 REFIID riid, 03912 LCID lcid, 03913 WORD wFlags, 03914 DISPPARAMS*pDispParams, 03915 VARIANT*pVarResult, 03916 EXCEPINFO*pExepInfo, 03917 UINT*puArgErr) { 03918 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03919 IVideoWindow* pVideoWindow; 03920 HRESULT hr; 03921 03922 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 03923 03924 EnterCriticalSection(&This->cs); 03925 03926 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03927 03928 if (hr == S_OK) 03929 hr = IVideoWindow_Invoke(pVideoWindow, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 03930 03931 LeaveCriticalSection(&This->cs); 03932 03933 return hr; 03934 } 03935 03936 03937 /*** IVideoWindow methods ***/ 03938 static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, 03939 BSTR strCaption) { 03940 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03941 IVideoWindow* pVideoWindow; 03942 HRESULT hr; 03943 03944 TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption); 03945 03946 EnterCriticalSection(&This->cs); 03947 03948 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03949 03950 if (hr == S_OK) 03951 hr = IVideoWindow_put_Caption(pVideoWindow, strCaption); 03952 03953 LeaveCriticalSection(&This->cs); 03954 03955 return hr; 03956 } 03957 03958 static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, 03959 BSTR *strCaption) { 03960 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03961 IVideoWindow* pVideoWindow; 03962 HRESULT hr; 03963 03964 TRACE("(%p/%p)->(%p)\n", This, iface, strCaption); 03965 03966 EnterCriticalSection(&This->cs); 03967 03968 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03969 03970 if (hr == S_OK) 03971 hr = IVideoWindow_get_Caption(pVideoWindow, strCaption); 03972 03973 LeaveCriticalSection(&This->cs); 03974 03975 return hr; 03976 } 03977 03978 static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, 03979 LONG WindowStyle) { 03980 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 03981 IVideoWindow* pVideoWindow; 03982 HRESULT hr; 03983 03984 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle); 03985 03986 EnterCriticalSection(&This->cs); 03987 03988 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 03989 03990 if (hr == S_OK) 03991 hr = IVideoWindow_put_WindowStyle(pVideoWindow, WindowStyle); 03992 03993 LeaveCriticalSection(&This->cs); 03994 03995 return hr; 03996 } 03997 03998 static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, 03999 LONG *WindowStyle) { 04000 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04001 IVideoWindow* pVideoWindow; 04002 HRESULT hr; 04003 04004 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle); 04005 04006 EnterCriticalSection(&This->cs); 04007 04008 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04009 04010 if (hr == S_OK) 04011 hr = IVideoWindow_get_WindowStyle(pVideoWindow, WindowStyle); 04012 04013 LeaveCriticalSection(&This->cs); 04014 04015 return hr; 04016 } 04017 04018 static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, 04019 LONG WindowStyleEx) { 04020 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04021 IVideoWindow* pVideoWindow; 04022 HRESULT hr; 04023 04024 TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx); 04025 04026 EnterCriticalSection(&This->cs); 04027 04028 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04029 04030 if (hr == S_OK) 04031 hr = IVideoWindow_put_WindowStyleEx(pVideoWindow, WindowStyleEx); 04032 04033 LeaveCriticalSection(&This->cs); 04034 04035 return hr; 04036 } 04037 04038 static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, 04039 LONG *WindowStyleEx) { 04040 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04041 IVideoWindow* pVideoWindow; 04042 HRESULT hr; 04043 04044 TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx); 04045 04046 EnterCriticalSection(&This->cs); 04047 04048 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04049 04050 if (hr == S_OK) 04051 hr = IVideoWindow_get_WindowStyleEx(pVideoWindow, WindowStyleEx); 04052 04053 LeaveCriticalSection(&This->cs); 04054 04055 return hr; 04056 } 04057 04058 static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, 04059 LONG AutoShow) { 04060 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04061 IVideoWindow* pVideoWindow; 04062 HRESULT hr; 04063 04064 TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow); 04065 04066 EnterCriticalSection(&This->cs); 04067 04068 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04069 04070 if (hr == S_OK) 04071 hr = IVideoWindow_put_AutoShow(pVideoWindow, AutoShow); 04072 04073 LeaveCriticalSection(&This->cs); 04074 04075 return hr; 04076 } 04077 04078 static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, 04079 LONG *AutoShow) { 04080 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04081 IVideoWindow* pVideoWindow; 04082 HRESULT hr; 04083 04084 TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow); 04085 04086 EnterCriticalSection(&This->cs); 04087 04088 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04089 04090 if (hr == S_OK) 04091 hr = IVideoWindow_get_AutoShow(pVideoWindow, AutoShow); 04092 04093 LeaveCriticalSection(&This->cs); 04094 04095 return hr; 04096 } 04097 04098 static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, 04099 LONG WindowState) { 04100 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04101 IVideoWindow* pVideoWindow; 04102 HRESULT hr; 04103 04104 TRACE("(%p/%p)->(%d)\n", This, iface, WindowState); 04105 04106 EnterCriticalSection(&This->cs); 04107 04108 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04109 04110 if (hr == S_OK) 04111 hr = IVideoWindow_put_WindowState(pVideoWindow, WindowState); 04112 04113 LeaveCriticalSection(&This->cs); 04114 04115 return hr; 04116 } 04117 04118 static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, 04119 LONG *WindowState) { 04120 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04121 IVideoWindow* pVideoWindow; 04122 HRESULT hr; 04123 04124 TRACE("(%p/%p)->(%p)\n", This, iface, WindowState); 04125 04126 EnterCriticalSection(&This->cs); 04127 04128 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04129 04130 if (hr == S_OK) 04131 hr = IVideoWindow_get_WindowState(pVideoWindow, WindowState); 04132 04133 LeaveCriticalSection(&This->cs); 04134 04135 return hr; 04136 } 04137 04138 static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, 04139 LONG BackgroundPalette) { 04140 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04141 IVideoWindow* pVideoWindow; 04142 HRESULT hr; 04143 04144 TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette); 04145 04146 EnterCriticalSection(&This->cs); 04147 04148 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04149 04150 if (hr == S_OK) 04151 hr = IVideoWindow_put_BackgroundPalette(pVideoWindow, BackgroundPalette); 04152 04153 LeaveCriticalSection(&This->cs); 04154 04155 return hr; 04156 } 04157 04158 static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface, 04159 LONG *pBackgroundPalette) { 04160 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04161 IVideoWindow* pVideoWindow; 04162 HRESULT hr; 04163 04164 TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette); 04165 04166 EnterCriticalSection(&This->cs); 04167 04168 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04169 04170 if (hr == S_OK) 04171 hr = IVideoWindow_get_BackgroundPalette(pVideoWindow, pBackgroundPalette); 04172 04173 LeaveCriticalSection(&This->cs); 04174 04175 return hr; 04176 } 04177 04178 static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, 04179 LONG Visible) { 04180 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04181 IVideoWindow* pVideoWindow; 04182 HRESULT hr; 04183 04184 TRACE("(%p/%p)->(%d)\n", This, iface, Visible); 04185 04186 EnterCriticalSection(&This->cs); 04187 04188 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04189 04190 if (hr == S_OK) 04191 hr = IVideoWindow_put_Visible(pVideoWindow, Visible); 04192 04193 LeaveCriticalSection(&This->cs); 04194 04195 return hr; 04196 } 04197 04198 static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, 04199 LONG *pVisible) { 04200 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04201 IVideoWindow* pVideoWindow; 04202 HRESULT hr; 04203 04204 TRACE("(%p/%p)->(%p)\n", This, iface, pVisible); 04205 04206 EnterCriticalSection(&This->cs); 04207 04208 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04209 04210 if (hr == S_OK) 04211 hr = IVideoWindow_get_Visible(pVideoWindow, pVisible); 04212 04213 LeaveCriticalSection(&This->cs); 04214 04215 return hr; 04216 } 04217 04218 static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, 04219 LONG Left) { 04220 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04221 IVideoWindow* pVideoWindow; 04222 HRESULT hr; 04223 04224 TRACE("(%p/%p)->(%d)\n", This, iface, Left); 04225 04226 EnterCriticalSection(&This->cs); 04227 04228 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04229 04230 if (hr == S_OK) 04231 hr = IVideoWindow_put_Left(pVideoWindow, Left); 04232 04233 LeaveCriticalSection(&This->cs); 04234 04235 return hr; 04236 } 04237 04238 static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, 04239 LONG *pLeft) { 04240 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04241 IVideoWindow* pVideoWindow; 04242 HRESULT hr; 04243 04244 TRACE("(%p/%p)->(%p)\n", This, iface, pLeft); 04245 04246 EnterCriticalSection(&This->cs); 04247 04248 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04249 04250 if (hr == S_OK) 04251 hr = IVideoWindow_get_Left(pVideoWindow, pLeft); 04252 04253 LeaveCriticalSection(&This->cs); 04254 04255 return hr; 04256 } 04257 04258 static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, 04259 LONG Width) { 04260 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04261 IVideoWindow* pVideoWindow; 04262 HRESULT hr; 04263 04264 TRACE("(%p/%p)->(%d)\n", This, iface, Width); 04265 04266 EnterCriticalSection(&This->cs); 04267 04268 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04269 04270 if (hr == S_OK) 04271 hr = IVideoWindow_put_Width(pVideoWindow, Width); 04272 04273 LeaveCriticalSection(&This->cs); 04274 04275 return hr; 04276 } 04277 04278 static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, 04279 LONG *pWidth) { 04280 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04281 IVideoWindow* pVideoWindow; 04282 HRESULT hr; 04283 04284 TRACE("(%p/%p)->(%p)\n", This, iface, pWidth); 04285 04286 EnterCriticalSection(&This->cs); 04287 04288 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04289 04290 if (hr == S_OK) 04291 hr = IVideoWindow_get_Width(pVideoWindow, pWidth); 04292 04293 LeaveCriticalSection(&This->cs); 04294 04295 return hr; 04296 } 04297 04298 static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, 04299 LONG Top) { 04300 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04301 IVideoWindow* pVideoWindow; 04302 HRESULT hr; 04303 04304 TRACE("(%p/%p)->(%d)\n", This, iface, Top); 04305 04306 EnterCriticalSection(&This->cs); 04307 04308 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04309 04310 if (hr == S_OK) 04311 hr = IVideoWindow_put_Top(pVideoWindow, Top); 04312 04313 LeaveCriticalSection(&This->cs); 04314 04315 return hr; 04316 } 04317 04318 static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, 04319 LONG *pTop) { 04320 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04321 IVideoWindow* pVideoWindow; 04322 HRESULT hr; 04323 04324 TRACE("(%p/%p)->(%p)\n", This, iface, pTop); 04325 04326 EnterCriticalSection(&This->cs); 04327 04328 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04329 04330 if (hr == S_OK) 04331 hr = IVideoWindow_get_Top(pVideoWindow, pTop); 04332 04333 LeaveCriticalSection(&This->cs); 04334 04335 return hr; 04336 } 04337 04338 static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, 04339 LONG Height) { 04340 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04341 IVideoWindow* pVideoWindow; 04342 HRESULT hr; 04343 04344 TRACE("(%p/%p)->(%d)\n", This, iface, Height); 04345 04346 EnterCriticalSection(&This->cs); 04347 04348 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04349 04350 if (hr == S_OK) 04351 hr = IVideoWindow_put_Height(pVideoWindow, Height); 04352 04353 LeaveCriticalSection(&This->cs); 04354 04355 return hr; 04356 } 04357 04358 static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, 04359 LONG *pHeight) { 04360 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04361 IVideoWindow* pVideoWindow; 04362 HRESULT hr; 04363 04364 TRACE("(%p/%p)->(%p)\n", This, iface, pHeight); 04365 04366 EnterCriticalSection(&This->cs); 04367 04368 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04369 04370 if (hr == S_OK) 04371 hr = IVideoWindow_get_Height(pVideoWindow, pHeight); 04372 04373 LeaveCriticalSection(&This->cs); 04374 04375 return hr; 04376 } 04377 04378 static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, 04379 OAHWND Owner) { 04380 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04381 IVideoWindow* pVideoWindow; 04382 HRESULT hr; 04383 04384 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner); 04385 04386 EnterCriticalSection(&This->cs); 04387 04388 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04389 04390 if (hr == S_OK) 04391 hr = IVideoWindow_put_Owner(pVideoWindow, Owner); 04392 04393 LeaveCriticalSection(&This->cs); 04394 04395 return hr; 04396 } 04397 04398 static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, 04399 OAHWND *Owner) { 04400 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04401 IVideoWindow* pVideoWindow; 04402 HRESULT hr; 04403 04404 TRACE("(%p/%p)->(%p)\n", This, iface, Owner); 04405 04406 EnterCriticalSection(&This->cs); 04407 04408 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04409 04410 if (hr == S_OK) 04411 hr = IVideoWindow_get_Owner(pVideoWindow, Owner); 04412 04413 LeaveCriticalSection(&This->cs); 04414 04415 return hr; 04416 } 04417 04418 static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, 04419 OAHWND Drain) { 04420 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04421 IVideoWindow* pVideoWindow; 04422 HRESULT hr; 04423 04424 TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain); 04425 04426 EnterCriticalSection(&This->cs); 04427 04428 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04429 04430 if (hr == S_OK) 04431 hr = IVideoWindow_put_MessageDrain(pVideoWindow, Drain); 04432 04433 LeaveCriticalSection(&This->cs); 04434 04435 return hr; 04436 } 04437 04438 static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, 04439 OAHWND *Drain) { 04440 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04441 IVideoWindow* pVideoWindow; 04442 HRESULT hr; 04443 04444 TRACE("(%p/%p)->(%p)\n", This, iface, Drain); 04445 04446 EnterCriticalSection(&This->cs); 04447 04448 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04449 04450 if (hr == S_OK) 04451 hr = IVideoWindow_get_MessageDrain(pVideoWindow, Drain); 04452 04453 LeaveCriticalSection(&This->cs); 04454 04455 return hr; 04456 } 04457 04458 static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, 04459 LONG *Color) { 04460 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04461 IVideoWindow* pVideoWindow; 04462 HRESULT hr; 04463 04464 TRACE("(%p/%p)->(%p)\n", This, iface, Color); 04465 04466 EnterCriticalSection(&This->cs); 04467 04468 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04469 04470 if (hr == S_OK) 04471 hr = IVideoWindow_get_BorderColor(pVideoWindow, Color); 04472 04473 LeaveCriticalSection(&This->cs); 04474 04475 return hr; 04476 } 04477 04478 static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, 04479 LONG Color) { 04480 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04481 IVideoWindow* pVideoWindow; 04482 HRESULT hr; 04483 04484 TRACE("(%p/%p)->(%d)\n", This, iface, Color); 04485 04486 EnterCriticalSection(&This->cs); 04487 04488 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04489 04490 if (hr == S_OK) 04491 hr = IVideoWindow_put_BorderColor(pVideoWindow, Color); 04492 04493 LeaveCriticalSection(&This->cs); 04494 04495 return hr; 04496 } 04497 04498 static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, 04499 LONG *FullScreenMode) { 04500 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04501 IVideoWindow* pVideoWindow; 04502 HRESULT hr; 04503 04504 TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode); 04505 04506 EnterCriticalSection(&This->cs); 04507 04508 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04509 04510 if (hr == S_OK) 04511 hr = IVideoWindow_get_FullScreenMode(pVideoWindow, FullScreenMode); 04512 04513 LeaveCriticalSection(&This->cs); 04514 04515 return hr; 04516 } 04517 04518 static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, 04519 LONG FullScreenMode) { 04520 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04521 IVideoWindow* pVideoWindow; 04522 HRESULT hr; 04523 04524 TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode); 04525 04526 EnterCriticalSection(&This->cs); 04527 04528 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04529 04530 if (hr == S_OK) 04531 hr = IVideoWindow_put_FullScreenMode(pVideoWindow, FullScreenMode); 04532 04533 LeaveCriticalSection(&This->cs); 04534 04535 return hr; 04536 } 04537 04538 static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, 04539 LONG Focus) { 04540 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04541 IVideoWindow* pVideoWindow; 04542 HRESULT hr; 04543 04544 TRACE("(%p/%p)->(%d)\n", This, iface, Focus); 04545 04546 EnterCriticalSection(&This->cs); 04547 04548 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04549 04550 if (hr == S_OK) 04551 hr = IVideoWindow_SetWindowForeground(pVideoWindow, Focus); 04552 04553 LeaveCriticalSection(&This->cs); 04554 04555 return hr; 04556 } 04557 04558 static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, 04559 OAHWND hwnd, 04560 LONG uMsg, 04561 LONG_PTR wParam, 04562 LONG_PTR lParam) { 04563 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04564 IVideoWindow* pVideoWindow; 04565 HRESULT hr; 04566 04567 TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam); 04568 04569 EnterCriticalSection(&This->cs); 04570 04571 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04572 04573 if (hr == S_OK) 04574 hr = IVideoWindow_NotifyOwnerMessage(pVideoWindow, hwnd, uMsg, wParam, lParam); 04575 04576 LeaveCriticalSection(&This->cs); 04577 04578 return hr; 04579 } 04580 04581 static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, 04582 LONG Left, 04583 LONG Top, 04584 LONG Width, 04585 LONG Height) { 04586 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04587 IVideoWindow* pVideoWindow; 04588 HRESULT hr; 04589 04590 TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); 04591 04592 EnterCriticalSection(&This->cs); 04593 04594 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04595 04596 if (hr == S_OK) 04597 hr = IVideoWindow_SetWindowPosition(pVideoWindow, Left, Top, Width, Height); 04598 04599 LeaveCriticalSection(&This->cs); 04600 04601 return hr; 04602 } 04603 04604 static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, 04605 LONG *pLeft, 04606 LONG *pTop, 04607 LONG *pWidth, 04608 LONG *pHeight) { 04609 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04610 IVideoWindow* pVideoWindow; 04611 HRESULT hr; 04612 04613 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); 04614 04615 EnterCriticalSection(&This->cs); 04616 04617 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04618 04619 if (hr == S_OK) 04620 hr = IVideoWindow_GetWindowPosition(pVideoWindow, pLeft, pTop, pWidth, pHeight); 04621 04622 LeaveCriticalSection(&This->cs); 04623 04624 return hr; 04625 } 04626 04627 static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, 04628 LONG *pWidth, 04629 LONG *pHeight) { 04630 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04631 IVideoWindow* pVideoWindow; 04632 HRESULT hr; 04633 04634 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); 04635 04636 EnterCriticalSection(&This->cs); 04637 04638 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04639 04640 if (hr == S_OK) 04641 hr = IVideoWindow_GetMinIdealImageSize(pVideoWindow, pWidth, pHeight); 04642 04643 LeaveCriticalSection(&This->cs); 04644 04645 return hr; 04646 } 04647 04648 static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, 04649 LONG *pWidth, 04650 LONG *pHeight) { 04651 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04652 IVideoWindow* pVideoWindow; 04653 HRESULT hr; 04654 04655 TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); 04656 04657 EnterCriticalSection(&This->cs); 04658 04659 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04660 04661 if (hr == S_OK) 04662 hr = IVideoWindow_GetMaxIdealImageSize(pVideoWindow, pWidth, pHeight); 04663 04664 LeaveCriticalSection(&This->cs); 04665 04666 return hr; 04667 } 04668 04669 static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, 04670 LONG *pLeft, 04671 LONG *pTop, 04672 LONG *pWidth, 04673 LONG *pHeight) { 04674 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04675 IVideoWindow* pVideoWindow; 04676 HRESULT hr; 04677 04678 TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); 04679 04680 EnterCriticalSection(&This->cs); 04681 04682 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04683 04684 if (hr == S_OK) 04685 hr = IVideoWindow_GetRestorePosition(pVideoWindow, pLeft, pTop, pWidth, pHeight); 04686 04687 LeaveCriticalSection(&This->cs); 04688 04689 return hr; 04690 } 04691 04692 static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, 04693 LONG HideCursor) { 04694 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04695 IVideoWindow* pVideoWindow; 04696 HRESULT hr; 04697 04698 TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor); 04699 04700 EnterCriticalSection(&This->cs); 04701 04702 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04703 04704 if (hr == S_OK) 04705 hr = IVideoWindow_HideCursor(pVideoWindow, HideCursor); 04706 04707 LeaveCriticalSection(&This->cs); 04708 04709 return hr; 04710 } 04711 04712 static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, 04713 LONG *CursorHidden) { 04714 ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); 04715 IVideoWindow* pVideoWindow; 04716 HRESULT hr; 04717 04718 TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden); 04719 04720 EnterCriticalSection(&This->cs); 04721 04722 hr = GetTargetInterface(This, &IID_IVideoWindow, (LPVOID*)&pVideoWindow); 04723 04724 if (hr == S_OK) 04725 hr = IVideoWindow_IsCursorHidden(pVideoWindow, CursorHidden); 04726 04727 LeaveCriticalSection(&This->cs); 04728 04729 return hr; 04730 } 04731 04732 04733 static const IVideoWindowVtbl IVideoWindow_VTable = 04734 { 04735 VideoWindow_QueryInterface, 04736 VideoWindow_AddRef, 04737 VideoWindow_Release, 04738 VideoWindow_GetTypeInfoCount, 04739 VideoWindow_GetTypeInfo, 04740 VideoWindow_GetIDsOfNames, 04741 VideoWindow_Invoke, 04742 VideoWindow_put_Caption, 04743 VideoWindow_get_Caption, 04744 VideoWindow_put_WindowStyle, 04745 VideoWindow_get_WindowStyle, 04746 VideoWindow_put_WindowStyleEx, 04747 VideoWindow_get_WindowStyleEx, 04748 VideoWindow_put_AutoShow, 04749 VideoWindow_get_AutoShow, 04750 VideoWindow_put_WindowState, 04751 VideoWindow_get_WindowState, 04752 VideoWindow_put_BackgroundPalette, 04753 VideoWindow_get_BackgroundPalette, 04754 VideoWindow_put_Visible, 04755 VideoWindow_get_Visible, 04756 VideoWindow_put_Left, 04757 VideoWindow_get_Left, 04758 VideoWindow_put_Width, 04759 VideoWindow_get_Width, 04760 VideoWindow_put_Top, 04761 VideoWindow_get_Top, 04762 VideoWindow_put_Height, 04763 VideoWindow_get_Height, 04764 VideoWindow_put_Owner, 04765 VideoWindow_get_Owner, 04766 VideoWindow_put_MessageDrain, 04767 VideoWindow_get_MessageDrain, 04768 VideoWindow_get_BorderColor, 04769 VideoWindow_put_BorderColor, 04770 VideoWindow_get_FullScreenMode, 04771 VideoWindow_put_FullScreenMode, 04772 VideoWindow_SetWindowForeground, 04773 VideoWindow_NotifyOwnerMessage, 04774 VideoWindow_SetWindowPosition, 04775 VideoWindow_GetWindowPosition, 04776 VideoWindow_GetMinIdealImageSize, 04777 VideoWindow_GetMaxIdealImageSize, 04778 VideoWindow_GetRestorePosition, 04779 VideoWindow_HideCursor, 04780 VideoWindow_IsCursorHidden 04781 }; 04782 04783 04784 /*** IUnknown methods ***/ 04785 static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, 04786 REFIID riid, 04787 LPVOID*ppvObj) { 04788 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04789 04790 TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); 04791 04792 return Filtergraph_QueryInterface(This, riid, ppvObj); 04793 } 04794 04795 static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) { 04796 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04797 04798 TRACE("(%p/%p)->()\n", This, iface); 04799 04800 return Filtergraph_AddRef(This); 04801 } 04802 04803 static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) { 04804 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04805 04806 TRACE("(%p/%p)->()\n", This, iface); 04807 04808 return Filtergraph_Release(This); 04809 } 04810 04811 /*** IDispatch methods ***/ 04812 static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, 04813 UINT*pctinfo) { 04814 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04815 04816 TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); 04817 04818 return S_OK; 04819 } 04820 04821 static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, 04822 UINT iTInfo, 04823 LCID lcid, 04824 ITypeInfo**ppTInfo) { 04825 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04826 04827 TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); 04828 04829 return S_OK; 04830 } 04831 04832 static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, 04833 REFIID riid, 04834 LPOLESTR*rgszNames, 04835 UINT cNames, 04836 LCID lcid, 04837 DISPID*rgDispId) { 04838 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04839 04840 TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); 04841 04842 return S_OK; 04843 } 04844 04845 static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, 04846 DISPID dispIdMember, 04847 REFIID riid, 04848 LCID lcid, 04849 WORD wFlags, 04850 DISPPARAMS*pDispParams, 04851 VARIANT*pVarResult, 04852 EXCEPINFO*pExepInfo, 04853 UINT*puArgErr) { 04854 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04855 04856 TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); 04857 04858 return S_OK; 04859 } 04860 04861 /*** IMediaEvent methods ***/ 04862 static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, 04863 OAEVENT *hEvent) { 04864 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04865 04866 TRACE("(%p/%p)->(%p)\n", This, iface, hEvent); 04867 04868 *hEvent = (OAEVENT)This->evqueue.msg_event; 04869 04870 return S_OK; 04871 } 04872 04873 static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, 04874 LONG *lEventCode, 04875 LONG_PTR *lParam1, 04876 LONG_PTR *lParam2, 04877 LONG msTimeout) { 04878 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04879 Event evt; 04880 04881 TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout); 04882 04883 if (EventsQueue_GetEvent(&This->evqueue, &evt, msTimeout)) 04884 { 04885 *lEventCode = evt.lEventCode; 04886 *lParam1 = evt.lParam1; 04887 *lParam2 = evt.lParam2; 04888 return S_OK; 04889 } 04890 04891 *lEventCode = 0; 04892 return E_ABORT; 04893 } 04894 04895 static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, 04896 LONG msTimeout, 04897 LONG *pEvCode) { 04898 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04899 04900 TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode); 04901 04902 if (This->state != State_Running) 04903 return VFW_E_WRONG_STATE; 04904 04905 if (WaitForSingleObject(This->hEventCompletion, msTimeout) == WAIT_OBJECT_0) 04906 { 04907 *pEvCode = This->CompletionStatus; 04908 return S_OK; 04909 } 04910 04911 *pEvCode = 0; 04912 return E_ABORT; 04913 } 04914 04915 static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, 04916 LONG lEvCode) { 04917 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04918 04919 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode); 04920 04921 if (lEvCode == EC_COMPLETE) 04922 This->HandleEcComplete = FALSE; 04923 else if (lEvCode == EC_REPAINT) 04924 This->HandleEcRepaint = FALSE; 04925 else if (lEvCode == EC_CLOCK_CHANGED) 04926 This->HandleEcClockChanged = FALSE; 04927 else 04928 return S_FALSE; 04929 04930 return S_OK; 04931 } 04932 04933 static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, 04934 LONG lEvCode) { 04935 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04936 04937 TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode); 04938 04939 if (lEvCode == EC_COMPLETE) 04940 This->HandleEcComplete = TRUE; 04941 else if (lEvCode == EC_REPAINT) 04942 This->HandleEcRepaint = TRUE; 04943 else if (lEvCode == EC_CLOCK_CHANGED) 04944 This->HandleEcClockChanged = TRUE; 04945 else 04946 return S_FALSE; 04947 04948 return S_OK; 04949 } 04950 04951 static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, 04952 LONG lEvCode, 04953 LONG_PTR lParam1, 04954 LONG_PTR lParam2) { 04955 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04956 04957 TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2); 04958 04959 return S_OK; 04960 } 04961 04962 /*** IMediaEventEx methods ***/ 04963 static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, 04964 OAHWND hwnd, 04965 LONG lMsg, 04966 LONG_PTR lInstanceData) { 04967 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04968 04969 TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData); 04970 04971 This->notif.hWnd = (HWND)hwnd; 04972 This->notif.msg = lMsg; 04973 This->notif.instance = lInstanceData; 04974 04975 return S_OK; 04976 } 04977 04978 static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, 04979 LONG lNoNotifyFlags) { 04980 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04981 04982 TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags); 04983 04984 if ((lNoNotifyFlags != 0) && (lNoNotifyFlags != 1)) 04985 return E_INVALIDARG; 04986 04987 This->notif.disabled = lNoNotifyFlags; 04988 04989 return S_OK; 04990 } 04991 04992 static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, 04993 LONG *lplNoNotifyFlags) { 04994 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); 04995 04996 TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags); 04997 04998 if (!lplNoNotifyFlags) 04999 return E_POINTER; 05000 05001 *lplNoNotifyFlags = This->notif.disabled; 05002 05003 return S_OK; 05004 } 05005 05006 05007 static const IMediaEventExVtbl IMediaEventEx_VTable = 05008 { 05009 MediaEvent_QueryInterface, 05010 MediaEvent_AddRef, 05011 MediaEvent_Release, 05012 MediaEvent_GetTypeInfoCount, 05013 MediaEvent_GetTypeInfo, 05014 MediaEvent_GetIDsOfNames, 05015 MediaEvent_Invoke, 05016 MediaEvent_GetEventHandle, 05017 MediaEvent_GetEvent, 05018 MediaEvent_WaitForCompletion, 05019 MediaEvent_CancelDefaultHandling, 05020 MediaEvent_RestoreDefaultHandling, 05021 MediaEvent_FreeEventParams, 05022 MediaEvent_SetNotifyWindow, 05023 MediaEvent_SetNotifyFlags, 05024 MediaEvent_GetNotifyFlags 05025 }; 05026 05027 05028 static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv) 05029 { 05030 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05031 05032 return Filtergraph_QueryInterface(This, riid, ppv); 05033 } 05034 05035 static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface) 05036 { 05037 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05038 05039 return Filtergraph_AddRef(This); 05040 } 05041 05042 static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface) 05043 { 05044 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05045 05046 return Filtergraph_Release(This); 05047 } 05048 05049 static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID) 05050 { 05051 FIXME("(%p): stub\n", pClassID); 05052 05053 return E_NOTIMPL; 05054 } 05055 05056 static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface) 05057 { 05058 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05059 return MediaControl_Stop((IMediaControl*)&This->IMediaControl_vtbl); 05060 } 05061 05062 static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface) 05063 { 05064 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05065 return MediaControl_Pause((IMediaControl*)&This->IMediaControl_vtbl); 05066 } 05067 05068 static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart) 05069 { 05070 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05071 return MediaControl_Run((IMediaControl*)&This->IMediaControl_vtbl); 05072 } 05073 05074 static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState) 05075 { 05076 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05077 return MediaControl_GetState((IMediaControl*)&This->IMediaControl_vtbl, dwMsTimeout, (OAFilterState*)pState); 05078 } 05079 05080 static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock) 05081 { 05082 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05083 HRESULT hr = S_OK; 05084 int i; 05085 05086 TRACE("(%p/%p)->(%p)\n", iface, This, pClock); 05087 05088 EnterCriticalSection(&This->cs); 05089 { 05090 for (i = 0;i < This->nFilters;i++) 05091 { 05092 hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock); 05093 if (FAILED(hr)) 05094 break; 05095 } 05096 05097 if (FAILED(hr)) 05098 { 05099 for(;i >= 0;i--) 05100 IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock); 05101 } 05102 else 05103 { 05104 if (This->refClock) 05105 IReferenceClock_Release(This->refClock); 05106 This->refClock = pClock; 05107 if (This->refClock) 05108 IReferenceClock_AddRef(This->refClock); 05109 05110 if (This->HandleEcClockChanged) 05111 { 05112 IMediaEventSink *pEventSink; 05113 HRESULT eshr; 05114 05115 eshr = IMediaFilter_QueryInterface(iface, &IID_IMediaEventSink, (LPVOID)&pEventSink); 05116 if (SUCCEEDED(eshr)) 05117 { 05118 IMediaEventSink_Notify(pEventSink, EC_CLOCK_CHANGED, 0, 0); 05119 IMediaEventSink_Release(pEventSink); 05120 } 05121 } 05122 } 05123 } 05124 LeaveCriticalSection(&This->cs); 05125 05126 return hr; 05127 } 05128 05129 static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock) 05130 { 05131 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); 05132 05133 TRACE("(%p/%p)->(%p)\n", iface, This, ppClock); 05134 05135 if (!ppClock) 05136 return E_POINTER; 05137 05138 EnterCriticalSection(&This->cs); 05139 { 05140 *ppClock = This->refClock; 05141 if (*ppClock) 05142 IReferenceClock_AddRef(*ppClock); 05143 } 05144 LeaveCriticalSection(&This->cs); 05145 05146 return S_OK; 05147 } 05148 05149 static const IMediaFilterVtbl IMediaFilter_VTable = 05150 { 05151 MediaFilter_QueryInterface, 05152 MediaFilter_AddRef, 05153 MediaFilter_Release, 05154 MediaFilter_GetClassID, 05155 MediaFilter_Stop, 05156 MediaFilter_Pause, 05157 MediaFilter_Run, 05158 MediaFilter_GetState, 05159 MediaFilter_SetSyncSource, 05160 MediaFilter_GetSyncSource 05161 }; 05162 05163 static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv) 05164 { 05165 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); 05166 05167 return Filtergraph_QueryInterface(This, riid, ppv); 05168 } 05169 05170 static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface) 05171 { 05172 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); 05173 05174 return Filtergraph_AddRef(This); 05175 } 05176 05177 static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface) 05178 { 05179 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); 05180 05181 return Filtergraph_Release(This); 05182 } 05183 05184 static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2) 05185 { 05186 ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); 05187 Event evt; 05188 05189 TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2); 05190 05191 /* We need thread safety here, let's use the events queue's one */ 05192 EnterCriticalSection(&This->evqueue.msg_crst); 05193 05194 if ((EventCode == EC_COMPLETE) && This->HandleEcComplete) 05195 { 05196 TRACE("Process EC_COMPLETE notification\n"); 05197 if (++This->EcCompleteCount == This->nRenderers) 05198 { 05199 evt.lEventCode = EC_COMPLETE; 05200 evt.lParam1 = S_OK; 05201 evt.lParam2 = 0; 05202 TRACE("Send EC_COMPLETE to app\n"); 05203 EventsQueue_PutEvent(&This->evqueue, &evt); 05204 if (!This->notif.disabled && This->notif.hWnd) 05205 { 05206 TRACE("Send Window message\n"); 05207 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); 05208 } 05209 This->CompletionStatus = EC_COMPLETE; 05210 SetEvent(This->hEventCompletion); 05211 } 05212 } 05213 else if ((EventCode == EC_REPAINT) && This->HandleEcRepaint) 05214 { 05215 /* FIXME: Not handled yet */ 05216 } 05217 else 05218 { 05219 evt.lEventCode = EventCode; 05220 evt.lParam1 = EventParam1; 05221 evt.lParam2 = EventParam2; 05222 EventsQueue_PutEvent(&This->evqueue, &evt); 05223 if (!This->notif.disabled && This->notif.hWnd) 05224 PostMessageW(This->notif.hWnd, This->notif.msg, 0, This->notif.instance); 05225 } 05226 05227 LeaveCriticalSection(&This->evqueue.msg_crst); 05228 return S_OK; 05229 } 05230 05231 static const IMediaEventSinkVtbl IMediaEventSink_VTable = 05232 { 05233 MediaEventSink_QueryInterface, 05234 MediaEventSink_AddRef, 05235 MediaEventSink_Release, 05236 MediaEventSink_Notify 05237 }; 05238 05239 static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv) 05240 { 05241 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05242 05243 return Filtergraph_QueryInterface(This, riid, ppv); 05244 } 05245 05246 static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface) 05247 { 05248 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05249 05250 return Filtergraph_AddRef(This); 05251 } 05252 05253 static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface) 05254 { 05255 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05256 05257 return Filtergraph_Release(This); 05258 } 05259 05260 static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, 05261 IPin* pOutputPin, 05262 IPin* pInputPin, 05263 const AM_MEDIA_TYPE* pmtFirstConnection, 05264 IBaseFilter* pUsingFilter, 05265 HANDLE hAbortEvent, 05266 DWORD dwFlags) 05267 { 05268 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05269 05270 FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags); 05271 05272 return E_NOTIMPL; 05273 } 05274 05275 static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, 05276 IGraphConfigCallback* pCallback, 05277 PVOID pvContext, 05278 DWORD dwFlags, 05279 HANDLE hAbortEvent) 05280 { 05281 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05282 HRESULT hr; 05283 05284 WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent); 05285 05286 if (hAbortEvent) 05287 FIXME("The parameter hAbortEvent is not handled!\n"); 05288 05289 EnterCriticalSection(&This->cs); 05290 05291 hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags); 05292 05293 LeaveCriticalSection(&This->cs); 05294 05295 return hr; 05296 } 05297 05298 static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, 05299 IBaseFilter* pFilter) 05300 { 05301 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05302 05303 FIXME("(%p)->(%p): stub!\n", This, pFilter); 05304 05305 return E_NOTIMPL; 05306 } 05307 05308 static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, 05309 IEnumFilters** pEnum) 05310 { 05311 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05312 05313 FIXME("(%p)->(%p): stub!\n", This, pEnum); 05314 05315 return E_NOTIMPL; 05316 } 05317 05318 static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, 05319 IBaseFilter* pFilter) 05320 { 05321 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05322 05323 FIXME("(%p)->(%p): stub!\n", This, pFilter); 05324 05325 return E_NOTIMPL; 05326 } 05327 05328 static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, 05329 REFERENCE_TIME* prtStart) 05330 { 05331 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05332 05333 FIXME("(%p)->(%p): stub!\n", This, prtStart); 05334 05335 return E_NOTIMPL; 05336 } 05337 05338 static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, 05339 IPin* pOutputPin, 05340 IPinConnection* pConnection, 05341 HANDLE hEventAbort) 05342 { 05343 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05344 05345 FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort); 05346 05347 return E_NOTIMPL; 05348 } 05349 05350 static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, 05351 IBaseFilter* pFilter, 05352 DWORD dwFlags) 05353 { 05354 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05355 05356 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags); 05357 05358 return E_NOTIMPL; 05359 } 05360 05361 static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, 05362 IBaseFilter* pFilter, 05363 DWORD* dwFlags) 05364 { 05365 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05366 05367 FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags); 05368 05369 return E_NOTIMPL; 05370 } 05371 05372 static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, 05373 IBaseFilter* pFilter, 05374 DWORD dwFlags) 05375 { 05376 ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); 05377 05378 FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags); 05379 05380 return E_NOTIMPL; 05381 } 05382 05383 static const IGraphConfigVtbl IGraphConfig_VTable = 05384 { 05385 GraphConfig_QueryInterface, 05386 GraphConfig_AddRef, 05387 GraphConfig_Release, 05388 GraphConfig_Reconnect, 05389 GraphConfig_Reconfigure, 05390 GraphConfig_AddFilterToCache, 05391 GraphConfig_EnumCacheFilter, 05392 GraphConfig_RemoveFilterFromCache, 05393 GraphConfig_GetStartTime, 05394 GraphConfig_PushThroughData, 05395 GraphConfig_SetFilterFlags, 05396 GraphConfig_GetFilterFlags, 05397 GraphConfig_RemoveFilterEx 05398 }; 05399 05400 static const IUnknownVtbl IInner_VTable = 05401 { 05402 FilterGraphInner_QueryInterface, 05403 FilterGraphInner_AddRef, 05404 FilterGraphInner_Release 05405 }; 05406 05407 static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This, 05408 REFIID riid, 05409 LPVOID * ppv) { 05410 if (This->bAggregatable) 05411 This->bUnkOuterValid = TRUE; 05412 05413 if (This->pUnkOuter) 05414 { 05415 if (This->bAggregatable) 05416 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); 05417 05418 if (IsEqualIID(riid, &IID_IUnknown)) 05419 { 05420 HRESULT hr; 05421 05422 IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); 05423 hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); 05424 IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); 05425 This->bAggregatable = TRUE; 05426 return hr; 05427 } 05428 05429 *ppv = NULL; 05430 return E_NOINTERFACE; 05431 } 05432 05433 return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); 05434 } 05435 05436 static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) { 05437 if (This->pUnkOuter && This->bUnkOuterValid) 05438 return IUnknown_AddRef(This->pUnkOuter); 05439 return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); 05440 } 05441 05442 static ULONG Filtergraph_Release(IFilterGraphImpl *This) { 05443 if (This->pUnkOuter && This->bUnkOuterValid) 05444 return IUnknown_Release(This->pUnkOuter); 05445 return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); 05446 } 05447 05448 /* This is the only function that actually creates a FilterGraph class... */ 05449 HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) 05450 { 05451 IFilterGraphImpl *fimpl; 05452 HRESULT hr; 05453 05454 TRACE("(%p,%p)\n", pUnkOuter, ppObj); 05455 05456 *ppObj = NULL; 05457 05458 fimpl = CoTaskMemAlloc(sizeof(*fimpl)); 05459 fimpl->pUnkOuter = pUnkOuter; 05460 fimpl->bUnkOuterValid = FALSE; 05461 fimpl->bAggregatable = FALSE; 05462 fimpl->IInner_vtbl = &IInner_VTable; 05463 fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable; 05464 fimpl->IMediaControl_vtbl = &IMediaControl_VTable; 05465 fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable; 05466 fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable; 05467 fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable; 05468 fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable; 05469 fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable; 05470 fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable; 05471 fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable; 05472 fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable; 05473 fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable; 05474 fimpl->ref = 1; 05475 fimpl->ppFiltersInGraph = NULL; 05476 fimpl->pFilterNames = NULL; 05477 fimpl->nFilters = 0; 05478 fimpl->filterCapacity = 0; 05479 fimpl->nameIndex = 1; 05480 fimpl->refClock = NULL; 05481 fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0); 05482 fimpl->HandleEcComplete = TRUE; 05483 fimpl->HandleEcRepaint = TRUE; 05484 fimpl->HandleEcClockChanged = TRUE; 05485 fimpl->notif.hWnd = 0; 05486 fimpl->notif.disabled = FALSE; 05487 fimpl->nRenderers = 0; 05488 fimpl->EcCompleteCount = 0; 05489 fimpl->state = State_Stopped; 05490 EventsQueue_Init(&fimpl->evqueue); 05491 InitializeCriticalSection(&fimpl->cs); 05492 fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs"); 05493 fimpl->nItfCacheEntries = 0; 05494 memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID)); 05495 fimpl->start_time = fimpl->position = 0; 05496 fimpl->stop_position = -1; 05497 fimpl->punkFilterMapper2 = NULL; 05498 fimpl->recursioncount = 0; 05499 05500 /* create Filtermapper aggregated. */ 05501 hr = CoCreateInstance(&CLSID_FilterMapper2, pUnkOuter ? pUnkOuter : (IUnknown*)&fimpl->IInner_vtbl, CLSCTX_INPROC_SERVER, 05502 &IID_IUnknown, (LPVOID*)&fimpl->punkFilterMapper2); 05503 05504 if (SUCCEEDED(hr)) { 05505 hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2); 05506 } 05507 05508 if (SUCCEEDED(hr)) { 05509 /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */ 05510 if (pUnkOuter) IUnknown_Release(pUnkOuter); 05511 else IUnknown_Release((IUnknown*)&fimpl->IInner_vtbl); 05512 } 05513 05514 if (FAILED(hr)) { 05515 ERR("Unable to create filter mapper (%x)\n", hr); 05516 if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2); 05517 CloseHandle(fimpl->hEventCompletion); 05518 EventsQueue_Destroy(&fimpl->evqueue); 05519 fimpl->cs.DebugInfo->Spare[0] = 0; 05520 DeleteCriticalSection(&fimpl->cs); 05521 CoTaskMemFree(fimpl); 05522 return hr; 05523 } 05524 IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl); 05525 05526 *ppObj = fimpl; 05527 return S_OK; 05528 } 05529 05530 HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj) 05531 { 05532 FIXME("CLSID_FilterGraphNoThread partially implemented - Forwarding to CLSID_FilterGraph\n"); 05533 return FilterGraph_create(pUnkOuter, ppObj); 05534 } Generated on Sat May 26 2012 04:20:31 for ReactOS by
1.7.6.1
|