dmime/tests: Add a track and longer segment to notifications tests.
[wine.git] / dlls / dmime / tests / dmime.c
blob35a6fbc98f4271437e9ac7bc18a8794791cdc3cb
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 <initguid.h>
25 #include <ole2.h>
26 #include <dmusici.h>
27 #include <dmusicf.h>
28 #include <audioclient.h>
29 #include <guiddef.h>
31 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
32 DEFINE_GUID(GUID_Bunk,0xFFFFFFFF,0xFFFF,0xFFFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
34 static ULONG get_refcount(void *iface)
36 IUnknown *unknown = iface;
37 IUnknown_AddRef(unknown);
38 return IUnknown_Release(unknown);
41 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c, FALSE)
42 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported, BOOL check_refs)
44 ULONG expect_ref = get_refcount(iface_ptr);
45 IUnknown *iface = iface_ptr;
46 HRESULT hr, expected;
47 IUnknown *unk;
49 expected = supported ? S_OK : E_NOINTERFACE;
50 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
51 ok_(__FILE__, line)(hr == expected, "got hr %#lx, expected %#lx.\n", hr, expected);
52 if (SUCCEEDED(hr))
54 LONG ref = get_refcount(unk);
55 if (check_refs) ok_(__FILE__, line)(ref == expect_ref + 1, "got %ld\n", ref);
56 IUnknown_Release(unk);
57 ref = get_refcount(iface_ptr);
58 if (check_refs) ok_(__FILE__, line)(ref == expect_ref, "got %ld\n", ref);
62 static void load_resource(const WCHAR *name, WCHAR *filename)
64 static WCHAR path[MAX_PATH];
65 DWORD written;
66 HANDLE file;
67 HRSRC res;
68 void *ptr;
70 GetTempPathW(ARRAY_SIZE(path), path);
71 GetTempFileNameW(path, name, 0, filename);
73 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
74 ok(file != INVALID_HANDLE_VALUE, "failed to create %s, error %lu\n", debugstr_w(filename), GetLastError());
76 res = FindResourceW(NULL, name, (const WCHAR *)RT_RCDATA);
77 ok(res != 0, "couldn't find resource\n");
78 ptr = LockResource(LoadResource(GetModuleHandleW(NULL ), res ));
79 WriteFile(file, ptr, SizeofResource(GetModuleHandleW(NULL ), res ), &written, NULL);
80 ok(written == SizeofResource(GetModuleHandleW(NULL ), res ), "couldn't write resource\n");
81 CloseHandle(file);
84 static void stream_begin_chunk(IStream *stream, const char type[5], ULARGE_INTEGER *offset)
86 static const LARGE_INTEGER zero = {0};
87 HRESULT hr;
88 hr = IStream_Write(stream, type, 4, NULL);
89 ok(hr == S_OK, "got %#lx\n", hr);
90 hr = IStream_Seek(stream, zero, STREAM_SEEK_CUR, offset);
91 ok(hr == S_OK, "got %#lx\n", hr);
92 hr = IStream_Write(stream, "\0\0\0\0", 4, NULL);
93 ok(hr == S_OK, "got %#lx\n", hr);
96 static void stream_end_chunk(IStream *stream, ULARGE_INTEGER *offset)
98 static const LARGE_INTEGER zero = {0};
99 ULARGE_INTEGER position;
100 HRESULT hr;
101 UINT size;
102 hr = IStream_Seek(stream, zero, STREAM_SEEK_CUR, &position);
103 ok(hr == S_OK, "got %#lx\n", hr);
104 hr = IStream_Seek(stream, *(LARGE_INTEGER *)offset, STREAM_SEEK_SET, NULL);
105 ok(hr == S_OK, "got %#lx\n", hr);
106 size = position.QuadPart - offset->QuadPart - 4;
107 hr = IStream_Write(stream, &size, 4, NULL);
108 ok(hr == S_OK, "got %#lx\n", hr);
109 hr = IStream_Seek(stream, *(LARGE_INTEGER *)&position, STREAM_SEEK_SET, NULL);
110 ok(hr == S_OK, "got %#lx\n", hr);
111 hr = IStream_Write(stream, &zero, (position.QuadPart & 1), NULL);
112 ok(hr == S_OK, "got %#lx\n", hr);
115 #define CHUNK_BEGIN(stream, type) \
116 do { \
117 ULARGE_INTEGER __off; \
118 IStream *__stream = (stream); \
119 stream_begin_chunk(stream, type, &__off); \
122 #define CHUNK_RIFF(stream, form) \
123 do { \
124 ULARGE_INTEGER __off; \
125 IStream *__stream = (stream); \
126 stream_begin_chunk(stream, "RIFF", &__off); \
127 IStream_Write(stream, form, 4, NULL); \
130 #define CHUNK_LIST(stream, form) \
131 do { \
132 ULARGE_INTEGER __off; \
133 IStream *__stream = (stream); \
134 stream_begin_chunk(stream, "LIST", &__off); \
135 IStream_Write(stream, form, 4, NULL); \
138 #define CHUNK_END \
139 while (0); \
140 stream_end_chunk(__stream, &__off); \
141 } while (0)
143 #define CHUNK_DATA(stream, type, data) \
144 CHUNK_BEGIN(stream, type) \
146 IStream_Write((stream), &(data), sizeof(data), NULL); \
148 CHUNK_END
150 #define CHUNK_ARRAY(stream, type, items) \
151 CHUNK_BEGIN(stream, type) \
153 UINT __size = sizeof(*(items)); \
154 IStream_Write((stream), &__size, 4, NULL); \
155 IStream_Write((stream), &(items), sizeof(items), NULL); \
157 CHUNK_END
159 struct test_tool
161 IDirectMusicTool IDirectMusicTool_iface;
162 LONG ref;
164 IDirectMusicGraph *graph;
165 const DWORD *types;
166 DWORD types_count;
168 SRWLOCK lock;
169 HANDLE message_event;
170 DMUS_PMSG *messages[32];
171 UINT message_count;
174 static DMUS_PMSG *test_tool_push_msg(struct test_tool *tool, DMUS_PMSG *msg)
176 AcquireSRWLockExclusive(&tool->lock);
177 ok(tool->message_count < ARRAY_SIZE(tool->messages),
178 "got %u messages\n", tool->message_count + 1);
179 if (tool->message_count < ARRAY_SIZE(tool->messages))
181 memmove(tool->messages + 1, tool->messages,
182 tool->message_count * sizeof(*tool->messages));
183 tool->messages[0] = msg;
184 tool->message_count++;
185 msg = NULL;
187 ReleaseSRWLockExclusive(&tool->lock);
189 return msg;
192 static struct test_tool *impl_from_IDirectMusicTool(IDirectMusicTool *iface)
194 return CONTAINING_RECORD(iface, struct test_tool, IDirectMusicTool_iface);
197 static HRESULT WINAPI test_tool_QueryInterface(IDirectMusicTool *iface, REFIID iid, void **out)
199 if (IsEqualGUID(iid, &IID_IUnknown)
200 || IsEqualGUID(iid, &IID_IDirectMusicTool))
202 IDirectMusicTool_AddRef(iface);
203 *out = iface;
204 return S_OK;
207 ok(IsEqualGUID(iid, &IID_IDirectMusicTool8) || IsEqualGUID(iid, &IID_IPersistStream),
208 "got iid %s\n", debugstr_guid(iid));
209 *out = NULL;
210 return E_NOINTERFACE;
213 static ULONG WINAPI test_tool_AddRef(IDirectMusicTool *iface)
215 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
216 return InterlockedIncrement(&tool->ref);
219 static ULONG WINAPI test_tool_Release(IDirectMusicTool *iface)
221 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
222 ULONG ref = InterlockedDecrement(&tool->ref);
224 if (!ref)
226 if (tool->graph) IDirectMusicGraph_Release(tool->graph);
227 ok(!tool->message_count, "got %p\n", &tool->message_count);
228 CloseHandle(tool->message_event);
229 free(tool);
232 return ref;
235 static HRESULT WINAPI test_tool_Init(IDirectMusicTool *iface, IDirectMusicGraph *graph)
237 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
238 if ((tool->graph = graph)) IDirectMusicGraph_AddRef(tool->graph);
239 return S_OK;
242 static HRESULT WINAPI test_tool_GetMsgDeliveryType(IDirectMusicTool *iface, DWORD *type)
244 *type = DMUS_PMSGF_TOOL_IMMEDIATE;
245 return S_OK;
248 static HRESULT WINAPI test_tool_GetMediaTypeArraySize(IDirectMusicTool *iface, DWORD *size)
250 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
251 *size = tool->types_count;
252 return S_OK;
255 static HRESULT WINAPI test_tool_GetMediaTypes(IDirectMusicTool *iface, DWORD **types, DWORD size)
257 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
258 UINT i;
259 for (i = 0; i < tool->types_count; i++) (*types)[i] = tool->types[i];
260 return S_OK;
263 static HRESULT WINAPI test_tool_ProcessPMsg(IDirectMusicTool *iface, IDirectMusicPerformance *performance, DMUS_PMSG *msg)
265 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
266 DMUS_PMSG *clone;
267 HRESULT hr;
269 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, &clone);
270 ok(hr == S_OK, "got %#lx\n", hr);
271 clone = test_tool_push_msg(tool, clone);
272 ok(!clone, "got %p\n", clone);
273 SetEvent(tool->message_event);
275 hr = IDirectMusicGraph_StampPMsg(msg->pGraph, msg);
276 ok(hr == S_OK, "got %#lx\n", hr);
278 return DMUS_S_REQUEUE;
281 static HRESULT WINAPI test_tool_Flush(IDirectMusicTool *iface, IDirectMusicPerformance *performance,
282 DMUS_PMSG *msg, REFERENCE_TIME time)
284 ok(0, "unexpected %s\n", __func__);
285 return S_OK;
288 static IDirectMusicToolVtbl test_tool_vtbl =
290 test_tool_QueryInterface,
291 test_tool_AddRef,
292 test_tool_Release,
293 test_tool_Init,
294 test_tool_GetMsgDeliveryType,
295 test_tool_GetMediaTypeArraySize,
296 test_tool_GetMediaTypes,
297 test_tool_ProcessPMsg,
298 test_tool_Flush,
301 static HRESULT test_tool_create(const DWORD *types, DWORD types_count,
302 IDirectMusicTool **ret_iface)
304 struct test_tool *tool;
306 *ret_iface = NULL;
307 if (!(tool = calloc(1, sizeof(*tool)))) return E_OUTOFMEMORY;
308 tool->IDirectMusicTool_iface.lpVtbl = &test_tool_vtbl;
309 tool->ref = 1;
311 tool->types = types;
312 tool->types_count = types_count;
313 tool->message_event = CreateEventW(NULL, FALSE, FALSE, NULL);
314 ok(!!tool->message_event, "CreateEventW failed, error %lu\n", GetLastError());
316 *ret_iface = &tool->IDirectMusicTool_iface;
317 return S_OK;
320 static HRESULT test_tool_get_graph(IDirectMusicTool *iface, IDirectMusicGraph **graph)
322 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
323 if ((*graph = tool->graph)) IDirectMusicGraph_AddRef(tool->graph);
324 return tool->graph ? S_OK : DMUS_E_NOT_FOUND;
327 static DWORD test_tool_wait_message(IDirectMusicTool *iface, DWORD timeout, DMUS_PMSG **msg)
329 struct test_tool *tool = impl_from_IDirectMusicTool(iface);
330 DWORD ret = WAIT_FAILED;
334 AcquireSRWLockExclusive(&tool->lock);
335 if (!tool->message_count)
336 *msg = NULL;
337 else
339 UINT index = --tool->message_count;
340 *msg = tool->messages[index];
341 tool->messages[index] = NULL;
343 ReleaseSRWLockExclusive(&tool->lock);
345 if (*msg) return 0;
346 } while (!(ret = WaitForSingleObject(tool->message_event, timeout)));
348 return ret;
351 struct test_loader_stream
353 IStream IStream_iface;
354 IDirectMusicGetLoader IDirectMusicGetLoader_iface;
355 LONG ref;
357 IStream *stream;
358 IDirectMusicLoader *loader;
361 static struct test_loader_stream *impl_from_IStream(IStream *iface)
363 return CONTAINING_RECORD(iface, struct test_loader_stream, IStream_iface);
366 static HRESULT WINAPI test_loader_stream_QueryInterface(IStream *iface, REFIID iid, void **out)
368 struct test_loader_stream *impl = impl_from_IStream(iface);
370 if (IsEqualGUID(iid, &IID_IUnknown)
371 || IsEqualGUID(iid, &IID_IStream))
373 IStream_AddRef(&impl->IStream_iface);
374 *out = &impl->IStream_iface;
375 return S_OK;
378 if (IsEqualGUID(iid, &IID_IDirectMusicGetLoader))
380 IDirectMusicGetLoader_AddRef(&impl->IDirectMusicGetLoader_iface);
381 *out = &impl->IDirectMusicGetLoader_iface;
382 return S_OK;
385 ok(IsEqualGUID(iid, &IID_IStream),
386 "got iid %s\n", debugstr_guid(iid));
387 *out = NULL;
388 return E_NOINTERFACE;
391 static ULONG WINAPI test_loader_stream_AddRef(IStream *iface)
393 struct test_loader_stream *impl = impl_from_IStream(iface);
394 return InterlockedIncrement(&impl->ref);
397 static ULONG WINAPI test_loader_stream_Release(IStream *iface)
399 struct test_loader_stream *impl = impl_from_IStream(iface);
400 ULONG ref = InterlockedDecrement(&impl->ref);
402 if (!ref)
404 IDirectMusicLoader_Release(impl->loader);
405 IStream_Release(impl->stream);
406 free(impl);
409 return ref;
412 static HRESULT WINAPI test_loader_stream_Read(IStream *iface, void *data, ULONG size, ULONG *ret_size)
414 struct test_loader_stream *impl = impl_from_IStream(iface);
415 return IStream_Read(impl->stream, data, size, ret_size);
418 static HRESULT WINAPI test_loader_stream_Write(IStream *iface, const void *data, ULONG size, ULONG *ret_size)
420 ok(0, "Unexpected call.\n");
421 return E_NOTIMPL;
424 static HRESULT WINAPI test_loader_stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD method, ULARGE_INTEGER *ret_offset)
426 struct test_loader_stream *impl = impl_from_IStream(iface);
427 return IStream_Seek(impl->stream, offset, method, ret_offset);
430 static HRESULT WINAPI test_loader_stream_SetSize(IStream *iface, ULARGE_INTEGER size)
432 ok(0, "Unexpected call.\n");
433 return E_NOTIMPL;
436 static HRESULT WINAPI test_loader_stream_CopyTo(IStream *iface, IStream *dest, ULARGE_INTEGER size,
437 ULARGE_INTEGER *read_size, ULARGE_INTEGER *write_size)
439 ok(0, "Unexpected call.\n");
440 return E_NOTIMPL;
443 static HRESULT WINAPI test_loader_stream_Commit(IStream *iface, DWORD flags)
445 ok(0, "Unexpected call.\n");
446 return E_NOTIMPL;
449 static HRESULT WINAPI test_loader_stream_Revert(IStream *iface)
451 ok(0, "Unexpected call.\n");
452 return E_NOTIMPL;
455 static HRESULT WINAPI test_loader_stream_LockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
457 ok(0, "Unexpected call.\n");
458 return E_NOTIMPL;
461 static HRESULT WINAPI test_loader_stream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
463 ok(0, "Unexpected call.\n");
464 return E_NOTIMPL;
467 static HRESULT WINAPI test_loader_stream_Stat(IStream *iface, STATSTG *stat, DWORD flags)
469 ok(0, "Unexpected call.\n");
470 return E_NOTIMPL;
473 static HRESULT WINAPI test_loader_stream_Clone(IStream *iface, IStream **out)
475 ok(0, "Unexpected call.\n");
476 return E_NOTIMPL;
479 static const IStreamVtbl test_loader_stream_vtbl =
481 test_loader_stream_QueryInterface,
482 test_loader_stream_AddRef,
483 test_loader_stream_Release,
484 test_loader_stream_Read,
485 test_loader_stream_Write,
486 test_loader_stream_Seek,
487 test_loader_stream_SetSize,
488 test_loader_stream_CopyTo,
489 test_loader_stream_Commit,
490 test_loader_stream_Revert,
491 test_loader_stream_LockRegion,
492 test_loader_stream_UnlockRegion,
493 test_loader_stream_Stat,
494 test_loader_stream_Clone,
497 static struct test_loader_stream *impl_from_IDirectMusicGetLoader(IDirectMusicGetLoader *iface)
499 return CONTAINING_RECORD(iface, struct test_loader_stream, IDirectMusicGetLoader_iface);
502 static HRESULT WINAPI test_loader_stream_getter_QueryInterface(IDirectMusicGetLoader *iface, REFIID iid, void **out)
504 struct test_loader_stream *impl = impl_from_IDirectMusicGetLoader(iface);
505 return IStream_QueryInterface(&impl->IStream_iface, iid, out);
508 static ULONG WINAPI test_loader_stream_getter_AddRef(IDirectMusicGetLoader *iface)
510 struct test_loader_stream *impl = impl_from_IDirectMusicGetLoader(iface);
511 return IStream_AddRef(&impl->IStream_iface);
514 static ULONG WINAPI test_loader_stream_getter_Release(IDirectMusicGetLoader *iface)
516 struct test_loader_stream *impl = impl_from_IDirectMusicGetLoader(iface);
517 return IStream_Release(&impl->IStream_iface);
520 static HRESULT WINAPI test_loader_stream_getter_GetLoader(IDirectMusicGetLoader *iface, IDirectMusicLoader **ret_loader)
522 struct test_loader_stream *impl = impl_from_IDirectMusicGetLoader(iface);
524 *ret_loader = impl->loader;
525 IDirectMusicLoader_AddRef(impl->loader);
527 return S_OK;
530 static const IDirectMusicGetLoaderVtbl test_loader_stream_getter_vtbl =
532 test_loader_stream_getter_QueryInterface,
533 test_loader_stream_getter_AddRef,
534 test_loader_stream_getter_Release,
535 test_loader_stream_getter_GetLoader,
538 static HRESULT test_loader_stream_create(IStream *stream, IDirectMusicLoader *loader,
539 IStream **ret_iface)
541 struct test_loader_stream *obj;
543 *ret_iface = NULL;
544 if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
545 obj->IStream_iface.lpVtbl = &test_loader_stream_vtbl;
546 obj->IDirectMusicGetLoader_iface.lpVtbl = &test_loader_stream_getter_vtbl;
547 obj->ref = 1;
549 obj->stream = stream;
550 IStream_AddRef(stream);
551 obj->loader = loader;
552 IDirectMusicLoader_AddRef(loader);
554 *ret_iface = &obj->IStream_iface;
555 return S_OK;
558 struct test_track
560 /* Implementing IDirectMusicTrack8 will cause native to call PlayEx */
561 IDirectMusicTrack IDirectMusicTrack_iface;
562 LONG ref;
564 DWORD data;
565 BOOL inserted;
566 BOOL initialized;
567 BOOL downloaded;
568 BOOL playing;
569 BOOL test_play;
570 HANDLE playing_event;
573 #define check_track_state(track, state, value) \
574 do \
576 DWORD ret = impl_from_IDirectMusicTrack(track)->state; \
577 ok(ret == (value), "got %#lx\n", ret); \
578 } while (0);
580 static inline struct test_track *impl_from_IDirectMusicTrack(IDirectMusicTrack *iface)
582 return CONTAINING_RECORD(iface, struct test_track, IDirectMusicTrack_iface);
585 static HRESULT WINAPI test_track_QueryInterface(IDirectMusicTrack *iface, REFIID riid,
586 void **ret_iface)
588 struct test_track *This = impl_from_IDirectMusicTrack(iface);
590 if (IsEqualIID(riid, &IID_IUnknown)
591 || IsEqualIID(riid, &IID_IDirectMusicTrack))
593 *ret_iface = &This->IDirectMusicTrack_iface;
594 IDirectMusicTrack_AddRef(&This->IDirectMusicTrack_iface);
595 return S_OK;
598 ok(IsEqualGUID(riid, &IID_IDirectMusicTrack8) || IsEqualGUID(riid, &IID_IPersistStream),
599 "unexpected %s %p %s\n", __func__, This, debugstr_guid(riid));
600 *ret_iface = NULL;
601 return E_NOINTERFACE;
604 static ULONG WINAPI test_track_AddRef(IDirectMusicTrack *iface)
606 struct test_track *This = impl_from_IDirectMusicTrack(iface);
607 return InterlockedIncrement(&This->ref);
610 static ULONG WINAPI test_track_Release(IDirectMusicTrack *iface)
612 struct test_track *This = impl_from_IDirectMusicTrack(iface);
613 ULONG ref = InterlockedDecrement(&This->ref);
615 if (!ref)
617 CloseHandle(This->playing_event);
618 free(This);
621 return ref;
624 static HRESULT WINAPI test_track_Init(IDirectMusicTrack *iface, IDirectMusicSegment *segment)
626 struct test_track *This = impl_from_IDirectMusicTrack(iface);
627 This->inserted = TRUE;
628 return S_OK;
631 static HRESULT WINAPI test_track_InitPlay(IDirectMusicTrack *iface, IDirectMusicSegmentState *segment_state,
632 IDirectMusicPerformance *performance, void **state_data, DWORD track_id, DWORD segment_flags)
634 struct test_track *This = impl_from_IDirectMusicTrack(iface);
636 ok(!!segment_state, "got %p\n", segment_state);
637 ok(!!performance, "got %p\n", performance);
638 ok(!!state_data, "got %p\n", state_data);
639 ok(!!track_id, "got %lu\n", track_id);
640 ok(!segment_flags, "got %#lx\n", segment_flags);
641 This->initialized = TRUE;
643 *state_data = &This->data;
644 return S_OK;
647 static HRESULT WINAPI test_track_EndPlay(IDirectMusicTrack *iface, void *state_data)
649 struct test_track *This = impl_from_IDirectMusicTrack(iface);
651 ok(state_data == &This->data, "got %p\n", state_data);
652 This->playing = FALSE;
654 return S_OK;
657 static HRESULT WINAPI test_track_Play(IDirectMusicTrack *iface, void *state_data,
658 MUSIC_TIME start_time, MUSIC_TIME end_time, MUSIC_TIME time_offset, DWORD segment_flags,
659 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state, DWORD track_id)
661 struct test_track *This = impl_from_IDirectMusicTrack(iface);
663 if (!This->test_play) return S_OK;
665 ok(state_data == &This->data, "got %p\n", state_data);
666 ok(start_time == 50, "got %lu\n", start_time);
667 ok(end_time == 100, "got %lu\n", end_time);
668 todo_wine ok(time_offset < 0, "got %lu\n", time_offset);
669 ok(segment_flags == (DMUS_TRACKF_DIRTY|DMUS_TRACKF_START|DMUS_TRACKF_SEEK),
670 "got %#lx\n", segment_flags);
671 ok(!!performance, "got %p\n", performance);
672 ok(!!segment_state, "got %p\n", segment_state);
673 ok(!!track_id, "got %lu\n", track_id);
674 This->playing = TRUE;
675 SetEvent(This->playing_event);
677 return S_OK;
680 static HRESULT WINAPI test_track_GetParam(IDirectMusicTrack *iface, REFGUID type, MUSIC_TIME time,
681 MUSIC_TIME *next, void *param)
683 struct test_track *This = impl_from_IDirectMusicTrack(iface);
684 ok(0, "unexpected %s %p\n", __func__, This);
685 return E_NOTIMPL;
688 static HRESULT WINAPI test_track_SetParam(IDirectMusicTrack *iface, REFGUID type, MUSIC_TIME time, void *param)
690 struct test_track *This = impl_from_IDirectMusicTrack(iface);
692 if (IsEqualGUID(type, &GUID_DownloadToAudioPath))
694 This->downloaded = TRUE;
695 return S_OK;
698 if (IsEqualGUID(type, &GUID_UnloadFromAudioPath))
700 This->downloaded = FALSE;
701 return S_OK;
704 ok(0, "unexpected %s %p %s %lu %p\n", __func__, This, debugstr_guid(type), time, param);
705 return E_NOTIMPL;
708 static HRESULT WINAPI test_track_IsParamSupported(IDirectMusicTrack *iface, REFGUID type)
710 struct test_track *This = impl_from_IDirectMusicTrack(iface);
712 if (IsEqualGUID(type, &GUID_DownloadToAudioPath)) return S_OK;
713 if (IsEqualGUID(type, &GUID_UnloadFromAudioPath)) return S_OK;
714 if (IsEqualGUID(type, &GUID_TimeSignature)) return DMUS_E_TYPE_UNSUPPORTED;
715 if (IsEqualGUID(type, &GUID_TempoParam)) return DMUS_E_TYPE_UNSUPPORTED;
717 ok(broken(type->Data1 == 0xe8dbd832), /* native also checks some unknown parameter */
718 "unexpected %s %p %s\n", __func__, This, debugstr_guid(type));
719 return E_NOTIMPL;
722 static HRESULT WINAPI test_track_AddNotificationType(IDirectMusicTrack *iface, REFGUID type)
724 ok(IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT) || IsEqualGUID(type, &GUID_NOTIFICATION_PERFORMANCE),
725 "got %s\n", debugstr_guid(type));
726 return E_NOTIMPL;
729 static HRESULT WINAPI test_track_RemoveNotificationType(IDirectMusicTrack *iface, REFGUID type)
731 ok(IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT) || IsEqualGUID(type, &GUID_NOTIFICATION_PERFORMANCE),
732 "got %s\n", debugstr_guid(type));
733 return E_NOTIMPL;
736 static HRESULT WINAPI test_track_Clone(IDirectMusicTrack *iface, MUSIC_TIME start_time,
737 MUSIC_TIME end_time, IDirectMusicTrack **ret_track)
739 struct test_track *This = impl_from_IDirectMusicTrack(iface);
740 ok(0, "unexpected %s %p\n", __func__, This);
741 return E_NOTIMPL;
744 static const IDirectMusicTrackVtbl test_track_vtbl =
746 test_track_QueryInterface,
747 test_track_AddRef,
748 test_track_Release,
749 test_track_Init,
750 test_track_InitPlay,
751 test_track_EndPlay,
752 test_track_Play,
753 test_track_GetParam,
754 test_track_SetParam,
755 test_track_IsParamSupported,
756 test_track_AddNotificationType,
757 test_track_RemoveNotificationType,
758 test_track_Clone,
761 static HRESULT test_track_create(IDirectMusicTrack **ret_iface, BOOL test_play)
763 struct test_track *track;
765 *ret_iface = NULL;
766 if (!(track = calloc(1, sizeof(*track)))) return E_OUTOFMEMORY;
767 track->IDirectMusicTrack_iface.lpVtbl = &test_track_vtbl;
768 track->ref = 1;
769 track->test_play = test_play;
771 track->playing_event = CreateEventW(NULL, FALSE, FALSE, NULL);
772 ok(!!track->playing_event, "CreateEventW failed, error %lu\n", GetLastError());
774 *ret_iface = &track->IDirectMusicTrack_iface;
775 return S_OK;
778 static DWORD test_track_wait_playing(IDirectMusicTrack *iface, DWORD timeout)
780 struct test_track *This = impl_from_IDirectMusicTrack(iface);
781 return WaitForSingleObject(This->playing_event, timeout);
784 static void create_performance(IDirectMusicPerformance8 **performance, IDirectMusic **dmusic,
785 IDirectSound **dsound, BOOL set_cooplevel)
787 HRESULT hr;
789 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
790 &IID_IDirectMusicPerformance8, (void **)performance);
791 ok(hr == S_OK, "DirectMusicPerformance create failed: %#lx\n", hr);
792 if (dmusic) {
793 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
794 (void **)dmusic);
795 ok(hr == S_OK, "DirectMusic create failed: %#lx\n", hr);
797 if (dsound) {
798 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)dsound, NULL);
799 ok(hr == S_OK, "DirectSoundCreate failed: %#lx\n", hr);
800 if (set_cooplevel) {
801 hr = IDirectSound_SetCooperativeLevel(*dsound, GetForegroundWindow(), DSSCL_PRIORITY);
802 ok(hr == S_OK, "SetCooperativeLevel failed: %#lx\n", hr);
807 static void destroy_performance(IDirectMusicPerformance8 *performance, IDirectMusic *dmusic,
808 IDirectSound *dsound)
810 HRESULT hr;
812 hr = IDirectMusicPerformance8_CloseDown(performance);
813 ok(hr == S_OK, "CloseDown failed: %#lx\n", hr);
814 IDirectMusicPerformance8_Release(performance);
815 if (dmusic)
816 IDirectMusic_Release(dmusic);
817 if (dsound)
818 IDirectSound_Release(dsound);
821 static BOOL missing_dmime(void)
823 IDirectMusicSegment8 *dms;
824 HRESULT hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
825 &IID_IDirectMusicSegment, (void**)&dms);
827 if (hr == S_OK && dms)
829 IDirectMusicSegment8_Release(dms);
830 return FALSE;
832 return TRUE;
835 static void test_COM_audiopath(void)
837 IDirectMusicAudioPath *dmap;
838 IUnknown *unk;
839 IDirectMusicPerformance8 *performance;
840 IDirectSoundBuffer *dsound;
841 IDirectSoundBuffer8 *dsound8;
842 IDirectSoundNotify *notify;
843 IDirectSound3DBuffer *dsound3d;
844 IKsPropertySet *propset;
845 ULONG refcount;
846 HRESULT hr;
847 DWORD buffer = 0;
849 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
850 &IID_IDirectMusicPerformance8, (void**)&performance);
851 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "DirectMusicPerformance create failed: %#lx\n", hr);
852 if (!performance) {
853 win_skip("IDirectMusicPerformance8 not available\n");
854 return;
856 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL,
857 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
858 ok(hr == S_OK || hr == DSERR_NODRIVER ||
859 broken(hr == AUDCLNT_E_ENDPOINT_CREATE_FAILED), /* Win 10 testbot */
860 "DirectMusicPerformance_InitAudio failed: %#lx\n", hr);
861 if (FAILED(hr)) {
862 skip("Audio failed to initialize\n");
863 return;
865 hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &dmap);
866 ok(hr == S_OK, "DirectMusicPerformance_GetDefaultAudioPath failed: %#lx\n", hr);
868 /* IDirectMusicObject and IPersistStream are not supported */
869 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IDirectMusicObject, (void**)&unk);
870 todo_wine ok(FAILED(hr) && !unk, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n",
871 hr, unk);
872 if (unk) IUnknown_Release(unk);
873 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IPersistStream, (void**)&unk);
874 todo_wine ok(FAILED(hr) && !unk, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n",
875 hr, unk);
876 if (unk) IUnknown_Release(unk);
878 /* Same refcount for all DirectMusicAudioPath interfaces */
879 refcount = IDirectMusicAudioPath_AddRef(dmap);
880 ok(refcount == 3, "refcount == %lu, expected 3\n", refcount);
882 hr = IDirectMusicAudioPath_QueryInterface(dmap, &IID_IUnknown, (void**)&unk);
883 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
884 ok(unk == (IUnknown*)dmap, "got %p, %p\n", unk, dmap);
885 refcount = IUnknown_AddRef(unk);
886 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
887 refcount = IUnknown_Release(unk);
889 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
890 0, &IID_IDirectSoundBuffer, (void**)&dsound);
891 ok(hr == S_OK, "Failed: %#lx\n", hr);
892 IDirectSoundBuffer_Release(dsound);
894 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
895 0, &IID_IDirectSoundBuffer8, (void**)&dsound8);
896 ok(hr == S_OK, "Failed: %#lx\n", hr);
897 IDirectSoundBuffer8_Release(dsound8);
899 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
900 0, &IID_IDirectSoundNotify, (void**)&notify);
901 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
903 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
904 0, &IID_IDirectSound3DBuffer, (void**)&dsound3d);
905 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
907 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
908 0, &IID_IKsPropertySet, (void**)&propset);
909 todo_wine ok(hr == S_OK, "Failed: %#lx\n", hr);
910 if (propset)
911 IKsPropertySet_Release(propset);
913 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
914 0, &IID_IUnknown, (void**)&unk);
915 ok(hr == S_OK, "Failed: %#lx\n", hr);
916 IUnknown_Release(unk);
918 hr = IDirectMusicAudioPath_GetObjectInPath(dmap, DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, buffer, &GUID_NULL,
919 0, &GUID_NULL, (void**)&unk);
920 ok(hr == E_NOINTERFACE, "Failed: %#lx\n", hr);
922 while (IDirectMusicAudioPath_Release(dmap) > 1); /* performance has a reference too */
923 IDirectMusicPerformance8_CloseDown(performance);
924 IDirectMusicPerformance8_Release(performance);
927 static void test_COM_audiopathconfig(void)
929 IDirectMusicAudioPath *dmap = (IDirectMusicAudioPath*)0xdeadbeef;
930 IDirectMusicObject *dmo;
931 IPersistStream *ps;
932 IUnknown *unk;
933 ULONG refcount;
934 HRESULT hr;
936 /* COM aggregation */
937 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
938 &IID_IUnknown, (void**)&dmap);
939 if (hr == REGDB_E_CLASSNOTREG) {
940 win_skip("DirectMusicAudioPathConfig not registered\n");
941 return;
943 ok(hr == CLASS_E_NOAGGREGATION,
944 "DirectMusicAudioPathConfig create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
945 ok(!dmap, "dmap = %p\n", dmap);
947 /* IDirectMusicAudioPath not supported */
948 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
949 &IID_IDirectMusicAudioPath, (void**)&dmap);
950 todo_wine ok(FAILED(hr) && !dmap,
951 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
953 /* IDirectMusicObject and IPersistStream supported */
954 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
955 &IID_IPersistStream, (void**)&ps);
956 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
957 IPersistStream_Release(ps);
958 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
959 &IID_IDirectMusicObject, (void**)&dmo);
960 ok(hr == S_OK, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr);
962 /* Same refcount for all DirectMusicObject interfaces */
963 refcount = IDirectMusicObject_AddRef(dmo);
964 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
966 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
967 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
968 refcount = IPersistStream_AddRef(ps);
969 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
970 IPersistStream_Release(ps);
972 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IUnknown, (void**)&unk);
973 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
974 refcount = IUnknown_AddRef(unk);
975 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
976 refcount = IUnknown_Release(unk);
978 /* IDirectMusicAudioPath still not supported */
979 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IDirectMusicAudioPath, (void**)&dmap);
980 todo_wine ok(FAILED(hr) && !dmap,
981 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr, dmap);
983 while (IDirectMusicObject_Release(dmo));
987 static void test_COM_graph(void)
989 IDirectMusicGraph *dmg = (IDirectMusicGraph*)0xdeadbeef;
990 IDirectMusicObject *dmo;
991 IPersistStream *ps;
992 IUnknown *unk;
993 ULONG refcount;
994 HRESULT hr;
996 /* COM aggregation */
997 hr = CoCreateInstance(&CLSID_DirectMusicGraph, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
998 &IID_IUnknown, (void**)&dmg);
999 ok(hr == CLASS_E_NOAGGREGATION,
1000 "DirectMusicGraph create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
1001 ok(!dmg, "dmg = %p\n", dmg);
1003 /* Invalid RIID */
1004 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory,
1005 (void**)&dmg);
1006 ok(hr == E_NOINTERFACE, "DirectMusicGraph create failed: %#lx, expected E_NOINTERFACE\n", hr);
1008 /* Same refcount for all DirectMusicGraph interfaces */
1009 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1010 &IID_IDirectMusicGraph, (void**)&dmg);
1011 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
1012 refcount = IDirectMusicGraph_AddRef(dmg);
1013 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
1015 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IDirectMusicObject, (void**)&dmo);
1016 if (hr == E_NOINTERFACE) {
1017 win_skip("DirectMusicGraph without IDirectMusicObject\n");
1018 return;
1020 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
1021 refcount = IDirectMusicObject_AddRef(dmo);
1022 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
1023 refcount = IDirectMusicObject_Release(dmo);
1025 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IPersistStream, (void**)&ps);
1026 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1027 refcount = IPersistStream_AddRef(ps);
1028 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
1029 refcount = IPersistStream_Release(ps);
1031 hr = IDirectMusicGraph_QueryInterface(dmg, &IID_IUnknown, (void**)&unk);
1032 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
1033 refcount = IUnknown_AddRef(unk);
1034 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
1035 refcount = IUnknown_Release(unk);
1037 while (IDirectMusicGraph_Release(dmg));
1040 static void test_COM_segment(void)
1042 IDirectMusicSegment8 *dms = (IDirectMusicSegment8*)0xdeadbeef;
1043 IDirectMusicObject *dmo;
1044 IPersistStream *stream;
1045 IUnknown *unk;
1046 ULONG refcount;
1047 HRESULT hr;
1049 /* COM aggregation */
1050 hr = CoCreateInstance(&CLSID_DirectMusicSegment, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
1051 &IID_IUnknown, (void**)&dms);
1052 ok(hr == CLASS_E_NOAGGREGATION,
1053 "DirectMusicSegment create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
1054 ok(!dms, "dms = %p\n", dms);
1056 /* Invalid RIID */
1057 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1058 &IID_IDirectSound, (void**)&dms);
1059 ok(hr == E_NOINTERFACE, "DirectMusicSegment create failed: %#lx, expected E_NOINTERFACE\n", hr);
1061 /* Same refcount */
1062 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1063 &IID_IDirectMusicSegment8, (void**)&dms);
1064 if (hr == E_NOINTERFACE) {
1065 win_skip("DirectMusicSegment without IDirectMusicSegment8\n");
1066 return;
1068 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
1069 refcount = IDirectMusicSegment8_AddRef(dms);
1070 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
1071 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IDirectMusicObject, (void**)&dmo);
1072 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr);
1073 IDirectMusicSegment8_AddRef(dms);
1074 refcount = IDirectMusicSegment8_Release(dms);
1075 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
1076 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IPersistStream, (void**)&stream);
1077 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1078 refcount = IDirectMusicSegment8_Release(dms);
1079 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
1080 hr = IDirectMusicSegment8_QueryInterface(dms, &IID_IUnknown, (void**)&unk);
1081 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
1082 refcount = IUnknown_Release(unk);
1083 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
1084 refcount = IDirectMusicObject_Release(dmo);
1085 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
1086 refcount = IPersistStream_Release(stream);
1087 ok (refcount == 1, "refcount == %lu, expected 1\n", refcount);
1088 refcount = IDirectMusicSegment8_Release(dms);
1089 ok (refcount == 0, "refcount == %lu, expected 0\n", refcount);
1092 static void test_COM_segmentstate(void)
1094 IDirectMusicSegmentState8 *dmss8 = (IDirectMusicSegmentState8*)0xdeadbeef;
1095 IUnknown *unk;
1096 ULONG refcount;
1097 HRESULT hr;
1099 /* COM aggregation */
1100 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
1101 &IID_IUnknown, (void**)&dmss8);
1102 ok(hr == CLASS_E_NOAGGREGATION,
1103 "DirectMusicSegmentState8 create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
1104 ok(!dmss8, "dmss8 = %p\n", dmss8);
1106 /* Invalid RIID */
1107 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
1108 &IID_IDirectMusicObject, (void**)&dmss8);
1109 ok(hr == E_NOINTERFACE, "DirectMusicSegmentState8 create failed: %#lx, expected E_NOINTERFACE\n", hr);
1111 /* Same refcount for all DirectMusicSegmentState interfaces */
1112 hr = CoCreateInstance(&CLSID_DirectMusicSegmentState, NULL, CLSCTX_INPROC_SERVER,
1113 &IID_IDirectMusicSegmentState8, (void**)&dmss8);
1114 if (hr == E_NOINTERFACE) {
1115 win_skip("DirectMusicSegmentState without IDirectMusicSegmentState8\n");
1116 return;
1118 ok(hr == S_OK, "DirectMusicSegmentState8 create failed: %#lx, expected S_OK\n", hr);
1119 refcount = IDirectMusicSegmentState8_AddRef(dmss8);
1120 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
1122 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, (void**)&unk);
1123 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
1124 refcount = IUnknown_AddRef(unk);
1125 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
1126 refcount = IUnknown_Release(unk);
1128 hr = IDirectMusicSegmentState8_QueryInterface(dmss8, &IID_IUnknown, NULL);
1129 ok(hr == E_POINTER, "got %#lx\n", hr);
1131 while (IDirectMusicSegmentState8_Release(dmss8));
1134 static void test_COM_track(void)
1136 IDirectMusicTrack *dmt;
1137 IDirectMusicTrack8 *dmt8;
1138 IPersistStream *ps;
1139 IUnknown *unk;
1140 ULONG refcount;
1141 HRESULT hr;
1142 #define X(class) &CLSID_ ## class, #class
1143 const struct {
1144 REFCLSID clsid;
1145 const char *name;
1146 BOOL has_dmt8;
1147 } class[] = {
1148 { X(DirectMusicLyricsTrack), TRUE },
1149 { X(DirectMusicMarkerTrack), FALSE },
1150 { X(DirectMusicParamControlTrack), TRUE },
1151 { X(DirectMusicSegmentTriggerTrack), TRUE },
1152 { X(DirectMusicSeqTrack), TRUE },
1153 { X(DirectMusicSysExTrack), TRUE },
1154 { X(DirectMusicTempoTrack), TRUE },
1155 { X(DirectMusicTimeSigTrack), FALSE },
1156 { X(DirectMusicWaveTrack), TRUE }
1158 #undef X
1159 unsigned int i;
1161 for (i = 0; i < ARRAY_SIZE(class); i++) {
1162 trace("Testing %s\n", class[i].name);
1163 /* COM aggregation */
1164 dmt8 = (IDirectMusicTrack8*)0xdeadbeef;
1165 hr = CoCreateInstance(class[i].clsid, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER, &IID_IUnknown,
1166 (void**)&dmt8);
1167 if (hr == REGDB_E_CLASSNOTREG) {
1168 win_skip("%s not registered\n", class[i].name);
1169 continue;
1171 ok(hr == CLASS_E_NOAGGREGATION,
1172 "%s create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", class[i].name, hr);
1173 ok(!dmt8, "dmt8 = %p\n", dmt8);
1175 /* Invalid RIID */
1176 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
1177 (void**)&dmt8);
1178 ok(hr == E_NOINTERFACE, "%s create failed: %#lx, expected E_NOINTERFACE\n", class[i].name, hr);
1180 /* Same refcount for all DirectMusicTrack interfaces */
1181 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
1182 (void**)&dmt);
1183 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
1184 refcount = IDirectMusicTrack_AddRef(dmt);
1185 ok(refcount == 2, "refcount == %lu, expected 2\n", refcount);
1187 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
1188 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1189 refcount = IPersistStream_AddRef(ps);
1190 ok(refcount == 4, "refcount == %lu, expected 4\n", refcount);
1191 IPersistStream_Release(ps);
1193 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IUnknown, (void**)&unk);
1194 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %#lx\n", hr);
1195 refcount = IUnknown_AddRef(unk);
1196 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
1197 refcount = IUnknown_Release(unk);
1199 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
1200 if (class[i].has_dmt8) {
1201 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
1202 refcount = IDirectMusicTrack8_AddRef(dmt8);
1203 ok(refcount == 6, "refcount == %lu, expected 6\n", refcount);
1204 refcount = IDirectMusicTrack8_Release(dmt8);
1205 } else {
1206 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr);
1207 refcount = IDirectMusicTrack_AddRef(dmt);
1208 ok(refcount == 5, "refcount == %lu, expected 5\n", refcount);
1211 while (IDirectMusicTrack_Release(dmt));
1215 static void test_COM_performance(void)
1217 IDirectMusicPerformance *dmp = (IDirectMusicPerformance*)0xdeadbeef;
1218 IDirectMusicPerformance *dmp2;
1219 IDirectMusicPerformance8 *dmp8;
1220 ULONG refcount;
1221 HRESULT hr;
1223 /* COM aggregation */
1224 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, (IUnknown *)0xdeadbeef, CLSCTX_INPROC_SERVER,
1225 &IID_IUnknown, (void**)&dmp);
1226 ok(hr == CLASS_E_NOAGGREGATION,
1227 "DirectMusicPerformance create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr);
1228 ok(!dmp, "dmp = %p\n", dmp);
1230 /* Invalid RIID */
1231 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1232 &IID_IDirectMusicObject, (void**)&dmp);
1233 ok(hr == E_NOINTERFACE, "DirectMusicPerformance create failed: %#lx, expected E_NOINTERFACE\n", hr);
1235 /* Same refcount */
1236 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
1237 &IID_IDirectMusicPerformance, (void**)&dmp);
1238 ok(hr == S_OK, "DirectMusicPerformance create failed: %#lx, expected S_OK\n", hr);
1239 refcount = IDirectMusicPerformance_AddRef(dmp);
1240 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
1241 hr = IDirectMusicPerformance_QueryInterface(dmp, &IID_IDirectMusicPerformance2, (void**)&dmp2);
1242 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicPerformance2 failed: %#lx\n", hr);
1243 IDirectMusicPerformance_AddRef(dmp);
1244 refcount = IDirectMusicPerformance_Release(dmp);
1245 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
1246 hr = IDirectMusicPerformance_QueryInterface(dmp, &IID_IDirectMusicPerformance8, (void**)&dmp8);
1247 ok(hr == S_OK, "QueryInterface for IID_IDirectMusicPerformance8 failed: %#lx\n", hr);
1248 refcount = IDirectMusicPerformance_Release(dmp);
1249 ok (refcount == 3, "refcount == %lu, expected 3\n", refcount);
1250 refcount = IDirectMusicPerformance8_Release(dmp8);
1251 ok (refcount == 2, "refcount == %lu, expected 2\n", refcount);
1252 refcount = IDirectMusicPerformance_Release(dmp2);
1253 ok (refcount == 1, "refcount == %lu, expected 1\n", refcount);
1254 refcount = IDirectMusicPerformance_Release(dmp);
1255 ok (refcount == 0, "refcount == %lu, expected 0\n", refcount);
1258 static void test_audiopathconfig(void)
1260 IDirectMusicObject *dmo;
1261 IPersistStream *ps;
1262 CLSID class = { 0 };
1263 ULARGE_INTEGER size;
1264 HRESULT hr;
1266 hr = CoCreateInstance(&CLSID_DirectMusicAudioPathConfig, NULL, CLSCTX_INPROC_SERVER,
1267 &IID_IDirectMusicObject, (void**)&dmo);
1268 if (hr == REGDB_E_CLASSNOTREG) {
1269 win_skip("DirectMusicAudioPathConfig not registered\n");
1270 return;
1272 ok(hr == S_OK, "DirectMusicAudioPathConfig create failed: %#lx, expected S_OK\n", hr);
1274 /* IPersistStream */
1275 hr = IDirectMusicObject_QueryInterface(dmo, &IID_IPersistStream, (void**)&ps);
1276 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1277 hr = IPersistStream_GetClassID(ps, &class);
1278 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
1279 ok(IsEqualGUID(&class, &CLSID_DirectMusicAudioPathConfig),
1280 "Expected class CLSID_DirectMusicAudioPathConfig got %s\n", wine_dbgstr_guid(&class));
1282 /* Unimplemented IPersistStream methods */
1283 hr = IPersistStream_IsDirty(ps);
1284 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
1285 hr = IPersistStream_GetSizeMax(ps, &size);
1286 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
1287 hr = IPersistStream_Save(ps, NULL, TRUE);
1288 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
1290 while (IDirectMusicObject_Release(dmo));
1293 static void test_graph(void)
1295 IDirectMusicTool *tool1, *tool2, *tmp_tool;
1296 IDirectMusicGraph *graph, *tmp_graph;
1297 IPersistStream *ps;
1298 CLSID class = { 0 };
1299 ULARGE_INTEGER size;
1300 DMUS_PMSG msg;
1301 HRESULT hr;
1303 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1304 &IID_IDirectMusicGraph, (void**)&graph);
1305 ok(hr == S_OK, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr);
1307 /* IPersistStream */
1308 hr = IDirectMusicGraph_QueryInterface(graph, &IID_IPersistStream, (void**)&ps);
1309 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1310 hr = IPersistStream_GetClassID(ps, &class);
1311 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
1312 if (hr == S_OK)
1313 ok(IsEqualGUID(&class, &CLSID_DirectMusicGraph),
1314 "Expected class CLSID_DirectMusicGraph got %s\n", wine_dbgstr_guid(&class));
1316 /* Unimplemented IPersistStream methods */
1317 hr = IPersistStream_IsDirty(ps);
1318 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
1319 hr = IPersistStream_GetSizeMax(ps, &size);
1320 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
1321 hr = IPersistStream_Save(ps, NULL, TRUE);
1322 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
1324 IDirectMusicGraph_Release(graph);
1327 hr = test_tool_create(NULL, 0, &tool1);
1328 ok(hr == S_OK, "got %#lx\n", hr);
1329 trace("created tool1 %p\n", tool1);
1330 hr = test_tool_create(NULL, 0, &tool2);
1331 ok(hr == S_OK, "got %#lx\n", hr);
1332 trace("created tool2 %p\n", tool2);
1334 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1335 &IID_IDirectMusicGraph, (void **)&graph);
1336 ok(hr == S_OK, "got %#lx\n", hr);
1339 hr = IDirectMusicGraph_InsertTool(graph, NULL, NULL, 0, -1);
1340 ok(hr == E_POINTER, "got %#lx\n", hr);
1342 /* InsertTool initializes the tool */
1343 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
1344 ok(hr == S_OK, "got %#lx\n", hr);
1345 hr = test_tool_get_graph(tool1, &tmp_graph);
1346 ok(hr == S_OK, "got %#lx\n", hr);
1347 ok(graph == tmp_graph, "got %#lx\n", hr);
1348 IDirectMusicGraph_Release(tmp_graph);
1350 hr = IDirectMusicGraph_InsertTool(graph, tool2, NULL, 0, 1);
1351 ok(hr == S_OK, "got %#lx\n", hr);
1353 hr = IDirectMusicGraph_GetTool(graph, 0, NULL);
1354 ok(hr == E_POINTER, "got %#lx\n", hr);
1355 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
1356 ok(hr == S_OK, "got %#lx\n", hr);
1357 ok(tool1 == tmp_tool, "got %p\n", tmp_tool);
1358 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
1359 hr = IDirectMusicGraph_GetTool(graph, 1, &tmp_tool);
1360 ok(hr == S_OK, "got %#lx\n", hr);
1361 ok(tool2 == tmp_tool, "got %p\n", tmp_tool);
1362 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
1363 hr = IDirectMusicGraph_GetTool(graph, 2, &tmp_tool);
1364 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
1366 /* cannot insert the tool twice */
1367 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
1368 ok(hr == DMUS_E_ALREADY_EXISTS, "got %#lx\n", hr);
1370 /* test removing the first tool */
1371 hr = IDirectMusicGraph_RemoveTool(graph, NULL);
1372 ok(hr == E_POINTER, "got %#lx\n", hr);
1373 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
1374 ok(hr == S_OK, "got %#lx\n", hr);
1375 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
1376 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
1378 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
1379 ok(hr == S_OK, "got %#lx\n", hr);
1380 ok(tool2 == tmp_tool, "got %p\n", tmp_tool);
1381 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
1382 hr = IDirectMusicGraph_GetTool(graph, 1, &tmp_tool);
1383 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
1385 hr = IDirectMusicGraph_InsertTool(graph, tool1, NULL, 0, -1);
1386 ok(hr == S_OK, "got %#lx\n", hr);
1387 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
1388 ok(hr == S_OK, "got %#lx\n", hr);
1389 ok(tool1 == tmp_tool, "got %p\n", tmp_tool);
1390 if (hr == S_OK) IDirectMusicTool_Release(tmp_tool);
1393 /* Test basic IDirectMusicGraph_StampPMsg usage */
1394 hr = IDirectMusicGraph_StampPMsg(graph, NULL);
1395 ok(hr == E_POINTER, "got %#lx\n", hr);
1396 memset(&msg, 0, sizeof(msg));
1397 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1398 ok(hr == S_OK, "got %#lx\n", hr);
1399 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1400 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
1402 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
1403 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
1404 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
1405 ok(msg.dwFlags == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", msg.dwFlags);
1406 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
1407 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
1408 ok(!msg.dwType, "got %#lx\n", msg.dwType);
1409 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
1410 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
1411 ok(!msg.punkUser, "got %p\n", msg.punkUser);
1413 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1414 ok(hr == S_OK, "got %#lx\n", hr);
1415 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1416 ok(msg.pTool == tool2, "got %p\n", msg.pTool);
1417 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1418 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
1419 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1420 ok(!msg.pTool, "got %p\n", msg.pTool);
1421 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1422 ok(hr == S_OK, "got %#lx\n", hr);
1423 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1424 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
1425 IDirectMusicGraph_Release(msg.pGraph);
1426 msg.pGraph = NULL;
1427 IDirectMusicGraph_Release(msg.pTool);
1428 msg.pTool = NULL;
1431 /* test StampPMsg with the wrong graph or innexistant tools */
1432 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
1433 &IID_IDirectMusicGraph, (void **)&tmp_graph);
1434 ok(hr == S_OK, "got %#lx\n", hr);
1436 msg.pGraph = tmp_graph;
1437 IDirectMusicGraph_AddRef(msg.pGraph);
1438 msg.pTool = tool1;
1439 IDirectMusicTool_AddRef(msg.pTool);
1440 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
1441 ok(hr == S_OK, "got %#lx\n", hr);
1442 ok(msg.pGraph == tmp_graph, "got %p\n", msg.pGraph);
1443 ok(msg.pTool == tool2, "got %p\n", msg.pTool);
1444 IDirectMusicGraph_Release(msg.pGraph);
1445 msg.pGraph = NULL;
1447 msg.pGraph = graph;
1448 IDirectMusicGraph_AddRef(msg.pGraph);
1449 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
1450 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
1451 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1452 ok(msg.pTool == NULL, "got %p\n", msg.pTool);
1454 msg.pTool = tool2;
1455 IDirectMusicTool_AddRef(msg.pTool);
1456 hr = IDirectMusicGraph_InsertTool(tmp_graph, tool1, NULL, 0, 0);
1457 ok(hr == S_OK, "got %#lx\n", hr);
1458 hr = IDirectMusicGraph_InsertTool(tmp_graph, tool2, NULL, 0, 0);
1459 ok(hr == S_OK, "got %#lx\n", hr);
1460 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
1461 ok(hr == S_OK, "got %#lx\n", hr);
1462 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
1463 ok(msg.pTool == tool1, "got %p\n", msg.pTool);
1464 IDirectMusicGraph_Release(msg.pGraph);
1465 msg.pGraph = NULL;
1467 hr = IDirectMusicGraph_RemoveTool(graph, tool1);
1468 ok(hr == S_OK, "got %#lx\n", hr);
1469 hr = IDirectMusicGraph_StampPMsg(tmp_graph, &msg);
1470 ok(hr == DMUS_S_LAST_TOOL, "got %#lx\n", hr);
1471 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
1472 ok(msg.pTool == NULL, "got %p\n", msg.pTool);
1474 IDirectMusicGraph_Release(tmp_graph);
1477 IDirectMusicGraph_Release(graph);
1478 IDirectMusicTool_Release(tool2);
1479 IDirectMusicTool_Release(tool1);
1482 static void test_segment(void)
1484 IDirectMusicSegment *dms;
1485 IPersistStream *ps;
1486 CLSID class = { 0 };
1487 ULARGE_INTEGER size;
1488 HRESULT hr;
1490 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1491 &IID_IDirectMusicSegment, (void**)&dms);
1492 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
1494 /* IPersistStream */
1495 hr = IDirectMusicSegment_QueryInterface(dms, &IID_IPersistStream, (void**)&ps);
1496 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1497 hr = IPersistStream_GetClassID(ps, &class);
1498 ok(hr == S_OK || broken(hr == E_NOTIMPL) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr);
1499 if (hr == S_OK)
1500 ok(IsEqualGUID(&class, &CLSID_DirectMusicSegment),
1501 "Expected class CLSID_DirectMusicSegment got %s\n", wine_dbgstr_guid(&class));
1503 /* Unimplemented IPersistStream methods */
1504 hr = IPersistStream_IsDirty(ps);
1505 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
1506 hr = IPersistStream_GetSizeMax(ps, &size);
1507 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
1508 hr = IPersistStream_Save(ps, NULL, TRUE);
1509 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
1511 while (IDirectMusicSegment_Release(dms));
1514 static void _add_track(IDirectMusicSegment8 *seg, REFCLSID class, const char *name, DWORD group)
1516 IDirectMusicTrack *track;
1517 HRESULT hr;
1519 hr = CoCreateInstance(class, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
1520 (void**)&track);
1521 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", name, hr);
1522 hr = IDirectMusicSegment8_InsertTrack(seg, track, group);
1523 if (group)
1524 ok(hr == S_OK, "Inserting %s failed: %#lx, expected S_OK\n", name, hr);
1525 else
1526 ok(hr == E_INVALIDARG, "Inserting %s failed: %#lx, expected E_INVALIDARG\n", name, hr);
1527 IDirectMusicTrack_Release(track);
1530 #define add_track(seg, class, group) _add_track(seg, &CLSID_DirectMusic ## class, #class, group)
1532 static void _expect_track(IDirectMusicSegment8 *seg, REFCLSID expect, const char *name, DWORD group,
1533 DWORD index, BOOL ignore_guid)
1535 IDirectMusicTrack *track;
1536 IPersistStream *ps;
1537 CLSID class;
1538 HRESULT hr;
1540 if (ignore_guid)
1541 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, group, index, &track);
1542 else
1543 hr = IDirectMusicSegment8_GetTrack(seg, expect, group, index, &track);
1544 if (!expect) {
1545 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
1546 return;
1549 ok(hr == S_OK, "GetTrack failed: %#lx, expected S_OK\n", hr);
1550 hr = IDirectMusicTrack_QueryInterface(track, &IID_IPersistStream, (void**)&ps);
1551 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1552 hr = IPersistStream_GetClassID(ps, &class);
1553 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
1554 ok(IsEqualGUID(&class, expect), "For group %#lx index %lu: Expected class %s got %s\n",
1555 group, index, name, wine_dbgstr_guid(&class));
1557 IPersistStream_Release(ps);
1558 IDirectMusicTrack_Release(track);
1561 #define expect_track(seg, class, group, index) \
1562 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, TRUE)
1563 #define expect_guid_track(seg, class, group, index) \
1564 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, FALSE)
1566 static void test_gettrack(void)
1568 IDirectMusicSegment8 *seg;
1569 IDirectMusicTrack *track;
1570 HRESULT hr;
1572 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1573 &IID_IDirectMusicSegment8, (void**)&seg);
1574 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
1576 add_track(seg, LyricsTrack, 0x0); /* failure */
1577 add_track(seg, LyricsTrack, 0x1); /* idx 0 group 1 */
1578 add_track(seg, ParamControlTrack, 0x3); /* idx 1 group 1, idx 0 group 2 */
1579 add_track(seg, SegmentTriggerTrack, 0x2); /* idx 1 group 2 */
1580 add_track(seg, SeqTrack, 0x1); /* idx 2 group 1 */
1581 add_track(seg, TempoTrack, 0x7); /* idx 3 group 1, idx 2 group 2, idx 0 group 3 */
1582 add_track(seg, WaveTrack, 0xffffffff); /* idx 4 group 1, idx 3 group 2, idx 1 group 3 */
1584 /* Ignore GUID in GetTrack */
1585 hr = IDirectMusicSegment8_GetTrack(seg, &GUID_NULL, 0, 0, &track);
1586 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
1588 expect_track(seg, LyricsTrack, 0x1, 0);
1589 expect_track(seg, ParamControlTrack, 0x1, 1);
1590 expect_track(seg, SeqTrack, 0x1, 2);
1591 expect_track(seg, TempoTrack, 0x1, 3);
1592 expect_track(seg, WaveTrack, 0x1, 4);
1593 _expect_track(seg, NULL, "", 0x1, 5, TRUE);
1594 _expect_track(seg, NULL, "", 0x1, DMUS_SEG_ANYTRACK, TRUE);
1595 expect_track(seg, ParamControlTrack, 0x2, 0);
1596 expect_track(seg, WaveTrack, 0x80000000, 0);
1597 expect_track(seg, SegmentTriggerTrack, 0x3, 2); /* groups 1+2 combined index */
1598 expect_track(seg, SeqTrack, 0x3, 3); /* groups 1+2 combined index */
1599 expect_track(seg, TempoTrack, 0x7, 4); /* groups 1+2+3 combined index */
1600 expect_track(seg, TempoTrack, 0xffffffff, 4); /* all groups combined index */
1601 _expect_track(seg, NULL, "", 0xffffffff, DMUS_SEG_ANYTRACK, TRUE);
1603 /* Use the GUID in GetTrack */
1604 hr = IDirectMusicSegment8_GetTrack(seg, &CLSID_DirectMusicLyricsTrack, 0, 0, &track);
1605 ok(hr == DMUS_E_NOT_FOUND, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr);
1607 expect_guid_track(seg, LyricsTrack, 0x1, 0);
1608 expect_guid_track(seg, ParamControlTrack, 0x1, 0);
1609 expect_guid_track(seg, SeqTrack, 0x1, 0);
1610 expect_guid_track(seg, TempoTrack, 0x1, 0);
1611 expect_guid_track(seg, ParamControlTrack, 0x2, 0);
1612 expect_guid_track(seg, SegmentTriggerTrack, 0x3, 0);
1613 expect_guid_track(seg, SeqTrack, 0x3, 0);
1614 expect_guid_track(seg, TempoTrack, 0x7, 0);
1615 expect_guid_track(seg, TempoTrack, 0xffffffff, 0);
1617 IDirectMusicSegment8_Release(seg);
1620 static void test_segment_param(void)
1622 IDirectMusicSegment8 *seg;
1623 char buf[64];
1624 HRESULT hr;
1626 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
1627 &IID_IDirectMusicSegment8, (void **)&seg);
1628 ok(hr == S_OK, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr);
1630 add_track(seg, LyricsTrack, 0x1); /* no params */
1631 add_track(seg, SegmentTriggerTrack, 0x1); /* all params "supported" */
1633 hr = IDirectMusicSegment8_GetParam(seg, NULL, 0x1, 0, 0, NULL, buf);
1634 ok(hr == E_POINTER, "GetParam failed: %#lx, expected E_POINTER\n", hr);
1635 hr = IDirectMusicSegment8_SetParam(seg, NULL, 0x1, 0, 0, buf);
1636 todo_wine ok(hr == E_POINTER, "SetParam failed: %#lx, expected E_POINTER\n", hr);
1638 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, NULL, buf);
1639 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
1640 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, NULL, buf);
1641 ok(hr == DMUS_E_TRACK_NOT_FOUND, "GetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
1642 hr = IDirectMusicSegment8_GetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ANYTRACK, 0,
1643 NULL, buf);
1644 ok(hr == DMUS_E_GET_UNSUPPORTED, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr);
1646 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 0, 0, buf);
1647 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
1648 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, 1, 0, buf);
1649 todo_wine ok(hr == DMUS_E_TRACK_NOT_FOUND,
1650 "SetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr);
1651 hr = IDirectMusicSegment8_SetParam(seg, &GUID_Valid_Start_Time, 0x1, DMUS_SEG_ALLTRACKS,
1652 0, buf);
1653 ok(hr == S_OK, "SetParam failed: %#lx, expected S_OK\n", hr);
1655 IDirectMusicSegment8_Release(seg);
1658 static void expect_getparam(IDirectMusicTrack *track, REFGUID type, const char *name,
1659 HRESULT expect)
1661 HRESULT hr;
1662 char buf[64] = { 0 };
1664 hr = IDirectMusicTrack_GetParam(track, type, 0, NULL, buf);
1665 ok(hr == expect, "GetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
1668 static void expect_setparam(IDirectMusicTrack *track, REFGUID type, const char *name,
1669 HRESULT expect)
1671 HRESULT hr;
1672 char buf[64] = { 0 };
1674 hr = IDirectMusicTrack_SetParam(track, type, 0, buf);
1675 ok(hr == expect, "SetParam(%s) failed: %#lx, expected %#lx\n", name, hr, expect);
1678 static void test_track(void)
1680 IDirectMusicTrack *dmt;
1681 IDirectMusicTrack8 *dmt8;
1682 IPersistStream *ps;
1683 CLSID classid;
1684 ULARGE_INTEGER size;
1685 HRESULT hr;
1686 #define X(guid) &guid, #guid
1687 const struct {
1688 REFGUID type;
1689 const char *name;
1690 } param_types[] = {
1691 { X(GUID_BandParam) },
1692 { X(GUID_ChordParam) },
1693 { X(GUID_Clear_All_Bands) },
1694 { X(GUID_CommandParam) },
1695 { X(GUID_CommandParam2) },
1696 { X(GUID_CommandParamNext) },
1697 { X(GUID_ConnectToDLSCollection) },
1698 { X(GUID_Disable_Auto_Download) },
1699 { X(GUID_DisableTempo) },
1700 { X(GUID_DisableTimeSig) },
1701 { X(GUID_Download) },
1702 { X(GUID_DownloadToAudioPath) },
1703 { X(GUID_Enable_Auto_Download) },
1704 { X(GUID_EnableTempo) },
1705 { X(GUID_EnableTimeSig) },
1706 { X(GUID_IDirectMusicBand) },
1707 { X(GUID_IDirectMusicChordMap) },
1708 { X(GUID_IDirectMusicStyle) },
1709 { X(GUID_MuteParam) },
1710 { X(GUID_Play_Marker) },
1711 { X(GUID_RhythmParam) },
1712 { X(GUID_SeedVariations) },
1713 { X(GUID_StandardMIDIFile) },
1714 { X(GUID_TempoParam) },
1715 { X(GUID_TimeSignature) },
1716 { X(GUID_Unload) },
1717 { X(GUID_UnloadFromAudioPath) },
1718 { X(GUID_Valid_Start_Time) },
1719 { X(GUID_Variations) },
1720 { X(GUID_NULL) }
1722 #undef X
1723 #define X(class) &CLSID_ ## class, #class
1724 const struct {
1725 REFCLSID clsid;
1726 const char *name;
1727 /* bitfield with supported param types */
1728 unsigned int has_params;
1729 } class[] = {
1730 { X(DirectMusicLyricsTrack), 0 },
1731 { X(DirectMusicMarkerTrack), 0x8080000 },
1732 { X(DirectMusicParamControlTrack), 0 },
1733 { X(DirectMusicSegmentTriggerTrack), 0x3fffffff },
1734 { X(DirectMusicSeqTrack), ~0 }, /* param methods not implemented */
1735 { X(DirectMusicSysExTrack), ~0 }, /* param methods not implemented */
1736 { X(DirectMusicTempoTrack), 0x802100 },
1737 { X(DirectMusicTimeSigTrack), 0x1004200 },
1738 { X(DirectMusicWaveTrack), 0x6001c80 }
1740 #undef X
1741 unsigned int i, j;
1743 for (i = 0; i < ARRAY_SIZE(class); i++) {
1744 trace("Testing %s\n", class[i].name);
1745 hr = CoCreateInstance(class[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack,
1746 (void**)&dmt);
1747 ok(hr == S_OK, "%s create failed: %#lx, expected S_OK\n", class[i].name, hr);
1749 /* IDirectMusicTrack */
1750 if (class[i].has_params != ~0) {
1751 for (j = 0; j < ARRAY_SIZE(param_types); j++) {
1752 hr = IDirectMusicTrack_IsParamSupported(dmt, param_types[j].type);
1753 if (class[i].has_params & (1 << j)) {
1754 ok(hr == S_OK, "IsParamSupported(%s) failed: %#lx, expected S_OK\n",
1755 param_types[j].name, hr);
1756 if (class[i].clsid == &CLSID_DirectMusicSegmentTriggerTrack) {
1757 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1758 DMUS_E_GET_UNSUPPORTED);
1759 expect_setparam(dmt, param_types[j].type, param_types[j].name, S_OK);
1760 } else if (class[i].clsid == &CLSID_DirectMusicMarkerTrack)
1761 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1762 DMUS_E_SET_UNSUPPORTED);
1763 else if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
1764 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1765 DMUS_E_GET_UNSUPPORTED);
1766 } else {
1767 ok(hr == DMUS_E_TYPE_UNSUPPORTED,
1768 "IsParamSupported(%s) failed: %#lx, expected DMUS_E_TYPE_UNSUPPORTED\n",
1769 param_types[j].name, hr);
1770 expect_getparam(dmt, param_types[j].type, param_types[j].name,
1771 DMUS_E_GET_UNSUPPORTED);
1772 if (class[i].clsid == &CLSID_DirectMusicWaveTrack)
1773 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1774 DMUS_E_TYPE_UNSUPPORTED);
1775 else
1776 expect_setparam(dmt, param_types[j].type, param_types[j].name,
1777 DMUS_E_SET_UNSUPPORTED);
1780 /* GetParam / SetParam for IsParamSupported supported types */
1781 if (class[i].clsid == &CLSID_DirectMusicTimeSigTrack) {
1782 expect_getparam(dmt, &GUID_DisableTimeSig, "GUID_DisableTimeSig",
1783 DMUS_E_GET_UNSUPPORTED);
1784 expect_getparam(dmt, &GUID_EnableTimeSig, "GUID_EnableTimeSig",
1785 DMUS_E_GET_UNSUPPORTED);
1786 expect_setparam(dmt, &GUID_TimeSignature, "GUID_TimeSignature",
1787 DMUS_E_SET_UNSUPPORTED);
1788 } else if (class[i].clsid == &CLSID_DirectMusicTempoTrack) {
1789 expect_getparam(dmt, &GUID_DisableTempo, "GUID_DisableTempo",
1790 DMUS_E_GET_UNSUPPORTED);
1791 expect_getparam(dmt, &GUID_EnableTempo, "GUID_EnableTempo",
1792 DMUS_E_GET_UNSUPPORTED);
1795 } else {
1796 hr = IDirectMusicTrack_GetParam(dmt, NULL, 0, NULL, NULL);
1797 ok(hr == E_NOTIMPL, "IDirectMusicTrack_GetParam failed: %#lx\n", hr);
1798 hr = IDirectMusicTrack_SetParam(dmt, NULL, 0, NULL);
1799 ok(hr == E_NOTIMPL, "IDirectMusicTrack_SetParam failed: %#lx\n", hr);
1800 hr = IDirectMusicTrack_IsParamSupported(dmt, NULL);
1801 ok(hr == E_NOTIMPL, "IDirectMusicTrack_IsParamSupported failed: %#lx\n", hr);
1803 hr = IDirectMusicTrack_IsParamSupported(dmt, &GUID_IDirectMusicStyle);
1804 ok(hr == E_NOTIMPL, "got: %#lx\n", hr);
1806 if (class[i].clsid != &CLSID_DirectMusicMarkerTrack &&
1807 class[i].clsid != &CLSID_DirectMusicTimeSigTrack) {
1808 hr = IDirectMusicTrack_AddNotificationType(dmt, NULL);
1809 ok(hr == E_NOTIMPL, "IDirectMusicTrack_AddNotificationType failed: %#lx\n", hr);
1810 hr = IDirectMusicTrack_RemoveNotificationType(dmt, NULL);
1811 ok(hr == E_NOTIMPL, "IDirectMusicTrack_RemoveNotificationType failed: %#lx\n", hr);
1813 hr = IDirectMusicTrack_Clone(dmt, 0, 0, NULL);
1814 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack_Clone failed: %#lx\n", hr);
1816 /* IDirectMusicTrack8 */
1817 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IDirectMusicTrack8, (void**)&dmt8);
1818 if (hr == S_OK) {
1819 hr = IDirectMusicTrack8_PlayEx(dmt8, NULL, 0, 0, 0, 0, NULL, NULL, 0);
1820 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_PlayEx failed: %#lx\n", hr);
1821 if (class[i].has_params == ~0) {
1822 hr = IDirectMusicTrack8_GetParamEx(dmt8, NULL, 0, NULL, NULL, NULL, 0);
1823 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_GetParamEx failed: %#lx\n", hr);
1824 hr = IDirectMusicTrack8_SetParamEx(dmt8, NULL, 0, NULL, NULL, 0);
1825 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_SetParamEx failed: %#lx\n", hr);
1827 hr = IDirectMusicTrack8_Compose(dmt8, NULL, 0, NULL);
1828 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Compose failed: %#lx\n", hr);
1829 hr = IDirectMusicTrack8_Join(dmt8, NULL, 0, NULL, 0, NULL);
1830 if (class[i].clsid == &CLSID_DirectMusicTempoTrack)
1831 todo_wine ok(hr == E_POINTER, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
1832 else
1833 ok(hr == E_NOTIMPL, "IDirectMusicTrack8_Join failed: %#lx\n", hr);
1834 IDirectMusicTrack8_Release(dmt8);
1837 /* IPersistStream */
1838 hr = IDirectMusicTrack_QueryInterface(dmt, &IID_IPersistStream, (void**)&ps);
1839 ok(hr == S_OK, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr);
1840 hr = IPersistStream_GetClassID(ps, &classid);
1841 ok(hr == S_OK, "IPersistStream_GetClassID failed: %#lx\n", hr);
1842 ok(IsEqualGUID(&classid, class[i].clsid),
1843 "Expected class %s got %s\n", class[i].name, wine_dbgstr_guid(&classid));
1844 hr = IPersistStream_IsDirty(ps);
1845 ok(hr == S_FALSE, "IPersistStream_IsDirty failed: %#lx\n", hr);
1847 /* Unimplemented IPersistStream methods */
1848 hr = IPersistStream_GetSizeMax(ps, &size);
1849 ok(hr == E_NOTIMPL, "IPersistStream_GetSizeMax failed: %#lx\n", hr);
1850 hr = IPersistStream_Save(ps, NULL, TRUE);
1851 ok(hr == E_NOTIMPL, "IPersistStream_Save failed: %#lx\n", hr);
1853 while (IDirectMusicTrack_Release(dmt));
1857 struct chunk {
1858 FOURCC id;
1859 DWORD size;
1860 FOURCC type;
1863 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
1865 /* Generate a RIFF file format stream from an array of FOURCC ids.
1866 RIFF and LIST need to be followed by the form type respectively list type,
1867 followed by the chunks of the list and terminated with 0. */
1868 static IStream *gen_riff_stream(const FOURCC *ids)
1870 static const LARGE_INTEGER zero;
1871 int level = -1;
1872 DWORD *sizes[4]; /* Stack for the sizes of RIFF and LIST chunks */
1873 char riff[1024];
1874 char *p = riff;
1875 struct chunk *ck;
1876 IStream *stream;
1878 do {
1879 ck = (struct chunk *)p;
1880 ck->id = *ids++;
1881 switch (ck->id) {
1882 case 0:
1883 *sizes[level] = p - (char *)sizes[level] - sizeof(DWORD);
1884 level--;
1885 break;
1886 case FOURCC_LIST:
1887 case FOURCC_RIFF:
1888 level++;
1889 sizes[level] = &ck->size;
1890 ck->type = *ids++;
1891 p += sizeof(*ck);
1892 break;
1893 case DMUS_FOURCC_GUID_CHUNK:
1894 ck->size = sizeof(GUID_NULL);
1895 p += CHUNK_HDR_SIZE;
1896 memcpy(p, &GUID_NULL, sizeof(GUID_NULL));
1897 p += ck->size;
1898 break;
1899 case DMUS_FOURCC_VERSION_CHUNK:
1901 DMUS_VERSION ver = {5, 8};
1903 ck->size = sizeof(ver);
1904 p += CHUNK_HDR_SIZE;
1905 memcpy(p, &ver, sizeof(ver));
1906 p += ck->size;
1907 break;
1909 default:
1911 /* Just convert the FOURCC id to a WCHAR string */
1912 WCHAR *s;
1914 ck->size = 5 * sizeof(WCHAR);
1915 p += CHUNK_HDR_SIZE;
1916 s = (WCHAR *)p;
1917 s[0] = (char)(ck->id);
1918 s[1] = (char)(ck->id >> 8);
1919 s[2] = (char)(ck->id >> 16);
1920 s[3] = (char)(ck->id >> 24);
1921 s[4] = 0;
1922 p += ck->size;
1925 } while (level >= 0);
1927 ck = (struct chunk *)riff;
1928 CreateStreamOnHGlobal(NULL, TRUE, &stream);
1929 IStream_Write(stream, riff, ck->size + CHUNK_HDR_SIZE, NULL);
1930 IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
1932 return stream;
1935 static void test_parsedescriptor(void)
1937 IDirectMusicObject *dmo;
1938 IStream *stream;
1939 DMUS_OBJECTDESC desc;
1940 HRESULT hr;
1941 DWORD valid;
1942 unsigned int i;
1943 /* fourcc ~0 will be replaced later on */
1944 FOURCC alldesc[] =
1946 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST,
1947 DMUS_FOURCC_UNAM_CHUNK, DMUS_FOURCC_UCOP_CHUNK, DMUS_FOURCC_UCMT_CHUNK,
1948 DMUS_FOURCC_USBJ_CHUNK, 0, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK, 0
1950 FOURCC dupes[] =
1952 FOURCC_RIFF, ~0, DMUS_FOURCC_CATEGORY_CHUNK, DMUS_FOURCC_CATEGORY_CHUNK,
1953 DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_VERSION_CHUNK, DMUS_FOURCC_GUID_CHUNK,
1954 DMUS_FOURCC_GUID_CHUNK, FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, DMUS_FOURCC_UNAM_CHUNK, 0,
1955 FOURCC_LIST, DMUS_FOURCC_UNFO_LIST, mmioFOURCC('I','N','A','M'), 0, 0
1957 FOURCC empty[] = {FOURCC_RIFF, ~0, 0};
1958 FOURCC inam[] = {FOURCC_RIFF, ~0, FOURCC_LIST, ~0, mmioFOURCC('I','N','A','M'), 0, 0};
1959 FOURCC noriff[] = {mmioFOURCC('J','U','N','K'), 0};
1960 #define X(class) &CLSID_ ## class, #class
1961 #define Y(form) form, #form
1962 const struct {
1963 REFCLSID clsid;
1964 const char *class;
1965 FOURCC form;
1966 const char *name;
1967 BOOL needs_size;
1968 } forms[] = {
1969 { X(DirectMusicSegment), Y(DMUS_FOURCC_SEGMENT_FORM), FALSE },
1970 { X(DirectMusicSegment), Y(mmioFOURCC('W','A','V','E')), FALSE },
1971 { X(DirectMusicAudioPathConfig), Y(DMUS_FOURCC_AUDIOPATH_FORM), TRUE },
1972 { X(DirectMusicGraph), Y(DMUS_FOURCC_TOOLGRAPH_FORM), TRUE },
1974 #undef X
1975 #undef Y
1977 for (i = 0; i < ARRAY_SIZE(forms); i++) {
1978 trace("Testing %s / %s\n", forms[i].class, forms[i].name);
1979 hr = CoCreateInstance(forms[i].clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject,
1980 (void **)&dmo);
1981 if (hr != S_OK) {
1982 win_skip("Could not create %s object: %#lx\n", forms[i].class, hr);
1983 return;
1986 /* Nothing loaded */
1987 memset(&desc, 0, sizeof(desc));
1988 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1989 if (forms[i].needs_size) {
1990 todo_wine ok(hr == E_INVALIDARG, "GetDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
1991 desc.dwSize = sizeof(desc);
1992 hr = IDirectMusicObject_GetDescriptor(dmo, &desc);
1994 ok(hr == S_OK, "GetDescriptor failed: %#lx, expected S_OK\n", hr);
1995 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
1996 desc.dwValidData);
1997 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
1998 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
2000 /* Empty RIFF stream */
2001 empty[1] = forms[i].form;
2002 stream = gen_riff_stream(empty);
2003 memset(&desc, 0, sizeof(desc));
2004 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2005 if (forms[i].needs_size) {
2006 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
2007 desc.dwSize = sizeof(desc);
2008 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2010 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
2011 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
2012 desc.dwValidData);
2013 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
2014 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
2016 /* NULL pointers */
2017 memset(&desc, 0, sizeof(desc));
2018 desc.dwSize = sizeof(desc);
2019 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, &desc);
2020 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
2021 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, NULL);
2022 if (forms[i].needs_size)
2023 ok(hr == E_INVALIDARG, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr);
2024 else
2025 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
2026 hr = IDirectMusicObject_ParseDescriptor(dmo, NULL, NULL);
2027 ok(hr == E_POINTER, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr);
2028 IStream_Release(stream);
2030 /* Wrong form */
2031 empty[1] = DMUS_FOURCC_CONTAINER_FORM;
2032 stream = gen_riff_stream(empty);
2033 memset(&desc, 0, sizeof(desc));
2034 desc.dwSize = sizeof(desc);
2035 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2036 if (forms[i].needs_size)
2037 ok(hr == DMUS_E_CHUNKNOTFOUND,
2038 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
2039 else
2040 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
2041 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
2042 IStream_Release(stream);
2044 /* Not a RIFF stream */
2045 stream = gen_riff_stream(noriff);
2046 memset(&desc, 0, sizeof(desc));
2047 desc.dwSize = sizeof(desc);
2048 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2049 if (forms[i].needs_size)
2050 ok(hr == DMUS_E_CHUNKNOTFOUND,
2051 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr);
2052 else
2053 ok(hr == E_FAIL, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr);
2054 ok(!desc.dwValidData, "Got valid data %#lx, expected 0\n", desc.dwValidData);
2055 IStream_Release(stream);
2057 /* All desc chunks */
2058 alldesc[1] = forms[i].form;
2059 stream = gen_riff_stream(alldesc);
2060 memset(&desc, 0, sizeof(desc));
2061 desc.dwSize = sizeof(desc);
2062 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2063 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
2064 valid = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_VERSION;
2065 if (forms[i].form != mmioFOURCC('W','A','V','E'))
2066 valid |= DMUS_OBJ_NAME | DMUS_OBJ_CATEGORY;
2067 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
2068 ok(IsEqualGUID(&desc.guidClass, forms[i].clsid), "Got class guid %s, expected CLSID_%s\n",
2069 wine_dbgstr_guid(&desc.guidClass), forms[i].class);
2070 ok(IsEqualGUID(&desc.guidObject, &GUID_NULL), "Got object guid %s, expected GUID_NULL\n",
2071 wine_dbgstr_guid(&desc.guidClass));
2072 ok(desc.vVersion.dwVersionMS == 5 && desc.vVersion.dwVersionLS == 8,
2073 "Got version %lu.%lu, expected 5.8\n", desc.vVersion.dwVersionMS,
2074 desc.vVersion.dwVersionLS);
2075 if (forms[i].form != mmioFOURCC('W','A','V','E'))
2076 ok(!lstrcmpW(desc.wszName, L"UNAM"), "Got name '%s', expected 'UNAM'\n",
2077 wine_dbgstr_w(desc.wszName));
2078 IStream_Release(stream);
2080 /* Duplicated chunks */
2081 dupes[1] = forms[i].form;
2082 stream = gen_riff_stream(dupes);
2083 memset(&desc, 0, sizeof(desc));
2084 desc.dwSize = sizeof(desc);
2085 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2086 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
2087 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
2088 IStream_Release(stream);
2090 /* UNFO list with INAM */
2091 inam[1] = forms[i].form;
2092 inam[3] = DMUS_FOURCC_UNFO_LIST;
2093 stream = gen_riff_stream(inam);
2094 memset(&desc, 0, sizeof(desc));
2095 desc.dwSize = sizeof(desc);
2096 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2097 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
2098 ok(desc.dwValidData == DMUS_OBJ_CLASS, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
2099 desc.dwValidData);
2100 IStream_Release(stream);
2102 /* INFO list with INAM */
2103 inam[3] = DMUS_FOURCC_INFO_LIST;
2104 stream = gen_riff_stream(inam);
2105 memset(&desc, 0, sizeof(desc));
2106 desc.dwSize = sizeof(desc);
2107 hr = IDirectMusicObject_ParseDescriptor(dmo, stream, &desc);
2108 ok(hr == S_OK, "ParseDescriptor failed: %#lx, expected S_OK\n", hr);
2109 valid = DMUS_OBJ_CLASS;
2110 if (forms[i].form == mmioFOURCC('W','A','V','E'))
2111 valid |= DMUS_OBJ_NAME;
2112 ok(desc.dwValidData == valid, "Got valid data %#lx, expected %#lx\n", desc.dwValidData, valid);
2113 if (forms[i].form == mmioFOURCC('W','A','V','E'))
2114 ok(!lstrcmpW(desc.wszName, L"I"), "Got name '%s', expected 'I'\n",
2115 wine_dbgstr_w(desc.wszName));
2116 IStream_Release(stream);
2118 IDirectMusicObject_Release(dmo);
2122 static void test_performance_InitAudio(void)
2124 DMUS_PORTPARAMS params =
2126 .dwSize = sizeof(params),
2127 .dwValidParams = DMUS_PORTPARAMS_EFFECTS,
2128 .dwEffectFlags = 1,
2130 IDirectMusicPerformance8 *performance;
2131 IDirectMusic *dmusic;
2132 IDirectSound *dsound;
2133 IDirectMusicPort *port;
2134 IDirectMusicAudioPath *path;
2135 DWORD channel, group;
2136 HRESULT hr;
2137 ULONG ref;
2139 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2140 &IID_IDirectMusicPerformance8, (void **)&performance);
2141 if (hr != S_OK) {
2142 win_skip("Cannot create DirectMusicPerformance object (%lx)\n", hr);
2143 CoUninitialize();
2144 return;
2147 dsound = NULL;
2148 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, &dsound, NULL,
2149 DMUS_APATH_SHARED_STEREOPLUSREVERB, 128, DMUS_AUDIOF_ALL, NULL);
2150 if (hr != S_OK) {
2151 IDirectMusicPerformance8_Release(performance);
2152 win_skip("InitAudio failed (%lx)\n", hr);
2153 return;
2156 hr = IDirectMusicPerformance8_PChannelInfo(performance, 128, &port, NULL, NULL);
2157 ok(hr == E_INVALIDARG, "PChannelInfo failed, got %#lx\n", hr);
2158 hr = IDirectMusicPerformance8_PChannelInfo(performance, 127, &port, NULL, NULL);
2159 ok(hr == S_OK, "PChannelInfo failed, got %#lx\n", hr);
2160 IDirectMusicPort_Release(port);
2161 port = NULL;
2162 hr = IDirectMusicPerformance8_PChannelInfo(performance, 0, &port, NULL, NULL);
2163 ok(hr == S_OK, "PChannelInfo failed, got %#lx\n", hr);
2164 ok(port != NULL, "IDirectMusicPort not set\n");
2165 hr = IDirectMusicPerformance8_AssignPChannel(performance, 0, port, 0, 0);
2166 ok(hr == DMUS_E_AUDIOPATHS_IN_USE, "AssignPChannel failed (%#lx)\n", hr);
2167 hr = IDirectMusicPerformance8_AssignPChannelBlock(performance, 0, port, 0);
2168 ok(hr == DMUS_E_AUDIOPATHS_IN_USE, "AssignPChannelBlock failed (%#lx)\n", hr);
2169 IDirectMusicPort_Release(port);
2171 hr = IDirectMusicPerformance8_GetDefaultAudioPath(performance, &path);
2172 ok(hr == S_OK, "Failed to call GetDefaultAudioPath (%lx)\n", hr);
2173 if (hr == S_OK)
2174 IDirectMusicAudioPath_Release(path);
2176 hr = IDirectMusicPerformance8_CloseDown(performance);
2177 ok(hr == S_OK, "Failed to call CloseDown (%lx)\n", hr);
2179 IDirectMusicPerformance8_Release(performance);
2181 /* Auto generated dmusic and dsound */
2182 create_performance(&performance, NULL, NULL, FALSE);
2183 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL, 0, 64, 0, NULL);
2184 ok(hr == S_OK, "InitAudio failed: %#lx\n", hr);
2185 hr = IDirectMusicPerformance8_PChannelInfo(performance, 0, &port, NULL, NULL);
2186 ok(hr == E_INVALIDARG, "PChannelInfo failed, got %#lx\n", hr);
2187 destroy_performance(performance, NULL, NULL);
2189 /* Refcounts for auto generated dmusic and dsound */
2190 create_performance(&performance, NULL, NULL, FALSE);
2191 dmusic = NULL;
2192 dsound = NULL;
2193 hr = IDirectMusicPerformance8_InitAudio(performance, &dmusic, &dsound, NULL, 0, 64, 0, NULL);
2194 ok(hr == S_OK, "InitAudio failed: %#lx\n", hr);
2195 ref = get_refcount(dsound);
2196 ok(ref == 3, "dsound ref count got %ld expected 3\n", ref);
2197 ref = get_refcount(dmusic);
2198 ok(ref == 2, "dmusic ref count got %ld expected 2\n", ref);
2199 destroy_performance(performance, NULL, NULL);
2201 /* dsound without SetCooperativeLevel() */
2202 create_performance(&performance, NULL, &dsound, FALSE);
2203 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, &dsound, NULL, 0, 0, 0, NULL);
2204 todo_wine ok(hr == DSERR_PRIOLEVELNEEDED, "InitAudio failed: %#lx\n", hr);
2205 destroy_performance(performance, NULL, dsound);
2207 /* Using the wrong CLSID_DirectSound */
2208 create_performance(&performance, NULL, NULL, FALSE);
2209 hr = DirectSoundCreate(NULL, &dsound, NULL);
2210 ok(hr == S_OK, "DirectSoundCreate failed: %#lx\n", hr);
2211 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, &dsound, NULL, 0, 0, 0, NULL);
2212 todo_wine ok(hr == E_NOINTERFACE, "InitAudio failed: %#lx\n", hr);
2213 destroy_performance(performance, NULL, dsound);
2215 /* Init() works with just a CLSID_DirectSound */
2216 create_performance(&performance, NULL, NULL, FALSE);
2217 hr = DirectSoundCreate(NULL, &dsound, NULL);
2218 ok(hr == S_OK, "DirectSoundCreate failed: %#lx\n", hr);
2219 hr = IDirectSound_SetCooperativeLevel(dsound, GetForegroundWindow(), DSSCL_PRIORITY);
2220 ok(hr == S_OK, "SetCooperativeLevel failed: %#lx\n", hr);
2221 hr = IDirectMusicPerformance8_Init(performance, NULL, dsound, NULL);
2222 ok(hr == S_OK, "Init failed: %#lx\n", hr);
2223 destroy_performance(performance, NULL, dsound);
2225 /* Init() followed by InitAudio() */
2226 create_performance(&performance, NULL, &dsound, TRUE);
2227 hr = IDirectMusicPerformance8_Init(performance, NULL, dsound, NULL);
2228 ok(hr == S_OK, "Init failed: %#lx\n", hr);
2229 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, &dsound, NULL, 0, 0, 0, NULL);
2230 ok(hr == DMUS_E_ALREADY_INITED, "InitAudio failed: %#lx\n", hr);
2231 destroy_performance(performance, NULL, dsound);
2233 /* Provided dmusic and dsound */
2234 create_performance(&performance, &dmusic, &dsound, TRUE);
2235 hr = IDirectMusicPerformance8_InitAudio(performance, &dmusic, &dsound, NULL, 0, 64, 0, NULL);
2236 ok(hr == S_OK, "InitAudio failed: %#lx\n", hr);
2237 ref = get_refcount(dsound);
2238 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
2239 ref = get_refcount(dmusic);
2240 ok(ref == 2, "dmusic ref count got %ld expected 2\n", ref);
2241 destroy_performance(performance, dmusic, dsound);
2243 /* Provided dmusic initialized with SetDirectSound */
2244 create_performance(&performance, &dmusic, &dsound, TRUE);
2245 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
2246 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
2247 ref = get_refcount(dsound);
2248 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
2249 hr = IDirectMusicPerformance8_InitAudio(performance, &dmusic, NULL, NULL, 0, 64, 0, NULL);
2250 ok(hr == S_OK, "InitAudio failed: %#lx\n", hr);
2251 ref = get_refcount(dsound);
2252 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
2253 ref = get_refcount(dmusic);
2254 ok(ref == 2, "dmusic ref count got %ld expected 2\n", ref);
2255 destroy_performance(performance, dmusic, dsound);
2257 /* Provided dmusic and dsound, dmusic initialized with SetDirectSound */
2258 create_performance(&performance, &dmusic, &dsound, TRUE);
2259 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
2260 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
2261 ref = get_refcount(dsound);
2262 ok(ref == 2, "dsound ref count got %ld expected 2\n", ref);
2263 hr = IDirectMusicPerformance8_InitAudio(performance, &dmusic, &dsound, NULL, 0, 64, 0, NULL);
2264 ok(hr == S_OK, "InitAudio failed: %#lx\n", hr);
2265 ref = get_refcount(dsound);
2266 ok(ref == 3, "dsound ref count got %ld expected 3\n", ref);
2267 ref = get_refcount(dmusic);
2268 ok(ref == 2, "dmusic ref count got %ld expected 2\n", ref);
2269 destroy_performance(performance, dmusic, dsound);
2271 /* Provided dmusic and dsound, dmusic initialized with SetDirectSound, port created and activated */
2272 create_performance(&performance, &dmusic, &dsound, TRUE);
2273 hr = IDirectMusic_SetDirectSound(dmusic, dsound, NULL);
2274 ok(hr == S_OK, "SetDirectSound failed: %#lx\n", hr);
2275 hr = IDirectMusic_CreatePort(dmusic, &CLSID_DirectMusicSynth, &params, &port, NULL);
2276 ok(hr == S_OK, "CreatePort failed: %#lx\n", hr);
2277 hr = IDirectMusicPort_Activate(port, TRUE);
2278 ok(hr == S_OK, "Activate failed: %#lx\n", hr);
2279 hr = IDirectMusicPort_SetNumChannelGroups(port, 1);
2280 ok(hr == S_OK, "SetNumChannelGroups failed: %#lx\n", hr);
2281 hr = IDirectMusicPerformance8_Init(performance, &dmusic, dsound, 0);
2282 ok(hr == S_OK, "Init failed: %#lx\n", hr);
2283 destroy_performance(performance, dmusic, dsound);
2285 /* InitAudio with perf channel count not a multiple of 16 rounds up */
2286 create_performance(&performance, NULL, NULL, TRUE);
2287 hr = IDirectMusicPerformance8_InitAudio(performance, NULL, NULL, NULL,
2288 DMUS_APATH_SHARED_STEREOPLUSREVERB, 29, DMUS_AUDIOF_ALL, NULL);
2289 ok(hr == S_OK, "InitAudio failed: %#lx\n", hr);
2290 hr = IDirectMusicPerformance8_PChannelInfo(performance, 31, &port, &group, &channel);
2291 ok(hr == S_OK && group == 2 && channel == 15,
2292 "PChannelInfo failed, got %#lx, %lu, %lu\n", hr, group, channel);
2293 hr = IDirectMusicPerformance8_PChannelInfo(performance, 32, &port, NULL, NULL);
2294 ok(hr == E_INVALIDARG, "PChannelInfo failed, got %#lx\n", hr);
2295 destroy_performance(performance, NULL, NULL);
2298 static void test_performance_createport(void)
2300 IDirectMusicPerformance8 *perf;
2301 IDirectMusic *music = NULL;
2302 IDirectMusicPort *port = NULL;
2303 DMUS_PORTCAPS portcaps;
2304 DMUS_PORTPARAMS portparams;
2305 DWORD i;
2306 HRESULT hr;
2308 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL,
2309 CLSCTX_INPROC_SERVER, &IID_IDirectMusicPerformance8, (void**)&perf);
2310 ok(hr == S_OK, "CoCreateInstance failed: %#lx\n", hr);
2312 hr = IDirectMusicPerformance8_Init(perf, &music, NULL, NULL);
2313 ok(hr == S_OK, "Init failed: %#lx\n", hr);
2314 ok(music != NULL, "Didn't get IDirectMusic pointer\n");
2316 i = 0;
2317 while(1){
2318 portcaps.dwSize = sizeof(portcaps);
2320 hr = IDirectMusic_EnumPort(music, i, &portcaps);
2321 ok(hr == S_OK || hr == S_FALSE || (i == 0 && hr == E_INVALIDARG), "EnumPort failed: %#lx\n", hr);
2322 if(hr != S_OK)
2323 break;
2325 ok(portcaps.dwSize == sizeof(portcaps), "Got unexpected portcaps struct size: %lu\n", portcaps.dwSize);
2326 trace("portcaps(%lu).dwFlags: %#lx\n", i, portcaps.dwFlags);
2327 trace("portcaps(%lu).guidPort: %s\n", i, wine_dbgstr_guid(&portcaps.guidPort));
2328 trace("portcaps(%lu).dwClass: %#lx\n", i, portcaps.dwClass);
2329 trace("portcaps(%lu).dwType: %#lx\n", i, portcaps.dwType);
2330 trace("portcaps(%lu).dwMemorySize: %#lx\n", i, portcaps.dwMemorySize);
2331 trace("portcaps(%lu).dwMaxChannelGroups: %lu\n", i, portcaps.dwMaxChannelGroups);
2332 trace("portcaps(%lu).dwMaxVoices: %lu\n", i, portcaps.dwMaxVoices);
2333 trace("portcaps(%lu).dwMaxAudioChannels: %lu\n", i, portcaps.dwMaxAudioChannels);
2334 trace("portcaps(%lu).dwEffectFlags: %#lx\n", i, portcaps.dwEffectFlags);
2335 trace("portcaps(%lu).wszDescription: %s\n", i, wine_dbgstr_w(portcaps.wszDescription));
2337 ++i;
2340 if(i == 0){
2341 win_skip("No ports available, skipping tests\n");
2342 return;
2345 portparams.dwSize = sizeof(portparams);
2347 /* dwValidParams == 0 -> S_OK, filled struct */
2348 portparams.dwValidParams = 0;
2349 hr = IDirectMusic_CreatePort(music, &CLSID_DirectMusicSynth, &portparams, &port, NULL);
2350 ok(hr == S_OK, "CreatePort failed: %#lx\n", hr);
2351 ok(port != NULL, "Didn't get IDirectMusicPort pointer\n");
2352 ok(portparams.dwValidParams, "portparams struct was not filled in\n");
2353 IDirectMusicPort_Release(port);
2354 port = NULL;
2356 /* dwValidParams != 0, invalid param -> S_FALSE, filled struct */
2357 portparams.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;
2358 portparams.dwChannelGroups = 0;
2359 hr = IDirectMusic_CreatePort(music, &CLSID_DirectMusicSynth, &portparams, &port, NULL);
2360 todo_wine ok(hr == S_FALSE, "CreatePort failed: %#lx\n", hr);
2361 ok(port != NULL, "Didn't get IDirectMusicPort pointer\n");
2362 ok(portparams.dwValidParams, "portparams struct was not filled in\n");
2363 IDirectMusicPort_Release(port);
2364 port = NULL;
2366 /* dwValidParams != 0, valid params -> S_OK */
2367 hr = IDirectMusic_CreatePort(music, &CLSID_DirectMusicSynth, &portparams, &port, NULL);
2368 ok(hr == S_OK, "CreatePort failed: %#lx\n", hr);
2369 ok(port != NULL, "Didn't get IDirectMusicPort pointer\n");
2370 IDirectMusicPort_Release(port);
2371 port = NULL;
2373 /* GUID_NULL succeeds */
2374 portparams.dwValidParams = 0;
2375 hr = IDirectMusic_CreatePort(music, &GUID_NULL, &portparams, &port, NULL);
2376 ok(hr == S_OK, "CreatePort failed: %#lx\n", hr);
2377 ok(port != NULL, "Didn't get IDirectMusicPort pointer\n");
2378 ok(portparams.dwValidParams, "portparams struct was not filled in\n");
2379 IDirectMusicPort_Release(port);
2380 port = NULL;
2382 /* null GUID fails */
2383 portparams.dwValidParams = 0;
2384 hr = IDirectMusic_CreatePort(music, NULL, &portparams, &port, NULL);
2385 ok(hr == E_POINTER, "CreatePort failed: %#lx\n", hr);
2386 ok(port == NULL, "Get IDirectMusicPort pointer? %p\n", port);
2387 ok(portparams.dwValidParams == 0, "portparams struct was filled in?\n");
2389 /* garbage GUID fails */
2390 portparams.dwValidParams = 0;
2391 hr = IDirectMusic_CreatePort(music, &GUID_Bunk, &portparams, &port, NULL);
2392 ok(hr == E_NOINTERFACE, "CreatePort failed: %#lx\n", hr);
2393 ok(port == NULL, "Get IDirectMusicPort pointer? %p\n", port);
2394 ok(portparams.dwValidParams == 0, "portparams struct was filled in?\n");
2396 hr = IDirectMusicPerformance8_CloseDown(perf);
2397 ok(hr == S_OK, "CloseDown failed: %#lx\n", hr);
2399 IDirectMusic_Release(music);
2400 IDirectMusicPerformance8_Release(perf);
2403 static void test_performance_pchannel(void)
2405 IDirectMusicPerformance8 *perf;
2406 IDirectMusicPort *port = NULL, *port2;
2407 DWORD channel, group;
2408 unsigned int i;
2409 HRESULT hr;
2411 create_performance(&perf, NULL, NULL, TRUE);
2412 hr = IDirectMusicPerformance8_Init(perf, NULL, NULL, NULL);
2413 ok(hr == S_OK, "Init failed: %#lx\n", hr);
2414 hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, &port, NULL, NULL);
2415 ok(hr == E_INVALIDARG && !port, "PChannelInfo failed, got %#lx, %p\n", hr, port);
2417 /* Add default port. Sets PChannels 0-15 to the corresponding channels in group 1 */
2418 hr = IDirectMusicPerformance8_AddPort(perf, NULL);
2419 ok(hr == S_OK, "AddPort of default port failed: %#lx\n", hr);
2420 hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, NULL, NULL, NULL);
2421 ok(hr == S_OK, "PChannelInfo failed, got %#lx\n", hr);
2422 hr = IDirectMusicPerformance8_PChannelInfo(perf, 0, &port, NULL, NULL);
2423 ok(hr == S_OK && port, "PChannelInfo failed, got %#lx, %p\n", hr, port);
2424 for (i = 1; i < 16; i++) {
2425 hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel);
2426 ok(hr == S_OK && port == port2 && group == 1 && channel == i,
2427 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2428 IDirectMusicPort_Release(port2);
2431 /* Unset PChannels fail to retrieve */
2432 hr = IDirectMusicPerformance8_PChannelInfo(perf, 16, &port2, NULL, NULL);
2433 ok(hr == E_INVALIDARG, "PChannelInfo failed, got %#lx, %p\n", hr, port);
2434 hr = IDirectMusicPerformance8_PChannelInfo(perf, MAXDWORD - 16, &port2, NULL, NULL);
2435 ok(hr == E_INVALIDARG, "PChannelInfo failed, got %#lx, %p\n", hr, port);
2437 /* Channel group 0 can be set just fine */
2438 hr = IDirectMusicPerformance8_AssignPChannel(perf, 0, port, 0, 0);
2439 ok(hr == S_OK, "AssignPChannel failed, got %#lx\n", hr);
2440 hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, 0, port, 0);
2441 ok(hr == S_OK, "AssignPChannelBlock failed, got %#lx\n", hr);
2442 for (i = 1; i < 16; i++) {
2443 hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel);
2444 ok(hr == S_OK && port == port2 && group == 0 && channel == i,
2445 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2446 IDirectMusicPort_Release(port2);
2449 /* Last PChannel Block can be set only individually but not read */
2450 hr = IDirectMusicPerformance8_AssignPChannel(perf, MAXDWORD, port, 0, 3);
2451 ok(hr == S_OK, "AssignPChannel failed, got %#lx\n", hr);
2452 port2 = (IDirectMusicPort *)0xdeadbeef;
2453 hr = IDirectMusicPerformance8_PChannelInfo(perf, MAXDWORD, &port2, NULL, NULL);
2454 todo_wine ok(hr == E_INVALIDARG && port2 == (IDirectMusicPort *)0xdeadbeef,
2455 "PChannelInfo failed, got %#lx, %p\n", hr, port2);
2456 hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD, port, 0);
2457 ok(hr == E_INVALIDARG, "AssignPChannelBlock failed, got %#lx\n", hr);
2458 hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD / 16, port, 1);
2459 todo_wine ok(hr == E_INVALIDARG, "AssignPChannelBlock failed, got %#lx\n", hr);
2460 for (i = MAXDWORD - 15; i < MAXDWORD; i++) {
2461 hr = IDirectMusicPerformance8_AssignPChannel(perf, i, port, 0, 0);
2462 ok(hr == S_OK, "AssignPChannel failed, got %#lx\n", hr);
2463 hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, NULL, NULL);
2464 todo_wine ok(hr == E_INVALIDARG && port2 == (IDirectMusicPort *)0xdeadbeef,
2465 "PChannelInfo failed, got %#lx, %p\n", hr, port2);
2468 /* Second to last PChannel Block can be set only individually and read */
2469 hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD / 16 - 1, port, 1);
2470 todo_wine ok(hr == E_INVALIDARG, "AssignPChannelBlock failed, got %#lx\n", hr);
2471 for (i = MAXDWORD - 31; i < MAXDWORD - 15; i++) {
2472 hr = IDirectMusicPerformance8_AssignPChannel(perf, i, port, 1, 7);
2473 ok(hr == S_OK, "AssignPChannel failed, got %#lx\n", hr);
2474 hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel);
2475 ok(hr == S_OK && port2 == port && group == 1 && channel == 7,
2476 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2477 IDirectMusicPort_Release(port2);
2480 /* Third to last PChannel Block behaves normal */
2481 hr = IDirectMusicPerformance8_AssignPChannelBlock(perf, MAXDWORD / 16 - 2, port, 0);
2482 ok(hr == S_OK, "AssignPChannelBlock failed, got %#lx\n", hr);
2483 for (i = MAXDWORD - 47; i < MAXDWORD - 31; i++) {
2484 hr = IDirectMusicPerformance8_PChannelInfo(perf, i, &port2, &group, &channel);
2485 ok(hr == S_OK && port2 == port && group == 0 && channel == i % 16,
2486 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2487 IDirectMusicPort_Release(port2);
2490 /* One PChannel set in a Block, rest is initialized too */
2491 hr = IDirectMusicPerformance8_AssignPChannel(perf, 4711, port, 1, 13);
2492 ok(hr == S_OK, "AssignPChannel failed, got %#lx\n", hr);
2493 hr = IDirectMusicPerformance8_PChannelInfo(perf, 4711, &port2, &group, &channel);
2494 ok(hr == S_OK && port2 == port && group == 1 && channel == 13,
2495 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2496 IDirectMusicPort_Release(port2);
2497 group = channel = 0xdeadbeef;
2498 hr = IDirectMusicPerformance8_PChannelInfo(perf, 4712, &port2, &group, &channel);
2499 ok(hr == S_OK && port2 == port && group == 0 && channel == 8,
2500 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2501 IDirectMusicPort_Release(port2);
2502 group = channel = 0xdeadbeef;
2503 hr = IDirectMusicPerformance8_PChannelInfo(perf, 4719, &port2, &group, &channel);
2504 ok(hr == S_OK && port2 == port && group == 0 && channel == 15,
2505 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr, port2, group, channel);
2506 IDirectMusicPort_Release(port2);
2508 IDirectMusicPort_Release(port);
2509 destroy_performance(perf, NULL, NULL);
2512 static void test_performance_tool(void)
2514 IDirectMusicPerformance *performance;
2515 IDirectMusicGraph *graph;
2516 IDirectMusicTool *tool;
2517 DWORD value, types[1];
2518 DMUS_PMSG msg = {0};
2519 HRESULT hr;
2521 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2522 &IID_IDirectMusicPerformance, (void **)&performance);
2523 ok(hr == S_OK, "got %#lx\n", hr);
2525 check_interface(performance, &IID_IDirectMusicTool8, FALSE);
2527 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicTool, (void **)&tool);
2528 ok(hr == S_OK, "got %#lx\n", hr);
2529 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
2530 ok(hr == S_OK, "got %#lx\n", hr);
2532 hr = IDirectMusicTool_Init(tool, graph);
2533 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
2534 value = 0xdeadbeef;
2535 hr = IDirectMusicTool_GetMsgDeliveryType(tool, &value);
2536 ok(hr == S_OK, "got %#lx\n", hr);
2537 ok(value == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", value);
2538 value = 0xdeadbeef;
2539 hr = IDirectMusicTool_GetMediaTypeArraySize(tool, &value);
2540 ok(hr == S_OK, "got %#lx\n", hr);
2541 ok(value == 0, "got %#lx\n", value);
2542 hr = IDirectMusicTool_GetMediaTypes(tool, (DWORD **)&types, 64);
2543 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
2544 hr = IDirectMusicTool_ProcessPMsg(tool, performance, &msg);
2545 ok(hr == DMUS_S_FREE, "got %#lx\n", hr);
2546 hr = IDirectMusicTool_Flush(tool, performance, &msg, 0);
2547 todo_wine ok(hr == S_OK, "got %#lx\n", hr);
2549 IDirectMusicGraph_Release(graph);
2550 IDirectMusicTool_Release(tool);
2552 IDirectMusicPerformance_Release(performance);
2555 static void test_performance_graph(void)
2557 IDirectMusicPerformance *performance;
2558 IDirectMusicGraph *graph, *tmp_graph;
2559 IDirectMusicTool *tool, *tmp_tool;
2560 DMUS_PMSG msg;
2561 HRESULT hr;
2563 hr = test_tool_create(NULL, 0, &tool);
2564 ok(hr == S_OK, "got %#lx\n", hr);
2566 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2567 &IID_IDirectMusicPerformance, (void **)&performance);
2568 ok(hr == S_OK, "got %#lx\n", hr);
2571 /* performance exposes a graph interface but it's not an actual toolgraph */
2572 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
2573 ok(hr == S_OK, "got %#lx\n", hr);
2574 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
2575 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
2576 hr = IDirectMusicGraph_GetTool(graph, 0, &tmp_tool);
2577 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
2578 hr = IDirectMusicGraph_RemoveTool(graph, tool);
2579 ok(hr == E_NOTIMPL, "got %#lx\n", hr);
2581 /* test IDirectMusicGraph_StampPMsg usage */
2582 hr = IDirectMusicGraph_StampPMsg(graph, NULL);
2583 ok(hr == E_POINTER, "got %#lx\n", hr);
2584 memset(&msg, 0, sizeof(msg));
2585 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
2586 ok(hr == S_OK, "got %#lx\n", hr);
2587 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
2588 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
2589 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
2591 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
2592 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
2593 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
2594 ok(msg.dwFlags == DMUS_PMSGF_TOOL_QUEUE, "got %#lx\n", msg.dwFlags);
2595 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
2596 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
2597 ok(!msg.dwType, "got %#lx\n", msg.dwType);
2598 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
2599 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
2600 ok(!msg.punkUser, "got %p\n", msg.punkUser);
2602 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
2603 ok(hr == S_OK, "got %#lx\n", hr);
2604 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
2605 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
2606 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
2608 IDirectMusicTool_Release(msg.pTool);
2609 msg.pTool = NULL;
2611 IDirectMusicGraph_Release(graph);
2614 /* performance doesn't have a default embedded toolgraph */
2615 hr = IDirectMusicPerformance_GetGraph(performance, &graph);
2616 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
2619 /* test adding a graph to the performance */
2620 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
2621 &IID_IDirectMusicGraph, (void **)&graph);
2622 ok(hr == S_OK, "got %#lx\n", hr);
2623 hr = IDirectMusicPerformance_SetGraph(performance, graph);
2624 ok(hr == S_OK, "got %#lx\n", hr);
2626 hr = IDirectMusicPerformance_GetGraph(performance, &tmp_graph);
2627 ok(hr == S_OK, "got %#lx\n", hr);
2628 ok(tmp_graph == graph, "got %p\n", graph);
2629 IDirectMusicGraph_Release(tmp_graph);
2631 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
2632 ok(hr == S_OK, "got %#lx\n", hr);
2634 IDirectMusicGraph_Release(graph);
2637 /* test IDirectMusicGraph_StampPMsg usage */
2638 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph);
2639 ok(hr == S_OK, "got %#lx\n", hr);
2641 memset(&msg, 0, sizeof(msg));
2642 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
2643 ok(hr == S_OK, "got %#lx\n", hr);
2644 ok(msg.pGraph == graph, "got %p\n", msg.pGraph);
2645 ok(msg.pTool == tool, "got %p\n", msg.pTool);
2647 ok(!msg.dwSize, "got %ld\n", msg.dwSize);
2648 ok(!msg.rtTime, "got %I64d\n", msg.rtTime);
2649 ok(!msg.mtTime, "got %ld\n", msg.mtTime);
2650 ok(msg.dwFlags == DMUS_PMSGF_TOOL_IMMEDIATE, "got %#lx\n", msg.dwFlags);
2651 ok(!msg.dwPChannel, "got %ld\n", msg.dwPChannel);
2652 ok(!msg.dwVirtualTrackID, "got %ld\n", msg.dwVirtualTrackID);
2653 ok(!msg.dwType, "got %#lx\n", msg.dwType);
2654 ok(!msg.dwVoiceID, "got %ld\n", msg.dwVoiceID);
2655 ok(!msg.dwGroupID, "got %ld\n", msg.dwGroupID);
2656 ok(!msg.punkUser, "got %p\n", msg.punkUser);
2658 hr = IDirectMusicGraph_StampPMsg(graph, &msg);
2659 ok(hr == S_OK, "got %#lx\n", hr);
2660 ok(msg.pGraph == NULL, "got %p\n", msg.pGraph);
2661 ok(msg.pTool != NULL, "got %p\n", msg.pTool);
2662 check_interface(msg.pTool, &IID_IDirectMusicPerformance, TRUE);
2664 IDirectMusicTool_Release(msg.pTool);
2665 msg.pTool = NULL;
2667 IDirectMusicGraph_Release(graph);
2670 IDirectMusicPerformance_Release(performance);
2671 IDirectMusicTool_Release(tool);
2674 static void test_performance_time(void)
2676 IDirectMusicPerformance *performance;
2677 REFERENCE_TIME init_time, time;
2678 IReferenceClock *clock;
2679 MUSIC_TIME music_time;
2680 IDirectMusic *dmusic;
2681 HRESULT hr;
2683 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2684 &IID_IDirectMusicPerformance, (void **)&performance);
2685 ok(hr == S_OK, "got %#lx\n", hr);
2688 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, NULL);
2689 ok(hr == E_POINTER, "got %#lx\n", hr);
2690 time = 0xdeadbeef;
2691 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, &time);
2692 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
2693 ok(time == 0, "got %I64d\n", time);
2695 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, 0, NULL);
2696 ok(hr == E_POINTER, "got %#lx\n", hr);
2697 music_time = 0xdeadbeef;
2698 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, 0, &music_time);
2699 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
2700 ok(music_time == 0, "got %ld\n", music_time);
2703 dmusic = NULL;
2704 hr = IDirectMusicPerformance_Init(performance, &dmusic, NULL, NULL);
2705 ok(hr == S_OK, "got %#lx\n", hr);
2706 hr = IDirectMusic_GetMasterClock(dmusic, NULL, &clock);
2707 ok(hr == S_OK, "got %#lx\n", hr);
2708 IDirectMusic_Release(dmusic);
2709 hr = IReferenceClock_GetTime(clock, &init_time);
2710 ok(hr == S_OK, "got %#lx\n", hr);
2711 IReferenceClock_Release(clock);
2714 time = 0xdeadbeef;
2715 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 0, &time);
2716 ok(hr == S_OK, "got %#lx\n", hr);
2717 ok(time - init_time <= 100 * 10000, "got %I64d\n", time - init_time);
2718 init_time = time;
2720 time = 0xdeadbeef;
2721 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 1, &time);
2722 ok(hr == S_OK, "got %#lx\n", hr);
2723 ok(time - init_time >= 6505, "got %I64d\n", time - init_time);
2724 ok(time - init_time <= 6515, "got %I64d\n", time - init_time);
2725 time = 0xdeadbeef;
2726 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 1000, &time);
2727 ok(hr == S_OK, "got %#lx\n", hr);
2728 ok(time - init_time >= 1000 * 6505, "got %I64d\n", time - init_time);
2729 ok(time - init_time <= 1000 * 6515, "got %I64d\n", time - init_time);
2730 time = 0xdeadbeef;
2731 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, 2000, &time);
2732 ok(hr == S_OK, "got %#lx\n", hr);
2733 ok(time - init_time >= 2000 * 6505, "got %I64d\n", time - init_time);
2734 ok(time - init_time <= 2000 * 6515, "got %I64d\n", time - init_time);
2736 music_time = 0xdeadbeef;
2737 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time, &music_time);
2738 ok(hr == S_OK, "got %#lx\n", hr);
2739 ok(music_time == 0, "got %ld\n", music_time);
2740 music_time = 0xdeadbeef;
2741 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time + 1000 * 6510, &music_time);
2742 ok(hr == S_OK, "got %#lx\n", hr);
2743 ok(music_time == 1000, "got %ld\n", music_time);
2744 music_time = 0xdeadbeef;
2745 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, init_time + 2000 * 6510, &music_time);
2746 ok(hr == S_OK, "got %#lx\n", hr);
2747 ok(music_time == 2000, "got %ld\n", music_time);
2749 time = 0xdeadbeef;
2750 music_time = 0xdeadbeef;
2751 hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
2752 ok(hr == S_OK, "got %#lx\n", hr);
2753 ok(time - init_time <= 200 * 10000, "got %I64d\n", time - init_time);
2754 ok(music_time == (time - init_time) / 6510, "got %ld\n", music_time);
2757 hr = IDirectMusicPerformance_CloseDown(performance);
2758 ok(hr == S_OK, "got %#lx\n", hr);
2760 IDirectMusicPerformance_Release(performance);
2764 static void test_performance_pmsg(void)
2766 static const DWORD delivery_flags[] = {DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGF_TOOL_ATTIME};
2767 static const DWORD message_types[] = {DMUS_PMSGT_MIDI, DMUS_PMSGT_USER};
2768 IDirectMusicPerformance *performance;
2769 IDirectMusicGraph *graph, *performance_graph;
2770 IDirectMusicTool *tool;
2771 DMUS_PMSG *msg, *clone;
2772 MUSIC_TIME music_time;
2773 REFERENCE_TIME time;
2774 HRESULT hr;
2775 DWORD ret;
2776 UINT i;
2778 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
2779 ok(hr == S_OK, "got %#lx\n", hr);
2781 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
2782 &IID_IDirectMusicPerformance, (void **)&performance);
2783 ok(hr == S_OK, "got %#lx\n", hr);
2784 hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&performance_graph);
2785 ok(hr == S_OK, "got %#lx\n", hr);
2788 hr = IDirectMusicPerformance_AllocPMsg(performance, 0, NULL);
2789 ok(hr == E_POINTER, "got %#lx\n", hr);
2790 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG) - 1, &msg);
2791 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
2793 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
2794 ok(hr == S_OK, "got %#lx\n", hr);
2795 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2796 ok(!msg->rtTime, "got %I64d\n", msg->rtTime);
2797 ok(!msg->mtTime, "got %ld\n", msg->mtTime);
2798 ok(!msg->dwFlags, "got %#lx\n", msg->dwFlags);
2799 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
2800 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
2801 ok(!msg->dwType, "got %#lx\n", msg->dwType);
2802 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
2803 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
2804 ok(!msg->punkUser, "got %p\n", msg->punkUser);
2806 hr = IDirectMusicPerformance_SendPMsg(performance, NULL);
2807 ok(hr == E_POINTER, "got %#lx\n", hr);
2808 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2809 ok(hr == DMUS_E_NO_MASTER_CLOCK, "got %#lx\n", hr);
2811 hr = IDirectMusicPerformance_FreePMsg(performance, NULL);
2812 ok(hr == E_POINTER, "got %#lx\n", hr);
2813 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2814 ok(hr == S_OK, "got %#lx\n", hr);
2817 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
2818 ok(hr == S_OK, "got %#lx\n", hr);
2820 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
2821 &IID_IDirectMusicGraph, (void **)&graph);
2822 ok(hr == S_OK, "got %#lx\n", hr);
2823 hr = IDirectMusicPerformance_SetGraph(performance, graph);
2824 ok(hr == S_OK, "got %#lx\n", hr);
2825 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
2826 ok(hr == S_OK, "got %#lx\n", hr);
2827 IDirectMusicGraph_Release(graph);
2829 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
2830 ok(hr == S_OK, "got %#lx\n", hr);
2831 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2832 ok(!msg->rtTime, "got %I64d\n", msg->rtTime);
2833 ok(!msg->mtTime, "got %ld\n", msg->mtTime);
2834 ok(!msg->dwFlags, "got %#lx\n", msg->dwFlags);
2835 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
2836 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
2837 ok(!msg->pTool, "got %p\n", msg->pTool);
2838 ok(!msg->pGraph, "got %p\n", msg->pGraph);
2839 ok(!msg->dwType, "got %#lx\n", msg->dwType);
2840 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
2841 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
2842 ok(!msg->punkUser, "got %p\n", msg->punkUser);
2843 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2844 ok(hr == E_INVALIDARG, "got %#lx\n", hr);
2846 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, NULL);
2847 ok(hr == E_POINTER, "got %#lx\n", hr);
2848 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, NULL, &clone);
2849 ok(hr == E_POINTER, "got %#lx\n", hr);
2850 clone = NULL;
2851 hr = IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8 *)performance, msg, &clone);
2852 ok(hr == S_OK, "got %#lx\n", hr);
2853 ok(clone != NULL, "got %p\n", clone);
2855 msg->mtTime = 500;
2856 msg->dwFlags = DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_QUEUE;
2857 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2858 ok(hr == S_OK, "got %#lx\n", hr);
2859 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2860 ok(hr == DMUS_E_ALREADY_SENT, "got %#lx\n", hr);
2861 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2862 ok(hr == DMUS_E_CANNOT_FREE, "got %#lx\n", hr);
2864 hr = IDirectMusicPerformance_FreePMsg(performance, clone);
2865 ok(hr == S_OK, "got %#lx\n", hr);
2868 /* SendPMsg skips all the tools unless messages are stamped beforehand */
2870 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
2871 ok(hr == S_OK, "got %#lx\n", hr);
2872 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2873 msg->mtTime = 0;
2874 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
2875 msg->dwType = DMUS_PMSGT_USER;
2876 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2877 ok(hr == S_OK, "got %#lx\n", hr);
2879 ret = test_tool_wait_message(tool, 10, &msg);
2880 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
2881 ok(!msg, "got %p\n", msg);
2884 /* SendPMsg converts music time to reference time if it is missing */
2886 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
2887 ok(hr == S_OK, "got %#lx\n", hr);
2888 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2889 msg->mtTime = 500;
2890 msg->dwFlags = DMUS_PMSGF_MUSICTIME;
2891 msg->dwType = DMUS_PMSGT_USER;
2892 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
2893 ok(hr == S_OK, "got %#lx\n", hr);
2894 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2895 ok(hr == S_OK, "got %#lx\n", hr);
2897 ret = test_tool_wait_message(tool, 50, &msg);
2898 ok(!ret, "got %#lx\n", ret);
2899 ok(msg != NULL, "got %p\n", msg);
2901 time = 0xdeadbeef;
2902 hr = IDirectMusicPerformance_MusicToReferenceTime(performance, msg->mtTime, &time);
2903 ok(hr == S_OK, "got %#lx\n", hr);
2904 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2905 ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
2906 ok(msg->mtTime == 500, "got %ld\n", msg->mtTime);
2907 ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
2908 ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
2909 ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
2910 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
2911 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
2912 ok(msg->pTool == tool, "got %p\n", msg->pTool);
2913 ok(msg->pGraph == performance_graph, "got %p\n", msg->pGraph);
2914 ok(msg->dwType == DMUS_PMSGT_USER, "got %#lx\n", msg->dwType);
2915 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
2916 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
2917 ok(!msg->punkUser, "got %p\n", msg->punkUser);
2919 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2920 ok(hr == S_OK, "got %#lx\n", hr);
2923 /* SendPMsg converts reference time to music time if it is missing */
2925 hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
2926 ok(hr == S_OK, "got %#lx\n", hr);
2928 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
2929 ok(hr == S_OK, "got %#lx\n", hr);
2930 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2931 msg->rtTime = time;
2932 msg->dwFlags = DMUS_PMSGF_REFTIME;
2933 msg->dwType = DMUS_PMSGT_USER;
2934 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
2935 ok(hr == S_OK, "got %#lx\n", hr);
2936 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2937 ok(hr == S_OK, "got %#lx\n", hr);
2939 ret = test_tool_wait_message(tool, 50, &msg);
2940 ok(!ret, "got %#lx\n", ret);
2941 ok(msg != NULL, "got %p\n", msg);
2943 music_time = 0xdeadbeef;
2944 hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, msg->rtTime, &music_time);
2945 ok(hr == S_OK, "got %#lx\n", hr);
2946 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2947 ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
2948 ok(msg->mtTime == music_time, "got %ld\n", msg->mtTime);
2949 ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
2950 ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
2951 ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
2952 ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
2953 ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
2954 ok(msg->pTool == tool, "got %p\n", msg->pTool);
2955 ok(msg->pGraph == performance_graph, "got %p\n", msg->pGraph);
2956 ok(msg->dwType == DMUS_PMSGT_USER, "got %#lx\n", msg->dwType);
2957 ok(!msg->dwVoiceID, "got %ld\n", msg->dwVoiceID);
2958 ok(!msg->dwGroupID, "got %ld\n", msg->dwGroupID);
2959 ok(!msg->punkUser, "got %p\n", msg->punkUser);
2961 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2962 ok(hr == S_OK, "got %#lx\n", hr);
2965 for (i = 0; i < ARRAY_SIZE(delivery_flags); i++)
2967 DWORD duration = 0;
2969 hr = IDirectMusicPerformance_GetTime(performance, &time, NULL);
2970 ok(hr == S_OK, "got %#lx\n", hr);
2971 hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_PMSG), &msg);
2972 ok(hr == S_OK, "got %#lx\n", hr);
2973 ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
2974 msg->rtTime = time + 150 * 10000;
2975 msg->dwFlags = DMUS_PMSGF_REFTIME;
2976 msg->dwType = DMUS_PMSGT_USER;
2977 hr = IDirectMusicGraph_StampPMsg(performance_graph, msg);
2978 ok(hr == S_OK, "got %#lx\n", hr);
2980 msg->dwFlags &= ~(DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME);
2981 msg->dwFlags |= delivery_flags[i];
2983 duration -= GetTickCount();
2984 hr = IDirectMusicPerformance_SendPMsg(performance, msg);
2985 ok(hr == S_OK, "got %#lx\n", hr);
2986 msg = NULL;
2987 ret = test_tool_wait_message(tool, 1000, &msg);
2988 ok(!ret, "got %#lx\n", ret);
2989 ok(msg != NULL, "got %p\n", msg);
2990 duration += GetTickCount();
2992 if (msg) hr = IDirectMusicPerformance_FreePMsg(performance, msg);
2993 ok(hr == S_OK, "got %#lx\n", hr);
2995 switch (delivery_flags[i])
2997 case DMUS_PMSGF_TOOL_IMMEDIATE: ok(duration <= 50, "got %lu\n", duration); break;
2998 case DMUS_PMSGF_TOOL_QUEUE: ok(duration >= 50 && duration <= 125, "got %lu\n", duration); break;
2999 case DMUS_PMSGF_TOOL_ATTIME: ok(duration >= 125 && duration <= 500, "got %lu\n", duration); break;
3004 hr = IDirectMusicPerformance_CloseDown(performance);
3005 ok(hr == S_OK, "got %#lx\n", hr);
3008 IDirectMusicGraph_Release(performance_graph);
3010 IDirectMusicPerformance_Release(performance);
3011 IDirectMusicTool_Release(tool);
3014 #define check_dmus_notification_pmsg(a, b, c) check_dmus_notification_pmsg_(__LINE__, a, b, c)
3015 static void check_dmus_notification_pmsg_(int line, DMUS_NOTIFICATION_PMSG *msg,
3016 const GUID *type, DWORD option)
3018 ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTIFICATION,
3019 "got dwType %#lx\n", msg->dwType);
3020 ok_(__FILE__, line)(IsEqualGUID(&msg->guidNotificationType, type),
3021 "got guidNotificationType %s\n", debugstr_guid(&msg->guidNotificationType));
3022 todo_wine_if(IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT) &&
3023 (option == DMUS_NOTIFICATION_SEGALMOSTEND || option == DMUS_NOTIFICATION_SEGEND))
3024 ok_(__FILE__, line)(msg->dwNotificationOption == option,
3025 "got dwNotificationOption %#lx\n", msg->dwNotificationOption);
3026 ok_(__FILE__, line)(!msg->dwField1, "got dwField1 %lu\n", msg->dwField1);
3027 ok_(__FILE__, line)(!msg->dwField2, "got dwField2 %lu\n", msg->dwField2);
3029 if (!IsEqualGUID(&msg->guidNotificationType, &GUID_NOTIFICATION_SEGMENT))
3030 ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser);
3031 else
3033 check_interface_(line, msg->punkUser, &IID_IDirectMusicSegmentState, TRUE, FALSE);
3034 check_interface_(line, msg->punkUser, &IID_IDirectMusicSegmentState8, TRUE, FALSE);
3038 static void test_notification_pmsg(void)
3040 static const DWORD message_types[] =
3042 DMUS_PMSGT_DIRTY,
3043 DMUS_PMSGT_NOTIFICATION,
3044 DMUS_PMSGT_WAVE,
3046 IDirectMusicPerformance *performance;
3047 IDirectMusicSegmentState *state;
3048 DMUS_NOTIFICATION_PMSG *notif;
3049 MUSIC_TIME music_time, length;
3050 IDirectMusicSegment *segment;
3051 IDirectMusicTrack *track;
3052 IDirectMusicGraph *graph;
3053 IDirectMusicTool *tool;
3054 DMUS_PMSG *msg;
3055 HRESULT hr;
3056 DWORD ret;
3058 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
3059 ok(hr == S_OK, "got %#lx\n", hr);
3061 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
3062 &IID_IDirectMusicPerformance, (void **)&performance);
3063 ok(hr == S_OK, "got %#lx\n", hr);
3065 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
3066 &IID_IDirectMusicGraph, (void **)&graph);
3067 ok(hr == S_OK, "got %#lx\n", hr);
3068 hr = IDirectMusicPerformance_SetGraph(performance, graph);
3069 ok(hr == S_OK, "got %#lx\n", hr);
3070 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
3071 ok(hr == S_OK, "got %#lx\n", hr);
3072 IDirectMusicGraph_Release(graph);
3074 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
3075 ok(hr == S_OK, "got %#lx\n", hr);
3078 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
3079 &IID_IDirectMusicSegment, (void **)&segment);
3080 ok(hr == S_OK, "got %#lx\n", hr);
3083 /* native needs a track or the segment will end immediately */
3085 hr = test_track_create(&track, FALSE);
3086 ok(hr == S_OK, "got %#lx\n", hr);
3087 hr = IDirectMusicSegment_InsertTrack(segment, track, 1);
3088 ok(hr == S_OK, "got %#lx\n", hr);
3089 IDirectMusicTrack_Release(track);
3091 /* native sends dirty / notification by batch of 1s, shorter length
3092 * will cause all messages to be received immediately */
3093 length = 10005870 / 6510;
3094 hr = IDirectMusicSegment_SetLength(segment, length);
3095 ok(hr == S_OK, "got %#lx\n", hr);
3097 hr = IDirectMusicSegment8_Download((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
3098 ok(hr == S_OK, "got %#lx\n", hr);
3099 hr = IDirectMusicSegment8_Unload((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
3100 ok(hr == S_OK, "got %#lx\n", hr);
3102 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
3103 ok(hr == S_OK, "got %#lx\n", hr);
3104 hr = IDirectMusicPerformance_GetTime(performance, NULL, &music_time);
3105 ok(hr == S_OK, "got %#lx\n", hr);
3107 ret = test_tool_wait_message(tool, 50, &msg);
3108 ok(!ret, "got %#lx\n", ret);
3109 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3110 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3111 ok(hr == S_OK, "got %#lx\n", hr);
3113 ret = test_tool_wait_message(tool, 50, &msg);
3114 todo_wine ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
3115 if (ret == WAIT_TIMEOUT) ret = test_tool_wait_message(tool, 500, &msg);
3116 ok(!ret, "got %#lx\n", ret);
3117 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3118 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3119 ok(hr == S_OK, "got %#lx\n", hr);
3121 ret = test_tool_wait_message(tool, 100, &msg);
3122 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
3123 ok(!msg, "got %p\n", msg);
3126 /* AddNotificationType is necessary to receive notification messages */
3128 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
3129 ok(hr == S_OK, "got %#lx\n", hr);
3130 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
3131 ok(hr == S_OK, "got %#lx\n", hr);
3132 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
3133 ok(hr == S_FALSE, "got %#lx\n", hr);
3135 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, &state);
3136 ok(hr == S_OK, "got %#lx\n", hr);
3137 hr = IDirectMusicPerformance_GetTime(performance, NULL, &music_time);
3138 ok(hr == S_OK, "got %#lx\n", hr);
3140 ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)&notif);
3141 ok(!ret, "got %#lx\n", ret);
3142 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
3143 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3144 ok(hr == S_OK, "got %#lx\n", hr);
3146 ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)&notif);
3147 ok(!ret, "got %#lx\n", ret);
3148 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
3149 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3150 ok(hr == S_OK, "got %#lx\n", hr);
3152 ret = test_tool_wait_message(tool, 50, &msg);
3153 ok(!ret, "got %#lx\n", ret);
3154 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3155 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3156 ok(hr == S_OK, "got %#lx\n", hr);
3158 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&notif);
3159 ok(!ret, "got %#lx\n", ret);
3160 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
3161 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3162 ok(hr == S_OK, "got %#lx\n", hr);
3164 ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)&notif);
3165 ok(!ret, "got %#lx\n", ret);
3166 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
3167 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3168 ok(hr == S_OK, "got %#lx\n", hr);
3170 ret = test_tool_wait_message(tool, 50, &msg);
3171 ok(!ret, "got %#lx\n", ret);
3172 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3173 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3174 ok(hr == S_OK, "got %#lx\n", hr);
3176 ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)&notif);
3177 ok(!ret, "got %#lx\n", ret);
3178 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
3179 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3180 ok(hr == S_OK, "got %#lx\n", hr);
3183 /* wait enough time for notifications to be delivered */
3185 ret = test_tool_wait_message(tool, 2000, &msg);
3186 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
3187 ok(!msg, "got %p\n", msg);
3190 /* notification messages are also queued for direct access */
3192 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3193 ok(hr == S_OK, "got %#lx\n", hr);
3194 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
3195 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3196 ok(hr == S_OK, "got %#lx\n", hr);
3198 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3199 ok(hr == S_OK, "got %#lx\n", hr);
3200 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
3201 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3202 ok(hr == S_OK, "got %#lx\n", hr);
3204 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3205 ok(hr == S_OK, "got %#lx\n", hr);
3206 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
3207 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3208 ok(hr == S_OK, "got %#lx\n", hr);
3210 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3211 ok(hr == S_OK, "got %#lx\n", hr);
3212 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
3213 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3214 ok(hr == S_OK, "got %#lx\n", hr);
3216 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3217 ok(hr == S_OK, "got %#lx\n", hr);
3218 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
3219 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3220 ok(hr == S_OK, "got %#lx\n", hr);
3222 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3223 ok(hr == S_FALSE, "got %#lx\n", hr);
3225 IDirectMusicSegmentState_Release(state);
3227 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
3228 ok(hr == S_OK, "got %#lx\n", hr);
3229 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
3230 ok(hr == S_OK, "got %#lx\n", hr);
3233 /* RemoveNotificationType returns S_FALSE if already removed */
3235 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
3236 ok(hr == S_FALSE, "got %#lx\n", hr);
3239 /* CloseDown removes all notifications and notification messages */
3241 hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
3242 ok(hr == S_OK, "got %#lx\n", hr);
3243 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, &state);
3244 ok(hr == S_OK, "got %#lx\n", hr);
3245 hr = IDirectMusicPerformance_GetTime(performance, NULL, &music_time);
3246 ok(hr == S_OK, "got %#lx\n", hr);
3248 ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)&notif);
3249 ok(!ret, "got %#lx\n", ret);
3250 check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
3251 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
3252 ok(hr == S_OK, "got %#lx\n", hr);
3254 hr = IDirectMusicPerformance_CloseDown(performance);
3255 ok(hr == S_OK, "got %#lx\n", hr);
3256 hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
3257 ok(hr == S_FALSE, "got %#lx\n", hr);
3258 hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
3259 ok(hr == S_FALSE, "got %#lx\n", hr);
3261 ret = test_tool_wait_message(tool, 50, &msg);
3262 ok(!ret, "got %#lx\n", ret);
3263 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3264 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3265 ok(hr == S_OK, "got %#lx\n", hr);
3267 ret = test_tool_wait_message(tool, 500, &msg);
3268 todo_wine ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
3269 if (!ret) IDirectMusicPerformance_FreePMsg(performance, msg);
3271 IDirectMusicSegmentState_Release(state);
3272 IDirectMusicSegment_Release(segment);
3275 IDirectMusicPerformance_Release(performance);
3276 IDirectMusicTool_Release(tool);
3279 static void test_wave_pmsg(void)
3281 static const DWORD message_types[] =
3283 DMUS_PMSGT_DIRTY,
3284 DMUS_PMSGT_WAVE,
3286 IDirectMusicPerformance *performance;
3287 IDirectMusicSegment *segment;
3288 IDirectMusicLoader8 *loader;
3289 IDirectMusicGraph *graph;
3290 WCHAR test_wav[MAX_PATH];
3291 IDirectMusicTool *tool;
3292 DMUS_WAVE_PMSG *wave;
3293 MUSIC_TIME length;
3294 DMUS_PMSG *msg;
3295 HRESULT hr;
3296 DWORD ret;
3298 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
3299 ok(hr == S_OK, "got %#lx\n", hr);
3301 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
3302 &IID_IDirectMusicPerformance, (void **)&performance);
3303 ok(hr == S_OK, "got %#lx\n", hr);
3305 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
3306 &IID_IDirectMusicGraph, (void **)&graph);
3307 ok(hr == S_OK, "got %#lx\n", hr);
3308 hr = IDirectMusicPerformance_SetGraph(performance, graph);
3309 ok(hr == S_OK, "got %#lx\n", hr);
3310 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
3311 ok(hr == S_OK, "got %#lx\n", hr);
3312 IDirectMusicGraph_Release(graph);
3314 hr = IDirectMusicPerformance8_InitAudio((IDirectMusicPerformance8 *)performance, NULL, NULL, NULL,
3315 DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL);
3316 ok(hr == S_OK, "got %#lx\n", hr);
3319 load_resource(L"test.wav", test_wav);
3321 hr = CoCreateInstance(&CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC_SERVER,
3322 &IID_IDirectMusicLoader8, (void **)&loader);
3323 ok(hr == S_OK, "got %#lx\n", hr);
3324 hr = IDirectMusicLoader8_LoadObjectFromFile(loader, &CLSID_DirectMusicSegment,
3325 &IID_IDirectMusicSegment, test_wav, (void **)&segment);
3326 ok(hr == S_OK, "got %#lx\n", hr);
3327 IDirectMusicLoader8_Release(loader);
3330 length = 0xdeadbeef;
3331 hr = IDirectMusicSegment_GetLength(segment, &length);
3332 ok(hr == S_OK, "got %#lx\n", hr);
3333 ok(length == 1, "got %lu\n", length);
3336 /* without Download, no DMUS_PMSGT_WAVE is sent */
3338 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
3339 ok(hr == S_OK, "got %#lx\n", hr);
3341 ret = test_tool_wait_message(tool, 500, &msg);
3342 ok(!ret, "got %#lx\n", ret);
3343 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
3344 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3345 ok(hr == S_OK, "got %#lx\n", hr);
3347 ret = test_tool_wait_message(tool, 500, &msg);
3348 ok(!ret, "got %#lx\n", ret);
3349 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
3350 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3351 ok(hr == S_OK, "got %#lx\n", hr);
3353 ret = test_tool_wait_message(tool, 100, &msg);
3354 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
3355 ok(!msg, "got %p\n", msg);
3358 /* a single DMUS_PMSGT_WAVE message is sent with punkUser set */
3360 hr = IDirectMusicSegment8_Download((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
3361 ok(hr == S_OK, "got %#lx\n", hr);
3363 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
3364 ok(hr == S_OK, "got %#lx\n", hr);
3366 ret = test_tool_wait_message(tool, 500, &msg);
3367 ok(!ret, "got %#lx\n", ret);
3368 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
3369 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3370 ok(hr == S_OK, "got %#lx\n", hr);
3372 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&wave);
3373 ok(!ret, "got %#lx\n", ret);
3374 ok(wave->dwType == DMUS_PMSGT_WAVE, "got %p\n", wave);
3375 ok(!!wave->punkUser, "got %p\n", wave->punkUser);
3376 ok(wave->rtStartOffset == 0, "got %I64d\n", wave->rtStartOffset);
3377 ok(wave->rtDuration == 1000000, "got %I64d\n", wave->rtDuration);
3378 ok(wave->lOffset == 0, "got %lu\n", wave->lOffset);
3379 ok(wave->lVolume == 0, "got %lu\n", wave->lVolume);
3380 ok(wave->lPitch == 0, "got %lu\n", wave->lPitch);
3381 ok(wave->bFlags == 0, "got %#x\n", wave->bFlags);
3382 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)wave);
3383 ok(hr == S_OK, "got %#lx\n", hr);
3385 ret = test_tool_wait_message(tool, 500, &msg);
3386 ok(!ret, "got %#lx\n", ret);
3387 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg);
3388 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3389 ok(hr == S_OK, "got %#lx\n", hr);
3391 hr = IDirectMusicSegment8_Unload((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
3392 ok(hr == S_OK, "got %#lx\n", hr);
3394 ret = test_tool_wait_message(tool, 100, &msg);
3395 ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret);
3396 ok(!msg, "got %p\n", msg);
3399 IDirectMusicSegment_Release(segment);
3402 hr = IDirectMusicPerformance_CloseDown(performance);
3403 ok(hr == S_OK, "got %#lx\n", hr);
3405 IDirectMusicPerformance_Release(performance);
3406 IDirectMusicTool_Release(tool);
3409 #define check_dmus_note_pmsg(a, b, c, d, e, f) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f)
3410 static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time, UINT chan,
3411 UINT duration, UINT key, UINT vel)
3413 ok_(__FILE__, line)(msg->dwSize == sizeof(*msg), "got dwSize %lu\n", msg->dwSize);
3414 ok_(__FILE__, line)(!!msg->rtTime, "got rtTime %I64u\n", msg->rtTime);
3415 ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime);
3416 ok_(__FILE__, line)(msg->dwPChannel == chan, "got dwPChannel %lu\n", msg->dwPChannel);
3417 ok_(__FILE__, line)(!!msg->dwVirtualTrackID, "got dwVirtualTrackID %lu\n", msg->dwVirtualTrackID);
3418 ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTE, "got %#lx\n", msg->dwType);
3419 ok_(__FILE__, line)(!msg->dwVoiceID, "got dwVoiceID %lu\n", msg->dwVoiceID);
3420 ok_(__FILE__, line)(msg->dwGroupID == 1, "got dwGroupID %lu\n", msg->dwGroupID);
3421 ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser);
3422 ok_(__FILE__, line)(msg->mtDuration == duration, "got mtDuration %lu\n", msg->mtDuration);
3423 ok_(__FILE__, line)(msg->wMusicValue == key, "got wMusicValue %u\n", msg->wMusicValue);
3424 ok_(__FILE__, line)(!msg->wMeasure, "got wMeasure %u\n", msg->wMeasure);
3425 /* FIXME: ok_(__FILE__, line)(!msg->nOffset, "got nOffset %u\n", msg->nOffset); */
3426 /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */
3427 /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */
3428 ok_(__FILE__, line)(msg->bVelocity == vel, "got bVelocity %u\n", msg->bVelocity);
3429 ok_(__FILE__, line)(msg->bFlags == 1, "got bFlags %#x\n", msg->bFlags);
3430 ok_(__FILE__, line)(!msg->bTimeRange, "got bTimeRange %u\n", msg->bTimeRange);
3431 ok_(__FILE__, line)(!msg->bDurRange, "got bDurRange %u\n", msg->bDurRange);
3432 ok_(__FILE__, line)(!msg->bVelRange, "got bVelRange %u\n", msg->bVelRange);
3433 ok_(__FILE__, line)(!msg->bPlayModeFlags, "got bPlayModeFlags %#x\n", msg->bPlayModeFlags);
3434 ok_(__FILE__, line)(!msg->bSubChordLevel, "got bSubChordLevel %u\n", msg->bSubChordLevel);
3435 ok_(__FILE__, line)(msg->bMidiValue == key, "got bMidiValue %u\n", msg->bMidiValue);
3436 ok_(__FILE__, line)(!msg->cTranspose, "got cTranspose %u\n", msg->cTranspose);
3439 static void test_sequence_track(void)
3441 static const DWORD message_types[] =
3443 DMUS_PMSGT_MIDI,
3444 DMUS_PMSGT_NOTE,
3445 DMUS_PMSGT_CURVE,
3446 DMUS_PMSGT_DIRTY,
3448 static const LARGE_INTEGER zero = {0};
3449 IDirectMusicPerformance *performance;
3450 IDirectMusicSegment *segment;
3451 IDirectMusicGraph *graph;
3452 IDirectMusicTrack *track;
3453 IPersistStream *persist;
3454 IDirectMusicTool *tool;
3455 DMUS_NOTE_PMSG *note;
3456 IStream *stream;
3457 DMUS_PMSG *msg;
3458 HRESULT hr;
3459 DWORD ret;
3461 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
3462 ok(hr == S_OK, "got %#lx\n", hr);
3464 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
3465 &IID_IDirectMusicPerformance, (void **)&performance);
3466 ok(hr == S_OK, "got %#lx\n", hr);
3468 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
3469 &IID_IDirectMusicGraph, (void **)&graph);
3470 ok(hr == S_OK, "got %#lx\n", hr);
3471 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
3472 ok(hr == S_OK, "got %#lx\n", hr);
3473 hr = IDirectMusicPerformance_SetGraph(performance, graph);
3474 ok(hr == S_OK, "got %#lx\n", hr);
3475 IDirectMusicGraph_Release(graph);
3478 /* create a segment and load a simple RIFF stream */
3480 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
3481 &IID_IDirectMusicSegment, (void **)&segment);
3482 ok(hr == S_OK, "got %#lx\n", hr);
3484 hr = IDirectMusicSegment_QueryInterface(segment, &IID_IPersistStream, (void **)&persist);
3485 ok(hr == S_OK, "got %#lx\n", hr);
3486 hr = CreateStreamOnHGlobal(0, TRUE, &stream);
3487 ok(hr == S_OK, "got %#lx\n", hr);
3489 CHUNK_RIFF(stream, "DMSG")
3491 /* set a non-zero segment length, or nothing will be played */
3492 DMUS_IO_SEGMENT_HEADER head = {.mtLength = 2000};
3493 CHUNK_DATA(stream, "segh", head);
3494 CHUNK_DATA(stream, "guid", CLSID_DirectMusicSegment);
3496 CHUNK_END;
3498 hr = IStream_Seek(stream, zero, 0, NULL);
3499 ok(hr == S_OK, "got %#lx\n", hr);
3500 hr = IPersistStream_Load(persist, stream);
3501 ok(hr == S_OK, "got %#lx\n", hr);
3502 IPersistStream_Release(persist);
3503 IStream_Release(stream);
3506 /* add a sequence track to our segment */
3508 hr = CoCreateInstance(&CLSID_DirectMusicSeqTrack, NULL, CLSCTX_INPROC_SERVER,
3509 &IID_IDirectMusicTrack, (void **)&track);
3510 ok(hr == S_OK, "got %#lx\n", hr);
3512 hr = IDirectMusicSegment_QueryInterface(track, &IID_IPersistStream, (void **)&persist);
3513 ok(hr == S_OK, "got %#lx\n", hr);
3514 hr = CreateStreamOnHGlobal(0, TRUE, &stream);
3515 ok(hr == S_OK, "got %#lx\n", hr);
3517 CHUNK_BEGIN(stream, "seqt")
3519 DMUS_IO_SEQ_ITEM items[] =
3521 {.mtTime = 0, .mtDuration = 500, .dwPChannel = 0, .bStatus = 0x90, .bByte1 = 60, .bByte2 = 120},
3522 {.mtTime = 1000, .mtDuration = 200, .dwPChannel = 1, .bStatus = 0x90, .bByte1 = 50, .bByte2 = 100},
3524 CHUNK_ARRAY(stream, "evtl", items);
3526 CHUNK_END;
3528 hr = IStream_Seek(stream, zero, 0, NULL);
3529 ok(hr == S_OK, "got %#lx\n", hr);
3530 hr = IPersistStream_Load(persist, stream);
3531 ok(hr == S_OK, "got %#lx\n", hr);
3532 IPersistStream_Release(persist);
3533 IStream_Release(stream);
3535 hr = IDirectMusicSegment_InsertTrack(segment, (IDirectMusicTrack *)track, 1);
3536 ok(hr == S_OK, "got %#lx\n", hr);
3537 IDirectMusicTrack_Release(track);
3540 /* now play the segment, and check produced messages */
3542 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
3543 ok(hr == S_OK, "got %#lx\n", hr);
3545 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0x800, 0, NULL);
3546 ok(hr == S_OK, "got %#lx\n", hr);
3548 ret = test_tool_wait_message(tool, 500, &msg);
3549 ok(!ret, "got %#lx\n", ret);
3550 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3551 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3552 ok(hr == S_OK, "got %#lx\n", hr);
3554 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&note);
3555 ok(!ret, "got %#lx\n", ret);
3556 check_dmus_note_pmsg(note, 0, 0, 500, 60, 120);
3557 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note);
3558 ok(hr == S_OK, "got %#lx\n", hr);
3560 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&note);
3561 ok(!ret, "got %#lx\n", ret);
3562 check_dmus_note_pmsg(note, 1000, 1, 200, 50, 100);
3563 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note);
3564 ok(hr == S_OK, "got %#lx\n", hr);
3566 ret = test_tool_wait_message(tool, 500, &msg);
3567 ok(!ret, "got %#lx\n", ret);
3568 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3569 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3570 ok(hr == S_OK, "got %#lx\n", hr);
3572 IDirectMusicSegment_Release(segment);
3575 hr = IDirectMusicPerformance_CloseDown(performance);
3576 ok(hr == S_OK, "got %#lx\n", hr);
3578 IDirectMusicPerformance_Release(performance);
3579 IDirectMusicTool_Release(tool);
3582 #define check_dmus_patch_pmsg(a, b, c, d, e) check_dmus_patch_pmsg_(__LINE__, a, b, c, d, e)
3583 static void check_dmus_patch_pmsg_(int line, DMUS_PATCH_PMSG *msg, MUSIC_TIME time, UINT chan,
3584 UINT bank, UINT patch)
3586 ok_(__FILE__, line)(msg->dwSize == sizeof(*msg), "got dwSize %lu\n", msg->dwSize);
3587 ok_(__FILE__, line)(msg->rtTime != 0, "got rtTime %I64u\n", msg->rtTime);
3588 ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime);
3589 ok_(__FILE__, line)(msg->dwPChannel == chan, "got dwPChannel %lu\n", msg->dwPChannel);
3590 ok_(__FILE__, line)(!!msg->dwVirtualTrackID, "got dwVirtualTrackID %lu\n", msg->dwVirtualTrackID);
3591 ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_PATCH, "got %#lx\n", msg->dwType);
3592 ok_(__FILE__, line)(!msg->dwVoiceID, "got dwVoiceID %lu\n", msg->dwVoiceID);
3593 ok_(__FILE__, line)(msg->dwGroupID == 1, "got dwGroupID %lu\n", msg->dwGroupID);
3594 ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser);
3595 ok_(__FILE__, line)(msg->byInstrument == patch, "got byInstrument %u\n", msg->byInstrument);
3596 ok_(__FILE__, line)(msg->byMSB == bank >> 8, "got byMSB %u\n", msg->byMSB);
3597 ok_(__FILE__, line)(msg->byLSB == (bank & 0xff), "got byLSB %u\n", msg->byLSB);
3600 static void test_band_track_play(void)
3602 static const DWORD message_types[] =
3604 DMUS_PMSGT_MIDI,
3605 DMUS_PMSGT_NOTE,
3606 DMUS_PMSGT_SYSEX,
3607 DMUS_PMSGT_NOTIFICATION,
3608 DMUS_PMSGT_TEMPO,
3609 DMUS_PMSGT_CURVE,
3610 DMUS_PMSGT_TIMESIG,
3611 DMUS_PMSGT_PATCH,
3612 DMUS_PMSGT_TRANSPOSE,
3613 DMUS_PMSGT_CHANNEL_PRIORITY,
3614 DMUS_PMSGT_STOP,
3615 DMUS_PMSGT_DIRTY,
3616 DMUS_PMSGT_WAVE,
3617 DMUS_PMSGT_LYRIC,
3618 DMUS_PMSGT_SCRIPTLYRIC,
3619 DMUS_PMSGT_USER,
3621 DMUS_OBJECTDESC desc =
3623 .dwSize = sizeof(DMUS_OBJECTDESC),
3624 .dwValidData = DMUS_OBJ_OBJECT | DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH,
3625 .guidClass = CLSID_DirectMusicCollection,
3626 .guidObject = GUID_DefaultGMCollection,
3627 .wszFileName = L"C:\\windows\\system32\\drivers\\gm.dls",
3629 static const LARGE_INTEGER zero = {0};
3630 IDirectMusicPerformance *performance;
3631 IStream *stream, *loader_stream;
3632 IDirectMusicSegment *segment;
3633 IDirectMusicLoader *loader;
3634 IDirectMusicGraph *graph;
3635 IDirectMusicTrack *track;
3636 IPersistStream *persist;
3637 IDirectMusicTool *tool;
3638 DMUS_PATCH_PMSG *patch;
3639 DMUS_PMSG *msg;
3640 HRESULT hr;
3641 DWORD ret;
3643 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
3644 ok(hr == S_OK, "got %#lx\n", hr);
3646 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
3647 &IID_IDirectMusicPerformance, (void **)&performance);
3648 ok(hr == S_OK, "got %#lx\n", hr);
3650 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
3651 &IID_IDirectMusicGraph, (void **)&graph);
3652 ok(hr == S_OK, "got %#lx\n", hr);
3653 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
3654 ok(hr == S_OK, "got %#lx\n", hr);
3655 hr = IDirectMusicPerformance_SetGraph(performance, graph);
3656 ok(hr == S_OK, "got %#lx\n", hr);
3657 IDirectMusicGraph_Release(graph);
3660 /* create a segment and load a simple RIFF stream */
3662 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
3663 &IID_IDirectMusicSegment, (void **)&segment);
3664 ok(hr == S_OK, "got %#lx\n", hr);
3666 hr = IDirectMusicSegment_QueryInterface(segment, &IID_IPersistStream, (void **)&persist);
3667 ok(hr == S_OK, "got %#lx\n", hr);
3668 hr = CreateStreamOnHGlobal(0, TRUE, &stream);
3669 ok(hr == S_OK, "got %#lx\n", hr);
3671 CHUNK_RIFF(stream, "DMSG")
3673 /* set a non-zero segment length, or nothing will be played */
3674 DMUS_IO_SEGMENT_HEADER head = {.mtLength = 2000};
3675 CHUNK_DATA(stream, "segh", head);
3676 CHUNK_DATA(stream, "guid", CLSID_DirectMusicSegment);
3678 CHUNK_END;
3680 hr = IStream_Seek(stream, zero, 0, NULL);
3681 ok(hr == S_OK, "got %#lx\n", hr);
3682 hr = IPersistStream_Load(persist, stream);
3683 ok(hr == S_OK, "got %#lx\n", hr);
3684 IPersistStream_Release(persist);
3685 IStream_Release(stream);
3688 /* add a sequence track to our segment */
3690 hr = CoCreateInstance(&CLSID_DirectMusicBandTrack, NULL, CLSCTX_INPROC_SERVER,
3691 &IID_IDirectMusicTrack, (void **)&track);
3692 ok(hr == S_OK, "got %#lx\n", hr);
3694 hr = IDirectMusicSegment_QueryInterface(track, &IID_IPersistStream, (void **)&persist);
3695 ok(hr == S_OK, "got %#lx\n", hr);
3696 hr = CreateStreamOnHGlobal(0, TRUE, &stream);
3697 ok(hr == S_OK, "got %#lx\n", hr);
3699 CHUNK_RIFF(stream, "DMBT")
3701 DMUS_IO_BAND_TRACK_HEADER head = {.bAutoDownload = TRUE};
3703 CHUNK_DATA(stream, "bdth", head);
3704 CHUNK_LIST(stream, "lbdl")
3706 CHUNK_LIST(stream, "lbnd")
3708 DMUS_IO_BAND_ITEM_HEADER head = {.lBandTime = 0};
3709 CHUNK_DATA(stream, "bdih", head);
3711 CHUNK_RIFF(stream, "DMBD")
3713 GUID guid = CLSID_DirectMusicBand;
3714 CHUNK_DATA(stream, "guid", guid);
3716 CHUNK_LIST(stream, "lbil")
3718 CHUNK_LIST(stream, "lbin")
3720 DMUS_IO_INSTRUMENT head = {.dwPatch = 1, .dwPChannel = 1, .dwFlags = DMUS_IO_INST_PATCH};
3721 CHUNK_DATA(stream, "bins", head);
3723 CHUNK_END;
3725 CHUNK_END;
3727 CHUNK_END;
3729 CHUNK_END;
3731 CHUNK_LIST(stream, "lbnd")
3733 DMUS_IO_BAND_ITEM_HEADER head = {.lBandTime = 1000};
3734 CHUNK_DATA(stream, "bdih", head);
3736 CHUNK_RIFF(stream, "DMBD")
3738 GUID guid = CLSID_DirectMusicBand;
3739 CHUNK_DATA(stream, "guid", guid);
3741 CHUNK_LIST(stream, "lbil")
3743 CHUNK_LIST(stream, "lbin")
3745 DMUS_IO_INSTRUMENT head = {.dwPatch = 2, .dwPChannel = 1, .dwFlags = DMUS_IO_INST_PATCH};
3746 CHUNK_DATA(stream, "bins", head);
3748 CHUNK_END;
3750 CHUNK_LIST(stream, "lbin")
3752 DMUS_IO_INSTRUMENT head = {.dwPatch = 3, .dwPChannel = 2, .dwFlags = DMUS_IO_INST_PATCH};
3753 CHUNK_DATA(stream, "bins", head);
3755 CHUNK_END;
3757 CHUNK_END;
3759 CHUNK_END;
3761 CHUNK_END;
3763 CHUNK_END;
3765 CHUNK_END;
3767 hr = IStream_Seek(stream, zero, 0, NULL);
3768 ok(hr == S_OK, "got %#lx\n", hr);
3770 /* band track requires the stream to implement IDirectMusicGetLoader */
3772 hr = CoCreateInstance(&CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC_SERVER,
3773 &IID_IDirectMusicLoader8, (void **)&loader);
3774 ok(hr == S_OK, "got %#lx\n", hr);
3775 hr = IDirectMusicLoader_SetObject(loader, &desc);
3776 if (hr == DMUS_E_LOADER_FAILEDOPEN)
3777 skip("Failed to open gm.dls, missing system SoundFont?\n");
3778 else
3779 ok(hr == S_OK, "got %#lx\n", hr);
3781 hr = test_loader_stream_create(stream, loader, &loader_stream);
3782 ok(hr == S_OK, "got %#lx\n", hr);
3783 IDirectMusicLoader8_Release(loader);
3785 hr = IPersistStream_Load(persist, loader_stream);
3786 ok(hr == S_OK, "got %#lx\n", hr);
3787 IStream_Release(loader_stream);
3789 IPersistStream_Release(persist);
3790 IStream_Release(stream);
3792 hr = IDirectMusicSegment_InsertTrack(segment, (IDirectMusicTrack *)track, 1);
3793 ok(hr == S_OK, "got %#lx\n", hr);
3794 IDirectMusicTrack_Release(track);
3797 /* now play the segment, and check produced messages */
3799 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
3800 ok(hr == S_OK, "got %#lx\n", hr);
3802 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0x800, 0, NULL);
3803 ok(hr == S_OK, "got %#lx\n", hr);
3805 ret = test_tool_wait_message(tool, 500, &msg);
3806 ok(!ret, "got %#lx\n", ret);
3807 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3808 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3809 ok(hr == S_OK, "got %#lx\n", hr);
3811 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&patch);
3812 ok(!ret, "got %#lx\n", ret);
3813 check_dmus_patch_pmsg(patch, 0, 1, 0, 1);
3814 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)patch);
3815 ok(hr == S_OK, "got %#lx\n", hr);
3817 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&patch);
3818 ok(!ret, "got %#lx\n", ret);
3819 check_dmus_patch_pmsg(patch, 1000, 2, 0, 3);
3820 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)patch);
3821 ok(hr == S_OK, "got %#lx\n", hr);
3823 ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&patch);
3824 ok(!ret, "got %#lx\n", ret);
3825 check_dmus_patch_pmsg(patch, 1000, 1, 0, 2);
3826 hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)patch);
3827 ok(hr == S_OK, "got %#lx\n", hr);
3829 ret = test_tool_wait_message(tool, 500, &msg);
3830 ok(!ret, "got %#lx\n", ret);
3831 ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType);
3832 hr = IDirectMusicPerformance_FreePMsg(performance, msg);
3833 ok(hr == S_OK, "got %#lx\n", hr);
3835 IDirectMusicSegment_Release(segment);
3838 hr = IDirectMusicPerformance_CloseDown(performance);
3839 ok(hr == S_OK, "got %#lx\n", hr);
3841 IDirectMusicPerformance_Release(performance);
3842 IDirectMusicTool_Release(tool);
3845 static void test_connect_to_collection(void)
3847 IDirectMusicCollection *collection;
3848 IDirectMusicSegment *segment;
3849 IDirectMusicTrack *track;
3850 void *param;
3851 HRESULT hr;
3853 hr = CoCreateInstance(&CLSID_DirectMusicCollection, NULL, CLSCTX_INPROC_SERVER,
3854 &IID_IDirectMusicCollection, (void **)&collection);
3855 ok(hr == S_OK, "got %#lx\n", hr);
3856 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
3857 &IID_IDirectMusicSegment, (void **)&segment);
3858 ok(hr == S_OK, "got %#lx\n", hr);
3859 hr = CoCreateInstance(&CLSID_DirectMusicBandTrack, NULL, CLSCTX_INPROC_SERVER,
3860 &IID_IDirectMusicTrack, (void **)&track);
3861 ok(hr == S_OK, "got %#lx\n", hr);
3863 hr = IDirectMusicSegment_InsertTrack(segment, track, 1);
3864 ok(hr == S_OK, "got %#lx\n", hr);
3866 /* it is possible to connect the band track to another collection, but not to disconnect it */
3867 hr = IDirectMusicTrack_IsParamSupported(track, &GUID_ConnectToDLSCollection);
3868 ok(hr == S_OK, "got %#lx\n", hr);
3870 hr = IDirectMusicTrack_SetParam(track, &GUID_ConnectToDLSCollection, 0, NULL);
3871 todo_wine ok(hr == E_POINTER, "got %#lx\n", hr);
3872 hr = IDirectMusicTrack_SetParam(track, &GUID_ConnectToDLSCollection, 0, collection);
3873 ok(hr == S_OK, "got %#lx\n", hr);
3875 hr = IDirectMusicTrack_GetParam(track, &GUID_ConnectToDLSCollection, 0, NULL, NULL);
3876 todo_wine ok(hr == E_POINTER, "got %#lx\n", hr);
3877 hr = IDirectMusicTrack_GetParam(track, &GUID_ConnectToDLSCollection, 0, NULL, &param);
3878 ok(hr == DMUS_E_GET_UNSUPPORTED, "got %#lx\n", hr);
3880 hr = IDirectMusicSegment_SetParam(segment, &GUID_ConnectToDLSCollection, -1, DMUS_SEG_ALLTRACKS, 0, NULL);
3881 todo_wine ok(hr == E_POINTER, "got %#lx\n", hr);
3882 hr = IDirectMusicSegment_SetParam(segment, &GUID_ConnectToDLSCollection, -1, DMUS_SEG_ALLTRACKS, 0, collection);
3883 ok(hr == S_OK, "got %#lx\n", hr);
3885 IDirectMusicTrack_Release(track);
3886 IDirectMusicSegment_Release(segment);
3887 IDirectMusicCollection_Release(collection);
3890 static void test_segment_state(void)
3892 static const DWORD message_types[] =
3894 DMUS_PMSGT_DIRTY,
3895 DMUS_PMSGT_NOTIFICATION,
3896 DMUS_PMSGT_WAVE,
3898 IDirectMusicSegmentState *state, *tmp_state;
3899 IDirectMusicSegment *segment, *tmp_segment;
3900 IDirectMusicPerformance *performance;
3901 IDirectMusicTrack *track;
3902 IDirectMusicGraph *graph;
3903 IDirectMusicTool *tool;
3904 DWORD value, ret;
3905 MUSIC_TIME time;
3906 HRESULT hr;
3908 hr = test_tool_create(message_types, ARRAY_SIZE(message_types), &tool);
3909 ok(hr == S_OK, "got %#lx\n", hr);
3910 hr = test_track_create(&track, TRUE);
3911 ok(hr == S_OK, "got %#lx\n", hr);
3913 hr = CoCreateInstance(&CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC_SERVER,
3914 &IID_IDirectMusicPerformance, (void **)&performance);
3915 ok(hr == S_OK, "got %#lx\n", hr);
3917 hr = CoCreateInstance(&CLSID_DirectMusicGraph, NULL, CLSCTX_INPROC_SERVER,
3918 &IID_IDirectMusicGraph, (void **)&graph);
3919 ok(hr == S_OK, "got %#lx\n", hr);
3920 hr = IDirectMusicPerformance_SetGraph(performance, graph);
3921 ok(hr == S_OK, "got %#lx\n", hr);
3922 hr = IDirectMusicGraph_InsertTool(graph, (IDirectMusicTool *)tool, NULL, 0, -1);
3923 ok(hr == S_OK, "got %#lx\n", hr);
3924 IDirectMusicGraph_Release(graph);
3927 hr = CoCreateInstance(&CLSID_DirectMusicSegment, NULL, CLSCTX_INPROC_SERVER,
3928 &IID_IDirectMusicSegment, (void **)&segment);
3929 ok(hr == S_OK, "got %#lx\n", hr);
3931 check_track_state(track, inserted, FALSE);
3932 hr = IDirectMusicSegment_InsertTrack(segment, track, 1);
3933 ok(hr == S_OK, "got %#lx\n", hr);
3934 check_track_state(track, inserted, TRUE);
3936 check_track_state(track, downloaded, FALSE);
3937 hr = IDirectMusicSegment8_Download((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
3938 ok(hr == S_OK, "got %#lx\n", hr);
3939 check_track_state(track, downloaded, TRUE);
3940 hr = IDirectMusicSegment8_Unload((IDirectMusicSegment8 *)segment, (IUnknown *)performance);
3941 ok(hr == S_OK, "got %#lx\n", hr);
3942 check_track_state(track, downloaded, FALSE);
3945 /* by default the segment length is 1 */
3947 time = 0xdeadbeef;
3948 hr = IDirectMusicSegment_GetLength(segment, &time);
3949 ok(hr == S_OK, "got %#lx\n", hr);
3950 todo_wine ok(time == 1, "got %lu\n", time);
3951 hr = IDirectMusicSegment_SetStartPoint(segment, 50);
3952 ok(hr == DMUS_E_OUT_OF_RANGE, "got %#lx\n", hr);
3953 hr = IDirectMusicSegment_SetRepeats(segment, 10);
3954 ok(hr == S_OK, "got %#lx\n", hr);
3955 hr = IDirectMusicSegment_SetLoopPoints(segment, 10, 70);
3956 ok(hr == DMUS_E_OUT_OF_RANGE, "got %#lx\n", hr);
3958 /* Setting a larger length will cause PlayEx to be called multiple times,
3959 * as native splits the segment into chunks and play each chunk separately */
3960 hr = IDirectMusicSegment_SetLength(segment, 100);
3961 ok(hr == S_OK, "got %#lx\n", hr);
3962 hr = IDirectMusicSegment_SetStartPoint(segment, 50);
3963 ok(hr == S_OK, "got %#lx\n", hr);
3964 hr = IDirectMusicSegment_SetRepeats(segment, 0);
3965 ok(hr == S_OK, "got %#lx\n", hr);
3966 hr = IDirectMusicSegment_SetLoopPoints(segment, 0, 0);
3967 ok(hr == S_OK, "got %#lx\n", hr);
3970 /* InitPlay returns a dummy segment state */
3972 state = (void *)0xdeadbeef;
3973 hr = IDirectMusicSegment_InitPlay(segment, &state, performance, 0);
3974 ok(hr == S_OK, "got %#lx\n", hr);
3975 ok(state != NULL, "got %p\n", state);
3976 ok(state != (void *)0xdeadbeef, "got %p\n", state);
3977 check_track_state(track, initialized, FALSE);
3979 tmp_segment = (void *)0xdeadbeef;
3980 hr = IDirectMusicSegmentState_GetSegment(state, &tmp_segment);
3981 ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
3982 ok(tmp_segment == NULL, "got %p\n", tmp_segment);
3983 time = 0xdeadbeef;
3984 hr = IDirectMusicSegmentState_GetStartPoint(state, &time);
3985 ok(hr == S_OK, "got %#lx\n", hr);
3986 ok(time == 0, "got %#lx\n", time);
3987 time = 0xdeadbeef;
3988 hr = IDirectMusicSegmentState_GetRepeats(state, &value);
3989 ok(hr == S_OK, "got %#lx\n", hr);
3990 ok(time == 0xdeadbeef, "got %#lx\n", time);
3991 time = 0xdeadbeef;
3992 hr = IDirectMusicSegmentState_GetStartTime(state, &time);
3993 ok(hr == S_OK, "got %#lx\n", hr);
3994 ok(time == -1, "got %#lx\n", time);
3995 time = 0xdeadbeef;
3996 hr = IDirectMusicSegmentState_GetSeek(state, &time);
3997 ok(hr == S_OK, "got %#lx\n", hr);
3998 ok(time == 0, "got %#lx\n", time);
4001 /* PlaySegment returns a different, genuine segment state */
4003 hr = IDirectMusicPerformance_Init(performance, NULL, 0, 0);
4004 ok(hr == S_OK, "got %#lx\n", hr);
4006 check_track_state(track, downloaded, FALSE);
4007 check_track_state(track, initialized, FALSE);
4008 check_track_state(track, playing, FALSE);
4010 tmp_state = state;
4011 state = (void *)0xdeadbeef;
4012 hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 20, &state);
4013 ok(hr == S_OK, "got %#lx\n", hr);
4014 ok(state != NULL, "got %p\n", state);
4015 ok(state != (void *)0xdeadbeef, "got %p\n", state);
4016 ok(state != tmp_state, "got %p\n", state);
4017 IDirectMusicSegmentState_Release(tmp_state);
4019 check_track_state(track, downloaded, FALSE);
4020 check_track_state(track, initialized, TRUE);
4023 /* The track can be removed from the segment */
4024 hr = IDirectMusicSegment_RemoveTrack(segment, track);
4025 ok(hr == S_OK, "got %#lx\n", hr);
4028 ret = test_track_wait_playing(track, 50);
4029 ok(ret == 0, "got %#lx\n", ret);
4032 tmp_segment = (void *)0xdeadbeef;
4033 hr = IDirectMusicSegmentState_GetSegment(state, &tmp_segment);
4034 ok(hr == S_OK, "got %#lx\n", hr);
4035 ok(tmp_segment == segment, "got %p\n", tmp_segment);
4036 IDirectMusicSegment_Release(tmp_segment);
4038 time = 0xdeadbeef;
4039 hr = IDirectMusicSegmentState_GetStartPoint(state, &time);
4040 ok(hr == S_OK, "got %#lx\n", hr);
4041 ok(time == 50, "got %lu\n", time);
4042 time = 0xdeadbeef;
4043 hr = IDirectMusicSegmentState_GetRepeats(state, &value);
4044 ok(hr == S_OK, "got %#lx\n", hr);
4045 ok(time == 0xdeadbeef, "got %#lx\n", time);
4046 time = 0xdeadbeef;
4047 hr = IDirectMusicSegmentState_GetStartTime(state, &time);
4048 ok(hr == S_OK, "got %#lx\n", hr);
4049 ok(time == 20, "got %#lx\n", time);
4050 time = 0xdeadbeef;
4052 /* The seek value is also dependent on whether the tracks are playing.
4053 * It is initially 0, then start_point right before playing, then length.
4055 hr = IDirectMusicSegmentState_GetSeek(state, &time);
4056 ok(hr == S_OK, "got %#lx\n", hr);
4057 todo_wine ok(time == 100, "got %#lx\n", time);
4059 /* changing the segment values doesn't change the segment state */
4061 hr = IDirectMusicSegment_SetStartPoint(segment, 0);
4062 ok(hr == S_OK, "got %#lx\n", hr);
4063 hr = IDirectMusicSegment_SetRepeats(segment, 10);
4064 ok(hr == S_OK, "got %#lx\n", hr);
4065 hr = IDirectMusicSegment_SetLoopPoints(segment, 50, 70);
4066 ok(hr == S_OK, "got %#lx\n", hr);
4068 time = 0xdeadbeef;
4069 hr = IDirectMusicSegmentState_GetStartPoint(state, &time);
4070 ok(hr == S_OK, "got %#lx\n", hr);
4071 ok(time == 50, "got %#lx\n", time);
4072 time = 0xdeadbeef;
4073 hr = IDirectMusicSegmentState_GetRepeats(state, &value);
4074 ok(hr == S_OK, "got %#lx\n", hr);
4075 ok(time == 0xdeadbeef, "got %#lx\n", time);
4076 time = 0xdeadbeef;
4077 hr = IDirectMusicSegmentState_GetStartTime(state, &time);
4078 ok(hr == S_OK, "got %#lx\n", hr);
4079 ok(time == 20, "got %#lx\n", time);
4080 time = 0xdeadbeef;
4081 hr = IDirectMusicSegmentState_GetSeek(state, &time);
4082 ok(hr == S_OK, "got %#lx\n", hr);
4083 todo_wine ok(time == 100, "got %#lx\n", time);
4085 IDirectMusicSegment_Release(segment);
4088 check_track_state(track, downloaded, FALSE);
4089 check_track_state(track, initialized, TRUE);
4090 check_track_state(track, playing, TRUE);
4092 hr = IDirectMusicPerformance_CloseDown(performance);
4093 ok(hr == S_OK, "got %#lx\n", hr);
4095 check_track_state(track, downloaded, FALSE);
4096 check_track_state(track, initialized, TRUE);
4097 check_track_state(track, playing, FALSE);
4100 IDirectMusicPerformance_Release(performance);
4101 IDirectMusicTrack_Release(track);
4102 IDirectMusicTool_Release(tool);
4105 START_TEST(dmime)
4107 CoInitialize(NULL);
4109 if (missing_dmime())
4111 skip("dmime not available\n");
4112 CoUninitialize();
4113 return;
4115 test_COM_audiopath();
4116 test_COM_audiopathconfig();
4117 test_COM_graph();
4118 test_COM_segment();
4119 test_COM_segmentstate();
4120 test_COM_track();
4121 test_COM_performance();
4122 test_audiopathconfig();
4123 test_graph();
4124 test_segment();
4125 test_gettrack();
4126 test_segment_param();
4127 test_track();
4128 test_parsedescriptor();
4129 test_performance_InitAudio();
4130 test_performance_createport();
4131 test_performance_pchannel();
4132 test_performance_tool();
4133 test_performance_graph();
4134 test_performance_time();
4135 test_performance_pmsg();
4136 test_notification_pmsg();
4137 test_wave_pmsg();
4138 test_sequence_track();
4139 test_band_track_play();
4140 test_connect_to_collection();
4141 test_segment_state();
4143 CoUninitialize();