d3d11: Remove null dxgi object checks.
[wine.git] / dlls / dmusic / tests / dmusic.c
blob37b517fe0ca0c579c2718e68ee35ca7bb8136bec
1 /*
2 * Unit tests for dmusic functions
4 * Copyright (C) 2012 Christian Costa
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.
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.
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
21 #define COBJMACROS
23 #include <stdio.h>
25 #include "wine/test.h"
26 #include "uuids.h"
27 #include "ole2.h"
28 #include "initguid.h"
29 #include "dmusici.h"
30 #include "dmusicf.h"
31 #include "dmksctrl.h"
33 static BOOL compare_time(REFERENCE_TIME x, REFERENCE_TIME y, unsigned int max_diff)
35 REFERENCE_TIME diff = x > y ? x - y : y - x;
36 return diff <= max_diff;
39 static void test_dmusic(void)
41 IDirectMusic *dmusic = NULL;
42 HRESULT hr;
43 ULONG index = 0;
44 DMUS_PORTCAPS port_caps;
45 DMUS_PORTPARAMS port_params;
46 IDirectMusicPort *port = NULL;
48 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (LPVOID*)&dmusic);
49 ok(hr == S_OK, "Cannot create DirectMusic object: %#lx\n", hr);
51 port_params.dwSize = sizeof(port_params);
52 port_params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
53 port_params.dwChannelGroups = 1;
54 port_params.dwAudioChannels = 2;
56 /* No port can be created before SetDirectSound is called */
57 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
58 ok(hr == DMUS_E_DSOUND_NOT_SET, "IDirectMusic_CreatePort returned: %#lx\n", hr);
60 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
61 ok(hr == S_OK, "IDirectMusic_SetDirectSound returned: %#lx\n", hr);
63 /* Check wrong params */
64 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, (IUnknown*)dmusic);
65 ok(hr == CLASS_E_NOAGGREGATION, "IDirectMusic_CreatePort returned: %#lx\n", hr);
66 hr = IDirectMusic_CreatePort(dmusic, NULL, &port_params, &port, NULL);
67 ok(hr == E_POINTER, "IDirectMusic_CreatePort returned: %#lx\n", hr);
68 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, NULL, &port, NULL);
69 ok(hr == E_INVALIDARG, "IDirectMusic_CreatePort returned: %#lx\n", hr);
70 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, NULL, NULL);
71 ok(hr == E_POINTER, "IDirectMusic_CreatePort returned: %#lx\n", hr);
73 /* Test creation of default port with GUID_NULL */
74 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
75 ok(hr == S_OK, "IDirectMusic_CreatePort returned: %#lx\n", hr);
77 port_caps.dwSize = sizeof(port_caps);
78 while (IDirectMusic_EnumPort(dmusic, index, &port_caps) == S_OK)
80 ok(port_caps.dwSize == sizeof(port_caps), "DMUS_PORTCAPS dwSize member is wrong (%lu)\n", port_caps.dwSize);
81 trace("Port %lu:\n", index);
82 trace(" dwFlags = %lx\n", port_caps.dwFlags);
83 trace(" guidPort = %s\n", wine_dbgstr_guid(&port_caps.guidPort));
84 trace(" dwClass = %lu\n", port_caps.dwClass);
85 trace(" dwType = %lu\n", port_caps.dwType);
86 trace(" dwMemorySize = %lu\n", port_caps.dwMemorySize);
87 trace(" dwMaxChannelGroups = %lu\n", port_caps.dwMaxChannelGroups);
88 trace(" dwMaxVoices = %lu\n", port_caps.dwMaxVoices);
89 trace(" dwMaxAudioChannels = %lu\n", port_caps.dwMaxAudioChannels);
90 trace(" dwEffectFlags = %lx\n", port_caps.dwEffectFlags);
91 trace(" wszDescription = %s\n", wine_dbgstr_w(port_caps.wszDescription));
92 index++;
95 if (port)
96 IDirectMusicPort_Release(port);
97 IDirectMusic_Release(dmusic);
100 static ULONG get_refcount(IDirectSound *iface)
102 IDirectSound_AddRef(iface);
103 return IDirectSound_Release(iface);
106 static void test_setdsound(void)
108 IDirectMusic *dmusic;
109 IDirectSound *dsound, *dsound2;
110 DMUS_PORTPARAMS params;
111 IDirectMusicPort *port = NULL;
112 HRESULT hr;
113 ULONG ref;
115 params.dwSize = sizeof(params);
116 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
117 params.dwChannelGroups = 1;
118 params.dwAudioChannels = 2;
120 /* Old dsound without SetCooperativeLevel() */
121 hr = DirectSoundCreate(NULL, &dsound, NULL);
122 if (hr == DSERR_NODRIVER ) {
123 skip("No driver\n");
124 return;
126 ok(hr == S_OK, "DirectSoundCreate failed: %#lx\n", hr);
127 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
128 (void **)&dmusic);
129 ok(hr == S_OK, "DirectMusic create failed: %#lx\n", hr);
130 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
131 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
132 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &params, &port, NULL);
133 ok(hr == S_OK, "CreatePort returned: %#lx\n", hr);
134 IDirectMusicPort_Release(port);
135 IDirectMusic_Release(dmusic);
136 IDirectSound_Release(dsound);
138 /* dsound ref counting */
139 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
140 (void **)&dmusic);
141 ok(hr == S_OK, "DirectMusic create failed: %#lx\n", hr);
142 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&dsound, NULL);
143 ok(hr == S_OK, "DirectSoundCreate failed: %#lx\n", hr);
144 hr = IDirectSound_SetCooperativeLevel(dsound, GetForegroundWindow(), DSSCL_PRIORITY);
145 ok(hr == S_OK, "SetCooperativeLevel failed: %#lx\n", hr);
146 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
147 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
148 ref = get_refcount(dsound);
149 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
150 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &params, &port, NULL);
151 ok(hr == S_OK, "CreatePort returned: %#lx\n", hr);
152 ref = get_refcount(dsound);
153 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
154 IDirectMusicPort_AddRef(port);
155 ref = IDirectMusicPort_Release(port);
156 ok(ref == 1, "port ref count got %ld expected 1\n", ref);
157 hr = IDirectMusicPort_Activate(port, TRUE);
158 ok(hr == S_OK, "Port Activate returned: %#lx\n", hr);
159 ref = get_refcount(dsound);
160 ok(ref == 4, "dsound ref count got %ld expected 4\n", ref);
161 IDirectMusicPort_AddRef(port);
162 ref = IDirectMusicPort_Release(port);
163 ok(ref == 1, "port ref count got %ld expected 1\n", ref);
165 /* Releasing dsound from dmusic */
166 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
167 ok(hr == DMUS_E_DSOUND_ALREADY_SET, "SetDirectSound failed: %#lx\n", hr);
168 hr = IDirectMusicPort_Activate(port, FALSE);
169 ok(hr == S_OK, "Port Activate returned: %#lx\n", hr);
170 ref = get_refcount(dsound);
171 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
172 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
173 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
174 ref = get_refcount(dsound);
175 ok(ref == 1, "dsound ref count got %ld expected 1\n", ref);
177 /* Setting the same dsound twice */
178 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
179 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
180 ref = get_refcount(dsound);
181 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
182 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
183 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
184 ref = get_refcount(dsound);
185 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
187 /* Replacing one dsound with another */
188 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&dsound2, NULL);
189 ok(hr == S_OK, "DirectSoundCreate failed: %#lx\n", hr);
190 hr = IDirectMusic_SetDirectSound(dmusic, dsound2, NULL);
191 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
192 ref = get_refcount(dsound);
193 ok(ref == 1, "dsound ref count got %ld expected 1\n", ref);
194 ref = get_refcount(dsound2);
195 ok(ref == 2, "dsound2 ref count got %ld expected 2\n", ref);
197 /* Replacing the dsound in the port */
198 hr = IDirectMusicPort_SetDirectSound(port, dsound, NULL);
199 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
200 ref = get_refcount(dsound);
201 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
202 ref = get_refcount(dsound2);
203 ok(ref == 2, "dsound2 ref count got %ld expected 2\n", ref);
204 /* Setting the dsound again on the port will mess with the parent dmusic */
205 hr = IDirectMusicPort_SetDirectSound(port, dsound, NULL);
206 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
207 ref = get_refcount(dsound);
208 ok(ref == 3, "dsound ref count got %ld expected 3\n", ref);
209 ref = get_refcount(dsound2);
210 ok(ref == 1, "dsound2 ref count got %ld expected 1\n", ref);
211 IDirectSound_AddRef(dsound2); /* Crash prevention */
212 hr = IDirectMusicPort_Activate(port, TRUE);
213 ok(hr == S_OK, "Activate returned: %#lx\n", hr);
214 ref = get_refcount(dsound);
215 ok(ref == 4, "dsound ref count got %ld expected 4\n", ref);
216 ref = get_refcount(dsound2);
217 ok(ref == 2, "dsound2 ref count got %ld expected 2\n", ref);
218 hr = IDirectMusicPort_Activate(port, TRUE);
219 ok(hr == S_FALSE, "Activate returned: %#lx\n", hr);
220 ref = get_refcount(dsound);
221 ok(ref == 4, "dsound ref count got %ld expected 4\n", ref);
222 ref = get_refcount(dsound2);
223 ok(ref == 2, "dsound2 ref count got %ld expected 2\n", ref);
225 /* Deactivating the port messes with the dsound refcount in the parent dmusic */
226 hr = IDirectMusicPort_Activate(port, FALSE);
227 ok(hr == S_OK, "Port Activate returned: %#lx\n", hr);
228 ref = get_refcount(dsound);
229 ok(ref == 3, "dsound ref count got %ld expected 3\n", ref);
230 ref = get_refcount(dsound2);
231 ok(ref == 1, "dsound2 ref count got %ld expected 1\n", ref);
232 hr = IDirectMusicPort_Activate(port, FALSE);
233 ok(hr == S_FALSE, "Port Activate returned: %#lx\n", hr);
234 ref = get_refcount(dsound);
235 ok(ref == 3, "dsound ref count got %ld expected 3\n", ref);
236 ref = get_refcount(dsound2);
237 ok(ref == 1, "dsound2 ref count got %ld expected 1\n", ref);
239 IDirectMusicPort_Release(port);
240 IDirectMusic_Release(dmusic);
241 while (IDirectSound_Release(dsound));
244 static void test_dmbuffer(void)
246 IDirectMusic *dmusic;
247 IDirectMusicBuffer *dmbuffer = NULL;
248 HRESULT hr;
249 DMUS_BUFFERDESC desc;
250 GUID format;
251 DWORD size;
252 DWORD bytes;
253 REFERENCE_TIME time;
254 LPBYTE data;
256 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (LPVOID*)&dmusic);
257 ok(hr == S_OK, "Cannot create DirectMusic object: %#lx\n", hr);
259 desc.dwSize = sizeof(DMUS_BUFFERDESC);
260 desc.dwFlags = 0;
261 desc.cbBuffer = 1023;
262 memcpy(&desc.guidBufferFormat, &GUID_NULL, sizeof(GUID));
264 hr = IDirectMusic_CreateMusicBuffer(dmusic, &desc, &dmbuffer, NULL);
265 ok(hr == S_OK, "IDirectMusic_CreateMusicBuffer returned %#lx\n", hr);
267 hr = IDirectMusicBuffer_GetBufferFormat(dmbuffer, &format);
268 ok(hr == S_OK, "IDirectMusicBuffer_GetBufferFormat returned %#lx\n", hr);
269 ok(IsEqualGUID(&format, &KSDATAFORMAT_SUBTYPE_MIDI), "Wrong format returned %s\n", wine_dbgstr_guid(&format));
270 hr = IDirectMusicBuffer_GetMaxBytes(dmbuffer, &size);
271 ok(hr == S_OK, "IDirectMusicBuffer_GetMaxBytes returned %#lx\n", hr);
272 ok(size == 1024, "Buffer size is %lu instead of 1024\n", size);
274 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
275 ok(hr == DMUS_E_BUFFER_EMPTY, "IDirectMusicBuffer_GetStartTime returned %#lx\n", hr);
276 hr = IDirectMusicBuffer_SetStartTime(dmbuffer, 10);
277 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %#lx\n", hr);
278 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
279 ok(hr == DMUS_E_BUFFER_EMPTY, "IDirectMusicBuffer_GetStartTime returned %#lx\n", hr);
281 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 20, 0, 0);
282 ok(hr == DMUS_E_INVALID_EVENT, "IDirectMusicBuffer_PackStructured returned %#lx\n", hr);
283 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 20, 0, 0x000090); /* note on : chan 0, note 0 & vel 0 */
284 ok(hr == S_OK, "IDirectMusicBuffer_PackStructured returned %#lx\n", hr);
285 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 30, 0, 0x000080); /* note off : chan 0, note 0 & vel 0 */
286 ok(hr == S_OK, "IDirectMusicBuffer_PackStructured returned %#lx\n", hr);
287 hr = IDirectMusicBuffer_GetUsedBytes(dmbuffer, &bytes);
288 ok(hr == S_OK, "IDirectMusicBuffer_GetUsedBytes returned %#lx\n", hr);
289 ok(bytes == 48, "Buffer size is %lu instead of 48\n", bytes);
291 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
292 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %#lx\n", hr);
293 ok(time == 20, "Buffer start time is wrong\n");
294 hr = IDirectMusicBuffer_SetStartTime(dmbuffer, 40);
295 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %#lx\n", hr);
296 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
297 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %#lx\n", hr);
298 ok(time == 40, "Buffer start time is wrong\n");
300 hr = IDirectMusicBuffer_GetRawBufferPtr(dmbuffer, &data);
301 ok(hr == S_OK, "IDirectMusicBuffer_GetRawBufferPtr returned %#lx\n", hr);
302 if (hr == S_OK)
304 DMUS_EVENTHEADER* header;
305 DWORD message;
307 /* Check message 1 */
308 header = (DMUS_EVENTHEADER*)data;
309 data += sizeof(DMUS_EVENTHEADER);
310 ok(header->cbEvent == 3, "cbEvent is %lu instead of 3\n", header->cbEvent);
311 ok(header->dwChannelGroup == 0, "dwChannelGroup is %lu instead of 0\n", header->dwChannelGroup);
312 ok(header->rtDelta == 0, "rtDelta is %s instead of 0\n", wine_dbgstr_longlong(header->rtDelta));
313 ok(header->dwFlags == DMUS_EVENT_STRUCTURED, "dwFlags is %lx instead of %x\n", header->dwFlags, DMUS_EVENT_STRUCTURED);
314 message = *(DWORD*)data & 0xffffff; /* Only 3 bytes are relevant */
315 data += sizeof(DWORD);
316 ok(message == 0x000090, "Message is %0lx instead of 0x000090\n", message);
318 /* Check message 2 */
319 header = (DMUS_EVENTHEADER*)data;
320 data += sizeof(DMUS_EVENTHEADER);
321 ok(header->cbEvent == 3, "cbEvent is %lu instead of 3\n", header->cbEvent);
322 ok(header->dwChannelGroup == 0, "dwChannelGroup is %lu instead of 0\n", header->dwChannelGroup);
323 ok(header->rtDelta == 10, "rtDelta is %s instead of 0\n", wine_dbgstr_longlong(header->rtDelta));
324 ok(header->dwFlags == DMUS_EVENT_STRUCTURED, "dwFlags is %lx instead of %x\n", header->dwFlags, DMUS_EVENT_STRUCTURED);
325 message = *(DWORD*)data & 0xffffff; /* Only 3 bytes are relevant */
326 ok(message == 0x000080, "Message 2 is %0lx instead of 0x000080\n", message);
329 if (dmbuffer)
330 IDirectMusicBuffer_Release(dmbuffer);
331 IDirectMusic_Release(dmusic);
334 static void test_COM(void)
336 IDirectMusic8 *dm8 = (IDirectMusic8*)0xdeadbeef;
337 IDirectMusic *dm;
338 IUnknown *unk;
339 ULONG refcount;
340 HRESULT hr;
342 /* COM aggregation */
343 hr = CoCreateInstance(&CLSID_DirectMusic, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
344 (void**)&dm8);
345 ok(hr == CLASS_E_NOAGGREGATION,
346 "DirectMusic8 create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
347 ok(!dm8, "dm8 = %p\n", dm8);
349 /* Invalid RIID */
350 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
351 (void**)&dm8);
352 ok(hr == E_NOINTERFACE, "DirectMusic8 create failed: %#lx, expected E_NOINTERFACE\n", hr);
354 /* Same refcount for DirectMusic and DirectMusic8 */
355 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
356 (void**)&dm8);
357 if (hr == E_NOINTERFACE)
359 win_skip("DirectMusic too old (no IDirectMusic8)\n");
360 return;
362 ok(hr == S_OK, "DirectMusic8 create failed: %#lx, expected S_OK\n", hr);
363 refcount = IDirectMusic8_AddRef(dm8);
364 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
366 hr = IDirectMusic8_QueryInterface(dm8, &IID_IDirectMusic, (void**)&dm);
367 ok(hr == S_OK, "QueryInterface for IID_IDirectMusic failed: %#lx\n", hr);
368 refcount = IDirectMusic_AddRef(dm);
369 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
370 IDirectMusic_Release(dm);
372 hr = IDirectMusic8_QueryInterface(dm8, &IID_IUnknown, (void**)&unk);
373 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
374 refcount = IUnknown_AddRef(unk);
375 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
376 refcount = IUnknown_Release(unk);
378 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
379 while (IDirectMusic8_Release(dm8));
382 static void test_COM_dmcoll(void)
384 IDirectMusicCollection *dmc = (IDirectMusicCollection*)0xdeadbeef;
385 IDirectMusicObject *dmo;
386 IPersistStream *ps;
387 IUnknown *unk;
388 ULONG refcount;
389 HRESULT hr;
391 /* COM aggregation */
392 hr = CoCreateInstance(&CLSID_DirectMusicCollection, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
393 &IID_IUnknown, (void**)&dmc);
394 ok(hr == CLASS_E_NOAGGREGATION,
395 "DirectMusicCollection create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
396 ok(!dmc, "dmc = %p\n", dmc);
398 /* Invalid RIID */
399 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
400 &IID_IClassFactory, (void**)&dmc);
401 ok(hr == E_NOINTERFACE, "DirectMusicCollection create failed: %#lx, expected E_NOINTERFACE\n", hr);
403 /* Same refcount for all DirectMusicCollection interfaces */
404 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
405 &IID_IDirectMusicCollection, (void**)&dmc);
406 ok(hr == S_OK, "DirectMusicCollection create failed: %#lx, expected S_OK\n", hr);
407 refcount = IDirectMusicCollection_AddRef(dmc);
408 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
410 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IDirectMusicObject, (void**)&dmo);
411 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
412 refcount = IDirectMusicObject_AddRef(dmo);
413 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
414 refcount = IDirectMusicObject_Release(dmo);
416 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IPersistStream, (void**)&ps);
417 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
418 refcount = IPersistStream_AddRef(ps);
419 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
420 refcount = IPersistStream_Release(ps);
422 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IUnknown, (void**)&unk);
423 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
424 refcount = IUnknown_AddRef(unk);
425 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
426 refcount = IUnknown_Release(unk);
428 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
429 while (IDirectMusicCollection_Release(dmc));
432 static void test_dmcoll(void)
434 IDirectMusicCollection *dmc;
435 IDirectMusicObject *dmo;
436 IPersistStream *ps;
437 DMUS_OBJECTDESC desc;
438 CLSID class;
439 ULARGE_INTEGER size;
440 HRESULT hr;
442 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
443 &IID_IDirectMusicCollection, (void**)&dmc);
444 ok(hr == S_OK, "DirectMusicCollection create failed: %#lx, expected S_OK\n", hr);
446 /* IDirectMusicObject */
447 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IDirectMusicObject, (void**)&dmo);
448 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
449 hr = IDirectMusicObject_GetDescriptor(dmo, NULL);
450 ok(hr == E_POINTER, "IDirectMusicObject_GetDescriptor: expected E_POINTER, got %#lx\n", hr);
451 hr = IDirectMusicObject_SetDescriptor(dmo, NULL);
452 ok(hr == E_POINTER, "IDirectMusicObject_SetDescriptor: expected E_POINTER, got %#lx\n", hr);
453 ZeroMemory(&desc, sizeof(desc));
454 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
455 ok(hr == S_OK, "IDirectMusicObject_GetDescriptor failed: %#lx\n", hr);
456 ok(desc.dwValidData == DMUS_OBJ_CLASS,
457 "Fresh object has more valid data (%#lx) than DMUS_OBJ_CLASS\n", desc.dwValidData);
458 /* DMUS_OBJ_CLASS is immutable */
459 desc.dwValidData = DMUS_OBJ_CLASS;
460 hr = IDirectMusicObject_SetDescriptor(dmo, &desc);
461 ok(hr == S_FALSE , "IDirectMusicObject_SetDescriptor failed: %#lx\n", hr);
462 ok(!desc.dwValidData, "dwValidData wasn't cleared: %#lx\n", desc.dwValidData);
463 desc.dwValidData = DMUS_OBJ_CLASS;
464 desc.guidClass = CLSID_DirectMusicSegment;
465 hr = IDirectMusicObject_SetDescriptor(dmo, &desc);
466 ok(hr == S_FALSE && !desc.dwValidData, "IDirectMusicObject_SetDescriptor failed: %#lx\n", hr);
467 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
468 ok(hr == S_OK, "IDirectMusicObject_GetDescriptor failed: %#lx\n", hr);
469 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
470 "guidClass changed, should be CLSID_DirectMusicCollection\n");
472 /* Unimplemented IPersistStream methods*/
473 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IPersistStream, (void**)&ps);
474 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
475 hr = IPersistStream_GetClassID(ps, &class);
476 ok(hr == E_NOTIMPL, "IPersistStream_GetClassID failed: %#lx\n", hr);
477 hr = IPersistStream_IsDirty(ps);
478 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
479 hr = IPersistStream_GetSizeMax(ps, &size);
480 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
481 hr = IPersistStream_Save(ps, NULL, TRUE);
482 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
484 while (IDirectMusicCollection_Release(dmc));
487 static BOOL missing_dmusic(void)
489 IDirectMusic8 *dm;
490 HRESULT hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic,
491 (void**)&dm);
493 if (hr == S_OK && dm)
495 IDirectMusic_Release(dm);
496 return FALSE;
498 return TRUE;
501 static IDirectMusicPort *create_synth_port(IDirectMusic **dmusic)
503 IDirectMusicPort *port = NULL;
504 DMUS_PORTPARAMS params;
505 HRESULT hr;
507 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (void **)dmusic);
508 ok(hr == S_OK, "Cannot create DirectMusic object: %#lx\n", hr);
510 params.dwSize = sizeof(params);
511 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
512 params.dwChannelGroups = 1;
513 params.dwAudioChannels = 2;
514 hr = IDirectMusic_SetDirectSound(*dmusic, NULL, NULL);
515 ok(hr == S_OK, "IDirectMusic_SetDirectSound failed: %#lx\n", hr);
516 hr = IDirectMusic_CreatePort(*dmusic, &GUID_NULL, &params, &port, NULL);
517 ok(hr == S_OK, "IDirectMusic_CreatePort failed: %#lx\n", hr);
519 return port;
522 static void test_COM_synthport(void)
524 IDirectMusic *dmusic;
525 IDirectMusicPort *port;
526 IDirectMusicPortDownload *dmpd;
527 IDirectMusicThru *dmt;
528 IKsControl *iksc;
529 IReferenceClock *clock;
530 IUnknown *unk;
531 ULONG refcount;
532 HRESULT hr;
534 port = create_synth_port(&dmusic);
536 /* Same refcount for all DirectMusicPort interfaces */
537 refcount = IDirectMusicPort_AddRef(port);
538 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
540 hr = IDirectMusicPort_QueryInterface(port, &IID_IDirectMusicPortDownload, (void**)&dmpd);
541 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicPortDownload failed: %#lx\n", hr);
542 refcount = IDirectMusicPortDownload_AddRef(dmpd);
543 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
544 IDirectMusicPortDownload_Release(dmpd);
546 hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void**)&iksc);
547 ok(hr == S_OK, "QueryInterface for IID_IKsControl failed: %#lx\n", hr);
548 refcount = IKsControl_AddRef(iksc);
549 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
550 IKsControl_Release(iksc);
552 hr = IDirectMusicPort_QueryInterface(port, &IID_IUnknown, (void**)&unk);
553 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
554 refcount = IUnknown_AddRef(unk);
555 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
556 IUnknown_Release(unk);
558 /* Unsupported interface */
559 hr = IDirectMusicPort_QueryInterface(port, &IID_IDirectMusicThru, (void**)&dmt);
560 todo_wine ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicThru failed: %#lx\n", hr);
561 hr = IDirectMusicPort_QueryInterface(port, &IID_IReferenceClock, (void**)&clock);
562 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IReferenceClock failed: %#lx\n", hr);
564 while (IDirectMusicPort_Release(port));
565 refcount = IDirectMusic_Release(dmusic);
566 ok(!refcount, "Got outstanding refcount %ld.\n", refcount);
569 struct chunk {
570 FOURCC id;
571 DWORD size;
572 FOURCC type;
575 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
577 /* Generate a RIFF file format stream from an array of FOURCC ids.
578 RIFF and LIST need to be followed by the form type respectively list type,
579 followed by the chunks of the list and terminated with 0. */
580 static IStream *gen_riff_stream(const FOURCC *ids)
582 static const LARGE_INTEGER zero;
583 int level = -1;
584 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
585 char riff[1024];
586 char *p = riff;
587 struct chunk *ck;
588 IStream *stream;
590 do {
591 ck = (struct chunk *)p;
592 ck->id = *ids++;
593 switch (ck->id) {
594 case 0:
595 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
596 level--;
597 break;
598 case FOURCC_LIST:
599 case FOURCC_RIFF:
600 level++;
601 sizes[level] = &ck->size;
602 ck->type = *ids++;
603 p += sizeof(*ck);
604 break;
605 case DMUS_FOURCC_GUID_CHUNK:
606 ck->size = sizeof(GUID_NULL);
607 p += CHUNK_HDR_SIZE;
608 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
609 p += ck->size;
610 break;
611 case DMUS_FOURCC_VERSION_CHUNK:
613 DMUS_VERSION ver = {5, 8};
615 ck->size = sizeof(ver);
616 p += CHUNK_HDR_SIZE;
617 memcpy(p, &ver, sizeof(ver));
618 p += ck->size;
619 break;
621 case mmioFOURCC('I','N','A','M'):
622 ck->size = 5;
623 p += CHUNK_HDR_SIZE;
624 strcpy(p, "INAM");
625 p += ck->size + 1; /* WORD aligned */
626 break;
627 default:
629 /* Just convert the FOURCC id to a WCHAR string */
630 WCHAR *s;
632 ck->size = 5 * sizeof(WCHAR);
633 p += CHUNK_HDR_SIZE;
634 s = (WCHAR *)p;
635 s[0] = (char)(ck->id);
636 s[1] = (char)(ck->id >> 8);
637 s[2] = (char)(ck->id >> 16);
638 s[3] = (char)(ck->id >> 24);
639 s[4] = 0;
640 p += ck->size;
643 } while (level >= 0);
645 ck = (struct chunk *)riff;
646 CreateStreamOnHGlobal(NULL, TRUE, &stream);
647 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
648 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
650 return stream;
653 static void test_parsedescriptor(void)
655 IDirectMusicObject *dmo;
656 IStream *stream;
657 DMUS_OBJECTDESC desc = {0};
658 HRESULT hr;
659 const FOURCC alldesc[] =
661 FOURCC_RIFF, FOURCC_DLS, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST,
662 DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK,
663 DMUS_FOURCC_UCMT_CHUNK, DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK,
664 DMUS_FOURCC_GUID_CHUNK, 0
666 const FOURCC dupes[] =
668 FOURCC_RIFF, FOURCC_DLS, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
669 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
670 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_INFO_LIST, mmioFOURCC('I','N','A','M'), 0,
671 FOURCC_LIST, DMUS_FOURCC_INFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
673 FOURCC empty[] = {FOURCC_RIFF, FOURCC_DLS, 0};
674 FOURCC inam[] =
676 FOURCC_RIFF, FOURCC_DLS, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
677 mmioFOURCC('I','N','A','M'), 0, 0
680 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
681 &IID_IDirectMusicObject, (void **)&dmo);
682 ok(hr == S_OK, "DirectMusicCollection create failed: %#lx, expected S_OK\n", hr);
684 /* Nothing loaded */
685 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
686 ok(hr == S_OK, "GetDescriptor failed: %#lx, expected S_OK\n", hr);
687 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_OBJECT\n",
688 desc.dwValidData);
689 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
690 "Got class guid %s, expected CLSID_DirectMusicCollection\n",
691 wine_dbgstr_guid(&desc.guidClass));
693 /* Empty RIFF stream */
694 stream = gen_riff_stream(empty);
695 memset(&desc, 0, sizeof(desc));
696 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
697 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
698 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
699 desc.dwValidData);
700 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
701 "Got class guid %s, expected CLSID_DirectMusicCollection\n",
702 wine_dbgstr_guid(&desc.guidClass));
703 IStream_Release(stream);
705 /* NULL pointers */
706 memset(&desc, 0, sizeof(desc));
707 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
708 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
709 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
710 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
712 /* Wrong form */
713 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
714 stream = gen_riff_stream(empty);
715 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
716 ok(hr == DMUS_E_NOTADLSCOL, "ParseDescriptor failed: %#lx, expected DMUS_E_NOTADLSCOL\n", hr);
717 IStream_Release(stream);
719 /* All desc chunks */
720 stream = gen_riff_stream(alldesc);
721 memset(&desc, 0, sizeof(desc));
722 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
723 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
724 ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_VERSION),
725 "Got valid data %#lx, expected DMUS_OBJ_CLASS | DMUS_OBJ_VERSION\n", desc.dwValidData);
726 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
727 "Got class guid %s, expected CLSID_DirectMusicCollection\n",
728 wine_dbgstr_guid(&desc.guidClass));
729 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
730 wine_dbgstr_guid(&desc.guidClass));
731 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
732 "Got version %lu.%lu, expected 5.8\n", desc.vVersion.dwVersionMS,
733 desc.vVersion.dwVersionLS);
734 IStream_Release(stream);
736 /* UNFO list with INAM */
737 inam[3] = DMUS_FOURCC_UNFO_LIST;
738 stream = gen_riff_stream(inam);
739 memset(&desc, 0, sizeof(desc));
740 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
741 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
742 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
743 desc.dwValidData);
744 IStream_Release(stream);
746 /* INFO list with INAM */
747 inam[3] = DMUS_FOURCC_INFO_LIST;
748 stream = gen_riff_stream(inam);
749 memset(&desc, 0, sizeof(desc));
750 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
751 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
752 ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_NAME),
753 "Got valid data %#lx, expected DMUS_OBJ_CLASS | DMUS_OBJ_NAME\n", desc.dwValidData);
754 ok(!lstrcmpW(desc.wszName, L"INAM"), "Got name '%s', expected 'INAM'\n",
755 wine_dbgstr_w(desc.wszName));
756 IStream_Release(stream);
758 /* Duplicated chunks */
759 stream = gen_riff_stream(dupes);
760 memset(&desc, 0, sizeof(desc));
761 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
762 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
763 ok(desc.dwValidData == (DMUS_OBJ_CLASS | DMUS_OBJ_NAME | DMUS_OBJ_VERSION),
764 "Got valid data %#lx, expected DMUS_OBJ_CLASS | DMUS_OBJ_NAME | DMUS_OBJ_VERSION\n",
765 desc.dwValidData);
766 ok(!lstrcmpW(desc.wszName, L"INAM"), "Got name '%s', expected 'INAM'\n",
767 wine_dbgstr_w(desc.wszName));
768 IStream_Release(stream);
770 IDirectMusicObject_Release(dmo);
773 static void test_master_clock(void)
775 static const GUID guid_system_clock = {0x58d58419, 0x71b4, 0x11d1, {0xa7, 0x4c, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12}};
776 static const GUID guid_dsound_clock = {0x58d58420, 0x71b4, 0x11d1, {0xa7, 0x4c, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12}};
777 IReferenceClock *clock, *clock2;
778 REFERENCE_TIME time1, time2;
779 LARGE_INTEGER counter, freq;
780 DMUS_CLOCKINFO clock_info;
781 IDirectMusic *dmusic;
782 DWORD cookie;
783 HRESULT hr;
784 ULONG ref;
785 GUID guid;
787 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (void **)&dmusic);
788 ok(hr == S_OK, "Got hr %#lx.\n", hr);
790 hr = IDirectMusic_GetMasterClock(dmusic, NULL, NULL);
791 ok(hr == S_OK, "Got hr %#lx.\n", hr);
793 memset(&guid, 0xcc, sizeof(guid));
794 hr = IDirectMusic_GetMasterClock(dmusic, &guid, NULL);
795 ok(hr == S_OK, "Got hr %#lx.\n", hr);
796 todo_wine ok(IsEqualGUID(&guid, &guid_system_clock), "Got guid %s.\n", wine_dbgstr_guid(&guid));
798 clock = (IReferenceClock *)0xdeadbeef;
799 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock);
800 ok(hr == S_OK, "Got hr %#lx.\n", hr);
801 ok(clock && clock != (IReferenceClock *)0xdeadbeef, "Got clock %p.\n", clock);
803 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock2);
804 ok(hr == S_OK, "Got hr %#lx.\n", hr);
805 ok(clock2 == clock, "Clocks didn't match.\n");
806 IReferenceClock_Release(clock2);
808 memset(&guid, 0xcc, sizeof(guid));
809 hr = IDirectMusic_GetMasterClock(dmusic, &guid, &clock2);
810 ok(hr == S_OK, "Got hr %#lx.\n", hr);
811 todo_wine ok(IsEqualGUID(&guid, &guid_system_clock), "Got guid %s.\n", wine_dbgstr_guid(&guid));
812 ok(clock2 == clock, "Clocks didn't match.\n");
813 IReferenceClock_Release(clock2);
815 QueryPerformanceFrequency(&freq);
816 QueryPerformanceCounter(&counter);
817 hr = IReferenceClock_GetTime(clock, &time1);
818 ok(hr == S_OK, "Got hr %#lx.\n", hr);
819 time2 = counter.QuadPart * 10000000.0 / freq.QuadPart;
820 ok(compare_time(time1, time2, 20 * 10000), "Expected about %s, got %s.\n",
821 wine_dbgstr_longlong(time2), wine_dbgstr_longlong(time1));
823 hr = IReferenceClock_GetTime(clock, &time2);
824 ok(hr == (time2 == time1 ? S_FALSE : S_OK), "Got hr %#lx.\n", hr);
826 Sleep(100);
827 hr = IReferenceClock_GetTime(clock, &time2);
828 ok(hr == S_OK, "Got hr %#lx.\n", hr);
829 ok(time2 - time1 > 80 * 10000, "Expected about %s, but got %s.\n",
830 wine_dbgstr_longlong(time1 + 100 * 10000), wine_dbgstr_longlong(time2));
832 hr = IReferenceClock_AdviseTime(clock, 0, 0, NULL, &cookie);
833 ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
835 hr = IReferenceClock_AdvisePeriodic(clock, 0, 0, NULL, &cookie);
836 ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
838 hr = IReferenceClock_Unadvise(clock, 0);
839 ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
841 IReferenceClock_Release(clock);
843 hr = IDirectMusic_EnumMasterClock(dmusic, 0, NULL);
844 todo_wine ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
846 memset(&clock_info, 0xcc, sizeof(DMUS_CLOCKINFO));
847 clock_info.dwSize = sizeof(DMUS_CLOCKINFO7);
848 hr = IDirectMusic_EnumMasterClock(dmusic, 0, &clock_info);
849 ok(hr == S_OK, "Got hr %#lx.\n", hr);
850 ok(clock_info.ctType == DMUS_CLOCK_SYSTEM, "Got type %#x.\n", clock_info.ctType);
851 ok(IsEqualGUID(&clock_info.guidClock, &guid_system_clock), "Got guid %s.\n",
852 wine_dbgstr_guid(&clock_info.guidClock));
853 ok(clock_info.dwFlags == 0xcccccccc, "Got flags %#lx.\n", clock_info.dwFlags);
855 memset(&clock_info, 0xcc, sizeof(DMUS_CLOCKINFO));
856 clock_info.dwSize = sizeof(DMUS_CLOCKINFO7);
857 hr = IDirectMusic_EnumMasterClock(dmusic, 1, &clock_info);
858 ok(hr == S_OK, "Got hr %#lx.\n", hr);
859 ok(clock_info.ctType == DMUS_CLOCK_SYSTEM, "Got type %#x.\n", clock_info.ctType);
860 ok(IsEqualGUID(&clock_info.guidClock, &guid_dsound_clock), "Got guid %s.\n",
861 wine_dbgstr_guid(&clock_info.guidClock));
862 ok(clock_info.dwFlags == 0xcccccccc, "Got flags %#lx.\n", clock_info.dwFlags);
864 memset(&clock_info, 0xcc, sizeof(DMUS_CLOCKINFO));
865 clock_info.dwSize = sizeof(DMUS_CLOCKINFO7);
866 hr = IDirectMusic_EnumMasterClock(dmusic, 2, &clock_info);
867 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
869 ref = IDirectMusic_Release(dmusic);
870 ok(!ref, "Got outstanding refcount %ld.\n", ref);
873 static void test_synthport(void)
875 IDirectMusic *dmusic;
876 IDirectMusicBuffer *buf;
877 IDirectMusicPort *port;
878 DMUS_BUFFERDESC desc;
879 DMUS_PORTCAPS caps;
880 WAVEFORMATEX fmt;
881 DWORD fmtsize, bufsize;
883 HRESULT hr;
885 port = create_synth_port(&dmusic);
887 /* Create a IDirectMusicPortBuffer */
888 desc.dwSize = sizeof(DMUS_BUFFERDESC);
889 desc.dwFlags = 0;
890 desc.cbBuffer = 1023;
891 memcpy(&desc.guidBufferFormat, &GUID_NULL, sizeof(GUID));
892 hr = IDirectMusic_CreateMusicBuffer(dmusic, &desc, &buf, NULL);
893 ok(hr == S_OK, "IDirectMusic_CreateMusicBuffer failed: %#lx\n", hr);
895 /* Unsupported methods */
896 hr = IDirectMusicPort_Read(port, NULL);
897 todo_wine ok(hr == E_POINTER, "Read returned: %#lx\n", hr);
898 hr = IDirectMusicPort_Read(port, buf);
899 ok(hr == E_NOTIMPL, "Read returned: %#lx\n", hr);
900 hr = IDirectMusicPort_SetReadNotificationHandle(port, NULL);
901 ok(hr == E_NOTIMPL, "SetReadNotificationHandle returned: %#lx\n", hr);
902 hr = IDirectMusicPort_Compact(port);
903 ok(hr == E_NOTIMPL, "Compact returned: %#lx\n", hr);
905 /* GetCaps */
906 hr = IDirectMusicPort_GetCaps(port, NULL);
907 ok(hr == E_INVALIDARG, "GetCaps failed: %#lx\n", hr);
908 memset(&caps, 0, sizeof(caps));
909 hr = IDirectMusicPort_GetCaps(port, &caps);
910 ok(hr == E_INVALIDARG, "GetCaps failed: %#lx\n", hr);
911 caps.dwSize = sizeof(caps);
912 hr = IDirectMusicPort_GetCaps(port, &caps);
913 ok(hr == S_OK, "GetCaps failed: %#lx\n", hr);
914 ok(caps.dwSize == sizeof(caps), "dwSize was modified to %ld\n", caps.dwSize);
915 ok(IsEqualGUID(&caps.guidPort, &CLSID_DirectMusicSynth), "Expected port guid CLSID_DirectMusicSynth, got %s\n",
916 wine_dbgstr_guid(&caps.guidPort));
917 ok(caps.dwClass == DMUS_PC_OUTPUTCLASS, "Got wrong dwClass: %#lx\n", caps.dwClass);
918 ok(caps.dwType == DMUS_PORT_USER_MODE_SYNTH, "Got wrong dwType: %#lx\n", caps.dwType);
919 ok(caps.dwFlags == (DMUS_PC_AUDIOPATH|DMUS_PC_DIRECTSOUND|DMUS_PC_DLS|DMUS_PC_DLS2|DMUS_PC_SOFTWARESYNTH|
920 DMUS_PC_WAVE), "Unexpected dwFlags returned: %#lx\n", caps.dwFlags);
921 ok(caps.dwMemorySize == DMUS_PC_SYSTEMMEMORY, "Got dwMemorySize: %#lx\n", caps.dwMemorySize);
922 ok(caps.dwMaxChannelGroups == 1000, "Got dwMaxChannelGroups: %ld\n", caps.dwMaxChannelGroups);
923 ok(caps.dwMaxVoices == 1000, "Got dwMaxVoices: %ld\n", caps.dwMaxVoices);
924 ok(caps.dwMaxAudioChannels == 2, "Got dwMaxAudioChannels: %#lx\n", caps.dwMaxAudioChannels);
925 ok(caps.dwEffectFlags == DMUS_EFFECT_REVERB, "Unexpected dwEffectFlags returned: %#lx\n", caps.dwEffectFlags);
926 trace("Port wszDescription: %s\n", wine_dbgstr_w(caps.wszDescription));
928 /* GetFormat */
929 hr = IDirectMusicPort_GetFormat(port, NULL, NULL, NULL);
930 ok(hr == E_POINTER, "GetFormat failed: %#lx\n", hr);
931 hr = IDirectMusicPort_GetFormat(port, NULL, &fmtsize, NULL);
932 ok(hr == S_OK, "GetFormat failed: %#lx\n", hr);
933 ok(fmtsize == sizeof(fmt), "format size; %ld\n", fmtsize);
934 fmtsize = 0;
935 hr = IDirectMusicPort_GetFormat(port, &fmt, &fmtsize, NULL);
936 ok(hr == S_OK, "GetFormat failed: %#lx\n", hr);
937 ok(fmtsize == sizeof(fmt), "format size; %ld\n", fmtsize);
938 hr = IDirectMusicPort_GetFormat(port, NULL, NULL, &bufsize);
939 ok(hr == E_POINTER, "GetFormat failed: %#lx\n", hr);
940 hr = IDirectMusicPort_GetFormat(port, NULL, &fmtsize, &bufsize);
941 ok(hr == S_OK, "GetFormat failed: %#lx\n", hr);
942 hr = IDirectMusicPort_GetFormat(port, &fmt, &fmtsize, &bufsize);
943 ok(hr == S_OK, "GetFormat failed: %#lx\n", hr);
944 ok(bufsize == fmt.nSamplesPerSec * fmt.nChannels * 4, "buffer size: %ld\n", bufsize);
946 IDirectMusicPort_Release(port);
947 IDirectMusic_Release(dmusic);
950 START_TEST(dmusic)
952 CoInitializeEx(NULL, COINIT_MULTITHREADED);
954 if (missing_dmusic())
956 skip("DirectMusic not available\n");
957 CoUninitialize();
958 return;
960 test_COM();
961 test_COM_dmcoll();
962 test_COM_synthport();
963 test_dmusic();
964 test_setdsound();
965 test_dmbuffer();
966 test_dmcoll();
967 test_parsedescriptor();
968 test_master_clock();
969 test_synthport();
971 CoUninitialize();