1 /* 2 * Unit tests for DSound Renderer functions 3 * 4 * Copyright (C) 2010 Maarten Lankhorst for CodeWeavers 5 * Copyright (C) 2007 Google (Lei Zhang) 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 #define COBJMACROS 23 24 #include "wine/test.h" 25 #include "dshow.h" 26 #include "initguid.h" 27 #include "dsound.h" 28 #include "amaudio.h" 29 30 #define QI_SUCCEED(iface, riid, ppv) hr = IUnknown_QueryInterface(iface, &riid, (LPVOID*)&ppv); \ 31 ok(hr == S_OK, "IUnknown_QueryInterface returned %x\n", hr); \ 32 ok(ppv != NULL, "Pointer is NULL\n"); 33 34 #define RELEASE_EXPECT(iface, num) if (iface) { \ 35 hr = IUnknown_Release((IUnknown*)iface); \ 36 ok(hr == num, "IUnknown_Release should return %d, got %d\n", num, hr); \ 37 } 38 39 static IUnknown *pDSRender = NULL; 40 41 static BOOL create_dsound_renderer(void) 42 { 43 HRESULT hr; 44 45 hr = CoCreateInstance(&CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER, 46 &IID_IUnknown, (LPVOID*)&pDSRender); 47 return (hr == S_OK && pDSRender != NULL); 48 } 49 50 static void release_dsound_renderer(void) 51 { 52 HRESULT hr; 53 54 hr = IUnknown_Release(pDSRender); 55 ok(hr == 0, "IUnknown_Release failed with %x\n", hr); 56 } 57 58 static HRESULT WINAPI PB_QueryInterface(IPropertyBag *iface, REFIID riid, void **ppv) 59 { 60 ok(0, "Should not be called\n"); 61 *ppv = NULL; 62 return E_NOINTERFACE; 63 } 64 65 static ULONG WINAPI PB_AddRef(IPropertyBag *iface) 66 { 67 ok(0, "Should not be called\n"); 68 return 2; 69 } 70 71 static ULONG WINAPI PB_Release(IPropertyBag *iface) 72 { 73 ok(0, "Should not be called\n"); 74 return 1; 75 } 76 77 static HRESULT WINAPI PB_Read(IPropertyBag *iface, LPCOLESTR name, VARIANT *var, IErrorLog *log) 78 { 79 static const WCHAR dsguid[] = { 'D','S','G','u','i','d', 0 }; 80 char temp[50]; 81 WideCharToMultiByte(CP_ACP, 0, name, -1, temp, sizeof(temp)-1, NULL, NULL); 82 temp[sizeof(temp)-1] = 0; 83 trace("Trying to read %s, type %u\n", temp, var->n1.n2.vt); 84 if (!lstrcmpW(name, dsguid)) 85 { 86 static const WCHAR defaultplayback[] = 87 { 88 '{','D','E','F','0','0','0','0','0','-', 89 '9','C','6','D','-','4','7','E','D','-', 90 'A','A','F','1','-','4','D','D','A','8', 91 'F','2','B','5','C','0','3','}',0 92 }; 93 ok(var->n1.n2.vt == VT_BSTR, "Wrong type asked: %u\n", var->n1.n2.vt); 94 var->n1.n2.n3.bstrVal = SysAllocString(defaultplayback); 95 return S_OK; 96 } 97 ok(0, "Unknown property '%s' queried\n", temp); 98 return E_FAIL; 99 } 100 101 static HRESULT WINAPI PB_Write(IPropertyBag *iface, LPCOLESTR name, VARIANT *var) 102 { 103 ok(0, "Should not be called\n"); 104 return E_FAIL; 105 } 106 107 static IPropertyBagVtbl PB_Vtbl = 108 { 109 PB_QueryInterface, 110 PB_AddRef, 111 PB_Release, 112 PB_Read, 113 PB_Write 114 }; 115 116 static void test_query_interface(void) 117 { 118 HRESULT hr; 119 IBaseFilter *pBaseFilter = NULL; 120 IBasicAudio *pBasicAudio = NULL; 121 IMediaPosition *pMediaPosition = NULL; 122 IMediaSeeking *pMediaSeeking = NULL; 123 IQualityControl *pQualityControl = NULL; 124 IPersistPropertyBag *ppb = NULL; 125 IDirectSound3DBuffer *ds3dbuf = NULL; 126 IReferenceClock *clock = NULL; 127 IAMDirectSound *pAMDirectSound = NULL; 128 129 QI_SUCCEED(pDSRender, IID_IBaseFilter, pBaseFilter); 130 RELEASE_EXPECT(pBaseFilter, 1); 131 QI_SUCCEED(pDSRender, IID_IBasicAudio, pBasicAudio); 132 RELEASE_EXPECT(pBasicAudio, 1); 133 QI_SUCCEED(pDSRender, IID_IMediaSeeking, pMediaSeeking); 134 RELEASE_EXPECT(pMediaSeeking, 1); 135 QI_SUCCEED(pDSRender, IID_IReferenceClock, clock); 136 RELEASE_EXPECT(clock, 1); 137 QI_SUCCEED(pDSRender, IID_IAMDirectSound, pAMDirectSound); 138 RELEASE_EXPECT( pAMDirectSound, 1); 139 todo_wine { 140 QI_SUCCEED(pDSRender, IID_IDirectSound3DBuffer, ds3dbuf); 141 RELEASE_EXPECT(ds3dbuf, 1); 142 QI_SUCCEED(pDSRender, IID_IPersistPropertyBag, ppb); 143 if (ppb) 144 { 145 IPropertyBag bag = { &PB_Vtbl }; 146 hr = IPersistPropertyBag_Load(ppb, &bag, NULL); 147 ok(hr == S_OK, "Couldn't load default device: %08x\n", hr); 148 } 149 RELEASE_EXPECT(ppb, 1); 150 } 151 QI_SUCCEED(pDSRender, IID_IMediaPosition, pMediaPosition); 152 RELEASE_EXPECT(pMediaPosition, 1); 153 QI_SUCCEED(pDSRender, IID_IQualityControl, pQualityControl); 154 RELEASE_EXPECT(pQualityControl, 1); 155 } 156 157 static void test_pin(IPin *pin) 158 { 159 IMemInputPin *mpin = NULL; 160 161 IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&mpin); 162 163 ok(mpin != NULL, "No IMemInputPin found!\n"); 164 if (mpin) 165 { 166 ok(IMemInputPin_ReceiveCanBlock(mpin) == S_OK, "Receive can't block for pin!\n"); 167 ok(IMemInputPin_NotifyAllocator(mpin, NULL, 0) == E_POINTER, "NotifyAllocator likes a NULL pointer argument\n"); 168 IMemInputPin_Release(mpin); 169 } 170 /* TODO */ 171 } 172 173 static void test_basefilter(void) 174 { 175 IEnumPins *pin_enum = NULL; 176 IBaseFilter *base = NULL; 177 IPin *pins[2]; 178 ULONG ref; 179 HRESULT hr; 180 181 IUnknown_QueryInterface(pDSRender, &IID_IBaseFilter, (void **)&base); 182 if (base == NULL) 183 { 184 /* test_query_interface handles this case */ 185 skip("No IBaseFilter\n"); 186 return; 187 } 188 189 hr = IBaseFilter_EnumPins(base, NULL); 190 ok(hr == E_POINTER, "hr = %08x and not E_POINTER\n", hr); 191 192 hr= IBaseFilter_EnumPins(base, &pin_enum); 193 ok(hr == S_OK, "hr = %08x and not S_OK\n", hr); 194 195 hr = IEnumPins_Next(pin_enum, 1, NULL, NULL); 196 ok(hr == E_POINTER, "hr = %08x and not E_POINTER\n", hr); 197 198 hr = IEnumPins_Next(pin_enum, 2, pins, NULL); 199 ok(hr == E_INVALIDARG, "hr = %08x and not E_INVALIDARG\n", hr); 200 201 pins[0] = (void *)0xdead; 202 pins[1] = (void *)0xdeed; 203 204 hr = IEnumPins_Next(pin_enum, 2, pins, &ref); 205 ok(hr == S_FALSE, "hr = %08x instead of S_FALSE\n", hr); 206 ok(pins[0] != (void *)0xdead && pins[0] != NULL, "pins[0] = %p\n", pins[0]); 207 if (pins[0] != (void *)0xdead && pins[0] != NULL) 208 { 209 test_pin(pins[0]); 210 IPin_Release(pins[0]); 211 } 212 213 ok(pins[1] == (void *)0xdeed, "pins[1] = %p\n", pins[1]); 214 215 ref = IEnumPins_Release(pin_enum); 216 ok(ref == 0, "ref is %u and not 0!\n", ref); 217 218 IBaseFilter_Release(base); 219 } 220 221 START_TEST(dsoundrender) 222 { 223 CoInitialize(NULL); 224 if (!create_dsound_renderer()) 225 return; 226 227 test_query_interface(); 228 test_basefilter(); 229 230 release_dsound_renderer(); 231 232 CoUninitialize(); 233 } 234