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
21 /* FIXME: critical sections */
26 #include "wine/strmbase.h"
29 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(strmbase
);
35 static inline SourceSeeking
*impl_from_IMediaSeeking(IMediaSeeking
*iface
)
37 return CONTAINING_RECORD(iface
, SourceSeeking
, IMediaSeeking_iface
);
40 HRESULT
SourceSeeking_Init(SourceSeeking
*pSeeking
, const IMediaSeekingVtbl
*Vtbl
, SourceSeeking_ChangeStop fnChangeStop
, SourceSeeking_ChangeStart fnChangeStart
, SourceSeeking_ChangeRate fnChangeRate
, PCRITICAL_SECTION crit_sect
)
42 assert(fnChangeStop
&& fnChangeStart
&& fnChangeRate
);
44 pSeeking
->IMediaSeeking_iface
.lpVtbl
= Vtbl
;
45 pSeeking
->refCount
= 1;
46 pSeeking
->fnChangeRate
= fnChangeRate
;
47 pSeeking
->fnChangeStop
= fnChangeStop
;
48 pSeeking
->fnChangeStart
= fnChangeStart
;
49 pSeeking
->dwCapabilities
= AM_SEEKING_CanSeekForwards
|
50 AM_SEEKING_CanSeekBackwards
|
51 AM_SEEKING_CanSeekAbsolute
|
52 AM_SEEKING_CanGetStopPos
|
53 AM_SEEKING_CanGetDuration
;
54 pSeeking
->llCurrent
= 0;
55 pSeeking
->llStop
= ((ULONGLONG
)0x80000000) << 32;
56 pSeeking
->llDuration
= pSeeking
->llStop
;
57 pSeeking
->dRate
= 1.0;
58 pSeeking
->timeformat
= TIME_FORMAT_MEDIA_TIME
;
59 pSeeking
->crst
= crit_sect
;
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
->crst
);
116 *pFormat
= This
->timeformat
;
117 LeaveCriticalSection(This
->crst
);
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
->crst
);
130 if (!IsEqualIID(pFormat
, &This
->timeformat
))
132 LeaveCriticalSection(This
->crst
);
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
->crst
);
152 *pDuration
= This
->llDuration
;
153 LeaveCriticalSection(This
->crst
);
158 HRESULT WINAPI
SourceSeekingImpl_GetStopPosition(IMediaSeeking
* iface
, LONGLONG
* pStop
)
160 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
162 TRACE("(%p)\n", pStop
);
164 EnterCriticalSection(This
->crst
);
165 *pStop
= This
->llStop
;
166 LeaveCriticalSection(This
->crst
);
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
->crst
);
179 *pCurrent
= This
->llCurrent
;
180 LeaveCriticalSection(This
->crst
);
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("(%p, %x, %p, %x)\n", pCurrent
, dwCurrentFlags
, pStop
, dwStopFlags
);
225 EnterCriticalSection(This
->crst
);
227 llNewCurrent
= Adjust(This
->llCurrent
, pCurrent
, dwCurrentFlags
);
228 llNewStop
= Adjust(This
->llStop
, pStop
, dwStopFlags
);
231 bChangeCurrent
= TRUE
;
232 if (llNewStop
!= This
->llStop
)
235 TRACE("Old: %u, New: %u\n", (DWORD
)(This
->llCurrent
/10000000), (DWORD
)(llNewCurrent
/10000000));
237 This
->llCurrent
= llNewCurrent
;
238 This
->llStop
= llNewStop
;
240 if (pCurrent
&& (dwCurrentFlags
& AM_SEEKING_ReturnTime
))
241 *pCurrent
= llNewCurrent
;
242 if (pStop
&& (dwStopFlags
& AM_SEEKING_ReturnTime
))
244 LeaveCriticalSection(This
->crst
);
247 This
->fnChangeStart(iface
);
249 This
->fnChangeStop(iface
);
254 HRESULT WINAPI
SourceSeekingImpl_GetPositions(IMediaSeeking
* iface
, LONGLONG
* pCurrent
, LONGLONG
* pStop
)
256 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
258 TRACE("(%p, %p)\n", pCurrent
, pStop
);
260 EnterCriticalSection(This
->crst
);
261 IMediaSeeking_GetCurrentPosition(iface
, pCurrent
);
262 IMediaSeeking_GetStopPosition(iface
, pStop
);
263 LeaveCriticalSection(This
->crst
);
268 HRESULT WINAPI
SourceSeekingImpl_GetAvailable(IMediaSeeking
* iface
, LONGLONG
* pEarliest
, LONGLONG
* pLatest
)
270 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
272 TRACE("(%p, %p)\n", pEarliest
, pLatest
);
274 EnterCriticalSection(This
->crst
);
276 *pLatest
= This
->llDuration
;
277 LeaveCriticalSection(This
->crst
);
282 HRESULT WINAPI
SourceSeekingImpl_SetRate(IMediaSeeking
* iface
, double dRate
)
284 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
285 BOOL bChangeRate
= (dRate
!= This
->dRate
);
288 TRACE("(%e)\n", dRate
);
290 if (dRate
> 100 || dRate
< .001)
292 FIXME("Excessive rate %e, ignoring\n", dRate
);
293 return VFW_E_UNSUPPORTED_AUDIO
;
296 EnterCriticalSection(This
->crst
);
299 hr
= This
->fnChangeRate(iface
);
300 LeaveCriticalSection(This
->crst
);
305 HRESULT WINAPI
SourceSeekingImpl_GetRate(IMediaSeeking
* iface
, double * dRate
)
307 SourceSeeking
*This
= impl_from_IMediaSeeking(iface
);
309 TRACE("(%p)\n", dRate
);
311 EnterCriticalSection(This
->crst
);
313 *dRate
= This
->dRate
;
314 LeaveCriticalSection(This
->crst
);
319 HRESULT WINAPI
SourceSeekingImpl_GetPreroll(IMediaSeeking
* iface
, LONGLONG
* pPreroll
)
321 TRACE("(%p)\n", pPreroll
);