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"
26 #include "wine/debug.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
)
38 HRESULT hr_return
= S_OK
;
39 IEnumPins
*enumpins
= NULL
;
40 BOOL foundend
= FALSE
, allnotimpl
= TRUE
;
42 hr
= IBaseFilter_EnumPins( from
, &enumpins
);
46 hr
= IEnumPins_Reset( enumpins
);
49 hr
= IEnumPins_Next( enumpins
, 1, &pin
, NULL
);
50 if (hr
== VFW_E_ENUM_OUT_OF_SYNC
)
52 hr
= IEnumPins_Reset( enumpins
);
59 IPin_QueryDirection( pin
, &dir
);
60 if (dir
== PINDIR_INPUT
)
62 IPin
*connected
= NULL
;
64 IPin_ConnectedTo( pin
, &connected
);
68 IMediaSeeking
*seek
= NULL
;
70 hr_local
= IPin_QueryInterface( connected
, &IID_IMediaSeeking
, (void**)&seek
);
74 hr_local
= fnSeek( seek
, arg
);
75 if (hr_local
!= E_NOTIMPL
)
78 hr_return
= updatehres( hr_return
, hr_local
);
79 IMediaSeeking_Release( seek
);
81 IPin_Release(connected
);
87 if (foundend
&& allnotimpl
)
93 FIXME("Returning: %08x\n", hr
);
98 HRESULT
MediaSeekingImpl_Init(IBaseFilter
*pUserData
, CHANGEPROC fnChangeStop
, CHANGEPROC fnChangeCurrent
, CHANGEPROC fnChangeRate
, MediaSeekingImpl
* pSeeking
, PCRITICAL_SECTION crit_sect
)
100 assert(fnChangeStop
&& fnChangeCurrent
&& fnChangeRate
);
102 pSeeking
->refCount
= 1;
103 pSeeking
->pUserData
= pUserData
;
104 pSeeking
->fnChangeRate
= fnChangeRate
;
105 pSeeking
->fnChangeStop
= fnChangeStop
;
106 pSeeking
->fnChangeCurrent
= fnChangeCurrent
;
107 pSeeking
->dwCapabilities
= AM_SEEKING_CanSeekForwards
|
108 AM_SEEKING_CanSeekBackwards
|
109 AM_SEEKING_CanSeekAbsolute
|
110 AM_SEEKING_CanGetStopPos
|
111 AM_SEEKING_CanGetDuration
;
112 pSeeking
->llCurrent
= 0;
113 pSeeking
->llStop
= ((ULONGLONG
)0x80000000) << 32;
114 pSeeking
->llDuration
= pSeeking
->llStop
;
115 pSeeking
->dRate
= 1.0;
116 pSeeking
->timeformat
= TIME_FORMAT_MEDIA_TIME
;
117 pSeeking
->crst
= crit_sect
;
123 HRESULT WINAPI
MediaSeekingImpl_GetCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
125 MediaSeekingImpl
*This
= (MediaSeekingImpl
*)iface
;
127 TRACE("(%p)\n", pCapabilities
);
129 *pCapabilities
= This
->dwCapabilities
;
134 static HRESULT
fwd_checkcaps(IMediaSeeking
*iface
, LPVOID pcaps
)
137 return IMediaSeeking_CheckCapabilities(iface
, caps
);
140 HRESULT WINAPI
MediaSeekingImpl_CheckCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
142 MediaSeekingImpl
*This
= (MediaSeekingImpl
*)iface
;
146 TRACE("(%p)\n", pCapabilities
);
151 hr
= ForwardCmdSeek(This
->pUserData
, fwd_checkcaps
, pCapabilities
);
152 if (FAILED(hr
) && hr
!= E_NOTIMPL
)
155 dwCommonCaps
= *pCapabilities
& This
->dwCapabilities
;
160 hr
= (*pCapabilities
== dwCommonCaps
) ? S_OK
: S_FALSE
;
161 *pCapabilities
= dwCommonCaps
;
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
;
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
);
193 HRESULT WINAPI
MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
195 MediaSeekingImpl
*This
= (MediaSeekingImpl
*)iface
;
198 TRACE("(%s)\n", qzdebugstr_guid(pFormat
));
200 EnterCriticalSection(This
->crst
);
201 if (!IsEqualIID(pFormat
, &This
->timeformat
))
203 LeaveCriticalSection(This
->crst
);
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
;
232 hr
= IMediaSeeking_GetDuration(iface
, &mydur
);
236 if ((mydur
< *duration
) || (*duration
< 0 && mydur
> 0))
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
);
256 static HRESULT
fwd_getstopposition(IMediaSeeking
*iface
, LPVOID pdur
)
258 LONGLONG
*duration
= pdur
;
259 LONGLONG mydur
= *duration
;
262 hr
= IMediaSeeking_GetStopPosition(iface
, &mydur
);
266 if ((mydur
< *duration
) || (*duration
< 0 && mydur
> 0))
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
);
286 static HRESULT
fwd_getcurposition(IMediaSeeking
*iface
, LPVOID pdur
)
288 LONGLONG
*duration
= pdur
;
289 LONGLONG mydur
= *duration
;
292 hr
= IMediaSeeking_GetCurrentPosition(iface
, &mydur
);
296 if ((mydur
< *duration
) || (*duration
< 0 && mydur
> 0))
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
->llCurrent
;
310 ForwardCmdSeek(This
->pUserData
, fwd_getcurposition
, pCurrent
);
311 LeaveCriticalSection(This
->crst
);
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
))
323 /* FIXME: clear pTarget? */
327 static inline LONGLONG
Adjust(LONGLONG value
, const LONGLONG
* pModifier
, DWORD dwFlags
)
329 switch (dwFlags
& AM_SEEKING_PositioningBitsMask
)
331 case AM_SEEKING_NoPositioning
:
333 case AM_SEEKING_AbsolutePositioning
:
335 case AM_SEEKING_RelativePositioning
:
336 case AM_SEEKING_IncrementalPositioning
:
337 return value
+ *pModifier
;
344 HRESULT WINAPI
MediaSeekingImpl_SetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, DWORD dwCurrentFlags
, LONGLONG
* pStop
, DWORD dwStopFlags
)
346 MediaSeekingImpl
*This
= (MediaSeekingImpl
*)iface
;
347 BOOL bChangeCurrent
= FALSE
, bChangeStop
= FALSE
;
348 LONGLONG llNewCurrent
, llNewStop
;
350 TRACE("(%p, %x, %p, %x)\n", pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
352 EnterCriticalSection(This
->crst
);
354 llNewCurrent
= Adjust(This
->llCurrent
, pCurrent
, dwCurrentFlags
);
355 llNewStop
= Adjust(This
->llStop
, pStop
, dwStopFlags
);
357 if (llNewCurrent
!= This
->llCurrent
)
358 bChangeCurrent
= TRUE
;
359 if (llNewStop
!= This
->llStop
)
362 This
->llCurrent
= llNewCurrent
;
363 This
->llStop
= llNewStop
;
365 if (dwCurrentFlags
& AM_SEEKING_ReturnTime
)
366 *pCurrent
= llNewCurrent
;
367 if (dwStopFlags
& AM_SEEKING_ReturnTime
)
371 This
->fnChangeCurrent(This
->pUserData
);
373 This
->fnChangeStop(This
->pUserData
);
375 LeaveCriticalSection(This
->crst
);
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
->llCurrent
;
388 *pStop
= This
->llStop
;
389 LeaveCriticalSection(This
->crst
);
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
);
402 *pLatest
= This
->llDuration
;
403 LeaveCriticalSection(This
->crst
);
408 static HRESULT
fwd_setrate(IMediaSeeking
*iface
, LPVOID prate
)
410 double *rate
= prate
;
414 hr
= IMediaSeeking_SetRate(iface
, *rate
);
421 HRESULT WINAPI
MediaSeekingImpl_SetRate(IMediaSeeking
* iface
, double dRate
)
423 MediaSeekingImpl
*This
= (MediaSeekingImpl
*)iface
;
424 BOOL bChangeRate
= (dRate
!= This
->dRate
);
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
);
438 hr
= This
->fnChangeRate(This
->pUserData
);
439 ForwardCmdSeek(This
->pUserData
, fwd_setrate
, &dRate
);
440 LeaveCriticalSection(This
->crst
);
445 HRESULT WINAPI
MediaSeekingImpl_GetRate(IMediaSeeking
* iface
, double * dRate
)
447 MediaSeekingImpl
*This
= (MediaSeekingImpl
*)iface
;
449 TRACE("(%p)\n", dRate
);
451 EnterCriticalSection(This
->crst
);
453 *dRate
= This
->dRate
;
454 LeaveCriticalSection(This
->crst
);
459 HRESULT WINAPI
MediaSeekingImpl_GetPreroll(IMediaSeeking
* iface
, LONGLONG
* pPreroll
)
461 TRACE("(%p)\n", pPreroll
);