dmime/tests: Add some DMUS_NOTIFICATION_PMSG tests.
[wine.git] / dlls / dmime / tests / dmime.c
blobe011488d126aca339c1e6e69e80b1c0837d7ac63
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 struct test_tool
60 IDirectMusicTool IDirectMusicTool_iface;
61 LONG ref;
63 IDirectMusicGraph *graph;
64 const DWORD *types;
65 DWORD types_count;
67 SRWLOCK lock;
68 HANDLE message_event;
69 DMUS_PMSG *messages[32];
70 UINT message_count;
73 static DMUS_PMSG *test_tool_push_msg(struct test_tool *tool, DMUS_PMSG *msg)
75 AcquireSRWLockExclusive(&tool->lock);
76 ok(tool->message_count < ARRAY_SIZE(tool->messages),
77 "got %u messages\n", tool->message_count + 1);
78 if (tool->message_count < ARRAY_SIZE(tool->messages))
80 memmove(tool->messages + 1, tool->messages,
81 tool->message_count * sizeof(*tool->messages));
82 tool->messages[0] = msg;
83 tool->message_count++;
84 msg = NULL;
86 ReleaseSRWLockExclusive(&tool->lock);
88 return msg;
91 static struct test_tool *impl_from_IDirectMusicTool(IDirectMusicTool *iface)
93 return CONTAINING_RECORD(iface, struct test_tool, IDirectMusicTool_iface);
96 static HRESULT WINAPI test_tool_QueryInterface(IDirectMusicTool *iface, REFIID iid, void **out)
98 if (IsEqualGUID(iid, &IID_IUnknown)
99 || IsEqualGUID(iid, &IID_IDirectMusicTool))
101 IDirectMusicTool_AddRef(iface);
102 *out = iface;
103 return S_OK;
106 ok(IsEqualGUID(iid, &IID_IDirectMusicTool8) || IsEqualGUID(iid, &IID_IPersistStream),
107 "got iid %s\n", debugstr_guid(iid));
108 *out = NULL;
109 return E_NOINTERFACE;
112 static ULONG WINAPI test_tool_AddRef(IDirectMusicTool *iface)
114 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
115 return InterlockedIncrement(&tool->ref);
118 static ULONG WINAPI test_tool_Release(IDirectMusicTool *iface)
120 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
121 ULONG ref = InterlockedDecrement(&tool->ref);
123 if (!ref)
125 if (tool->graph) IDirectMusicGraph_Release(tool->graph);
126 ok(!tool->message_count, "got %p\n", &tool->message_count);
127 CloseHandle(tool->message_event);
128 free(tool);
131 return ref;
134 static HRESULT WINAPI test_tool_Init(IDirectMusicTool *iface, IDirectMusicGraph *graph)
136 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
137 if ((tool->graph = graph)) IDirectMusicGraph_AddRef(tool->graph);
138 return S_OK;
141 static HRESULT WINAPI test_tool_GetMsgDeliveryType(IDirectMusicTool *iface, DWORD *type)
143 *type = DMUS_PMSGF_TOOL_IMMEDIATE;
144 return S_OK;
147 static HRESULT WINAPI test_tool_GetMediaTypeArraySize(IDirectMusicTool *iface, DWORD *size)
149 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
150 *size = tool->types_count;
151 return S_OK;
154 static HRESULT WINAPI test_tool_GetMediaTypes(IDirectMusicTool *iface, DWORD **types, DWORD size)
156 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
157 UINT i;
158 for (i = 0; i < tool->types_count; i++) (*types)[i] = tool->types[i];
159 return S_OK;
162 static HRESULT WINAPI test_tool_ProcessPMsg(IDirectMusicTool *iface, IDirectMusicPerformance *performance, DMUS_PMSG *msg)
164 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
165 DMUS_PMSG *clone;
166 HRESULT hr;
168 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, &clone);
169 ok(hr == S_OK, "got %#lx\n", hr);
170 clone = test_tool_push_msg(tool, clone);
171 ok(!clone, "got %p\n", clone);
172 SetEvent(tool->message_event);
174 hr = IDirectMusicGraph_StampPMsg(msg->pGraph, msg);
175 ok(hr == S_OK, "got %#lx\n", hr);
177 return DMUS_S_REQUEUE;
180 static HRESULT WINAPI test_tool_Flush(IDirectMusicTool *iface, IDirectMusicPerformance *performance,
181 DMUS_PMSG *msg, REFERENCE_TIME time)
183 ok(0, "unexpected %s\n", __func__);
184 return S_OK;
187 static IDirectMusicToolVtbl test_tool_vtbl =
189 test_tool_QueryInterface,
190 test_tool_AddRef,
191 test_tool_Release,
192 test_tool_Init,
193 test_tool_GetMsgDeliveryType,
194 test_tool_GetMediaTypeArraySize,
195 test_tool_GetMediaTypes,
196 test_tool_ProcessPMsg,
197 test_tool_Flush,
200 static HRESULT test_tool_create(const DWORD *types, DWORD types_count,
201 IDirectMusicTool **ret_iface)
203 struct test_tool *tool;
205 *ret_iface = NULL;
206 if (!(tool = calloc(1, sizeof(*tool)))) return E_OUTOFMEMORY;
207 tool->IDirectMusicTool_iface.lpVtbl = &test_tool_vtbl;
208 tool->ref = 1;
210 tool->types = types;
211 tool->types_count = types_count;
212 tool->message_event = CreateEventW(NULL, FALSE, FALSE, NULL);
213 ok(!!tool->message_event, "CreateEventW failed, error %lu\n", GetLastError());
215 *ret_iface = &tool->IDirectMusicTool_iface;
216 return S_OK;
219 static HRESULT test_tool_get_graph(IDirectMusicTool *iface, IDirectMusicGraph **graph)
221 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
222 if ((*graph = tool->graph)) IDirectMusicGraph_AddRef(tool->graph);
223 return tool->graph ? S_OK : DMUS_E_NOT_FOUND;
226 static DWORD test_tool_wait_message(IDirectMusicTool *iface, DWORD timeout, DMUS_PMSG **msg)
228 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
229 DWORD ret = WAIT_FAILED;
233 AcquireSRWLockExclusive(&tool->lock);
234 if (!tool->message_count)
235 *msg = NULL;
236 else
238 UINT index = --tool->message_count;
239 *msg = tool->messages[index];
240 tool->messages[index] = NULL;
242 ReleaseSRWLockExclusive(&tool->lock);
244 if (*msg) return 0;
245 } while (!(ret = WaitForSingleObject(tool->message_event, timeout)));
247 return ret;
250 static BOOL missing_dmime(void)
252 IDirectMusicSegment8 *dms;
253 HRESULT hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
254 &IID_IDirectMusicSegment, (void**)&dms);
256 if (hr == S_OK && dms)
258 IDirectMusicSegment8_Release(dms);
259 return FALSE;
261 return TRUE;
264 static void test_COM_audiopath(void)
266 IDirectMusicAudioPath *dmap;
267 IUnknown *unk;
268 IDirectMusicPerformance8 *performance;
269 IDirectSoundBuffer *dsound;
270 IDirectSoundBuffer8 *dsound8;
271 IDirectSoundNotify *notify;
272 IDirectSound3DBuffer *dsound3d;
273 IKsPropertySet *propset;
274 ULONG refcount;
275 HRESULT hr;
276 DWORD buffer = 0;
278 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
279 &IID_IDirectMusicPerformance8, (void**)&performance);
280 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "DirectMusicPerformance create failed: %#lx\n", hr);
281 if (!performance) {
282 win_skip("IDirectMusicPerformance8 not available\n");
283 return;
285 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL,
286 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
287 ok(hr == S_OK || hr == DSERR_NODRIVER ||
288 broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED), /* Win 10 testbot */
289 "DirectMusicPerformance_InitAudio failed: %#lx\n", hr);
290 if (FAILED(hr)) {
291 skip("Audio failed to initialize\n");
292 return;
294 hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &dmap);
295 ok(hr == S_OK, "DirectMusicPerformance_GetDefaultAudioPath failed: %#lx\n", hr);
297 /* IDirectMusicObject and IPersistStream are not supported */
298 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IDirectMusicObject, (void**)&unk);
299 todo_wine ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n",
300 hr, unk);
301 if (unk) IUnknown_Release(unk);
302 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IPersistStream, (void**)&unk);
303 todo_wine ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n",
304 hr, unk);
305 if (unk) IUnknown_Release(unk);
307 /* Same refcount for all DirectMusicAudioPath interfaces */
308 refcount = IDirectMusicAudioPath_AddRef(dmap);
309 ok(refcount == 3, "refcount == %lu, expected 3\n", refcount);
311 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IUnknown, (void**)&unk);
312 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
313 ok(unk == (IUnknown*)dmap, "got %p, %p\n", unk, dmap);
314 refcount = IUnknown_AddRef(unk);
315 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
316 refcount = IUnknown_Release(unk);
318 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
319 0, &IID_IDirectSoundBuffer, (void**)&dsound);
320 ok(hr == S_OK, "Failed: %#lx\n", hr);
321 IDirectSoundBuffer_Release(dsound);
323 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
324 0, &IID_IDirectSoundBuffer8, (void**)&dsound8);
325 ok(hr == S_OK, "Failed: %#lx\n", hr);
326 IDirectSoundBuffer8_Release(dsound8);
328 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
329 0, &IID_IDirectSoundNotify, (void**)&notify);
330 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
332 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
333 0, &IID_IDirectSound3DBuffer, (void**)&dsound3d);
334 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
336 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
337 0, &IID_IKsPropertySet, (void**)&propset);
338 todo_wine ok(hr == S_OK, "Failed: %#lx\n", hr);
339 if (propset)
340 IKsPropertySet_Release(propset);
342 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
343 0, &IID_IUnknown, (void**)&unk);
344 ok(hr == S_OK, "Failed: %#lx\n", hr);
345 IUnknown_Release(unk);
347 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
348 0, &GUID_NULL, (void**)&unk);
349 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
351 while (IDirectMusicAudioPath_Release(dmap) > 1); /* performance has a reference too */
352 IDirectMusicPerformance8_CloseDown(performance);
353 IDirectMusicPerformance8_Release(performance);
356 static void test_COM_audiopathconfig(void)
358 IDirectMusicAudioPath *dmap = (IDirectMusicAudioPath*)0xdeadbeef;
359 IDirectMusicObject *dmo;
360 IPersistStream *ps;
361 IUnknown *unk;
362 ULONG refcount;
363 HRESULT hr;
365 /* COM aggregation */
366 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
367 &IID_IUnknown, (void**)&dmap);
368 if (hr == REGDB_E_CLASSNOTREG) {
369 win_skip("DirectMusicAudioPathConfig not registered\n");
370 return;
372 ok(hr == CLASS_E_NOAGGREGATION,
373 "DirectMusicAudioPathConfig create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
374 ok(!dmap, "dmap = %p\n", dmap);
376 /* IDirectMusicAudioPath not supported */
377 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
378 &IID_IDirectMusicAudioPath, (void**)&dmap);
379 todo_wine ok(FAILED(hr) && !dmap,
380 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
382 /* IDirectMusicObject and IPersistStream supported */
383 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
384 &IID_IPersistStream, (void**)&ps);
385 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
386 IPersistStream_Release(ps);
387 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
388 &IID_IDirectMusicObject, (void**)&dmo);
389 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
391 /* Same refcount for all DirectMusicObject interfaces */
392 refcount = IDirectMusicObject_AddRef(dmo);
393 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
395 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
396 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
397 refcount = IPersistStream_AddRef(ps);
398 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
399 IPersistStream_Release(ps);
401 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IUnknown, (void**)&unk);
402 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
403 refcount = IUnknown_AddRef(unk);
404 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
405 refcount = IUnknown_Release(unk);
407 /* IDirectMusicAudioPath still not supported */
408 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IDirectMusicAudioPath, (void**)&dmap);
409 todo_wine ok(FAILED(hr) && !dmap,
410 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
412 while (IDirectMusicObject_Release(dmo));
416 static void test_COM_graph(void)
418 IDirectMusicGraph *dmg = (IDirectMusicGraph*)0xdeadbeef;
419 IDirectMusicObject *dmo;
420 IPersistStream *ps;
421 IUnknown *unk;
422 ULONG refcount;
423 HRESULT hr;
425 /* COM aggregation */
426 hr = CoCreateInstance(&CLSID_DirectMusicGraph, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
427 &IID_IUnknown, (void**)&dmg);
428 ok(hr == CLASS_E_NOAGGREGATION,
429 "DirectMusicGraph create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
430 ok(!dmg, "dmg = %p\n", dmg);
432 /* Invalid RIID */
433 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory,
434 (void**)&dmg);
435 ok(hr == E_NOINTERFACE, "DirectMusicGraph create failed: %#lx, expected E_NOINTERFACE\n", hr);
437 /* Same refcount for all DirectMusicGraph interfaces */
438 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
439 &IID_IDirectMusicGraph, (void**)&dmg);
440 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
441 refcount = IDirectMusicGraph_AddRef(dmg);
442 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
444 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IDirectMusicObject, (void**)&dmo);
445 if (hr == E_NOINTERFACE) {
446 win_skip("DirectMusicGraph without IDirectMusicObject\n");
447 return;
449 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
450 refcount = IDirectMusicObject_AddRef(dmo);
451 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
452 refcount = IDirectMusicObject_Release(dmo);
454 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
455 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
456 refcount = IPersistStream_AddRef(ps);
457 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
458 refcount = IPersistStream_Release(ps);
460 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IUnknown, (void**)&unk);
461 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
462 refcount = IUnknown_AddRef(unk);
463 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
464 refcount = IUnknown_Release(unk);
466 while (IDirectMusicGraph_Release(dmg));
469 static void test_COM_segment(void)
471 IDirectMusicSegment8 *dms = (IDirectMusicSegment8*)0xdeadbeef;
472 IDirectMusicObject *dmo;
473 IPersistStream *stream;
474 IUnknown *unk;
475 ULONG refcount;
476 HRESULT hr;
478 /* COM aggregation */
479 hr = CoCreateInstance(&CLSID_DirectMusicSegment, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
480 &IID_IUnknown, (void**)&dms);
481 ok(hr == CLASS_E_NOAGGREGATION,
482 "DirectMusicSegment create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
483 ok(!dms, "dms = %p\n", dms);
485 /* Invalid RIID */
486 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
487 &IID_IDirectSound, (void**)&dms);
488 ok(hr == E_NOINTERFACE, "DirectMusicSegment create failed: %#lx, expected E_NOINTERFACE\n", hr);
490 /* Same refcount */
491 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
492 &IID_IDirectMusicSegment8, (void**)&dms);
493 if (hr == E_NOINTERFACE) {
494 win_skip("DirectMusicSegment without IDirectMusicSegment8\n");
495 return;
497 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
498 refcount = IDirectMusicSegment8_AddRef(dms);
499 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
500 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IDirectMusicObject, (void**)&dmo);
501 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
502 IDirectMusicSegment8_AddRef(dms);
503 refcount = IDirectMusicSegment8_Release(dms);
504 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
505 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IPersistStream, (void**)&stream);
506 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
507 refcount = IDirectMusicSegment8_Release(dms);
508 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
509 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IUnknown, (void**)&unk);
510 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
511 refcount = IUnknown_Release(unk);
512 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
513 refcount = IDirectMusicObject_Release(dmo);
514 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
515 refcount = IPersistStream_Release(stream);
516 ok (refcount == 1, "refcount == %lu, expected 1\n", refcount);
517 refcount = IDirectMusicSegment8_Release(dms);
518 ok (refcount == 0, "refcount == %lu, expected 0\n", refcount);
521 static void test_COM_segmentstate(void)
523 IDirectMusicSegmentState8 *dmss8 = (IDirectMusicSegmentState8*)0xdeadbeef;
524 IUnknown *unk;
525 ULONG refcount;
526 HRESULT hr;
528 /* COM aggregation */
529 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
530 &IID_IUnknown, (void**)&dmss8);
531 ok(hr == CLASS_E_NOAGGREGATION,
532 "DirectMusicSegmentState8 create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
533 ok(!dmss8, "dmss8 = %p\n", dmss8);
535 /* Invalid RIID */
536 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
537 &IID_IDirectMusicObject, (void**)&dmss8);
538 ok(hr == E_NOINTERFACE, "DirectMusicSegmentState8 create failed: %#lx, expected E_NOINTERFACE\n", hr);
540 /* Same refcount for all DirectMusicSegmentState interfaces */
541 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
542 &IID_IDirectMusicSegmentState8, (void**)&dmss8);
543 if (hr == E_NOINTERFACE) {
544 win_skip("DirectMusicSegmentState without IDirectMusicSegmentState8\n");
545 return;
547 ok(hr == S_OK, "DirectMusicSegmentState8 create failed: %#lx, expected S_OK\n", hr);
548 refcount = IDirectMusicSegmentState8_AddRef(dmss8);
549 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
551 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, (void**)&unk);
552 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
553 refcount = IUnknown_AddRef(unk);
554 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
555 refcount = IUnknown_Release(unk);
557 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, NULL);
558 ok(hr == E_POINTER, "got %#lx\n", hr);
560 while (IDirectMusicSegmentState8_Release(dmss8));
563 static void test_COM_track(void)
565 IDirectMusicTrack *dmt;
566 IDirectMusicTrack8 *dmt8;
567 IPersistStream *ps;
568 IUnknown *unk;
569 ULONG refcount;
570 HRESULT hr;
571 #define X(class) &CLSID_ ## class, #class
572 const struct {
573 REFCLSID clsid;
574 const char *name;
575 BOOL has_dmt8;
576 } class[] = {
577 { X(DirectMusicLyricsTrack), TRUE },
578 { X(DirectMusicMarkerTrack), FALSE },
579 { X(DirectMusicParamControlTrack), TRUE },
580 { X(DirectMusicSegmentTriggerTrack), TRUE },
581 { X(DirectMusicSeqTrack), TRUE },
582 { X(DirectMusicSysExTrack), TRUE },
583 { X(DirectMusicTempoTrack), TRUE },
584 { X(DirectMusicTimeSigTrack), FALSE },
585 { X(DirectMusicWaveTrack), TRUE }
587 #undef X
588 unsigned int i;
590 for (i = 0; i < ARRAY_SIZE(class); i++) {
591 trace("Testing %s\n", class[i].name);
592 /* COM aggregation */
593 dmt8 = (IDirectMusicTrack8*)0xdeadbeef;
594 hr = CoCreateInstance(class[i].clsid, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
595 (void**)&dmt8);
596 if (hr == REGDB_E_CLASSNOTREG) {
597 win_skip("%s not registered\n", class[i].name);
598 continue;
600 ok(hr == CLASS_E_NOAGGREGATION,
601 "%s create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", class[i].name, hr);
602 ok(!dmt8, "dmt8 = %p\n", dmt8);
604 /* Invalid RIID */
605 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
606 (void**)&dmt8);
607 ok(hr == E_NOINTERFACE, "%s create failed: %#lx, expected E_NOINTERFACE\n", class[i].name, hr);
609 /* Same refcount for all DirectMusicTrack interfaces */
610 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
611 (void**)&dmt);
612 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
613 refcount = IDirectMusicTrack_AddRef(dmt);
614 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
616 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
617 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
618 refcount = IPersistStream_AddRef(ps);
619 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
620 IPersistStream_Release(ps);
622 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IUnknown, (void**)&unk);
623 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
624 refcount = IUnknown_AddRef(unk);
625 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
626 refcount = IUnknown_Release(unk);
628 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
629 if (class[i].has_dmt8) {
630 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
631 refcount = IDirectMusicTrack8_AddRef(dmt8);
632 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
633 refcount = IDirectMusicTrack8_Release(dmt8);
634 } else {
635 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
636 refcount = IDirectMusicTrack_AddRef(dmt);
637 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
640 while (IDirectMusicTrack_Release(dmt));
644 static void test_audiopathconfig(void)
646 IDirectMusicObject *dmo;
647 IPersistStream *ps;
648 CLSID class = { 0 };
649 ULARGE_INTEGER size;
650 HRESULT hr;
652 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
653 &IID_IDirectMusicObject, (void**)&dmo);
654 if (hr == REGDB_E_CLASSNOTREG) {
655 win_skip("DirectMusicAudioPathConfig not registered\n");
656 return;
658 ok(hr == S_OK, "DirectMusicAudioPathConfig create failed: %#lx, expected S_OK\n", hr);
660 /* IPersistStream */
661 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
662 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
663 hr = IPersistStream_GetClassID(ps, &class);
664 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
665 ok(IsEqualGUID(&class, &CLSID_DirectMusicAudioPathConfig),
666 "Expected class CLSID_DirectMusicAudioPathConfig got %s\n", wine_dbgstr_guid(&class));
668 /* Unimplemented IPersistStream methods */
669 hr = IPersistStream_IsDirty(ps);
670 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
671 hr = IPersistStream_GetSizeMax(ps, &size);
672 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
673 hr = IPersistStream_Save(ps, NULL, TRUE);
674 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
676 while (IDirectMusicObject_Release(dmo));
679 static void test_graph(void)
681 IDirectMusicTool *tool1, *tool2, *tmp_tool;
682 IDirectMusicGraph *graph, *tmp_graph;
683 IPersistStream *ps;
684 CLSID class = { 0 };
685 ULARGE_INTEGER size;
686 DMUS_PMSG msg;
687 HRESULT hr;
689 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
690 &IID_IDirectMusicGraph, (void**)&graph);
691 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
693 /* IPersistStream */
694 hr = IDirectMusicGraph_QueryInterface(graph, &IID_IPersistStream, (void**)&ps);
695 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
696 hr = IPersistStream_GetClassID(ps, &class);
697 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
698 if (hr == S_OK)
699 ok(IsEqualGUID(&class, &CLSID_DirectMusicGraph),
700 "Expected class CLSID_DirectMusicGraph got %s\n", wine_dbgstr_guid(&class));
702 /* Unimplemented IPersistStream methods */
703 hr = IPersistStream_IsDirty(ps);
704 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
705 hr = IPersistStream_GetSizeMax(ps, &size);
706 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
707 hr = IPersistStream_Save(ps, NULL, TRUE);
708 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
710 IDirectMusicGraph_Release(graph);
713 hr = test_tool_create(NULL, 0, &tool1);
714 ok(hr == S_OK, "got %#lx\n", hr);
715 trace("created tool1 %p\n", tool1);
716 hr = test_tool_create(NULL, 0, &tool2);
717 ok(hr == S_OK, "got %#lx\n", hr);
718 trace("created tool2 %p\n", tool2);
720 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
721 &IID_IDirectMusicGraph, (void **)&graph);
722 ok(hr == S_OK, "got %#lx\n", hr);
725 hr = IDirectMusicGraph_InsertTool(graph, NULL, NULL, 0, -1);
726 ok(hr == E_POINTER, "got %#lx\n", hr);
728 /* InsertTool initializes the tool */
729 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
730 ok(hr == S_OK, "got %#lx\n", hr);
731 hr = test_tool_get_graph(tool1, &tmp_graph);
732 ok(hr == S_OK, "got %#lx\n", hr);
733 ok(graph == tmp_graph, "got %#lx\n", hr);
734 IDirectMusicGraph_Release(tmp_graph);
736 hr = IDirectMusicGraph_InsertTool(graph, tool2, NULL, 0, 1);
737 ok(hr == S_OK, "got %#lx\n", hr);
739 hr = IDirectMusicGraph_GetTool(graph, 0, NULL);
740 ok(hr == E_POINTER, "got %#lx\n", hr);
741 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
742 ok(hr == S_OK, "got %#lx\n", hr);
743 ok(tool1 == tmp_tool, "got %p\n", tmp_tool);
744 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
745 hr = IDirectMusicGraph_GetTool(graph, 1, &tmp_tool);
746 ok(hr == S_OK, "got %#lx\n", hr);
747 ok(tool2 == tmp_tool, "got %p\n", tmp_tool);
748 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
749 hr = IDirectMusicGraph_GetTool(graph, 2, &tmp_tool);
750 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
752 /* cannot insert the tool twice */
753 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
754 ok(hr == DMUS_E_ALREADY_EXISTS, "got %#lx\n", hr);
756 /* test removing the first tool */
757 hr = IDirectMusicGraph_RemoveTool(graph, NULL);
758 ok(hr == E_POINTER, "got %#lx\n", hr);
759 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
760 ok(hr == S_OK, "got %#lx\n", hr);
761 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
762 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
764 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
765 ok(hr == S_OK, "got %#lx\n", hr);
766 ok(tool2 == tmp_tool, "got %p\n", tmp_tool);
767 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
768 hr = IDirectMusicGraph_GetTool(graph, 1, &tmp_tool);
769 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
771 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
772 ok(hr == S_OK, "got %#lx\n", hr);
773 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
774 ok(hr == S_OK, "got %#lx\n", hr);
775 ok(tool1 == tmp_tool, "got %p\n", tmp_tool);
776 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
779 /* Test basic IDirectMusicGraph_StampPMsg usage */
780 hr = IDirectMusicGraph_StampPMsg(graph, NULL);
781 ok(hr == E_POINTER, "got %#lx\n", hr);
782 memset(&msg, 0, sizeof(msg));
783 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
784 ok(hr == S_OK, "got %#lx\n", hr);
785 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
786 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
788 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
789 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
790 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
791 ok(msg.dwFlags == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", msg.dwFlags);
792 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
793 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
794 ok(!msg.dwType, "got %#lx\n", msg.dwType);
795 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
796 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
797 ok(!msg.punkUser, "got %p\n", msg.punkUser);
799 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
800 ok(hr == S_OK, "got %#lx\n", hr);
801 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
802 ok(msg.pTool == tool2, "got %p\n", msg.pTool);
803 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
804 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
805 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
806 ok(!msg.pTool, "got %p\n", msg.pTool);
807 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
808 ok(hr == S_OK, "got %#lx\n", hr);
809 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
810 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
811 IDirectMusicGraph_Release(msg.pGraph);
812 msg.pGraph = NULL;
813 IDirectMusicGraph_Release(msg.pTool);
814 msg.pTool = NULL;
817 /* test StampPMsg with the wrong graph or innexistant tools */
818 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
819 &IID_IDirectMusicGraph, (void **)&tmp_graph);
820 ok(hr == S_OK, "got %#lx\n", hr);
822 msg.pGraph = tmp_graph;
823 IDirectMusicGraph_AddRef(msg.pGraph);
824 msg.pTool = tool1;
825 IDirectMusicTool_AddRef(msg.pTool);
826 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
827 ok(hr == S_OK, "got %#lx\n", hr);
828 ok(msg.pGraph == tmp_graph, "got %p\n", msg.pGraph);
829 ok(msg.pTool == tool2, "got %p\n", msg.pTool);
830 IDirectMusicGraph_Release(msg.pGraph);
831 msg.pGraph = NULL;
833 msg.pGraph = graph;
834 IDirectMusicGraph_AddRef(msg.pGraph);
835 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
836 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
837 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
838 ok(msg.pTool == NULL, "got %p\n", msg.pTool);
840 msg.pTool = tool2;
841 IDirectMusicTool_AddRef(msg.pTool);
842 hr = IDirectMusicGraph_InsertTool(tmp_graph, tool1, NULL, 0, 0);
843 ok(hr == S_OK, "got %#lx\n", hr);
844 hr = IDirectMusicGraph_InsertTool(tmp_graph, tool2, NULL, 0, 0);
845 ok(hr == S_OK, "got %#lx\n", hr);
846 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
847 ok(hr == S_OK, "got %#lx\n", hr);
848 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
849 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
850 IDirectMusicGraph_Release(msg.pGraph);
851 msg.pGraph = NULL;
853 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
854 ok(hr == S_OK, "got %#lx\n", hr);
855 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
856 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
857 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
858 ok(msg.pTool == NULL, "got %p\n", msg.pTool);
860 IDirectMusicGraph_Release(tmp_graph);
863 IDirectMusicGraph_Release(graph);
864 IDirectMusicTool_Release(tool2);
865 IDirectMusicTool_Release(tool1);
868 static void test_segment(void)
870 IDirectMusicSegment *dms;
871 IPersistStream *ps;
872 CLSID class = { 0 };
873 ULARGE_INTEGER size;
874 HRESULT hr;
876 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
877 &IID_IDirectMusicSegment, (void**)&dms);
878 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
880 /* IPersistStream */
881 hr = IDirectMusicSegment_QueryInterface(dms, &IID_IPersistStream, (void**)&ps);
882 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
883 hr = IPersistStream_GetClassID(ps, &class);
884 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
885 if (hr == S_OK)
886 ok(IsEqualGUID(&class, &CLSID_DirectMusicSegment),
887 "Expected class CLSID_DirectMusicSegment got %s\n", wine_dbgstr_guid(&class));
889 /* Unimplemented IPersistStream methods */
890 hr = IPersistStream_IsDirty(ps);
891 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
892 hr = IPersistStream_GetSizeMax(ps, &size);
893 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
894 hr = IPersistStream_Save(ps, NULL, TRUE);
895 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
897 while (IDirectMusicSegment_Release(dms));
900 static void _add_track(IDirectMusicSegment8 *seg, REFCLSID class, const char *name, DWORD group)
902 IDirectMusicTrack *track;
903 HRESULT hr;
905 hr = CoCreateInstance(class, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
906 (void**)&track);
907 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", name, hr);
908 hr = IDirectMusicSegment8_InsertTrack(seg, track, group);
909 if (group)
910 ok(hr == S_OK, "Inserting %s failed: %#lx, expected S_OK\n", name, hr);
911 else
912 ok(hr == E_INVALIDARG, "Inserting %s failed: %#lx, expected E_INVALIDARG\n", name, hr);
913 IDirectMusicTrack_Release(track);
916 #define add_track(seg, class, group) _add_track(seg, &CLSID_DirectMusic ## class, #class, group)
918 static void _expect_track(IDirectMusicSegment8 *seg, REFCLSID expect, const char *name, DWORD group,
919 DWORD index, BOOL ignore_guid)
921 IDirectMusicTrack *track;
922 IPersistStream *ps;
923 CLSID class;
924 HRESULT hr;
926 if (ignore_guid)
927 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, group, index, &track);
928 else
929 hr = IDirectMusicSegment8_GetTrack(seg, expect, group, index, &track);
930 if (!expect) {
931 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
932 return;
935 ok(hr == S_OK, "GetTrack failed: %#lx, expected S_OK\n", hr);
936 hr = IDirectMusicTrack_QueryInterface(track, &IID_IPersistStream, (void**)&ps);
937 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
938 hr = IPersistStream_GetClassID(ps, &class);
939 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
940 ok(IsEqualGUID(&class, expect), "For group %#lx index %lu: Expected class %s got %s\n",
941 group, index, name, wine_dbgstr_guid(&class));
943 IPersistStream_Release(ps);
944 IDirectMusicTrack_Release(track);
947 #define expect_track(seg, class, group, index) \
948 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, TRUE)
949 #define expect_guid_track(seg, class, group, index) \
950 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, FALSE)
952 static void test_gettrack(void)
954 IDirectMusicSegment8 *seg;
955 IDirectMusicTrack *track;
956 HRESULT hr;
958 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
959 &IID_IDirectMusicSegment8, (void**)&seg);
960 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
962 add_track(seg, LyricsTrack, 0x0); /* failure */
963 add_track(seg, LyricsTrack, 0x1); /* idx 0 group 1 */
964 add_track(seg, ParamControlTrack, 0x3); /* idx 1 group 1, idx 0 group 2 */
965 add_track(seg, SegmentTriggerTrack, 0x2); /* idx 1 group 2 */
966 add_track(seg, SeqTrack, 0x1); /* idx 2 group 1 */
967 add_track(seg, TempoTrack, 0x7); /* idx 3 group 1, idx 2 group 2, idx 0 group 3 */
968 add_track(seg, WaveTrack, 0xffffffff); /* idx 4 group 1, idx 3 group 2, idx 1 group 3 */
970 /* Ignore GUID in GetTrack */
971 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, 0, 0, &track);
972 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
974 expect_track(seg, LyricsTrack, 0x1, 0);
975 expect_track(seg, ParamControlTrack, 0x1, 1);
976 expect_track(seg, SeqTrack, 0x1, 2);
977 expect_track(seg, TempoTrack, 0x1, 3);
978 expect_track(seg, WaveTrack, 0x1, 4);
979 _expect_track(seg, NULL, "", 0x1, 5, TRUE);
980 _expect_track(seg, NULL, "", 0x1, DMUS_SEG_ANYTRACK, TRUE);
981 expect_track(seg, ParamControlTrack, 0x2, 0);
982 expect_track(seg, WaveTrack, 0x80000000, 0);
983 expect_track(seg, SegmentTriggerTrack, 0x3, 2); /* groups 1+2 combined index */
984 expect_track(seg, SeqTrack, 0x3, 3); /* groups 1+2 combined index */
985 expect_track(seg, TempoTrack, 0x7, 4); /* groups 1+2+3 combined index */
986 expect_track(seg, TempoTrack, 0xffffffff, 4); /* all groups combined index */
987 _expect_track(seg, NULL, "", 0xffffffff, DMUS_SEG_ANYTRACK, TRUE);
989 /* Use the GUID in GetTrack */
990 hr = IDirectMusicSegment8_GetTrack(seg, &CLSID_DirectMusicLyricsTrack, 0, 0, &track);
991 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
993 expect_guid_track(seg, LyricsTrack, 0x1, 0);
994 expect_guid_track(seg, ParamControlTrack, 0x1, 0);
995 expect_guid_track(seg, SeqTrack, 0x1, 0);
996 expect_guid_track(seg, TempoTrack, 0x1, 0);
997 expect_guid_track(seg, ParamControlTrack, 0x2, 0);
998 expect_guid_track(seg, SegmentTriggerTrack, 0x3, 0);
999 expect_guid_track(seg, SeqTrack, 0x3, 0);
1000 expect_guid_track(seg, TempoTrack, 0x7, 0);
1001 expect_guid_track(seg, TempoTrack, 0xffffffff, 0);
1003 IDirectMusicSegment8_Release(seg);
1006 static void test_segment_param(void)
1008 IDirectMusicSegment8 *seg;
1009 char buf[64];
1010 HRESULT hr;
1012 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1013 &IID_IDirectMusicSegment8, (void **)&seg);
1014 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
1016 add_track(seg, LyricsTrack, 0x1); /* no params */
1017 add_track(seg, SegmentTriggerTrack, 0x1); /* all params "supported" */
1019 hr = IDirectMusicSegment8_GetParam(seg, NULL, 0x1, 0, 0, NULL, buf);
1020 ok(hr == E_POINTER, "GetParam failed: %#lx, expected E_POINTER\n", hr);
1021 hr = IDirectMusicSegment8_SetParam(seg, NULL, 0x1, 0, 0, buf);
1022 todo_wine ok(hr == E_POINTER, "SetParam failed: %#lx, expected E_POINTER\n", hr);
1024 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, NULL, buf);
1025 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
1026 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, NULL, buf);
1027 ok(hr == DMUS_E_TRACK_NOT_FOUND, "GetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
1028 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ANYTRACK, 0,
1029 NULL, buf);
1030 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
1032 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, buf);
1033 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
1034 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, buf);
1035 todo_wine ok(hr == DMUS_E_TRACK_NOT_FOUND,
1036 "SetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
1037 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ALLTRACKS,
1038 0, buf);
1039 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
1041 IDirectMusicSegment8_Release(seg);
1044 static void expect_getparam(IDirectMusicTrack *track, REFGUID type, const char *name,
1045 HRESULT expect)
1047 HRESULT hr;
1048 char buf[64] = { 0 };
1050 hr = IDirectMusicTrack_GetParam(track, type, 0, NULL, buf);
1051 ok(hr == expect, "GetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
1054 static void expect_setparam(IDirectMusicTrack *track, REFGUID type, const char *name,
1055 HRESULT expect)
1057 HRESULT hr;
1058 char buf[64] = { 0 };
1060 hr = IDirectMusicTrack_SetParam(track, type, 0, buf);
1061 ok(hr == expect, "SetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
1064 static void test_track(void)
1066 IDirectMusicTrack *dmt;
1067 IDirectMusicTrack8 *dmt8;
1068 IPersistStream *ps;
1069 CLSID classid;
1070 ULARGE_INTEGER size;
1071 HRESULT hr;
1072 #define X(guid) &guid, #guid
1073 const struct {
1074 REFGUID type;
1075 const char *name;
1076 } param_types[] = {
1077 { X(GUID_BandParam) },
1078 { X(GUID_ChordParam) },
1079 { X(GUID_Clear_All_Bands) },
1080 { X(GUID_CommandParam) },
1081 { X(GUID_CommandParam2) },
1082 { X(GUID_CommandParamNext) },
1083 { X(GUID_ConnectToDLSCollection) },
1084 { X(GUID_Disable_Auto_Download) },
1085 { X(GUID_DisableTempo) },
1086 { X(GUID_DisableTimeSig) },
1087 { X(GUID_Download) },
1088 { X(GUID_DownloadToAudioPath) },
1089 { X(GUID_Enable_Auto_Download) },
1090 { X(GUID_EnableTempo) },
1091 { X(GUID_EnableTimeSig) },
1092 { X(GUID_IDirectMusicBand) },
1093 { X(GUID_IDirectMusicChordMap) },
1094 { X(GUID_IDirectMusicStyle) },
1095 { X(GUID_MuteParam) },
1096 { X(GUID_Play_Marker) },
1097 { X(GUID_RhythmParam) },
1098 { X(GUID_SeedVariations) },
1099 { X(GUID_StandardMIDIFile) },
1100 { X(GUID_TempoParam) },
1101 { X(GUID_TimeSignature) },
1102 { X(GUID_Unload) },
1103 { X(GUID_UnloadFromAudioPath) },
1104 { X(GUID_Valid_Start_Time) },
1105 { X(GUID_Variations) },
1106 { X(GUID_NULL) }
1108 #undef X
1109 #define X(class) &CLSID_ ## class, #class
1110 const struct {
1111 REFCLSID clsid;
1112 const char *name;
1113 /* bitfield with supported param types */
1114 unsigned int has_params;
1115 } class[] = {
1116 { X(DirectMusicLyricsTrack), 0 },
1117 { X(DirectMusicMarkerTrack), 0x8080000 },
1118 { X(DirectMusicParamControlTrack), 0 },
1119 { X(DirectMusicSegmentTriggerTrack), 0x3fffffff },
1120 { X(DirectMusicSeqTrack), ~0 }, /* param methods not implemented */
1121 { X(DirectMusicSysExTrack), ~0 }, /* param methods not implemented */
1122 { X(DirectMusicTempoTrack), 0x802100 },
1123 { X(DirectMusicTimeSigTrack), 0x1004200 },
1124 { X(DirectMusicWaveTrack), 0x6001c80 }
1126 #undef X
1127 unsigned int i, j;
1129 for (i = 0; i < ARRAY_SIZE(class); i++) {
1130 trace("Testing %s\n", class[i].name);
1131 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
1132 (void**)&dmt);
1133 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
1135 /* IDirectMusicTrack */
1136 if (class[i].has_params != ~0) {
1137 for (j = 0; j < ARRAY_SIZE(param_types); j++) {
1138 hr = IDirectMusicTrack_IsParamSupported(dmt, param_types[j].type);
1139 if (class[i].has_params & (1 << j)) {
1140 ok(hr == S_OK, "IsParamSupported(%s) failed: %#lx, expected S_OK\n",
1141 param_types[j].name, hr);
1142 if (class[i].clsid == &CLSID_DirectMusicSegmentTriggerTrack) {
1143 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1144 DMUS_E_GET_UNSUPPORTED);
1145 expect_setparam(dmt, param_types[j].type, param_types[j].name, S_OK);
1146 } else if (class[i].clsid == &CLSID_DirectMusicMarkerTrack)
1147 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1148 DMUS_E_SET_UNSUPPORTED);
1149 else if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
1150 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1151 DMUS_E_GET_UNSUPPORTED);
1152 } else {
1153 ok(hr == DMUS_E_TYPE_UNSUPPORTED,
1154 "IsParamSupported(%s) failed: %#lx, expected DMUS_E_TYPE_UNSUPPORTED\n",
1155 param_types[j].name, hr);
1156 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1157 DMUS_E_GET_UNSUPPORTED);
1158 if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
1159 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1160 DMUS_E_TYPE_UNSUPPORTED);
1161 else
1162 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1163 DMUS_E_SET_UNSUPPORTED);
1166 /* GetParam / SetParam for IsParamSupported supported types */
1167 if (class[i].clsid == &CLSID_DirectMusicTimeSigTrack) {
1168 expect_getparam(dmt, &GUID_DisableTimeSig, "GUID_DisableTimeSig",
1169 DMUS_E_GET_UNSUPPORTED);
1170 expect_getparam(dmt, &GUID_EnableTimeSig, "GUID_EnableTimeSig",
1171 DMUS_E_GET_UNSUPPORTED);
1172 expect_setparam(dmt, &GUID_TimeSignature, "GUID_TimeSignature",
1173 DMUS_E_SET_UNSUPPORTED);
1174 } else if (class[i].clsid == &CLSID_DirectMusicTempoTrack) {
1175 expect_getparam(dmt, &GUID_DisableTempo, "GUID_DisableTempo",
1176 DMUS_E_GET_UNSUPPORTED);
1177 expect_getparam(dmt, &GUID_EnableTempo, "GUID_EnableTempo",
1178 DMUS_E_GET_UNSUPPORTED);
1181 } else {
1182 hr = IDirectMusicTrack_GetParam(dmt, NULL, 0, NULL, NULL);
1183 ok(hr == E_NOTIMPL, "IDirectMusicTrack_GetParam failed: %#lx\n", hr);
1184 hr = IDirectMusicTrack_SetParam(dmt, NULL, 0, NULL);
1185 ok(hr == E_NOTIMPL, "IDirectMusicTrack_SetParam failed: %#lx\n", hr);
1186 hr = IDirectMusicTrack_IsParamSupported(dmt, NULL);
1187 ok(hr == E_NOTIMPL, "IDirectMusicTrack_IsParamSupported failed: %#lx\n", hr);
1189 hr = IDirectMusicTrack_IsParamSupported(dmt, &GUID_IDirectMusicStyle);
1190 ok(hr == E_NOTIMPL, "got: %#lx\n", hr);
1192 if (class[i].clsid != &CLSID_DirectMusicMarkerTrack &&
1193 class[i].clsid != &CLSID_DirectMusicTimeSigTrack) {
1194 hr = IDirectMusicTrack_AddNotificationType(dmt, NULL);
1195 ok(hr == E_NOTIMPL, "IDirectMusicTrack_AddNotificationType failed: %#lx\n", hr);
1196 hr = IDirectMusicTrack_RemoveNotificationType(dmt, NULL);
1197 ok(hr == E_NOTIMPL, "IDirectMusicTrack_RemoveNotificationType failed: %#lx\n", hr);
1199 hr = IDirectMusicTrack_Clone(dmt, 0, 0, NULL);
1200 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack_Clone failed: %#lx\n", hr);
1202 /* IDirectMusicTrack8 */
1203 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
1204 if (hr == S_OK) {
1205 hr = IDirectMusicTrack8_PlayEx(dmt8, NULL, 0, 0, 0, 0, NULL, NULL, 0);
1206 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_PlayEx failed: %#lx\n", hr);
1207 if (class[i].has_params == ~0) {
1208 hr = IDirectMusicTrack8_GetParamEx(dmt8, NULL, 0, NULL, NULL, NULL, 0);
1209 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_GetParamEx failed: %#lx\n", hr);
1210 hr = IDirectMusicTrack8_SetParamEx(dmt8, NULL, 0, NULL, NULL, 0);
1211 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_SetParamEx failed: %#lx\n", hr);
1213 hr = IDirectMusicTrack8_Compose(dmt8, NULL, 0, NULL);
1214 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Compose failed: %#lx\n", hr);
1215 hr = IDirectMusicTrack8_Join(dmt8, NULL, 0, NULL, 0, NULL);
1216 if (class[i].clsid == &CLSID_DirectMusicTempoTrack)
1217 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
1218 else
1219 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
1220 IDirectMusicTrack8_Release(dmt8);
1223 /* IPersistStream */
1224 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
1225 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1226 hr = IPersistStream_GetClassID(ps, &classid);
1227 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
1228 ok(IsEqualGUID(&classid, class[i].clsid),
1229 "Expected class %s got %s\n", class[i].name, wine_dbgstr_guid(&classid));
1230 hr = IPersistStream_IsDirty(ps);
1231 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
1233 /* Unimplemented IPersistStream methods */
1234 hr = IPersistStream_GetSizeMax(ps, &size);
1235 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
1236 hr = IPersistStream_Save(ps, NULL, TRUE);
1237 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
1239 while (IDirectMusicTrack_Release(dmt));
1243 struct chunk {
1244 FOURCC id;
1245 DWORD size;
1246 FOURCC type;
1249 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
1251 /* Generate a RIFF file format stream from an array of FOURCC ids.
1252 RIFF and LIST need to be followed by the form type respectively list type,
1253 followed by the chunks of the list and terminated with 0. */
1254 static IStream *gen_riff_stream(const FOURCC *ids)
1256 static const LARGE_INTEGER zero;
1257 int level = -1;
1258 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
1259 char riff[1024];
1260 char *p = riff;
1261 struct chunk *ck;
1262 IStream *stream;
1264 do {
1265 ck = (struct chunk *)p;
1266 ck->id = *ids++;
1267 switch (ck->id) {
1268 case 0:
1269 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
1270 level--;
1271 break;
1272 case FOURCC_LIST:
1273 case FOURCC_RIFF:
1274 level++;
1275 sizes[level] = &ck->size;
1276 ck->type = *ids++;
1277 p += sizeof(*ck);
1278 break;
1279 case DMUS_FOURCC_GUID_CHUNK:
1280 ck->size = sizeof(GUID_NULL);
1281 p += CHUNK_HDR_SIZE;
1282 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
1283 p += ck->size;
1284 break;
1285 case DMUS_FOURCC_VERSION_CHUNK:
1287 DMUS_VERSION ver = {5, 8};
1289 ck->size = sizeof(ver);
1290 p += CHUNK_HDR_SIZE;
1291 memcpy(p, &ver, sizeof(ver));
1292 p += ck->size;
1293 break;
1295 default:
1297 /* Just convert the FOURCC id to a WCHAR string */
1298 WCHAR *s;
1300 ck->size = 5 * sizeof(WCHAR);
1301 p += CHUNK_HDR_SIZE;
1302 s = (WCHAR *)p;
1303 s[0] = (char)(ck->id);
1304 s[1] = (char)(ck->id >> 8);
1305 s[2] = (char)(ck->id >> 16);
1306 s[3] = (char)(ck->id >> 24);
1307 s[4] = 0;
1308 p += ck->size;
1311 } while (level >= 0);
1313 ck = (struct chunk *)riff;
1314 CreateStreamOnHGlobal(NULL, TRUE, &stream);
1315 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
1316 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1318 return stream;
1321 static void test_parsedescriptor(void)
1323 IDirectMusicObject *dmo;
1324 IStream *stream;
1325 DMUS_OBJECTDESC desc;
1326 HRESULT hr;
1327 DWORD valid;
1328 unsigned int i;
1329 /* fourcc ~0 will be replaced later on */
1330 FOURCC alldesc[] =
1332 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
1333 DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK, DMUS_FOURCC_UCMT_CHUNK,
1334 DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, 0
1336 FOURCC dupes[] =
1338 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
1339 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
1340 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, 0,
1341 FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
1343 FOURCC empty[] = {FOURCC_RIFF, ~0, 0};
1344 FOURCC inam[] = {FOURCC_RIFF, ~0, FOURCC_LIST, ~0, mmioFOURCC('I','N','A','M'), 0, 0};
1345 FOURCC noriff[] = {mmioFOURCC('J','U','N','K'), 0};
1346 #define X(class) &CLSID_ ## class, #class
1347 #define Y(form) form, #form
1348 const struct {
1349 REFCLSID clsid;
1350 const char *class;
1351 FOURCC form;
1352 const char *name;
1353 BOOL needs_size;
1354 } forms[] = {
1355 { X(DirectMusicSegment), Y(DMUS_FOURCC_SEGMENT_FORM), FALSE },
1356 { X(DirectMusicSegment), Y(mmioFOURCC('W','A','V','E')), FALSE },
1357 { X(DirectMusicAudioPathConfig), Y(DMUS_FOURCC_AUDIOPATH_FORM), TRUE },
1358 { X(DirectMusicGraph), Y(DMUS_FOURCC_TOOLGRAPH_FORM), TRUE },
1360 #undef X
1361 #undef Y
1363 for (i = 0; i < ARRAY_SIZE(forms); i++) {
1364 trace("Testing %s / %s\n", forms[i].class, forms[i].name);
1365 hr = CoCreateInstance(forms[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
1366 (void **)&dmo);
1367 if (hr != S_OK) {
1368 win_skip("Could not create %s object: %#lx\n", forms[i].class, hr);
1369 return;
1372 /* Nothing loaded */
1373 memset(&desc, 0, sizeof(desc));
1374 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1375 if (forms[i].needs_size) {
1376 todo_wine ok(hr == E_INVALIDARG, "GetDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1377 desc.dwSize = sizeof(desc);
1378 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1380 ok(hr == S_OK, "GetDescriptor failed: %#lx, expected S_OK\n", hr);
1381 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1382 desc.dwValidData);
1383 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1384 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1386 /* Empty RIFF stream */
1387 empty[1] = forms[i].form;
1388 stream = gen_riff_stream(empty);
1389 memset(&desc, 0, sizeof(desc));
1390 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1391 if (forms[i].needs_size) {
1392 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1393 desc.dwSize = sizeof(desc);
1394 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1396 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1397 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1398 desc.dwValidData);
1399 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1400 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1402 /* NULL pointers */
1403 memset(&desc, 0, sizeof(desc));
1404 desc.dwSize = sizeof(desc);
1405 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
1406 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1407 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
1408 if (forms[i].needs_size)
1409 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1410 else
1411 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1412 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, NULL);
1413 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
1414 IStream_Release(stream);
1416 /* Wrong form */
1417 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
1418 stream = gen_riff_stream(empty);
1419 memset(&desc, 0, sizeof(desc));
1420 desc.dwSize = sizeof(desc);
1421 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1422 if (forms[i].needs_size)
1423 ok(hr == DMUS_E_CHUNKNOTFOUND,
1424 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1425 else
1426 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
1427 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
1428 IStream_Release(stream);
1430 /* Not a RIFF stream */
1431 stream = gen_riff_stream(noriff);
1432 memset(&desc, 0, sizeof(desc));
1433 desc.dwSize = sizeof(desc);
1434 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1435 if (forms[i].needs_size)
1436 ok(hr == DMUS_E_CHUNKNOTFOUND,
1437 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
1438 else
1439 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
1440 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
1441 IStream_Release(stream);
1443 /* All desc chunks */
1444 alldesc[1] = forms[i].form;
1445 stream = gen_riff_stream(alldesc);
1446 memset(&desc, 0, sizeof(desc));
1447 desc.dwSize = sizeof(desc);
1448 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1449 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1450 valid = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_VERSION;
1451 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1452 valid |= DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY;
1453 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1454 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1455 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
1456 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
1457 wine_dbgstr_guid(&desc.guidClass));
1458 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
1459 "Got version %lu.%lu, expected 5.8\n", desc.vVersion.dwVersionMS,
1460 desc.vVersion.dwVersionLS);
1461 if (forms[i].form != mmioFOURCC('W','A','V','E'))
1462 ok(!lstrcmpW(desc.wszName, L"UNAM"), "Got name '%s', expected 'UNAM'\n",
1463 wine_dbgstr_w(desc.wszName));
1464 IStream_Release(stream);
1466 /* Duplicated chunks */
1467 dupes[1] = forms[i].form;
1468 stream = gen_riff_stream(dupes);
1469 memset(&desc, 0, sizeof(desc));
1470 desc.dwSize = sizeof(desc);
1471 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1472 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1473 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1474 IStream_Release(stream);
1476 /* UNFO list with INAM */
1477 inam[1] = forms[i].form;
1478 inam[3] = DMUS_FOURCC_UNFO_LIST;
1479 stream = gen_riff_stream(inam);
1480 memset(&desc, 0, sizeof(desc));
1481 desc.dwSize = sizeof(desc);
1482 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
1483 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
1484 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1485 desc.dwValidData);
1486 IStream_Release(stream);
1488 /* INFO list with INAM */
1489 inam[3] = DMUS_FOURCC_INFO_LIST;
1490 stream = gen_riff_stream(inam);
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 valid = DMUS_OBJ_CLASS;
1496 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1497 valid |= DMUS_OBJ_NAME;
1498 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
1499 if (forms[i].form == mmioFOURCC('W','A','V','E'))
1500 ok(!lstrcmpW(desc.wszName, L"I"), "Got name '%s', expected 'I'\n",
1501 wine_dbgstr_w(desc.wszName));
1502 IStream_Release(stream);
1504 IDirectMusicObject_Release(dmo);
1508 static void test_performance_tool(void)
1510 IDirectMusicPerformance *performance;
1511 IDirectMusicGraph *graph;
1512 IDirectMusicTool *tool;
1513 DWORD value, types[1];
1514 DMUS_PMSG msg = {0};
1515 HRESULT hr;
1517 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1518 &IID_IDirectMusicPerformance, (void **)&performance);
1519 ok(hr == S_OK, "got %#lx\n", hr);
1521 check_interface(performance, &IID_IDirectMusicTool8, FALSE);
1523 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicTool, (void **)&tool);
1524 ok(hr == S_OK, "got %#lx\n", hr);
1525 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
1526 ok(hr == S_OK, "got %#lx\n", hr);
1528 hr = IDirectMusicTool_Init(tool, graph);
1529 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1530 value = 0xdeadbeef;
1531 hr = IDirectMusicTool_GetMsgDeliveryType(tool, &value);
1532 ok(hr == S_OK, "got %#lx\n", hr);
1533 ok(value == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", value);
1534 value = 0xdeadbeef;
1535 hr = IDirectMusicTool_GetMediaTypeArraySize(tool, &value);
1536 ok(hr == S_OK, "got %#lx\n", hr);
1537 ok(value == 0, "got %#lx\n", value);
1538 hr = IDirectMusicTool_GetMediaTypes(tool, (DWORD **)&types, 64);
1539 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1540 hr = IDirectMusicTool_ProcessPMsg(tool, performance, &msg);
1541 ok(hr == DMUS_S_FREE, "got %#lx\n", hr);
1542 hr = IDirectMusicTool_Flush(tool, performance, &msg, 0);
1543 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
1545 IDirectMusicGraph_Release(graph);
1546 IDirectMusicTool_Release(tool);
1548 IDirectMusicPerformance_Release(performance);
1551 static void test_performance_graph(void)
1553 IDirectMusicPerformance *performance;
1554 IDirectMusicGraph *graph, *tmp_graph;
1555 IDirectMusicTool *tool, *tmp_tool;
1556 DMUS_PMSG msg;
1557 HRESULT hr;
1559 hr = test_tool_create(NULL, 0, &tool);
1560 ok(hr == S_OK, "got %#lx\n", hr);
1562 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1563 &IID_IDirectMusicPerformance, (void **)&performance);
1564 ok(hr == S_OK, "got %#lx\n", hr);
1567 /* performance exposes a graph interface but it's not an actual toolgraph */
1568 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
1569 ok(hr == S_OK, "got %#lx\n", hr);
1570 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
1571 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1572 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
1573 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1574 hr = IDirectMusicGraph_RemoveTool(graph, tool);
1575 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
1577 /* test IDirectMusicGraph_StampPMsg usage */
1578 hr = IDirectMusicGraph_StampPMsg(graph, NULL);
1579 ok(hr == E_POINTER, "got %#lx\n", hr);
1580 memset(&msg, 0, sizeof(msg));
1581 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1582 ok(hr == S_OK, "got %#lx\n", hr);
1583 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1584 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
1585 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
1587 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
1588 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
1589 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
1590 ok(msg.dwFlags == DMUS_PMSGF_TOOL_QUEUE, "got %#lx\n", msg.dwFlags);
1591 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
1592 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
1593 ok(!msg.dwType, "got %#lx\n", msg.dwType);
1594 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
1595 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
1596 ok(!msg.punkUser, "got %p\n", msg.punkUser);
1598 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1599 ok(hr == S_OK, "got %#lx\n", hr);
1600 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1601 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
1602 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
1604 IDirectMusicTool_Release(msg.pTool);
1605 msg.pTool = NULL;
1607 IDirectMusicGraph_Release(graph);
1610 /* performance doesn't have a default embedded toolgraph */
1611 hr = IDirectMusicPerformance_GetGraph(performance, &graph);
1612 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
1615 /* test adding a graph to the performance */
1616 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1617 &IID_IDirectMusicGraph, (void **)&graph);
1618 ok(hr == S_OK, "got %#lx\n", hr);
1619 hr = IDirectMusicPerformance_SetGraph(performance, graph);
1620 ok(hr == S_OK, "got %#lx\n", hr);
1622 hr = IDirectMusicPerformance_GetGraph(performance, &tmp_graph);
1623 ok(hr == S_OK, "got %#lx\n", hr);
1624 ok(tmp_graph == graph, "got %p\n", graph);
1625 IDirectMusicGraph_Release(tmp_graph);
1627 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
1628 ok(hr == S_OK, "got %#lx\n", hr);
1630 IDirectMusicGraph_Release(graph);
1633 /* test IDirectMusicGraph_StampPMsg usage */
1634 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
1635 ok(hr == S_OK, "got %#lx\n", hr);
1637 memset(&msg, 0, sizeof(msg));
1638 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1639 ok(hr == S_OK, "got %#lx\n", hr);
1640 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1641 ok(msg.pTool == tool, "got %p\n", msg.pTool);
1643 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
1644 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
1645 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
1646 ok(msg.dwFlags == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", msg.dwFlags);
1647 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
1648 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
1649 ok(!msg.dwType, "got %#lx\n", msg.dwType);
1650 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
1651 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
1652 ok(!msg.punkUser, "got %p\n", msg.punkUser);
1654 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1655 ok(hr == S_OK, "got %#lx\n", hr);
1656 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1657 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
1658 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
1660 IDirectMusicTool_Release(msg.pTool);
1661 msg.pTool = NULL;
1663 IDirectMusicGraph_Release(graph);
1666 IDirectMusicPerformance_Release(performance);
1667 IDirectMusicTool_Release(tool);
1670 static void test_performance_time(void)
1672 IDirectMusicPerformance *performance;
1673 REFERENCE_TIME init_time, time;
1674 IReferenceClock *clock;
1675 MUSIC_TIME music_time;
1676 IDirectMusic *dmusic;
1677 HRESULT hr;
1679 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1680 &IID_IDirectMusicPerformance, (void **)&performance);
1681 ok(hr == S_OK, "got %#lx\n", hr);
1684 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, NULL);
1685 ok(hr == E_POINTER, "got %#lx\n", hr);
1686 time = 0xdeadbeef;
1687 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, &time);
1688 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
1689 ok(time == 0, "got %I64d\n", time);
1691 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, 0, NULL);
1692 ok(hr == E_POINTER, "got %#lx\n", hr);
1693 music_time = 0xdeadbeef;
1694 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, 0, &music_time);
1695 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
1696 ok(music_time == 0, "got %ld\n", music_time);
1699 dmusic = NULL;
1700 hr = IDirectMusicPerformance_Init(performance, &dmusic, NULL, NULL);
1701 ok(hr == S_OK, "got %#lx\n", hr);
1702 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock);
1703 ok(hr == S_OK, "got %#lx\n", hr);
1704 IDirectMusic_Release(dmusic);
1705 hr = IReferenceClock_GetTime(clock, &init_time);
1706 ok(hr == S_OK, "got %#lx\n", hr);
1707 IReferenceClock_Release(clock);
1710 time = 0xdeadbeef;
1711 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, &time);
1712 ok(hr == S_OK, "got %#lx\n", hr);
1713 ok(time - init_time <= 100 * 10000, "got %I64d\n", time - init_time);
1714 init_time = time;
1716 time = 0xdeadbeef;
1717 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 1, &time);
1718 ok(hr == S_OK, "got %#lx\n", hr);
1719 ok(time - init_time >= 6505, "got %I64d\n", time - init_time);
1720 ok(time - init_time <= 6515, "got %I64d\n", time - init_time);
1721 time = 0xdeadbeef;
1722 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 1000, &time);
1723 ok(hr == S_OK, "got %#lx\n", hr);
1724 ok(time - init_time >= 1000 * 6505, "got %I64d\n", time - init_time);
1725 ok(time - init_time <= 1000 * 6515, "got %I64d\n", time - init_time);
1726 time = 0xdeadbeef;
1727 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 2000, &time);
1728 ok(hr == S_OK, "got %#lx\n", hr);
1729 ok(time - init_time >= 2000 * 6505, "got %I64d\n", time - init_time);
1730 ok(time - init_time <= 2000 * 6515, "got %I64d\n", time - init_time);
1732 music_time = 0xdeadbeef;
1733 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time, &music_time);
1734 ok(hr == S_OK, "got %#lx\n", hr);
1735 ok(music_time == 0, "got %ld\n", music_time);
1736 music_time = 0xdeadbeef;
1737 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time + 1000 * 6510, &music_time);
1738 ok(hr == S_OK, "got %#lx\n", hr);
1739 ok(music_time == 1000, "got %ld\n", music_time);
1740 music_time = 0xdeadbeef;
1741 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time + 2000 * 6510, &music_time);
1742 ok(hr == S_OK, "got %#lx\n", hr);
1743 ok(music_time == 2000, "got %ld\n", music_time);
1745 time = 0xdeadbeef;
1746 music_time = 0xdeadbeef;
1747 hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
1748 ok(hr == S_OK, "got %#lx\n", hr);
1749 ok(time - init_time <= 200 * 10000, "got %I64d\n", time - init_time);
1750 ok(music_time == (time - init_time) / 6510, "got %ld\n", music_time);
1753 hr = IDirectMusicPerformance_CloseDown(performance);
1754 ok(hr == S_OK, "got %#lx\n", hr);
1756 IDirectMusicPerformance_Release(performance);
1760 static void test_performance_pmsg(void)
1762 static const DWORD delivery_flags[] = {DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGF_TOOL_ATTIME};
1763 static const DWORD message_types[] = {DMUS_PMSGT_MIDI, DMUS_PMSGT_USER};
1764 IDirectMusicPerformance *performance;
1765 IDirectMusicGraph *graph, *performance_graph;
1766 IDirectMusicTool *tool;
1767 DMUS_PMSG *msg, *clone;
1768 MUSIC_TIME music_time;
1769 REFERENCE_TIME time;
1770 HRESULT hr;
1771 DWORD ret;
1772 UINT i;
1774 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
1775 ok(hr == S_OK, "got %#lx\n", hr);
1777 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1778 &IID_IDirectMusicPerformance, (void **)&performance);
1779 ok(hr == S_OK, "got %#lx\n", hr);
1780 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&performance_graph);
1781 ok(hr == S_OK, "got %#lx\n", hr);
1784 hr = IDirectMusicPerformance_AllocPMsg(performance, 0, NULL);
1785 ok(hr == E_POINTER, "got %#lx\n", hr);
1786 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG) - 1, &msg);
1787 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
1789 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1790 ok(hr == S_OK, "got %#lx\n", hr);
1791 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1792 ok(!msg->rtTime, "got %I64d\n", msg->rtTime);
1793 ok(!msg->mtTime, "got %ld\n", msg->mtTime);
1794 ok(!msg->dwFlags, "got %#lx\n", msg->dwFlags);
1795 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1796 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1797 ok(!msg->dwType, "got %#lx\n", msg->dwType);
1798 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1799 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1800 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1802 hr = IDirectMusicPerformance_SendPMsg(performance, NULL);
1803 ok(hr == E_POINTER, "got %#lx\n", hr);
1804 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1805 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
1807 hr = IDirectMusicPerformance_FreePMsg(performance, NULL);
1808 ok(hr == E_POINTER, "got %#lx\n", hr);
1809 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1810 ok(hr == S_OK, "got %#lx\n", hr);
1813 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
1814 ok(hr == S_OK, "got %#lx\n", hr);
1816 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1817 &IID_IDirectMusicGraph, (void **)&graph);
1818 ok(hr == S_OK, "got %#lx\n", hr);
1819 hr = IDirectMusicPerformance_SetGraph(performance, graph);
1820 ok(hr == S_OK, "got %#lx\n", hr);
1821 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
1822 ok(hr == S_OK, "got %#lx\n", hr);
1823 IDirectMusicGraph_Release(graph);
1825 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1826 ok(hr == S_OK, "got %#lx\n", hr);
1827 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1828 ok(!msg->rtTime, "got %I64d\n", msg->rtTime);
1829 ok(!msg->mtTime, "got %ld\n", msg->mtTime);
1830 ok(!msg->dwFlags, "got %#lx\n", msg->dwFlags);
1831 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1832 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1833 ok(!msg->pTool, "got %p\n", msg->pTool);
1834 ok(!msg->pGraph, "got %p\n", msg->pGraph);
1835 ok(!msg->dwType, "got %#lx\n", msg->dwType);
1836 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1837 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1838 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1839 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1840 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
1842 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, NULL);
1843 ok(hr == E_POINTER, "got %#lx\n", hr);
1844 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, NULL, &clone);
1845 ok(hr == E_POINTER, "got %#lx\n", hr);
1846 clone = NULL;
1847 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, &clone);
1848 ok(hr == S_OK, "got %#lx\n", hr);
1849 ok(clone != NULL, "got %p\n", clone);
1851 msg->mtTime = 500;
1852 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
1853 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1854 ok(hr == S_OK, "got %#lx\n", hr);
1855 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1856 ok(hr == DMUS_E_ALREADY_SENT, "got %#lx\n", hr);
1857 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1858 ok(hr == DMUS_E_CANNOT_FREE, "got %#lx\n", hr);
1860 hr = IDirectMusicPerformance_FreePMsg(performance, clone);
1861 ok(hr == S_OK, "got %#lx\n", hr);
1864 /* SendPMsg skips all the tools unless messages are stamped beforehand */
1866 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1867 ok(hr == S_OK, "got %#lx\n", hr);
1868 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1869 msg->mtTime = 0;
1870 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
1871 msg->dwType = DMUS_PMSGT_USER;
1872 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1873 ok(hr == S_OK, "got %#lx\n", hr);
1875 ret = test_tool_wait_message(tool, 10, &msg);
1876 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
1877 ok(!msg, "got %p\n", msg);
1880 /* SendPMsg converts music time to reference time if it is missing */
1882 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1883 ok(hr == S_OK, "got %#lx\n", hr);
1884 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1885 msg->mtTime = 500;
1886 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
1887 msg->dwType = DMUS_PMSGT_USER;
1888 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
1889 ok(hr == S_OK, "got %#lx\n", hr);
1890 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1891 ok(hr == S_OK, "got %#lx\n", hr);
1893 ret = test_tool_wait_message(tool, 50, &msg);
1894 ok(!ret, "got %#lx\n", ret);
1895 ok(msg != NULL, "got %p\n", msg);
1897 time = 0xdeadbeef;
1898 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, msg->mtTime, &time);
1899 ok(hr == S_OK, "got %#lx\n", hr);
1900 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1901 ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1902 ok(msg->mtTime == 500, "got %ld\n", msg->mtTime);
1903 ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1904 ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1905 ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
1906 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1907 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1908 ok(msg->pTool == tool, "got %p\n", msg->pTool);
1909 ok(msg->pGraph == performance_graph, "got %p\n", msg->pGraph);
1910 ok(msg->dwType == DMUS_PMSGT_USER, "got %#lx\n", msg->dwType);
1911 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1912 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1913 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1915 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1916 ok(hr == S_OK, "got %#lx\n", hr);
1919 /* SendPMsg converts reference time to music time if it is missing */
1921 hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
1922 ok(hr == S_OK, "got %#lx\n", hr);
1924 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1925 ok(hr == S_OK, "got %#lx\n", hr);
1926 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1927 msg->rtTime = time;
1928 msg->dwFlags = DMUS_PMSGF_REFTIME;
1929 msg->dwType = DMUS_PMSGT_USER;
1930 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
1931 ok(hr == S_OK, "got %#lx\n", hr);
1932 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1933 ok(hr == S_OK, "got %#lx\n", hr);
1935 ret = test_tool_wait_message(tool, 50, &msg);
1936 ok(!ret, "got %#lx\n", ret);
1937 ok(msg != NULL, "got %p\n", msg);
1939 music_time = 0xdeadbeef;
1940 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, msg->rtTime, &music_time);
1941 ok(hr == S_OK, "got %#lx\n", hr);
1942 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1943 ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1944 ok(msg->mtTime == music_time, "got %ld\n", msg->mtTime);
1945 ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1946 ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1947 ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
1948 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
1949 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
1950 ok(msg->pTool == tool, "got %p\n", msg->pTool);
1951 ok(msg->pGraph == performance_graph, "got %p\n", msg->pGraph);
1952 ok(msg->dwType == DMUS_PMSGT_USER, "got %#lx\n", msg->dwType);
1953 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
1954 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
1955 ok(!msg->punkUser, "got %p\n", msg->punkUser);
1957 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1958 ok(hr == S_OK, "got %#lx\n", hr);
1961 for (i = 0; i < ARRAY_SIZE(delivery_flags); i++)
1963 DWORD duration = 0;
1965 hr = IDirectMusicPerformance_GetTime(performance, &time, NULL);
1966 ok(hr == S_OK, "got %#lx\n", hr);
1967 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
1968 ok(hr == S_OK, "got %#lx\n", hr);
1969 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1970 msg->rtTime = time + 150 * 10000;
1971 msg->dwFlags = DMUS_PMSGF_REFTIME;
1972 msg->dwType = DMUS_PMSGT_USER;
1973 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
1974 ok(hr == S_OK, "got %#lx\n", hr);
1976 msg->dwFlags &= ~(DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME);
1977 msg->dwFlags |= delivery_flags[i];
1979 duration -= GetTickCount();
1980 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
1981 ok(hr == S_OK, "got %#lx\n", hr);
1982 msg = NULL;
1983 ret = test_tool_wait_message(tool, 1000, &msg);
1984 ok(!ret, "got %#lx\n", ret);
1985 ok(msg != NULL, "got %p\n", msg);
1986 duration += GetTickCount();
1988 if (msg) hr = IDirectMusicPerformance_FreePMsg(performance, msg);
1989 ok(hr == S_OK, "got %#lx\n", hr);
1991 switch (delivery_flags[i])
1993 case DMUS_PMSGF_TOOL_IMMEDIATE: ok(duration <= 50, "got %lu\n", duration); break;
1994 case DMUS_PMSGF_TOOL_QUEUE: ok(duration >= 50 && duration <= 125, "got %lu\n", duration); break;
1995 case DMUS_PMSGF_TOOL_ATTIME: ok(duration >= 125 && duration <= 500, "got %lu\n", duration); break;
2000 hr = IDirectMusicPerformance_CloseDown(performance);
2001 ok(hr == S_OK, "got %#lx\n", hr);
2004 IDirectMusicGraph_Release(performance_graph);
2006 IDirectMusicPerformance_Release(performance);
2007 IDirectMusicTool_Release(tool);
2010 #define check_dmus_notification_pmsg(a, b, c) check_dmus_notification_pmsg_(__LINE__, a, b, c)
2011 static void check_dmus_notification_pmsg_(int line, DMUS_NOTIFICATION_PMSG *msg,
2012 const GUID *type, DWORD option)
2014 ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTIFICATION,
2015 "got dwType %#lx\n", msg->dwType);
2016 ok_(__FILE__, line)(IsEqualGUID(&msg->guidNotificationType, type),
2017 "got guidNotificationType %s\n", debugstr_guid(&msg->guidNotificationType));
2018 ok_(__FILE__, line)(msg->dwNotificationOption == option,
2019 "got dwNotificationOption %#lx\n", msg->dwNotificationOption);
2020 ok_(__FILE__, line)(!msg->dwField1, "got dwField1 %lu\n", msg->dwField1);
2021 ok_(__FILE__, line)(!msg->dwField2, "got dwField2 %lu\n", msg->dwField2);
2023 if (!IsEqualGUID(&msg->guidNotificationType, &GUID_NOTIFICATION_SEGMENT))
2024 ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser);
2025 else
2027 check_interface_(line, msg->punkUser, &IID_IDirectMusicSegmentState, TRUE);
2028 check_interface_(line, msg->punkUser, &IID_IDirectMusicSegmentState8, TRUE);
2032 static void test_notification_pmsg(void)
2034 static const DWORD message_types[] =
2036 DMUS_PMSGT_DIRTY,
2037 DMUS_PMSGT_NOTIFICATION,
2038 DMUS_PMSGT_WAVE,
2040 IDirectMusicPerformance *performance;
2041 DMUS_NOTIFICATION_PMSG *notif;
2042 IDirectMusicSegment *segment;
2043 IDirectMusicGraph *graph;
2044 IDirectMusicTool *tool;
2045 DMUS_PMSG *msg;
2046 HRESULT hr;
2047 DWORD ret;
2049 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
2050 ok(hr == S_OK, "got %#lx\n", hr);
2052 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2053 &IID_IDirectMusicPerformance, (void **)&performance);
2054 ok(hr == S_OK, "got %#lx\n", hr);
2056 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
2057 &IID_IDirectMusicGraph, (void **)&graph);
2058 ok(hr == S_OK, "got %#lx\n", hr);
2059 hr = IDirectMusicPerformance_SetGraph(performance, graph);
2060 ok(hr == S_OK, "got %#lx\n", hr);
2061 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
2062 ok(hr == S_OK, "got %#lx\n", hr);
2063 IDirectMusicGraph_Release(graph);
2065 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
2066 ok(hr == S_OK, "got %#lx\n", hr);
2069 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
2070 &IID_IDirectMusicSegment, (void **)&segment);
2071 ok(hr == S_OK, "got %#lx\n", hr);
2073 hr = IDirectMusicSegment8_Download((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
2074 ok(hr == S_OK, "got %#lx\n", hr);
2075 hr = IDirectMusicSegment8_Unload((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
2076 ok(hr == S_OK, "got %#lx\n", hr);
2078 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
2079 ok(hr == S_OK, "got %#lx\n", hr);
2081 ret = test_tool_wait_message(tool, 500, &msg);
2082 todo_wine ok(!ret, "got %#lx\n", ret);
2083 if (!ret)
2085 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2086 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2087 ok(hr == S_OK, "got %#lx\n", hr);
2090 ret = test_tool_wait_message(tool, 500, &msg);
2091 todo_wine ok(!ret, "got %#lx\n", ret);
2092 if (!ret)
2094 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2095 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2096 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2099 ret = test_tool_wait_message(tool, 100, &msg);
2100 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2101 ok(!msg, "got %p\n", msg);
2104 /* AddNotificationType is necessary to receive notification messages */
2106 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
2107 ok(hr == S_OK, "got %#lx\n", hr);
2108 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
2109 ok(hr == S_OK, "got %#lx\n", hr);
2111 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
2112 ok(hr == S_OK, "got %#lx\n", hr);
2114 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2115 todo_wine ok(!ret, "got %#lx\n", ret);
2116 if (!ret)
2118 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
2119 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2120 ok(hr == S_OK, "got %#lx\n", hr);
2123 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2124 todo_wine ok(!ret, "got %#lx\n", ret);
2125 if (!ret)
2127 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
2128 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2129 ok(hr == S_OK, "got %#lx\n", hr);
2132 ret = test_tool_wait_message(tool, 500, &msg);
2133 todo_wine ok(!ret, "got %#lx\n", ret);
2134 if (!ret)
2136 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2137 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2138 ok(hr == S_OK, "got %#lx\n", hr);
2141 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2142 todo_wine ok(!ret, "got %#lx\n", ret);
2143 if (!ret)
2145 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
2146 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2147 ok(hr == S_OK, "got %#lx\n", hr);
2150 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2151 todo_wine ok(!ret, "got %#lx\n", ret);
2152 if (!ret)
2154 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
2155 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2156 ok(hr == S_OK, "got %#lx\n", hr);
2159 ret = test_tool_wait_message(tool, 500, &msg);
2160 todo_wine ok(!ret, "got %#lx\n", ret);
2161 if (!ret)
2163 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
2164 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2165 ok(hr == S_OK, "got %#lx\n", hr);
2168 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
2169 todo_wine ok(!ret, "got %#lx\n", ret);
2170 if (!ret)
2172 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
2173 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2174 ok(hr == S_OK, "got %#lx\n", hr);
2177 ret = test_tool_wait_message(tool, 100, &msg);
2178 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2179 ok(!msg, "got %p\n", msg);
2181 IDirectMusicSegment_Release(segment);
2183 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
2184 ok(hr == S_OK, "got %#lx\n", hr);
2185 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
2186 ok(hr == S_OK, "got %#lx\n", hr);
2189 /* notification messages are also queued for direct access */
2191 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2192 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2193 if (hr == S_OK)
2195 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
2196 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2197 ok(hr == S_OK, "got %#lx\n", hr);
2200 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2201 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2202 if (hr == S_OK)
2204 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
2205 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2206 ok(hr == S_OK, "got %#lx\n", hr);
2209 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2210 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2211 if (hr == S_OK)
2213 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
2214 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2215 ok(hr == S_OK, "got %#lx\n", hr);
2218 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2219 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2220 if (hr == S_OK)
2222 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
2223 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2224 ok(hr == S_OK, "got %#lx\n", hr);
2227 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2228 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2229 if (hr == S_OK)
2231 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
2232 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
2233 ok(hr == S_OK, "got %#lx\n", hr);
2236 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
2237 ok(hr == S_FALSE, "got %#lx\n", hr);
2240 hr = IDirectMusicPerformance_CloseDown(performance);
2241 ok(hr == S_OK, "got %#lx\n", hr);
2243 IDirectMusicPerformance_Release(performance);
2244 IDirectMusicTool_Release(tool);
2247 START_TEST(dmime)
2249 CoInitialize(NULL);
2251 if (missing_dmime())
2253 skip("dmime not available\n");
2254 CoUninitialize();
2255 return;
2257 test_COM_audiopath();
2258 test_COM_audiopathconfig();
2259 test_COM_graph();
2260 test_COM_segment();
2261 test_COM_segmentstate();
2262 test_COM_track();
2263 test_audiopathconfig();
2264 test_graph();
2265 test_segment();
2266 test_gettrack();
2267 test_segment_param();
2268 test_track();
2269 test_parsedescriptor();
2270 test_performance_tool();
2271 test_performance_graph();
2272 test_performance_time();
2273 test_performance_pmsg();
2274 test_notification_pmsg();
2276 CoUninitialize();