dmusic: Fail in CreatePort() if SetDirectSound() wasn't called.
[wine.git] / dlls / dmusic / tests / dmusic.c
blob7da8aab3663fc32e96fc64753256d2568cf74a9a
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 "dmksctrl.h"
32 static inline const char* debugstr_longlong(ULONGLONG ll)
34 static char string[17];
35 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
36 sprintf(string, "%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
37 else
38 sprintf(string, "%lx", (unsigned long)ll);
39 return string;
42 static void test_dmusic(void)
44 IDirectMusic *dmusic = NULL;
45 HRESULT hr;
46 ULONG index = 0;
47 DMUS_PORTCAPS port_caps;
48 DMUS_PORTPARAMS port_params;
49 IDirectMusicPort *port = NULL;
50 DMUS_CLOCKINFO clock_info;
51 GUID guid_clock;
52 IReferenceClock *clock = NULL;
54 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (LPVOID*)&dmusic);
55 ok(hr == S_OK, "Cannot create DirectMusic object (%x)\n", hr);
57 hr = IDirectMusic_GetMasterClock(dmusic, &guid_clock, &clock);
58 ok(hr == S_OK, "IDirectMusic_GetMasterClock returned: %x\n", hr);
59 ok(clock != NULL, "No clock returned\n");
60 trace(" guidPort = %s\n", wine_dbgstr_guid(&guid_clock));
61 if (clock)
62 IReferenceClock_Release(clock);
64 port_params.dwSize = sizeof(port_params);
65 port_params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
66 port_params.dwChannelGroups = 1;
67 port_params.dwAudioChannels = 2;
69 /* No port can be created before SetDirectSound is called */
70 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
71 ok(hr == DMUS_E_DSOUND_NOT_SET, "IDirectMusic_CreatePort returned: %x\n", hr);
73 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
74 ok(hr == S_OK, "IDirectMusic_SetDirectSound returned: %x\n", hr);
76 /* Check wrong params */
77 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, (IUnknown*)dmusic);
78 ok(hr == CLASS_E_NOAGGREGATION, "IDirectMusic_CreatePort returned: %x\n", hr);
79 hr = IDirectMusic_CreatePort(dmusic, NULL, &port_params, &port, NULL);
80 ok(hr == E_POINTER, "IDirectMusic_CreatePort returned: %x\n", hr);
81 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, NULL, &port, NULL);
82 ok(hr == E_INVALIDARG, "IDirectMusic_CreatePort returned: %x\n", hr);
83 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, NULL, NULL);
84 ok(hr == E_POINTER, "IDirectMusic_CreatePort returned: %x\n", hr);
86 /* Test creation of default port with GUID_NULL */
87 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
88 ok(hr == S_OK, "IDirectMusic_CreatePort returned: %x\n", hr);
90 port_caps.dwSize = sizeof(port_caps);
91 while (IDirectMusic_EnumPort(dmusic, index, &port_caps) == S_OK)
93 ok(port_caps.dwSize == sizeof(port_caps), "DMUS_PORTCAPS dwSize member is wrong (%u)\n", port_caps.dwSize);
94 trace("Port %u:\n", index);
95 trace(" dwFlags = %x\n", port_caps.dwFlags);
96 trace(" guidPort = %s\n", wine_dbgstr_guid(&port_caps.guidPort));
97 trace(" dwClass = %u\n", port_caps.dwClass);
98 trace(" dwType = %u\n", port_caps.dwType);
99 trace(" dwMemorySize = %u\n", port_caps.dwMemorySize);
100 trace(" dwMaxChannelGroups = %u\n", port_caps.dwMaxChannelGroups);
101 trace(" dwMaxVoices = %u\n", port_caps.dwMaxVoices);
102 trace(" dwMaxAudioChannels = %u\n", port_caps.dwMaxAudioChannels);
103 trace(" dwEffectFlags = %x\n", port_caps.dwEffectFlags);
104 trace(" wszDescription = %s\n", wine_dbgstr_w(port_caps.wszDescription));
105 index++;
108 index = 0;
109 clock_info.dwSize = sizeof(clock_info);
110 while (IDirectMusic_EnumMasterClock(dmusic, index, &clock_info) == S_OK)
112 ok(clock_info.dwSize == sizeof(clock_info), "DMUS_CLOCKINFO dwSize member is wrong (%u)\n", clock_info.dwSize);
113 trace("Clock %u:\n", index);
114 trace(" ctType = %u\n", clock_info.ctType);
115 trace(" guidClock = %s\n", wine_dbgstr_guid(&clock_info.guidClock));
116 trace(" wszDescription = %s\n", wine_dbgstr_w(clock_info.wszDescription));
117 index++;
120 if (port)
121 IDirectMusicPort_Release(port);
122 IDirectMusic_Release(dmusic);
125 static ULONG get_refcount(IDirectSound *iface)
127 IDirectSound_AddRef(iface);
128 return IDirectSound_Release(iface);
131 static void test_setdsound(void)
133 IDirectMusic *dmusic;
134 IDirectSound *dsound, *dsound2;
135 DMUS_PORTPARAMS params;
136 IDirectMusicPort *port = NULL;
137 HRESULT hr;
138 ULONG ref;
140 params.dwSize = sizeof(params);
141 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
142 params.dwChannelGroups = 1;
143 params.dwAudioChannels = 2;
145 /* Old dsound without SetCooperativeLevel() */
146 hr = DirectSoundCreate(NULL, &dsound, NULL);
147 if (hr == DSERR_NODRIVER ) {
148 skip("No driver\n");
149 return;
151 ok(hr == S_OK, "DirectSoundCreate failed: %08x\n", hr);
152 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
153 (void **)&dmusic);
154 ok(hr == S_OK, "DirectMusic create failed: %08x\n", hr);
155 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
156 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
157 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &params, &port, NULL);
158 ok(hr == S_OK, "CreatePort returned: %x\n", hr);
159 IDirectMusicPort_Release(port);
160 IDirectMusic_Release(dmusic);
161 IDirectSound_Release(dsound);
163 /* dsound ref counting */
164 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
165 (void **)&dmusic);
166 ok(hr == S_OK, "DirectMusic create failed: %08x\n", hr);
167 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&dsound, NULL);
168 ok(hr == S_OK, "DirectSoundCreate failed: %08x\n", hr);
169 hr = IDirectSound_SetCooperativeLevel(dsound, GetForegroundWindow(), DSSCL_PRIORITY);
170 ok(hr == S_OK, "SetCooperativeLevel failed: %08x\n", hr);
171 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
172 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
173 ref = get_refcount(dsound);
174 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
175 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &params, &port, NULL);
176 ok(hr == S_OK, "CreatePort returned: %x\n", hr);
177 ref = get_refcount(dsound);
178 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
179 IDirectMusicPort_AddRef(port);
180 ref = IDirectMusicPort_Release(port);
181 ok(ref == 1, "port ref count got %d expected 1\n", ref);
182 hr = IDirectMusicPort_Activate(port, TRUE);
183 ok(hr == S_OK, "Port Activate returned: %x\n", hr);
184 ref = get_refcount(dsound);
185 ok(ref == 4, "dsound ref count got %d expected 4\n", ref);
186 IDirectMusicPort_AddRef(port);
187 ref = IDirectMusicPort_Release(port);
188 ok(ref == 1, "port ref count got %d expected 1\n", ref);
190 /* Releasing dsound from dmusic */
191 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
192 ok(hr == DMUS_E_DSOUND_ALREADY_SET, "SetDirectSound failed: %08x\n", hr);
193 hr = IDirectMusicPort_Activate(port, FALSE);
194 ok(hr == S_OK, "Port Activate returned: %x\n", hr);
195 ref = get_refcount(dsound);
196 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
197 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
198 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
199 ref = get_refcount(dsound);
200 ok(ref == 1, "dsound ref count got %d expected 1\n", ref);
202 /* Setting the same dsound twice */
203 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
204 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
205 ref = get_refcount(dsound);
206 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
207 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
208 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
209 ref = get_refcount(dsound);
210 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
212 /* Replacing one dsound with another */
213 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&dsound2, NULL);
214 ok(hr == S_OK, "DirectSoundCreate failed: %08x\n", hr);
215 hr = IDirectMusic_SetDirectSound(dmusic, dsound2, NULL);
216 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
217 ref = get_refcount(dsound);
218 ok(ref == 1, "dsound ref count got %d expected 1\n", ref);
219 ref = get_refcount(dsound2);
220 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
222 /* Replacing the dsound in the port */
223 hr = IDirectMusicPort_SetDirectSound(port, dsound, NULL);
224 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
225 ref = get_refcount(dsound);
226 ok(ref == 2, "dsound ref count got %d expected 2\n", ref);
227 ref = get_refcount(dsound2);
228 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
229 /* Setting the dsound again on the port will mess with the parent dmusic */
230 hr = IDirectMusicPort_SetDirectSound(port, dsound, NULL);
231 ok(hr == S_OK, "SetDirectSound failed: %08x\n", hr);
232 ref = get_refcount(dsound);
233 ok(ref == 3, "dsound ref count got %d expected 3\n", ref);
234 ref = get_refcount(dsound2);
235 ok(ref == 1, "dsound2 ref count got %d expected 1\n", ref);
236 IDirectSound_AddRef(dsound2); /* Crash prevention */
237 hr = IDirectMusicPort_Activate(port, TRUE);
238 ok(hr == S_OK, "Activate returned: %x\n", hr);
239 ref = get_refcount(dsound);
240 ok(ref == 4, "dsound ref count got %d expected 4\n", ref);
241 ref = get_refcount(dsound2);
242 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
243 hr = IDirectMusicPort_Activate(port, TRUE);
244 ok(hr == S_FALSE, "Activate returned: %x\n", hr);
245 ref = get_refcount(dsound);
246 ok(ref == 4, "dsound ref count got %d expected 4\n", ref);
247 ref = get_refcount(dsound2);
248 ok(ref == 2, "dsound2 ref count got %d expected 2\n", ref);
250 /* Deactivating the port messes with the dsound refcount in the parent dmusic */
251 hr = IDirectMusicPort_Activate(port, FALSE);
252 ok(hr == S_OK, "Port Activate returned: %x\n", hr);
253 ref = get_refcount(dsound);
254 ok(ref == 3, "dsound ref count got %d expected 3\n", ref);
255 ref = get_refcount(dsound2);
256 ok(ref == 1, "dsound2 ref count got %d expected 1\n", ref);
257 hr = IDirectMusicPort_Activate(port, FALSE);
258 ok(hr == S_FALSE, "Port Activate returned: %x\n", hr);
259 ref = get_refcount(dsound);
260 ok(ref == 3, "dsound ref count got %d expected 3\n", ref);
261 ref = get_refcount(dsound2);
262 ok(ref == 1, "dsound2 ref count got %d expected 1\n", ref);
264 IDirectMusicPort_Release(port);
265 IDirectMusic_Release(dmusic);
266 while (IDirectSound_Release(dsound));
269 static void test_dmbuffer(void)
271 IDirectMusic *dmusic;
272 IDirectMusicBuffer *dmbuffer = NULL;
273 HRESULT hr;
274 DMUS_BUFFERDESC desc;
275 GUID format;
276 DWORD size;
277 DWORD bytes;
278 REFERENCE_TIME time;
279 LPBYTE data;
281 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic, (LPVOID*)&dmusic);
282 ok(hr == S_OK, "Cannot create DirectMusic object (%x)\n", hr);
284 desc.dwSize = sizeof(DMUS_BUFFERDESC);
285 desc.dwFlags = 0;
286 desc.cbBuffer = 1023;
287 memcpy(&desc.guidBufferFormat, &GUID_NULL, sizeof(GUID));
289 hr = IDirectMusic_CreateMusicBuffer(dmusic, &desc, &dmbuffer, NULL);
290 ok(hr == S_OK, "IDirectMusic_CreateMusicBuffer return %x\n", hr);
292 hr = IDirectMusicBuffer_GetBufferFormat(dmbuffer, &format);
293 ok(hr == S_OK, "IDirectMusicBuffer_GetBufferFormat returned %x\n", hr);
294 ok(IsEqualGUID(&format, &KSDATAFORMAT_SUBTYPE_MIDI), "Wrong format returned %s\n", wine_dbgstr_guid(&format));
295 hr = IDirectMusicBuffer_GetMaxBytes(dmbuffer, &size);
296 ok(hr == S_OK, "IDirectMusicBuffer_GetMaxBytes returned %x\n", hr);
297 ok(size == 1024, "Buffer size is %u instead of 1024\n", size);
299 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
300 ok(hr == DMUS_E_BUFFER_EMPTY, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
301 hr = IDirectMusicBuffer_SetStartTime(dmbuffer, 10);
302 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
303 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
304 ok(hr == DMUS_E_BUFFER_EMPTY, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
306 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 20, 0, 0);
307 ok(hr == DMUS_E_INVALID_EVENT, "IDirectMusicBuffer_PackStructured returned %x\n", hr);
308 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 20, 0, 0x000090); /* note on : chan 0, note 0 & vel 0 */
309 ok(hr == S_OK, "IDirectMusicBuffer_PackStructured returned %x\n", hr);
310 hr = IDirectMusicBuffer_PackStructured(dmbuffer, 30, 0, 0x000080); /* note off : chan 0, note 0 & vel 0 */
311 ok(hr == S_OK, "IDirectMusicBuffer_PackStructured returned %x\n", hr);
312 hr = IDirectMusicBuffer_GetUsedBytes(dmbuffer, &bytes);
313 ok(hr == S_OK, "IDirectMusicBuffer_GetUsedBytes returned %x\n", hr);
314 ok(bytes == 48, "Buffer size is %u instead of 48\n", bytes);
316 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
317 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
318 ok(time == 20, "Buffer start time is wrong\n");
319 hr = IDirectMusicBuffer_SetStartTime(dmbuffer, 40);
320 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
321 hr = IDirectMusicBuffer_GetStartTime(dmbuffer, &time);
322 ok(hr == S_OK, "IDirectMusicBuffer_GetStartTime returned %x\n", hr);
323 ok(time == 40, "Buffer start time is wrong\n");
325 hr = IDirectMusicBuffer_GetRawBufferPtr(dmbuffer, &data);
326 ok(hr == S_OK, "IDirectMusicBuffer_GetRawBufferPtr returned %x\n", hr);
327 if (hr == S_OK)
329 DMUS_EVENTHEADER* header;
330 DWORD message;
332 /* Check message 1 */
333 header = (DMUS_EVENTHEADER*)data;
334 data += sizeof(DMUS_EVENTHEADER);
335 ok(header->cbEvent == 3, "cbEvent is %u instead of 3\n", header->cbEvent);
336 ok(header->dwChannelGroup == 0, "dwChannelGroup is %u instead of 0\n", header->dwChannelGroup);
337 ok(header->rtDelta == 0, "rtDelta is %s instead of 0\n", debugstr_longlong(header->rtDelta));
338 ok(header->dwFlags == DMUS_EVENT_STRUCTURED, "dwFlags is %x instead of %x\n", header->dwFlags, DMUS_EVENT_STRUCTURED);
339 message = *(DWORD*)data & 0xffffff; /* Only 3 bytes are relevant */
340 data += sizeof(DWORD);
341 ok(message == 0x000090, "Message is %0x instead of 0x000090\n", message);
343 /* Check message 2 */
344 header = (DMUS_EVENTHEADER*)data;
345 data += sizeof(DMUS_EVENTHEADER);
346 ok(header->cbEvent == 3, "cbEvent is %u instead of 3\n", header->cbEvent);
347 ok(header->dwChannelGroup == 0, "dwChannelGroup is %u instead of 0\n", header->dwChannelGroup);
348 ok(header->rtDelta == 10, "rtDelta is %s instead of 0\n", debugstr_longlong(header->rtDelta));
349 ok(header->dwFlags == DMUS_EVENT_STRUCTURED, "dwFlags is %x instead of %x\n", header->dwFlags, DMUS_EVENT_STRUCTURED);
350 message = *(DWORD*)data & 0xffffff; /* Only 3 bytes are relevant */
351 ok(message == 0x000080, "Message 2 is %0x instead of 0x000080\n", message);
354 if (dmbuffer)
355 IDirectMusicBuffer_Release(dmbuffer);
356 IDirectMusic_Release(dmusic);
359 static void test_COM(void)
361 IDirectMusic8 *dm8 = (IDirectMusic8*)0xdeadbeef;
362 IDirectMusic *dm;
363 IUnknown *unk;
364 ULONG refcount;
365 HRESULT hr;
367 /* COM aggregation */
368 hr = CoCreateInstance(&CLSID_DirectMusic, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
369 (void**)&dm8);
370 ok(hr == CLASS_E_NOAGGREGATION,
371 "DirectMusic8 create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
372 ok(!dm8, "dm8 = %p\n", dm8);
374 /* Invalid RIID */
375 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
376 (void**)&dm8);
377 ok(hr == E_NOINTERFACE, "DirectMusic8 create failed: %08x, expected E_NOINTERFACE\n", hr);
379 /* Same refcount for DirectMusic and DirectMusic8 */
380 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
381 (void**)&dm8);
382 if (hr == E_NOINTERFACE)
384 win_skip("DirectMusic too old (no IDirectMusic8)\n");
385 return;
387 ok(hr == S_OK, "DirectMusic8 create failed: %08x, expected S_OK\n", hr);
388 refcount = IDirectMusic8_AddRef(dm8);
389 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
391 hr = IDirectMusic8_QueryInterface(dm8, &IID_IDirectMusic, (void**)&dm);
392 ok(hr == S_OK, "QueryInterface for IID_IDirectMusic failed: %08x\n", hr);
393 refcount = IDirectMusic_AddRef(dm);
394 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
395 IDirectMusic_Release(dm);
397 hr = IDirectMusic8_QueryInterface(dm8, &IID_IUnknown, (void**)&unk);
398 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
399 refcount = IUnknown_AddRef(unk);
400 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
401 refcount = IUnknown_Release(unk);
403 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
404 while (IDirectMusic8_Release(dm8));
407 static void test_COM_dmcoll(void)
409 IDirectMusicCollection *dmc = (IDirectMusicCollection*)0xdeadbeef;
410 IDirectMusicObject *dmo;
411 IPersistStream *ps;
412 IUnknown *unk;
413 ULONG refcount;
414 HRESULT hr;
416 /* COM aggregation */
417 hr = CoCreateInstance(&CLSID_DirectMusicCollection, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
418 &IID_IUnknown, (void**)&dmc);
419 ok(hr == CLASS_E_NOAGGREGATION,
420 "DirectMusicCollection create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
421 ok(!dmc, "dmc = %p\n", dmc);
423 /* Invalid RIID */
424 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
425 &IID_IClassFactory, (void**)&dmc);
426 ok(hr == E_NOINTERFACE, "DirectMusicCollection create failed: %08x, expected E_NOINTERFACE\n", hr);
428 /* Same refcount for all DirectMusicCollection interfaces */
429 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
430 &IID_IDirectMusicCollection, (void**)&dmc);
431 ok(hr == S_OK, "DirectMusicCollection create failed: %08x, expected S_OK\n", hr);
432 refcount = IDirectMusicCollection_AddRef(dmc);
433 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
435 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IDirectMusicObject, (void**)&dmo);
436 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
437 refcount = IDirectMusicObject_AddRef(dmo);
438 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
439 refcount = IDirectMusicObject_Release(dmo);
441 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IPersistStream, (void**)&ps);
442 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
443 refcount = IPersistStream_AddRef(ps);
444 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
445 refcount = IPersistStream_Release(ps);
447 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IUnknown, (void**)&unk);
448 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
449 refcount = IUnknown_AddRef(unk);
450 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
451 refcount = IUnknown_Release(unk);
453 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
454 while (IDirectMusicCollection_Release(dmc));
457 static void test_dmcoll(void)
459 IDirectMusicCollection *dmc;
460 IDirectMusicObject *dmo;
461 IPersistStream *ps;
462 DMUS_OBJECTDESC desc;
463 CLSID class;
464 ULARGE_INTEGER size;
465 HRESULT hr;
467 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
468 &IID_IDirectMusicCollection, (void**)&dmc);
469 ok(hr == S_OK, "DirectMusicCollection create failed: %08x, expected S_OK\n", hr);
471 /* IDirectMusicObject */
472 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IDirectMusicObject, (void**)&dmo);
473 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
474 hr = IDirectMusicObject_GetDescriptor(dmo, NULL);
475 ok(hr == E_POINTER, "IDirectMusicObject_GetDescriptor: expected E_POINTER, got %08x\n", hr);
476 hr = IDirectMusicObject_SetDescriptor(dmo, NULL);
477 ok(hr == E_POINTER, "IDirectMusicObject_SetDescriptor: expected E_POINTER, got %08x\n", hr);
478 ZeroMemory(&desc, sizeof(desc));
479 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
480 ok(hr == S_OK, "IDirectMusicObject_GetDescriptor failed: %08x\n", hr);
481 ok(desc.dwValidData == DMUS_OBJ_CLASS,
482 "Fresh object has more valid data (%08x) than DMUS_OBJ_CLASS\n", desc.dwValidData);
483 /* DMUS_OBJ_CLASS is immutable */
484 desc.dwValidData = DMUS_OBJ_CLASS;
485 hr = IDirectMusicObject_SetDescriptor(dmo, &desc);
486 ok(hr == S_FALSE , "IDirectMusicObject_SetDescriptor failed: %08x\n", hr);
487 ok(!desc.dwValidData, "dwValidData wasn't cleared: %08x\n", desc.dwValidData);
488 desc.dwValidData = DMUS_OBJ_CLASS;
489 desc.guidClass = CLSID_DirectMusicSegment;
490 hr = IDirectMusicObject_SetDescriptor(dmo, &desc);
491 ok(hr == S_FALSE && !desc.dwValidData, "IDirectMusicObject_SetDescriptor failed: %08x\n", hr);
492 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
493 ok(hr == S_OK, "IDirectMusicObject_GetDescriptor failed: %08x\n", hr);
494 ok(IsEqualGUID(&desc.guidClass, &CLSID_DirectMusicCollection),
495 "guidClass changed, should be CLSID_DirectMusicCollection\n");
497 /* Unimplemented IPersistStream methods*/
498 hr = IDirectMusicCollection_QueryInterface(dmc, &IID_IPersistStream, (void**)&ps);
499 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
500 hr = IPersistStream_GetClassID(ps, &class);
501 ok(hr == E_NOTIMPL, "IPersistStream_GetClassID failed: %08x\n", hr);
502 hr = IPersistStream_IsDirty(ps);
503 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
504 hr = IPersistStream_GetSizeMax(ps, &size);
505 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
506 hr = IPersistStream_Save(ps, NULL, TRUE);
507 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
509 while (IDirectMusicCollection_Release(dmc));
512 static BOOL missing_dmusic(void)
514 IDirectMusic8 *dm;
515 HRESULT hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic,
516 (void**)&dm);
518 if (hr == S_OK && dm)
520 IDirectMusic_Release(dm);
521 return FALSE;
523 return TRUE;
526 static void test_COM_synthport(void)
528 IDirectMusic *dmusic = NULL;
529 IDirectMusicPort *port = NULL;
530 IDirectMusicPortDownload *dmpd;
531 IDirectMusicThru *dmt;
532 IKsControl *iksc;
533 IReferenceClock *clock;
534 IUnknown *unk;
535 DMUS_PORTPARAMS port_params;
536 ULONG refcount;
537 HRESULT hr;
539 /* Create a IDirectMusicPort */
540 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic,
541 (void**)&dmusic);
542 ok(hr == S_OK, "Cannot create DirectMusic object (%x)\n", hr);
543 port_params.dwSize = sizeof(port_params);
544 port_params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_AUDIOCHANNELS;
545 port_params.dwChannelGroups = 1;
546 port_params.dwAudioChannels = 2;
547 hr = IDirectMusic_SetDirectSound(dmusic, NULL, NULL);
548 ok(hr == S_OK, "IDirectMusic_SetDirectSound returned: %x\n", hr);
549 hr = IDirectMusic_CreatePort(dmusic, &GUID_NULL, &port_params, &port, NULL);
550 ok(hr == S_OK, "IDirectMusic_CreatePort returned: %x\n", hr);
552 /* Same refcount for all DirectMusicPort interfaces */
553 refcount = IDirectMusicPort_AddRef(port);
554 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
556 hr = IDirectMusicPort_QueryInterface(port, &IID_IDirectMusicPortDownload, (void**)&dmpd);
557 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicPortDownload failed: %08x\n", hr);
558 refcount = IDirectMusicPortDownload_AddRef(dmpd);
559 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
560 IDirectMusicPortDownload_Release(dmpd);
562 hr = IDirectMusicPort_QueryInterface(port, &IID_IKsControl, (void**)&iksc);
563 ok(hr == S_OK, "QueryInterface for IID_IKsControl failed: %08x\n", hr);
564 refcount = IKsControl_AddRef(iksc);
565 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
566 IKsControl_Release(iksc);
568 hr = IDirectMusicPort_QueryInterface(port, &IID_IUnknown, (void**)&unk);
569 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
570 refcount = IUnknown_AddRef(unk);
571 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
572 IUnknown_Release(unk);
574 /* Unsupported interface */
575 hr = IDirectMusicPort_QueryInterface(port, &IID_IDirectMusicThru, (void**)&dmt);
576 todo_wine ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicThru failed: %08x\n", hr);
577 hr = IDirectMusicPort_QueryInterface(port, &IID_IReferenceClock, (void**)&clock);
578 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IReferenceClock failed: %08x\n", hr);
580 while (IDirectMusicPort_Release(port));
583 START_TEST(dmusic)
585 CoInitializeEx(NULL, COINIT_MULTITHREADED);
587 if (missing_dmusic())
589 skip("DirectMusic not available\n");
590 CoUninitialize();
591 return;
593 test_COM();
594 test_COM_dmcoll();
595 test_COM_synthport();
596 test_dmusic();
597 test_setdsound();
598 test_dmbuffer();
599 test_dmcoll();
601 CoUninitialize();