dmime/tests: Test wave segments and DMUS_WAVE_PMSG.
[wine.git] / dlls / dmime / tests / dmime.c
blobe76949e71c7304632b1edef2db1dd3ab6fb96c30
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 ULONG get_refcount(void *iface)
32 IUnknown *unknown = iface;
33 IUnknown_AddRef(unknown);
34 return IUnknown_Release(unknown);
37 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
38 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
40 ULONG expect_ref = get_refcount(iface_ptr);
41 IUnknown *iface = iface_ptr;
42 HRESULT hr, expected;
43 IUnknown *unk;
45 expected = supported ? S_OK : E_NOINTERFACE;
46 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
47 ok_(__FILE__, line)(hr == expected, "got hr %#lx, expected %#lx.\n", hr, expected);
48 if (SUCCEEDED(hr))
50 LONG ref = get_refcount(unk);
51 ok_(__FILE__, line)(ref == expect_ref + 1, "got %ld\n", ref);
52 IUnknown_Release(unk);
53 ref = get_refcount(iface_ptr);
54 ok_(__FILE__, line)(ref == expect_ref, "got %ld\n", ref);
58 static void load_resource(const WCHAR *name, WCHAR *filename)
60 static WCHAR path[MAX_PATH];
61 DWORD written;
62 HANDLE file;
63 HRSRC res;
64 void *ptr;
66 GetTempPathW(ARRAY_SIZE(path), path);
67 GetTempFileNameW(path, name, 0, filename);
69 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
70 ok(file != INVALID_HANDLE_VALUE, "failed to create %s, error %lu\n", debugstr_w(filename), GetLastError());
72 res = FindResourceW(NULL, name, (const WCHAR *)RT_RCDATA);
73 ok(res != 0, "couldn't find resource\n");
74 ptr = LockResource(LoadResource(GetModuleHandleW(NULL ), res ));
75 WriteFile(file, ptr, SizeofResource(GetModuleHandleW(NULL ), res ), &written, NULL);
76 ok(written == SizeofResource(GetModuleHandleW(NULL ), res ), "couldn't write resource\n");
77 CloseHandle(file);
80 struct test_tool
82 IDirectMusicTool IDirectMusicTool_iface;
83 LONG ref;
85 IDirectMusicGraph *graph;
86 const DWORD *types;
87 DWORD types_count;
89 SRWLOCK lock;
90 HANDLE message_event;
91 DMUS_PMSG *messages[32];
92 UINT message_count;
95 static DMUS_PMSG *test_tool_push_msg(struct test_tool *tool, DMUS_PMSG *msg)
97 AcquireSRWLockExclusive(&tool->lock);
98 ok(tool->message_count < ARRAY_SIZE(tool->messages),
99 "got %u messages\n", tool->message_count + 1);
100 if (tool->message_count < ARRAY_SIZE(tool->messages))
102 memmove(tool->messages + 1, tool->messages,
103 tool->message_count * sizeof(*tool->messages));
104 tool->messages[0] = msg;
105 tool->message_count++;
106 msg = NULL;
108 ReleaseSRWLockExclusive(&tool->lock);
110 return msg;
113 static struct test_tool *impl_from_IDirectMusicTool(IDirectMusicTool *iface)
115 return CONTAINING_RECORD(iface, struct test_tool, IDirectMusicTool_iface);
118 static HRESULT WINAPI test_tool_QueryInterface(IDirectMusicTool *iface, REFIID iid, void **out)
120 if (IsEqualGUID(iid, &IID_IUnknown)
121 || IsEqualGUID(iid, &IID_IDirectMusicTool))
123 IDirectMusicTool_AddRef(iface);
124 *out = iface;
125 return S_OK;
128 ok(IsEqualGUID(iid, &IID_IDirectMusicTool8) || IsEqualGUID(iid, &IID_IPersistStream),
129 "got iid %s\n", debugstr_guid(iid));
130 *out = NULL;
131 return E_NOINTERFACE;
134 static ULONG WINAPI test_tool_AddRef(IDirectMusicTool *iface)
136 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
137 return InterlockedIncrement(&tool->ref);
140 static ULONG WINAPI test_tool_Release(IDirectMusicTool *iface)
142 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
143 ULONG ref = InterlockedDecrement(&tool->ref);
145 if (!ref)
147 if (tool->graph) IDirectMusicGraph_Release(tool->graph);
148 ok(!tool->message_count, "got %p\n", &tool->message_count);
149 CloseHandle(tool->message_event);
150 free(tool);
153 return ref;
156 static HRESULT WINAPI test_tool_Init(IDirectMusicTool *iface, IDirectMusicGraph *graph)
158 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
159 if ((tool->graph = graph)) IDirectMusicGraph_AddRef(tool->graph);
160 return S_OK;
163 static HRESULT WINAPI test_tool_GetMsgDeliveryType(IDirectMusicTool *iface, DWORD *type)
165 *type = DMUS_PMSGF_TOOL_IMMEDIATE;
166 return S_OK;
169 static HRESULT WINAPI test_tool_GetMediaTypeArraySize(IDirectMusicTool *iface, DWORD *size)
171 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
172 *size = tool->types_count;
173 return S_OK;
176 static HRESULT WINAPI test_tool_GetMediaTypes(IDirectMusicTool *iface, DWORD **types, DWORD size)
178 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
179 UINT i;
180 for (i = 0; i < tool->types_count; i++) (*types)[i] = tool->types[i];
181 return S_OK;
184 static HRESULT WINAPI test_tool_ProcessPMsg(IDirectMusicTool *iface, IDirectMusicPerformance *performance, DMUS_PMSG *msg)
186 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
187 DMUS_PMSG *clone;
188 HRESULT hr;
190 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, &clone);
191 ok(hr == S_OK, "got %#lx\n", hr);
192 clone = test_tool_push_msg(tool, clone);
193 ok(!clone, "got %p\n", clone);
194 SetEvent(tool->message_event);
196 hr = IDirectMusicGraph_StampPMsg(msg->pGraph, msg);
197 ok(hr == S_OK, "got %#lx\n", hr);
199 return DMUS_S_REQUEUE;
202 static HRESULT WINAPI test_tool_Flush(IDirectMusicTool *iface, IDirectMusicPerformance *performance,
203 DMUS_PMSG *msg, REFERENCE_TIME time)
205 ok(0, "unexpected %s\n", __func__);
206 return S_OK;
209 static IDirectMusicToolVtbl test_tool_vtbl =
211 test_tool_QueryInterface,
212 test_tool_AddRef,
213 test_tool_Release,
214 test_tool_Init,
215 test_tool_GetMsgDeliveryType,
216 test_tool_GetMediaTypeArraySize,
217 test_tool_GetMediaTypes,
218 test_tool_ProcessPMsg,
219 test_tool_Flush,
222 static HRESULT test_tool_create(const DWORD *types, DWORD types_count,
223 IDirectMusicTool **ret_iface)
225 struct test_tool *tool;
227 *ret_iface = NULL;
228 if (!(tool = calloc(1, sizeof(*tool)))) return E_OUTOFMEMORY;
229 tool->IDirectMusicTool_iface.lpVtbl = &test_tool_vtbl;
230 tool->ref = 1;
232 tool->types = types;
233 tool->types_count = types_count;
234 tool->message_event = CreateEventW(NULL, FALSE, FALSE, NULL);
235 ok(!!tool->message_event, "CreateEventW failed, error %lu\n", GetLastError());
237 *ret_iface = &tool->IDirectMusicTool_iface;
238 return S_OK;
241 static HRESULT test_tool_get_graph(IDirectMusicTool *iface, IDirectMusicGraph **graph)
243 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
244 if ((*graph = tool->graph)) IDirectMusicGraph_AddRef(tool->graph);
245 return tool->graph ? S_OK : DMUS_E_NOT_FOUND;
248 static DWORD test_tool_wait_message(IDirectMusicTool *iface, DWORD timeout, DMUS_PMSG **msg)
250 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
251 DWORD ret = WAIT_FAILED;
255 AcquireSRWLockExclusive(&tool->lock);
256 if (!tool->message_count)
257 *msg = NULL;
258 else
260 UINT index = --tool->message_count;
261 *msg = tool->messages[index];
262 tool->messages[index] = NULL;
264 ReleaseSRWLockExclusive(&tool->lock);
266 if (*msg) return 0;
267 } while (!(ret = WaitForSingleObject(tool->message_event, timeout)));
269 return ret;
272 static BOOL missing_dmime(void)
274 IDirectMusicSegment8 *dms;
275 HRESULT hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
276 &IID_IDirectMusicSegment, (void**)&dms);
278 if (hr == S_OK && dms)
280 IDirectMusicSegment8_Release(dms);
281 return FALSE;
283 return TRUE;
286 static void test_COM_audiopath(void)
288 IDirectMusicAudioPath *dmap;
289 IUnknown *unk;
290 IDirectMusicPerformance8 *performance;
291 IDirectSoundBuffer *dsound;
292 IDirectSoundBuffer8 *dsound8;
293 IDirectSoundNotify *notify;
294 IDirectSound3DBuffer *dsound3d;
295 IKsPropertySet *propset;
296 ULONG refcount;
297 HRESULT hr;
298 DWORD buffer = 0;
300 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
301 &IID_IDirectMusicPerformance8, (void**)&performance);
302 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "DirectMusicPerformance create failed: %#lx\n", hr);
303 if (!performance) {
304 win_skip("IDirectMusicPerformance8 not available\n");
305 return;
307 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL,
308 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
309 ok(hr == S_OK || hr == DSERR_NODRIVER ||
310 broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED), /* Win 10 testbot */
311 "DirectMusicPerformance_InitAudio failed: %#lx\n", hr);
312 if (FAILED(hr)) {
313 skip("Audio failed to initialize\n");
314 return;
316 hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &dmap);
317 ok(hr == S_OK, "DirectMusicPerformance_GetDefaultAudioPath failed: %#lx\n", hr);
319 /* IDirectMusicObject and IPersistStream are not supported */
320 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IDirectMusicObject, (void**)&unk);
321 todo_wine ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n",
322 hr, unk);
323 if (unk) IUnknown_Release(unk);
324 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IPersistStream, (void**)&unk);
325 todo_wine ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n",
326 hr, unk);
327 if (unk) IUnknown_Release(unk);
329 /* Same refcount for all DirectMusicAudioPath interfaces */
330 refcount = IDirectMusicAudioPath_AddRef(dmap);
331 ok(refcount == 3, "refcount == %lu, expected 3\n", refcount);
333 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IUnknown, (void**)&unk);
334 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
335 ok(unk == (IUnknown*)dmap, "got %p, %p\n", unk, dmap);
336 refcount = IUnknown_AddRef(unk);
337 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
338 refcount = IUnknown_Release(unk);
340 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
341 0, &IID_IDirectSoundBuffer, (void**)&dsound);
342 ok(hr == S_OK, "Failed: %#lx\n", hr);
343 IDirectSoundBuffer_Release(dsound);
345 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
346 0, &IID_IDirectSoundBuffer8, (void**)&dsound8);
347 ok(hr == S_OK, "Failed: %#lx\n", hr);
348 IDirectSoundBuffer8_Release(dsound8);
350 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
351 0, &IID_IDirectSoundNotify, (void**)&notify);
352 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
354 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
355 0, &IID_IDirectSound3DBuffer, (void**)&dsound3d);
356 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
358 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
359 0, &IID_IKsPropertySet, (void**)&propset);
360 todo_wine ok(hr == S_OK, "Failed: %#lx\n", hr);
361 if (propset)
362 IKsPropertySet_Release(propset);
364 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
365 0, &IID_IUnknown, (void**)&unk);
366 ok(hr == S_OK, "Failed: %#lx\n", hr);
367 IUnknown_Release(unk);
369 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
370 0, &GUID_NULL, (void**)&unk);
371 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
373 while (IDirectMusicAudioPath_Release(dmap) > 1); /* performance has a reference too */
374 IDirectMusicPerformance8_CloseDown(performance);
375 IDirectMusicPerformance8_Release(performance);
378 static void test_COM_audiopathconfig(void)
380 IDirectMusicAudioPath *dmap = (IDirectMusicAudioPath*)0xdeadbeef;
381 IDirectMusicObject *dmo;
382 IPersistStream *ps;
383 IUnknown *unk;
384 ULONG refcount;
385 HRESULT hr;
387 /* COM aggregation */
388 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
389 &IID_IUnknown, (void**)&dmap);
390 if (hr == REGDB_E_CLASSNOTREG) {
391 win_skip("DirectMusicAudioPathConfig not registered\n");
392 return;
394 ok(hr == CLASS_E_NOAGGREGATION,
395 "DirectMusicAudioPathConfig create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
396 ok(!dmap, "dmap = %p\n", dmap);
398 /* IDirectMusicAudioPath not supported */
399 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
400 &IID_IDirectMusicAudioPath, (void**)&dmap);
401 todo_wine ok(FAILED(hr) && !dmap,
402 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
404 /* IDirectMusicObject and IPersistStream supported */
405 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
406 &IID_IPersistStream, (void**)&ps);
407 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
408 IPersistStream_Release(ps);
409 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
410 &IID_IDirectMusicObject, (void**)&dmo);
411 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
413 /* Same refcount for all DirectMusicObject interfaces */
414 refcount = IDirectMusicObject_AddRef(dmo);
415 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
417 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
418 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
419 refcount = IPersistStream_AddRef(ps);
420 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
421 IPersistStream_Release(ps);
423 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IUnknown, (void**)&unk);
424 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
425 refcount = IUnknown_AddRef(unk);
426 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
427 refcount = IUnknown_Release(unk);
429 /* IDirectMusicAudioPath still not supported */
430 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IDirectMusicAudioPath, (void**)&dmap);
431 todo_wine ok(FAILED(hr) && !dmap,
432 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
434 while (IDirectMusicObject_Release(dmo));
438 static void test_COM_graph(void)
440 IDirectMusicGraph *dmg = (IDirectMusicGraph*)0xdeadbeef;
441 IDirectMusicObject *dmo;
442 IPersistStream *ps;
443 IUnknown *unk;
444 ULONG refcount;
445 HRESULT hr;
447 /* COM aggregation */
448 hr = CoCreateInstance(&CLSID_DirectMusicGraph, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
449 &IID_IUnknown, (void**)&dmg);
450 ok(hr == CLASS_E_NOAGGREGATION,
451 "DirectMusicGraph create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
452 ok(!dmg, "dmg = %p\n", dmg);
454 /* Invalid RIID */
455 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory,
456 (void**)&dmg);
457 ok(hr == E_NOINTERFACE, "DirectMusicGraph create failed: %#lx, expected E_NOINTERFACE\n", hr);
459 /* Same refcount for all DirectMusicGraph interfaces */
460 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
461 &IID_IDirectMusicGraph, (void**)&dmg);
462 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
463 refcount = IDirectMusicGraph_AddRef(dmg);
464 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
466 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IDirectMusicObject, (void**)&dmo);
467 if (hr == E_NOINTERFACE) {
468 win_skip("DirectMusicGraph without IDirectMusicObject\n");
469 return;
471 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
472 refcount = IDirectMusicObject_AddRef(dmo);
473 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
474 refcount = IDirectMusicObject_Release(dmo);
476 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
477 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
478 refcount = IPersistStream_AddRef(ps);
479 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
480 refcount = IPersistStream_Release(ps);
482 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IUnknown, (void**)&unk);
483 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
484 refcount = IUnknown_AddRef(unk);
485 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
486 refcount = IUnknown_Release(unk);
488 while (IDirectMusicGraph_Release(dmg));
491 static void test_COM_segment(void)
493 IDirectMusicSegment8 *dms = (IDirectMusicSegment8*)0xdeadbeef;
494 IDirectMusicObject *dmo;
495 IPersistStream *stream;
496 IUnknown *unk;
497 ULONG refcount;
498 HRESULT hr;
500 /* COM aggregation */
501 hr = CoCreateInstance(&CLSID_DirectMusicSegment, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
502 &IID_IUnknown, (void**)&dms);
503 ok(hr == CLASS_E_NOAGGREGATION,
504 "DirectMusicSegment create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
505 ok(!dms, "dms = %p\n", dms);
507 /* Invalid RIID */
508 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
509 &IID_IDirectSound, (void**)&dms);
510 ok(hr == E_NOINTERFACE, "DirectMusicSegment create failed: %#lx, expected E_NOINTERFACE\n", hr);
512 /* Same refcount */
513 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
514 &IID_IDirectMusicSegment8, (void**)&dms);
515 if (hr == E_NOINTERFACE) {
516 win_skip("DirectMusicSegment without IDirectMusicSegment8\n");
517 return;
519 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
520 refcount = IDirectMusicSegment8_AddRef(dms);
521 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
522 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IDirectMusicObject, (void**)&dmo);
523 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
524 IDirectMusicSegment8_AddRef(dms);
525 refcount = IDirectMusicSegment8_Release(dms);
526 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
527 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IPersistStream, (void**)&stream);
528 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
529 refcount = IDirectMusicSegment8_Release(dms);
530 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
531 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IUnknown, (void**)&unk);
532 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
533 refcount = IUnknown_Release(unk);
534 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
535 refcount = IDirectMusicObject_Release(dmo);
536 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
537 refcount = IPersistStream_Release(stream);
538 ok (refcount == 1, "refcount == %lu, expected 1\n", refcount);
539 refcount = IDirectMusicSegment8_Release(dms);
540 ok (refcount == 0, "refcount == %lu, expected 0\n", refcount);
543 static void test_COM_segmentstate(void)
545 IDirectMusicSegmentState8 *dmss8 = (IDirectMusicSegmentState8*)0xdeadbeef;
546 IUnknown *unk;
547 ULONG refcount;
548 HRESULT hr;
550 /* COM aggregation */
551 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
552 &IID_IUnknown, (void**)&dmss8);
553 ok(hr == CLASS_E_NOAGGREGATION,
554 "DirectMusicSegmentState8 create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
555 ok(!dmss8, "dmss8 = %p\n", dmss8);
557 /* Invalid RIID */
558 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
559 &IID_IDirectMusicObject, (void**)&dmss8);
560 ok(hr == E_NOINTERFACE, "DirectMusicSegmentState8 create failed: %#lx, expected E_NOINTERFACE\n", hr);
562 /* Same refcount for all DirectMusicSegmentState interfaces */
563 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
564 &IID_IDirectMusicSegmentState8, (void**)&dmss8);
565 if (hr == E_NOINTERFACE) {
566 win_skip("DirectMusicSegmentState without IDirectMusicSegmentState8\n");
567 return;
569 ok(hr == S_OK, "DirectMusicSegmentState8 create failed: %#lx, expected S_OK\n", hr);
570 refcount = IDirectMusicSegmentState8_AddRef(dmss8);
571 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
573 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, (void**)&unk);
574 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
575 refcount = IUnknown_AddRef(unk);
576 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
577 refcount = IUnknown_Release(unk);
579 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, NULL);
580 ok(hr == E_POINTER, "got %#lx\n", hr);
582 while (IDirectMusicSegmentState8_Release(dmss8));
585 static void test_COM_track(void)
587 IDirectMusicTrack *dmt;
588 IDirectMusicTrack8 *dmt8;
589 IPersistStream *ps;
590 IUnknown *unk;
591 ULONG refcount;
592 HRESULT hr;
593 #define X(class) &CLSID_ ## class, #class
594 const struct {
595 REFCLSID clsid;
596 const char *name;
597 BOOL has_dmt8;
598 } class[] = {
599 { X(DirectMusicLyricsTrack), TRUE },
600 { X(DirectMusicMarkerTrack), FALSE },
601 { X(DirectMusicParamControlTrack), TRUE },
602 { X(DirectMusicSegmentTriggerTrack), TRUE },
603 { X(DirectMusicSeqTrack), TRUE },
604 { X(DirectMusicSysExTrack), TRUE },
605 { X(DirectMusicTempoTrack), TRUE },
606 { X(DirectMusicTimeSigTrack), FALSE },
607 { X(DirectMusicWaveTrack), TRUE }
609 #undef X
610 unsigned int i;
612 for (i = 0; i < ARRAY_SIZE(class); i++) {
613 trace("Testing %s\n", class[i].name);
614 /* COM aggregation */
615 dmt8 = (IDirectMusicTrack8*)0xdeadbeef;
616 hr = CoCreateInstance(class[i].clsid, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
617 (void**)&dmt8);
618 if (hr == REGDB_E_CLASSNOTREG) {
619 win_skip("%s not registered\n", class[i].name);
620 continue;
622 ok(hr == CLASS_E_NOAGGREGATION,
623 "%s create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", class[i].name, hr);
624 ok(!dmt8, "dmt8 = %p\n", dmt8);
626 /* Invalid RIID */
627 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
628 (void**)&dmt8);
629 ok(hr == E_NOINTERFACE, "%s create failed: %#lx, expected E_NOINTERFACE\n", class[i].name, hr);
631 /* Same refcount for all DirectMusicTrack interfaces */
632 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
633 (void**)&dmt);
634 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
635 refcount = IDirectMusicTrack_AddRef(dmt);
636 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
638 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
639 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
640 refcount = IPersistStream_AddRef(ps);
641 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
642 IPersistStream_Release(ps);
644 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IUnknown, (void**)&unk);
645 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
646 refcount = IUnknown_AddRef(unk);
647 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
648 refcount = IUnknown_Release(unk);
650 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
651 if (class[i].has_dmt8) {
652 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
653 refcount = IDirectMusicTrack8_AddRef(dmt8);
654 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
655 refcount = IDirectMusicTrack8_Release(dmt8);
656 } else {
657 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
658 refcount = IDirectMusicTrack_AddRef(dmt);
659 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
662 while (IDirectMusicTrack_Release(dmt));
666 static void test_audiopathconfig(void)
668 IDirectMusicObject *dmo;
669 IPersistStream *ps;
670 CLSID class = { 0 };
671 ULARGE_INTEGER size;
672 HRESULT hr;
674 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
675 &IID_IDirectMusicObject, (void**)&dmo);
676 if (hr == REGDB_E_CLASSNOTREG) {
677 win_skip("DirectMusicAudioPathConfig not registered\n");
678 return;
680 ok(hr == S_OK, "DirectMusicAudioPathConfig create failed: %#lx, expected S_OK\n", hr);
682 /* IPersistStream */
683 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
684 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
685 hr = IPersistStream_GetClassID(ps, &class);
686 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
687 ok(IsEqualGUID(&class, &CLSID_DirectMusicAudioPathConfig),
688 "Expected class CLSID_DirectMusicAudioPathConfig got %s\n", wine_dbgstr_guid(&class));
690 /* Unimplemented IPersistStream methods */
691 hr = IPersistStream_IsDirty(ps);
692 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
693 hr = IPersistStream_GetSizeMax(ps, &size);
694 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
695 hr = IPersistStream_Save(ps, NULL, TRUE);
696 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
698 while (IDirectMusicObject_Release(dmo));
701 static void test_graph(void)
703 IDirectMusicTool *tool1, *tool2, *tmp_tool;
704 IDirectMusicGraph *graph, *tmp_graph;
705 IPersistStream *ps;
706 CLSID class = { 0 };
707 ULARGE_INTEGER size;
708 DMUS_PMSG msg;
709 HRESULT hr;
711 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
712 &IID_IDirectMusicGraph, (void**)&graph);
713 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
715 /* IPersistStream */
716 hr = IDirectMusicGraph_QueryInterface(graph, &IID_IPersistStream, (void**)&ps);
717 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
718 hr = IPersistStream_GetClassID(ps, &class);
719 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
720 if (hr == S_OK)
721 ok(IsEqualGUID(&class, &CLSID_DirectMusicGraph),
722 "Expected class CLSID_DirectMusicGraph got %s\n", wine_dbgstr_guid(&class));
724 /* Unimplemented IPersistStream methods */
725 hr = IPersistStream_IsDirty(ps);
726 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
727 hr = IPersistStream_GetSizeMax(ps, &size);
728 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
729 hr = IPersistStream_Save(ps, NULL, TRUE);
730 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
732 IDirectMusicGraph_Release(graph);
735 hr = test_tool_create(NULL, 0, &tool1);
736 ok(hr == S_OK, "got %#lx\n", hr);
737 trace("created tool1 %p\n", tool1);
738 hr = test_tool_create(NULL, 0, &tool2);
739 ok(hr == S_OK, "got %#lx\n", hr);
740 trace("created tool2 %p\n", tool2);
742 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
743 &IID_IDirectMusicGraph, (void **)&graph);
744 ok(hr == S_OK, "got %#lx\n", hr);
747 hr = IDirectMusicGraph_InsertTool(graph, NULL, NULL, 0, -1);
748 ok(hr == E_POINTER, "got %#lx\n", hr);
750 /* InsertTool initializes the tool */
751 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
752 ok(hr == S_OK, "got %#lx\n", hr);
753 hr = test_tool_get_graph(tool1, &tmp_graph);
754 ok(hr == S_OK, "got %#lx\n", hr);
755 ok(graph == tmp_graph, "got %#lx\n", hr);
756 IDirectMusicGraph_Release(tmp_graph);
758 hr = IDirectMusicGraph_InsertTool(graph, tool2, NULL, 0, 1);
759 ok(hr == S_OK, "got %#lx\n", hr);
761 hr = IDirectMusicGraph_GetTool(graph, 0, NULL);
762 ok(hr == E_POINTER, "got %#lx\n", hr);
763 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
764 ok(hr == S_OK, "got %#lx\n", hr);
765 ok(tool1 == tmp_tool, "got %p\n", tmp_tool);
766 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
767 hr = IDirectMusicGraph_GetTool(graph, 1, &tmp_tool);
768 ok(hr == S_OK, "got %#lx\n", hr);
769 ok(tool2 == tmp_tool, "got %p\n", tmp_tool);
770 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
771 hr = IDirectMusicGraph_GetTool(graph, 2, &tmp_tool);
772 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
774 /* cannot insert the tool twice */
775 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
776 ok(hr == DMUS_E_ALREADY_EXISTS, "got %#lx\n", hr);
778 /* test removing the first tool */
779 hr = IDirectMusicGraph_RemoveTool(graph, NULL);
780 ok(hr == E_POINTER, "got %#lx\n", hr);
781 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
782 ok(hr == S_OK, "got %#lx\n", hr);
783 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
784 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
786 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
787 ok(hr == S_OK, "got %#lx\n", hr);
788 ok(tool2 == tmp_tool, "got %p\n", tmp_tool);
789 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
790 hr = IDirectMusicGraph_GetTool(graph, 1, &tmp_tool);
791 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
793 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
794 ok(hr == S_OK, "got %#lx\n", hr);
795 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
796 ok(hr == S_OK, "got %#lx\n", hr);
797 ok(tool1 == tmp_tool, "got %p\n", tmp_tool);
798 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
801 /* Test basic IDirectMusicGraph_StampPMsg usage */
802 hr = IDirectMusicGraph_StampPMsg(graph, NULL);
803 ok(hr == E_POINTER, "got %#lx\n", hr);
804 memset(&msg, 0, sizeof(msg));
805 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
806 ok(hr == S_OK, "got %#lx\n", hr);
807 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
808 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
810 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
811 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
812 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
813 ok(msg.dwFlags == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", msg.dwFlags);
814 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
815 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
816 ok(!msg.dwType, "got %#lx\n", msg.dwType);
817 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
818 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
819 ok(!msg.punkUser, "got %p\n", msg.punkUser);
821 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
822 ok(hr == S_OK, "got %#lx\n", hr);
823 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
824 ok(msg.pTool == tool2, "got %p\n", msg.pTool);
825 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
826 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
827 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
828 ok(!msg.pTool, "got %p\n", msg.pTool);
829 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
830 ok(hr == S_OK, "got %#lx\n", hr);
831 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
832 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
833 IDirectMusicGraph_Release(msg.pGraph);
834 msg.pGraph = NULL;
835 IDirectMusicGraph_Release(msg.pTool);
836 msg.pTool = NULL;
839 /* test StampPMsg with the wrong graph or innexistant tools */
840 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
841 &IID_IDirectMusicGraph, (void **)&tmp_graph);
842 ok(hr == S_OK, "got %#lx\n", hr);
844 msg.pGraph = tmp_graph;
845 IDirectMusicGraph_AddRef(msg.pGraph);
846 msg.pTool = tool1;
847 IDirectMusicTool_AddRef(msg.pTool);
848 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
849 ok(hr == S_OK, "got %#lx\n", hr);
850 ok(msg.pGraph == tmp_graph, "got %p\n", msg.pGraph);
851 ok(msg.pTool == tool2, "got %p\n", msg.pTool);
852 IDirectMusicGraph_Release(msg.pGraph);
853 msg.pGraph = NULL;
855 msg.pGraph = graph;
856 IDirectMusicGraph_AddRef(msg.pGraph);
857 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
858 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
859 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
860 ok(msg.pTool == NULL, "got %p\n", msg.pTool);
862 msg.pTool = tool2;
863 IDirectMusicTool_AddRef(msg.pTool);
864 hr = IDirectMusicGraph_InsertTool(tmp_graph, tool1, NULL, 0, 0);
865 ok(hr == S_OK, "got %#lx\n", hr);
866 hr = IDirectMusicGraph_InsertTool(tmp_graph, tool2, NULL, 0, 0);
867 ok(hr == S_OK, "got %#lx\n", hr);
868 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
869 ok(hr == S_OK, "got %#lx\n", hr);
870 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
871 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
872 IDirectMusicGraph_Release(msg.pGraph);
873 msg.pGraph = NULL;
875 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
876 ok(hr == S_OK, "got %#lx\n", hr);
877 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
878 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
879 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
880 ok(msg.pTool == NULL, "got %p\n", msg.pTool);
882 IDirectMusicGraph_Release(tmp_graph);
885 IDirectMusicGraph_Release(graph);
886 IDirectMusicTool_Release(tool2);
887 IDirectMusicTool_Release(tool1);
890 static void test_segment(void)
892 IDirectMusicSegment *dms;
893 IPersistStream *ps;
894 CLSID class = { 0 };
895 ULARGE_INTEGER size;
896 HRESULT hr;
898 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
899 &IID_IDirectMusicSegment, (void**)&dms);
900 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
902 /* IPersistStream */
903 hr = IDirectMusicSegment_QueryInterface(dms, &IID_IPersistStream, (void**)&ps);
904 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
905 hr = IPersistStream_GetClassID(ps, &class);
906 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
907 if (hr == S_OK)
908 ok(IsEqualGUID(&class, &CLSID_DirectMusicSegment),
909 "Expected class CLSID_DirectMusicSegment got %s\n", wine_dbgstr_guid(&class));
911 /* Unimplemented IPersistStream methods */
912 hr = IPersistStream_IsDirty(ps);
913 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
914 hr = IPersistStream_GetSizeMax(ps, &size);
915 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
916 hr = IPersistStream_Save(ps, NULL, TRUE);
917 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
919 while (IDirectMusicSegment_Release(dms));
922 static void _add_track(IDirectMusicSegment8 *seg, REFCLSID class, const char *name, DWORD group)
924 IDirectMusicTrack *track;
925 HRESULT hr;
927 hr = CoCreateInstance(class, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
928 (void**)&track);
929 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", name, hr);
930 hr = IDirectMusicSegment8_InsertTrack(seg, track, group);
931 if (group)
932 ok(hr == S_OK, "Inserting %s failed: %#lx, expected S_OK\n", name, hr);
933 else
934 ok(hr == E_INVALIDARG, "Inserting %s failed: %#lx, expected E_INVALIDARG\n", name, hr);
935 IDirectMusicTrack_Release(track);
938 #define add_track(seg, class, group) _add_track(seg, &CLSID_DirectMusic ## class, #class, group)
940 static void _expect_track(IDirectMusicSegment8 *seg, REFCLSID expect, const char *name, DWORD group,
941 DWORD index, BOOL ignore_guid)
943 IDirectMusicTrack *track;
944 IPersistStream *ps;
945 CLSID class;
946 HRESULT hr;
948 if (ignore_guid)
949 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, group, index, &track);
950 else
951 hr = IDirectMusicSegment8_GetTrack(seg, expect, group, index, &track);
952 if (!expect) {
953 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
954 return;
957 ok(hr == S_OK, "GetTrack failed: %#lx, expected S_OK\n", hr);
958 hr = IDirectMusicTrack_QueryInterface(track, &IID_IPersistStream, (void**)&ps);
959 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
960 hr = IPersistStream_GetClassID(ps, &class);
961 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
962 ok(IsEqualGUID(&class, expect), "For group %#lx index %lu: Expected class %s got %s\n",
963 group, index, name, wine_dbgstr_guid(&class));
965 IPersistStream_Release(ps);
966 IDirectMusicTrack_Release(track);
969 #define expect_track(seg, class, group, index) \
970 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, TRUE)
971 #define expect_guid_track(seg, class, group, index) \
972 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, FALSE)
974 static void test_gettrack(void)
976 IDirectMusicSegment8 *seg;
977 IDirectMusicTrack *track;
978 HRESULT hr;
980 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
981 &IID_IDirectMusicSegment8, (void**)&seg);
982 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
984 add_track(seg, LyricsTrack, 0x0); /* failure */
985 add_track(seg, LyricsTrack, 0x1); /* idx 0 group 1 */
986 add_track(seg, ParamControlTrack, 0x3); /* idx 1 group 1, idx 0 group 2 */
987 add_track(seg, SegmentTriggerTrack, 0x2); /* idx 1 group 2 */
988 add_track(seg, SeqTrack, 0x1); /* idx 2 group 1 */
989 add_track(seg, TempoTrack, 0x7); /* idx 3 group 1, idx 2 group 2, idx 0 group 3 */
990 add_track(seg, WaveTrack, 0xffffffff); /* idx 4 group 1, idx 3 group 2, idx 1 group 3 */
992 /* Ignore GUID in GetTrack */
993 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, 0, 0, &track);
994 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
996 expect_track(seg, LyricsTrack, 0x1, 0);
997 expect_track(seg, ParamControlTrack, 0x1, 1);
998 expect_track(seg, SeqTrack, 0x1, 2);
999 expect_track(seg, TempoTrack, 0x1, 3);
1000 expect_track(seg, WaveTrack, 0x1, 4);
1001 _expect_track(seg, NULL, "", 0x1, 5, TRUE);
1002 _expect_track(seg, NULL, "", 0x1, DMUS_SEG_ANYTRACK, TRUE);
1003 expect_track(seg, ParamControlTrack, 0x2, 0);
1004 expect_track(seg, WaveTrack, 0x80000000, 0);
1005 expect_track(seg, SegmentTriggerTrack, 0x3, 2); /* groups 1+2 combined index */
1006 expect_track(seg, SeqTrack, 0x3, 3); /* groups 1+2 combined index */
1007 expect_track(seg, TempoTrack, 0x7, 4); /* groups 1+2+3 combined index */
1008 expect_track(seg, TempoTrack, 0xffffffff, 4); /* all groups combined index */
1009 _expect_track(seg, NULL, "", 0xffffffff, DMUS_SEG_ANYTRACK, TRUE);
1011 /* Use the GUID in GetTrack */
1012 hr = IDirectMusicSegment8_GetTrack(seg, &CLSID_DirectMusicLyricsTrack, 0, 0, &track);
1013 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
1015 expect_guid_track(seg, LyricsTrack, 0x1, 0);
1016 expect_guid_track(seg, ParamControlTrack, 0x1, 0);
1017 expect_guid_track(seg, SeqTrack, 0x1, 0);
1018 expect_guid_track(seg, TempoTrack, 0x1, 0);
1019 expect_guid_track(seg, ParamControlTrack, 0x2, 0);
1020 expect_guid_track(seg, SegmentTriggerTrack, 0x3, 0);
1021 expect_guid_track(seg, SeqTrack, 0x3, 0);
1022 expect_guid_track(seg, TempoTrack, 0x7, 0);
1023 expect_guid_track(seg, TempoTrack, 0xffffffff, 0);
1025 IDirectMusicSegment8_Release(seg);
1028 static void test_segment_param(void)
1030 IDirectMusicSegment8 *seg;
1031 char buf[64];
1032 HRESULT hr;
1034 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1035 &IID_IDirectMusicSegment8, (void **)&seg);
1036 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
1038 add_track(seg, LyricsTrack, 0x1); /* no params */
1039 add_track(seg, SegmentTriggerTrack, 0x1); /* all params "supported" */
1041 hr = IDirectMusicSegment8_GetParam(seg, NULL, 0x1, 0, 0, NULL, buf);
1042 ok(hr == E_POINTER, "GetParam failed: %#lx, expected E_POINTER\n", hr);
1043 hr = IDirectMusicSegment8_SetParam(seg, NULL, 0x1, 0, 0, buf);
1044 todo_wine ok(hr == E_POINTER, "SetParam failed: %#lx, expected E_POINTER\n", hr);
1046 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, NULL, buf);
1047 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
1048 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, NULL, buf);
1049 ok(hr == DMUS_E_TRACK_NOT_FOUND, "GetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
1050 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ANYTRACK, 0,
1051 NULL, buf);
1052 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
1054 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, buf);
1055 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
1056 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, buf);
1057 todo_wine ok(hr == DMUS_E_TRACK_NOT_FOUND,
1058 "SetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
1059 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ALLTRACKS,
1060 0, buf);
1061 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
1063 IDirectMusicSegment8_Release(seg);
1066 static void expect_getparam(IDirectMusicTrack *track, REFGUID type, const char *name,
1067 HRESULT expect)
1069 HRESULT hr;
1070 char buf[64] = { 0 };
1072 hr = IDirectMusicTrack_GetParam(track, type, 0, NULL, buf);
1073 ok(hr == expect, "GetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
1076 static void expect_setparam(IDirectMusicTrack *track, REFGUID type, const char *name,
1077 HRESULT expect)
1079 HRESULT hr;
1080 char buf[64] = { 0 };
1082 hr = IDirectMusicTrack_SetParam(track, type, 0, buf);
1083 ok(hr == expect, "SetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
1086 static void test_track(void)
1088 IDirectMusicTrack *dmt;
1089 IDirectMusicTrack8 *dmt8;
1090 IPersistStream *ps;
1091 CLSID classid;
1092 ULARGE_INTEGER size;
1093 HRESULT hr;
1094 #define X(guid) &guid, #guid
1095 const struct {
1096 REFGUID type;
1097 const char *name;
1098 } param_types[] = {
1099 { X(GUID_BandParam) },
1100 { X(GUID_ChordParam) },
1101 { X(GUID_Clear_All_Bands) },
1102 { X(GUID_CommandParam) },
1103 { X(GUID_CommandParam2) },
1104 { X(GUID_CommandParamNext) },
1105 { X(GUID_ConnectToDLSCollection) },
1106 { X(GUID_Disable_Auto_Download) },
1107 { X(GUID_DisableTempo) },
1108 { X(GUID_DisableTimeSig) },
1109 { X(GUID_Download) },
1110 { X(GUID_DownloadToAudioPath) },
1111 { X(GUID_Enable_Auto_Download) },
1112 { X(GUID_EnableTempo) },
1113 { X(GUID_EnableTimeSig) },
1114 { X(GUID_IDirectMusicBand) },
1115 { X(GUID_IDirectMusicChordMap) },
1116 { X(GUID_IDirectMusicStyle) },
1117 { X(GUID_MuteParam) },
1118 { X(GUID_Play_Marker) },
1119 { X(GUID_RhythmParam) },
1120 { X(GUID_SeedVariations) },
1121 { X(GUID_StandardMIDIFile) },
1122 { X(GUID_TempoParam) },
1123 { X(GUID_TimeSignature) },
1124 { X(GUID_Unload) },
1125 { X(GUID_UnloadFromAudioPath) },
1126 { X(GUID_Valid_Start_Time) },
1127 { X(GUID_Variations) },
1128 { X(GUID_NULL) }
1130 #undef X
1131 #define X(class) &CLSID_ ## class, #class
1132 const struct {
1133 REFCLSID clsid;
1134 const char *name;
1135 /* bitfield with supported param types */
1136 unsigned int has_params;
1137 } class[] = {
1138 { X(DirectMusicLyricsTrack), 0 },
1139 { X(DirectMusicMarkerTrack), 0x8080000 },
1140 { X(DirectMusicParamControlTrack), 0 },
1141 { X(DirectMusicSegmentTriggerTrack), 0x3fffffff },
1142 { X(DirectMusicSeqTrack), ~0 }, /* param methods not implemented */
1143 { X(DirectMusicSysExTrack), ~0 }, /* param methods not implemented */
1144 { X(DirectMusicTempoTrack), 0x802100 },
1145 { X(DirectMusicTimeSigTrack), 0x1004200 },
1146 { X(DirectMusicWaveTrack), 0x6001c80 }
1148 #undef X
1149 unsigned int i, j;
1151 for (i = 0; i < ARRAY_SIZE(class); i++) {
1152 trace("Testing %s\n", class[i].name);
1153 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
1154 (void**)&dmt);
1155 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
1157 /* IDirectMusicTrack */
1158 if (class[i].has_params != ~0) {
1159 for (j = 0; j < ARRAY_SIZE(param_types); j++) {
1160 hr = IDirectMusicTrack_IsParamSupported(dmt, param_types[j].type);
1161 if (class[i].has_params & (1 << j)) {
1162 ok(hr == S_OK, "IsParamSupported(%s) failed: %#lx, expected S_OK\n",
1163 param_types[j].name, hr);
1164 if (class[i].clsid == &CLSID_DirectMusicSegmentTriggerTrack) {
1165 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1166 DMUS_E_GET_UNSUPPORTED);
1167 expect_setparam(dmt, param_types[j].type, param_types[j].name, S_OK);
1168 } else if (class[i].clsid == &CLSID_DirectMusicMarkerTrack)
1169 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1170 DMUS_E_SET_UNSUPPORTED);
1171 else if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
1172 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1173 DMUS_E_GET_UNSUPPORTED);
1174 } else {
1175 ok(hr == DMUS_E_TYPE_UNSUPPORTED,
1176 "IsParamSupported(%s) failed: %#lx, expected DMUS_E_TYPE_UNSUPPORTED\n",
1177 param_types[j].name, hr);
1178 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1179 DMUS_E_GET_UNSUPPORTED);
1180 if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
1181 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1182 DMUS_E_TYPE_UNSUPPORTED);
1183 else
1184 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1185 DMUS_E_SET_UNSUPPORTED);
1188 /* GetParam / SetParam for IsParamSupported supported types */
1189 if (class[i].clsid == &CLSID_DirectMusicTimeSigTrack) {
1190 expect_getparam(dmt, &GUID_DisableTimeSig, "GUID_DisableTimeSig",
1191 DMUS_E_GET_UNSUPPORTED);
1192 expect_getparam(dmt, &GUID_EnableTimeSig, "GUID_EnableTimeSig",
1193 DMUS_E_GET_UNSUPPORTED);
1194 expect_setparam(dmt, &GUID_TimeSignature, "GUID_TimeSignature",
1195 DMUS_E_SET_UNSUPPORTED);
1196 } else if (class[i].clsid == &CLSID_DirectMusicTempoTrack) {
1197 expect_getparam(dmt, &GUID_DisableTempo, "GUID_DisableTempo",
1198 DMUS_E_GET_UNSUPPORTED);
1199 expect_getparam(dmt, &GUID_EnableTempo, "GUID_EnableTempo",
1200 DMUS_E_GET_UNSUPPORTED);
1203 } else {
1204 hr = IDirectMusicTrack_GetParam(dmt, NULL, 0, NULL, NULL);
1205 ok(hr == E_NOTIMPL, "IDirectMusicTrack_GetParam failed: %#lx\n", hr);
1206 hr = IDirectMusicTrack_SetParam(dmt, NULL, 0, NULL);
1207 ok(hr == E_NOTIMPL, "IDirectMusicTrack_SetParam failed: %#lx\n", hr);
1208 hr = IDirectMusicTrack_IsParamSupported(dmt, NULL);
1209 ok(hr == E_NOTIMPL, "IDirectMusicTrack_IsParamSupported failed: %#lx\n", hr);
1211 hr = IDirectMusicTrack_IsParamSupported(dmt, &GUID_IDirectMusicStyle);
1212 ok(hr == E_NOTIMPL, "got: %#lx\n", hr);
1214 if (class[i].clsid != &CLSID_DirectMusicMarkerTrack &&
1215 class[i].clsid != &CLSID_DirectMusicTimeSigTrack) {
1216 hr = IDirectMusicTrack_AddNotificationType(dmt, NULL);
1217 ok(hr == E_NOTIMPL, "IDirectMusicTrack_AddNotificationType failed: %#lx\n", hr);
1218 hr = IDirectMusicTrack_RemoveNotificationType(dmt, NULL);
1219 ok(hr == E_NOTIMPL, "IDirectMusicTrack_RemoveNotificationType failed: %#lx\n", hr);
1221 hr = IDirectMusicTrack_Clone(dmt, 0, 0, NULL);
1222 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack_Clone failed: %#lx\n", hr);
1224 /* IDirectMusicTrack8 */
1225 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
1226 if (hr == S_OK) {
1227 hr = IDirectMusicTrack8_PlayEx(dmt8, NULL, 0, 0, 0, 0, NULL, NULL, 0);
1228 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_PlayEx failed: %#lx\n", hr);
1229 if (class[i].has_params == ~0) {
1230 hr = IDirectMusicTrack8_GetParamEx(dmt8, NULL, 0, NULL, NULL, NULL, 0);
1231 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_GetParamEx failed: %#lx\n", hr);
1232 hr = IDirectMusicTrack8_SetParamEx(dmt8, NULL, 0, NULL, NULL, 0);
1233 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_SetParamEx failed: %#lx\n", hr);
1235 hr = IDirectMusicTrack8_Compose(dmt8, NULL, 0, NULL);
1236 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Compose failed: %#lx\n", hr);
1237 hr = IDirectMusicTrack8_Join(dmt8, NULL, 0, NULL, 0, NULL);
1238 if (class[i].clsid == &CLSID_DirectMusicTempoTrack)
1239 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
1240 else
1241 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
1242 IDirectMusicTrack8_Release(dmt8);
1245 /* IPersistStream */
1246 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
1247 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1248 hr = IPersistStream_GetClassID(ps, &classid);
1249 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
1250 ok(IsEqualGUID(&classid, class[i].clsid),
1251 "Expected class %s got %s\n", class[i].name, wine_dbgstr_guid(&classid));
1252 hr = IPersistStream_IsDirty(ps);
1253 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
1255 /* Unimplemented IPersistStream methods */
1256 hr = IPersistStream_GetSizeMax(ps, &size);
1257 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
1258 hr = IPersistStream_Save(ps, NULL, TRUE);
1259 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
1261 while (IDirectMusicTrack_Release(dmt));
1265 struct chunk {
1266 FOURCC id;
1267 DWORD size;
1268 FOURCC type;
1271 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
1273 /* Generate a RIFF file format stream from an array of FOURCC ids.
1274 RIFF and LIST need to be followed by the form type respectively list type,
1275 followed by the chunks of the list and terminated with 0. */
1276 static IStream *gen_riff_stream(const FOURCC *ids)
1278 static const LARGE_INTEGER zero;
1279 int level = -1;
1280 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
1281 char riff[1024];
1282 char *p = riff;
1283 struct chunk *ck;
1284 IStream *stream;
1286 do {
1287 ck = (struct chunk *)p;
1288 ck->id = *ids++;
1289 switch (ck->id) {
1290 case 0:
1291 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
1292 level--;
1293 break;
1294 case FOURCC_LIST:
1295 case FOURCC_RIFF:
1296 level++;
1297 sizes[level] = &ck->size;
1298 ck->type = *ids++;
1299 p += sizeof(*ck);
1300 break;
1301 case DMUS_FOURCC_GUID_CHUNK:
1302 ck->size = sizeof(GUID_NULL);
1303 p += CHUNK_HDR_SIZE;
1304 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
1305 p += ck->size;
1306 break;
1307 case DMUS_FOURCC_VERSION_CHUNK:
1309 DMUS_VERSION ver = {5, 8};
1311 ck->size = sizeof(ver);
1312 p += CHUNK_HDR_SIZE;
1313 memcpy(p, &ver, sizeof(ver));
1314 p += ck->size;
1315 break;
1317 default:
1319 /* Just convert the FOURCC id to a WCHAR string */
1320 WCHAR *s;
1322 ck->size = 5 * sizeof(WCHAR);
1323 p += CHUNK_HDR_SIZE;
1324 s = (WCHAR *)p;
1325 s[0] = (char)(ck->id);
1326 s[1] = (char)(ck->id >> 8);
1327 s[2] = (char)(ck->id >> 16);
1328 s[3] = (char)(ck->id >> 24);
1329 s[4] = 0;
1330 p += ck->size;
1333 } while (level >= 0);
1335 ck = (struct chunk *)riff;
1336 CreateStreamOnHGlobal(NULL, TRUE, &stream);
1337 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
1338 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1340 return stream;
1343 static void test_parsedescriptor(void)
1345 IDirectMusicObject *dmo;
1346 IStream *stream;
1347 DMUS_OBJECTDESC desc;
1348 HRESULT hr;
1349 DWORD valid;
1350 unsigned int i;
1351 /* fourcc ~0 will be replaced later on */
1352 FOURCC alldesc[] =
1354 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
1355 DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK, DMUS_FOURCC_UCMT_CHUNK,
1356 DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, 0
1358 FOURCC dupes[] =
1360 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
1361 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
1362 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, 0,
1363 FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
1365 FOURCC empty[] = {FOURCC_RIFF, ~0, 0};
1366 FOURCC inam[] = {FOURCC_RIFF, ~0, FOURCC_LIST, ~0, mmioFOURCC('I','N','A','M'), 0, 0};
1367 FOURCC noriff[] = {mmioFOURCC('J','U','N','K'), 0};
1368 #define X(class) &CLSID_ ## class, #class
1369 #define Y(form) form, #form
1370 const struct {
1371 REFCLSID clsid;
1372 const char *class;
1373 FOURCC form;
1374 const char *name;
1375 BOOL needs_size;
1376 } forms[] = {
1377 { X(DirectMusicSegment), Y(DMUS_FOURCC_SEGMENT_FORM), FALSE },
1378 { X(DirectMusicSegment), Y(mmioFOURCC('W','A','V','E')), FALSE },
1379 { X(DirectMusicAudioPathConfig), Y(DMUS_FOURCC_AUDIOPATH_FORM), TRUE },
1380 { X(DirectMusicGraph), Y(DMUS_FOURCC_TOOLGRAPH_FORM), TRUE },
1382 #undef X
1383 #undef Y
1385 for (i = 0; i < ARRAY_SIZE(forms); i++) {
1386 trace("Testing %s / %s\n", forms[i].class, forms[i].name);
1387 hr = CoCreateInstance(forms[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
1388 (void **)&dmo);
1389 if (hr != S_OK) {
1390 win_skip("Could not create %s object: %#lx\n", forms[i].class, hr);
1391 return;
1394 /* Nothing loaded */
1395 memset(&desc, 0, sizeof(desc));
1396 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1397 if (forms[i].needs_size) {
1398 todo_wine ok(hr == E_INVALIDARG, "GetDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1399 desc.dwSize = sizeof(desc);
1400 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1402 ok(hr == S_OK, "GetDescriptor failed: %#lx, expected S_OK\n", hr);
1403 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1404 desc.dwValidData);
1405 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1406 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1408 /* Empty RIFF stream */
1409 empty[1] = forms[i].form;
1410 stream = gen_riff_stream(empty);
1411 memset(&desc, 0, sizeof(desc));
1412 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1413 if (forms[i].needs_size) {
1414 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1415 desc.dwSize = sizeof(desc);
1416 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1418 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1419 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1420 desc.dwValidData);
1421 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1422 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1424 /* NULL pointers */
1425 memset(&desc, 0, sizeof(desc));
1426 desc.dwSize = sizeof(desc);
1427 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
1428 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1429 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
1430 if (forms[i].needs_size)
1431 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1432 else
1433 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1434 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, NULL);
1435 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1436 IStream_Release(stream);
1438 /* Wrong form */
1439 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
1440 stream = gen_riff_stream(empty);
1441 memset(&desc, 0, sizeof(desc));
1442 desc.dwSize = sizeof(desc);
1443 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1444 if (forms[i].needs_size)
1445 ok(hr == DMUS_E_CHUNKNOTFOUND,
1446 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1447 else
1448 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
1449 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
1450 IStream_Release(stream);
1452 /* Not a RIFF stream */
1453 stream = gen_riff_stream(noriff);
1454 memset(&desc, 0, sizeof(desc));
1455 desc.dwSize = sizeof(desc);
1456 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1457 if (forms[i].needs_size)
1458 ok(hr == DMUS_E_CHUNKNOTFOUND,
1459 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1460 else
1461 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
1462 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
1463 IStream_Release(stream);
1465 /* All desc chunks */
1466 alldesc[1] = forms[i].form;
1467 stream = gen_riff_stream(alldesc);
1468 memset(&desc, 0, sizeof(desc));
1469 desc.dwSize = sizeof(desc);
1470 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1471 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1472 valid = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_VERSION;
1473 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1474 valid |= DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY;
1475 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1476 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1477 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1478 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
1479 wine_dbgstr_guid(&desc.guidClass));
1480 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
1481 "Got version %lu.%lu, expected 5.8\n", desc.vVersion.dwVersionMS,
1482 desc.vVersion.dwVersionLS);
1483 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1484 ok(!lstrcmpW(desc.wszName, L"UNAM"), "Got name '%s', expected 'UNAM'\n",
1485 wine_dbgstr_w(desc.wszName));
1486 IStream_Release(stream);
1488 /* Duplicated chunks */
1489 dupes[1] = forms[i].form;
1490 stream = gen_riff_stream(dupes);
1491 memset(&desc, 0, sizeof(desc));
1492 desc.dwSize = sizeof(desc);
1493 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1494 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1495 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1496 IStream_Release(stream);
1498 /* UNFO list with INAM */
1499 inam[1] = forms[i].form;
1500 inam[3] = DMUS_FOURCC_UNFO_LIST;
1501 stream = gen_riff_stream(inam);
1502 memset(&desc, 0, sizeof(desc));
1503 desc.dwSize = sizeof(desc);
1504 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1505 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1506 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1507 desc.dwValidData);
1508 IStream_Release(stream);
1510 /* INFO list with INAM */
1511 inam[3] = DMUS_FOURCC_INFO_LIST;
1512 stream = gen_riff_stream(inam);
1513 memset(&desc, 0, sizeof(desc));
1514 desc.dwSize = sizeof(desc);
1515 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1516 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1517 valid = DMUS_OBJ_CLASS;
1518 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1519 valid |= DMUS_OBJ_NAME;
1520 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1521 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1522 ok(!lstrcmpW(desc.wszName, L"I"), "Got name '%s', expected 'I'\n",
1523 wine_dbgstr_w(desc.wszName));
1524 IStream_Release(stream);
1526 IDirectMusicObject_Release(dmo);
1530 static void test_performance_tool(void)
1532 IDirectMusicPerformance *performance;
1533 IDirectMusicGraph *graph;
1534 IDirectMusicTool *tool;
1535 DWORD value, types[1];
1536 DMUS_PMSG msg = {0};
1537 HRESULT hr;
1539 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1540 &IID_IDirectMusicPerformance, (void **)&performance);
1541 ok(hr == S_OK, "got %#lx\n", hr);
1543 check_interface(performance, &IID_IDirectMusicTool8, FALSE);
1545 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicTool, (void **)&tool);
1546 ok(hr == S_OK, "got %#lx\n", hr);
1547 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
1548 ok(hr == S_OK, "got %#lx\n", hr);
1550 hr = IDirectMusicTool_Init(tool, graph);
1551 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1552 value = 0xdeadbeef;
1553 hr = IDirectMusicTool_GetMsgDeliveryType(tool, &value);
1554 ok(hr == S_OK, "got %#lx\n", hr);
1555 ok(value == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", value);
1556 value = 0xdeadbeef;
1557 hr = IDirectMusicTool_GetMediaTypeArraySize(tool, &value);
1558 ok(hr == S_OK, "got %#lx\n", hr);
1559 ok(value == 0, "got %#lx\n", value);
1560 hr = IDirectMusicTool_GetMediaTypes(tool, (DWORD **)&types, 64);
1561 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1562 hr = IDirectMusicTool_ProcessPMsg(tool, performance, &msg);
1563 ok(hr == DMUS_S_FREE, "got %#lx\n", hr);
1564 hr = IDirectMusicTool_Flush(tool, performance, &msg, 0);
1565 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
1567 IDirectMusicGraph_Release(graph);
1568 IDirectMusicTool_Release(tool);
1570 IDirectMusicPerformance_Release(performance);
1573 static void test_performance_graph(void)
1575 IDirectMusicPerformance *performance;
1576 IDirectMusicGraph *graph, *tmp_graph;
1577 IDirectMusicTool *tool, *tmp_tool;
1578 DMUS_PMSG msg;
1579 HRESULT hr;
1581 hr = test_tool_create(NULL, 0, &tool);
1582 ok(hr == S_OK, "got %#lx\n", hr);
1584 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1585 &IID_IDirectMusicPerformance, (void **)&performance);
1586 ok(hr == S_OK, "got %#lx\n", hr);
1589 /* performance exposes a graph interface but it's not an actual toolgraph */
1590 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
1591 ok(hr == S_OK, "got %#lx\n", hr);
1592 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
1593 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1594 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
1595 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1596 hr = IDirectMusicGraph_RemoveTool(graph, tool);
1597 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1599 /* test IDirectMusicGraph_StampPMsg usage */
1600 hr = IDirectMusicGraph_StampPMsg(graph, NULL);
1601 ok(hr == E_POINTER, "got %#lx\n", hr);
1602 memset(&msg, 0, sizeof(msg));
1603 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1604 ok(hr == S_OK, "got %#lx\n", hr);
1605 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1606 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
1607 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
1609 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
1610 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
1611 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
1612 ok(msg.dwFlags == DMUS_PMSGF_TOOL_QUEUE, "got %#lx\n", msg.dwFlags);
1613 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
1614 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
1615 ok(!msg.dwType, "got %#lx\n", msg.dwType);
1616 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
1617 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
1618 ok(!msg.punkUser, "got %p\n", msg.punkUser);
1620 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1621 ok(hr == S_OK, "got %#lx\n", hr);
1622 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1623 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
1624 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
1626 IDirectMusicTool_Release(msg.pTool);
1627 msg.pTool = NULL;
1629 IDirectMusicGraph_Release(graph);
1632 /* performance doesn't have a default embedded toolgraph */
1633 hr = IDirectMusicPerformance_GetGraph(performance, &graph);
1634 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
1637 /* test adding a graph to the performance */
1638 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1639 &IID_IDirectMusicGraph, (void **)&graph);
1640 ok(hr == S_OK, "got %#lx\n", hr);
1641 hr = IDirectMusicPerformance_SetGraph(performance, graph);
1642 ok(hr == S_OK, "got %#lx\n", hr);
1644 hr = IDirectMusicPerformance_GetGraph(performance, &tmp_graph);
1645 ok(hr == S_OK, "got %#lx\n", hr);
1646 ok(tmp_graph == graph, "got %p\n", graph);
1647 IDirectMusicGraph_Release(tmp_graph);
1649 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
1650 ok(hr == S_OK, "got %#lx\n", hr);
1652 IDirectMusicGraph_Release(graph);
1655 /* test IDirectMusicGraph_StampPMsg usage */
1656 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
1657 ok(hr == S_OK, "got %#lx\n", hr);
1659 memset(&msg, 0, sizeof(msg));
1660 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1661 ok(hr == S_OK, "got %#lx\n", hr);
1662 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1663 ok(msg.pTool == tool, "got %p\n", msg.pTool);
1665 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
1666 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
1667 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
1668 ok(msg.dwFlags == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", msg.dwFlags);
1669 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
1670 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
1671 ok(!msg.dwType, "got %#lx\n", msg.dwType);
1672 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
1673 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
1674 ok(!msg.punkUser, "got %p\n", msg.punkUser);
1676 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1677 ok(hr == S_OK, "got %#lx\n", hr);
1678 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1679 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
1680 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
1682 IDirectMusicTool_Release(msg.pTool);
1683 msg.pTool = NULL;
1685 IDirectMusicGraph_Release(graph);
1688 IDirectMusicPerformance_Release(performance);
1689 IDirectMusicTool_Release(tool);
1692 static void test_performance_time(void)
1694 IDirectMusicPerformance *performance;
1695 REFERENCE_TIME init_time, time;
1696 IReferenceClock *clock;
1697 MUSIC_TIME music_time;
1698 IDirectMusic *dmusic;
1699 HRESULT hr;
1701 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1702 &IID_IDirectMusicPerformance, (void **)&performance);
1703 ok(hr == S_OK, "got %#lx\n", hr);
1706 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, NULL);
1707 ok(hr == E_POINTER, "got %#lx\n", hr);
1708 time = 0xdeadbeef;
1709 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, &time);
1710 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
1711 ok(time == 0, "got %I64d\n", time);
1713 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, 0, NULL);
1714 ok(hr == E_POINTER, "got %#lx\n", hr);
1715 music_time = 0xdeadbeef;
1716 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, 0, &music_time);
1717 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
1718 ok(music_time == 0, "got %ld\n", music_time);
1721 dmusic = NULL;
1722 hr = IDirectMusicPerformance_Init(performance, &dmusic, NULL, NULL);
1723 ok(hr == S_OK, "got %#lx\n", hr);
1724 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock);
1725 ok(hr == S_OK, "got %#lx\n", hr);
1726 IDirectMusic_Release(dmusic);
1727 hr = IReferenceClock_GetTime(clock, &init_time);
1728 ok(hr == S_OK, "got %#lx\n", hr);
1729 IReferenceClock_Release(clock);
1732 time = 0xdeadbeef;
1733 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, &time);
1734 ok(hr == S_OK, "got %#lx\n", hr);
1735 ok(time - init_time <= 100 * 10000, "got %I64d\n", time - init_time);
1736 init_time = time;
1738 time = 0xdeadbeef;
1739 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 1, &time);
1740 ok(hr == S_OK, "got %#lx\n", hr);
1741 ok(time - init_time >= 6505, "got %I64d\n", time - init_time);
1742 ok(time - init_time <= 6515, "got %I64d\n", time - init_time);
1743 time = 0xdeadbeef;
1744 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 1000, &time);
1745 ok(hr == S_OK, "got %#lx\n", hr);
1746 ok(time - init_time >= 1000 * 6505, "got %I64d\n", time - init_time);
1747 ok(time - init_time <= 1000 * 6515, "got %I64d\n", time - init_time);
1748 time = 0xdeadbeef;
1749 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 2000, &time);
1750 ok(hr == S_OK, "got %#lx\n", hr);
1751 ok(time - init_time >= 2000 * 6505, "got %I64d\n", time - init_time);
1752 ok(time - init_time <= 2000 * 6515, "got %I64d\n", time - init_time);
1754 music_time = 0xdeadbeef;
1755 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time, &music_time);
1756 ok(hr == S_OK, "got %#lx\n", hr);
1757 ok(music_time == 0, "got %ld\n", music_time);
1758 music_time = 0xdeadbeef;
1759 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time + 1000 * 6510, &music_time);
1760 ok(hr == S_OK, "got %#lx\n", hr);
1761 ok(music_time == 1000, "got %ld\n", music_time);
1762 music_time = 0xdeadbeef;
1763 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time + 2000 * 6510, &music_time);
1764 ok(hr == S_OK, "got %#lx\n", hr);
1765 ok(music_time == 2000, "got %ld\n", music_time);
1767 time = 0xdeadbeef;
1768 music_time = 0xdeadbeef;
1769 hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
1770 ok(hr == S_OK, "got %#lx\n", hr);
1771 ok(time - init_time <= 200 * 10000, "got %I64d\n", time - init_time);
1772 ok(music_time == (time - init_time) / 6510, "got %ld\n", music_time);
1775 hr = IDirectMusicPerformance_CloseDown(performance);
1776 ok(hr == S_OK, "got %#lx\n", hr);
1778 IDirectMusicPerformance_Release(performance);
1782 static void test_performance_pmsg(void)
1784 static const DWORD delivery_flags[] = {DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGF_TOOL_ATTIME};
1785 static const DWORD message_types[] = {DMUS_PMSGT_MIDI, DMUS_PMSGT_USER};
1786 IDirectMusicPerformance *performance;
1787 IDirectMusicGraph *graph, *performance_graph;
1788 IDirectMusicTool *tool;
1789 DMUS_PMSG *msg, *clone;
1790 MUSIC_TIME music_time;
1791 REFERENCE_TIME time;
1792 HRESULT hr;
1793 DWORD ret;
1794 UINT i;
1796 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
1797 ok(hr == S_OK, "got %#lx\n", hr);
1799 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1800 &IID_IDirectMusicPerformance, (void **)&performance);
1801 ok(hr == S_OK, "got %#lx\n", hr);
1802 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&performance_graph);
1803 ok(hr == S_OK, "got %#lx\n", hr);
1806 hr = IDirectMusicPerformance_AllocPMsg(performance, 0, NULL);
1807 ok(hr == E_POINTER, "got %#lx\n", hr);
1808 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG) - 1, &msg);
1809 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
1811 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1812 ok(hr == S_OK, "got %#lx\n", hr);
1813 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1814 ok(!msg->rtTime, "got %I64d\n", msg->rtTime);
1815 ok(!msg->mtTime, "got %ld\n", msg->mtTime);
1816 ok(!msg->dwFlags, "got %#lx\n", msg->dwFlags);
1817 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1818 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1819 ok(!msg->dwType, "got %#lx\n", msg->dwType);
1820 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1821 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1822 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1824 hr = IDirectMusicPerformance_SendPMsg(performance, NULL);
1825 ok(hr == E_POINTER, "got %#lx\n", hr);
1826 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1827 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
1829 hr = IDirectMusicPerformance_FreePMsg(performance, NULL);
1830 ok(hr == E_POINTER, "got %#lx\n", hr);
1831 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1832 ok(hr == S_OK, "got %#lx\n", hr);
1835 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
1836 ok(hr == S_OK, "got %#lx\n", hr);
1838 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1839 &IID_IDirectMusicGraph, (void **)&graph);
1840 ok(hr == S_OK, "got %#lx\n", hr);
1841 hr = IDirectMusicPerformance_SetGraph(performance, graph);
1842 ok(hr == S_OK, "got %#lx\n", hr);
1843 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
1844 ok(hr == S_OK, "got %#lx\n", hr);
1845 IDirectMusicGraph_Release(graph);
1847 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1848 ok(hr == S_OK, "got %#lx\n", hr);
1849 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1850 ok(!msg->rtTime, "got %I64d\n", msg->rtTime);
1851 ok(!msg->mtTime, "got %ld\n", msg->mtTime);
1852 ok(!msg->dwFlags, "got %#lx\n", msg->dwFlags);
1853 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1854 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1855 ok(!msg->pTool, "got %p\n", msg->pTool);
1856 ok(!msg->pGraph, "got %p\n", msg->pGraph);
1857 ok(!msg->dwType, "got %#lx\n", msg->dwType);
1858 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1859 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1860 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1861 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1862 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
1864 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, NULL);
1865 ok(hr == E_POINTER, "got %#lx\n", hr);
1866 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, NULL, &clone);
1867 ok(hr == E_POINTER, "got %#lx\n", hr);
1868 clone = NULL;
1869 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, &clone);
1870 ok(hr == S_OK, "got %#lx\n", hr);
1871 ok(clone != NULL, "got %p\n", clone);
1873 msg->mtTime = 500;
1874 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
1875 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1876 ok(hr == S_OK, "got %#lx\n", hr);
1877 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1878 ok(hr == DMUS_E_ALREADY_SENT, "got %#lx\n", hr);
1879 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1880 ok(hr == DMUS_E_CANNOT_FREE, "got %#lx\n", hr);
1882 hr = IDirectMusicPerformance_FreePMsg(performance, clone);
1883 ok(hr == S_OK, "got %#lx\n", hr);
1886 /* SendPMsg skips all the tools unless messages are stamped beforehand */
1888 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1889 ok(hr == S_OK, "got %#lx\n", hr);
1890 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1891 msg->mtTime = 0;
1892 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
1893 msg->dwType = DMUS_PMSGT_USER;
1894 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1895 ok(hr == S_OK, "got %#lx\n", hr);
1897 ret = test_tool_wait_message(tool, 10, &msg);
1898 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
1899 ok(!msg, "got %p\n", msg);
1902 /* SendPMsg converts music time to reference time if it is missing */
1904 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1905 ok(hr == S_OK, "got %#lx\n", hr);
1906 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1907 msg->mtTime = 500;
1908 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
1909 msg->dwType = DMUS_PMSGT_USER;
1910 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
1911 ok(hr == S_OK, "got %#lx\n", hr);
1912 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1913 ok(hr == S_OK, "got %#lx\n", hr);
1915 ret = test_tool_wait_message(tool, 50, &msg);
1916 ok(!ret, "got %#lx\n", ret);
1917 ok(msg != NULL, "got %p\n", msg);
1919 time = 0xdeadbeef;
1920 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, msg->mtTime, &time);
1921 ok(hr == S_OK, "got %#lx\n", hr);
1922 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1923 ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1924 ok(msg->mtTime == 500, "got %ld\n", msg->mtTime);
1925 ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1926 ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1927 ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
1928 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1929 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1930 ok(msg->pTool == tool, "got %p\n", msg->pTool);
1931 ok(msg->pGraph == performance_graph, "got %p\n", msg->pGraph);
1932 ok(msg->dwType == DMUS_PMSGT_USER, "got %#lx\n", msg->dwType);
1933 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1934 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1935 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1937 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1938 ok(hr == S_OK, "got %#lx\n", hr);
1941 /* SendPMsg converts reference time to music time if it is missing */
1943 hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
1944 ok(hr == S_OK, "got %#lx\n", hr);
1946 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1947 ok(hr == S_OK, "got %#lx\n", hr);
1948 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1949 msg->rtTime = time;
1950 msg->dwFlags = DMUS_PMSGF_REFTIME;
1951 msg->dwType = DMUS_PMSGT_USER;
1952 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
1953 ok(hr == S_OK, "got %#lx\n", hr);
1954 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1955 ok(hr == S_OK, "got %#lx\n", hr);
1957 ret = test_tool_wait_message(tool, 50, &msg);
1958 ok(!ret, "got %#lx\n", ret);
1959 ok(msg != NULL, "got %p\n", msg);
1961 music_time = 0xdeadbeef;
1962 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, msg->rtTime, &music_time);
1963 ok(hr == S_OK, "got %#lx\n", hr);
1964 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1965 ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1966 ok(msg->mtTime == music_time, "got %ld\n", msg->mtTime);
1967 ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1968 ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1969 ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
1970 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1971 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1972 ok(msg->pTool == tool, "got %p\n", msg->pTool);
1973 ok(msg->pGraph == performance_graph, "got %p\n", msg->pGraph);
1974 ok(msg->dwType == DMUS_PMSGT_USER, "got %#lx\n", msg->dwType);
1975 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1976 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1977 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1979 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1980 ok(hr == S_OK, "got %#lx\n", hr);
1983 for (i = 0; i < ARRAY_SIZE(delivery_flags); i++)
1985 DWORD duration = 0;
1987 hr = IDirectMusicPerformance_GetTime(performance, &time, NULL);
1988 ok(hr == S_OK, "got %#lx\n", hr);
1989 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1990 ok(hr == S_OK, "got %#lx\n", hr);
1991 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1992 msg->rtTime = time + 150 * 10000;
1993 msg->dwFlags = DMUS_PMSGF_REFTIME;
1994 msg->dwType = DMUS_PMSGT_USER;
1995 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
1996 ok(hr == S_OK, "got %#lx\n", hr);
1998 msg->dwFlags &= ~(DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME);
1999 msg->dwFlags |= delivery_flags[i];
2001 duration -= GetTickCount();
2002 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2003 ok(hr == S_OK, "got %#lx\n", hr);
2004 msg = NULL;
2005 ret = test_tool_wait_message(tool, 1000, &msg);
2006 ok(!ret, "got %#lx\n", ret);
2007 ok(msg != NULL, "got %p\n", msg);
2008 duration += GetTickCount();
2010 if (msg) hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2011 ok(hr == S_OK, "got %#lx\n", hr);
2013 switch (delivery_flags[i])
2015 case DMUS_PMSGF_TOOL_IMMEDIATE: ok(duration <= 50, "got %lu\n", duration); break;
2016 case DMUS_PMSGF_TOOL_QUEUE: ok(duration >= 50 && duration <= 125, "got %lu\n", duration); break;
2017 case DMUS_PMSGF_TOOL_ATTIME: ok(duration >= 125 && duration <= 500, "got %lu\n", duration); break;
2022 hr = IDirectMusicPerformance_CloseDown(performance);
2023 ok(hr == S_OK, "got %#lx\n", hr);
2026 IDirectMusicGraph_Release(performance_graph);
2028 IDirectMusicPerformance_Release(performance);
2029 IDirectMusicTool_Release(tool);
2032 #define check_dmus_notification_pmsg(a, b, c) check_dmus_notification_pmsg_(__LINE__, a, b, c)
2033 static void check_dmus_notification_pmsg_(int line, DMUS_NOTIFICATION_PMSG *msg,
2034 const GUID *type, DWORD option)
2036 ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTIFICATION,
2037 "got dwType %#lx\n", msg->dwType);
2038 ok_(__FILE__, line)(IsEqualGUID(&msg->guidNotificationType, type),
2039 "got guidNotificationType %s\n", debugstr_guid(&msg->guidNotificationType));
2040 ok_(__FILE__, line)(msg->dwNotificationOption == option,
2041 "got dwNotificationOption %#lx\n", msg->dwNotificationOption);
2042 ok_(__FILE__, line)(!msg->dwField1, "got dwField1 %lu\n", msg->dwField1);
2043 ok_(__FILE__, line)(!msg->dwField2, "got dwField2 %lu\n", msg->dwField2);
2045 if (!IsEqualGUID(&msg->guidNotificationType, &GUID_NOTIFICATION_SEGMENT))
2046 ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser);
2047 else
2049 check_interface_(line, msg->punkUser, &IID_IDirectMusicSegmentState, TRUE);
2050 check_interface_(line, msg->punkUser, &IID_IDirectMusicSegmentState8, TRUE);
2054 static void test_notification_pmsg(void)
2056 static const DWORD message_types[] =
2058 DMUS_PMSGT_DIRTY,
2059 DMUS_PMSGT_NOTIFICATION,
2060 DMUS_PMSGT_WAVE,
2062 IDirectMusicPerformance *performance;
2063 DMUS_NOTIFICATION_PMSG *notif;
2064 IDirectMusicSegment *segment;
2065 IDirectMusicGraph *graph;
2066 IDirectMusicTool *tool;
2067 DMUS_PMSG *msg;
2068 HRESULT hr;
2069 DWORD ret;
2071 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
2072 ok(hr == S_OK, "got %#lx\n", hr);
2074 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2075 &IID_IDirectMusicPerformance, (void **)&performance);
2076 ok(hr == S_OK, "got %#lx\n", hr);
2078 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
2079 &IID_IDirectMusicGraph, (void **)&graph);
2080 ok(hr == S_OK, "got %#lx\n", hr);
2081 hr = IDirectMusicPerformance_SetGraph(performance, graph);
2082 ok(hr == S_OK, "got %#lx\n", hr);
2083 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
2084 ok(hr == S_OK, "got %#lx\n", hr);
2085 IDirectMusicGraph_Release(graph);
2087 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
2088 ok(hr == S_OK, "got %#lx\n", hr);
2091 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
2092 &IID_IDirectMusicSegment, (void **)&segment);
2093 ok(hr == S_OK, "got %#lx\n", hr);
2095 hr = IDirectMusicSegment8_Download((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
2096 ok(hr == S_OK, "got %#lx\n", hr);
2097 hr = IDirectMusicSegment8_Unload((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
2098 ok(hr == S_OK, "got %#lx\n", hr);
2100 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
2101 ok(hr == S_OK, "got %#lx\n", hr);
2103 ret = test_tool_wait_message(tool, 500, &msg);
2104 todo_wine ok(!ret, "got %#lx\n", ret);
2105 if (!ret)
2107 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2108 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2109 ok(hr == S_OK, "got %#lx\n", hr);
2112 ret = test_tool_wait_message(tool, 500, &msg);
2113 todo_wine ok(!ret, "got %#lx\n", ret);
2114 if (!ret)
2116 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2117 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2118 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2121 ret = test_tool_wait_message(tool, 100, &msg);
2122 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2123 ok(!msg, "got %p\n", msg);
2126 /* AddNotificationType is necessary to receive notification messages */
2128 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
2129 ok(hr == S_OK, "got %#lx\n", hr);
2130 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
2131 ok(hr == S_OK, "got %#lx\n", hr);
2133 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
2134 ok(hr == S_OK, "got %#lx\n", hr);
2136 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2137 todo_wine ok(!ret, "got %#lx\n", ret);
2138 if (!ret)
2140 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
2141 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2142 ok(hr == S_OK, "got %#lx\n", hr);
2145 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2146 todo_wine ok(!ret, "got %#lx\n", ret);
2147 if (!ret)
2149 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
2150 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2151 ok(hr == S_OK, "got %#lx\n", hr);
2154 ret = test_tool_wait_message(tool, 500, &msg);
2155 todo_wine ok(!ret, "got %#lx\n", ret);
2156 if (!ret)
2158 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2159 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2160 ok(hr == S_OK, "got %#lx\n", hr);
2163 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2164 todo_wine ok(!ret, "got %#lx\n", ret);
2165 if (!ret)
2167 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
2168 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2169 ok(hr == S_OK, "got %#lx\n", hr);
2172 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2173 todo_wine ok(!ret, "got %#lx\n", ret);
2174 if (!ret)
2176 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
2177 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2178 ok(hr == S_OK, "got %#lx\n", hr);
2181 ret = test_tool_wait_message(tool, 500, &msg);
2182 todo_wine ok(!ret, "got %#lx\n", ret);
2183 if (!ret)
2185 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2186 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2187 ok(hr == S_OK, "got %#lx\n", hr);
2190 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2191 todo_wine ok(!ret, "got %#lx\n", ret);
2192 if (!ret)
2194 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
2195 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2196 ok(hr == S_OK, "got %#lx\n", hr);
2199 ret = test_tool_wait_message(tool, 100, &msg);
2200 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2201 ok(!msg, "got %p\n", msg);
2203 IDirectMusicSegment_Release(segment);
2205 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
2206 ok(hr == S_OK, "got %#lx\n", hr);
2207 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
2208 ok(hr == S_OK, "got %#lx\n", hr);
2211 /* notification messages are also queued for direct access */
2213 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2214 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2215 if (hr == S_OK)
2217 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
2218 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2219 ok(hr == S_OK, "got %#lx\n", hr);
2222 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2223 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2224 if (hr == S_OK)
2226 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
2227 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2228 ok(hr == S_OK, "got %#lx\n", hr);
2231 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2232 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2233 if (hr == S_OK)
2235 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
2236 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2237 ok(hr == S_OK, "got %#lx\n", hr);
2240 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2241 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2242 if (hr == S_OK)
2244 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
2245 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2246 ok(hr == S_OK, "got %#lx\n", hr);
2249 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2250 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2251 if (hr == S_OK)
2253 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
2254 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2255 ok(hr == S_OK, "got %#lx\n", hr);
2258 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2259 ok(hr == S_FALSE, "got %#lx\n", hr);
2262 hr = IDirectMusicPerformance_CloseDown(performance);
2263 ok(hr == S_OK, "got %#lx\n", hr);
2265 IDirectMusicPerformance_Release(performance);
2266 IDirectMusicTool_Release(tool);
2269 static void test_wave_pmsg(void)
2271 static const DWORD message_types[] =
2273 DMUS_PMSGT_DIRTY,
2274 DMUS_PMSGT_WAVE,
2276 IDirectMusicPerformance *performance;
2277 IDirectMusicSegment *segment;
2278 IDirectMusicLoader8 *loader;
2279 IDirectMusicGraph *graph;
2280 WCHAR test_wav[MAX_PATH];
2281 IDirectMusicTool *tool;
2282 DMUS_WAVE_PMSG *wave;
2283 MUSIC_TIME length;
2284 DMUS_PMSG *msg;
2285 HRESULT hr;
2286 DWORD ret;
2288 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
2289 ok(hr == S_OK, "got %#lx\n", hr);
2291 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2292 &IID_IDirectMusicPerformance, (void **)&performance);
2293 ok(hr == S_OK, "got %#lx\n", hr);
2295 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
2296 &IID_IDirectMusicGraph, (void **)&graph);
2297 ok(hr == S_OK, "got %#lx\n", hr);
2298 hr = IDirectMusicPerformance_SetGraph(performance, graph);
2299 ok(hr == S_OK, "got %#lx\n", hr);
2300 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
2301 ok(hr == S_OK, "got %#lx\n", hr);
2302 IDirectMusicGraph_Release(graph);
2304 hr = IDirectMusicPerformance8_InitAudio((IDirectMusicPerformance8 *)performance, NULL, NULL, NULL,
2305 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
2306 ok(hr == S_OK, "got %#lx\n", hr);
2309 load_resource(L"test.wav", test_wav);
2311 hr = CoCreateInstance(&CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC_SERVER,
2312 &IID_IDirectMusicLoader8, (void **)&loader);
2313 ok(hr == S_OK, "got %#lx\n", hr);
2314 hr = IDirectMusicLoader8_LoadObjectFromFile(loader, &CLSID_DirectMusicSegment,
2315 &IID_IDirectMusicSegment, test_wav, (void **)&segment);
2316 ok(hr == S_OK, "got %#lx\n", hr);
2317 IDirectMusicLoader8_Release(loader);
2320 length = 0xdeadbeef;
2321 hr = IDirectMusicSegment_GetLength(segment, &length);
2322 ok(hr == S_OK, "got %#lx\n", hr);
2323 todo_wine ok(length == 1, "got %lu\n", length);
2326 /* without Download, no DMUS_PMSGT_WAVE is sent */
2328 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
2329 ok(hr == S_OK, "got %#lx\n", hr);
2331 ret = test_tool_wait_message(tool, 500, &msg);
2332 todo_wine ok(!ret, "got %#lx\n", ret);
2333 if (!ret)
2335 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
2336 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2337 ok(hr == S_OK, "got %#lx\n", hr);
2340 ret = test_tool_wait_message(tool, 500, &msg);
2341 todo_wine ok(!ret, "got %#lx\n", ret);
2342 if (!ret)
2344 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
2345 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2346 ok(hr == S_OK, "got %#lx\n", hr);
2349 ret = test_tool_wait_message(tool, 100, &msg);
2350 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2351 ok(!msg, "got %p\n", msg);
2354 /* a single DMUS_PMSGT_WAVE message is sent with punkUser set */
2356 hr = IDirectMusicSegment8_Download((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
2357 ok(hr == S_OK, "got %#lx\n", hr);
2359 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
2360 ok(hr == S_OK, "got %#lx\n", hr);
2362 ret = test_tool_wait_message(tool, 500, &msg);
2363 todo_wine ok(!ret, "got %#lx\n", ret);
2364 if (!ret)
2366 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
2367 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2368 ok(hr == S_OK, "got %#lx\n", hr);
2371 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&wave);
2372 todo_wine ok(!ret, "got %#lx\n", ret);
2373 if (!ret)
2375 ok(wave->dwType == DMUS_PMSGT_WAVE, "got %p\n", wave);
2376 ok(!!wave->punkUser, "got %p\n", wave->punkUser);
2377 ok(wave->rtStartOffset == 0, "got %I64d\n", wave->rtStartOffset);
2378 ok(wave->rtDuration == 1000000, "got %I64d\n", wave->rtDuration);
2379 ok(wave->lOffset == 0, "got %lu\n", wave->lOffset);
2380 ok(wave->lVolume == 0, "got %lu\n", wave->lVolume);
2381 ok(wave->lPitch == 0, "got %lu\n", wave->lPitch);
2382 ok(wave->bFlags == 0, "got %#x\n", wave->bFlags);
2383 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)wave);
2384 ok(hr == S_OK, "got %#lx\n", hr);
2387 ret = test_tool_wait_message(tool, 500, &msg);
2388 todo_wine ok(!ret, "got %#lx\n", ret);
2389 if (!ret)
2391 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
2392 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2393 ok(hr == S_OK, "got %#lx\n", hr);
2396 hr = IDirectMusicSegment8_Unload((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
2397 ok(hr == S_OK, "got %#lx\n", hr);
2399 ret = test_tool_wait_message(tool, 100, &msg);
2400 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2401 ok(!msg, "got %p\n", msg);
2404 IDirectMusicSegment_Release(segment);
2407 hr = IDirectMusicPerformance_CloseDown(performance);
2408 ok(hr == S_OK, "got %#lx\n", hr);
2410 IDirectMusicPerformance_Release(performance);
2411 IDirectMusicTool_Release(tool);
2414 START_TEST(dmime)
2416 CoInitialize(NULL);
2418 if (missing_dmime())
2420 skip("dmime not available\n");
2421 CoUninitialize();
2422 return;
2424 test_COM_audiopath();
2425 test_COM_audiopathconfig();
2426 test_COM_graph();
2427 test_COM_segment();
2428 test_COM_segmentstate();
2429 test_COM_track();
2430 test_audiopathconfig();
2431 test_graph();
2432 test_segment();
2433 test_gettrack();
2434 test_segment_param();
2435 test_track();
2436 test_parsedescriptor();
2437 test_performance_tool();
2438 test_performance_graph();
2439 test_performance_time();
2440 test_performance_pmsg();
2441 test_notification_pmsg();
2442 test_wave_pmsg();
2444 CoUninitialize();