2 * Filter Seeking and Control Interfaces
4 * Copyright 2003 Robert Shearman
5 * Copyright 2010 Aric Stewart, CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "strmbase_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(strmbase
);
26 static inline SourceSeeking
*impl_from_IMediaSeeking(IMediaSeeking
*iface
)
28 return CONTAINING_RECORD(iface
, SourceSeeking
, IMediaSeeking_iface
);
31 HRESULT
strmbase_seeking_init(SourceSeeking
*pSeeking
, const IMediaSeekingVtbl
*Vtbl
,
32 SourceSeeking_ChangeStop fnChangeStop
, SourceSeeking_ChangeStart fnChangeStart
,
33 SourceSeeking_ChangeRate fnChangeRate
)
35 assert(fnChangeStop
&& fnChangeStart
&& fnChangeRate
);
37 pSeeking
->IMediaSeeking_iface
.lpVtbl
= Vtbl
;
38 pSeeking
->refCount
= 1;
39 pSeeking
->fnChangeRate
= fnChangeRate
;
40 pSeeking
->fnChangeStop
= fnChangeStop
;
41 pSeeking
->fnChangeStart
= fnChangeStart
;
42 pSeeking
->dwCapabilities
= AM_SEEKING_CanSeekForwards
|
43 AM_SEEKING_CanSeekBackwards
|
44 AM_SEEKING_CanSeekAbsolute
|
45 AM_SEEKING_CanGetStopPos
|
46 AM_SEEKING_CanGetDuration
;
47 pSeeking
->llCurrent
= 0;
48 pSeeking
->llStop
= ((ULONGLONG
)0x80000000) << 32;
49 pSeeking
->llDuration
= pSeeking
->llStop
;
50 pSeeking
->dRate
= 1.0;
51 pSeeking
->timeformat
= TIME_FORMAT_MEDIA_TIME
;
52 InitializeCriticalSection(&pSeeking
->cs
);
53 pSeeking
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": SourceSeeking.cs");
57 void strmbase_seeking_cleanup(SourceSeeking
*seeking
)
59 DeleteCriticalSection(&seeking
->cs
);
62 HRESULT WINAPI
SourceSeekingImpl_GetCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
64 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
66 TRACE("(%p)\n", pCapabilities
);
68 *pCapabilities
= This
->dwCapabilities
;
73 HRESULT WINAPI
SourceSeekingImpl_CheckCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
75 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
79 TRACE("(%p)\n", pCapabilities
);
84 dwCommonCaps
= *pCapabilities
& This
->dwCapabilities
;
89 hr
= (*pCapabilities
== dwCommonCaps
) ? S_OK
: S_FALSE
;
90 *pCapabilities
= dwCommonCaps
;
94 HRESULT WINAPI
SourceSeekingImpl_IsFormatSupported(IMediaSeeking
* iface
, const GUID
* pFormat
)
96 TRACE("(%s)\n", debugstr_guid(pFormat
));
98 return (IsEqualIID(pFormat
, &TIME_FORMAT_MEDIA_TIME
) ? S_OK
: S_FALSE
);
101 HRESULT WINAPI
SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking
* iface
, GUID
* pFormat
)
103 TRACE("(%s)\n", debugstr_guid(pFormat
));
105 *pFormat
= TIME_FORMAT_MEDIA_TIME
;
109 HRESULT WINAPI
SourceSeekingImpl_GetTimeFormat(IMediaSeeking
* iface
, GUID
* pFormat
)
111 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
112 TRACE("(%s)\n", debugstr_guid(pFormat
));
114 EnterCriticalSection(&This
->cs
);
115 *pFormat
= This
->timeformat
;
116 LeaveCriticalSection(&This
->cs
);
121 HRESULT WINAPI
SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
123 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
126 TRACE("(%s)\n", debugstr_guid(pFormat
));
128 EnterCriticalSection(&This
->cs
);
129 if (!IsEqualIID(pFormat
, &This
->timeformat
))
131 LeaveCriticalSection(&This
->cs
);
136 HRESULT WINAPI
SourceSeekingImpl_SetTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
138 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
139 TRACE("%p %s\n", This
, debugstr_guid(pFormat
));
140 return (IsEqualIID(pFormat
, &TIME_FORMAT_MEDIA_TIME
) ? S_OK
: E_INVALIDARG
);
144 HRESULT WINAPI
SourceSeekingImpl_GetDuration(IMediaSeeking
* iface
, LONGLONG
* pDuration
)
146 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
148 TRACE("(%p)\n", pDuration
);
150 EnterCriticalSection(&This
->cs
);
151 *pDuration
= This
->llDuration
;
152 LeaveCriticalSection(&This
->cs
);
157 HRESULT WINAPI
SourceSeekingImpl_GetStopPosition(IMediaSeeking
* iface
, LONGLONG
* pStop
)
159 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
161 TRACE("(%p)\n", pStop
);
163 EnterCriticalSection(&This
->cs
);
164 *pStop
= This
->llStop
;
165 LeaveCriticalSection(&This
->cs
);
170 /* FIXME: Make use of the info the filter should expose */
171 HRESULT WINAPI
SourceSeekingImpl_GetCurrentPosition(IMediaSeeking
* iface
, LONGLONG
* pCurrent
)
173 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
175 TRACE("(%p)\n", pCurrent
);
177 EnterCriticalSection(&This
->cs
);
178 *pCurrent
= This
->llCurrent
;
179 LeaveCriticalSection(&This
->cs
);
184 HRESULT WINAPI
SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking
* iface
, LONGLONG
* pTarget
, const GUID
* pTargetFormat
, LONGLONG Source
, const GUID
* pSourceFormat
)
186 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
188 pTargetFormat
= &This
->timeformat
;
190 pSourceFormat
= &This
->timeformat
;
191 if (IsEqualIID(pTargetFormat
, &TIME_FORMAT_MEDIA_TIME
) && IsEqualIID(pSourceFormat
, &TIME_FORMAT_MEDIA_TIME
))
196 /* FIXME: clear pTarget? */
200 static inline LONGLONG
Adjust(LONGLONG value
, const LONGLONG
* pModifier
, DWORD dwFlags
)
202 switch (dwFlags
& AM_SEEKING_PositioningBitsMask
)
204 case AM_SEEKING_NoPositioning
:
206 case AM_SEEKING_AbsolutePositioning
:
208 case AM_SEEKING_RelativePositioning
:
209 case AM_SEEKING_IncrementalPositioning
:
210 return value
+ *pModifier
;
217 HRESULT WINAPI
SourceSeekingImpl_SetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, DWORD dwCurrentFlags
, LONGLONG
* pStop
, DWORD dwStopFlags
)
219 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
220 BOOL bChangeCurrent
= FALSE
, bChangeStop
= FALSE
;
221 LONGLONG llNewCurrent
, llNewStop
;
223 TRACE("(%p, %x, %p, %x)\n", pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
224 EnterCriticalSection(&This
->cs
);
226 llNewCurrent
= Adjust(This
->llCurrent
, pCurrent
, dwCurrentFlags
);
227 llNewStop
= Adjust(This
->llStop
, pStop
, dwStopFlags
);
230 bChangeCurrent
= TRUE
;
231 if (llNewStop
!= This
->llStop
)
234 TRACE("Old: %u, New: %u\n", (DWORD
)(This
->llCurrent
/10000000), (DWORD
)(llNewCurrent
/10000000));
236 This
->llCurrent
= llNewCurrent
;
237 This
->llStop
= llNewStop
;
239 if (pCurrent
&& (dwCurrentFlags
& AM_SEEKING_ReturnTime
))
240 *pCurrent
= llNewCurrent
;
241 if (pStop
&& (dwStopFlags
& AM_SEEKING_ReturnTime
))
243 LeaveCriticalSection(&This
->cs
);
246 This
->fnChangeStart(iface
);
248 This
->fnChangeStop(iface
);
253 HRESULT WINAPI
SourceSeekingImpl_GetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, LONGLONG
* pStop
)
255 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
257 TRACE("(%p, %p)\n", pCurrent
, pStop
);
259 EnterCriticalSection(&This
->cs
);
260 IMediaSeeking_GetCurrentPosition(iface
, pCurrent
);
261 IMediaSeeking_GetStopPosition(iface
, pStop
);
262 LeaveCriticalSection(&This
->cs
);
267 HRESULT WINAPI
SourceSeekingImpl_GetAvailable(IMediaSeeking
* iface
, LONGLONG
* pEarliest
, LONGLONG
* pLatest
)
269 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
271 TRACE("(%p, %p)\n", pEarliest
, pLatest
);
273 EnterCriticalSection(&This
->cs
);
275 *pLatest
= This
->llDuration
;
276 LeaveCriticalSection(&This
->cs
);
281 HRESULT WINAPI
SourceSeekingImpl_SetRate(IMediaSeeking
* iface
, double dRate
)
283 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
284 BOOL bChangeRate
= (dRate
!= This
->dRate
);
287 TRACE("(%e)\n", dRate
);
289 if (dRate
> 100 || dRate
< .001)
291 FIXME("Excessive rate %e, ignoring\n", dRate
);
292 return VFW_E_UNSUPPORTED_AUDIO
;
295 EnterCriticalSection(&This
->cs
);
298 hr
= This
->fnChangeRate(iface
);
299 LeaveCriticalSection(&This
->cs
);
304 HRESULT WINAPI
SourceSeekingImpl_GetRate(IMediaSeeking
* iface
, double * dRate
)
306 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
308 TRACE("(%p)\n", dRate
);
310 EnterCriticalSection(&This
->cs
);
312 *dRate
= This
->dRate
;
313 LeaveCriticalSection(&This
->cs
);
318 HRESULT WINAPI
SourceSeekingImpl_GetPreroll(IMediaSeeking
* iface
, LONGLONG
* pPreroll
)
320 TRACE("(%p)\n", pPreroll
);