wineps.drv: Slightly simplify a PPD parser code snippet.
[wine] / dlls / strmbase / seeking.c
1 /*
2  * Filter Seeking and Control Interfaces
3  *
4  * Copyright 2003 Robert Shearman
5  * Copyright 2010 Aric Stewart, CodeWeavers
6  *
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.
11  *
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.
16  *
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
20  */
21 /* FIXME: critical sections */
22
23 #define COBJMACROS
24
25 #include "dshow.h"
26 #include "wine/strmbase.h"
27
28 #include "uuids.h"
29 #include "wine/debug.h"
30
31 #include <assert.h>
32
33 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
34
35 static inline SourceSeeking *impl_from_IMediaSeeking(IMediaSeeking *iface)
36 {
37     return CONTAINING_RECORD(iface, SourceSeeking, IMediaSeeking_iface);
38 }
39
40 HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect)
41 {
42     assert(fnChangeStop && fnChangeStart && fnChangeRate);
43
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;
60     return S_OK;
61 }
62
63 HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
64 {
65     SourceSeeking *This = impl_from_IMediaSeeking(iface);
66
67     TRACE("(%p)\n", pCapabilities);
68
69     *pCapabilities = This->dwCapabilities;
70
71     return S_OK;
72 }
73
74 HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
75 {
76     SourceSeeking *This = impl_from_IMediaSeeking(iface);
77     HRESULT hr;
78     DWORD dwCommonCaps;
79
80     TRACE("(%p)\n", pCapabilities);
81
82     if (!pCapabilities)
83         return E_POINTER;
84
85     dwCommonCaps = *pCapabilities & This->dwCapabilities;
86
87     if (!dwCommonCaps)
88         hr = E_FAIL;
89     else
90         hr = (*pCapabilities == dwCommonCaps) ?  S_OK : S_FALSE;
91     *pCapabilities = dwCommonCaps;
92     return hr;
93 }
94
95 HRESULT WINAPI SourceSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
96 {
97     TRACE("(%s)\n", debugstr_guid(pFormat));
98
99     return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
100 }
101
102 HRESULT WINAPI SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
103 {
104     TRACE("(%s)\n", debugstr_guid(pFormat));
105
106     *pFormat = TIME_FORMAT_MEDIA_TIME;
107     return S_OK;
108 }
109
110 HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
111 {
112     SourceSeeking *This = impl_from_IMediaSeeking(iface);
113     TRACE("(%s)\n", debugstr_guid(pFormat));
114
115     EnterCriticalSection(This->crst);
116     *pFormat = This->timeformat;
117     LeaveCriticalSection(This->crst);
118
119     return S_OK;
120 }
121
122 HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
123 {
124     SourceSeeking *This = impl_from_IMediaSeeking(iface);
125     HRESULT hr = S_OK;
126
127     TRACE("(%s)\n", debugstr_guid(pFormat));
128
129     EnterCriticalSection(This->crst);
130     if (!IsEqualIID(pFormat, &This->timeformat))
131         hr = S_FALSE;
132     LeaveCriticalSection(This->crst);
133
134     return hr;
135 }
136
137 HRESULT WINAPI SourceSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
138 {
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);
142 }
143
144
145 HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
146 {
147     SourceSeeking *This = impl_from_IMediaSeeking(iface);
148
149     TRACE("(%p)\n", pDuration);
150
151     EnterCriticalSection(This->crst);
152     *pDuration = This->llDuration;
153     LeaveCriticalSection(This->crst);
154
155     return S_OK;
156 }
157
158 HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
159 {
160     SourceSeeking *This = impl_from_IMediaSeeking(iface);
161
162     TRACE("(%p)\n", pStop);
163
164     EnterCriticalSection(This->crst);
165     *pStop = This->llStop;
166     LeaveCriticalSection(This->crst);
167
168     return S_OK;
169 }
170
171 /* FIXME: Make use of the info the filter should expose */
172 HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
173 {
174     SourceSeeking *This = impl_from_IMediaSeeking(iface);
175
176     TRACE("(%p)\n", pCurrent);
177
178     EnterCriticalSection(This->crst);
179     *pCurrent = This->llCurrent;
180     LeaveCriticalSection(This->crst);
181
182     return S_OK;
183 }
184
185 HRESULT WINAPI SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
186 {
187     SourceSeeking *This = impl_from_IMediaSeeking(iface);
188     if (!pTargetFormat)
189         pTargetFormat = &This->timeformat;
190     if (!pSourceFormat)
191         pSourceFormat = &This->timeformat;
192     if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
193     {
194         *pTarget = Source;
195         return S_OK;
196     }
197     /* FIXME: clear pTarget? */
198     return E_INVALIDARG;
199 }
200
201 static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
202 {
203     switch (dwFlags & AM_SEEKING_PositioningBitsMask)
204     {
205     case AM_SEEKING_NoPositioning:
206         return value;
207     case AM_SEEKING_AbsolutePositioning:
208         return *pModifier;
209     case AM_SEEKING_RelativePositioning:
210     case AM_SEEKING_IncrementalPositioning:
211         return value + *pModifier;
212     default:
213         assert(FALSE);
214         return 0;
215     }
216 }
217
218 HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
219 {
220     SourceSeeking *This = impl_from_IMediaSeeking(iface);
221     BOOL bChangeCurrent = FALSE, bChangeStop = FALSE;
222     LONGLONG llNewCurrent, llNewStop;
223
224     TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
225     EnterCriticalSection(This->crst);
226
227     llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags);
228     llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
229
230     if (pCurrent)
231         bChangeCurrent = TRUE;
232     if (llNewStop != This->llStop)
233         bChangeStop = TRUE;
234
235     TRACE("Old: %u, New: %u\n", (DWORD)(This->llCurrent/10000000), (DWORD)(llNewCurrent/10000000));
236
237     This->llCurrent = llNewCurrent;
238     This->llStop = llNewStop;
239
240     if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime))
241         *pCurrent = llNewCurrent;
242     if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime))
243         *pStop = llNewStop;
244     LeaveCriticalSection(This->crst);
245
246     if (bChangeCurrent)
247         This->fnChangeStart(iface);
248     if (bChangeStop)
249         This->fnChangeStop(iface);
250
251     return S_OK;
252 }
253
254 HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
255 {
256     SourceSeeking *This = impl_from_IMediaSeeking(iface);
257
258     TRACE("(%p, %p)\n", pCurrent, pStop);
259
260     EnterCriticalSection(This->crst);
261     IMediaSeeking_GetCurrentPosition(iface, pCurrent);
262     IMediaSeeking_GetStopPosition(iface, pStop);
263     LeaveCriticalSection(This->crst);
264
265     return S_OK;
266 }
267
268 HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
269 {
270     SourceSeeking *This = impl_from_IMediaSeeking(iface);
271
272     TRACE("(%p, %p)\n", pEarliest, pLatest);
273
274     EnterCriticalSection(This->crst);
275     *pEarliest = 0;
276     *pLatest = This->llDuration;
277     LeaveCriticalSection(This->crst);
278
279     return S_OK;
280 }
281
282 HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
283 {
284     SourceSeeking *This = impl_from_IMediaSeeking(iface);
285     BOOL bChangeRate = (dRate != This->dRate);
286     HRESULT hr = S_OK;
287
288     TRACE("(%e)\n", dRate);
289
290     if (dRate > 100 || dRate < .001)
291     {
292         FIXME("Excessive rate %e, ignoring\n", dRate);
293         return VFW_E_UNSUPPORTED_AUDIO;
294     }
295
296     EnterCriticalSection(This->crst);
297     This->dRate = dRate;
298     if (bChangeRate)
299         hr = This->fnChangeRate(iface);
300     LeaveCriticalSection(This->crst);
301
302     return hr;
303 }
304
305 HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
306 {
307     SourceSeeking *This = impl_from_IMediaSeeking(iface);
308
309     TRACE("(%p)\n", dRate);
310
311     EnterCriticalSection(This->crst);
312     /* Forward? */
313     *dRate = This->dRate;
314     LeaveCriticalSection(This->crst);
315
316     return S_OK;
317 }
318
319 HRESULT WINAPI SourceSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
320 {
321     TRACE("(%p)\n", pPreroll);
322
323     *pPreroll = 0;
324     return S_OK;
325 }