quartz: Use a safe APC to kill the PullPin thread when the PullPin is being released.
[wine] / dlls / quartz / control.c
1 /*
2  * Filter Seeking and Control Interfaces
3  *
4  * Copyright 2003 Robert Shearman
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 /* FIXME: critical sections */
21
22 #include "quartz_private.h"
23 #include "control_private.h"
24
25 #include "uuids.h"
26 #include "wine/debug.h"
27
28 #include <assert.h>
29
30 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
31
32 HRESULT MediaSeekingImpl_Init(LPVOID pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeStart, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking)
33 {
34     assert(fnChangeStop && fnChangeStart && fnChangeRate);
35
36     pSeeking->refCount = 1;
37     pSeeking->pUserData = pUserData;
38     pSeeking->fnChangeRate = fnChangeRate;
39     pSeeking->fnChangeStop = fnChangeStop;
40     pSeeking->fnChangeStart = fnChangeStart;
41     pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards |
42         AM_SEEKING_CanSeekBackwards |
43         AM_SEEKING_CanSeekAbsolute |
44         AM_SEEKING_CanGetStopPos |
45         AM_SEEKING_CanGetDuration;
46     pSeeking->llStart = 0;
47     pSeeking->llStop = ((ULONGLONG)0x80000000) << 32;
48     pSeeking->llDuration = pSeeking->llStop - pSeeking->llStart;
49     pSeeking->dRate = 1.0;
50
51     return S_OK;
52 }
53
54
55 HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
56 {
57     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
58
59     TRACE("(%p)\n", pCapabilities);
60
61     *pCapabilities = This->dwCapabilities;
62
63     return S_OK;
64 }
65
66 HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities)
67 {
68     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
69     HRESULT hr;
70     DWORD dwCommonCaps;
71
72     TRACE("(%p)\n", pCapabilities);
73
74     dwCommonCaps = *pCapabilities & This->dwCapabilities;
75
76     if (!dwCommonCaps)
77         hr = E_FAIL;
78     else
79         hr = (*pCapabilities == dwCommonCaps) ?  S_OK : S_FALSE;
80     *pCapabilities = dwCommonCaps;
81
82     return hr;
83 }
84
85 HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat)
86 {
87     TRACE("(%s)\n", qzdebugstr_guid(pFormat));
88
89     return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
90 }
91
92 HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat)
93 {
94     TRACE("(%s)\n", qzdebugstr_guid(pFormat));
95
96     *pFormat = TIME_FORMAT_MEDIA_TIME;
97     return S_OK;
98 }
99
100 HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat)
101 {
102     TRACE("(%s)\n", qzdebugstr_guid(pFormat));
103
104     *pFormat = TIME_FORMAT_MEDIA_TIME;
105     return S_OK;
106 }
107
108 HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
109 {
110     TRACE("(%s)\n", qzdebugstr_guid(pFormat));
111
112     return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
113 }
114
115 HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat)
116 {
117     TRACE("(%s)\n", qzdebugstr_guid(pFormat));
118
119     return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE);
120 }
121
122 HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration)
123 {
124     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
125
126     TRACE("(%p)\n", pDuration);
127
128     *pDuration = This->llDuration;
129
130     return S_OK;
131 }
132
133 HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop)
134 {
135     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
136
137     TRACE("(%p)\n", pStop);
138
139     *pStop = This->llStop;
140
141     return S_OK;
142 }
143
144 HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent)
145 {
146     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
147
148     TRACE("(%p)\n", pCurrent);
149
150     *pCurrent = This->llStart;
151
152     return S_OK;
153 }
154
155 HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat)
156 {
157     if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME))
158     {
159         *pTarget = Source;
160         return S_OK;
161     }
162     /* FIXME: clear pTarget? */
163     return E_INVALIDARG;
164 }
165
166 static inline LONGLONG Adjust(LONGLONG value, LONGLONG * pModifier, DWORD dwFlags)
167 {
168     switch (dwFlags & AM_SEEKING_PositioningBitsMask)
169     {
170     case AM_SEEKING_NoPositioning:
171         return value;
172     case AM_SEEKING_AbsolutePositioning:
173         return *pModifier;
174     case AM_SEEKING_RelativePositioning:
175     case AM_SEEKING_IncrementalPositioning:
176         return value + *pModifier;
177     default:
178         assert(FALSE);
179         return 0;
180     }
181 }
182
183 HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags)
184 {
185     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
186     BOOL bChangeStart = FALSE, bChangeStop = FALSE;
187     LONGLONG llNewStart, llNewStop;
188
189     TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags);
190
191     llNewStart = Adjust(This->llStart, pCurrent, dwCurrentFlags);
192     llNewStop = Adjust(This->llStop, pStop, dwStopFlags);
193
194     if (llNewStart != This->llStart)
195         bChangeStart = TRUE;
196     if (llNewStop != This->llStop)
197         bChangeStop = TRUE;
198
199     This->llStart = llNewStart;
200     This->llStop = llNewStop;
201
202     if (dwCurrentFlags & AM_SEEKING_ReturnTime)
203         *pCurrent = llNewStart;
204     if (dwStopFlags & AM_SEEKING_ReturnTime)
205         *pStop = llNewStop;
206
207     if (bChangeStart)
208         This->fnChangeStart(This->pUserData);
209     if (bChangeStop)
210         This->fnChangeStop(This->pUserData);
211
212     return S_OK;
213 }
214
215 HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop)
216 {
217     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
218
219     TRACE("(%p, %p)\n", pCurrent, pStop);
220
221     *pCurrent = This->llStart;
222     *pStop = This->llStop;
223         
224     return S_OK;
225 }
226
227 HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest)
228 {
229     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
230
231     TRACE("(%p, %p)\n", pEarliest, pLatest);
232
233     *pEarliest = 0;
234     *pLatest = This->llDuration;
235
236     return S_OK;
237 }
238
239 HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate)
240 {
241     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
242     BOOL bChangeRate = (dRate != This->dRate);
243
244     TRACE("(%e)\n", dRate);
245         
246     This->dRate = dRate;
247         
248     if (bChangeRate)
249         return This->fnChangeRate(This->pUserData);
250     else
251         return S_OK;
252 }
253
254 HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate)
255 {
256     MediaSeekingImpl *This = (MediaSeekingImpl *)iface;
257
258     TRACE("(%p)\n", dRate);
259
260     *dRate = This->dRate;
261
262     return S_OK;
263 }
264
265 HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll)
266 {
267     TRACE("(%p)\n", pPreroll);
268
269     *pPreroll = 0;
270     return S_OK;
271 }