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 HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect)
37 assert(fnChangeStop && fnChangeStart && fnChangeRate);
39 pSeeking->lpVtbl = Vtbl;
40 pSeeking->refCount = 1;
41 pSeeking->fnChangeRate = fnChangeRate;
42 pSeeking->fnChangeStop = fnChangeStop;
43 pSeeking->fnChangeStart = fnChangeStart;
44 pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards |
45 AM_SEEKING_CanSeekBackwards |
46 AM_SEEKING_CanSeekAbsolute |
47 AM_SEEKING_CanGetStopPos |
48 AM_SEEKING_CanGetDuration;
49 pSeeking->llCurrent = 0;
50 pSeeking->llStop = ((ULONGLONG)0x80000000) << 32;
51 pSeeking->llDuration = pSeeking->llStop;
52 pSeeking->dRate = 1.0;
53 pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME;
54 pSeeking->crst = crit_sect;
58 HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
60 SourceSeeking *This = (SourceSeeking *)iface;
62 TRACE("(%p)\n", pCapabilities);
64 *pCapabilities = This->dwCapabilities;
69 HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
71 SourceSeeking *This = (SourceSeeking *)iface;
75 TRACE("(%p)\n", pCapabilities);
80 dwCommonCaps = *pCapabilities & This->dwCapabilities;
85 hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE;
86 *pCapabilities = dwCommonCaps;
90 HRESULT WINAPI SourceSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
92 TRACE("(%s)\n", debugstr_guid(pFormat));
94 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
97 HRESULT WINAPI SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
99 TRACE("(%s)\n", debugstr_guid(pFormat));
101 *pFormat = TIME_FORMAT_MEDIA_TIME;
105 HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
107 SourceSeeking *This = (SourceSeeking *)iface;
108 TRACE("(%s)\n", debugstr_guid(pFormat));
110 EnterCriticalSection(This->crst);
111 *pFormat = This->timeformat;
112 LeaveCriticalSection(This->crst);
117 HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
119 SourceSeeking *This = (SourceSeeking *)iface;
122 TRACE("(%s)\n", debugstr_guid(pFormat));
124 EnterCriticalSection(This->crst);
125 if (!IsEqualIID(pFormat, &This->timeformat))
127 LeaveCriticalSection(This->crst);
132 HRESULT WINAPI SourceSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
134 SourceSeeking *This = (SourceSeeking *)iface;
135 TRACE("%p %s\n", This, debugstr_guid(pFormat));
136 return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : E_INVALIDARG);
140 HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
142 SourceSeeking *This = (SourceSeeking *)iface;
144 TRACE("(%p)\n", pDuration);
146 EnterCriticalSection(This->crst);
147 *pDuration = This->llDuration;
148 LeaveCriticalSection(This->crst);
153 HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
155 SourceSeeking *This = (SourceSeeking *)iface;
157 TRACE("(%p)\n", pStop);
159 EnterCriticalSection(This->crst);
160 *pStop = This->llStop;
161 LeaveCriticalSection(This->crst);
166 /* FIXME: Make use of the info the filter should expose */
167 HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
169 SourceSeeking *This = (SourceSeeking *)iface;
171 TRACE("(%p)\n", pCurrent);
173 EnterCriticalSection(This->crst);
174 *pCurrent = This->llCurrent;
175 LeaveCriticalSection(This->crst);
180 HRESULT WINAPI SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
182 if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
187 /* FIXME: clear pTarget? */
191 static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
193 switch (dwFlags & AM_SEEKING_PositioningBitsMask)
195 case AM_SEEKING_NoPositioning:
197 case AM_SEEKING_AbsolutePositioning:
199 case AM_SEEKING_RelativePositioning:
200 case AM_SEEKING_IncrementalPositioning:
201 return value + *pModifier;
208 HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
210 SourceSeeking *This = (SourceSeeking *)iface;
211 BOOL bChangeCurrent = FALSE, bChangeStop = FALSE;
212 LONGLONG llNewCurrent, llNewStop;
214 TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
215 EnterCriticalSection(This->crst);
217 llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags);
218 llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
221 bChangeCurrent = TRUE;
222 if (llNewStop != This->llStop)
225 TRACE("Old: %u, New: %u\n", (DWORD)(This->llCurrent/10000000), (DWORD)(llNewCurrent/10000000));
227 This->llCurrent = llNewCurrent;
228 This->llStop = llNewStop;
230 if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime))
231 *pCurrent = llNewCurrent;
232 if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime))
234 LeaveCriticalSection(This->crst);
237 This->fnChangeStart(iface);
239 This->fnChangeStop(iface);
244 HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
246 SourceSeeking *This = (SourceSeeking *)iface;
248 TRACE("(%p, %p)\n", pCurrent, pStop);
250 EnterCriticalSection(This->crst);
251 IMediaSeeking_GetCurrentPosition(iface, pCurrent);
252 IMediaSeeking_GetStopPosition(iface, pStop);
253 LeaveCriticalSection(This->crst);
258 HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
260 SourceSeeking *This = (SourceSeeking *)iface;
262 TRACE("(%p, %p)\n", pEarliest, pLatest);
264 EnterCriticalSection(This->crst);
266 *pLatest = This->llDuration;
267 LeaveCriticalSection(This->crst);
272 HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
274 SourceSeeking *This = (SourceSeeking *)iface;
275 BOOL bChangeRate = (dRate != This->dRate);
278 TRACE("(%e)\n", dRate);
280 if (dRate > 100 || dRate < .001)
282 FIXME("Excessive rate %e, ignoring\n", dRate);
283 return VFW_E_UNSUPPORTED_AUDIO;
286 EnterCriticalSection(This->crst);
289 hr = This->fnChangeRate(iface);
290 LeaveCriticalSection(This->crst);
295 HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
297 SourceSeeking *This = (SourceSeeking *)iface;
299 TRACE("(%p)\n", dRate);
301 EnterCriticalSection(This->crst);
303 *dRate = This->dRate;
304 LeaveCriticalSection(This->crst);
309 HRESULT WINAPI SourceSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
311 TRACE("(%p)\n", pPreroll);