[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 const GUID IID_IKsPinEx = {0x7bb38260L, 0xd19c, 0x11d2, {0xb3, 0x8a, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e}};
12
13 #ifndef _MSC_VER
14 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 #endif
16
17 #ifndef _MSC_VER
18 KSPIN_INTERFACE StandardPinInterface =
19 {
20 {STATIC_KSINTERFACESETID_Standard},
21 KSINTERFACE_STANDARD_STREAMING,
22 0
23 };
24
25 KSPIN_MEDIUM StandardPinMedium =
26 {
27 {STATIC_KSMEDIUMSETID_Standard},
28 KSMEDIUM_TYPE_ANYINSTANCE,
29 0
30 };
31
32 #else
33
34 KSPIN_INTERFACE StandardPinInterface =
35 {
36 STATIC_KSINTERFACESETID_Standard,
37 KSINTERFACE_STANDARD_STREAMING,
38 0
39 };
40
41 KSPIN_MEDIUM StandardPinMedium =
42 {
43 STATIC_KSMEDIUMSETID_Standard,
44 KSMEDIUM_TYPE_ANYINSTANCE,
45 0
46 };
47
48 #endif
49
50 class CInputPin : public IPin,
51 public IKsPropertySet,
52 public IKsControl,
53 public IKsObject,
54 public IKsPinEx,
55 public IMemInputPin,
56 public ISpecifyPropertyPages
57 /*
58 public IQualityControl,
59 public IKsPinPipe,
60 public IStreamBuilder,
61 public IKsPinFactory,
62 public IKsAggregateControl
63 */
64 {
65 public:
66 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
67
68 STDMETHODIMP_(ULONG) AddRef()
69 {
70 InterlockedIncrement(&m_Ref);
71 return m_Ref;
72 }
73 STDMETHODIMP_(ULONG) Release()
74 {
75 InterlockedDecrement(&m_Ref);
76 if (!m_Ref)
77 {
78 delete this;
79 return 0;
80 }
81 return m_Ref;
82 }
83
84 //IPin methods
85 HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
86 HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
87 HRESULT STDMETHODCALLTYPE Disconnect();
88 HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **pPin);
89 HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt);
90 HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo);
91 HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir);
92 HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id);
93 HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt);
94 HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum);
95 HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin);
96 HRESULT STDMETHODCALLTYPE EndOfStream();
97 HRESULT STDMETHODCALLTYPE BeginFlush();
98 HRESULT STDMETHODCALLTYPE EndFlush();
99 HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
100
101 // ISpecifyPropertyPages
102 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages);
103
104 //IKsObject methods
105 HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
106
107 //IKsPropertySet
108 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData);
109 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned);
110 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
111
112 //IKsControl
113 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned);
114 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned);
115 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned);
116
117 //IKsPin
118 HRESULT STDMETHODCALLTYPE KsQueryMediums(PKSMULTIPLE_ITEM* MediumList);
119 HRESULT STDMETHODCALLTYPE KsQueryInterfaces(PKSMULTIPLE_ITEM* InterfaceList);
120 HRESULT STDMETHODCALLTYPE KsCreateSinkPinHandle(KSPIN_INTERFACE& Interface, KSPIN_MEDIUM& Medium);
121 HRESULT STDMETHODCALLTYPE KsGetCurrentCommunication(KSPIN_COMMUNICATION *Communication, KSPIN_INTERFACE *Interface, KSPIN_MEDIUM *Medium);
122 HRESULT STDMETHODCALLTYPE KsPropagateAcquire();
123 HRESULT STDMETHODCALLTYPE KsDeliver(IMediaSample* Sample, ULONG Flags);
124 HRESULT STDMETHODCALLTYPE KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment);
125 IMemAllocator * STDMETHODCALLTYPE KsPeekAllocator(KSPEEKOPERATION Operation);
126 HRESULT STDMETHODCALLTYPE KsReceiveAllocator(IMemAllocator *MemAllocator);
127 HRESULT STDMETHODCALLTYPE KsRenegotiateAllocator();
128 LONG STDMETHODCALLTYPE KsIncrementPendingIoCount();
129 LONG STDMETHODCALLTYPE KsDecrementPendingIoCount();
130 HRESULT STDMETHODCALLTYPE KsQualityNotify(ULONG Proportion, REFERENCE_TIME TimeDelta);
131 // IKsPinEx
132 VOID STDMETHODCALLTYPE KsNotifyError(IMediaSample* Sample, HRESULT hr);
133
134 //IMemInputPin
135 HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator);
136 HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly);
137 HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);
138 HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample);
139 HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed);
140 HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void);
141
142 //---------------------------------------------------------------
143 HRESULT STDMETHODCALLTYPE CheckFormat(const AM_MEDIA_TYPE *pmt);
144 HRESULT STDMETHODCALLTYPE CreatePin(const AM_MEDIA_TYPE *pmt);
145 HRESULT STDMETHODCALLTYPE CreatePinHandle(PKSPIN_MEDIUM Medium, PKSPIN_INTERFACE Interface, const AM_MEDIA_TYPE *pmt);
146 CInputPin(IBaseFilter * ParentFilter, LPCWSTR PinName, HANDLE hFilter, ULONG PinId, KSPIN_COMMUNICATION Communication) : m_Ref(0), m_ParentFilter(ParentFilter), m_PinName(PinName), m_hFilter(hFilter), m_hPin(INVALID_HANDLE_VALUE), m_PinId(PinId), m_MemAllocator(0), m_IoCount(0), m_Communication(Communication), m_Pin(0), m_ReadOnly(0){};
147 virtual ~CInputPin(){};
148
149 protected:
150 LONG m_Ref;
151 IBaseFilter * m_ParentFilter;
152 LPCWSTR m_PinName;
153 HANDLE m_hFilter;
154 HANDLE m_hPin;
155 ULONG m_PinId;
156 IMemAllocator * m_MemAllocator;
157 LONG m_IoCount;
158 KSPIN_COMMUNICATION m_Communication;
159 KSPIN_INTERFACE m_Interface;
160 KSPIN_MEDIUM m_Medium;
161 IPin * m_Pin;
162 BOOL m_ReadOnly;
163 };
164
165 HRESULT
166 STDMETHODCALLTYPE
167 CInputPin::QueryInterface(
168 IN REFIID refiid,
169 OUT PVOID* Output)
170 {
171 *Output = NULL;
172
173 if (IsEqualGUID(refiid, IID_IUnknown) ||
174 IsEqualGUID(refiid, IID_IPin))
175 {
176 *Output = PVOID(this);
177 reinterpret_cast<IUnknown*>(*Output)->AddRef();
178 return NOERROR;
179 }
180 else if (IsEqualGUID(refiid, IID_IMemInputPin))
181 {
182 *Output = (IMemInputPin*)(this);
183 reinterpret_cast<IMemInputPin*>(*Output)->AddRef();
184 return NOERROR;
185 }
186 else if (IsEqualGUID(refiid, IID_IKsObject))
187 {
188 *Output = (IKsObject*)(this);
189 reinterpret_cast<IKsObject*>(*Output)->AddRef();
190 return NOERROR;
191 }
192 else if (IsEqualGUID(refiid, IID_IKsPropertySet))
193 {
194 *Output = (IKsPropertySet*)(this);
195 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef();
196 return NOERROR;
197 }
198 else if (IsEqualGUID(refiid, IID_IKsControl))
199 {
200 *Output = (IKsControl*)(this);
201 reinterpret_cast<IKsControl*>(*Output)->AddRef();
202 return NOERROR;
203 }
204 else if (IsEqualGUID(refiid, IID_IKsPin) ||
205 IsEqualGUID(refiid, IID_IKsPinEx))
206 {
207 *Output = (IKsPinEx*)(this);
208 reinterpret_cast<IKsPinEx*>(*Output)->AddRef();
209 return NOERROR;
210 }
211 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages))
212 {
213 *Output = (ISpecifyPropertyPages*)(this);
214 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef();
215 return NOERROR;
216 }
217
218 WCHAR Buffer[MAX_PATH];
219 LPOLESTR lpstr;
220 StringFromCLSID(refiid, &lpstr);
221 swprintf(Buffer, L"CInputPin::QueryInterface: NoInterface for %s\n", lpstr);
222 OutputDebugStringW(Buffer);
223 CoTaskMemFree(lpstr);
224
225 return E_NOINTERFACE;
226 }
227
228 //-------------------------------------------------------------------
229 // ISpecifyPropertyPages
230 //
231
232 HRESULT
233 STDMETHODCALLTYPE
234 CInputPin::GetPages(CAUUID *pPages)
235 {
236 if (!pPages)
237 return E_POINTER;
238
239 pPages->cElems = 0;
240 pPages->pElems = NULL;
241
242 return S_OK;
243 }
244
245 //-------------------------------------------------------------------
246 // IMemInputPin
247 //
248
249
250 HRESULT
251 STDMETHODCALLTYPE
252 CInputPin::GetAllocator(IMemAllocator **ppAllocator)
253 {
254 OutputDebugStringW(L"CInputPin::GetAllocator\n");
255 return VFW_E_NO_ALLOCATOR;
256 }
257
258 HRESULT
259 STDMETHODCALLTYPE
260 CInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
261 {
262 if (pAllocator)
263 {
264 pAllocator->AddRef();
265 }
266
267 if (m_MemAllocator)
268 {
269 m_MemAllocator->Release();
270 }
271
272 m_MemAllocator = pAllocator;
273 m_ReadOnly = bReadOnly;
274 return NOERROR;
275 }
276
277 HRESULT
278 STDMETHODCALLTYPE
279 CInputPin::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps)
280 {
281 KSALLOCATOR_FRAMING Framing;
282 KSPROPERTY Property;
283 HRESULT hr;
284 ULONG BytesReturned;
285
286 Property.Set = KSPROPSETID_Connection;
287 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
288 Property.Flags = KSPROPERTY_TYPE_SET;
289
290 hr = KsProperty(&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
291 if (SUCCEEDED(hr))
292 {
293 pProps->cBuffers = Framing.Frames;
294 pProps->cbBuffer = Framing.FrameSize;
295 pProps->cbAlign = Framing.FileAlignment;
296 pProps->cbPrefix = 0;
297 return hr;
298 }
299 else
300 return E_NOTIMPL;
301 }
302
303 HRESULT
304 STDMETHODCALLTYPE
305 CInputPin::Receive(IMediaSample *pSample)
306 {
307 OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
308 return E_NOTIMPL;
309 }
310
311 HRESULT
312 STDMETHODCALLTYPE
313 CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed)
314 {
315 OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
316 return E_NOTIMPL;
317 }
318
319 HRESULT
320 STDMETHODCALLTYPE
321 CInputPin::ReceiveCanBlock( void)
322 {
323 OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
324 return S_FALSE;
325 }
326
327
328 //-------------------------------------------------------------------
329 // IKsPin
330 //
331
332 HRESULT
333 STDMETHODCALLTYPE
334 CInputPin::KsQueryMediums(
335 PKSMULTIPLE_ITEM* MediumList)
336 {
337 return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_MEDIUMS, (PVOID*)MediumList);
338 }
339
340 HRESULT
341 STDMETHODCALLTYPE
342 CInputPin::KsQueryInterfaces(
343 PKSMULTIPLE_ITEM* InterfaceList)
344 {
345 return KsGetMultiplePinFactoryItems(m_hFilter, m_PinId, KSPROPERTY_PIN_INTERFACES, (PVOID*)InterfaceList);
346 }
347
348 HRESULT
349 STDMETHODCALLTYPE
350 CInputPin::KsCreateSinkPinHandle(
351 KSPIN_INTERFACE& Interface,
352 KSPIN_MEDIUM& Medium)
353 {
354 OutputDebugStringW(L"CInputPin::KsCreateSinkPinHandle NotImplemented\n");
355 return E_NOTIMPL;
356 }
357
358 HRESULT
359 STDMETHODCALLTYPE
360 CInputPin::KsGetCurrentCommunication(
361 KSPIN_COMMUNICATION *Communication,
362 KSPIN_INTERFACE *Interface,
363 KSPIN_MEDIUM *Medium)
364 {
365 if (Communication)
366 {
367 *Communication = m_Communication;
368 }
369
370 if (Interface)
371 {
372 if (!m_hPin)
373 return VFW_E_NOT_CONNECTED;
374
375 CopyMemory(Interface, &m_Interface, sizeof(KSPIN_INTERFACE));
376 }
377
378 if (Medium)
379 {
380 if (!m_hPin)
381 return VFW_E_NOT_CONNECTED;
382
383 CopyMemory(Medium, &m_Medium, sizeof(KSPIN_MEDIUM));
384 }
385 return NOERROR;
386 }
387
388 HRESULT
389 STDMETHODCALLTYPE
390 CInputPin::KsPropagateAcquire()
391 {
392 OutputDebugStringW(L"CInputPin::KsPropagateAcquire NotImplemented\n");
393 return E_NOTIMPL;
394 }
395
396 HRESULT
397 STDMETHODCALLTYPE
398 CInputPin::KsDeliver(
399 IMediaSample* Sample,
400 ULONG Flags)
401 {
402 return E_FAIL;
403 }
404
405 HRESULT
406 STDMETHODCALLTYPE
407 CInputPin::KsMediaSamplesCompleted(PKSSTREAM_SEGMENT StreamSegment)
408 {
409 return NOERROR;
410 }
411
412 IMemAllocator *
413 STDMETHODCALLTYPE
414 CInputPin::KsPeekAllocator(KSPEEKOPERATION Operation)
415 {
416 if (Operation == KsPeekOperation_AddRef)
417 {
418 // add reference on allocator
419 m_MemAllocator->AddRef();
420 }
421
422 return m_MemAllocator;
423 }
424
425 HRESULT
426 STDMETHODCALLTYPE
427 CInputPin::KsReceiveAllocator(IMemAllocator *MemAllocator)
428 {
429 if (MemAllocator)
430 {
431 MemAllocator->AddRef();
432 }
433
434 if (m_MemAllocator)
435 {
436 m_MemAllocator->Release();
437 }
438
439 m_MemAllocator = MemAllocator;
440 return NOERROR;
441 }
442
443 HRESULT
444 STDMETHODCALLTYPE
445 CInputPin::KsRenegotiateAllocator()
446 {
447 return E_FAIL;
448 }
449
450 LONG
451 STDMETHODCALLTYPE
452 CInputPin::KsIncrementPendingIoCount()
453 {
454 return InterlockedIncrement((volatile LONG*)&m_IoCount);
455 }
456
457 LONG
458 STDMETHODCALLTYPE
459 CInputPin::KsDecrementPendingIoCount()
460 {
461 return InterlockedDecrement((volatile LONG*)&m_IoCount);
462 }
463
464 HRESULT
465 STDMETHODCALLTYPE
466 CInputPin::KsQualityNotify(
467 ULONG Proportion,
468 REFERENCE_TIME TimeDelta)
469 {
470 OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
471 return E_NOTIMPL;
472 }
473
474 //-------------------------------------------------------------------
475 // IKsPinEx
476 //
477
478 VOID
479 STDMETHODCALLTYPE
480 CInputPin::KsNotifyError(
481 IMediaSample* Sample,
482 HRESULT hr)
483 {
484 OutputDebugStringW(L"CInputPin::KsNotifyError NotImplemented\n");
485 }
486
487
488 //-------------------------------------------------------------------
489 // IKsControl
490 //
491 HRESULT
492 STDMETHODCALLTYPE
493 CInputPin::KsProperty(
494 PKSPROPERTY Property,
495 ULONG PropertyLength,
496 LPVOID PropertyData,
497 ULONG DataLength,
498 ULONG* BytesReturned)
499 {
500 assert(m_hPin != 0);
501 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned);
502 }
503
504 HRESULT
505 STDMETHODCALLTYPE
506 CInputPin::KsMethod(
507 PKSMETHOD Method,
508 ULONG MethodLength,
509 LPVOID MethodData,
510 ULONG DataLength,
511 ULONG* BytesReturned)
512 {
513 assert(m_hPin != 0);
514 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned);
515 }
516
517 HRESULT
518 STDMETHODCALLTYPE
519 CInputPin::KsEvent(
520 PKSEVENT Event,
521 ULONG EventLength,
522 LPVOID EventData,
523 ULONG DataLength,
524 ULONG* BytesReturned)
525 {
526 assert(m_hPin != 0);
527
528 if (EventLength)
529 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned);
530 else
531 return KsSynchronousDeviceControl(m_hPin, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned);
532 }
533
534
535 //-------------------------------------------------------------------
536 // IKsPropertySet
537 //
538 HRESULT
539 STDMETHODCALLTYPE
540 CInputPin::Set(
541 REFGUID guidPropSet,
542 DWORD dwPropID,
543 LPVOID pInstanceData,
544 DWORD cbInstanceData,
545 LPVOID pPropData,
546 DWORD cbPropData)
547 {
548 ULONG BytesReturned;
549
550 if (cbInstanceData)
551 {
552 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
553 if (!Property)
554 return E_OUTOFMEMORY;
555
556 Property->Set = guidPropSet;
557 Property->Id = dwPropID;
558 Property->Flags = KSPROPERTY_TYPE_SET;
559
560 CopyMemory((Property+1), pInstanceData, cbInstanceData);
561
562 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
563 CoTaskMemFree(Property);
564 return hr;
565 }
566 else
567 {
568 KSPROPERTY Property;
569
570 Property.Set = guidPropSet;
571 Property.Id = dwPropID;
572 Property.Flags = KSPROPERTY_TYPE_SET;
573
574 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
575 return hr;
576 }
577 }
578
579 HRESULT
580 STDMETHODCALLTYPE
581 CInputPin::Get(
582 REFGUID guidPropSet,
583 DWORD dwPropID,
584 LPVOID pInstanceData,
585 DWORD cbInstanceData,
586 LPVOID pPropData,
587 DWORD cbPropData,
588 DWORD *pcbReturned)
589 {
590 ULONG BytesReturned;
591
592 if (cbInstanceData)
593 {
594 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData);
595 if (!Property)
596 return E_OUTOFMEMORY;
597
598 Property->Set = guidPropSet;
599 Property->Id = dwPropID;
600 Property->Flags = KSPROPERTY_TYPE_GET;
601
602 CopyMemory((Property+1), pInstanceData, cbInstanceData);
603
604 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned);
605 CoTaskMemFree(Property);
606 return hr;
607 }
608 else
609 {
610 KSPROPERTY Property;
611
612 Property.Set = guidPropSet;
613 Property.Id = dwPropID;
614 Property.Flags = KSPROPERTY_TYPE_GET;
615
616 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned);
617 return hr;
618 }
619 }
620
621 HRESULT
622 STDMETHODCALLTYPE
623 CInputPin::QuerySupported(
624 REFGUID guidPropSet,
625 DWORD dwPropID,
626 DWORD *pTypeSupport)
627 {
628 KSPROPERTY Property;
629 ULONG BytesReturned;
630
631 Property.Set = guidPropSet;
632 Property.Id = dwPropID;
633 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT;
634
635 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned);
636 }
637
638
639 //-------------------------------------------------------------------
640 // IKsObject
641 //
642 HANDLE
643 STDMETHODCALLTYPE
644 CInputPin::KsGetObjectHandle()
645 {
646 assert(m_hPin);
647 return m_hPin;
648 }
649
650 //-------------------------------------------------------------------
651 // IPin interface
652 //
653 HRESULT
654 STDMETHODCALLTYPE
655 CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
656 {
657 OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
658 return NOERROR;
659 }
660
661 HRESULT
662 STDMETHODCALLTYPE
663 CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
664 {
665 HRESULT hr;
666
667 if (m_Pin)
668 {
669 return VFW_E_ALREADY_CONNECTED;
670 }
671
672 // first check format
673 hr = CheckFormat(pmt);
674 if (FAILED(hr))
675 return hr;
676
677 if (FAILED(CheckFormat(pmt)))
678 return hr;
679
680 hr = CreatePin(pmt);
681 if (FAILED(hr))
682 {
683 return hr;
684 }
685
686 //FIXME create pin
687 m_Pin = pConnector;
688 m_Pin->AddRef();
689
690 return S_OK;
691 }
692 HRESULT
693 STDMETHODCALLTYPE
694 CInputPin::Disconnect( void)
695 {
696 if (!m_Pin)
697 {
698 // pin was not connected
699 return S_FALSE;
700 }
701
702 //FIXME
703 //check if filter is active
704
705 m_Pin->Release();
706 m_Pin = NULL;
707
708 OutputDebugStringW(L"CInputPin::Disconnect\n");
709 return S_OK;
710 }
711 HRESULT
712 STDMETHODCALLTYPE
713 CInputPin::ConnectedTo(IPin **pPin)
714 {
715 if (!pPin)
716 return E_POINTER;
717
718 if (m_Pin)
719 {
720 // increment reference count
721 m_Pin->AddRef();
722 *pPin = m_Pin;
723 return S_OK;
724 }
725
726 *pPin = NULL;
727 return VFW_E_NOT_CONNECTED;
728 }
729 HRESULT
730 STDMETHODCALLTYPE
731 CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
732 {
733 if (!m_Pin)
734 return VFW_E_NOT_CONNECTED;
735
736 OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
737 return E_NOTIMPL;
738 }
739 HRESULT
740 STDMETHODCALLTYPE
741 CInputPin::QueryPinInfo(PIN_INFO *pInfo)
742 {
743 wcscpy(pInfo->achName, m_PinName);
744 pInfo->dir = PINDIR_INPUT;
745 pInfo->pFilter = m_ParentFilter;
746 m_ParentFilter->AddRef();
747
748 return S_OK;
749 }
750 HRESULT
751 STDMETHODCALLTYPE
752 CInputPin::QueryDirection(PIN_DIRECTION *pPinDir)
753 {
754 if (pPinDir)
755 {
756 *pPinDir = PINDIR_INPUT;
757 return S_OK;
758 }
759
760 return E_POINTER;
761 }
762 HRESULT
763 STDMETHODCALLTYPE
764 CInputPin::QueryId(LPWSTR *Id)
765 {
766 *Id = (LPWSTR)CoTaskMemAlloc((wcslen(m_PinName)+1)*sizeof(WCHAR));
767 if (!*Id)
768 return E_OUTOFMEMORY;
769
770 wcscpy(*Id, m_PinName);
771 return S_OK;
772 }
773
774 HRESULT
775 STDMETHODCALLTYPE
776 CInputPin::QueryAccept(
777 const AM_MEDIA_TYPE *pmt)
778 {
779 return CheckFormat(pmt);
780 }
781 HRESULT
782 STDMETHODCALLTYPE
783 CInputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
784 {
785 HRESULT hr;
786 ULONG MediaTypeCount = 0, Index;
787 AM_MEDIA_TYPE * MediaTypes;
788
789 // query media type count
790 hr = KsGetMediaTypeCount(m_hFilter, m_PinId, &MediaTypeCount);
791 if (FAILED(hr) || !MediaTypeCount)
792 return hr;
793
794 // allocate media types
795 MediaTypes = (AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
796 if (!MediaTypes)
797 {
798 // not enough memory
799 return E_OUTOFMEMORY;
800 }
801
802 // zero media types
803 ZeroMemory(MediaTypes, sizeof(AM_MEDIA_TYPE) * MediaTypeCount);
804
805 for(Index = 0; Index < MediaTypeCount; Index++)
806 {
807 // get media type
808 hr = KsGetMediaType(Index, &MediaTypes[Index], m_hFilter, m_PinId);
809 if (FAILED(hr))
810 {
811 // failed
812 CoTaskMemFree(MediaTypes);
813 return hr;
814 }
815 }
816
817 return CEnumMediaTypes_fnConstructor(MediaTypeCount, MediaTypes, IID_IEnumMediaTypes, (void**)ppEnum);
818 }
819
820 HRESULT
821 STDMETHODCALLTYPE
822 CInputPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
823 {
824 OutputDebugStringW(L"CInputPin::QueryInternalConnections NotImplemented\n");
825 return E_NOTIMPL;
826 }
827 HRESULT
828 STDMETHODCALLTYPE
829 CInputPin::EndOfStream( void)
830 {
831 OutputDebugStringW(L"CInputPin::EndOfStream NotImplemented\n");
832 return E_NOTIMPL;
833 }
834 HRESULT
835 STDMETHODCALLTYPE
836 CInputPin::BeginFlush( void)
837 {
838 OutputDebugStringW(L"CInputPin::BeginFlush NotImplemented\n");
839 return E_NOTIMPL;
840 }
841 HRESULT
842 STDMETHODCALLTYPE
843 CInputPin::EndFlush( void)
844 {
845 OutputDebugStringW(L"CInputPin::EndFlush NotImplemented\n");
846 return E_NOTIMPL;
847 }
848 HRESULT
849 STDMETHODCALLTYPE
850 CInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
851 {
852 OutputDebugStringW(L"CInputPin::NewSegment NotImplemented\n");
853 return E_NOTIMPL;
854 }
855
856 //-------------------------------------------------------------------
857 HRESULT
858 STDMETHODCALLTYPE
859 CInputPin::CheckFormat(
860 const AM_MEDIA_TYPE *pmt)
861 {
862 KSP_PIN Property;
863 PKSMULTIPLE_ITEM MultipleItem;
864 PKSDATAFORMAT DataFormat;
865 ULONG BytesReturned;
866 HRESULT hr;
867
868 // prepare request
869 Property.Property.Set = KSPROPSETID_Pin;
870 Property.Property.Id = KSPROPERTY_PIN_DATARANGES;
871 Property.Property.Flags = KSPROPERTY_TYPE_GET;
872 Property.PinId = m_PinId;
873 Property.Reserved = 0;
874
875 if (!pmt)
876 return E_POINTER;
877
878 // query for size of dataranges
879 hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
880
881 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA))
882 {
883 // allocate dataranges buffer
884 MultipleItem = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned);
885
886 if (!MultipleItem)
887 return E_OUTOFMEMORY;
888
889 // query dataranges
890 hr = KsSynchronousDeviceControl(m_hFilter, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
891
892 if (FAILED(hr))
893 {
894 // failed to query data ranges
895 CoTaskMemFree(MultipleItem);
896 return hr;
897 }
898
899 DataFormat = (PKSDATAFORMAT)(MultipleItem + 1);
900 for(ULONG Index = 0; Index < MultipleItem->Count; Index++)
901 {
902 if (IsEqualGUID(pmt->majortype, DataFormat->MajorFormat) &&
903 IsEqualGUID(pmt->subtype, DataFormat->SubFormat) &&
904 IsEqualGUID(pmt->formattype, DataFormat->Specifier))
905 {
906 // format is supported
907 CoTaskMemFree(MultipleItem);
908 OutputDebugStringW(L"CInputPin::CheckFormat format OK\n");
909 return S_OK;
910 }
911 DataFormat = (PKSDATAFORMAT)((ULONG_PTR)DataFormat + DataFormat->FormatSize);
912 }
913 //format is not supported
914 CoTaskMemFree(MultipleItem);
915 }
916 return S_FALSE;
917 }
918
919 HRESULT
920 STDMETHODCALLTYPE
921 CInputPin::CreatePin(
922 const AM_MEDIA_TYPE *pmt)
923 {
924 PKSMULTIPLE_ITEM MediumList;
925 PKSMULTIPLE_ITEM InterfaceList;
926 PKSPIN_MEDIUM Medium;
927 PKSPIN_INTERFACE Interface;
928 HRESULT hr;
929
930 // query for pin medium
931 hr = KsQueryMediums(&MediumList);
932 if (FAILED(hr))
933 return hr;
934
935 // query for pin interface
936 hr = KsQueryInterfaces(&InterfaceList);
937 if (FAILED(hr))
938 {
939 // failed
940 CoTaskMemFree(MediumList);
941 return hr;
942 }
943
944 if (MediumList->Count)
945 {
946 //use first available medium
947 Medium = (PKSPIN_MEDIUM)(MediumList + 1);
948 }
949 else
950 {
951 // default to standard medium
952 Medium = &StandardPinMedium;
953 }
954
955 if (InterfaceList->Count)
956 {
957 //use first available interface
958 Interface = (PKSPIN_INTERFACE)(InterfaceList + 1);
959 }
960 else
961 {
962 // default to standard interface
963 Interface = &StandardPinInterface;
964 }
965
966 // now create pin
967 hr = CreatePinHandle(Medium, Interface, pmt);
968
969 // free medium / interface / dataformat
970 CoTaskMemFree(MediumList);
971 CoTaskMemFree(InterfaceList);
972
973 return hr;
974 }
975
976 HRESULT
977 STDMETHODCALLTYPE
978 CInputPin::CreatePinHandle(
979 PKSPIN_MEDIUM Medium,
980 PKSPIN_INTERFACE Interface,
981 const AM_MEDIA_TYPE *pmt)
982 {
983 PKSPIN_CONNECT PinConnect;
984 PKSDATAFORMAT DataFormat;
985 ULONG Length;
986 HRESULT hr;
987
988 // calc format size
989 Length = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT) + pmt->cbFormat;
990
991 // allocate pin connect
992 PinConnect = (PKSPIN_CONNECT)CoTaskMemAlloc(Length);
993 if (!PinConnect)
994 {
995 // failed
996 return E_OUTOFMEMORY;
997 }
998
999 // setup request
1000 CopyMemory(&PinConnect->Interface, Interface, sizeof(KSPIN_INTERFACE));
1001 CopyMemory(&PinConnect->Medium, Medium, sizeof(KSPIN_MEDIUM));
1002 PinConnect->PinId = m_PinId;
1003 PinConnect->PinToHandle = NULL;
1004 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
1005 PinConnect->Priority.PrioritySubClass = KSPRIORITY_NORMAL;
1006
1007 // get dataformat offset
1008 DataFormat = (PKSDATAFORMAT)(PinConnect + 1);
1009
1010 // copy data format
1011 DataFormat->FormatSize = sizeof(KSDATAFORMAT) + pmt->cbFormat;
1012 DataFormat->Flags = 0;
1013 DataFormat->SampleSize = pmt->lSampleSize;
1014 DataFormat->Reserved = 0;
1015 CopyMemory(&DataFormat->MajorFormat, &pmt->majortype, sizeof(GUID));
1016 CopyMemory(&DataFormat->SubFormat, &pmt->subtype, sizeof(GUID));
1017 CopyMemory(&DataFormat->Specifier, &pmt->formattype, sizeof(GUID));
1018
1019 if (pmt->cbFormat)
1020 {
1021 // copy extended format
1022 CopyMemory((DataFormat + 1), pmt->pbFormat, pmt->cbFormat);
1023 }
1024
1025 // create pin
1026 hr = KsCreatePin(m_hFilter, PinConnect, GENERIC_WRITE, &m_hPin);
1027
1028 // free pin connect
1029 CoTaskMemFree(PinConnect);
1030
1031 return hr;
1032 }
1033
1034 HRESULT
1035 WINAPI
1036 CInputPin_Constructor(
1037 IBaseFilter * ParentFilter,
1038 LPCWSTR PinName,
1039 HANDLE hFilter,
1040 ULONG PinId,
1041 KSPIN_COMMUNICATION Communication,
1042 REFIID riid,
1043 LPVOID * ppv)
1044 {
1045 CInputPin * handler = new CInputPin(ParentFilter, PinName, hFilter, PinId, Communication);
1046
1047 if (!handler)
1048 return E_OUTOFMEMORY;
1049
1050 if (FAILED(handler->QueryInterface(riid, ppv)))
1051 {
1052 /* not supported */
1053 delete handler;
1054 return E_NOINTERFACE;
1055 }
1056
1057 return S_OK;
1058 }