[KSPROXY]
[reactos.git] / reactos / dll / directx / ksproxy / input_pin.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/input_cpp.cpp
5 * PURPOSE: InputPin of Proxy Filter
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 class CInputPin : public IPin,
12 public IKsPropertySet,
13 public IKsControl,
14 public IKsObject
15 /*
16 public IQualityControl,
17 public IKsPinEx,
18 public IKsPinPipe,
19 public ISpecifyPropertyPages,
20 public IStreamBuilder,
21 public IKsPinFactory,
22 public IKsAggregateControl
23 */
24 {
25 public:
26 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
27
28 STDMETHODIMP_(ULONG) AddRef()
29 {
30 InterlockedIncrement(&m_Ref);
31 return m_Ref;
32 }
33 STDMETHODIMP_(ULONG) Release()
34 {
35 InterlockedDecrement(&m_Ref);
36 if (!m_Ref)
37 {
38 delete this;
39 return 0;
40 }
41 return m_Ref;
42 }
43
44 //IPin methods
45 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
46 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
47 HRESULT STDMETHODCALLTYPE Disconnect();
48 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
49 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
50 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
51 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
52 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
53 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
54 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
55 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
56 HRESULT STDMETHODCALLTYPE EndOfStream();
57 HRESULT STDMETHODCALLTYPE BeginFlush();
58 HRESULT STDMETHODCALLTYPE EndFlush();
59 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
60
61 //IKsObject methods
62 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
63
64 //IKsPropertySet
65 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
66 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
67 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
68
69 //IKsControl
70 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
71 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
72 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
73
74 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
75 CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(0), m_PinId(PinId){};
76 virtual ~CInputPin(){};
77
78 protected:
79 LONG m_Ref;
80 IBaseFilter * m_ParentFilter;
81 LPCWSTR m_PinName;
82 HANDLE m_hFilter;
83 HANDLE m_hPin;
84 ULONG m_PinId;
85 };
86
87 HRESULT
88 STDMETHODCALLTYPE
89 CInputPin::QueryInterface(
90 IN REFIID refiid,
91 OUT PVOID* Output)
92 {
93 *Output = NULL;
94
95 if (IsEqualGUID(refiid, IID_IUnknown) ||
96 IsEqualGUID(refiid, IID_IPin))
97 {
98 *Output = PVOID(this);
99 reinterpret_cast<IUnknown*>(*Output)->AddRef();
100 return NOERROR;
101 }
102 else if (IsEqualGUID(refiid, IID_IKsObject))
103 {
104 if (!m_hPin)
105 {
106 OutputDebugStringW(L"CInputPin::QueryInterface IID_IKsObject Create PIN!!!\n");
107 DebugBreak();
108 }
109
110 *Output = (IKsObject*)(this);
111 reinterpret_cast<IKsObject*>(*Output)->AddRef();
112 return NOERROR;
113 }
114 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
115 {
116 if (!m_hPin)
117 {
118 OutputDebugStringW(L"CInputPin::QueryInterface IID_IKsPropertySet Create PIN!!!\n");
119 DebugBreak();
120 }
121
122 *Output = (IKsPropertySet*)(this);
123 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
124 return NOERROR;
125 }
126 else if (IsEqualGUID(refiid, IID_IKsControl))
127 {
128 if (!m_hPin)
129 {
130 OutputDebugStringW(L"CInputPin::QueryInterface IID_IKsControl Create PIN!!!\n");
131 DebugBreak();
132 }
133
134 *Output = (IKsControl*)(this);
135 reinterpret_cast<IKsControl*>(*Output)->AddRef();
136 return NOERROR;
137 }
138
139 WCHAR Buffer[MAX_PATH];
140 LPOLESTR lpstr;
141 StringFromCLSID(refiid, &lpstr);
142 swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr);
143 OutputDebugStringW(Buffer);
144 CoTaskMemFree(lpstr);
145
146 return E_NOINTERFACE;
147 }
148
149 //-------------------------------------------------------------------
150 // IKsPropertySet
151 //
152 HRESULT
153 STDMETHODCALLTYPE
154 CInputPin::KsProperty(
155 PKSPROPERTY Property,
156 ULONG PropertyLength,
157 LPVOID PropertyData,
158 ULONG DataLength,
159 ULONG* BytesReturned)
160 {
161 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
162 }
163
164 HRESULT
165 STDMETHODCALLTYPE
166 CInputPin::KsMethod(
167 PKSMETHOD Method,
168 ULONG MethodLength,
169 LPVOID MethodData,
170 ULONG DataLength,
171 ULONG* BytesReturned)
172 {
173 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
174 }
175
176 HRESULT
177 STDMETHODCALLTYPE
178 CInputPin::KsEvent(
179 PKSEVENT Event,
180 ULONG EventLength,
181 LPVOID EventData,
182 ULONG DataLength,
183 ULONG* BytesReturned)
184 {
185 if (EventLength)
186 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
187 else
188 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
189 }
190
191
192 //-------------------------------------------------------------------
193 // IKsPropertySet
194 //
195 HRESULT
196 STDMETHODCALLTYPE
197 CInputPin::Set(
198 REFGUID guidPropSet,
199 DWORD dwPropID,
200 LPVOID pInstanceData,
201 DWORD cbInstanceData,
202 LPVOID pPropData,
203 DWORD cbPropData)
204 {
205 ULONG BytesReturned;
206
207 if (cbInstanceData)
208 {
209 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
210 if (!Property)
211 return E_OUTOFMEMORY;
212
213 Property->Set = guidPropSet;
214 Property->Id = dwPropID;
215 Property->Flags = KSPROPERTY_TYPE_SET;
216
217 CopyMemory((Property+1), pInstanceData, cbInstanceData);
218
219 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
220 CoTaskMemFree(Property);
221 return hr;
222 }
223 else
224 {
225 KSPROPERTY Property;
226
227 Property.Set = guidPropSet;
228 Property.Id = dwPropID;
229 Property.Flags = KSPROPERTY_TYPE_SET;
230
231 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
232 return hr;
233 }
234 }
235
236 HRESULT
237 STDMETHODCALLTYPE
238 CInputPin::Get(
239 REFGUID guidPropSet,
240 DWORD dwPropID,
241 LPVOID pInstanceData,
242 DWORD cbInstanceData,
243 LPVOID pPropData,
244 DWORD cbPropData,
245 DWORD *pcbReturned)
246 {
247 ULONG BytesReturned;
248
249 if (cbInstanceData)
250 {
251 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
252 if (!Property)
253 return E_OUTOFMEMORY;
254
255 Property->Set = guidPropSet;
256 Property->Id = dwPropID;
257 Property->Flags = KSPROPERTY_TYPE_GET;
258
259 CopyMemory((Property+1), pInstanceData, cbInstanceData);
260
261 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
262 CoTaskMemFree(Property);
263 return hr;
264 }
265 else
266 {
267 KSPROPERTY Property;
268
269 Property.Set = guidPropSet;
270 Property.Id = dwPropID;
271 Property.Flags = KSPROPERTY_TYPE_GET;
272
273 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
274 return hr;
275 }
276 }
277
278 HRESULT
279 STDMETHODCALLTYPE
280 CInputPin::QuerySupported(
281 REFGUID guidPropSet,
282 DWORD dwPropID,
283 DWORD *pTypeSupport)
284 {
285 KSPROPERTY Property;
286 ULONG BytesReturned;
287
288 Property.Set = guidPropSet;
289 Property.Id = dwPropID;
290 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
291
292 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
293 }
294
295
296 //-------------------------------------------------------------------
297 // IKsObject
298 //
299 HANDLE
300 STDMETHODCALLTYPE
301 CInputPin::KsGetObjectHandle()
302 {
303 OutputDebugStringW(L"CInputPin::KsGetObjectHandle CALLED\n");
304
305 //FIXME
306 // return pin handle
307 return m_hPin;
308 }
309
310 //-------------------------------------------------------------------
311 // IPin interface
312 //
313 HRESULT
314 STDMETHODCALLTYPE
315 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
316 {
317 //MajorFormat: KSDATAFORMAT_TYPE_BDA_ANTENNA
318 //SubType: MEDIASUBTYPE_None
319 //FormatType: FORMAT_None
320 //bFixedSizeSamples 1 bTemporalCompression 0 lSampleSize 1 pUnk 00000000 cbFormat 0 pbFormat 00000000
321
322 //KSPROPSETID_Connection KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT
323 //PriorityClass = KSPRIORITY_NORMAL PrioritySubClass = KSPRIORITY_NORMAL
324
325
326 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
327 return E_NOTIMPL;
328 }
329
330 HRESULT
331 STDMETHODCALLTYPE
332 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
333 {
334 OutputDebugStringW(L"CInputPin::ReceiveConnection NotImplemented\n");
335 return E_NOTIMPL;
336 }
337 HRESULT
338 STDMETHODCALLTYPE
339 CInputPin::Disconnect( void)
340 {
341 OutputDebugStringW(L"CInputPin::Disconnect NotImplemented\n");
342 return E_NOTIMPL;
343 }
344 HRESULT
345 STDMETHODCALLTYPE
346 CInputPin::ConnectedTo(IPin **pPin)
347 {
348 *pPin = NULL;
349 OutputDebugStringW(L"CInputPin::ConnectedTo NotImplemented\n");
350 return VFW_E_NOT_CONNECTED;
351 }
352 HRESULT
353 STDMETHODCALLTYPE
354 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
355 {
356 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
357 return E_NOTIMPL;
358 }
359 HRESULT
360 STDMETHODCALLTYPE
361 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
362 {
363 wcscpy(pInfo->achName, m_PinName);
364 pInfo->dir = PINDIR_INPUT;
365 pInfo->pFilter = m_ParentFilter;
366 m_ParentFilter->AddRef();
367
368 return S_OK;
369 }
370 HRESULT
371 STDMETHODCALLTYPE
372 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
373 {
374 if (pPinDir)
375 {
376 *pPinDir = PINDIR_INPUT;
377 return S_OK;
378 }
379
380 return E_POINTER;
381 }
382 HRESULT
383 STDMETHODCALLTYPE
384 CInputPin::QueryId(LPWSTR *Id)
385 {
386 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
387 if (!*Id)
388 return E_OUTOFMEMORY;
389
390 wcscpy(*Id, m_PinName);
391 return S_OK;
392 }
393
394 HRESULT
395 STDMETHODCALLTYPE
396 CInputPin::CheckFormat(
397 const AM_MEDIA_TYPE *pmt)
398 {
399 KSP_PIN Property;
400 PKSMULTIPLE_ITEM MultipleItem;
401 PKSDATAFORMAT DataFormat;
402 ULONG BytesReturned;
403 HRESULT hr;
404
405 // prepare request
406 Property.Property.Set = KSPROPSETID_Pin;
407 Property.Property.Id = KSPROPERTY_PIN_DATARANGES;
408 Property.Property.Flags = KSPROPERTY_TYPE_GET;
409 Property.PinId = m_PinId;
410 Property.Reserved = 0;
411
412 // query for size of dataranges
413 hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
414
415 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
416 {
417 // allocate dataranges buffer
418 MultipleItem = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
419
420 if (!MultipleItem)
421 return E_OUTOFMEMORY;
422
423 // query dataranges
424 hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
425
426 if (FAILED(hr))
427 {
428 // failed to query data ranges
429 CoTaskMemFree(MultipleItem);
430 return hr;
431 }
432
433 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
434 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
435 {
436 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
437 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
438 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
439 {
440 // format is supported
441 CoTaskMemFree(MultipleItem);
442 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
443 return S_OK;
444 }
445 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
446 }
447 //format is not supported
448 CoTaskMemFree(MultipleItem);
449 }
450 return S_FALSE;
451 }
452
453 HRESULT
454 STDMETHODCALLTYPE
455 CInputPin::QueryAccept(
456 const AM_MEDIA_TYPE *pmt)
457 {
458 return CheckFormat(pmt);
459 }
460 HRESULT
461 STDMETHODCALLTYPE
462 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
463 {
464 return CEnumMediaTypes_fnConstructor(0, NULL, IID_IEnumMediaTypes, (void**)ppEnum);
465 }
466 HRESULT
467 STDMETHODCALLTYPE
468 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
469 {
470 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
471 return E_NOTIMPL;
472 }
473 HRESULT
474 STDMETHODCALLTYPE
475 CInputPin::EndOfStream( void)
476 {
477 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
478 return E_NOTIMPL;
479 }
480 HRESULT
481 STDMETHODCALLTYPE
482 CInputPin::BeginFlush( void)
483 {
484 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
485 return E_NOTIMPL;
486 }
487 HRESULT
488 STDMETHODCALLTYPE
489 CInputPin::EndFlush( void)
490 {
491 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
492 return E_NOTIMPL;
493 }
494 HRESULT
495 STDMETHODCALLTYPE
496 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
497 {
498 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
499 return E_NOTIMPL;
500 }
501
502 HRESULT
503 WINAPI
504 CInputPin_Constructor(
505 IBaseFilter * ParentFilter,
506 LPCWSTR PinName,
507 HANDLE hFilter,
508 ULONG PinId,
509 REFIID riid,
510 LPVOID * ppv)
511 {
512 CInputPin * handler = new CInputPin(ParentFilter, PinName, hFilter, PinId);
513
514 if (!handler)
515 return E_OUTOFMEMORY;
516
517 if (FAILED(handler->QueryInterface(riid, ppv)))
518 {
519 /* not supported */
520 delete handler;
521 return E_NOINTERFACE;
522 }
523
524 return S_OK;
525 }