Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/strmbase/seeking.c
8729 views
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
22
#include <assert.h>
23
#define COBJMACROS
24
#include "wine/strmbase.h"
25
#include "wine/debug.h"
26
27
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
28
29
static inline SourceSeeking *impl_from_IMediaSeeking(IMediaSeeking *iface)
30
{
31
return CONTAINING_RECORD(iface, SourceSeeking, IMediaSeeking_iface);
32
}
33
34
HRESULT strmbase_seeking_init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl,
35
SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart,
36
SourceSeeking_ChangeRate fnChangeRate)
37
{
38
assert(fnChangeStop && fnChangeStart && fnChangeRate);
39
40
pSeeking->IMediaSeeking_iface.lpVtbl = Vtbl;
41
pSeeking->refCount = 1;
42
pSeeking->fnChangeRate = fnChangeRate;
43
pSeeking->fnChangeStop = fnChangeStop;
44
pSeeking->fnChangeStart = fnChangeStart;
45
pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards |
46
AM_SEEKING_CanSeekBackwards |
47
AM_SEEKING_CanSeekAbsolute |
48
AM_SEEKING_CanGetStopPos |
49
AM_SEEKING_CanGetDuration;
50
pSeeking->llCurrent = 0;
51
pSeeking->llStop = ((ULONGLONG)0x80000000) << 32;
52
pSeeking->llDuration = pSeeking->llStop;
53
pSeeking->dRate = 1.0;
54
pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME;
55
if (!InitializeCriticalSectionEx(&pSeeking->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO))
56
InitializeCriticalSection(&pSeeking->cs);
57
pSeeking->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SourceSeeking.cs");
58
return S_OK;
59
}
60
61
void strmbase_seeking_cleanup(SourceSeeking *seeking)
62
{
63
seeking->cs.DebugInfo->Spare[0] = 0;
64
DeleteCriticalSection(&seeking->cs);
65
}
66
67
HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
68
{
69
SourceSeeking *This = impl_from_IMediaSeeking(iface);
70
71
TRACE("(%p)\n", pCapabilities);
72
73
*pCapabilities = This->dwCapabilities;
74
75
return S_OK;
76
}
77
78
HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
79
{
80
SourceSeeking *This = impl_from_IMediaSeeking(iface);
81
HRESULT hr;
82
DWORD dwCommonCaps;
83
84
TRACE("(%p)\n", pCapabilities);
85
86
if (!pCapabilities)
87
return E_POINTER;
88
89
dwCommonCaps = *pCapabilities & This->dwCapabilities;
90
91
if (!dwCommonCaps)
92
hr = E_FAIL;
93
else
94
hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE;
95
*pCapabilities = dwCommonCaps;
96
return hr;
97
}
98
99
HRESULT WINAPI SourceSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
100
{
101
TRACE("(%s)\n", debugstr_guid(pFormat));
102
103
return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
104
}
105
106
HRESULT WINAPI SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
107
{
108
TRACE("(%s)\n", debugstr_guid(pFormat));
109
110
*pFormat = TIME_FORMAT_MEDIA_TIME;
111
return S_OK;
112
}
113
114
HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
115
{
116
SourceSeeking *This = impl_from_IMediaSeeking(iface);
117
TRACE("(%s)\n", debugstr_guid(pFormat));
118
119
EnterCriticalSection(&This->cs);
120
*pFormat = This->timeformat;
121
LeaveCriticalSection(&This->cs);
122
123
return S_OK;
124
}
125
126
HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
127
{
128
SourceSeeking *This = impl_from_IMediaSeeking(iface);
129
HRESULT hr = S_OK;
130
131
TRACE("(%s)\n", debugstr_guid(pFormat));
132
133
EnterCriticalSection(&This->cs);
134
if (!IsEqualIID(pFormat, &This->timeformat))
135
hr = S_FALSE;
136
LeaveCriticalSection(&This->cs);
137
138
return hr;
139
}
140
141
HRESULT WINAPI SourceSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
142
{
143
SourceSeeking *This = impl_from_IMediaSeeking(iface);
144
TRACE("%p %s\n", This, debugstr_guid(pFormat));
145
return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : E_INVALIDARG);
146
}
147
148
149
HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
150
{
151
SourceSeeking *This = impl_from_IMediaSeeking(iface);
152
153
TRACE("(%p)\n", pDuration);
154
155
EnterCriticalSection(&This->cs);
156
*pDuration = This->llDuration;
157
LeaveCriticalSection(&This->cs);
158
159
return S_OK;
160
}
161
162
HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
163
{
164
SourceSeeking *This = impl_from_IMediaSeeking(iface);
165
166
TRACE("(%p)\n", pStop);
167
168
EnterCriticalSection(&This->cs);
169
*pStop = This->llStop;
170
LeaveCriticalSection(&This->cs);
171
172
return S_OK;
173
}
174
175
/* FIXME: Make use of the info the filter should expose */
176
HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
177
{
178
SourceSeeking *This = impl_from_IMediaSeeking(iface);
179
180
TRACE("(%p)\n", pCurrent);
181
182
EnterCriticalSection(&This->cs);
183
*pCurrent = This->llCurrent;
184
LeaveCriticalSection(&This->cs);
185
186
return S_OK;
187
}
188
189
HRESULT WINAPI SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
190
{
191
SourceSeeking *This = impl_from_IMediaSeeking(iface);
192
if (!pTargetFormat)
193
pTargetFormat = &This->timeformat;
194
if (!pSourceFormat)
195
pSourceFormat = &This->timeformat;
196
if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
197
{
198
*pTarget = Source;
199
return S_OK;
200
}
201
/* FIXME: clear pTarget? */
202
return E_INVALIDARG;
203
}
204
205
static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags)
206
{
207
switch (dwFlags & AM_SEEKING_PositioningBitsMask)
208
{
209
case AM_SEEKING_NoPositioning:
210
return value;
211
case AM_SEEKING_AbsolutePositioning:
212
return *pModifier;
213
case AM_SEEKING_RelativePositioning:
214
case AM_SEEKING_IncrementalPositioning:
215
return value + *pModifier;
216
default:
217
assert(FALSE);
218
return 0;
219
}
220
}
221
222
HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
223
{
224
SourceSeeking *This = impl_from_IMediaSeeking(iface);
225
BOOL bChangeCurrent = FALSE, bChangeStop = FALSE;
226
LONGLONG llNewCurrent, llNewStop;
227
228
TRACE("iface %p, current %s, current_flags %#lx, stop %s, stop_flags %#lx.\n", iface,
229
pCurrent ? debugstr_time(*pCurrent) : "<null>", dwCurrentFlags,
230
pStop ? debugstr_time(*pStop): "<null>", dwStopFlags);
231
232
EnterCriticalSection(&This->cs);
233
234
llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags);
235
llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
236
237
if (pCurrent)
238
bChangeCurrent = TRUE;
239
if (llNewStop != This->llStop)
240
bChangeStop = TRUE;
241
242
TRACE("Seeking from %s to %s.\n", debugstr_time(This->llCurrent), debugstr_time(llNewCurrent));
243
244
This->llCurrent = llNewCurrent;
245
This->llStop = llNewStop;
246
247
if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime))
248
*pCurrent = llNewCurrent;
249
if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime))
250
*pStop = llNewStop;
251
LeaveCriticalSection(&This->cs);
252
253
if (bChangeCurrent)
254
This->fnChangeStart(iface);
255
if (bChangeStop)
256
This->fnChangeStop(iface);
257
258
return S_OK;
259
}
260
261
HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
262
{
263
SourceSeeking *This = impl_from_IMediaSeeking(iface);
264
265
TRACE("(%p, %p)\n", pCurrent, pStop);
266
267
EnterCriticalSection(&This->cs);
268
IMediaSeeking_GetCurrentPosition(iface, pCurrent);
269
IMediaSeeking_GetStopPosition(iface, pStop);
270
LeaveCriticalSection(&This->cs);
271
272
return S_OK;
273
}
274
275
HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
276
{
277
SourceSeeking *This = impl_from_IMediaSeeking(iface);
278
279
TRACE("(%p, %p)\n", pEarliest, pLatest);
280
281
EnterCriticalSection(&This->cs);
282
*pEarliest = 0;
283
*pLatest = This->llDuration;
284
LeaveCriticalSection(&This->cs);
285
286
return S_OK;
287
}
288
289
HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
290
{
291
SourceSeeking *This = impl_from_IMediaSeeking(iface);
292
BOOL bChangeRate = (dRate != This->dRate);
293
HRESULT hr = S_OK;
294
295
TRACE("(%e)\n", dRate);
296
297
if (dRate > 100 || dRate < .001)
298
{
299
FIXME("Excessive rate %e, ignoring\n", dRate);
300
return VFW_E_UNSUPPORTED_AUDIO;
301
}
302
303
EnterCriticalSection(&This->cs);
304
This->dRate = dRate;
305
if (bChangeRate)
306
hr = This->fnChangeRate(iface);
307
LeaveCriticalSection(&This->cs);
308
309
return hr;
310
}
311
312
HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
313
{
314
SourceSeeking *This = impl_from_IMediaSeeking(iface);
315
316
TRACE("(%p)\n", dRate);
317
318
EnterCriticalSection(&This->cs);
319
/* Forward? */
320
*dRate = This->dRate;
321
LeaveCriticalSection(&This->cs);
322
323
return S_OK;
324
}
325
326
HRESULT WINAPI SourceSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
327
{
328
TRACE("(%p)\n", pPreroll);
329
330
*pPreroll = 0;
331
return S_OK;
332
}
333
334