sync with trunk r46493
[reactos.git] / dll / directx / msdvbnp / networkprovider.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Network Provider for MPEG2 based networks
4 * FILE: dll/directx/msdvbnp/networkprovider.cpp
5 * PURPOSE: IBDA_NetworkProvider interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9 #include "precomp.h"
10
11 #define DEVICE_FILTER_MASK (0x80000000)
12
13 class CNetworkProvider : public IBaseFilter,
14 public IAMovieSetup,
15 public IBDA_NetworkProvider
16 {
17 public:
18 typedef std::vector<IUnknown*>DeviceFilterStack;
19
20 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
21
22 STDMETHODIMP_(ULONG) AddRef()
23 {
24 InterlockedIncrement(&m_Ref);
25 return m_Ref;
26 }
27 STDMETHODIMP_(ULONG) Release()
28 {
29 InterlockedDecrement(&m_Ref);
30 if (!m_Ref)
31 {
32 delete this;
33 return 0;
34 }
35 return m_Ref;
36 }
37
38 // IBaseFilter methods
39 HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
40 HRESULT STDMETHODCALLTYPE Stop( void);
41 HRESULT STDMETHODCALLTYPE Pause( void);
42 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart);
43 HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State);
44 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock);
45 HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock);
46 HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum);
47 HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin);
48 HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo);
49 HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName);
50 HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo);
51
52 //IAMovieSetup methods
53 HRESULT STDMETHODCALLTYPE Register( void);
54 HRESULT STDMETHODCALLTYPE Unregister( void);
55
56 //IBDA_NetworkProvider methods
57 HRESULT STDMETHODCALLTYPE PutSignalSource(ULONG ulSignalSource);
58 HRESULT STDMETHODCALLTYPE GetSignalSource(ULONG *pulSignalSource);
59 HRESULT STDMETHODCALLTYPE GetNetworkType(GUID *pguidNetworkType);
60 HRESULT STDMETHODCALLTYPE PutTuningSpace(REFGUID guidTuningSpace);
61 HRESULT STDMETHODCALLTYPE GetTuningSpace(GUID *pguidTuingSpace);
62 HRESULT STDMETHODCALLTYPE RegisterDeviceFilter(IUnknown *pUnkFilterControl, ULONG *ppvRegisitrationContext);
63 HRESULT STDMETHODCALLTYPE UnRegisterDeviceFilter(ULONG pvRegistrationContext);
64
65 CNetworkProvider(LPCGUID ClassID);
66 virtual ~CNetworkProvider(){};
67
68 protected:
69 LONG m_Ref;
70 IFilterGraph *m_pGraph;
71 IReferenceClock * m_ReferenceClock;
72 FILTER_STATE m_FilterState;
73 IPin * m_Pins[1];
74 GUID m_ClassID;
75 DeviceFilterStack m_DeviceFilters;
76 IScanningTuner * m_Tuner;
77 };
78
79 HRESULT
80 STDMETHODCALLTYPE
81 CNetworkProvider::QueryInterface(
82 IN REFIID refiid,
83 OUT PVOID* Output)
84 {
85 ULONG Index;
86 HRESULT hr;
87
88 *Output = NULL;
89
90 if (IsEqualGUID(refiid, IID_IUnknown))
91 {
92 *Output = PVOID(this);
93 reinterpret_cast<IUnknown*>(*Output)->AddRef();
94 return NOERROR;
95 }
96 if (IsEqualGUID(refiid, IID_IBaseFilter))
97 {
98 *Output = (IBaseFilter*)(this);
99 reinterpret_cast<IBaseFilter*>(*Output)->AddRef();
100 return NOERROR;
101 }
102
103 if (IsEqualGUID(refiid, IID_ITuner) ||
104 IsEqualGUID(refiid, IID_IScanningTuner))
105 {
106 // construct scanning tuner
107 if (!m_Tuner)
108 {
109 HRESULT hr = CScanningTunner_fnConstructor(m_DeviceFilters, refiid, (void**)&m_Tuner);
110 if (FAILED(hr))
111 return hr;
112 }
113 m_Tuner->AddRef();
114 *Output = (IUnknown*)m_Tuner;
115
116 return NOERROR;
117 }
118
119 if (IsEqualGUID(refiid, IID_IBDA_NetworkProvider))
120 {
121 *Output = (IBDA_NetworkProvider*)(this);
122 reinterpret_cast<IBDA_NetworkProvider*>(*Output)->AddRef();
123 return NOERROR;
124 }
125
126 for(Index = 0; Index < m_DeviceFilters.size(); Index++)
127 {
128 // get device filter
129 IUnknown *pFilter = m_DeviceFilters[Index];
130
131 if (!pFilter)
132 continue;
133
134 // query for requested interface
135 hr = pFilter->QueryInterface(refiid, Output);
136 if (SUCCEEDED(hr))
137 {
138 #ifdef MSDVBNP_TRACE
139 WCHAR Buffer[MAX_PATH];
140 LPOLESTR lpstr;
141 StringFromCLSID(refiid, &lpstr);
142 swprintf(Buffer, L"CNetworkProvider::QueryInterface: DeviceFilter %lu supports %s !!!\n", Index, lpstr);
143 OutputDebugStringW(Buffer);
144 CoTaskMemFree(lpstr);
145 #endif
146 return hr;
147 }
148 }
149
150 WCHAR Buffer[MAX_PATH];
151 LPOLESTR lpstr;
152 StringFromCLSID(refiid, &lpstr);
153 swprintf(Buffer, L"CNetworkProvider::QueryInterface: NoInterface for %s !!!\n", lpstr);
154 OutputDebugStringW(Buffer);
155 CoTaskMemFree(lpstr);
156 DebugBreak();
157
158 return E_NOINTERFACE;
159 }
160
161 CNetworkProvider::CNetworkProvider(LPCGUID ClassID) : m_Ref(0),
162 m_pGraph(0),
163 m_ReferenceClock(0),
164 m_FilterState(State_Stopped),
165 m_DeviceFilters(),
166 m_Tuner(0)
167 {
168 m_Pins[0] = 0;
169
170 CopyMemory(&m_ClassID, ClassID, sizeof(GUID));
171 };
172
173 //-------------------------------------------------------------------
174 // IBaseFilter interface
175 //
176
177 HRESULT
178 STDMETHODCALLTYPE
179 CNetworkProvider::GetClassID(
180 CLSID *pClassID)
181 {
182 OutputDebugStringW(L"CNetworkProvider::GetClassID\n");
183 CopyMemory(&pClassID, &m_ClassID, sizeof(GUID));
184
185 return S_OK;
186 }
187
188 HRESULT
189 STDMETHODCALLTYPE
190 CNetworkProvider::Stop()
191 {
192 OutputDebugStringW(L"CNetworkProvider::Stop\n");
193 m_FilterState = State_Stopped;
194 return S_OK;
195 }
196
197 HRESULT
198 STDMETHODCALLTYPE
199 CNetworkProvider::Pause()
200 {
201 OutputDebugStringW(L"CNetworkProvider::Pause\n");
202
203 m_FilterState = State_Paused;
204 return S_OK;
205 }
206
207 HRESULT
208 STDMETHODCALLTYPE
209 CNetworkProvider::Run(
210 REFERENCE_TIME tStart)
211 {
212 OutputDebugStringW(L"CNetworkProvider::Run\n");
213
214 m_FilterState = State_Running;
215 return S_OK;
216 }
217
218 HRESULT
219 STDMETHODCALLTYPE
220 CNetworkProvider::GetState(
221 DWORD dwMilliSecsTimeout,
222 FILTER_STATE *State)
223 {
224 *State = m_FilterState;
225 return S_OK;
226 }
227
228 HRESULT
229 STDMETHODCALLTYPE
230 CNetworkProvider::SetSyncSource(
231 IReferenceClock *pClock)
232 {
233 if (pClock)
234 {
235 pClock->AddRef();
236
237 }
238 if (m_ReferenceClock)
239 {
240 m_ReferenceClock->Release();
241 }
242
243 m_ReferenceClock = pClock;
244 return S_OK;
245 }
246
247 HRESULT
248 STDMETHODCALLTYPE
249 CNetworkProvider::GetSyncSource(
250 IReferenceClock **pClock)
251 {
252 if (!pClock)
253 return E_POINTER;
254
255 if (m_ReferenceClock)
256 m_ReferenceClock->AddRef();
257
258 *pClock = m_ReferenceClock;
259 return S_OK;
260 }
261
262 HRESULT
263 STDMETHODCALLTYPE
264 CNetworkProvider::EnumPins(
265 IEnumPins **ppEnum)
266 {
267 if (m_Pins[0] == 0)
268 {
269 HRESULT hr = CPin_fnConstructor(NULL, (IBaseFilter*)this, IID_IUnknown, (void**)&m_Pins[0]);
270 if (FAILED(hr))
271 return hr;
272 }
273
274 return CEnumPins_fnConstructor(NULL, 1, m_Pins, IID_IEnumPins, (void**)ppEnum);
275 }
276
277 HRESULT
278 STDMETHODCALLTYPE
279 CNetworkProvider::FindPin(
280 LPCWSTR Id, IPin **ppPin)
281 {
282 OutputDebugStringW(L"CNetworkProvider::FindPin : NotImplemented\n");
283 return E_NOTIMPL;
284 }
285
286
287 HRESULT
288 STDMETHODCALLTYPE
289 CNetworkProvider::QueryFilterInfo(
290 FILTER_INFO *pInfo)
291 {
292 if (!pInfo)
293 return E_POINTER;
294
295 pInfo->achName[0] = L'\0';
296 pInfo->pGraph = m_pGraph;
297
298 if (m_pGraph)
299 m_pGraph->AddRef();
300
301 return S_OK;
302 }
303
304 HRESULT
305 STDMETHODCALLTYPE
306 CNetworkProvider::JoinFilterGraph(
307 IFilterGraph *pGraph,
308 LPCWSTR pName)
309 {
310 if (pGraph)
311 {
312 // joining filter graph
313 m_pGraph = pGraph;
314 }
315 else
316 {
317 // leaving graph
318 m_pGraph = 0;
319 }
320
321 OutputDebugStringW(L"CNetworkProvider::JoinFilterGraph\n");
322 return S_OK;
323 }
324
325
326 HRESULT
327 STDMETHODCALLTYPE
328 CNetworkProvider::QueryVendorInfo(
329 LPWSTR *pVendorInfo)
330 {
331 return E_NOTIMPL;
332 }
333
334 //-------------------------------------------------------------------
335 // IAMovieSetup interface
336 //
337
338 HRESULT
339 STDMETHODCALLTYPE
340 CNetworkProvider::Register()
341 {
342 OutputDebugStringW(L"CNetworkProvider::Register : NotImplemented\n");
343 return E_NOTIMPL;
344 }
345
346 HRESULT
347 STDMETHODCALLTYPE
348 CNetworkProvider::Unregister()
349 {
350 OutputDebugStringW(L"CNetworkProvider::Unregister : NotImplemented\n");
351 return E_NOTIMPL;
352 }
353
354 //-------------------------------------------------------------------
355 // IBDA_NetworkProvider interface
356 //
357
358 HRESULT
359 STDMETHODCALLTYPE
360 CNetworkProvider::PutSignalSource(
361 ULONG ulSignalSource)
362 {
363 OutputDebugStringW(L"CNetworkProvider::PutSignalSource : NotImplemented\n");
364 return E_NOTIMPL;
365 }
366
367 HRESULT
368 STDMETHODCALLTYPE
369 CNetworkProvider::GetSignalSource(
370 ULONG *pulSignalSource)
371 {
372 OutputDebugStringW(L"CNetworkProvider::GetSignalSource : NotImplemented\n");
373 return E_NOTIMPL;
374 }
375
376 HRESULT
377 STDMETHODCALLTYPE
378 CNetworkProvider::GetNetworkType(
379 GUID *pguidNetworkType)
380 {
381 OutputDebugStringW(L"CNetworkProvider::GetNetworkType : NotImplemented\n");
382 return E_NOTIMPL;
383 }
384
385 HRESULT
386 STDMETHODCALLTYPE
387 CNetworkProvider::PutTuningSpace(
388 REFGUID guidTuningSpace)
389 {
390 OutputDebugStringW(L"CNetworkProvider::PutTuningSpace : NotImplemented\n");
391 return E_NOTIMPL;
392 }
393
394 HRESULT
395 STDMETHODCALLTYPE
396 CNetworkProvider::GetTuningSpace(
397 GUID *pguidTuingSpace)
398 {
399 OutputDebugStringW(L"CNetworkProvider::GetTuningSpace : NotImplemented\n");
400 return E_NOTIMPL;
401 }
402
403 HRESULT
404 STDMETHODCALLTYPE
405 CNetworkProvider::RegisterDeviceFilter(
406 IUnknown *pUnkFilterControl,
407 ULONG *ppvRegisitrationContext)
408 {
409 HRESULT hr;
410 IBDA_DeviceControl * pDeviceControl = NULL;
411 IBDA_Topology *pTopology = NULL;
412
413 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter\n");
414
415 if (!pUnkFilterControl || !ppvRegisitrationContext)
416 {
417 //invalid argument
418 return E_POINTER;
419 }
420
421 // the filter must support IBDA_DeviceControl and IBDA_Topology
422 hr = pUnkFilterControl->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
423 if (FAILED(hr))
424 {
425 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter Filter does not support IBDA_DeviceControl\n");
426 return hr;
427 }
428
429 hr = pUnkFilterControl->QueryInterface(IID_IBDA_Topology, (void**)&pTopology);
430 if (FAILED(hr))
431 {
432 pDeviceControl->Release();
433 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter Filter does not support IID_IBDA_Topology\n");
434 return hr;
435 }
436
437 //TODO
438 // analyize device filter
439
440 // increment reference
441 pUnkFilterControl->AddRef();
442
443 // release IBDA_DeviceControl interface
444 pDeviceControl->Release();
445
446 // release IBDA_Topology interface
447 pTopology->Release();
448
449 // store registration ctx
450 *ppvRegisitrationContext = (m_DeviceFilters.size() | DEVICE_FILTER_MASK);
451
452 // store filter
453 m_DeviceFilters.push_back(pUnkFilterControl);
454
455 OutputDebugStringW(L"CNetworkProvider::RegisterDeviceFilter complete\n");
456
457 return S_OK;
458 }
459
460 HRESULT
461 STDMETHODCALLTYPE
462 CNetworkProvider::UnRegisterDeviceFilter(ULONG pvRegistrationContext)
463 {
464 ULONG Index;
465 IUnknown * pUnknown;
466
467 OutputDebugStringW(L"CNetworkProvider::UnRegisterDeviceFilter\n");
468
469 if (!(pvRegistrationContext & DEVICE_FILTER_MASK))
470 {
471 // invalid argument
472 return E_INVALIDARG;
473 }
474
475 // get real index
476 Index = pvRegistrationContext & ~DEVICE_FILTER_MASK;
477
478 if (Index >= m_DeviceFilters.size())
479 {
480 // invalid argument
481 return E_INVALIDARG;
482 }
483
484 pUnknown = m_DeviceFilters[Index];
485 if (!pUnknown)
486 {
487 // filter was already de-registered
488 return E_INVALIDARG;
489 }
490
491 // remove from vector
492 m_DeviceFilters[Index] = NULL;
493
494 // release extra reference
495 pUnknown->Release();
496
497 return NOERROR;
498 }
499
500 HRESULT
501 WINAPI
502 CNetworkProvider_fnConstructor(
503 IUnknown *pUnknown,
504 REFIID riid,
505 LPVOID * ppv)
506 {
507 CNetworkProvider * handler = new CNetworkProvider(&CLSID_DVBTNetworkProvider);
508
509 #ifdef MSDVBNP_TRACE
510 WCHAR Buffer[MAX_PATH];
511 LPOLESTR lpstr;
512 StringFromCLSID(riid, &lpstr);
513 swprintf(Buffer, L"CNetworkProvider_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown);
514 OutputDebugStringW(Buffer);
515 #endif
516
517 if (!handler)
518 return E_OUTOFMEMORY;
519
520 if (FAILED(handler->QueryInterface(riid, ppv)))
521 {
522 /* not supported */
523 delete handler;
524 return E_NOINTERFACE;
525 }
526 return NOERROR;
527 }