setupapi: Forward SetupInstallServicesFromInfSectionA to W-function.
[wine/multimedia.git] / dlls / quartz / control.c
blobd32d054ba9249ed8a45e593f22859e2140bdc25e
1 /*
2 * Filter Seeking and Control Interfaces
4 * Copyright 2003 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /* FIXME: critical sections */
22 #include "quartz_private.h"
23 #include "control_private.h"
25 #include "uuids.h"
26 #include "wine/debug.h"
28 #include <assert.h>
30 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
33 typedef HRESULT (*SeekFunc)( IMediaSeeking *to, LPVOID arg );
35 static HRESULT ForwardCmdSeek( IBaseFilter* from, SeekFunc fnSeek, LPVOID arg )
37 HRESULT hr = S_OK;
38 HRESULT hr_return = S_OK;
39 IEnumPins *enumpins = NULL;
40 BOOL foundend = FALSE, allnotimpl = TRUE;
42 hr = IBaseFilter_EnumPins( from, &enumpins );
43 if (FAILED(hr))
44 goto out;
46 hr = IEnumPins_Reset( enumpins );
47 while (hr == S_OK) {
48 IPin *pin = NULL;
49 hr = IEnumPins_Next( enumpins, 1, &pin, NULL );
50 if (hr == VFW_E_ENUM_OUT_OF_SYNC)
52 hr = IEnumPins_Reset( enumpins );
53 continue;
55 if (pin)
57 PIN_DIRECTION dir;
59 IPin_QueryDirection( pin, &dir );
60 if (dir == PINDIR_INPUT)
62 IPin *connected = NULL;
64 IPin_ConnectedTo( pin, &connected );
65 if (connected)
67 HRESULT hr_local;
68 IMediaSeeking *seek = NULL;
70 hr_local = IPin_QueryInterface( connected, &IID_IMediaSeeking, (void**)&seek );
71 if (!hr_local)
73 foundend = TRUE;
74 hr_local = fnSeek( seek , arg );
75 if (hr_local != E_NOTIMPL)
76 allnotimpl = FALSE;
78 hr_return = updatehres( hr_return, hr_local );
79 IMediaSeeking_Release( seek );
81 IPin_Release(connected);
84 IPin_Release( pin );
86 } while (hr == S_OK);
87 if (foundend && allnotimpl)
88 hr = E_NOTIMPL;
89 else
90 hr = hr_return;
92 out:
93 FIXME("Returning: %08x\n", hr);
94 return hr;
98 HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeStart, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking, PCRITICAL_SECTION crit_sect)
100 assert(fnChangeStop && fnChangeStart && fnChangeRate);
102 pSeeking->refCount = 1;
103 pSeeking->pUserData = pUserData;
104 pSeeking->fnChangeRate = fnChangeRate;
105 pSeeking->fnChangeStop = fnChangeStop;
106 pSeeking->fnChangeStart = fnChangeStart;
107 pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards |
108 AM_SEEKING_CanSeekBackwards |
109 AM_SEEKING_CanSeekAbsolute |
110 AM_SEEKING_CanGetStopPos |
111 AM_SEEKING_CanGetDuration;
112 pSeeking->llStart = 0;
113 pSeeking->llStop = ((ULONGLONG)0x80000000) << 32;
114 pSeeking->llDuration = pSeeking->llStop - pSeeking->llStart;
115 pSeeking->dRate = 1.0;
116 pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME;
117 pSeeking->crst = crit_sect;
119 return S_OK;
123 HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
125 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
127 TRACE("(%p)\n", pCapabilities);
129 *pCapabilities = This->dwCapabilities;
131 return S_OK;
134 static HRESULT fwd_checkcaps(IMediaSeeking *iface, LPVOID pcaps)
136 DWORD *caps = pcaps;
137 return IMediaSeeking_CheckCapabilities(iface, caps);
140 HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
142 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
143 HRESULT hr;
144 DWORD dwCommonCaps;
146 TRACE("(%p)\n", pCapabilities);
148 if (!pCapabilities)
149 return E_POINTER;
151 hr = ForwardCmdSeek(This->pUserData, fwd_checkcaps, pCapabilities);
152 if (FAILED(hr) && hr != E_NOTIMPL)
153 return hr;
155 dwCommonCaps = *pCapabilities & This->dwCapabilities;
157 if (!dwCommonCaps)
158 hr = E_FAIL;
159 else
160 hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE;
161 *pCapabilities = dwCommonCaps;
163 return hr;
166 HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
168 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
170 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
173 HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
175 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
177 *pFormat = TIME_FORMAT_MEDIA_TIME;
178 return S_OK;
181 HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
183 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
184 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
186 EnterCriticalSection(This->crst);
187 *pFormat = This->timeformat;
188 LeaveCriticalSection(This->crst);
190 return S_OK;
193 HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
195 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
196 HRESULT hr = S_OK;
198 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
200 EnterCriticalSection(This->crst);
201 if (!IsEqualIID(pFormat, &This->timeformat))
202 hr = S_FALSE;
203 LeaveCriticalSection(This->crst);
205 return hr;
209 static HRESULT fwd_settimeformat(IMediaSeeking *iface, LPVOID pformat)
211 const GUID *format = pformat;
212 return IMediaSeeking_SetTimeFormat(iface, format);
215 HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
217 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
218 TRACE("(%s)\n", qzdebugstr_guid(pFormat));
220 ForwardCmdSeek(This->pUserData, fwd_settimeformat, (LPVOID)pFormat);
222 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
226 static HRESULT fwd_getduration(IMediaSeeking *iface, LPVOID pdur)
228 LONGLONG *duration = pdur;
229 LONGLONG mydur = *duration;
230 HRESULT hr;
232 hr = IMediaSeeking_GetDuration(iface, &mydur);
233 if (FAILED(hr))
234 return hr;
236 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
237 *duration = mydur;
238 return hr;
241 HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
243 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
245 TRACE("(%p)\n", pDuration);
247 EnterCriticalSection(This->crst);
248 *pDuration = This->llDuration;
249 ForwardCmdSeek(This->pUserData, fwd_getduration, pDuration);
250 LeaveCriticalSection(This->crst);
252 return S_OK;
256 static HRESULT fwd_getstopposition(IMediaSeeking *iface, LPVOID pdur)
258 LONGLONG *duration = pdur;
259 LONGLONG mydur = *duration;
260 HRESULT hr;
262 hr = IMediaSeeking_GetStopPosition(iface, &mydur);
263 if (FAILED(hr))
264 return hr;
266 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
267 *duration = mydur;
268 return hr;
271 HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
273 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
275 TRACE("(%p)\n", pStop);
277 EnterCriticalSection(This->crst);
278 *pStop = This->llStop;
279 ForwardCmdSeek(This->pUserData, fwd_getstopposition, pStop);
280 LeaveCriticalSection(This->crst);
282 return S_OK;
286 static HRESULT fwd_getcurposition(IMediaSeeking *iface, LPVOID pdur)
288 LONGLONG *duration = pdur;
289 LONGLONG mydur = *duration;
290 HRESULT hr;
292 hr = IMediaSeeking_GetCurrentPosition(iface, &mydur);
293 if (FAILED(hr))
294 return hr;
296 if ((mydur < *duration) || (*duration < 0 && mydur > 0))
297 *duration = mydur;
298 return hr;
301 /* FIXME: Make use of the info the filter should expose */
302 HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
304 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
306 TRACE("(%p)\n", pCurrent);
308 EnterCriticalSection(This->crst);
309 *pCurrent = This->llStart;
310 ForwardCmdSeek(This->pUserData, fwd_getcurposition, pCurrent);
311 LeaveCriticalSection(This->crst);
313 return S_OK;
316 HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
318 if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
320 *pTarget = Source;
321 return S_OK;
323 /* FIXME: clear pTarget? */
324 return E_INVALIDARG;
327 static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
329 switch (dwFlags & AM_SEEKING_PositioningBitsMask)
331 case AM_SEEKING_NoPositioning:
332 return value;
333 case AM_SEEKING_AbsolutePositioning:
334 return *pModifier;
335 case AM_SEEKING_RelativePositioning:
336 case AM_SEEKING_IncrementalPositioning:
337 return value + *pModifier;
338 default:
339 assert(FALSE);
340 return 0;
344 HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
346 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
347 BOOL bChangeStart = FALSE, bChangeStop = FALSE;
348 LONGLONG llNewStart, llNewStop;
350 TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
352 EnterCriticalSection(This->crst);
354 llNewStart = Adjust(This->llStart, pCurrent, dwCurrentFlags);
355 llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
357 if (llNewStart != This->llStart)
358 bChangeStart = TRUE;
359 if (llNewStop != This->llStop)
360 bChangeStop = TRUE;
362 This->llStart = llNewStart;
363 This->llStop = llNewStop;
365 if (dwCurrentFlags & AM_SEEKING_ReturnTime)
366 *pCurrent = llNewStart;
367 if (dwStopFlags & AM_SEEKING_ReturnTime)
368 *pStop = llNewStop;
370 if (bChangeStart)
371 This->fnChangeStart(This->pUserData);
372 if (bChangeStop)
373 This->fnChangeStop(This->pUserData);
375 LeaveCriticalSection(This->crst);
377 return S_OK;
380 HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
382 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
384 TRACE("(%p, %p)\n", pCurrent, pStop);
386 EnterCriticalSection(This->crst);
387 *pCurrent = This->llStart;
388 *pStop = This->llStop;
389 LeaveCriticalSection(This->crst);
391 return S_OK;
394 HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
396 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
398 TRACE("(%p, %p)\n", pEarliest, pLatest);
400 EnterCriticalSection(This->crst);
401 *pEarliest = 0;
402 *pLatest = This->llDuration;
403 LeaveCriticalSection(This->crst);
405 return S_OK;
408 static HRESULT fwd_setrate(IMediaSeeking *iface, LPVOID prate)
410 double *rate = prate;
412 HRESULT hr;
414 hr = IMediaSeeking_SetRate(iface, *rate);
415 if (FAILED(hr))
416 return hr;
418 return hr;
421 HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
423 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
424 BOOL bChangeRate = (dRate != This->dRate);
425 HRESULT hr = S_OK;
427 TRACE("(%e)\n", dRate);
429 if (dRate > 100 || dRate < .001)
431 FIXME("Excessive rate %e, ignoring\n", dRate);
432 return VFW_E_UNSUPPORTED_AUDIO;
435 EnterCriticalSection(This->crst);
436 This->dRate = dRate;
437 if (bChangeRate)
438 hr = This->fnChangeRate(This->pUserData);
439 ForwardCmdSeek(This->pUserData, fwd_setrate, &dRate);
440 LeaveCriticalSection(This->crst);
442 return hr;
445 HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
447 MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
449 TRACE("(%p)\n", dRate);
451 EnterCriticalSection(This->crst);
452 /* Forward? */
453 *dRate = This->dRate;
454 LeaveCriticalSection(This->crst);
456 return S_OK;
459 HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
461 TRACE("(%p)\n", pPreroll);
463 *pPreroll = 0;
464 return S_OK;