makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / dmime / tests / dmime.c
blob99295f391bd824cab3d56ebfff7f4dc0d3cc830d
1 /*
2 * Copyright 2012, 2014 Michael Stefaniuc
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <wine/test.h>
24 #include <ole2.h>
25 #include <dmusici.h>
26 #include <dmusicf.h>
27 #include <audioclient.h>
28 #include <guiddef.h>
30 static BOOL missing_dmime(void)
32 IDirectMusicSegment8 *dms;
33 HRESULT hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
34 &IID_IDirectMusicSegment, (void**)&dms);
36 if (hr == S_OK && dms)
38 IDirectMusicSegment_Release(dms);
39 return FALSE;
41 return TRUE;
44 static void test_COM_audiopath(void)
46 IDirectMusicAudioPath *dmap;
47 IUnknown *unk;
48 IDirectMusicPerformance8 *performance;
49 IDirectSoundBuffer *dsound;
50 IDirectSoundBuffer8 *dsound8;
51 IDirectSoundNotify *notify;
52 IDirectSound3DBuffer *dsound3d;
53 IKsPropertySet *propset;
54 ULONG refcount;
55 HRESULT hr;
56 DWORD buffer = 0;
58 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
59 &IID_IDirectMusicPerformance8, (void**)&performance);
60 ok(hr == S_OK || broken(hr == E_NOINTERFACE),
61 "DirectMusicPerformance create failed: %08x\n", hr);
62 if (!performance) {
63 win_skip("IDirectMusicPerformance8 not available\n");
64 return;
66 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL,
67 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
68 ok(hr == S_OK || hr == DSERR_NODRIVER ||
69 broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED), /* Win 10 testbot */
70 "DirectMusicPerformance_InitAudio failed: %08x\n", hr);
71 if (FAILED(hr)) {
72 skip("Audio failed to initialize\n");
73 return;
75 hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &dmap);
76 ok(hr == S_OK, "DirectMusicPerformance_GetDefaultAudioPath failed: %08x\n", hr);
78 /* IDirectMusicObject and IPersistStream are not supported */
79 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IDirectMusicObject, (void**)&unk);
80 todo_wine ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%08x, iface=%p\n",
81 hr, unk);
82 if (unk) IUnknown_Release(unk);
83 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IPersistStream, (void**)&unk);
84 todo_wine ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%08x, iface=%p\n",
85 hr, unk);
86 if (unk) IUnknown_Release(unk);
88 /* Same refcount for all DirectMusicAudioPath interfaces */
89 refcount = IDirectMusicAudioPath_AddRef(dmap);
90 ok(refcount == 3, "refcount == %u, expected 3\n", refcount);
92 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IUnknown, (void**)&unk);
93 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
94 ok(unk == (IUnknown*)dmap, "got %p, %p\n", unk, dmap);
95 refcount = IUnknown_AddRef(unk);
96 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
97 refcount = IUnknown_Release(unk);
99 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
100 0, &IID_IDirectSoundBuffer, (void**)&dsound);
101 ok(hr == S_OK, "Failed: %08x\n", hr);
102 IDirectSoundBuffer_Release(dsound);
104 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
105 0, &IID_IDirectSoundBuffer8, (void**)&dsound8);
106 ok(hr == S_OK, "Failed: %08x\n", hr);
107 IDirectSoundBuffer8_Release(dsound8);
109 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
110 0, &IID_IDirectSoundNotify, (void**)&notify);
111 ok(hr == E_NOINTERFACE, "Failed: %08x\n", hr);
113 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
114 0, &IID_IDirectSound3DBuffer, (void**)&dsound3d);
115 ok(hr == E_NOINTERFACE, "Failed: %08x\n", hr);
117 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
118 0, &IID_IKsPropertySet, (void**)&propset);
119 todo_wine ok(hr == S_OK, "Failed: %08x\n", hr);
120 if (propset)
121 IKsPropertySet_Release(propset);
123 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
124 0, &IID_IUnknown, (void**)&unk);
125 ok(hr == S_OK, "Failed: %08x\n", hr);
126 IUnknown_Release(unk);
128 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
129 0, &GUID_NULL, (void**)&unk);
130 ok(hr == E_NOINTERFACE, "Failed: %08x\n", hr);
132 while (IDirectMusicAudioPath_Release(dmap) > 1); /* performance has a reference too */
133 IDirectMusicPerformance8_CloseDown(performance);
134 IDirectMusicPerformance8_Release(performance);
137 static void test_COM_audiopathconfig(void)
139 IDirectMusicAudioPath *dmap = (IDirectMusicAudioPath*)0xdeadbeef;
140 IDirectMusicObject *dmo;
141 IPersistStream *ps;
142 IUnknown *unk;
143 ULONG refcount;
144 HRESULT hr;
146 /* COM aggregation */
147 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
148 &IID_IUnknown, (void**)&dmap);
149 if (hr == REGDB_E_CLASSNOTREG) {
150 win_skip("DirectMusicAudioPathConfig not registered\n");
151 return;
153 ok(hr == CLASS_E_NOAGGREGATION,
154 "DirectMusicAudioPathConfig create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
155 ok(!dmap, "dmap = %p\n", dmap);
157 /* IDirectMusicAudioPath not supported */
158 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
159 &IID_IDirectMusicAudioPath, (void**)&dmap);
160 todo_wine ok(FAILED(hr) && !dmap,
161 "Unexpected IDirectMusicAudioPath interface: hr=%08x, iface=%p\n", hr, dmap);
163 /* IDirectMusicObject and IPersistStream supported */
164 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
165 &IID_IPersistStream, (void**)&ps);
166 ok(hr == S_OK, "DirectMusicObject create failed: %08x, expected S_OK\n", hr);
167 IPersistStream_Release(ps);
168 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
169 &IID_IDirectMusicObject, (void**)&dmo);
170 ok(hr == S_OK, "DirectMusicObject create failed: %08x, expected S_OK\n", hr);
172 /* Same refcount for all DirectMusicObject interfaces */
173 refcount = IDirectMusicObject_AddRef(dmo);
174 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
176 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
177 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
178 refcount = IPersistStream_AddRef(ps);
179 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
180 IPersistStream_Release(ps);
182 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IUnknown, (void**)&unk);
183 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
184 refcount = IUnknown_AddRef(unk);
185 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
186 refcount = IUnknown_Release(unk);
188 /* IDirectMusicAudioPath still not supported */
189 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IDirectMusicAudioPath, (void**)&dmap);
190 todo_wine ok(FAILED(hr) && !dmap,
191 "Unexpected IDirectMusicAudioPath interface: hr=%08x, iface=%p\n", hr, dmap);
193 while (IDirectMusicObject_Release(dmo));
197 static void test_COM_graph(void)
199 IDirectMusicGraph *dmg = (IDirectMusicGraph*)0xdeadbeef;
200 IDirectMusicObject *dmo;
201 IPersistStream *ps;
202 IUnknown *unk;
203 ULONG refcount;
204 HRESULT hr;
206 /* COM aggregation */
207 hr = CoCreateInstance(&CLSID_DirectMusicGraph, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
208 &IID_IUnknown, (void**)&dmg);
209 ok(hr == CLASS_E_NOAGGREGATION,
210 "DirectMusicGraph create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
211 ok(!dmg, "dmg = %p\n", dmg);
213 /* Invalid RIID */
214 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory,
215 (void**)&dmg);
216 ok(hr == E_NOINTERFACE, "DirectMusicGraph create failed: %08x, expected E_NOINTERFACE\n", hr);
218 /* Same refcount for all DirectMusicGraph interfaces */
219 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
220 &IID_IDirectMusicGraph, (void**)&dmg);
221 ok(hr == S_OK, "DirectMusicGraph create failed: %08x, expected S_OK\n", hr);
222 refcount = IDirectMusicGraph_AddRef(dmg);
223 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
225 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IDirectMusicObject, (void**)&dmo);
226 if (hr == E_NOINTERFACE) {
227 win_skip("DirectMusicGraph without IDirectMusicObject\n");
228 return;
230 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
231 refcount = IDirectMusicObject_AddRef(dmo);
232 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
233 refcount = IDirectMusicObject_Release(dmo);
235 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
236 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
237 refcount = IPersistStream_AddRef(ps);
238 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
239 refcount = IPersistStream_Release(ps);
241 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IUnknown, (void**)&unk);
242 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
243 refcount = IUnknown_AddRef(unk);
244 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
245 refcount = IUnknown_Release(unk);
247 while (IDirectMusicGraph_Release(dmg));
250 static void test_COM_segment(void)
252 IDirectMusicSegment8 *dms = (IDirectMusicSegment8*)0xdeadbeef;
253 IDirectMusicObject *dmo;
254 IPersistStream *stream;
255 IUnknown *unk;
256 ULONG refcount;
257 HRESULT hr;
259 /* COM aggregation */
260 hr = CoCreateInstance(&CLSID_DirectMusicSegment, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
261 &IID_IUnknown, (void**)&dms);
262 ok(hr == CLASS_E_NOAGGREGATION,
263 "DirectMusicSegment create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
264 ok(!dms, "dms = %p\n", dms);
266 /* Invalid RIID */
267 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
268 &IID_IDirectSound, (void**)&dms);
269 ok(hr == E_NOINTERFACE,
270 "DirectMusicSegment create failed: %08x, expected E_NOINTERFACE\n", hr);
272 /* Same refcount */
273 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
274 &IID_IDirectMusicSegment8, (void**)&dms);
275 if (hr == E_NOINTERFACE) {
276 win_skip("DirectMusicSegment without IDirectMusicSegment8\n");
277 return;
279 ok(hr == S_OK, "DirectMusicSegment create failed: %08x, expected S_OK\n", hr);
280 refcount = IDirectMusicSegment8_AddRef(dms);
281 ok (refcount == 2, "refcount == %u, expected 2\n", refcount);
282 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IDirectMusicObject, (void**)&dmo);
283 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %08x\n", hr);
284 IDirectMusicSegment8_AddRef(dms);
285 refcount = IDirectMusicSegment8_Release(dms);
286 ok (refcount == 3, "refcount == %u, expected 3\n", refcount);
287 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IPersistStream, (void**)&stream);
288 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
289 refcount = IDirectMusicSegment8_Release(dms);
290 ok (refcount == 3, "refcount == %u, expected 3\n", refcount);
291 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IUnknown, (void**)&unk);
292 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
293 refcount = IUnknown_Release(unk);
294 ok (refcount == 3, "refcount == %u, expected 3\n", refcount);
295 refcount = IDirectMusicObject_Release(dmo);
296 ok (refcount == 2, "refcount == %u, expected 2\n", refcount);
297 refcount = IPersistStream_Release(stream);
298 ok (refcount == 1, "refcount == %u, expected 1\n", refcount);
299 refcount = IDirectMusicSegment8_Release(dms);
300 ok (refcount == 0, "refcount == %u, expected 0\n", refcount);
303 static void test_COM_segmentstate(void)
305 IDirectMusicSegmentState8 *dmss8 = (IDirectMusicSegmentState8*)0xdeadbeef;
306 IUnknown *unk;
307 ULONG refcount;
308 HRESULT hr;
310 /* COM aggregation */
311 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
312 &IID_IUnknown, (void**)&dmss8);
313 ok(hr == CLASS_E_NOAGGREGATION,
314 "DirectMusicSegmentState8 create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
315 ok(!dmss8, "dmss8 = %p\n", dmss8);
317 /* Invalid RIID */
318 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
319 &IID_IDirectMusicObject, (void**)&dmss8);
320 ok(hr == E_NOINTERFACE,
321 "DirectMusicSegmentState8 create failed: %08x, expected E_NOINTERFACE\n", hr);
323 /* Same refcount for all DirectMusicSegmentState interfaces */
324 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
325 &IID_IDirectMusicSegmentState8, (void**)&dmss8);
326 if (hr == E_NOINTERFACE) {
327 win_skip("DirectMusicSegmentState without IDirectMusicSegmentState8\n");
328 return;
330 ok(hr == S_OK, "DirectMusicSegmentState8 create failed: %08x, expected S_OK\n", hr);
331 refcount = IDirectMusicSegmentState8_AddRef(dmss8);
332 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
334 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, (void**)&unk);
335 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
336 refcount = IUnknown_AddRef(unk);
337 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
338 refcount = IUnknown_Release(unk);
340 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, NULL);
341 ok(hr == E_POINTER, "got %08x\n", hr);
343 while (IDirectMusicSegmentState8_Release(dmss8));
346 static void test_COM_track(void)
348 IDirectMusicTrack *dmt;
349 IDirectMusicTrack8 *dmt8;
350 IPersistStream *ps;
351 IUnknown *unk;
352 ULONG refcount;
353 HRESULT hr;
354 #define X(class) &CLSID_ ## class, #class
355 const struct {
356 REFCLSID clsid;
357 const char *name;
358 BOOL has_dmt8;
359 } class[] = {
360 { X(DirectMusicLyricsTrack), TRUE },
361 { X(DirectMusicMarkerTrack), FALSE },
362 { X(DirectMusicParamControlTrack), TRUE },
363 { X(DirectMusicSegmentTriggerTrack), TRUE },
364 { X(DirectMusicSeqTrack), TRUE },
365 { X(DirectMusicSysExTrack), TRUE },
366 { X(DirectMusicTempoTrack), TRUE },
367 { X(DirectMusicTimeSigTrack), FALSE },
368 { X(DirectMusicWaveTrack), TRUE }
370 #undef X
371 unsigned int i;
373 for (i = 0; i < ARRAY_SIZE(class); i++) {
374 trace("Testing %s\n", class[i].name);
375 /* COM aggregation */
376 dmt8 = (IDirectMusicTrack8*)0xdeadbeef;
377 hr = CoCreateInstance(class[i].clsid, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
378 (void**)&dmt8);
379 if (hr == REGDB_E_CLASSNOTREG) {
380 win_skip("%s not registered\n", class[i].name);
381 continue;
383 ok(hr == CLASS_E_NOAGGREGATION,
384 "%s create failed: %08x, expected CLASS_E_NOAGGREGATION\n", class[i].name, hr);
385 ok(!dmt8, "dmt8 = %p\n", dmt8);
387 /* Invalid RIID */
388 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
389 (void**)&dmt8);
390 ok(hr == E_NOINTERFACE, "%s create failed: %08x, expected E_NOINTERFACE\n",
391 class[i].name, hr);
393 /* Same refcount for all DirectMusicTrack interfaces */
394 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
395 (void**)&dmt);
396 ok(hr == S_OK, "%s create failed: %08x, expected S_OK\n", class[i].name, hr);
397 refcount = IDirectMusicTrack_AddRef(dmt);
398 ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
400 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
401 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
402 refcount = IPersistStream_AddRef(ps);
403 ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
404 IPersistStream_Release(ps);
406 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IUnknown, (void**)&unk);
407 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
408 refcount = IUnknown_AddRef(unk);
409 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
410 refcount = IUnknown_Release(unk);
412 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
413 if (class[i].has_dmt8) {
414 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicTrack8 failed: %08x\n", hr);
415 refcount = IDirectMusicTrack8_AddRef(dmt8);
416 ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
417 refcount = IDirectMusicTrack8_Release(dmt8);
418 } else {
419 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicTrack8 failed: %08x\n", hr);
420 refcount = IDirectMusicTrack_AddRef(dmt);
421 ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
424 while (IDirectMusicTrack_Release(dmt));
428 static void test_audiopathconfig(void)
430 IDirectMusicObject *dmo;
431 IPersistStream *ps;
432 CLSID class = { 0 };
433 ULARGE_INTEGER size;
434 HRESULT hr;
436 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
437 &IID_IDirectMusicObject, (void**)&dmo);
438 if (hr == REGDB_E_CLASSNOTREG) {
439 win_skip("DirectMusicAudioPathConfig not registered\n");
440 return;
442 ok(hr == S_OK, "DirectMusicAudioPathConfig create failed: %08x, expected S_OK\n", hr);
444 /* IPersistStream */
445 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
446 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
447 hr = IPersistStream_GetClassID(ps, &class);
448 ok(hr == S_OK, "IPersistStream_GetClassID failed: %08x\n", hr);
449 ok(IsEqualGUID(&class, &CLSID_DirectMusicAudioPathConfig),
450 "Expected class CLSID_DirectMusicAudioPathConfig got %s\n", wine_dbgstr_guid(&class));
452 /* Unimplemented IPersistStream methods */
453 hr = IPersistStream_IsDirty(ps);
454 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
455 hr = IPersistStream_GetSizeMax(ps, &size);
456 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
457 hr = IPersistStream_Save(ps, NULL, TRUE);
458 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
460 while (IDirectMusicObject_Release(dmo));
463 static void test_graph(void)
465 IDirectMusicGraph *dmg;
466 IPersistStream *ps;
467 CLSID class = { 0 };
468 ULARGE_INTEGER size;
469 HRESULT hr;
471 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
472 &IID_IDirectMusicGraph, (void**)&dmg);
473 ok(hr == S_OK, "DirectMusicGraph create failed: %08x, expected S_OK\n", hr);
475 /* IPersistStream */
476 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
477 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
478 hr = IPersistStream_GetClassID(ps, &class);
479 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %08x\n", hr);
480 if (hr == S_OK)
481 ok(IsEqualGUID(&class, &CLSID_DirectMusicGraph),
482 "Expected class CLSID_DirectMusicGraph got %s\n", wine_dbgstr_guid(&class));
484 /* Unimplemented IPersistStream methods */
485 hr = IPersistStream_IsDirty(ps);
486 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
487 hr = IPersistStream_GetSizeMax(ps, &size);
488 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
489 hr = IPersistStream_Save(ps, NULL, TRUE);
490 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
492 while (IDirectMusicGraph_Release(dmg));
495 static void test_segment(void)
497 IDirectMusicSegment *dms;
498 IPersistStream *ps;
499 CLSID class = { 0 };
500 ULARGE_INTEGER size;
501 HRESULT hr;
503 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
504 &IID_IDirectMusicSegment, (void**)&dms);
505 ok(hr == S_OK, "DirectMusicSegment create failed: %08x, expected S_OK\n", hr);
507 /* IPersistStream */
508 hr = IDirectMusicSegment_QueryInterface(dms, &IID_IPersistStream, (void**)&ps);
509 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
510 hr = IPersistStream_GetClassID(ps, &class);
511 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %08x\n", hr);
512 if (hr == S_OK)
513 ok(IsEqualGUID(&class, &CLSID_DirectMusicSegment),
514 "Expected class CLSID_DirectMusicSegment got %s\n", wine_dbgstr_guid(&class));
516 /* Unimplemented IPersistStream methods */
517 hr = IPersistStream_IsDirty(ps);
518 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
519 hr = IPersistStream_GetSizeMax(ps, &size);
520 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
521 hr = IPersistStream_Save(ps, NULL, TRUE);
522 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
524 while (IDirectMusicSegment_Release(dms));
527 static void _add_track(IDirectMusicSegment8 *seg, REFCLSID class, const char *name, DWORD group)
529 IDirectMusicTrack *track;
530 HRESULT hr;
532 hr = CoCreateInstance(class, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
533 (void**)&track);
534 ok(hr == S_OK, "%s create failed: %08x, expected S_OK\n", name, hr);
535 hr = IDirectMusicSegment8_InsertTrack(seg, track, group);
536 if (group)
537 ok(hr == S_OK, "Inserting %s failed: %08x, expected S_OK\n", name, hr);
538 else
539 ok(hr == E_INVALIDARG, "Inserting %s failed: %08x, expected E_INVALIDARG\n", name, hr);
540 IDirectMusicTrack_Release(track);
543 #define add_track(seg, class, group) _add_track(seg, &CLSID_DirectMusic ## class, #class, group)
545 static void _expect_track(IDirectMusicSegment8 *seg, REFCLSID expect, const char *name, DWORD group,
546 DWORD index, BOOL ignore_guid)
548 IDirectMusicTrack *track;
549 IPersistStream *ps;
550 CLSID class;
551 HRESULT hr;
553 if (ignore_guid)
554 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, group, index, &track);
555 else
556 hr = IDirectMusicSegment8_GetTrack(seg, expect, group, index, &track);
557 if (!expect) {
558 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %08x, expected DMUS_E_NOT_FOUND\n", hr);
559 return;
562 ok(hr == S_OK, "GetTrack failed: %08x, expected S_OK\n", hr);
563 hr = IDirectMusicTrack_QueryInterface(track, &IID_IPersistStream, (void**)&ps);
564 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
565 hr = IPersistStream_GetClassID(ps, &class);
566 ok(hr == S_OK, "IPersistStream_GetClassID failed: %08x\n", hr);
567 ok(IsEqualGUID(&class, expect), "For group %#x index %u: Expected class %s got %s\n",
568 group, index, name, wine_dbgstr_guid(&class));
570 IPersistStream_Release(ps);
571 IDirectMusicTrack_Release(track);
574 #define expect_track(seg, class, group, index) \
575 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, TRUE)
576 #define expect_guid_track(seg, class, group, index) \
577 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, FALSE)
579 static void test_gettrack(void)
581 IDirectMusicSegment8 *seg;
582 IDirectMusicTrack *track;
583 HRESULT hr;
585 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
586 &IID_IDirectMusicSegment8, (void**)&seg);
587 ok(hr == S_OK, "DirectMusicSegment create failed: %08x, expected S_OK\n", hr);
589 add_track(seg, LyricsTrack, 0x0); /* failure */
590 add_track(seg, LyricsTrack, 0x1); /* idx 0 group 1 */
591 add_track(seg, ParamControlTrack, 0x3); /* idx 1 group 1, idx 0 group 2 */
592 add_track(seg, SegmentTriggerTrack, 0x2); /* idx 1 group 2 */
593 add_track(seg, SeqTrack, 0x1); /* idx 2 group 1 */
594 add_track(seg, TempoTrack, 0x7); /* idx 3 group 1, idx 2 group 2, idx 0 group 3 */
595 add_track(seg, WaveTrack, 0xffffffff); /* idx 4 group 1, idx 3 group 2, idx 1 group 3 */
597 /* Ignore GUID in GetTrack */
598 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, 0, 0, &track);
599 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %08x, expected DMUS_E_NOT_FOUND\n", hr);
601 expect_track(seg, LyricsTrack, 0x1, 0);
602 expect_track(seg, ParamControlTrack, 0x1, 1);
603 expect_track(seg, SeqTrack, 0x1, 2);
604 expect_track(seg, TempoTrack, 0x1, 3);
605 expect_track(seg, WaveTrack, 0x1, 4);
606 _expect_track(seg, NULL, "", 0x1, 5, TRUE);
607 _expect_track(seg, NULL, "", 0x1, DMUS_SEG_ANYTRACK, TRUE);
608 expect_track(seg, ParamControlTrack, 0x2, 0);
609 expect_track(seg, WaveTrack, 0x80000000, 0);
610 expect_track(seg, SegmentTriggerTrack, 0x3, 2); /* groups 1+2 combined index */
611 expect_track(seg, SeqTrack, 0x3, 3); /* groups 1+2 combined index */
612 expect_track(seg, TempoTrack, 0x7, 4); /* groups 1+2+3 combined index */
613 expect_track(seg, TempoTrack, 0xffffffff, 4); /* all groups combined index */
614 _expect_track(seg, NULL, "", 0xffffffff, DMUS_SEG_ANYTRACK, TRUE);
616 /* Use the GUID in GetTrack */
617 hr = IDirectMusicSegment8_GetTrack(seg, &CLSID_DirectMusicLyricsTrack, 0, 0, &track);
618 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %08x, expected DMUS_E_NOT_FOUND\n", hr);
620 expect_guid_track(seg, LyricsTrack, 0x1, 0);
621 expect_guid_track(seg, ParamControlTrack, 0x1, 0);
622 expect_guid_track(seg, SeqTrack, 0x1, 0);
623 expect_guid_track(seg, TempoTrack, 0x1, 0);
624 expect_guid_track(seg, ParamControlTrack, 0x2, 0);
625 expect_guid_track(seg, SegmentTriggerTrack, 0x3, 0);
626 expect_guid_track(seg, SeqTrack, 0x3, 0);
627 expect_guid_track(seg, TempoTrack, 0x7, 0);
628 expect_guid_track(seg, TempoTrack, 0xffffffff, 0);
630 IDirectMusicSegment8_Release(seg);
633 static void test_segment_param(void)
635 IDirectMusicSegment8 *seg;
636 char buf[64];
637 HRESULT hr;
639 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
640 &IID_IDirectMusicSegment8, (void **)&seg);
641 ok(hr == S_OK, "DirectMusicSegment create failed: %08x, expected S_OK\n", hr);
643 add_track(seg, LyricsTrack, 0x1); /* no params */
644 add_track(seg, SegmentTriggerTrack, 0x1); /* all params "supported" */
646 hr = IDirectMusicSegment8_GetParam(seg, NULL, 0x1, 0, 0, NULL, buf);
647 ok(hr == E_POINTER, "GetParam failed: %08x, expected E_POINTER\n", hr);
648 hr = IDirectMusicSegment8_SetParam(seg, NULL, 0x1, 0, 0, buf);
649 todo_wine ok(hr == E_POINTER, "SetParam failed: %08x, expected E_POINTER\n", hr);
651 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, NULL, buf);
652 ok(hr == DMUS_E_GET_UNSUPPORTED,
653 "GetParam failed: %08x, expected DMUS_E_GET_UNSUPPORTED\n", hr);
654 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, NULL, buf);
655 ok(hr == DMUS_E_TRACK_NOT_FOUND,
656 "GetParam failed: %08x, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
657 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ANYTRACK, 0,
658 NULL, buf);
659 ok(hr == DMUS_E_GET_UNSUPPORTED,
660 "GetParam failed: %08x, expected DMUS_E_GET_UNSUPPORTED\n", hr);
662 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, buf);
663 ok(hr == S_OK, "SetParam failed: %08x, expected S_OK\n", hr);
664 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, buf);
665 todo_wine ok(hr == DMUS_E_TRACK_NOT_FOUND,
666 "SetParam failed: %08x, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
667 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ALLTRACKS,
668 0, buf);
669 ok(hr == S_OK, "SetParam failed: %08x, expected S_OK\n", hr);
671 IDirectMusicSegment8_Release(seg);
674 static void expect_getparam(IDirectMusicTrack *track, REFGUID type, const char *name,
675 HRESULT expect)
677 HRESULT hr;
678 char buf[64] = { 0 };
680 hr = IDirectMusicTrack8_GetParam(track, type, 0, NULL, buf);
681 ok(hr == expect, "GetParam(%s) failed: %08x, expected %08x\n", name, hr, expect);
684 static void expect_setparam(IDirectMusicTrack *track, REFGUID type, const char *name,
685 HRESULT expect)
687 HRESULT hr;
688 char buf[64] = { 0 };
690 hr = IDirectMusicTrack8_SetParam(track, type, 0, buf);
691 ok(hr == expect, "SetParam(%s) failed: %08x, expected %08x\n", name, hr, expect);
694 static void test_track(void)
696 IDirectMusicTrack *dmt;
697 IDirectMusicTrack8 *dmt8;
698 IPersistStream *ps;
699 CLSID classid;
700 ULARGE_INTEGER size;
701 HRESULT hr;
702 #define X(guid) &guid, #guid
703 const struct {
704 REFGUID type;
705 const char *name;
706 } param_types[] = {
707 { X(GUID_BandParam) },
708 { X(GUID_ChordParam) },
709 { X(GUID_Clear_All_Bands) },
710 { X(GUID_CommandParam) },
711 { X(GUID_CommandParam2) },
712 { X(GUID_CommandParamNext) },
713 { X(GUID_ConnectToDLSCollection) },
714 { X(GUID_Disable_Auto_Download) },
715 { X(GUID_DisableTempo) },
716 { X(GUID_DisableTimeSig) },
717 { X(GUID_Download) },
718 { X(GUID_DownloadToAudioPath) },
719 { X(GUID_Enable_Auto_Download) },
720 { X(GUID_EnableTempo) },
721 { X(GUID_EnableTimeSig) },
722 { X(GUID_IDirectMusicBand) },
723 { X(GUID_IDirectMusicChordMap) },
724 { X(GUID_IDirectMusicStyle) },
725 { X(GUID_MuteParam) },
726 { X(GUID_Play_Marker) },
727 { X(GUID_RhythmParam) },
728 { X(GUID_SeedVariations) },
729 { X(GUID_StandardMIDIFile) },
730 { X(GUID_TempoParam) },
731 { X(GUID_TimeSignature) },
732 { X(GUID_Unload) },
733 { X(GUID_UnloadFromAudioPath) },
734 { X(GUID_Valid_Start_Time) },
735 { X(GUID_Variations) },
736 { X(GUID_NULL) }
738 #undef X
739 #define X(class) &CLSID_ ## class, #class
740 const struct {
741 REFCLSID clsid;
742 const char *name;
743 /* bitfield with supported param types */
744 unsigned int has_params;
745 } class[] = {
746 { X(DirectMusicLyricsTrack), 0 },
747 { X(DirectMusicMarkerTrack), 0x8080000 },
748 { X(DirectMusicParamControlTrack), 0 },
749 { X(DirectMusicSegmentTriggerTrack), 0x3fffffff },
750 { X(DirectMusicSeqTrack), ~0 }, /* param methods not implemented */
751 { X(DirectMusicSysExTrack), ~0 }, /* param methods not implemented */
752 { X(DirectMusicTempoTrack), 0x802100 },
753 { X(DirectMusicTimeSigTrack), 0x1004200 },
754 { X(DirectMusicWaveTrack), 0x6001c80 }
756 #undef X
757 unsigned int i, j;
759 for (i = 0; i < ARRAY_SIZE(class); i++) {
760 trace("Testing %s\n", class[i].name);
761 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
762 (void**)&dmt);
763 ok(hr == S_OK, "%s create failed: %08x, expected S_OK\n", class[i].name, hr);
765 /* IDirectMusicTrack */
766 if (class[i].has_params != ~0) {
767 for (j = 0; j < ARRAY_SIZE(param_types); j++) {
768 hr = IDirectMusicTrack8_IsParamSupported(dmt, param_types[j].type);
769 if (class[i].has_params & (1 << j)) {
770 ok(hr == S_OK, "IsParamSupported(%s) failed: %08x, expected S_OK\n",
771 param_types[j].name, hr);
772 if (class[i].clsid == &CLSID_DirectMusicSegmentTriggerTrack) {
773 expect_getparam(dmt, param_types[j].type, param_types[j].name,
774 DMUS_E_GET_UNSUPPORTED);
775 expect_setparam(dmt, param_types[j].type, param_types[j].name, S_OK);
776 } else if (class[i].clsid == &CLSID_DirectMusicMarkerTrack)
777 expect_setparam(dmt, param_types[j].type, param_types[j].name,
778 DMUS_E_SET_UNSUPPORTED);
779 else if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
780 expect_getparam(dmt, param_types[j].type, param_types[j].name,
781 DMUS_E_GET_UNSUPPORTED);
782 } else {
783 ok(hr == DMUS_E_TYPE_UNSUPPORTED,
784 "IsParamSupported(%s) failed: %08x, expected DMUS_E_TYPE_UNSUPPORTED\n",
785 param_types[j].name, hr);
786 expect_getparam(dmt, param_types[j].type, param_types[j].name,
787 DMUS_E_GET_UNSUPPORTED);
788 if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
789 expect_setparam(dmt, param_types[j].type, param_types[j].name,
790 DMUS_E_TYPE_UNSUPPORTED);
791 else
792 expect_setparam(dmt, param_types[j].type, param_types[j].name,
793 DMUS_E_SET_UNSUPPORTED);
796 /* GetParam / SetParam for IsParamSupported supported types */
797 if (class[i].clsid == &CLSID_DirectMusicTimeSigTrack) {
798 expect_getparam(dmt, &GUID_DisableTimeSig, "GUID_DisableTimeSig",
799 DMUS_E_GET_UNSUPPORTED);
800 expect_getparam(dmt, &GUID_EnableTimeSig, "GUID_EnableTimeSig",
801 DMUS_E_GET_UNSUPPORTED);
802 expect_setparam(dmt, &GUID_TimeSignature, "GUID_TimeSignature",
803 DMUS_E_SET_UNSUPPORTED);
804 } else if (class[i].clsid == &CLSID_DirectMusicTempoTrack) {
805 expect_getparam(dmt, &GUID_DisableTempo, "GUID_DisableTempo",
806 DMUS_E_GET_UNSUPPORTED);
807 expect_getparam(dmt, &GUID_EnableTempo, "GUID_EnableTempo",
808 DMUS_E_GET_UNSUPPORTED);
811 } else {
812 hr = IDirectMusicTrack_GetParam(dmt, NULL, 0, NULL, NULL);
813 ok(hr == E_NOTIMPL, "IDirectMusicTrack_GetParam failed: %08x\n", hr);
814 hr = IDirectMusicTrack_SetParam(dmt, NULL, 0, NULL);
815 ok(hr == E_NOTIMPL, "IDirectMusicTrack_SetParam failed: %08x\n", hr);
816 hr = IDirectMusicTrack_IsParamSupported(dmt, NULL);
817 ok(hr == E_NOTIMPL, "IDirectMusicTrack_IsParamSupported failed: %08x\n", hr);
819 hr = IDirectMusicTrack_IsParamSupported(dmt, &GUID_IDirectMusicStyle);
820 ok(hr == E_NOTIMPL, "got: %08x\n", hr);
822 if (class[i].clsid != &CLSID_DirectMusicMarkerTrack &&
823 class[i].clsid != &CLSID_DirectMusicTimeSigTrack) {
824 hr = IDirectMusicTrack_AddNotificationType(dmt, NULL);
825 ok(hr == E_NOTIMPL, "IDirectMusicTrack_AddNotificationType failed: %08x\n", hr);
826 hr = IDirectMusicTrack_RemoveNotificationType(dmt, NULL);
827 ok(hr == E_NOTIMPL, "IDirectMusicTrack_RemoveNotificationType failed: %08x\n", hr);
829 hr = IDirectMusicTrack_Clone(dmt, 0, 0, NULL);
830 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack_Clone failed: %08x\n", hr);
832 /* IDirectMusicTrack8 */
833 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
834 if (hr == S_OK) {
835 hr = IDirectMusicTrack8_PlayEx(dmt8, NULL, 0, 0, 0, 0, NULL, NULL, 0);
836 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_PlayEx failed: %08x\n", hr);
837 if (class[i].has_params == ~0) {
838 hr = IDirectMusicTrack8_GetParamEx(dmt8, NULL, 0, NULL, NULL, NULL, 0);
839 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_GetParamEx failed: %08x\n", hr);
840 hr = IDirectMusicTrack8_SetParamEx(dmt8, NULL, 0, NULL, NULL, 0);
841 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_SetParamEx failed: %08x\n", hr);
843 hr = IDirectMusicTrack8_Compose(dmt8, NULL, 0, NULL);
844 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Compose failed: %08x\n", hr);
845 hr = IDirectMusicTrack8_Join(dmt8, NULL, 0, NULL, 0, NULL);
846 if (class[i].clsid == &CLSID_DirectMusicTempoTrack)
847 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_Join failed: %08x\n", hr);
848 else
849 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Join failed: %08x\n", hr);
850 IDirectMusicTrack8_Release(dmt8);
853 /* IPersistStream */
854 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
855 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %08x\n", hr);
856 hr = IPersistStream_GetClassID(ps, &classid);
857 ok(hr == S_OK, "IPersistStream_GetClassID failed: %08x\n", hr);
858 ok(IsEqualGUID(&classid, class[i].clsid),
859 "Expected class %s got %s\n", class[i].name, wine_dbgstr_guid(&classid));
860 hr = IPersistStream_IsDirty(ps);
861 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %08x\n", hr);
863 /* Unimplemented IPersistStream methods */
864 hr = IPersistStream_GetSizeMax(ps, &size);
865 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %08x\n", hr);
866 hr = IPersistStream_Save(ps, NULL, TRUE);
867 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %08x\n", hr);
869 while (IDirectMusicTrack_Release(dmt));
873 struct chunk {
874 FOURCC id;
875 DWORD size;
876 FOURCC type;
879 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
881 /* Generate a RIFF file format stream from an array of FOURCC ids.
882 RIFF and LIST need to be followed by the form type respectively list type,
883 followed by the chunks of the list and terminated with 0. */
884 static IStream *gen_riff_stream(const FOURCC *ids)
886 static const LARGE_INTEGER zero;
887 int level = -1;
888 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
889 char riff[1024];
890 char *p = riff;
891 struct chunk *ck;
892 IStream *stream;
894 do {
895 ck = (struct chunk *)p;
896 ck->id = *ids++;
897 switch (ck->id) {
898 case 0:
899 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
900 level--;
901 break;
902 case FOURCC_LIST:
903 case FOURCC_RIFF:
904 level++;
905 sizes[level] = &ck->size;
906 ck->type = *ids++;
907 p += sizeof(*ck);
908 break;
909 case DMUS_FOURCC_GUID_CHUNK:
910 ck->size = sizeof(GUID_NULL);
911 p += CHUNK_HDR_SIZE;
912 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
913 p += ck->size;
914 break;
915 case DMUS_FOURCC_VERSION_CHUNK:
917 DMUS_VERSION ver = {5, 8};
919 ck->size = sizeof(ver);
920 p += CHUNK_HDR_SIZE;
921 memcpy(p, &ver, sizeof(ver));
922 p += ck->size;
923 break;
925 default:
927 /* Just convert the FOURCC id to a WCHAR string */
928 WCHAR *s;
930 ck->size = 5 * sizeof(WCHAR);
931 p += CHUNK_HDR_SIZE;
932 s = (WCHAR *)p;
933 s[0] = (char)(ck->id);
934 s[1] = (char)(ck->id >> 8);
935 s[2] = (char)(ck->id >> 16);
936 s[3] = (char)(ck->id >> 24);
937 s[4] = 0;
938 p += ck->size;
941 } while (level >= 0);
943 ck = (struct chunk *)riff;
944 CreateStreamOnHGlobal(NULL, TRUE, &stream);
945 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
946 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
948 return stream;
951 static void test_parsedescriptor(void)
953 IDirectMusicObject *dmo;
954 IStream *stream;
955 DMUS_OBJECTDESC desc;
956 HRESULT hr;
957 DWORD valid;
958 unsigned int i;
959 /* fourcc ~0 will be replaced later on */
960 FOURCC alldesc[] =
962 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
963 DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK, DMUS_FOURCC_UCMT_CHUNK,
964 DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, 0
966 FOURCC dupes[] =
968 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
969 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
970 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, 0,
971 FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
973 FOURCC empty[] = {FOURCC_RIFF, ~0, 0};
974 FOURCC inam[] = {FOURCC_RIFF, ~0, FOURCC_LIST, ~0, mmioFOURCC('I','N','A','M'), 0, 0};
975 FOURCC noriff[] = {mmioFOURCC('J','U','N','K'), 0};
976 #define X(class) &CLSID_ ## class, #class
977 #define Y(form) form, #form
978 const struct {
979 REFCLSID clsid;
980 const char *class;
981 FOURCC form;
982 const char *name;
983 BOOL needs_size;
984 } forms[] = {
985 { X(DirectMusicSegment), Y(DMUS_FOURCC_SEGMENT_FORM), FALSE },
986 { X(DirectMusicSegment), Y(mmioFOURCC('W','A','V','E')), FALSE },
987 { X(DirectMusicAudioPathConfig), Y(DMUS_FOURCC_AUDIOPATH_FORM), TRUE },
988 { X(DirectMusicGraph), Y(DMUS_FOURCC_TOOLGRAPH_FORM), TRUE },
990 #undef X
991 #undef Y
993 for (i = 0; i < ARRAY_SIZE(forms); i++) {
994 trace("Testing %s / %s\n", forms[i].class, forms[i].name);
995 hr = CoCreateInstance(forms[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
996 (void **)&dmo);
997 if (hr != S_OK) {
998 win_skip("Could not create %s object: %08x\n", forms[i].class, hr);
999 return;
1002 /* Nothing loaded */
1003 memset(&desc, 0, sizeof(desc));
1004 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1005 if (forms[i].needs_size) {
1006 todo_wine ok(hr == E_INVALIDARG,
1007 "GetDescriptor failed: %08x, expected E_INVALIDARG\n", hr);
1008 desc.dwSize = sizeof(desc);
1009 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1011 ok(hr == S_OK, "GetDescriptor failed: %08x, expected S_OK\n", hr);
1012 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n",
1013 desc.dwValidData);
1014 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1015 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1017 /* Empty RIFF stream */
1018 empty[1] = forms[i].form;
1019 stream = gen_riff_stream(empty);
1020 memset(&desc, 0, sizeof(desc));
1021 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1022 if (forms[i].needs_size) {
1023 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %08x, expected E_INVALIDARG\n", hr);
1024 desc.dwSize = sizeof(desc);
1025 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1027 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
1028 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n",
1029 desc.dwValidData);
1030 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1031 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1033 /* NULL pointers */
1034 memset(&desc, 0, sizeof(desc));
1035 desc.dwSize = sizeof(desc);
1036 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
1037 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
1038 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
1039 if (forms[i].needs_size)
1040 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %08x, expected E_INVALIDARG\n", hr);
1041 else
1042 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
1043 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, NULL);
1044 ok(hr == E_POINTER, "ParseDescriptor failed: %08x, expected E_POINTER\n", hr);
1045 IStream_Release(stream);
1047 /* Wrong form */
1048 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
1049 stream = gen_riff_stream(empty);
1050 memset(&desc, 0, sizeof(desc));
1051 desc.dwSize = sizeof(desc);
1052 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1053 if (forms[i].needs_size)
1054 ok(hr == DMUS_E_CHUNKNOTFOUND,
1055 "ParseDescriptor failed: %08x, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1056 else
1057 ok(hr == E_FAIL, "ParseDescriptor failed: %08x, expected E_FAIL\n", hr);
1058 ok(!desc.dwValidData, "Got valid data %#x, expected 0\n", desc.dwValidData);
1059 IStream_Release(stream);
1061 /* Not a RIFF stream */
1062 stream = gen_riff_stream(noriff);
1063 memset(&desc, 0, sizeof(desc));
1064 desc.dwSize = sizeof(desc);
1065 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1066 if (forms[i].needs_size)
1067 ok(hr == DMUS_E_CHUNKNOTFOUND,
1068 "ParseDescriptor failed: %08x, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1069 else
1070 ok(hr == E_FAIL, "ParseDescriptor failed: %08x, expected E_FAIL\n", hr);
1071 ok(!desc.dwValidData, "Got valid data %#x, expected 0\n", desc.dwValidData);
1072 IStream_Release(stream);
1074 /* All desc chunks */
1075 alldesc[1] = forms[i].form;
1076 stream = gen_riff_stream(alldesc);
1077 memset(&desc, 0, sizeof(desc));
1078 desc.dwSize = sizeof(desc);
1079 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1080 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
1081 valid = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_VERSION;
1082 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1083 valid |= DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY;
1084 ok(desc.dwValidData == valid, "Got valid data %#x, expected %#x\n", desc.dwValidData, valid);
1085 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1086 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1087 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
1088 wine_dbgstr_guid(&desc.guidClass));
1089 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
1090 "Got version %u.%u, expected 5.8\n", desc.vVersion.dwVersionMS,
1091 desc.vVersion.dwVersionLS);
1092 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1093 ok(!lstrcmpW(desc.wszName, L"UNAM"), "Got name '%s', expected 'UNAM'\n",
1094 wine_dbgstr_w(desc.wszName));
1095 IStream_Release(stream);
1097 /* Duplicated chunks */
1098 dupes[1] = forms[i].form;
1099 stream = gen_riff_stream(dupes);
1100 memset(&desc, 0, sizeof(desc));
1101 desc.dwSize = sizeof(desc);
1102 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1103 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
1104 ok(desc.dwValidData == valid, "Got valid data %#x, expected %#x\n", desc.dwValidData, valid);
1105 IStream_Release(stream);
1107 /* UNFO list with INAM */
1108 inam[1] = forms[i].form;
1109 inam[3] = DMUS_FOURCC_UNFO_LIST;
1110 stream = gen_riff_stream(inam);
1111 memset(&desc, 0, sizeof(desc));
1112 desc.dwSize = sizeof(desc);
1113 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1114 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
1115 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#x, expected DMUS_OBJ_CLASS\n",
1116 desc.dwValidData);
1117 IStream_Release(stream);
1119 /* INFO list with INAM */
1120 inam[3] = DMUS_FOURCC_INFO_LIST;
1121 stream = gen_riff_stream(inam);
1122 memset(&desc, 0, sizeof(desc));
1123 desc.dwSize = sizeof(desc);
1124 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1125 ok(hr == S_OK, "ParseDescriptor failed: %08x, expected S_OK\n", hr);
1126 valid = DMUS_OBJ_CLASS;
1127 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1128 valid |= DMUS_OBJ_NAME;
1129 ok(desc.dwValidData == valid, "Got valid data %#x, expected %#x\n", desc.dwValidData, valid);
1130 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1131 ok(!lstrcmpW(desc.wszName, L"I"), "Got name '%s', expected 'I'\n",
1132 wine_dbgstr_w(desc.wszName));
1133 IStream_Release(stream);
1135 IDirectMusicObject_Release(dmo);
1139 START_TEST(dmime)
1141 CoInitialize(NULL);
1143 if (missing_dmime())
1145 skip("dmime not available\n");
1146 CoUninitialize();
1147 return;
1149 test_COM_audiopath();
1150 test_COM_audiopathconfig();
1151 test_COM_graph();
1152 test_COM_segment();
1153 test_COM_segmentstate();
1154 test_COM_track();
1155 test_audiopathconfig();
1156 test_graph();
1157 test_segment();
1158 test_gettrack();
1159 test_segment_param();
1160 test_track();
1161 test_parsedescriptor();
1163 CoUninitialize();