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(quartz
);
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 seeking
->cs
.DebugInfo
->Spare
[0] = 0;
60 DeleteCriticalSection(&seeking
->cs
);
63 HRESULT WINAPI
SourceSeekingImpl_GetCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
65 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
67 TRACE("(%p)\n", pCapabilities
);
69 *pCapabilities
= This
->dwCapabilities
;
74 HRESULT WINAPI
SourceSeekingImpl_CheckCapabilities(IMediaSeeking
* iface
, DWORD
* pCapabilities
)
76 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
80 TRACE("(%p)\n", pCapabilities
);
85 dwCommonCaps
= *pCapabilities
& This
->dwCapabilities
;
90 hr
= (*pCapabilities
== dwCommonCaps
) ? S_OK
: S_FALSE
;
91 *pCapabilities
= dwCommonCaps
;
95 HRESULT WINAPI
SourceSeekingImpl_IsFormatSupported(IMediaSeeking
* iface
, const GUID
* pFormat
)
97 TRACE("(%s)\n", debugstr_guid(pFormat
));
99 return (IsEqualIID(pFormat
, &TIME_FORMAT_MEDIA_TIME
) ? S_OK
: S_FALSE
);
102 HRESULT WINAPI
SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking
* iface
, GUID
* pFormat
)
104 TRACE("(%s)\n", debugstr_guid(pFormat
));
106 *pFormat
= TIME_FORMAT_MEDIA_TIME
;
110 HRESULT WINAPI
SourceSeekingImpl_GetTimeFormat(IMediaSeeking
* iface
, GUID
* pFormat
)
112 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
113 TRACE("(%s)\n", debugstr_guid(pFormat
));
115 EnterCriticalSection(&This
->cs
);
116 *pFormat
= This
->timeformat
;
117 LeaveCriticalSection(&This
->cs
);
122 HRESULT WINAPI
SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
124 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
127 TRACE("(%s)\n", debugstr_guid(pFormat
));
129 EnterCriticalSection(&This
->cs
);
130 if (!IsEqualIID(pFormat
, &This
->timeformat
))
132 LeaveCriticalSection(&This
->cs
);
137 HRESULT WINAPI
SourceSeekingImpl_SetTimeFormat(IMediaSeeking
* iface
, const GUID
* pFormat
)
139 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
140 TRACE("%p %s\n", This
, debugstr_guid(pFormat
));
141 return (IsEqualIID(pFormat
, &TIME_FORMAT_MEDIA_TIME
) ? S_OK
: E_INVALIDARG
);
145 HRESULT WINAPI
SourceSeekingImpl_GetDuration(IMediaSeeking
* iface
, LONGLONG
* pDuration
)
147 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
149 TRACE("(%p)\n", pDuration
);
151 EnterCriticalSection(&This
->cs
);
152 *pDuration
= This
->llDuration
;
153 LeaveCriticalSection(&This
->cs
);
158 HRESULT WINAPI
SourceSeekingImpl_GetStopPosition(IMediaSeeking
* iface
, LONGLONG
* pStop
)
160 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
162 TRACE("(%p)\n", pStop
);
164 EnterCriticalSection(&This
->cs
);
165 *pStop
= This
->llStop
;
166 LeaveCriticalSection(&This
->cs
);
171 /* FIXME: Make use of the info the filter should expose */
172 HRESULT WINAPI
SourceSeekingImpl_GetCurrentPosition(IMediaSeeking
* iface
, LONGLONG
* pCurrent
)
174 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
176 TRACE("(%p)\n", pCurrent
);
178 EnterCriticalSection(&This
->cs
);
179 *pCurrent
= This
->llCurrent
;
180 LeaveCriticalSection(&This
->cs
);
185 HRESULT WINAPI
SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking
* iface
, LONGLONG
* pTarget
, const GUID
* pTargetFormat
, LONGLONG Source
, const GUID
* pSourceFormat
)
187 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
189 pTargetFormat
= &This
->timeformat
;
191 pSourceFormat
= &This
->timeformat
;
192 if (IsEqualIID(pTargetFormat
, &TIME_FORMAT_MEDIA_TIME
) && IsEqualIID(pSourceFormat
, &TIME_FORMAT_MEDIA_TIME
))
197 /* FIXME: clear pTarget? */
201 static inline LONGLONG
Adjust(LONGLONG value
, const LONGLONG
* pModifier
, DWORD dwFlags
)
203 switch (dwFlags
& AM_SEEKING_PositioningBitsMask
)
205 case AM_SEEKING_NoPositioning
:
207 case AM_SEEKING_AbsolutePositioning
:
209 case AM_SEEKING_RelativePositioning
:
210 case AM_SEEKING_IncrementalPositioning
:
211 return value
+ *pModifier
;
218 HRESULT WINAPI
SourceSeekingImpl_SetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, DWORD dwCurrentFlags
, LONGLONG
* pStop
, DWORD dwStopFlags
)
220 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
221 BOOL bChangeCurrent
= FALSE
, bChangeStop
= FALSE
;
222 LONGLONG llNewCurrent
, llNewStop
;
224 TRACE("iface %p, current %s, current_flags %#lx, stop %s, stop_flags %#lx.\n", iface
,
225 pCurrent
? debugstr_time(*pCurrent
) : "<null>", dwCurrentFlags
,
226 pStop
? debugstr_time(*pStop
): "<null>", dwStopFlags
);
228 EnterCriticalSection(&This
->cs
);
230 llNewCurrent
= Adjust(This
->llCurrent
, pCurrent
, dwCurrentFlags
);
231 llNewStop
= Adjust(This
->llStop
, pStop
, dwStopFlags
);
234 bChangeCurrent
= TRUE
;
235 if (llNewStop
!= This
->llStop
)
238 TRACE("Seeking from %s to %s.\n", debugstr_time(This
->llCurrent
), debugstr_time(llNewCurrent
));
240 This
->llCurrent
= llNewCurrent
;
241 This
->llStop
= llNewStop
;
243 if (pCurrent
&& (dwCurrentFlags
& AM_SEEKING_ReturnTime
))
244 *pCurrent
= llNewCurrent
;
245 if (pStop
&& (dwStopFlags
& AM_SEEKING_ReturnTime
))
247 LeaveCriticalSection(&This
->cs
);
250 This
->fnChangeStart(iface
);
252 This
->fnChangeStop(iface
);
257 HRESULT WINAPI
SourceSeekingImpl_GetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, LONGLONG
* pStop
)
259 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
261 TRACE("(%p, %p)\n", pCurrent
, pStop
);
263 EnterCriticalSection(&This
->cs
);
264 IMediaSeeking_GetCurrentPosition(iface
, pCurrent
);
265 IMediaSeeking_GetStopPosition(iface
, pStop
);
266 LeaveCriticalSection(&This
->cs
);
271 HRESULT WINAPI
SourceSeekingImpl_GetAvailable(IMediaSeeking
* iface
, LONGLONG
* pEarliest
, LONGLONG
* pLatest
)
273 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
275 TRACE("(%p, %p)\n", pEarliest
, pLatest
);
277 EnterCriticalSection(&This
->cs
);
279 *pLatest
= This
->llDuration
;
280 LeaveCriticalSection(&This
->cs
);
285 HRESULT WINAPI
SourceSeekingImpl_SetRate(IMediaSeeking
* iface
, double dRate
)
287 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
288 BOOL bChangeRate
= (dRate
!= This
->dRate
);
291 TRACE("(%e)\n", dRate
);
293 if (dRate
> 100 || dRate
< .001)
295 FIXME("Excessive rate %e, ignoring\n", dRate
);
296 return VFW_E_UNSUPPORTED_AUDIO
;
299 EnterCriticalSection(&This
->cs
);
302 hr
= This
->fnChangeRate(iface
);
303 LeaveCriticalSection(&This
->cs
);
308 HRESULT WINAPI
SourceSeekingImpl_GetRate(IMediaSeeking
* iface
, double * dRate
)
310 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
312 TRACE("(%p)\n", dRate
);
314 EnterCriticalSection(&This
->cs
);
316 *dRate
= This
->dRate
;
317 LeaveCriticalSection(&This
->cs
);
322 HRESULT WINAPI
SourceSeekingImpl_GetPreroll(IMediaSeeking
* iface
, LONGLONG
* pPreroll
)
324 TRACE("(%p)\n", pPreroll
);