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
24 #include <wine/test.h>
29 #include <audioclient.h>
32 DEFINE_GUID(GUID_NULL
,0,0,0,0,0,0,0,0,0,0,0);
33 DEFINE_GUID(GUID_Bunk
,0xFFFFFFFF,0xFFFF,0xFFFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
35 static ULONG
get_refcount(void *iface
)
37 IUnknown
*unknown
= iface
;
38 IUnknown_AddRef(unknown
);
39 return IUnknown_Release(unknown
);
42 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c, FALSE)
43 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
, BOOL check_refs
)
45 ULONG expect_ref
= get_refcount(iface_ptr
);
46 IUnknown
*iface
= iface_ptr
;
50 expected
= supported
? S_OK
: E_NOINTERFACE
;
51 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
52 ok_(__FILE__
, line
)(hr
== expected
, "got hr %#lx, expected %#lx.\n", hr
, expected
);
55 LONG ref
= get_refcount(unk
);
56 if (check_refs
) ok_(__FILE__
, line
)(ref
== expect_ref
+ 1, "got %ld\n", ref
);
57 IUnknown_Release(unk
);
58 ref
= get_refcount(iface_ptr
);
59 if (check_refs
) ok_(__FILE__
, line
)(ref
== expect_ref
, "got %ld\n", ref
);
63 static double scale_music_time(MUSIC_TIME time
, double tempo
)
65 return (600000000.0 * time
) / (tempo
* 768.0);
68 #define check_dmus_note_pmsg(a, b, c, d, e, f, g) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f, g)
69 static void check_dmus_note_pmsg_(int line
, DMUS_NOTE_PMSG
*msg
, MUSIC_TIME time
, UINT chan
,
70 UINT duration
, UINT key
, UINT vel
, UINT flags
)
72 ok_(__FILE__
, line
)(msg
->dwSize
== sizeof(*msg
), "got dwSize %lu\n", msg
->dwSize
);
73 ok_(__FILE__
, line
)(!!msg
->rtTime
, "got rtTime %I64u\n", msg
->rtTime
);
74 ok_(__FILE__
, line
)(abs(msg
->mtTime
- time
) < 10, "got mtTime %lu\n", msg
->mtTime
);
75 ok_(__FILE__
, line
)(msg
->dwPChannel
== chan
, "got dwPChannel %lu\n", msg
->dwPChannel
);
76 ok_(__FILE__
, line
)(!!msg
->dwVirtualTrackID
, "got dwVirtualTrackID %lu\n", msg
->dwVirtualTrackID
);
77 ok_(__FILE__
, line
)(msg
->dwType
== DMUS_PMSGT_NOTE
, "got %#lx\n", msg
->dwType
);
78 ok_(__FILE__
, line
)(!msg
->dwVoiceID
, "got dwVoiceID %lu\n", msg
->dwVoiceID
);
79 ok_(__FILE__
, line
)(msg
->dwGroupID
== 1, "got dwGroupID %lu\n", msg
->dwGroupID
);
80 ok_(__FILE__
, line
)(!msg
->punkUser
, "got punkUser %p\n", msg
->punkUser
);
81 ok_(__FILE__
, line
)(msg
->mtDuration
== duration
, "got mtDuration %lu\n", msg
->mtDuration
);
82 ok_(__FILE__
, line
)(msg
->wMusicValue
== key
, "got wMusicValue %u\n", msg
->wMusicValue
);
83 ok_(__FILE__
, line
)(!msg
->wMeasure
, "got wMeasure %u\n", msg
->wMeasure
);
84 /* FIXME: ok_(__FILE__, line)(!msg->nOffset, "got nOffset %u\n", msg->nOffset); */
85 /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */
86 /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */
87 ok_(__FILE__
, line
)(msg
->bVelocity
== vel
, "got bVelocity %u\n", msg
->bVelocity
);
88 ok_(__FILE__
, line
)(msg
->bFlags
== flags
, "got bFlags %#x\n", msg
->bFlags
);
89 ok_(__FILE__
, line
)(!msg
->bTimeRange
, "got bTimeRange %u\n", msg
->bTimeRange
);
90 ok_(__FILE__
, line
)(!msg
->bDurRange
, "got bDurRange %u\n", msg
->bDurRange
);
91 ok_(__FILE__
, line
)(!msg
->bVelRange
, "got bVelRange %u\n", msg
->bVelRange
);
92 ok_(__FILE__
, line
)(!msg
->bPlayModeFlags
, "got bPlayModeFlags %#x\n", msg
->bPlayModeFlags
);
93 ok_(__FILE__
, line
)(!msg
->bSubChordLevel
, "got bSubChordLevel %u\n", msg
->bSubChordLevel
);
94 ok_(__FILE__
, line
)(msg
->bMidiValue
== key
, "got bMidiValue %u\n", msg
->bMidiValue
);
95 ok_(__FILE__
, line
)(!msg
->cTranspose
, "got cTranspose %u\n", msg
->cTranspose
);
98 static void load_resource(const WCHAR
*name
, WCHAR
*filename
)
100 static WCHAR path
[MAX_PATH
];
106 GetTempPathW(ARRAY_SIZE(path
), path
);
107 GetTempFileNameW(path
, name
, 0, filename
);
109 file
= CreateFileW(filename
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
110 ok(file
!= INVALID_HANDLE_VALUE
, "failed to create %s, error %lu\n", debugstr_w(filename
), GetLastError());
112 res
= FindResourceW(NULL
, name
, (const WCHAR
*)RT_RCDATA
);
113 ok(res
!= 0, "couldn't find resource\n");
114 ptr
= LockResource(LoadResource(GetModuleHandleW(NULL
), res
));
115 WriteFile(file
, ptr
, SizeofResource(GetModuleHandleW(NULL
), res
), &written
, NULL
);
116 ok(written
== SizeofResource(GetModuleHandleW(NULL
), res
), "couldn't write resource\n");
120 static void stream_begin_chunk(IStream
*stream
, const char type
[5], ULARGE_INTEGER
*offset
)
122 static const LARGE_INTEGER zero
= {0};
124 hr
= IStream_Write(stream
, type
, 4, NULL
);
125 ok(hr
== S_OK
, "got %#lx\n", hr
);
126 hr
= IStream_Seek(stream
, zero
, STREAM_SEEK_CUR
, offset
);
127 ok(hr
== S_OK
, "got %#lx\n", hr
);
128 hr
= IStream_Write(stream
, "\0\0\0\0", 4, NULL
);
129 ok(hr
== S_OK
, "got %#lx\n", hr
);
132 static void stream_end_chunk(IStream
*stream
, ULARGE_INTEGER
*offset
)
134 static const LARGE_INTEGER zero
= {0};
135 ULARGE_INTEGER position
;
138 hr
= IStream_Seek(stream
, zero
, STREAM_SEEK_CUR
, &position
);
139 ok(hr
== S_OK
, "got %#lx\n", hr
);
140 hr
= IStream_Seek(stream
, *(LARGE_INTEGER
*)offset
, STREAM_SEEK_SET
, NULL
);
141 ok(hr
== S_OK
, "got %#lx\n", hr
);
142 size
= position
.QuadPart
- offset
->QuadPart
- 4;
143 hr
= IStream_Write(stream
, &size
, 4, NULL
);
144 ok(hr
== S_OK
, "got %#lx\n", hr
);
145 hr
= IStream_Seek(stream
, *(LARGE_INTEGER
*)&position
, STREAM_SEEK_SET
, NULL
);
146 ok(hr
== S_OK
, "got %#lx\n", hr
);
147 hr
= IStream_Write(stream
, &zero
, (position
.QuadPart
& 1), NULL
);
148 ok(hr
== S_OK
, "got %#lx\n", hr
);
151 #define CHUNK_BEGIN(stream, type) \
153 ULARGE_INTEGER __off; \
154 IStream *__stream = (stream); \
155 stream_begin_chunk(stream, type, &__off); \
158 #define CHUNK_RIFF(stream, form) \
160 ULARGE_INTEGER __off; \
161 IStream *__stream = (stream); \
162 stream_begin_chunk(stream, "RIFF", &__off); \
163 IStream_Write(stream, form, 4, NULL); \
166 #define CHUNK_LIST(stream, form) \
168 ULARGE_INTEGER __off; \
169 IStream *__stream = (stream); \
170 stream_begin_chunk(stream, "LIST", &__off); \
171 IStream_Write(stream, form, 4, NULL); \
176 stream_end_chunk(__stream, &__off); \
179 #define CHUNK_DATA(stream, type, data) \
180 CHUNK_BEGIN(stream, type) \
182 IStream_Write((stream), &(data), sizeof(data), NULL); \
186 #define CHUNK_ARRAY(stream, type, items) \
187 CHUNK_BEGIN(stream, type) \
189 UINT __size = sizeof(*(items)); \
190 IStream_Write((stream), &__size, 4, NULL); \
191 IStream_Write((stream), &(items), sizeof(items), NULL); \
197 IDirectMusicTool IDirectMusicTool_iface
;
200 IDirectMusicGraph
*graph
;
205 HANDLE message_event
;
206 DMUS_PMSG
*messages
[32];
210 static DMUS_PMSG
*test_tool_push_msg(struct test_tool
*tool
, DMUS_PMSG
*msg
)
212 AcquireSRWLockExclusive(&tool
->lock
);
213 ok(tool
->message_count
< ARRAY_SIZE(tool
->messages
),
214 "got %u messages\n", tool
->message_count
+ 1);
215 if (tool
->message_count
< ARRAY_SIZE(tool
->messages
))
217 memmove(tool
->messages
+ 1, tool
->messages
,
218 tool
->message_count
* sizeof(*tool
->messages
));
219 tool
->messages
[0] = msg
;
220 tool
->message_count
++;
223 ReleaseSRWLockExclusive(&tool
->lock
);
228 static struct test_tool
*impl_from_IDirectMusicTool(IDirectMusicTool
*iface
)
230 return CONTAINING_RECORD(iface
, struct test_tool
, IDirectMusicTool_iface
);
233 static HRESULT WINAPI
test_tool_QueryInterface(IDirectMusicTool
*iface
, REFIID iid
, void **out
)
235 if (IsEqualGUID(iid
, &IID_IUnknown
)
236 || IsEqualGUID(iid
, &IID_IDirectMusicTool
))
238 IDirectMusicTool_AddRef(iface
);
243 ok(IsEqualGUID(iid
, &IID_IDirectMusicTool8
) || IsEqualGUID(iid
, &IID_IPersistStream
),
244 "got iid %s\n", debugstr_guid(iid
));
246 return E_NOINTERFACE
;
249 static ULONG WINAPI
test_tool_AddRef(IDirectMusicTool
*iface
)
251 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
252 return InterlockedIncrement(&tool
->ref
);
255 static ULONG WINAPI
test_tool_Release(IDirectMusicTool
*iface
)
257 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
258 ULONG ref
= InterlockedDecrement(&tool
->ref
);
262 if (tool
->graph
) IDirectMusicGraph_Release(tool
->graph
);
263 ok(!tool
->message_count
, "got %p\n", &tool
->message_count
);
264 CloseHandle(tool
->message_event
);
271 static HRESULT WINAPI
test_tool_Init(IDirectMusicTool
*iface
, IDirectMusicGraph
*graph
)
273 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
274 if ((tool
->graph
= graph
)) IDirectMusicGraph_AddRef(tool
->graph
);
278 static HRESULT WINAPI
test_tool_GetMsgDeliveryType(IDirectMusicTool
*iface
, DWORD
*type
)
280 *type
= DMUS_PMSGF_TOOL_IMMEDIATE
;
284 static HRESULT WINAPI
test_tool_GetMediaTypeArraySize(IDirectMusicTool
*iface
, DWORD
*size
)
286 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
287 *size
= tool
->types_count
;
291 static HRESULT WINAPI
test_tool_GetMediaTypes(IDirectMusicTool
*iface
, DWORD
**types
, DWORD size
)
293 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
295 for (i
= 0; i
< tool
->types_count
; i
++) (*types
)[i
] = tool
->types
[i
];
299 static HRESULT WINAPI
test_tool_ProcessPMsg(IDirectMusicTool
*iface
, IDirectMusicPerformance
*performance
, DMUS_PMSG
*msg
)
301 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
305 hr
= IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8
*)performance
, msg
, &clone
);
306 ok(hr
== S_OK
, "got %#lx\n", hr
);
307 clone
= test_tool_push_msg(tool
, clone
);
308 ok(!clone
, "got %p\n", clone
);
309 SetEvent(tool
->message_event
);
311 hr
= IDirectMusicGraph_StampPMsg(msg
->pGraph
, msg
);
312 ok(hr
== S_OK
, "got %#lx\n", hr
);
314 return DMUS_S_REQUEUE
;
317 static HRESULT WINAPI
test_tool_Flush(IDirectMusicTool
*iface
, IDirectMusicPerformance
*performance
,
318 DMUS_PMSG
*msg
, REFERENCE_TIME time
)
320 ok(0, "unexpected %s\n", __func__
);
324 static IDirectMusicToolVtbl test_tool_vtbl
=
326 test_tool_QueryInterface
,
330 test_tool_GetMsgDeliveryType
,
331 test_tool_GetMediaTypeArraySize
,
332 test_tool_GetMediaTypes
,
333 test_tool_ProcessPMsg
,
337 static HRESULT
test_tool_create(const DWORD
*types
, DWORD types_count
,
338 IDirectMusicTool
**ret_iface
)
340 struct test_tool
*tool
;
343 if (!(tool
= calloc(1, sizeof(*tool
)))) return E_OUTOFMEMORY
;
344 tool
->IDirectMusicTool_iface
.lpVtbl
= &test_tool_vtbl
;
348 tool
->types_count
= types_count
;
349 tool
->message_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
350 ok(!!tool
->message_event
, "CreateEventW failed, error %lu\n", GetLastError());
352 *ret_iface
= &tool
->IDirectMusicTool_iface
;
356 static HRESULT
test_tool_get_graph(IDirectMusicTool
*iface
, IDirectMusicGraph
**graph
)
358 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
359 if ((*graph
= tool
->graph
)) IDirectMusicGraph_AddRef(tool
->graph
);
360 return tool
->graph
? S_OK
: DMUS_E_NOT_FOUND
;
363 static DWORD
test_tool_wait_message(IDirectMusicTool
*iface
, DWORD timeout
, DMUS_PMSG
**msg
)
365 struct test_tool
*tool
= impl_from_IDirectMusicTool(iface
);
366 DWORD ret
= WAIT_FAILED
;
370 AcquireSRWLockExclusive(&tool
->lock
);
371 if (!tool
->message_count
)
375 UINT index
= --tool
->message_count
;
376 *msg
= tool
->messages
[index
];
377 tool
->messages
[index
] = NULL
;
379 ReleaseSRWLockExclusive(&tool
->lock
);
382 } while (!(ret
= WaitForSingleObject(tool
->message_event
, timeout
)));
387 struct test_loader_stream
389 IStream IStream_iface
;
390 IDirectMusicGetLoader IDirectMusicGetLoader_iface
;
394 IDirectMusicLoader
*loader
;
397 static struct test_loader_stream
*impl_from_IStream(IStream
*iface
)
399 return CONTAINING_RECORD(iface
, struct test_loader_stream
, IStream_iface
);
402 static HRESULT WINAPI
test_loader_stream_QueryInterface(IStream
*iface
, REFIID iid
, void **out
)
404 struct test_loader_stream
*impl
= impl_from_IStream(iface
);
406 if (IsEqualGUID(iid
, &IID_IUnknown
)
407 || IsEqualGUID(iid
, &IID_IStream
))
409 IStream_AddRef(&impl
->IStream_iface
);
410 *out
= &impl
->IStream_iface
;
414 if (IsEqualGUID(iid
, &IID_IDirectMusicGetLoader
))
416 IDirectMusicGetLoader_AddRef(&impl
->IDirectMusicGetLoader_iface
);
417 *out
= &impl
->IDirectMusicGetLoader_iface
;
421 ok(IsEqualGUID(iid
, &IID_IStream
),
422 "got iid %s\n", debugstr_guid(iid
));
424 return E_NOINTERFACE
;
427 static ULONG WINAPI
test_loader_stream_AddRef(IStream
*iface
)
429 struct test_loader_stream
*impl
= impl_from_IStream(iface
);
430 return InterlockedIncrement(&impl
->ref
);
433 static ULONG WINAPI
test_loader_stream_Release(IStream
*iface
)
435 struct test_loader_stream
*impl
= impl_from_IStream(iface
);
436 ULONG ref
= InterlockedDecrement(&impl
->ref
);
440 IDirectMusicLoader_Release(impl
->loader
);
441 IStream_Release(impl
->stream
);
448 static HRESULT WINAPI
test_loader_stream_Read(IStream
*iface
, void *data
, ULONG size
, ULONG
*ret_size
)
450 struct test_loader_stream
*impl
= impl_from_IStream(iface
);
451 return IStream_Read(impl
->stream
, data
, size
, ret_size
);
454 static HRESULT WINAPI
test_loader_stream_Write(IStream
*iface
, const void *data
, ULONG size
, ULONG
*ret_size
)
456 ok(0, "Unexpected call.\n");
460 static HRESULT WINAPI
test_loader_stream_Seek(IStream
*iface
, LARGE_INTEGER offset
, DWORD method
, ULARGE_INTEGER
*ret_offset
)
462 struct test_loader_stream
*impl
= impl_from_IStream(iface
);
463 return IStream_Seek(impl
->stream
, offset
, method
, ret_offset
);
466 static HRESULT WINAPI
test_loader_stream_SetSize(IStream
*iface
, ULARGE_INTEGER size
)
468 ok(0, "Unexpected call.\n");
472 static HRESULT WINAPI
test_loader_stream_CopyTo(IStream
*iface
, IStream
*dest
, ULARGE_INTEGER size
,
473 ULARGE_INTEGER
*read_size
, ULARGE_INTEGER
*write_size
)
475 ok(0, "Unexpected call.\n");
479 static HRESULT WINAPI
test_loader_stream_Commit(IStream
*iface
, DWORD flags
)
481 ok(0, "Unexpected call.\n");
485 static HRESULT WINAPI
test_loader_stream_Revert(IStream
*iface
)
487 ok(0, "Unexpected call.\n");
491 static HRESULT WINAPI
test_loader_stream_LockRegion(IStream
*iface
, ULARGE_INTEGER offset
, ULARGE_INTEGER size
, DWORD type
)
493 ok(0, "Unexpected call.\n");
497 static HRESULT WINAPI
test_loader_stream_UnlockRegion(IStream
*iface
, ULARGE_INTEGER offset
, ULARGE_INTEGER size
, DWORD type
)
499 ok(0, "Unexpected call.\n");
503 static HRESULT WINAPI
test_loader_stream_Stat(IStream
*iface
, STATSTG
*stat
, DWORD flags
)
505 ok(0, "Unexpected call.\n");
509 static HRESULT WINAPI
test_loader_stream_Clone(IStream
*iface
, IStream
**out
)
511 ok(0, "Unexpected call.\n");
515 static const IStreamVtbl test_loader_stream_vtbl
=
517 test_loader_stream_QueryInterface
,
518 test_loader_stream_AddRef
,
519 test_loader_stream_Release
,
520 test_loader_stream_Read
,
521 test_loader_stream_Write
,
522 test_loader_stream_Seek
,
523 test_loader_stream_SetSize
,
524 test_loader_stream_CopyTo
,
525 test_loader_stream_Commit
,
526 test_loader_stream_Revert
,
527 test_loader_stream_LockRegion
,
528 test_loader_stream_UnlockRegion
,
529 test_loader_stream_Stat
,
530 test_loader_stream_Clone
,
533 static struct test_loader_stream
*impl_from_IDirectMusicGetLoader(IDirectMusicGetLoader
*iface
)
535 return CONTAINING_RECORD(iface
, struct test_loader_stream
, IDirectMusicGetLoader_iface
);
538 static HRESULT WINAPI
test_loader_stream_getter_QueryInterface(IDirectMusicGetLoader
*iface
, REFIID iid
, void **out
)
540 struct test_loader_stream
*impl
= impl_from_IDirectMusicGetLoader(iface
);
541 return IStream_QueryInterface(&impl
->IStream_iface
, iid
, out
);
544 static ULONG WINAPI
test_loader_stream_getter_AddRef(IDirectMusicGetLoader
*iface
)
546 struct test_loader_stream
*impl
= impl_from_IDirectMusicGetLoader(iface
);
547 return IStream_AddRef(&impl
->IStream_iface
);
550 static ULONG WINAPI
test_loader_stream_getter_Release(IDirectMusicGetLoader
*iface
)
552 struct test_loader_stream
*impl
= impl_from_IDirectMusicGetLoader(iface
);
553 return IStream_Release(&impl
->IStream_iface
);
556 static HRESULT WINAPI
test_loader_stream_getter_GetLoader(IDirectMusicGetLoader
*iface
, IDirectMusicLoader
**ret_loader
)
558 struct test_loader_stream
*impl
= impl_from_IDirectMusicGetLoader(iface
);
560 *ret_loader
= impl
->loader
;
561 IDirectMusicLoader_AddRef(impl
->loader
);
566 static const IDirectMusicGetLoaderVtbl test_loader_stream_getter_vtbl
=
568 test_loader_stream_getter_QueryInterface
,
569 test_loader_stream_getter_AddRef
,
570 test_loader_stream_getter_Release
,
571 test_loader_stream_getter_GetLoader
,
574 static HRESULT
test_loader_stream_create(IStream
*stream
, IDirectMusicLoader
*loader
,
577 struct test_loader_stream
*obj
;
580 if (!(obj
= calloc(1, sizeof(*obj
)))) return E_OUTOFMEMORY
;
581 obj
->IStream_iface
.lpVtbl
= &test_loader_stream_vtbl
;
582 obj
->IDirectMusicGetLoader_iface
.lpVtbl
= &test_loader_stream_getter_vtbl
;
585 obj
->stream
= stream
;
586 IStream_AddRef(stream
);
587 obj
->loader
= loader
;
588 IDirectMusicLoader_AddRef(loader
);
590 *ret_iface
= &obj
->IStream_iface
;
596 /* Implementing IDirectMusicTrack8 will cause native to call PlayEx */
597 IDirectMusicTrack IDirectMusicTrack_iface
;
606 HANDLE playing_event
;
609 #define check_track_state(track, state, value) \
612 DWORD ret = impl_from_IDirectMusicTrack(track)->state; \
613 ok(ret == (value), "got %#lx\n", ret); \
616 static inline struct test_track
*impl_from_IDirectMusicTrack(IDirectMusicTrack
*iface
)
618 return CONTAINING_RECORD(iface
, struct test_track
, IDirectMusicTrack_iface
);
621 static HRESULT WINAPI
test_track_QueryInterface(IDirectMusicTrack
*iface
, REFIID riid
,
624 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
626 if (IsEqualIID(riid
, &IID_IUnknown
)
627 || IsEqualIID(riid
, &IID_IDirectMusicTrack
))
629 *ret_iface
= &This
->IDirectMusicTrack_iface
;
630 IDirectMusicTrack_AddRef(&This
->IDirectMusicTrack_iface
);
634 ok(IsEqualGUID(riid
, &IID_IDirectMusicTrack8
) || IsEqualGUID(riid
, &IID_IPersistStream
),
635 "unexpected %s %p %s\n", __func__
, This
, debugstr_guid(riid
));
637 return E_NOINTERFACE
;
640 static ULONG WINAPI
test_track_AddRef(IDirectMusicTrack
*iface
)
642 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
643 return InterlockedIncrement(&This
->ref
);
646 static ULONG WINAPI
test_track_Release(IDirectMusicTrack
*iface
)
648 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
649 ULONG ref
= InterlockedDecrement(&This
->ref
);
653 CloseHandle(This
->playing_event
);
660 static HRESULT WINAPI
test_track_Init(IDirectMusicTrack
*iface
, IDirectMusicSegment
*segment
)
662 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
663 This
->inserted
= TRUE
;
667 static HRESULT WINAPI
test_track_InitPlay(IDirectMusicTrack
*iface
, IDirectMusicSegmentState
*segment_state
,
668 IDirectMusicPerformance
*performance
, void **state_data
, DWORD track_id
, DWORD segment_flags
)
670 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
672 ok(!!segment_state
, "got %p\n", segment_state
);
673 ok(!!performance
, "got %p\n", performance
);
674 ok(!!state_data
, "got %p\n", state_data
);
675 ok(!!track_id
, "got %lu\n", track_id
);
676 ok(!segment_flags
, "got %#lx\n", segment_flags
);
677 This
->initialized
= TRUE
;
679 *state_data
= &This
->data
;
683 static HRESULT WINAPI
test_track_EndPlay(IDirectMusicTrack
*iface
, void *state_data
)
685 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
687 ok(state_data
== &This
->data
, "got %p\n", state_data
);
688 This
->playing
= FALSE
;
693 static HRESULT WINAPI
test_track_Play(IDirectMusicTrack
*iface
, void *state_data
,
694 MUSIC_TIME start_time
, MUSIC_TIME end_time
, MUSIC_TIME time_offset
, DWORD segment_flags
,
695 IDirectMusicPerformance
*performance
, IDirectMusicSegmentState
*segment_state
, DWORD track_id
)
697 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
699 if (!This
->test_play
) return S_OK
;
701 ok(state_data
== &This
->data
, "got %p\n", state_data
);
702 ok(start_time
== 50, "got %lu\n", start_time
);
703 ok(end_time
== 100, "got %lu\n", end_time
);
704 todo_wine
ok(time_offset
< 0, "got %lu\n", time_offset
);
705 ok(segment_flags
== (DMUS_TRACKF_DIRTY
|DMUS_TRACKF_START
|DMUS_TRACKF_SEEK
),
706 "got %#lx\n", segment_flags
);
707 ok(!!performance
, "got %p\n", performance
);
708 ok(!!segment_state
, "got %p\n", segment_state
);
709 ok(!!track_id
, "got %lu\n", track_id
);
710 This
->playing
= TRUE
;
711 SetEvent(This
->playing_event
);
716 static HRESULT WINAPI
test_track_GetParam(IDirectMusicTrack
*iface
, REFGUID type
, MUSIC_TIME time
,
717 MUSIC_TIME
*next
, void *param
)
719 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
720 ok(0, "unexpected %s %p\n", __func__
, This
);
724 static HRESULT WINAPI
test_track_SetParam(IDirectMusicTrack
*iface
, REFGUID type
, MUSIC_TIME time
, void *param
)
726 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
728 if (IsEqualGUID(type
, &GUID_DownloadToAudioPath
))
730 This
->downloaded
= TRUE
;
734 if (IsEqualGUID(type
, &GUID_UnloadFromAudioPath
))
736 This
->downloaded
= FALSE
;
740 ok(0, "unexpected %s %p %s %lu %p\n", __func__
, This
, debugstr_guid(type
), time
, param
);
744 static HRESULT WINAPI
test_track_IsParamSupported(IDirectMusicTrack
*iface
, REFGUID type
)
746 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
748 if (IsEqualGUID(type
, &GUID_DownloadToAudioPath
)) return S_OK
;
749 if (IsEqualGUID(type
, &GUID_UnloadFromAudioPath
)) return S_OK
;
750 if (IsEqualGUID(type
, &GUID_TimeSignature
)) return DMUS_E_TYPE_UNSUPPORTED
;
751 if (IsEqualGUID(type
, &GUID_TempoParam
)) return DMUS_E_TYPE_UNSUPPORTED
;
753 ok(broken(type
->Data1
== 0xe8dbd832), /* native also checks some unknown parameter */
754 "unexpected %s %p %s\n", __func__
, This
, debugstr_guid(type
));
758 static HRESULT WINAPI
test_track_AddNotificationType(IDirectMusicTrack
*iface
, REFGUID type
)
760 ok(IsEqualGUID(type
, &GUID_NOTIFICATION_SEGMENT
) || IsEqualGUID(type
, &GUID_NOTIFICATION_PERFORMANCE
),
761 "got %s\n", debugstr_guid(type
));
765 static HRESULT WINAPI
test_track_RemoveNotificationType(IDirectMusicTrack
*iface
, REFGUID type
)
767 ok(IsEqualGUID(type
, &GUID_NOTIFICATION_SEGMENT
) || IsEqualGUID(type
, &GUID_NOTIFICATION_PERFORMANCE
),
768 "got %s\n", debugstr_guid(type
));
772 static HRESULT WINAPI
test_track_Clone(IDirectMusicTrack
*iface
, MUSIC_TIME start_time
,
773 MUSIC_TIME end_time
, IDirectMusicTrack
**ret_track
)
775 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
776 ok(0, "unexpected %s %p\n", __func__
, This
);
780 static const IDirectMusicTrackVtbl test_track_vtbl
=
782 test_track_QueryInterface
,
791 test_track_IsParamSupported
,
792 test_track_AddNotificationType
,
793 test_track_RemoveNotificationType
,
797 static HRESULT
test_track_create(IDirectMusicTrack
**ret_iface
, BOOL test_play
)
799 struct test_track
*track
;
802 if (!(track
= calloc(1, sizeof(*track
)))) return E_OUTOFMEMORY
;
803 track
->IDirectMusicTrack_iface
.lpVtbl
= &test_track_vtbl
;
805 track
->test_play
= test_play
;
807 track
->playing_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
808 ok(!!track
->playing_event
, "CreateEventW failed, error %lu\n", GetLastError());
810 *ret_iface
= &track
->IDirectMusicTrack_iface
;
814 static DWORD
test_track_wait_playing(IDirectMusicTrack
*iface
, DWORD timeout
)
816 struct test_track
*This
= impl_from_IDirectMusicTrack(iface
);
817 return WaitForSingleObject(This
->playing_event
, timeout
);
820 static void create_performance(IDirectMusicPerformance8
**performance
, IDirectMusic
**dmusic
,
821 IDirectSound
**dsound
, BOOL set_cooplevel
)
825 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
826 &IID_IDirectMusicPerformance8
, (void **)performance
);
827 ok(hr
== S_OK
, "DirectMusicPerformance create failed: %#lx\n", hr
);
829 hr
= CoCreateInstance(&CLSID_DirectMusic
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusic8
,
831 ok(hr
== S_OK
, "DirectMusic create failed: %#lx\n", hr
);
834 hr
= DirectSoundCreate8(NULL
, (IDirectSound8
**)dsound
, NULL
);
835 ok(hr
== S_OK
, "DirectSoundCreate failed: %#lx\n", hr
);
837 hr
= IDirectSound_SetCooperativeLevel(*dsound
, GetForegroundWindow(), DSSCL_PRIORITY
);
838 ok(hr
== S_OK
, "SetCooperativeLevel failed: %#lx\n", hr
);
843 static void destroy_performance(IDirectMusicPerformance8
*performance
, IDirectMusic
*dmusic
,
844 IDirectSound
*dsound
)
848 hr
= IDirectMusicPerformance8_CloseDown(performance
);
849 ok(hr
== S_OK
, "CloseDown failed: %#lx\n", hr
);
850 IDirectMusicPerformance8_Release(performance
);
852 IDirectMusic_Release(dmusic
);
854 IDirectSound_Release(dsound
);
857 static BOOL
missing_dmime(void)
859 IDirectMusicSegment8
*dms
;
860 HRESULT hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
861 &IID_IDirectMusicSegment
, (void**)&dms
);
863 if (hr
== S_OK
&& dms
)
865 IDirectMusicSegment8_Release(dms
);
871 static void test_COM_audiopath(void)
873 IDirectMusicAudioPath
*dmap
;
875 IDirectMusicPerformance8
*performance
;
876 IDirectSoundBuffer
*dsound
;
877 IDirectSoundBuffer8
*dsound8
;
878 IDirectSoundNotify
*notify
;
879 IDirectSound3DBuffer
*dsound3d
;
880 IKsPropertySet
*propset
;
885 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
886 &IID_IDirectMusicPerformance8
, (void**)&performance
);
887 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "DirectMusicPerformance create failed: %#lx\n", hr
);
889 win_skip("IDirectMusicPerformance8 not available\n");
892 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, NULL
, NULL
,
893 DMUS_APATH_SHARED_STEREOPLUSREVERB
, 64, DMUS_AUDIOF_ALL
, NULL
);
894 ok(hr
== S_OK
|| hr
== DSERR_NODRIVER
||
895 broken(hr
== AUDCLNT_E_ENDPOINT_CREATE_FAILED
), /* Win 10 testbot */
896 "DirectMusicPerformance_InitAudio failed: %#lx\n", hr
);
898 skip("Audio failed to initialize\n");
901 hr
= IDirectMusicPerformance8_GetDefaultAudioPath(performance
, &dmap
);
902 ok(hr
== S_OK
, "DirectMusicPerformance_GetDefaultAudioPath failed: %#lx\n", hr
);
904 /* IDirectMusicObject and IPersistStream are not supported */
905 hr
= IDirectMusicAudioPath_QueryInterface(dmap
, &IID_IDirectMusicObject
, (void**)&unk
);
906 todo_wine
ok(FAILED(hr
) && !unk
, "Unexpected IDirectMusicObject interface: hr=%#lx, iface=%p\n",
908 if (unk
) IUnknown_Release(unk
);
909 hr
= IDirectMusicAudioPath_QueryInterface(dmap
, &IID_IPersistStream
, (void**)&unk
);
910 todo_wine
ok(FAILED(hr
) && !unk
, "Unexpected IPersistStream interface: hr=%#lx, iface=%p\n",
912 if (unk
) IUnknown_Release(unk
);
914 /* Same refcount for all DirectMusicAudioPath interfaces */
915 refcount
= IDirectMusicAudioPath_AddRef(dmap
);
916 ok(refcount
== 3, "refcount == %lu, expected 3\n", refcount
);
918 hr
= IDirectMusicAudioPath_QueryInterface(dmap
, &IID_IUnknown
, (void**)&unk
);
919 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
920 ok(unk
== (IUnknown
*)dmap
, "got %p, %p\n", unk
, dmap
);
921 refcount
= IUnknown_AddRef(unk
);
922 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
923 refcount
= IUnknown_Release(unk
);
925 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
926 0, &IID_IDirectSoundBuffer
, (void**)&dsound
);
927 ok(hr
== S_OK
, "Failed: %#lx\n", hr
);
928 IDirectSoundBuffer_Release(dsound
);
930 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
931 0, &IID_IDirectSoundBuffer8
, (void**)&dsound8
);
932 ok(hr
== S_OK
, "Failed: %#lx\n", hr
);
933 IDirectSoundBuffer8_Release(dsound8
);
935 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
936 0, &IID_IDirectSoundNotify
, (void**)¬ify
);
937 ok(hr
== E_NOINTERFACE
, "Failed: %#lx\n", hr
);
939 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
940 0, &IID_IDirectSound3DBuffer
, (void**)&dsound3d
);
941 ok(hr
== E_NOINTERFACE
, "Failed: %#lx\n", hr
);
943 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
944 0, &IID_IKsPropertySet
, (void**)&propset
);
945 todo_wine
ok(hr
== S_OK
, "Failed: %#lx\n", hr
);
947 IKsPropertySet_Release(propset
);
949 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
950 0, &IID_IUnknown
, (void**)&unk
);
951 ok(hr
== S_OK
, "Failed: %#lx\n", hr
);
952 IUnknown_Release(unk
);
954 hr
= IDirectMusicAudioPath_GetObjectInPath(dmap
, DMUS_PCHANNEL_ALL
, DMUS_PATH_BUFFER
, buffer
, &GUID_NULL
,
955 0, &GUID_NULL
, (void**)&unk
);
956 ok(hr
== E_NOINTERFACE
, "Failed: %#lx\n", hr
);
958 while (IDirectMusicAudioPath_Release(dmap
) > 1); /* performance has a reference too */
959 IDirectMusicPerformance8_CloseDown(performance
);
960 IDirectMusicPerformance8_Release(performance
);
963 static void test_COM_audiopathconfig(void)
965 IDirectMusicAudioPath
*dmap
= (IDirectMusicAudioPath
*)0xdeadbeef;
966 IDirectMusicObject
*dmo
;
972 /* COM aggregation */
973 hr
= CoCreateInstance(&CLSID_DirectMusicAudioPathConfig
, (IUnknown
*)0xdeadbeef, CLSCTX_INPROC_SERVER
,
974 &IID_IUnknown
, (void**)&dmap
);
975 if (hr
== REGDB_E_CLASSNOTREG
) {
976 win_skip("DirectMusicAudioPathConfig not registered\n");
979 ok(hr
== CLASS_E_NOAGGREGATION
,
980 "DirectMusicAudioPathConfig create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
981 ok(!dmap
, "dmap = %p\n", dmap
);
983 /* IDirectMusicAudioPath not supported */
984 hr
= CoCreateInstance(&CLSID_DirectMusicAudioPathConfig
, NULL
, CLSCTX_INPROC_SERVER
,
985 &IID_IDirectMusicAudioPath
, (void**)&dmap
);
986 todo_wine
ok(FAILED(hr
) && !dmap
,
987 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr
, dmap
);
989 /* IDirectMusicObject and IPersistStream supported */
990 hr
= CoCreateInstance(&CLSID_DirectMusicAudioPathConfig
, NULL
, CLSCTX_INPROC_SERVER
,
991 &IID_IPersistStream
, (void**)&ps
);
992 ok(hr
== S_OK
, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr
);
993 IPersistStream_Release(ps
);
994 hr
= CoCreateInstance(&CLSID_DirectMusicAudioPathConfig
, NULL
, CLSCTX_INPROC_SERVER
,
995 &IID_IDirectMusicObject
, (void**)&dmo
);
996 ok(hr
== S_OK
, "DirectMusicObject create failed: %#lx, expected S_OK\n", hr
);
998 /* Same refcount for all DirectMusicObject interfaces */
999 refcount
= IDirectMusicObject_AddRef(dmo
);
1000 ok(refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1002 hr
= IDirectMusicObject_QueryInterface(dmo
, &IID_IPersistStream
, (void**)&ps
);
1003 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1004 refcount
= IPersistStream_AddRef(ps
);
1005 ok(refcount
== 4, "refcount == %lu, expected 4\n", refcount
);
1006 IPersistStream_Release(ps
);
1008 hr
= IDirectMusicObject_QueryInterface(dmo
, &IID_IUnknown
, (void**)&unk
);
1009 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
1010 refcount
= IUnknown_AddRef(unk
);
1011 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
1012 refcount
= IUnknown_Release(unk
);
1014 /* IDirectMusicAudioPath still not supported */
1015 hr
= IDirectMusicObject_QueryInterface(dmo
, &IID_IDirectMusicAudioPath
, (void**)&dmap
);
1016 todo_wine
ok(FAILED(hr
) && !dmap
,
1017 "Unexpected IDirectMusicAudioPath interface: hr=%#lx, iface=%p\n", hr
, dmap
);
1019 while (IDirectMusicObject_Release(dmo
));
1023 static void test_COM_graph(void)
1025 IDirectMusicGraph
*dmg
= (IDirectMusicGraph
*)0xdeadbeef;
1026 IDirectMusicObject
*dmo
;
1032 /* COM aggregation */
1033 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, (IUnknown
*)0xdeadbeef, CLSCTX_INPROC_SERVER
,
1034 &IID_IUnknown
, (void**)&dmg
);
1035 ok(hr
== CLASS_E_NOAGGREGATION
,
1036 "DirectMusicGraph create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
1037 ok(!dmg
, "dmg = %p\n", dmg
);
1040 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IClassFactory
,
1042 ok(hr
== E_NOINTERFACE
, "DirectMusicGraph create failed: %#lx, expected E_NOINTERFACE\n", hr
);
1044 /* Same refcount for all DirectMusicGraph interfaces */
1045 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1046 &IID_IDirectMusicGraph
, (void**)&dmg
);
1047 ok(hr
== S_OK
, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr
);
1048 refcount
= IDirectMusicGraph_AddRef(dmg
);
1049 ok(refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1051 hr
= IDirectMusicGraph_QueryInterface(dmg
, &IID_IDirectMusicObject
, (void**)&dmo
);
1052 if (hr
== E_NOINTERFACE
) {
1053 win_skip("DirectMusicGraph without IDirectMusicObject\n");
1056 ok(hr
== S_OK
, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr
);
1057 refcount
= IDirectMusicObject_AddRef(dmo
);
1058 ok(refcount
== 4, "refcount == %lu, expected 4\n", refcount
);
1059 refcount
= IDirectMusicObject_Release(dmo
);
1061 hr
= IDirectMusicGraph_QueryInterface(dmg
, &IID_IPersistStream
, (void**)&ps
);
1062 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1063 refcount
= IPersistStream_AddRef(ps
);
1064 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
1065 refcount
= IPersistStream_Release(ps
);
1067 hr
= IDirectMusicGraph_QueryInterface(dmg
, &IID_IUnknown
, (void**)&unk
);
1068 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
1069 refcount
= IUnknown_AddRef(unk
);
1070 ok(refcount
== 6, "refcount == %lu, expected 6\n", refcount
);
1071 refcount
= IUnknown_Release(unk
);
1073 while (IDirectMusicGraph_Release(dmg
));
1076 static void test_COM_segment(void)
1078 IDirectMusicSegment8
*dms
= (IDirectMusicSegment8
*)0xdeadbeef;
1079 IDirectMusicObject
*dmo
;
1080 IPersistStream
*stream
;
1085 /* COM aggregation */
1086 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, (IUnknown
*)0xdeadbeef, CLSCTX_INPROC_SERVER
,
1087 &IID_IUnknown
, (void**)&dms
);
1088 ok(hr
== CLASS_E_NOAGGREGATION
,
1089 "DirectMusicSegment create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
1090 ok(!dms
, "dms = %p\n", dms
);
1093 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
1094 &IID_IDirectSound
, (void**)&dms
);
1095 ok(hr
== E_NOINTERFACE
, "DirectMusicSegment create failed: %#lx, expected E_NOINTERFACE\n", hr
);
1098 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
1099 &IID_IDirectMusicSegment8
, (void**)&dms
);
1100 if (hr
== E_NOINTERFACE
) {
1101 win_skip("DirectMusicSegment without IDirectMusicSegment8\n");
1104 ok(hr
== S_OK
, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr
);
1105 refcount
= IDirectMusicSegment8_AddRef(dms
);
1106 ok (refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1107 hr
= IDirectMusicSegment8_QueryInterface(dms
, &IID_IDirectMusicObject
, (void**)&dmo
);
1108 ok(hr
== S_OK
, "QueryInterface for IID_IDirectMusicObject failed: %#lx\n", hr
);
1109 IDirectMusicSegment8_AddRef(dms
);
1110 refcount
= IDirectMusicSegment8_Release(dms
);
1111 ok (refcount
== 3, "refcount == %lu, expected 3\n", refcount
);
1112 hr
= IDirectMusicSegment8_QueryInterface(dms
, &IID_IPersistStream
, (void**)&stream
);
1113 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1114 refcount
= IDirectMusicSegment8_Release(dms
);
1115 ok (refcount
== 3, "refcount == %lu, expected 3\n", refcount
);
1116 hr
= IDirectMusicSegment8_QueryInterface(dms
, &IID_IUnknown
, (void**)&unk
);
1117 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
1118 refcount
= IUnknown_Release(unk
);
1119 ok (refcount
== 3, "refcount == %lu, expected 3\n", refcount
);
1120 refcount
= IDirectMusicObject_Release(dmo
);
1121 ok (refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1122 refcount
= IPersistStream_Release(stream
);
1123 ok (refcount
== 1, "refcount == %lu, expected 1\n", refcount
);
1124 refcount
= IDirectMusicSegment8_Release(dms
);
1125 ok (refcount
== 0, "refcount == %lu, expected 0\n", refcount
);
1128 static void test_COM_segmentstate(void)
1130 IDirectMusicSegmentState8
*dmss8
= (IDirectMusicSegmentState8
*)0xdeadbeef;
1135 /* COM aggregation */
1136 hr
= CoCreateInstance(&CLSID_DirectMusicSegmentState
, (IUnknown
*)0xdeadbeef, CLSCTX_INPROC_SERVER
,
1137 &IID_IUnknown
, (void**)&dmss8
);
1138 ok(hr
== CLASS_E_NOAGGREGATION
,
1139 "DirectMusicSegmentState8 create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
1140 ok(!dmss8
, "dmss8 = %p\n", dmss8
);
1143 hr
= CoCreateInstance(&CLSID_DirectMusicSegmentState
, NULL
, CLSCTX_INPROC_SERVER
,
1144 &IID_IDirectMusicObject
, (void**)&dmss8
);
1145 ok(hr
== E_NOINTERFACE
, "DirectMusicSegmentState8 create failed: %#lx, expected E_NOINTERFACE\n", hr
);
1147 /* Same refcount for all DirectMusicSegmentState interfaces */
1148 hr
= CoCreateInstance(&CLSID_DirectMusicSegmentState
, NULL
, CLSCTX_INPROC_SERVER
,
1149 &IID_IDirectMusicSegmentState8
, (void**)&dmss8
);
1150 if (hr
== E_NOINTERFACE
) {
1151 win_skip("DirectMusicSegmentState without IDirectMusicSegmentState8\n");
1154 ok(hr
== S_OK
, "DirectMusicSegmentState8 create failed: %#lx, expected S_OK\n", hr
);
1155 refcount
= IDirectMusicSegmentState8_AddRef(dmss8
);
1156 ok(refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1158 hr
= IDirectMusicSegmentState8_QueryInterface(dmss8
, &IID_IUnknown
, (void**)&unk
);
1159 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
1160 refcount
= IUnknown_AddRef(unk
);
1161 ok(refcount
== 4, "refcount == %lu, expected 4\n", refcount
);
1162 refcount
= IUnknown_Release(unk
);
1164 hr
= IDirectMusicSegmentState8_QueryInterface(dmss8
, &IID_IUnknown
, NULL
);
1165 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
1167 while (IDirectMusicSegmentState8_Release(dmss8
));
1170 static void test_COM_track(void)
1172 IDirectMusicTrack
*dmt
;
1173 IDirectMusicTrack8
*dmt8
;
1178 #define X(class) &CLSID_ ## class, #class
1184 { X(DirectMusicLyricsTrack
), TRUE
},
1185 { X(DirectMusicMarkerTrack
), FALSE
},
1186 { X(DirectMusicParamControlTrack
), TRUE
},
1187 { X(DirectMusicSegmentTriggerTrack
), TRUE
},
1188 { X(DirectMusicSeqTrack
), TRUE
},
1189 { X(DirectMusicSysExTrack
), TRUE
},
1190 { X(DirectMusicTempoTrack
), TRUE
},
1191 { X(DirectMusicTimeSigTrack
), FALSE
},
1192 { X(DirectMusicWaveTrack
), TRUE
}
1197 for (i
= 0; i
< ARRAY_SIZE(class); i
++) {
1198 trace("Testing %s\n", class[i
].name
);
1199 /* COM aggregation */
1200 dmt8
= (IDirectMusicTrack8
*)0xdeadbeef;
1201 hr
= CoCreateInstance(class[i
].clsid
, (IUnknown
*)0xdeadbeef, CLSCTX_INPROC_SERVER
, &IID_IUnknown
,
1203 if (hr
== REGDB_E_CLASSNOTREG
) {
1204 win_skip("%s not registered\n", class[i
].name
);
1207 ok(hr
== CLASS_E_NOAGGREGATION
,
1208 "%s create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", class[i
].name
, hr
);
1209 ok(!dmt8
, "dmt8 = %p\n", dmt8
);
1212 hr
= CoCreateInstance(class[i
].clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
,
1214 ok(hr
== E_NOINTERFACE
, "%s create failed: %#lx, expected E_NOINTERFACE\n", class[i
].name
, hr
);
1216 /* Same refcount for all DirectMusicTrack interfaces */
1217 hr
= CoCreateInstance(class[i
].clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
,
1219 ok(hr
== S_OK
, "%s create failed: %#lx, expected S_OK\n", class[i
].name
, hr
);
1220 refcount
= IDirectMusicTrack_AddRef(dmt
);
1221 ok(refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1223 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IPersistStream
, (void**)&ps
);
1224 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1225 refcount
= IPersistStream_AddRef(ps
);
1226 ok(refcount
== 4, "refcount == %lu, expected 4\n", refcount
);
1227 IPersistStream_Release(ps
);
1229 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IUnknown
, (void**)&unk
);
1230 ok(hr
== S_OK
, "QueryInterface for IID_IUnknown failed: %#lx\n", hr
);
1231 refcount
= IUnknown_AddRef(unk
);
1232 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
1233 refcount
= IUnknown_Release(unk
);
1235 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IDirectMusicTrack8
, (void**)&dmt8
);
1236 if (class[i
].has_dmt8
) {
1237 ok(hr
== S_OK
, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr
);
1238 refcount
= IDirectMusicTrack8_AddRef(dmt8
);
1239 ok(refcount
== 6, "refcount == %lu, expected 6\n", refcount
);
1240 refcount
= IDirectMusicTrack8_Release(dmt8
);
1242 ok(hr
== E_NOINTERFACE
, "QueryInterface for IID_IDirectMusicTrack8 failed: %#lx\n", hr
);
1243 refcount
= IDirectMusicTrack_AddRef(dmt
);
1244 ok(refcount
== 5, "refcount == %lu, expected 5\n", refcount
);
1247 while (IDirectMusicTrack_Release(dmt
));
1251 static void test_COM_performance(void)
1253 IDirectMusicPerformance
*dmp
= (IDirectMusicPerformance
*)0xdeadbeef;
1254 IDirectMusicPerformance
*dmp2
;
1255 IDirectMusicPerformance8
*dmp8
;
1259 /* COM aggregation */
1260 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, (IUnknown
*)0xdeadbeef, CLSCTX_INPROC_SERVER
,
1261 &IID_IUnknown
, (void**)&dmp
);
1262 ok(hr
== CLASS_E_NOAGGREGATION
,
1263 "DirectMusicPerformance create failed: %#lx, expected CLASS_E_NOAGGREGATION\n", hr
);
1264 ok(!dmp
, "dmp = %p\n", dmp
);
1267 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
1268 &IID_IDirectMusicObject
, (void**)&dmp
);
1269 ok(hr
== E_NOINTERFACE
, "DirectMusicPerformance create failed: %#lx, expected E_NOINTERFACE\n", hr
);
1272 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
1273 &IID_IDirectMusicPerformance
, (void**)&dmp
);
1274 ok(hr
== S_OK
, "DirectMusicPerformance create failed: %#lx, expected S_OK\n", hr
);
1275 refcount
= IDirectMusicPerformance_AddRef(dmp
);
1276 ok (refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1277 hr
= IDirectMusicPerformance_QueryInterface(dmp
, &IID_IDirectMusicPerformance2
, (void**)&dmp2
);
1278 ok(hr
== S_OK
, "QueryInterface for IID_IDirectMusicPerformance2 failed: %#lx\n", hr
);
1279 IDirectMusicPerformance_AddRef(dmp
);
1280 refcount
= IDirectMusicPerformance_Release(dmp
);
1281 ok (refcount
== 3, "refcount == %lu, expected 3\n", refcount
);
1282 hr
= IDirectMusicPerformance_QueryInterface(dmp
, &IID_IDirectMusicPerformance8
, (void**)&dmp8
);
1283 ok(hr
== S_OK
, "QueryInterface for IID_IDirectMusicPerformance8 failed: %#lx\n", hr
);
1284 refcount
= IDirectMusicPerformance_Release(dmp
);
1285 ok (refcount
== 3, "refcount == %lu, expected 3\n", refcount
);
1286 refcount
= IDirectMusicPerformance8_Release(dmp8
);
1287 ok (refcount
== 2, "refcount == %lu, expected 2\n", refcount
);
1288 refcount
= IDirectMusicPerformance_Release(dmp2
);
1289 ok (refcount
== 1, "refcount == %lu, expected 1\n", refcount
);
1290 refcount
= IDirectMusicPerformance_Release(dmp
);
1291 ok (refcount
== 0, "refcount == %lu, expected 0\n", refcount
);
1294 static void test_audiopathconfig(void)
1296 IDirectMusicObject
*dmo
;
1298 CLSID
class = { 0 };
1299 ULARGE_INTEGER size
;
1302 hr
= CoCreateInstance(&CLSID_DirectMusicAudioPathConfig
, NULL
, CLSCTX_INPROC_SERVER
,
1303 &IID_IDirectMusicObject
, (void**)&dmo
);
1304 if (hr
== REGDB_E_CLASSNOTREG
) {
1305 win_skip("DirectMusicAudioPathConfig not registered\n");
1308 ok(hr
== S_OK
, "DirectMusicAudioPathConfig create failed: %#lx, expected S_OK\n", hr
);
1310 /* IPersistStream */
1311 hr
= IDirectMusicObject_QueryInterface(dmo
, &IID_IPersistStream
, (void**)&ps
);
1312 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1313 hr
= IPersistStream_GetClassID(ps
, &class);
1314 ok(hr
== S_OK
, "IPersistStream_GetClassID failed: %#lx\n", hr
);
1315 ok(IsEqualGUID(&class, &CLSID_DirectMusicAudioPathConfig
),
1316 "Expected class CLSID_DirectMusicAudioPathConfig got %s\n", wine_dbgstr_guid(&class));
1318 /* Unimplemented IPersistStream methods */
1319 hr
= IPersistStream_IsDirty(ps
);
1320 ok(hr
== S_FALSE
, "IPersistStream_IsDirty failed: %#lx\n", hr
);
1321 hr
= IPersistStream_GetSizeMax(ps
, &size
);
1322 ok(hr
== E_NOTIMPL
, "IPersistStream_GetSizeMax failed: %#lx\n", hr
);
1323 hr
= IPersistStream_Save(ps
, NULL
, TRUE
);
1324 ok(hr
== E_NOTIMPL
, "IPersistStream_Save failed: %#lx\n", hr
);
1326 while (IDirectMusicObject_Release(dmo
));
1329 static void test_graph(void)
1331 IDirectMusicTool
*tool1
, *tool2
, *tmp_tool
;
1332 IDirectMusicGraph
*graph
, *tmp_graph
;
1334 CLSID
class = { 0 };
1335 ULARGE_INTEGER size
;
1339 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1340 &IID_IDirectMusicGraph
, (void**)&graph
);
1341 ok(hr
== S_OK
, "DirectMusicGraph create failed: %#lx, expected S_OK\n", hr
);
1343 /* IPersistStream */
1344 hr
= IDirectMusicGraph_QueryInterface(graph
, &IID_IPersistStream
, (void**)&ps
);
1345 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1346 hr
= IPersistStream_GetClassID(ps
, &class);
1347 ok(hr
== S_OK
|| broken(hr
== E_NOTIMPL
) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr
);
1349 ok(IsEqualGUID(&class, &CLSID_DirectMusicGraph
),
1350 "Expected class CLSID_DirectMusicGraph got %s\n", wine_dbgstr_guid(&class));
1352 /* Unimplemented IPersistStream methods */
1353 hr
= IPersistStream_IsDirty(ps
);
1354 ok(hr
== S_FALSE
, "IPersistStream_IsDirty failed: %#lx\n", hr
);
1355 hr
= IPersistStream_GetSizeMax(ps
, &size
);
1356 ok(hr
== E_NOTIMPL
, "IPersistStream_GetSizeMax failed: %#lx\n", hr
);
1357 hr
= IPersistStream_Save(ps
, NULL
, TRUE
);
1358 ok(hr
== E_NOTIMPL
, "IPersistStream_Save failed: %#lx\n", hr
);
1360 IDirectMusicGraph_Release(graph
);
1363 hr
= test_tool_create(NULL
, 0, &tool1
);
1364 ok(hr
== S_OK
, "got %#lx\n", hr
);
1365 trace("created tool1 %p\n", tool1
);
1366 hr
= test_tool_create(NULL
, 0, &tool2
);
1367 ok(hr
== S_OK
, "got %#lx\n", hr
);
1368 trace("created tool2 %p\n", tool2
);
1370 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1371 &IID_IDirectMusicGraph
, (void **)&graph
);
1372 ok(hr
== S_OK
, "got %#lx\n", hr
);
1375 hr
= IDirectMusicGraph_InsertTool(graph
, NULL
, NULL
, 0, -1);
1376 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
1378 /* InsertTool initializes the tool */
1379 hr
= IDirectMusicGraph_InsertTool(graph
, tool1
, NULL
, 0, -1);
1380 ok(hr
== S_OK
, "got %#lx\n", hr
);
1381 hr
= test_tool_get_graph(tool1
, &tmp_graph
);
1382 ok(hr
== S_OK
, "got %#lx\n", hr
);
1383 ok(graph
== tmp_graph
, "got %#lx\n", hr
);
1384 IDirectMusicGraph_Release(tmp_graph
);
1386 hr
= IDirectMusicGraph_InsertTool(graph
, tool2
, NULL
, 0, 1);
1387 ok(hr
== S_OK
, "got %#lx\n", hr
);
1389 hr
= IDirectMusicGraph_GetTool(graph
, 0, NULL
);
1390 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
1391 hr
= IDirectMusicGraph_GetTool(graph
, 0, &tmp_tool
);
1392 ok(hr
== S_OK
, "got %#lx\n", hr
);
1393 ok(tool1
== tmp_tool
, "got %p\n", tmp_tool
);
1394 if (hr
== S_OK
) IDirectMusicTool_Release(tmp_tool
);
1395 hr
= IDirectMusicGraph_GetTool(graph
, 1, &tmp_tool
);
1396 ok(hr
== S_OK
, "got %#lx\n", hr
);
1397 ok(tool2
== tmp_tool
, "got %p\n", tmp_tool
);
1398 if (hr
== S_OK
) IDirectMusicTool_Release(tmp_tool
);
1399 hr
= IDirectMusicGraph_GetTool(graph
, 2, &tmp_tool
);
1400 ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
1402 /* cannot insert the tool twice */
1403 hr
= IDirectMusicGraph_InsertTool(graph
, tool1
, NULL
, 0, -1);
1404 ok(hr
== DMUS_E_ALREADY_EXISTS
, "got %#lx\n", hr
);
1406 /* test removing the first tool */
1407 hr
= IDirectMusicGraph_RemoveTool(graph
, NULL
);
1408 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
1409 hr
= IDirectMusicGraph_RemoveTool(graph
, tool1
);
1410 ok(hr
== S_OK
, "got %#lx\n", hr
);
1411 hr
= IDirectMusicGraph_RemoveTool(graph
, tool1
);
1412 ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
1414 hr
= IDirectMusicGraph_GetTool(graph
, 0, &tmp_tool
);
1415 ok(hr
== S_OK
, "got %#lx\n", hr
);
1416 ok(tool2
== tmp_tool
, "got %p\n", tmp_tool
);
1417 if (hr
== S_OK
) IDirectMusicTool_Release(tmp_tool
);
1418 hr
= IDirectMusicGraph_GetTool(graph
, 1, &tmp_tool
);
1419 ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
1421 hr
= IDirectMusicGraph_InsertTool(graph
, tool1
, NULL
, 0, -1);
1422 ok(hr
== S_OK
, "got %#lx\n", hr
);
1423 hr
= IDirectMusicGraph_GetTool(graph
, 0, &tmp_tool
);
1424 ok(hr
== S_OK
, "got %#lx\n", hr
);
1425 ok(tool1
== tmp_tool
, "got %p\n", tmp_tool
);
1426 if (hr
== S_OK
) IDirectMusicTool_Release(tmp_tool
);
1429 /* Test basic IDirectMusicGraph_StampPMsg usage */
1430 hr
= IDirectMusicGraph_StampPMsg(graph
, NULL
);
1431 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
1432 memset(&msg
, 0, sizeof(msg
));
1433 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
1434 ok(hr
== S_OK
, "got %#lx\n", hr
);
1435 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
1436 ok(msg
.pTool
== tool1
, "got %p\n", msg
.pTool
);
1438 ok(!msg
.dwSize
, "got %ld\n", msg
.dwSize
);
1439 ok(!msg
.rtTime
, "got %I64d\n", msg
.rtTime
);
1440 ok(!msg
.mtTime
, "got %ld\n", msg
.mtTime
);
1441 ok(msg
.dwFlags
== DMUS_PMSGF_TOOL_IMMEDIATE
, "got %#lx\n", msg
.dwFlags
);
1442 ok(!msg
.dwPChannel
, "got %ld\n", msg
.dwPChannel
);
1443 ok(!msg
.dwVirtualTrackID
, "got %ld\n", msg
.dwVirtualTrackID
);
1444 ok(!msg
.dwType
, "got %#lx\n", msg
.dwType
);
1445 ok(!msg
.dwVoiceID
, "got %ld\n", msg
.dwVoiceID
);
1446 ok(!msg
.dwGroupID
, "got %ld\n", msg
.dwGroupID
);
1447 ok(!msg
.punkUser
, "got %p\n", msg
.punkUser
);
1449 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
1450 ok(hr
== S_OK
, "got %#lx\n", hr
);
1451 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
1452 ok(msg
.pTool
== tool2
, "got %p\n", msg
.pTool
);
1453 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
1454 ok(hr
== DMUS_S_LAST_TOOL
, "got %#lx\n", hr
);
1455 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
1456 ok(!msg
.pTool
, "got %p\n", msg
.pTool
);
1457 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
1458 ok(hr
== S_OK
, "got %#lx\n", hr
);
1459 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
1460 ok(msg
.pTool
== tool1
, "got %p\n", msg
.pTool
);
1461 IDirectMusicGraph_Release(msg
.pGraph
);
1463 IDirectMusicGraph_Release(msg
.pTool
);
1467 /* test StampPMsg with the wrong graph or innexistant tools */
1468 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1469 &IID_IDirectMusicGraph
, (void **)&tmp_graph
);
1470 ok(hr
== S_OK
, "got %#lx\n", hr
);
1472 msg
.pGraph
= tmp_graph
;
1473 IDirectMusicGraph_AddRef(msg
.pGraph
);
1475 IDirectMusicTool_AddRef(msg
.pTool
);
1476 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
1477 ok(hr
== S_OK
, "got %#lx\n", hr
);
1478 ok(msg
.pGraph
== tmp_graph
, "got %p\n", msg
.pGraph
);
1479 ok(msg
.pTool
== tool2
, "got %p\n", msg
.pTool
);
1480 IDirectMusicGraph_Release(msg
.pGraph
);
1484 IDirectMusicGraph_AddRef(msg
.pGraph
);
1485 hr
= IDirectMusicGraph_StampPMsg(tmp_graph
, &msg
);
1486 ok(hr
== DMUS_S_LAST_TOOL
, "got %#lx\n", hr
);
1487 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
1488 ok(msg
.pTool
== NULL
, "got %p\n", msg
.pTool
);
1491 IDirectMusicTool_AddRef(msg
.pTool
);
1492 hr
= IDirectMusicGraph_InsertTool(tmp_graph
, tool1
, NULL
, 0, 0);
1493 ok(hr
== S_OK
, "got %#lx\n", hr
);
1494 hr
= IDirectMusicGraph_InsertTool(tmp_graph
, tool2
, NULL
, 0, 0);
1495 ok(hr
== S_OK
, "got %#lx\n", hr
);
1496 hr
= IDirectMusicGraph_StampPMsg(tmp_graph
, &msg
);
1497 ok(hr
== S_OK
, "got %#lx\n", hr
);
1498 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
1499 ok(msg
.pTool
== tool1
, "got %p\n", msg
.pTool
);
1500 IDirectMusicGraph_Release(msg
.pGraph
);
1503 hr
= IDirectMusicGraph_RemoveTool(graph
, tool1
);
1504 ok(hr
== S_OK
, "got %#lx\n", hr
);
1505 hr
= IDirectMusicGraph_StampPMsg(tmp_graph
, &msg
);
1506 ok(hr
== DMUS_S_LAST_TOOL
, "got %#lx\n", hr
);
1507 ok(msg
.pGraph
== NULL
, "got %p\n", msg
.pGraph
);
1508 ok(msg
.pTool
== NULL
, "got %p\n", msg
.pTool
);
1510 IDirectMusicGraph_Release(tmp_graph
);
1513 IDirectMusicGraph_Release(graph
);
1514 IDirectMusicTool_Release(tool2
);
1515 IDirectMusicTool_Release(tool1
);
1518 static void test_segment(void)
1520 IDirectMusicSegment
*dms
;
1522 CLSID
class = { 0 };
1523 ULARGE_INTEGER size
;
1526 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
1527 &IID_IDirectMusicSegment
, (void**)&dms
);
1528 ok(hr
== S_OK
, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr
);
1530 /* IPersistStream */
1531 hr
= IDirectMusicSegment_QueryInterface(dms
, &IID_IPersistStream
, (void**)&ps
);
1532 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1533 hr
= IPersistStream_GetClassID(ps
, &class);
1534 ok(hr
== S_OK
|| broken(hr
== E_NOTIMPL
) /* win2k */, "IPersistStream_GetClassID failed: %#lx\n", hr
);
1536 ok(IsEqualGUID(&class, &CLSID_DirectMusicSegment
),
1537 "Expected class CLSID_DirectMusicSegment got %s\n", wine_dbgstr_guid(&class));
1539 /* Unimplemented IPersistStream methods */
1540 hr
= IPersistStream_IsDirty(ps
);
1541 ok(hr
== S_FALSE
, "IPersistStream_IsDirty failed: %#lx\n", hr
);
1542 hr
= IPersistStream_GetSizeMax(ps
, &size
);
1543 ok(hr
== E_NOTIMPL
, "IPersistStream_GetSizeMax failed: %#lx\n", hr
);
1544 hr
= IPersistStream_Save(ps
, NULL
, TRUE
);
1545 ok(hr
== E_NOTIMPL
, "IPersistStream_Save failed: %#lx\n", hr
);
1547 while (IDirectMusicSegment_Release(dms
));
1550 static void _add_track(IDirectMusicSegment8
*seg
, REFCLSID
class, const char *name
, DWORD group
)
1552 IDirectMusicTrack
*track
;
1555 hr
= CoCreateInstance(class, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
,
1557 ok(hr
== S_OK
, "%s create failed: %#lx, expected S_OK\n", name
, hr
);
1558 hr
= IDirectMusicSegment8_InsertTrack(seg
, track
, group
);
1560 ok(hr
== S_OK
, "Inserting %s failed: %#lx, expected S_OK\n", name
, hr
);
1562 ok(hr
== E_INVALIDARG
, "Inserting %s failed: %#lx, expected E_INVALIDARG\n", name
, hr
);
1563 IDirectMusicTrack_Release(track
);
1566 #define add_track(seg, class, group) _add_track(seg, &CLSID_DirectMusic ## class, #class, group)
1568 static void _expect_track(IDirectMusicSegment8
*seg
, REFCLSID expect
, const char *name
, DWORD group
,
1569 DWORD index
, BOOL ignore_guid
)
1571 IDirectMusicTrack
*track
;
1577 hr
= IDirectMusicSegment8_GetTrack(seg
, &GUID_NULL
, group
, index
, &track
);
1579 hr
= IDirectMusicSegment8_GetTrack(seg
, expect
, group
, index
, &track
);
1581 ok(hr
== DMUS_E_NOT_FOUND
, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr
);
1585 ok(hr
== S_OK
, "GetTrack failed: %#lx, expected S_OK\n", hr
);
1586 hr
= IDirectMusicTrack_QueryInterface(track
, &IID_IPersistStream
, (void**)&ps
);
1587 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1588 hr
= IPersistStream_GetClassID(ps
, &class);
1589 ok(hr
== S_OK
, "IPersistStream_GetClassID failed: %#lx\n", hr
);
1590 ok(IsEqualGUID(&class, expect
), "For group %#lx index %lu: Expected class %s got %s\n",
1591 group
, index
, name
, wine_dbgstr_guid(&class));
1593 IPersistStream_Release(ps
);
1594 IDirectMusicTrack_Release(track
);
1597 #define expect_track(seg, class, group, index) \
1598 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, TRUE)
1599 #define expect_guid_track(seg, class, group, index) \
1600 _expect_track(seg, &CLSID_DirectMusic ## class, #class, group, index, FALSE)
1602 static void test_gettrack(void)
1604 IDirectMusicSegment8
*seg
;
1605 IDirectMusicTrack
*track
;
1608 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
1609 &IID_IDirectMusicSegment8
, (void**)&seg
);
1610 ok(hr
== S_OK
, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr
);
1612 add_track(seg
, LyricsTrack
, 0x0); /* failure */
1613 add_track(seg
, LyricsTrack
, 0x1); /* idx 0 group 1 */
1614 add_track(seg
, ParamControlTrack
, 0x3); /* idx 1 group 1, idx 0 group 2 */
1615 add_track(seg
, SegmentTriggerTrack
, 0x2); /* idx 1 group 2 */
1616 add_track(seg
, SeqTrack
, 0x1); /* idx 2 group 1 */
1617 add_track(seg
, TempoTrack
, 0x7); /* idx 3 group 1, idx 2 group 2, idx 0 group 3 */
1618 add_track(seg
, WaveTrack
, 0xffffffff); /* idx 4 group 1, idx 3 group 2, idx 1 group 3 */
1620 /* Ignore GUID in GetTrack */
1621 hr
= IDirectMusicSegment8_GetTrack(seg
, &GUID_NULL
, 0, 0, &track
);
1622 ok(hr
== DMUS_E_NOT_FOUND
, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr
);
1624 expect_track(seg
, LyricsTrack
, 0x1, 0);
1625 expect_track(seg
, ParamControlTrack
, 0x1, 1);
1626 expect_track(seg
, SeqTrack
, 0x1, 2);
1627 expect_track(seg
, TempoTrack
, 0x1, 3);
1628 expect_track(seg
, WaveTrack
, 0x1, 4);
1629 _expect_track(seg
, NULL
, "", 0x1, 5, TRUE
);
1630 _expect_track(seg
, NULL
, "", 0x1, DMUS_SEG_ANYTRACK
, TRUE
);
1631 expect_track(seg
, ParamControlTrack
, 0x2, 0);
1632 expect_track(seg
, WaveTrack
, 0x80000000, 0);
1633 expect_track(seg
, SegmentTriggerTrack
, 0x3, 2); /* groups 1+2 combined index */
1634 expect_track(seg
, SeqTrack
, 0x3, 3); /* groups 1+2 combined index */
1635 expect_track(seg
, TempoTrack
, 0x7, 4); /* groups 1+2+3 combined index */
1636 expect_track(seg
, TempoTrack
, 0xffffffff, 4); /* all groups combined index */
1637 _expect_track(seg
, NULL
, "", 0xffffffff, DMUS_SEG_ANYTRACK
, TRUE
);
1639 /* Use the GUID in GetTrack */
1640 hr
= IDirectMusicSegment8_GetTrack(seg
, &CLSID_DirectMusicLyricsTrack
, 0, 0, &track
);
1641 ok(hr
== DMUS_E_NOT_FOUND
, "GetTrack failed: %#lx, expected DMUS_E_NOT_FOUND\n", hr
);
1643 expect_guid_track(seg
, LyricsTrack
, 0x1, 0);
1644 expect_guid_track(seg
, ParamControlTrack
, 0x1, 0);
1645 expect_guid_track(seg
, SeqTrack
, 0x1, 0);
1646 expect_guid_track(seg
, TempoTrack
, 0x1, 0);
1647 expect_guid_track(seg
, ParamControlTrack
, 0x2, 0);
1648 expect_guid_track(seg
, SegmentTriggerTrack
, 0x3, 0);
1649 expect_guid_track(seg
, SeqTrack
, 0x3, 0);
1650 expect_guid_track(seg
, TempoTrack
, 0x7, 0);
1651 expect_guid_track(seg
, TempoTrack
, 0xffffffff, 0);
1653 IDirectMusicSegment8_Release(seg
);
1656 static void test_segment_param(void)
1658 IDirectMusicSegment8
*seg
;
1662 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
1663 &IID_IDirectMusicSegment8
, (void **)&seg
);
1664 ok(hr
== S_OK
, "DirectMusicSegment create failed: %#lx, expected S_OK\n", hr
);
1666 add_track(seg
, LyricsTrack
, 0x1); /* no params */
1667 add_track(seg
, SegmentTriggerTrack
, 0x1); /* all params "supported" */
1669 hr
= IDirectMusicSegment8_GetParam(seg
, NULL
, 0x1, 0, 0, NULL
, buf
);
1670 ok(hr
== E_POINTER
, "GetParam failed: %#lx, expected E_POINTER\n", hr
);
1671 hr
= IDirectMusicSegment8_SetParam(seg
, NULL
, 0x1, 0, 0, buf
);
1672 todo_wine
ok(hr
== E_POINTER
, "SetParam failed: %#lx, expected E_POINTER\n", hr
);
1674 hr
= IDirectMusicSegment8_GetParam(seg
, &GUID_Valid_Start_Time
, 0x1, 0, 0, NULL
, buf
);
1675 ok(hr
== DMUS_E_GET_UNSUPPORTED
, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr
);
1676 hr
= IDirectMusicSegment8_GetParam(seg
, &GUID_Valid_Start_Time
, 0x1, 1, 0, NULL
, buf
);
1677 ok(hr
== DMUS_E_TRACK_NOT_FOUND
, "GetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr
);
1678 hr
= IDirectMusicSegment8_GetParam(seg
, &GUID_Valid_Start_Time
, 0x1, DMUS_SEG_ANYTRACK
, 0,
1680 ok(hr
== DMUS_E_GET_UNSUPPORTED
, "GetParam failed: %#lx, expected DMUS_E_GET_UNSUPPORTED\n", hr
);
1682 hr
= IDirectMusicSegment8_SetParam(seg
, &GUID_Valid_Start_Time
, 0x1, 0, 0, buf
);
1683 ok(hr
== S_OK
, "SetParam failed: %#lx, expected S_OK\n", hr
);
1684 hr
= IDirectMusicSegment8_SetParam(seg
, &GUID_Valid_Start_Time
, 0x1, 1, 0, buf
);
1685 todo_wine
ok(hr
== DMUS_E_TRACK_NOT_FOUND
,
1686 "SetParam failed: %#lx, expected DMUS_E_TRACK_NOT_FOUND\n", hr
);
1687 hr
= IDirectMusicSegment8_SetParam(seg
, &GUID_Valid_Start_Time
, 0x1, DMUS_SEG_ALLTRACKS
,
1689 ok(hr
== S_OK
, "SetParam failed: %#lx, expected S_OK\n", hr
);
1691 IDirectMusicSegment8_Release(seg
);
1694 static void expect_getparam(IDirectMusicTrack
*track
, REFGUID type
, const char *name
,
1698 char buf
[64] = { 0 };
1700 hr
= IDirectMusicTrack_GetParam(track
, type
, 0, NULL
, buf
);
1701 ok(hr
== expect
, "GetParam(%s) failed: %#lx, expected %#lx\n", name
, hr
, expect
);
1704 static void expect_setparam(IDirectMusicTrack
*track
, REFGUID type
, const char *name
,
1708 char buf
[64] = { 0 };
1710 hr
= IDirectMusicTrack_SetParam(track
, type
, 0, buf
);
1711 ok(hr
== expect
, "SetParam(%s) failed: %#lx, expected %#lx\n", name
, hr
, expect
);
1714 static void test_track(void)
1716 IDirectMusicTrack
*dmt
;
1717 IDirectMusicTrack8
*dmt8
;
1720 ULARGE_INTEGER size
;
1722 #define X(guid) &guid, #guid
1727 { X(GUID_BandParam
) },
1728 { X(GUID_ChordParam
) },
1729 { X(GUID_Clear_All_Bands
) },
1730 { X(GUID_CommandParam
) },
1731 { X(GUID_CommandParam2
) },
1732 { X(GUID_CommandParamNext
) },
1733 { X(GUID_ConnectToDLSCollection
) },
1734 { X(GUID_Disable_Auto_Download
) },
1735 { X(GUID_DisableTempo
) },
1736 { X(GUID_DisableTimeSig
) },
1737 { X(GUID_Download
) },
1738 { X(GUID_DownloadToAudioPath
) },
1739 { X(GUID_Enable_Auto_Download
) },
1740 { X(GUID_EnableTempo
) },
1741 { X(GUID_EnableTimeSig
) },
1742 { X(GUID_IDirectMusicBand
) },
1743 { X(GUID_IDirectMusicChordMap
) },
1744 { X(GUID_IDirectMusicStyle
) },
1745 { X(GUID_MuteParam
) },
1746 { X(GUID_Play_Marker
) },
1747 { X(GUID_RhythmParam
) },
1748 { X(GUID_SeedVariations
) },
1749 { X(GUID_StandardMIDIFile
) },
1750 { X(GUID_TempoParam
) },
1751 { X(GUID_TimeSignature
) },
1753 { X(GUID_UnloadFromAudioPath
) },
1754 { X(GUID_Valid_Start_Time
) },
1755 { X(GUID_Variations
) },
1759 #define X(class) &CLSID_ ## class, #class
1763 /* bitfield with supported param types */
1764 unsigned int has_params
;
1766 { X(DirectMusicLyricsTrack
), 0 },
1767 { X(DirectMusicMarkerTrack
), 0x8080000 },
1768 { X(DirectMusicParamControlTrack
), 0 },
1769 { X(DirectMusicSegmentTriggerTrack
), 0x3fffffff },
1770 { X(DirectMusicSeqTrack
), ~0 }, /* param methods not implemented */
1771 { X(DirectMusicSysExTrack
), ~0 }, /* param methods not implemented */
1772 { X(DirectMusicTempoTrack
), 0x802100 },
1773 { X(DirectMusicTimeSigTrack
), 0x1004200 },
1774 { X(DirectMusicWaveTrack
), 0x6001c80 }
1779 for (i
= 0; i
< ARRAY_SIZE(class); i
++) {
1780 trace("Testing %s\n", class[i
].name
);
1781 hr
= CoCreateInstance(class[i
].clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
,
1783 ok(hr
== S_OK
, "%s create failed: %#lx, expected S_OK\n", class[i
].name
, hr
);
1785 /* IDirectMusicTrack */
1786 if (class[i
].has_params
!= ~0) {
1787 for (j
= 0; j
< ARRAY_SIZE(param_types
); j
++) {
1788 hr
= IDirectMusicTrack_IsParamSupported(dmt
, param_types
[j
].type
);
1789 if (class[i
].has_params
& (1 << j
)) {
1790 ok(hr
== S_OK
, "IsParamSupported(%s) failed: %#lx, expected S_OK\n",
1791 param_types
[j
].name
, hr
);
1792 if (class[i
].clsid
== &CLSID_DirectMusicSegmentTriggerTrack
) {
1793 expect_getparam(dmt
, param_types
[j
].type
, param_types
[j
].name
,
1794 DMUS_E_GET_UNSUPPORTED
);
1795 expect_setparam(dmt
, param_types
[j
].type
, param_types
[j
].name
, S_OK
);
1796 } else if (class[i
].clsid
== &CLSID_DirectMusicMarkerTrack
)
1797 expect_setparam(dmt
, param_types
[j
].type
, param_types
[j
].name
,
1798 DMUS_E_SET_UNSUPPORTED
);
1799 else if (class[i
].clsid
== &CLSID_DirectMusicWaveTrack
)
1800 expect_getparam(dmt
, param_types
[j
].type
, param_types
[j
].name
,
1801 DMUS_E_GET_UNSUPPORTED
);
1803 ok(hr
== DMUS_E_TYPE_UNSUPPORTED
,
1804 "IsParamSupported(%s) failed: %#lx, expected DMUS_E_TYPE_UNSUPPORTED\n",
1805 param_types
[j
].name
, hr
);
1806 expect_getparam(dmt
, param_types
[j
].type
, param_types
[j
].name
,
1807 DMUS_E_GET_UNSUPPORTED
);
1808 if (class[i
].clsid
== &CLSID_DirectMusicWaveTrack
)
1809 expect_setparam(dmt
, param_types
[j
].type
, param_types
[j
].name
,
1810 DMUS_E_TYPE_UNSUPPORTED
);
1812 expect_setparam(dmt
, param_types
[j
].type
, param_types
[j
].name
,
1813 DMUS_E_SET_UNSUPPORTED
);
1816 /* GetParam / SetParam for IsParamSupported supported types */
1817 if (class[i
].clsid
== &CLSID_DirectMusicTimeSigTrack
) {
1818 expect_getparam(dmt
, &GUID_DisableTimeSig
, "GUID_DisableTimeSig",
1819 DMUS_E_GET_UNSUPPORTED
);
1820 expect_getparam(dmt
, &GUID_EnableTimeSig
, "GUID_EnableTimeSig",
1821 DMUS_E_GET_UNSUPPORTED
);
1822 expect_setparam(dmt
, &GUID_TimeSignature
, "GUID_TimeSignature",
1823 DMUS_E_SET_UNSUPPORTED
);
1824 } else if (class[i
].clsid
== &CLSID_DirectMusicTempoTrack
) {
1825 expect_getparam(dmt
, &GUID_DisableTempo
, "GUID_DisableTempo",
1826 DMUS_E_GET_UNSUPPORTED
);
1827 expect_getparam(dmt
, &GUID_EnableTempo
, "GUID_EnableTempo",
1828 DMUS_E_GET_UNSUPPORTED
);
1832 hr
= IDirectMusicTrack_GetParam(dmt
, NULL
, 0, NULL
, NULL
);
1833 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack_GetParam failed: %#lx\n", hr
);
1834 hr
= IDirectMusicTrack_SetParam(dmt
, NULL
, 0, NULL
);
1835 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack_SetParam failed: %#lx\n", hr
);
1836 hr
= IDirectMusicTrack_IsParamSupported(dmt
, NULL
);
1837 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack_IsParamSupported failed: %#lx\n", hr
);
1839 hr
= IDirectMusicTrack_IsParamSupported(dmt
, &GUID_IDirectMusicStyle
);
1840 ok(hr
== E_NOTIMPL
, "got: %#lx\n", hr
);
1842 if (class[i
].clsid
!= &CLSID_DirectMusicMarkerTrack
&&
1843 class[i
].clsid
!= &CLSID_DirectMusicTimeSigTrack
) {
1844 hr
= IDirectMusicTrack_AddNotificationType(dmt
, NULL
);
1845 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack_AddNotificationType failed: %#lx\n", hr
);
1846 hr
= IDirectMusicTrack_RemoveNotificationType(dmt
, NULL
);
1847 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack_RemoveNotificationType failed: %#lx\n", hr
);
1849 hr
= IDirectMusicTrack_Clone(dmt
, 0, 0, NULL
);
1850 todo_wine
ok(hr
== E_POINTER
, "IDirectMusicTrack_Clone failed: %#lx\n", hr
);
1852 /* IDirectMusicTrack8 */
1853 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IDirectMusicTrack8
, (void**)&dmt8
);
1855 hr
= IDirectMusicTrack8_PlayEx(dmt8
, NULL
, 0, 0, 0, 0, NULL
, NULL
, 0);
1856 todo_wine
ok(hr
== E_POINTER
, "IDirectMusicTrack8_PlayEx failed: %#lx\n", hr
);
1857 if (class[i
].has_params
== ~0) {
1858 hr
= IDirectMusicTrack8_GetParamEx(dmt8
, NULL
, 0, NULL
, NULL
, NULL
, 0);
1859 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_GetParamEx failed: %#lx\n", hr
);
1860 hr
= IDirectMusicTrack8_SetParamEx(dmt8
, NULL
, 0, NULL
, NULL
, 0);
1861 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_SetParamEx failed: %#lx\n", hr
);
1863 hr
= IDirectMusicTrack8_Compose(dmt8
, NULL
, 0, NULL
);
1864 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_Compose failed: %#lx\n", hr
);
1865 hr
= IDirectMusicTrack8_Join(dmt8
, NULL
, 0, NULL
, 0, NULL
);
1866 if (class[i
].clsid
== &CLSID_DirectMusicTempoTrack
)
1867 todo_wine
ok(hr
== E_POINTER
, "IDirectMusicTrack8_Join failed: %#lx\n", hr
);
1869 ok(hr
== E_NOTIMPL
, "IDirectMusicTrack8_Join failed: %#lx\n", hr
);
1870 IDirectMusicTrack8_Release(dmt8
);
1873 /* IPersistStream */
1874 hr
= IDirectMusicTrack_QueryInterface(dmt
, &IID_IPersistStream
, (void**)&ps
);
1875 ok(hr
== S_OK
, "QueryInterface for IID_IPersistStream failed: %#lx\n", hr
);
1876 hr
= IPersistStream_GetClassID(ps
, &classid
);
1877 ok(hr
== S_OK
, "IPersistStream_GetClassID failed: %#lx\n", hr
);
1878 ok(IsEqualGUID(&classid
, class[i
].clsid
),
1879 "Expected class %s got %s\n", class[i
].name
, wine_dbgstr_guid(&classid
));
1880 hr
= IPersistStream_IsDirty(ps
);
1881 ok(hr
== S_FALSE
, "IPersistStream_IsDirty failed: %#lx\n", hr
);
1883 /* Unimplemented IPersistStream methods */
1884 hr
= IPersistStream_GetSizeMax(ps
, &size
);
1885 ok(hr
== E_NOTIMPL
, "IPersistStream_GetSizeMax failed: %#lx\n", hr
);
1886 hr
= IPersistStream_Save(ps
, NULL
, TRUE
);
1887 ok(hr
== E_NOTIMPL
, "IPersistStream_Save failed: %#lx\n", hr
);
1889 while (IDirectMusicTrack_Release(dmt
));
1899 #define CHUNK_HDR_SIZE (sizeof(FOURCC) + sizeof(DWORD))
1901 /* Generate a RIFF file format stream from an array of FOURCC ids.
1902 RIFF and LIST need to be followed by the form type respectively list type,
1903 followed by the chunks of the list and terminated with 0. */
1904 static IStream
*gen_riff_stream(const FOURCC
*ids
)
1906 static const LARGE_INTEGER zero
;
1908 DWORD
*sizes
[4]; /* Stack for the sizes of RIFF and LIST chunks */
1915 ck
= (struct chunk
*)p
;
1919 *sizes
[level
] = p
- (char *)sizes
[level
] - sizeof(DWORD
);
1925 sizes
[level
] = &ck
->size
;
1929 case DMUS_FOURCC_GUID_CHUNK
:
1930 ck
->size
= sizeof(GUID_NULL
);
1931 p
+= CHUNK_HDR_SIZE
;
1932 memcpy(p
, &GUID_NULL
, sizeof(GUID_NULL
));
1935 case DMUS_FOURCC_VERSION_CHUNK
:
1937 DMUS_VERSION ver
= {5, 8};
1939 ck
->size
= sizeof(ver
);
1940 p
+= CHUNK_HDR_SIZE
;
1941 memcpy(p
, &ver
, sizeof(ver
));
1947 /* Just convert the FOURCC id to a WCHAR string */
1950 ck
->size
= 5 * sizeof(WCHAR
);
1951 p
+= CHUNK_HDR_SIZE
;
1953 s
[0] = (char)(ck
->id
);
1954 s
[1] = (char)(ck
->id
>> 8);
1955 s
[2] = (char)(ck
->id
>> 16);
1956 s
[3] = (char)(ck
->id
>> 24);
1961 } while (level
>= 0);
1963 ck
= (struct chunk
*)riff
;
1964 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1965 IStream_Write(stream
, riff
, ck
->size
+ CHUNK_HDR_SIZE
, NULL
);
1966 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
1971 static void test_parsedescriptor(void)
1973 IDirectMusicObject
*dmo
;
1975 DMUS_OBJECTDESC desc
;
1979 /* fourcc ~0 will be replaced later on */
1982 FOURCC_RIFF
, ~0, DMUS_FOURCC_CATEGORY_CHUNK
, FOURCC_LIST
, DMUS_FOURCC_UNFO_LIST
,
1983 DMUS_FOURCC_UNAM_CHUNK
, DMUS_FOURCC_UCOP_CHUNK
, DMUS_FOURCC_UCMT_CHUNK
,
1984 DMUS_FOURCC_USBJ_CHUNK
, 0, DMUS_FOURCC_VERSION_CHUNK
, DMUS_FOURCC_GUID_CHUNK
, 0
1988 FOURCC_RIFF
, ~0, DMUS_FOURCC_CATEGORY_CHUNK
, DMUS_FOURCC_CATEGORY_CHUNK
,
1989 DMUS_FOURCC_VERSION_CHUNK
, DMUS_FOURCC_VERSION_CHUNK
, DMUS_FOURCC_GUID_CHUNK
,
1990 DMUS_FOURCC_GUID_CHUNK
, FOURCC_LIST
, DMUS_FOURCC_UNFO_LIST
, DMUS_FOURCC_UNAM_CHUNK
, 0,
1991 FOURCC_LIST
, DMUS_FOURCC_UNFO_LIST
, mmioFOURCC('I','N','A','M'), 0, 0
1993 FOURCC empty
[] = {FOURCC_RIFF
, ~0, 0};
1994 FOURCC inam
[] = {FOURCC_RIFF
, ~0, FOURCC_LIST
, ~0, mmioFOURCC('I','N','A','M'), 0, 0};
1995 FOURCC noriff
[] = {mmioFOURCC('J','U','N','K'), 0};
1996 #define X(class) &CLSID_ ## class, #class
1997 #define Y(form) form, #form
2005 { X(DirectMusicSegment
), Y(DMUS_FOURCC_SEGMENT_FORM
), FALSE
},
2006 { X(DirectMusicSegment
), Y(mmioFOURCC('W','A','V','E')), FALSE
},
2007 { X(DirectMusicAudioPathConfig
), Y(DMUS_FOURCC_AUDIOPATH_FORM
), TRUE
},
2008 { X(DirectMusicGraph
), Y(DMUS_FOURCC_TOOLGRAPH_FORM
), TRUE
},
2013 for (i
= 0; i
< ARRAY_SIZE(forms
); i
++) {
2014 trace("Testing %s / %s\n", forms
[i
].class, forms
[i
].name
);
2015 hr
= CoCreateInstance(forms
[i
].clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
,
2018 win_skip("Could not create %s object: %#lx\n", forms
[i
].class, hr
);
2022 /* Nothing loaded */
2023 memset(&desc
, 0, sizeof(desc
));
2024 hr
= IDirectMusicObject_GetDescriptor(dmo
, &desc
);
2025 if (forms
[i
].needs_size
) {
2026 todo_wine
ok(hr
== E_INVALIDARG
, "GetDescriptor failed: %#lx, expected E_INVALIDARG\n", hr
);
2027 desc
.dwSize
= sizeof(desc
);
2028 hr
= IDirectMusicObject_GetDescriptor(dmo
, &desc
);
2030 ok(hr
== S_OK
, "GetDescriptor failed: %#lx, expected S_OK\n", hr
);
2031 ok(desc
.dwValidData
== DMUS_OBJ_CLASS
, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
2033 ok(IsEqualGUID(&desc
.guidClass
, forms
[i
].clsid
), "Got class guid %s, expected CLSID_%s\n",
2034 wine_dbgstr_guid(&desc
.guidClass
), forms
[i
].class);
2036 /* Empty RIFF stream */
2037 empty
[1] = forms
[i
].form
;
2038 stream
= gen_riff_stream(empty
);
2039 memset(&desc
, 0, sizeof(desc
));
2040 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2041 if (forms
[i
].needs_size
) {
2042 ok(hr
== E_INVALIDARG
, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr
);
2043 desc
.dwSize
= sizeof(desc
);
2044 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2046 ok(hr
== S_OK
, "ParseDescriptor failed: %#lx, expected S_OK\n", hr
);
2047 ok(desc
.dwValidData
== DMUS_OBJ_CLASS
, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
2049 ok(IsEqualGUID(&desc
.guidClass
, forms
[i
].clsid
), "Got class guid %s, expected CLSID_%s\n",
2050 wine_dbgstr_guid(&desc
.guidClass
), forms
[i
].class);
2053 memset(&desc
, 0, sizeof(desc
));
2054 desc
.dwSize
= sizeof(desc
);
2055 hr
= IDirectMusicObject_ParseDescriptor(dmo
, NULL
, &desc
);
2056 ok(hr
== E_POINTER
, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr
);
2057 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, NULL
);
2058 if (forms
[i
].needs_size
)
2059 ok(hr
== E_INVALIDARG
, "ParseDescriptor failed: %#lx, expected E_INVALIDARG\n", hr
);
2061 ok(hr
== E_POINTER
, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr
);
2062 hr
= IDirectMusicObject_ParseDescriptor(dmo
, NULL
, NULL
);
2063 ok(hr
== E_POINTER
, "ParseDescriptor failed: %#lx, expected E_POINTER\n", hr
);
2064 IStream_Release(stream
);
2067 empty
[1] = DMUS_FOURCC_CONTAINER_FORM
;
2068 stream
= gen_riff_stream(empty
);
2069 memset(&desc
, 0, sizeof(desc
));
2070 desc
.dwSize
= sizeof(desc
);
2071 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2072 if (forms
[i
].needs_size
)
2073 ok(hr
== DMUS_E_CHUNKNOTFOUND
,
2074 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr
);
2076 ok(hr
== E_FAIL
, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr
);
2077 ok(!desc
.dwValidData
, "Got valid data %#lx, expected 0\n", desc
.dwValidData
);
2078 IStream_Release(stream
);
2080 /* Not a RIFF stream */
2081 stream
= gen_riff_stream(noriff
);
2082 memset(&desc
, 0, sizeof(desc
));
2083 desc
.dwSize
= sizeof(desc
);
2084 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2085 if (forms
[i
].needs_size
)
2086 ok(hr
== DMUS_E_CHUNKNOTFOUND
,
2087 "ParseDescriptor failed: %#lx, expected DMUS_E_CHUNKNOTFOUND\n", hr
);
2089 ok(hr
== E_FAIL
, "ParseDescriptor failed: %#lx, expected E_FAIL\n", hr
);
2090 ok(!desc
.dwValidData
, "Got valid data %#lx, expected 0\n", desc
.dwValidData
);
2091 IStream_Release(stream
);
2093 /* All desc chunks */
2094 alldesc
[1] = forms
[i
].form
;
2095 stream
= gen_riff_stream(alldesc
);
2096 memset(&desc
, 0, sizeof(desc
));
2097 desc
.dwSize
= sizeof(desc
);
2098 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2099 ok(hr
== S_OK
, "ParseDescriptor failed: %#lx, expected S_OK\n", hr
);
2100 valid
= DMUS_OBJ_OBJECT
| DMUS_OBJ_CLASS
| DMUS_OBJ_VERSION
;
2101 if (forms
[i
].form
!= mmioFOURCC('W','A','V','E'))
2102 valid
|= DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
;
2103 ok(desc
.dwValidData
== valid
, "Got valid data %#lx, expected %#lx\n", desc
.dwValidData
, valid
);
2104 ok(IsEqualGUID(&desc
.guidClass
, forms
[i
].clsid
), "Got class guid %s, expected CLSID_%s\n",
2105 wine_dbgstr_guid(&desc
.guidClass
), forms
[i
].class);
2106 ok(IsEqualGUID(&desc
.guidObject
, &GUID_NULL
), "Got object guid %s, expected GUID_NULL\n",
2107 wine_dbgstr_guid(&desc
.guidClass
));
2108 ok(desc
.vVersion
.dwVersionMS
== 5 && desc
.vVersion
.dwVersionLS
== 8,
2109 "Got version %lu.%lu, expected 5.8\n", desc
.vVersion
.dwVersionMS
,
2110 desc
.vVersion
.dwVersionLS
);
2111 if (forms
[i
].form
!= mmioFOURCC('W','A','V','E'))
2112 ok(!lstrcmpW(desc
.wszName
, L
"UNAM"), "Got name '%s', expected 'UNAM'\n",
2113 wine_dbgstr_w(desc
.wszName
));
2114 IStream_Release(stream
);
2116 /* Duplicated chunks */
2117 dupes
[1] = forms
[i
].form
;
2118 stream
= gen_riff_stream(dupes
);
2119 memset(&desc
, 0, sizeof(desc
));
2120 desc
.dwSize
= sizeof(desc
);
2121 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2122 ok(hr
== S_OK
, "ParseDescriptor failed: %#lx, expected S_OK\n", hr
);
2123 ok(desc
.dwValidData
== valid
, "Got valid data %#lx, expected %#lx\n", desc
.dwValidData
, valid
);
2124 IStream_Release(stream
);
2126 /* UNFO list with INAM */
2127 inam
[1] = forms
[i
].form
;
2128 inam
[3] = DMUS_FOURCC_UNFO_LIST
;
2129 stream
= gen_riff_stream(inam
);
2130 memset(&desc
, 0, sizeof(desc
));
2131 desc
.dwSize
= sizeof(desc
);
2132 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2133 ok(hr
== S_OK
, "ParseDescriptor failed: %#lx, expected S_OK\n", hr
);
2134 ok(desc
.dwValidData
== DMUS_OBJ_CLASS
, "Got valid data %#lx, expected DMUS_OBJ_CLASS\n",
2136 IStream_Release(stream
);
2138 /* INFO list with INAM */
2139 inam
[3] = DMUS_FOURCC_INFO_LIST
;
2140 stream
= gen_riff_stream(inam
);
2141 memset(&desc
, 0, sizeof(desc
));
2142 desc
.dwSize
= sizeof(desc
);
2143 hr
= IDirectMusicObject_ParseDescriptor(dmo
, stream
, &desc
);
2144 ok(hr
== S_OK
, "ParseDescriptor failed: %#lx, expected S_OK\n", hr
);
2145 valid
= DMUS_OBJ_CLASS
;
2146 if (forms
[i
].form
== mmioFOURCC('W','A','V','E'))
2147 valid
|= DMUS_OBJ_NAME
;
2148 ok(desc
.dwValidData
== valid
, "Got valid data %#lx, expected %#lx\n", desc
.dwValidData
, valid
);
2149 if (forms
[i
].form
== mmioFOURCC('W','A','V','E'))
2150 ok(!lstrcmpW(desc
.wszName
, L
"I"), "Got name '%s', expected 'I'\n",
2151 wine_dbgstr_w(desc
.wszName
));
2152 IStream_Release(stream
);
2154 IDirectMusicObject_Release(dmo
);
2158 static void test_performance_InitAudio(void)
2160 DMUS_PORTPARAMS params
=
2162 .dwSize
= sizeof(params
),
2163 .dwValidParams
= DMUS_PORTPARAMS_EFFECTS
,
2166 IDirectMusicPerformance8
*performance
;
2167 IDirectMusic
*dmusic
;
2168 IDirectSound
*dsound
;
2169 IDirectMusicPort
*port
;
2170 IDirectMusicAudioPath
*path
;
2171 DWORD channel
, group
;
2175 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
2176 &IID_IDirectMusicPerformance8
, (void **)&performance
);
2178 win_skip("Cannot create DirectMusicPerformance object (%lx)\n", hr
);
2184 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, &dsound
, NULL
,
2185 DMUS_APATH_SHARED_STEREOPLUSREVERB
, 128, DMUS_AUDIOF_ALL
, NULL
);
2187 IDirectMusicPerformance8_Release(performance
);
2188 win_skip("InitAudio failed (%lx)\n", hr
);
2192 hr
= IDirectMusicPerformance8_PChannelInfo(performance
, 128, &port
, NULL
, NULL
);
2193 ok(hr
== E_INVALIDARG
, "PChannelInfo failed, got %#lx\n", hr
);
2194 hr
= IDirectMusicPerformance8_PChannelInfo(performance
, 127, &port
, NULL
, NULL
);
2195 ok(hr
== S_OK
, "PChannelInfo failed, got %#lx\n", hr
);
2196 IDirectMusicPort_Release(port
);
2198 hr
= IDirectMusicPerformance8_PChannelInfo(performance
, 0, &port
, NULL
, NULL
);
2199 ok(hr
== S_OK
, "PChannelInfo failed, got %#lx\n", hr
);
2200 ok(port
!= NULL
, "IDirectMusicPort not set\n");
2201 hr
= IDirectMusicPerformance8_AssignPChannel(performance
, 0, port
, 0, 0);
2202 ok(hr
== DMUS_E_AUDIOPATHS_IN_USE
, "AssignPChannel failed (%#lx)\n", hr
);
2203 hr
= IDirectMusicPerformance8_AssignPChannelBlock(performance
, 0, port
, 0);
2204 ok(hr
== DMUS_E_AUDIOPATHS_IN_USE
, "AssignPChannelBlock failed (%#lx)\n", hr
);
2205 IDirectMusicPort_Release(port
);
2207 hr
= IDirectMusicPerformance8_GetDefaultAudioPath(performance
, &path
);
2208 ok(hr
== S_OK
, "Failed to call GetDefaultAudioPath (%lx)\n", hr
);
2210 IDirectMusicAudioPath_Release(path
);
2212 hr
= IDirectMusicPerformance8_CloseDown(performance
);
2213 ok(hr
== S_OK
, "Failed to call CloseDown (%lx)\n", hr
);
2215 IDirectMusicPerformance8_Release(performance
);
2217 /* Auto generated dmusic and dsound */
2218 create_performance(&performance
, NULL
, NULL
, FALSE
);
2219 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, NULL
, NULL
, 0, 64, 0, NULL
);
2220 ok(hr
== S_OK
, "InitAudio failed: %#lx\n", hr
);
2221 hr
= IDirectMusicPerformance8_PChannelInfo(performance
, 0, &port
, NULL
, NULL
);
2222 ok(hr
== E_INVALIDARG
, "PChannelInfo failed, got %#lx\n", hr
);
2223 destroy_performance(performance
, NULL
, NULL
);
2225 /* Refcounts for auto generated dmusic and dsound */
2226 create_performance(&performance
, NULL
, NULL
, FALSE
);
2229 hr
= IDirectMusicPerformance8_InitAudio(performance
, &dmusic
, &dsound
, NULL
, 0, 64, 0, NULL
);
2230 ok(hr
== S_OK
, "InitAudio failed: %#lx\n", hr
);
2231 ref
= get_refcount(dsound
);
2232 ok(ref
== 3, "dsound ref count got %ld expected 3\n", ref
);
2233 ref
= get_refcount(dmusic
);
2234 ok(ref
== 2, "dmusic ref count got %ld expected 2\n", ref
);
2235 destroy_performance(performance
, NULL
, NULL
);
2237 /* dsound without SetCooperativeLevel() */
2238 create_performance(&performance
, NULL
, &dsound
, FALSE
);
2239 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, &dsound
, NULL
, 0, 0, 0, NULL
);
2240 todo_wine
ok(hr
== DSERR_PRIOLEVELNEEDED
, "InitAudio failed: %#lx\n", hr
);
2241 destroy_performance(performance
, NULL
, dsound
);
2243 /* Using the wrong CLSID_DirectSound */
2244 create_performance(&performance
, NULL
, NULL
, FALSE
);
2245 hr
= DirectSoundCreate(NULL
, &dsound
, NULL
);
2246 ok(hr
== S_OK
, "DirectSoundCreate failed: %#lx\n", hr
);
2247 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, &dsound
, NULL
, 0, 0, 0, NULL
);
2248 todo_wine
ok(hr
== E_NOINTERFACE
, "InitAudio failed: %#lx\n", hr
);
2249 destroy_performance(performance
, NULL
, dsound
);
2251 /* Init() works with just a CLSID_DirectSound */
2252 create_performance(&performance
, NULL
, NULL
, FALSE
);
2253 hr
= DirectSoundCreate(NULL
, &dsound
, NULL
);
2254 ok(hr
== S_OK
, "DirectSoundCreate failed: %#lx\n", hr
);
2255 hr
= IDirectSound_SetCooperativeLevel(dsound
, GetForegroundWindow(), DSSCL_PRIORITY
);
2256 ok(hr
== S_OK
, "SetCooperativeLevel failed: %#lx\n", hr
);
2257 hr
= IDirectMusicPerformance8_Init(performance
, NULL
, dsound
, NULL
);
2258 ok(hr
== S_OK
, "Init failed: %#lx\n", hr
);
2259 destroy_performance(performance
, NULL
, dsound
);
2261 /* Init() followed by InitAudio() */
2262 create_performance(&performance
, NULL
, &dsound
, TRUE
);
2263 hr
= IDirectMusicPerformance8_Init(performance
, NULL
, dsound
, NULL
);
2264 ok(hr
== S_OK
, "Init failed: %#lx\n", hr
);
2265 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, &dsound
, NULL
, 0, 0, 0, NULL
);
2266 ok(hr
== DMUS_E_ALREADY_INITED
, "InitAudio failed: %#lx\n", hr
);
2267 destroy_performance(performance
, NULL
, dsound
);
2269 /* Provided dmusic and dsound */
2270 create_performance(&performance
, &dmusic
, &dsound
, TRUE
);
2271 hr
= IDirectMusicPerformance8_InitAudio(performance
, &dmusic
, &dsound
, NULL
, 0, 64, 0, NULL
);
2272 ok(hr
== S_OK
, "InitAudio failed: %#lx\n", hr
);
2273 ref
= get_refcount(dsound
);
2274 ok(ref
== 2, "dsound ref count got %ld expected 2\n", ref
);
2275 ref
= get_refcount(dmusic
);
2276 ok(ref
== 2, "dmusic ref count got %ld expected 2\n", ref
);
2277 destroy_performance(performance
, dmusic
, dsound
);
2279 /* Provided dmusic initialized with SetDirectSound */
2280 create_performance(&performance
, &dmusic
, &dsound
, TRUE
);
2281 hr
= IDirectMusic_SetDirectSound(dmusic
, dsound
, NULL
);
2282 ok(hr
== S_OK
, "SetDirectSound failed: %#lx\n", hr
);
2283 ref
= get_refcount(dsound
);
2284 ok(ref
== 2, "dsound ref count got %ld expected 2\n", ref
);
2285 hr
= IDirectMusicPerformance8_InitAudio(performance
, &dmusic
, NULL
, NULL
, 0, 64, 0, NULL
);
2286 ok(hr
== S_OK
, "InitAudio failed: %#lx\n", hr
);
2287 ref
= get_refcount(dsound
);
2288 ok(ref
== 2, "dsound ref count got %ld expected 2\n", ref
);
2289 ref
= get_refcount(dmusic
);
2290 ok(ref
== 2, "dmusic ref count got %ld expected 2\n", ref
);
2291 destroy_performance(performance
, dmusic
, dsound
);
2293 /* Provided dmusic and dsound, dmusic initialized with SetDirectSound */
2294 create_performance(&performance
, &dmusic
, &dsound
, TRUE
);
2295 hr
= IDirectMusic_SetDirectSound(dmusic
, dsound
, NULL
);
2296 ok(hr
== S_OK
, "SetDirectSound failed: %#lx\n", hr
);
2297 ref
= get_refcount(dsound
);
2298 ok(ref
== 2, "dsound ref count got %ld expected 2\n", ref
);
2299 hr
= IDirectMusicPerformance8_InitAudio(performance
, &dmusic
, &dsound
, NULL
, 0, 64, 0, NULL
);
2300 ok(hr
== S_OK
, "InitAudio failed: %#lx\n", hr
);
2301 ref
= get_refcount(dsound
);
2302 ok(ref
== 3, "dsound ref count got %ld expected 3\n", ref
);
2303 ref
= get_refcount(dmusic
);
2304 ok(ref
== 2, "dmusic ref count got %ld expected 2\n", ref
);
2305 destroy_performance(performance
, dmusic
, dsound
);
2307 /* Provided dmusic and dsound, dmusic initialized with SetDirectSound, port created and activated */
2308 create_performance(&performance
, &dmusic
, &dsound
, TRUE
);
2309 hr
= IDirectMusic_SetDirectSound(dmusic
, dsound
, NULL
);
2310 ok(hr
== S_OK
, "SetDirectSound failed: %#lx\n", hr
);
2311 hr
= IDirectMusic_CreatePort(dmusic
, &CLSID_DirectMusicSynth
, ¶ms
, &port
, NULL
);
2312 ok(hr
== S_OK
, "CreatePort failed: %#lx\n", hr
);
2313 hr
= IDirectMusicPort_Activate(port
, TRUE
);
2314 ok(hr
== S_OK
, "Activate failed: %#lx\n", hr
);
2315 hr
= IDirectMusicPort_SetNumChannelGroups(port
, 1);
2316 ok(hr
== S_OK
, "SetNumChannelGroups failed: %#lx\n", hr
);
2317 hr
= IDirectMusicPerformance8_Init(performance
, &dmusic
, dsound
, 0);
2318 ok(hr
== S_OK
, "Init failed: %#lx\n", hr
);
2319 destroy_performance(performance
, dmusic
, dsound
);
2321 /* InitAudio with perf channel count not a multiple of 16 rounds up */
2322 create_performance(&performance
, NULL
, NULL
, TRUE
);
2323 hr
= IDirectMusicPerformance8_InitAudio(performance
, NULL
, NULL
, NULL
,
2324 DMUS_APATH_SHARED_STEREOPLUSREVERB
, 29, DMUS_AUDIOF_ALL
, NULL
);
2325 ok(hr
== S_OK
, "InitAudio failed: %#lx\n", hr
);
2326 hr
= IDirectMusicPerformance8_PChannelInfo(performance
, 31, &port
, &group
, &channel
);
2327 ok(hr
== S_OK
&& group
== 2 && channel
== 15,
2328 "PChannelInfo failed, got %#lx, %lu, %lu\n", hr
, group
, channel
);
2329 hr
= IDirectMusicPerformance8_PChannelInfo(performance
, 32, &port
, NULL
, NULL
);
2330 ok(hr
== E_INVALIDARG
, "PChannelInfo failed, got %#lx\n", hr
);
2331 destroy_performance(performance
, NULL
, NULL
);
2334 static void test_performance_createport(void)
2336 IDirectMusicPerformance8
*perf
;
2337 IDirectMusic
*music
= NULL
;
2338 IDirectMusicPort
*port
= NULL
;
2339 DMUS_PORTCAPS portcaps
;
2340 DMUS_PORTPARAMS portparams
;
2344 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
,
2345 CLSCTX_INPROC_SERVER
, &IID_IDirectMusicPerformance8
, (void**)&perf
);
2346 ok(hr
== S_OK
, "CoCreateInstance failed: %#lx\n", hr
);
2348 hr
= IDirectMusicPerformance8_Init(perf
, &music
, NULL
, NULL
);
2349 ok(hr
== S_OK
, "Init failed: %#lx\n", hr
);
2350 ok(music
!= NULL
, "Didn't get IDirectMusic pointer\n");
2354 portcaps
.dwSize
= sizeof(portcaps
);
2356 hr
= IDirectMusic_EnumPort(music
, i
, &portcaps
);
2357 ok(hr
== S_OK
|| hr
== S_FALSE
|| (i
== 0 && hr
== E_INVALIDARG
), "EnumPort failed: %#lx\n", hr
);
2361 ok(portcaps
.dwSize
== sizeof(portcaps
), "Got unexpected portcaps struct size: %lu\n", portcaps
.dwSize
);
2362 trace("portcaps(%lu).dwFlags: %#lx\n", i
, portcaps
.dwFlags
);
2363 trace("portcaps(%lu).guidPort: %s\n", i
, wine_dbgstr_guid(&portcaps
.guidPort
));
2364 trace("portcaps(%lu).dwClass: %#lx\n", i
, portcaps
.dwClass
);
2365 trace("portcaps(%lu).dwType: %#lx\n", i
, portcaps
.dwType
);
2366 trace("portcaps(%lu).dwMemorySize: %#lx\n", i
, portcaps
.dwMemorySize
);
2367 trace("portcaps(%lu).dwMaxChannelGroups: %lu\n", i
, portcaps
.dwMaxChannelGroups
);
2368 trace("portcaps(%lu).dwMaxVoices: %lu\n", i
, portcaps
.dwMaxVoices
);
2369 trace("portcaps(%lu).dwMaxAudioChannels: %lu\n", i
, portcaps
.dwMaxAudioChannels
);
2370 trace("portcaps(%lu).dwEffectFlags: %#lx\n", i
, portcaps
.dwEffectFlags
);
2371 trace("portcaps(%lu).wszDescription: %s\n", i
, wine_dbgstr_w(portcaps
.wszDescription
));
2377 win_skip("No ports available, skipping tests\n");
2381 portparams
.dwSize
= sizeof(portparams
);
2383 /* dwValidParams == 0 -> S_OK, filled struct */
2384 portparams
.dwValidParams
= 0;
2385 hr
= IDirectMusic_CreatePort(music
, &CLSID_DirectMusicSynth
, &portparams
, &port
, NULL
);
2386 ok(hr
== S_OK
, "CreatePort failed: %#lx\n", hr
);
2387 ok(port
!= NULL
, "Didn't get IDirectMusicPort pointer\n");
2388 ok(portparams
.dwValidParams
, "portparams struct was not filled in\n");
2389 IDirectMusicPort_Release(port
);
2392 /* dwValidParams != 0, invalid param -> S_FALSE, filled struct */
2393 portparams
.dwValidParams
= DMUS_PORTPARAMS_CHANNELGROUPS
;
2394 portparams
.dwChannelGroups
= 0;
2395 hr
= IDirectMusic_CreatePort(music
, &CLSID_DirectMusicSynth
, &portparams
, &port
, NULL
);
2396 todo_wine
ok(hr
== S_FALSE
, "CreatePort failed: %#lx\n", hr
);
2397 ok(port
!= NULL
, "Didn't get IDirectMusicPort pointer\n");
2398 ok(portparams
.dwValidParams
, "portparams struct was not filled in\n");
2399 IDirectMusicPort_Release(port
);
2402 /* dwValidParams != 0, valid params -> S_OK */
2403 hr
= IDirectMusic_CreatePort(music
, &CLSID_DirectMusicSynth
, &portparams
, &port
, NULL
);
2404 ok(hr
== S_OK
, "CreatePort failed: %#lx\n", hr
);
2405 ok(port
!= NULL
, "Didn't get IDirectMusicPort pointer\n");
2406 IDirectMusicPort_Release(port
);
2409 /* GUID_NULL succeeds */
2410 portparams
.dwValidParams
= 0;
2411 hr
= IDirectMusic_CreatePort(music
, &GUID_NULL
, &portparams
, &port
, NULL
);
2412 ok(hr
== S_OK
, "CreatePort failed: %#lx\n", hr
);
2413 ok(port
!= NULL
, "Didn't get IDirectMusicPort pointer\n");
2414 ok(portparams
.dwValidParams
, "portparams struct was not filled in\n");
2415 IDirectMusicPort_Release(port
);
2418 /* null GUID fails */
2419 portparams
.dwValidParams
= 0;
2420 hr
= IDirectMusic_CreatePort(music
, NULL
, &portparams
, &port
, NULL
);
2421 ok(hr
== E_POINTER
, "CreatePort failed: %#lx\n", hr
);
2422 ok(port
== NULL
, "Get IDirectMusicPort pointer? %p\n", port
);
2423 ok(portparams
.dwValidParams
== 0, "portparams struct was filled in?\n");
2425 /* garbage GUID fails */
2426 portparams
.dwValidParams
= 0;
2427 hr
= IDirectMusic_CreatePort(music
, &GUID_Bunk
, &portparams
, &port
, NULL
);
2428 ok(hr
== E_NOINTERFACE
, "CreatePort failed: %#lx\n", hr
);
2429 ok(port
== NULL
, "Get IDirectMusicPort pointer? %p\n", port
);
2430 ok(portparams
.dwValidParams
== 0, "portparams struct was filled in?\n");
2432 hr
= IDirectMusicPerformance8_CloseDown(perf
);
2433 ok(hr
== S_OK
, "CloseDown failed: %#lx\n", hr
);
2435 IDirectMusic_Release(music
);
2436 IDirectMusicPerformance8_Release(perf
);
2439 static void test_performance_pchannel(void)
2441 IDirectMusicPerformance8
*perf
;
2442 IDirectMusicPort
*port
= NULL
, *port2
;
2443 DWORD channel
, group
;
2447 create_performance(&perf
, NULL
, NULL
, TRUE
);
2448 hr
= IDirectMusicPerformance8_Init(perf
, NULL
, NULL
, NULL
);
2449 ok(hr
== S_OK
, "Init failed: %#lx\n", hr
);
2450 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 0, &port
, NULL
, NULL
);
2451 ok(hr
== E_INVALIDARG
&& !port
, "PChannelInfo failed, got %#lx, %p\n", hr
, port
);
2453 /* Add default port. Sets PChannels 0-15 to the corresponding channels in group 1 */
2454 hr
= IDirectMusicPerformance8_AddPort(perf
, NULL
);
2455 ok(hr
== S_OK
, "AddPort of default port failed: %#lx\n", hr
);
2456 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 0, NULL
, NULL
, NULL
);
2457 ok(hr
== S_OK
, "PChannelInfo failed, got %#lx\n", hr
);
2458 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 0, &port
, NULL
, NULL
);
2459 ok(hr
== S_OK
&& port
, "PChannelInfo failed, got %#lx, %p\n", hr
, port
);
2460 for (i
= 1; i
< 16; i
++) {
2461 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, i
, &port2
, &group
, &channel
);
2462 ok(hr
== S_OK
&& port
== port2
&& group
== 1 && channel
== i
,
2463 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2464 IDirectMusicPort_Release(port2
);
2467 /* Unset PChannels fail to retrieve */
2468 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 16, &port2
, NULL
, NULL
);
2469 ok(hr
== E_INVALIDARG
, "PChannelInfo failed, got %#lx, %p\n", hr
, port
);
2470 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, MAXDWORD
- 16, &port2
, NULL
, NULL
);
2471 ok(hr
== E_INVALIDARG
, "PChannelInfo failed, got %#lx, %p\n", hr
, port
);
2473 /* Channel group 0 can be set just fine */
2474 hr
= IDirectMusicPerformance8_AssignPChannel(perf
, 0, port
, 0, 0);
2475 ok(hr
== S_OK
, "AssignPChannel failed, got %#lx\n", hr
);
2476 hr
= IDirectMusicPerformance8_AssignPChannelBlock(perf
, 0, port
, 0);
2477 ok(hr
== S_OK
, "AssignPChannelBlock failed, got %#lx\n", hr
);
2478 for (i
= 1; i
< 16; i
++) {
2479 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, i
, &port2
, &group
, &channel
);
2480 ok(hr
== S_OK
&& port
== port2
&& group
== 0 && channel
== i
,
2481 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2482 IDirectMusicPort_Release(port2
);
2485 /* Last PChannel Block can be set only individually but not read */
2486 hr
= IDirectMusicPerformance8_AssignPChannel(perf
, MAXDWORD
, port
, 0, 3);
2487 ok(hr
== S_OK
, "AssignPChannel failed, got %#lx\n", hr
);
2488 port2
= (IDirectMusicPort
*)0xdeadbeef;
2489 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, MAXDWORD
, &port2
, NULL
, NULL
);
2490 todo_wine
ok(hr
== E_INVALIDARG
&& port2
== (IDirectMusicPort
*)0xdeadbeef,
2491 "PChannelInfo failed, got %#lx, %p\n", hr
, port2
);
2492 hr
= IDirectMusicPerformance8_AssignPChannelBlock(perf
, MAXDWORD
, port
, 0);
2493 ok(hr
== E_INVALIDARG
, "AssignPChannelBlock failed, got %#lx\n", hr
);
2494 hr
= IDirectMusicPerformance8_AssignPChannelBlock(perf
, MAXDWORD
/ 16, port
, 1);
2495 todo_wine
ok(hr
== E_INVALIDARG
, "AssignPChannelBlock failed, got %#lx\n", hr
);
2496 for (i
= MAXDWORD
- 15; i
< MAXDWORD
; i
++) {
2497 hr
= IDirectMusicPerformance8_AssignPChannel(perf
, i
, port
, 0, 0);
2498 ok(hr
== S_OK
, "AssignPChannel failed, got %#lx\n", hr
);
2499 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, i
, &port2
, NULL
, NULL
);
2500 todo_wine
ok(hr
== E_INVALIDARG
&& port2
== (IDirectMusicPort
*)0xdeadbeef,
2501 "PChannelInfo failed, got %#lx, %p\n", hr
, port2
);
2504 /* Second to last PChannel Block can be set only individually and read */
2505 hr
= IDirectMusicPerformance8_AssignPChannelBlock(perf
, MAXDWORD
/ 16 - 1, port
, 1);
2506 todo_wine
ok(hr
== E_INVALIDARG
, "AssignPChannelBlock failed, got %#lx\n", hr
);
2507 for (i
= MAXDWORD
- 31; i
< MAXDWORD
- 15; i
++) {
2508 hr
= IDirectMusicPerformance8_AssignPChannel(perf
, i
, port
, 1, 7);
2509 ok(hr
== S_OK
, "AssignPChannel failed, got %#lx\n", hr
);
2510 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, i
, &port2
, &group
, &channel
);
2511 ok(hr
== S_OK
&& port2
== port
&& group
== 1 && channel
== 7,
2512 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2513 IDirectMusicPort_Release(port2
);
2516 /* Third to last PChannel Block behaves normal */
2517 hr
= IDirectMusicPerformance8_AssignPChannelBlock(perf
, MAXDWORD
/ 16 - 2, port
, 0);
2518 ok(hr
== S_OK
, "AssignPChannelBlock failed, got %#lx\n", hr
);
2519 for (i
= MAXDWORD
- 47; i
< MAXDWORD
- 31; i
++) {
2520 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, i
, &port2
, &group
, &channel
);
2521 ok(hr
== S_OK
&& port2
== port
&& group
== 0 && channel
== i
% 16,
2522 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2523 IDirectMusicPort_Release(port2
);
2526 /* One PChannel set in a Block, rest is initialized too */
2527 hr
= IDirectMusicPerformance8_AssignPChannel(perf
, 4711, port
, 1, 13);
2528 ok(hr
== S_OK
, "AssignPChannel failed, got %#lx\n", hr
);
2529 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 4711, &port2
, &group
, &channel
);
2530 ok(hr
== S_OK
&& port2
== port
&& group
== 1 && channel
== 13,
2531 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2532 IDirectMusicPort_Release(port2
);
2533 group
= channel
= 0xdeadbeef;
2534 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 4712, &port2
, &group
, &channel
);
2535 ok(hr
== S_OK
&& port2
== port
&& group
== 0 && channel
== 8,
2536 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2537 IDirectMusicPort_Release(port2
);
2538 group
= channel
= 0xdeadbeef;
2539 hr
= IDirectMusicPerformance8_PChannelInfo(perf
, 4719, &port2
, &group
, &channel
);
2540 ok(hr
== S_OK
&& port2
== port
&& group
== 0 && channel
== 15,
2541 "PChannelInfo failed, got %#lx, %p, %lu, %lu\n", hr
, port2
, group
, channel
);
2542 IDirectMusicPort_Release(port2
);
2544 IDirectMusicPort_Release(port
);
2545 destroy_performance(perf
, NULL
, NULL
);
2548 static void test_performance_tool(void)
2550 DMUS_NOTE_PMSG note60
=
2552 .dwSize
= sizeof(DMUS_NOTE_PMSG
),
2553 .dwFlags
= DMUS_PMSGF_REFTIME
| DMUS_PMSGF_MUSICTIME
| DMUS_PMSGF_TOOL_QUEUE
,
2554 .dwVirtualTrackID
= 1,
2555 .dwType
= DMUS_PMSGT_NOTE
,
2560 .bFlags
= DMUS_NOTEF_NOTEON
,
2561 .bPlayModeFlags
= DMUS_PLAYMODE_FIXED
,
2564 IDirectMusicPerformance
*performance
;
2565 IDirectMusicGraph
*graph
;
2566 IDirectMusicTool
*tool
;
2567 DWORD value
, types
[1];
2568 DMUS_NOTE_PMSG
*note
;
2569 DMUS_PMSG msg
= {0};
2572 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
2573 &IID_IDirectMusicPerformance
, (void **)&performance
);
2574 ok(hr
== S_OK
, "got %#lx\n", hr
);
2576 check_interface(performance
, &IID_IDirectMusicTool8
, FALSE
);
2578 hr
= IDirectMusicPerformance_QueryInterface(performance
, &IID_IDirectMusicTool
, (void **)&tool
);
2579 ok(hr
== S_OK
, "got %#lx\n", hr
);
2580 hr
= IDirectMusicPerformance_QueryInterface(performance
, &IID_IDirectMusicGraph
, (void **)&graph
);
2581 ok(hr
== S_OK
, "got %#lx\n", hr
);
2583 hr
= IDirectMusicTool_Init(tool
, graph
);
2584 ok(hr
== E_NOTIMPL
, "got %#lx\n", hr
);
2586 hr
= IDirectMusicTool_GetMsgDeliveryType(tool
, &value
);
2587 ok(hr
== S_OK
, "got %#lx\n", hr
);
2588 ok(value
== DMUS_PMSGF_TOOL_IMMEDIATE
, "got %#lx\n", value
);
2590 hr
= IDirectMusicTool_GetMediaTypeArraySize(tool
, &value
);
2591 ok(hr
== S_OK
, "got %#lx\n", hr
);
2592 ok(value
== 0, "got %#lx\n", value
);
2593 hr
= IDirectMusicTool_GetMediaTypes(tool
, (DWORD
**)&types
, 64);
2594 ok(hr
== E_NOTIMPL
, "got %#lx\n", hr
);
2595 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, &msg
);
2596 ok(hr
== DMUS_S_FREE
, "got %#lx\n", hr
);
2597 hr
= IDirectMusicTool_Flush(tool
, performance
, &msg
, 0);
2598 todo_wine
ok(hr
== S_OK
, "got %#lx\n", hr
);
2600 hr
= IDirectMusicPerformance_Init(performance
, NULL
, NULL
, NULL
);
2601 ok(hr
== S_OK
, "got %#lx\n", hr
);
2603 hr
= IDirectMusicPerformance_AddPort(performance
, NULL
);
2604 ok(hr
== S_OK
, "got %#lx\n", hr
);
2606 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_NOTE_PMSG
), (DMUS_PMSG
**)¬e
);
2607 ok(hr
== S_OK
, "got %#lx\n", hr
);
2609 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, ¬e60
.mtTime
);
2610 ok(hr
== S_OK
, "got %#lx\n", hr
);
2611 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, note60
.mtTime
, ¬e60
.rtTime
);
2612 ok(hr
== S_OK
, "got %#lx\n", hr
);
2616 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, (DMUS_PMSG
*)note
);
2617 ok(hr
== DMUS_S_FREE
, "got %#lx\n", hr
);
2619 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, ¬e60
.mtTime
);
2620 ok(hr
== S_OK
, "got %#lx\n", hr
);
2621 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, note60
.mtTime
, ¬e60
.rtTime
);
2622 ok(hr
== S_OK
, "got %#lx\n", hr
);
2625 note
->mtDuration
= 0;
2626 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, (DMUS_PMSG
*)note
);
2627 ok(hr
== DMUS_S_FREE
, "got %#lx\n", hr
);
2629 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, ¬e60
.mtTime
);
2630 ok(hr
== S_OK
, "got %#lx\n", hr
);
2631 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, note60
.mtTime
, ¬e60
.rtTime
);
2632 ok(hr
== S_OK
, "got %#lx\n", hr
);
2635 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, (DMUS_PMSG
*)note
);
2636 ok(hr
== DMUS_S_REQUEUE
, "got %#lx\n", hr
);
2637 ok(fabs(note
->rtTime
- note60
.rtTime
- scale_music_time(999, 120.0)) < 10.0,
2638 "got %I64d\n", note
->rtTime
- note60
.rtTime
);
2639 ok(note
->mtTime
- note60
.mtTime
== 999, "got %ld\n", note
->mtTime
- note60
.mtTime
);
2640 check_dmus_note_pmsg(note
, note60
.mtTime
+ 999, 0, 1000, 60, 127, 0);
2642 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, ¬e60
.mtTime
);
2643 ok(hr
== S_OK
, "got %#lx\n", hr
);
2644 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, note60
.mtTime
, ¬e60
.rtTime
);
2645 ok(hr
== S_OK
, "got %#lx\n", hr
);
2648 note
->nOffset
= 1000;
2649 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, (DMUS_PMSG
*)note
);
2650 ok(hr
== DMUS_S_REQUEUE
, "got %#lx\n", hr
);
2651 ok(fabs(note
->rtTime
- note60
.rtTime
- scale_music_time(999, 120.0)) < 10.0,
2652 "got %I64d\n", note
->rtTime
- note60
.rtTime
);
2653 ok(note
->mtTime
- note60
.mtTime
== 999, "got %ld\n", note
->mtTime
- note60
.mtTime
);
2654 check_dmus_note_pmsg(note
, note60
.mtTime
+ 999, 0, 1000, 60, 127, 0);
2656 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, ¬e60
.mtTime
);
2657 ok(hr
== S_OK
, "got %#lx\n", hr
);
2658 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, note60
.mtTime
, ¬e60
.rtTime
);
2659 ok(hr
== S_OK
, "got %#lx\n", hr
);
2662 note
->mtDuration
= 2;
2663 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, (DMUS_PMSG
*)note
);
2664 ok(hr
== DMUS_S_REQUEUE
, "got %#lx\n", hr
);
2665 ok(fabs(note
->rtTime
- note60
.rtTime
- scale_music_time(1, 120.0)) < 10.0,
2666 "got %I64d\n", note
->rtTime
- note60
.rtTime
);
2667 ok(note
->mtTime
- note60
.mtTime
== 1, "got %ld\n", note
->mtTime
- note60
.mtTime
);
2668 check_dmus_note_pmsg(note
, note60
.mtTime
+ 1, 0, 2, 60, 127, 0);
2670 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, ¬e60
.mtTime
);
2671 ok(hr
== S_OK
, "got %#lx\n", hr
);
2672 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, note60
.mtTime
, ¬e60
.rtTime
);
2673 ok(hr
== S_OK
, "got %#lx\n", hr
);
2676 note
->mtDuration
= 1;
2677 hr
= IDirectMusicTool_ProcessPMsg(tool
, performance
, (DMUS_PMSG
*)note
);
2678 ok(hr
== DMUS_S_REQUEUE
, "got %#lx\n", hr
);
2679 ok(fabs(note
->rtTime
- note60
.rtTime
- scale_music_time(1, 120.0)) < 10.0,
2680 "got %I64d\n", note
->rtTime
- note60
.rtTime
);
2681 ok(note
->mtTime
- note60
.mtTime
== 1, "got %ld\n", note
->mtTime
- note60
.mtTime
);
2682 check_dmus_note_pmsg(note
, note60
.mtTime
+ 1, 0, 1, 60, 127, 0);
2684 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)note
);
2685 ok(hr
== S_OK
, "got %#lx\n", hr
);
2687 hr
= IDirectMusicPerformance_CloseDown(performance
);
2688 ok(hr
== S_OK
, "got %#lx\n", hr
);
2690 IDirectMusicGraph_Release(graph
);
2691 IDirectMusicTool_Release(tool
);
2693 IDirectMusicPerformance_Release(performance
);
2696 static void test_performance_graph(void)
2698 IDirectMusicPerformance
*performance
;
2699 IDirectMusicGraph
*graph
, *tmp_graph
;
2700 IDirectMusicTool
*tool
, *tmp_tool
;
2704 hr
= test_tool_create(NULL
, 0, &tool
);
2705 ok(hr
== S_OK
, "got %#lx\n", hr
);
2707 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
2708 &IID_IDirectMusicPerformance
, (void **)&performance
);
2709 ok(hr
== S_OK
, "got %#lx\n", hr
);
2712 /* performance exposes a graph interface but it's not an actual toolgraph */
2713 hr
= IDirectMusicPerformance_QueryInterface(performance
, &IID_IDirectMusicGraph
, (void **)&graph
);
2714 ok(hr
== S_OK
, "got %#lx\n", hr
);
2715 hr
= IDirectMusicGraph_InsertTool(graph
, tool
, NULL
, 0, -1);
2716 ok(hr
== E_NOTIMPL
, "got %#lx\n", hr
);
2717 hr
= IDirectMusicGraph_GetTool(graph
, 0, &tmp_tool
);
2718 ok(hr
== E_NOTIMPL
, "got %#lx\n", hr
);
2719 hr
= IDirectMusicGraph_RemoveTool(graph
, tool
);
2720 ok(hr
== E_NOTIMPL
, "got %#lx\n", hr
);
2722 /* test IDirectMusicGraph_StampPMsg usage */
2723 hr
= IDirectMusicGraph_StampPMsg(graph
, NULL
);
2724 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2725 memset(&msg
, 0, sizeof(msg
));
2726 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
2727 ok(hr
== S_OK
, "got %#lx\n", hr
);
2728 ok(msg
.pGraph
== NULL
, "got %p\n", msg
.pGraph
);
2729 ok(msg
.pTool
!= NULL
, "got %p\n", msg
.pTool
);
2730 check_interface(msg
.pTool
, &IID_IDirectMusicPerformance
, TRUE
);
2732 ok(!msg
.dwSize
, "got %ld\n", msg
.dwSize
);
2733 ok(!msg
.rtTime
, "got %I64d\n", msg
.rtTime
);
2734 ok(!msg
.mtTime
, "got %ld\n", msg
.mtTime
);
2735 ok(msg
.dwFlags
== DMUS_PMSGF_TOOL_QUEUE
, "got %#lx\n", msg
.dwFlags
);
2736 ok(!msg
.dwPChannel
, "got %ld\n", msg
.dwPChannel
);
2737 ok(!msg
.dwVirtualTrackID
, "got %ld\n", msg
.dwVirtualTrackID
);
2738 ok(!msg
.dwType
, "got %#lx\n", msg
.dwType
);
2739 ok(!msg
.dwVoiceID
, "got %ld\n", msg
.dwVoiceID
);
2740 ok(!msg
.dwGroupID
, "got %ld\n", msg
.dwGroupID
);
2741 ok(!msg
.punkUser
, "got %p\n", msg
.punkUser
);
2743 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
2744 ok(hr
== S_OK
, "got %#lx\n", hr
);
2745 ok(msg
.pGraph
== NULL
, "got %p\n", msg
.pGraph
);
2746 ok(msg
.pTool
!= NULL
, "got %p\n", msg
.pTool
);
2747 check_interface(msg
.pTool
, &IID_IDirectMusicPerformance
, TRUE
);
2749 IDirectMusicTool_Release(msg
.pTool
);
2752 IDirectMusicGraph_Release(graph
);
2755 /* performance doesn't have a default embedded toolgraph */
2756 hr
= IDirectMusicPerformance_GetGraph(performance
, &graph
);
2757 ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
2760 /* test adding a graph to the performance */
2761 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
2762 &IID_IDirectMusicGraph
, (void **)&graph
);
2763 ok(hr
== S_OK
, "got %#lx\n", hr
);
2764 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
2765 ok(hr
== S_OK
, "got %#lx\n", hr
);
2767 hr
= IDirectMusicPerformance_GetGraph(performance
, &tmp_graph
);
2768 ok(hr
== S_OK
, "got %#lx\n", hr
);
2769 ok(tmp_graph
== graph
, "got %p\n", graph
);
2770 IDirectMusicGraph_Release(tmp_graph
);
2772 hr
= IDirectMusicGraph_InsertTool(graph
, tool
, NULL
, 0, -1);
2773 ok(hr
== S_OK
, "got %#lx\n", hr
);
2775 IDirectMusicGraph_Release(graph
);
2778 /* test IDirectMusicGraph_StampPMsg usage */
2779 hr
= IDirectMusicPerformance_QueryInterface(performance
, &IID_IDirectMusicGraph
, (void **)&graph
);
2780 ok(hr
== S_OK
, "got %#lx\n", hr
);
2782 memset(&msg
, 0, sizeof(msg
));
2783 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
2784 ok(hr
== S_OK
, "got %#lx\n", hr
);
2785 ok(msg
.pGraph
== graph
, "got %p\n", msg
.pGraph
);
2786 ok(msg
.pTool
== tool
, "got %p\n", msg
.pTool
);
2788 ok(!msg
.dwSize
, "got %ld\n", msg
.dwSize
);
2789 ok(!msg
.rtTime
, "got %I64d\n", msg
.rtTime
);
2790 ok(!msg
.mtTime
, "got %ld\n", msg
.mtTime
);
2791 ok(msg
.dwFlags
== DMUS_PMSGF_TOOL_IMMEDIATE
, "got %#lx\n", msg
.dwFlags
);
2792 ok(!msg
.dwPChannel
, "got %ld\n", msg
.dwPChannel
);
2793 ok(!msg
.dwVirtualTrackID
, "got %ld\n", msg
.dwVirtualTrackID
);
2794 ok(!msg
.dwType
, "got %#lx\n", msg
.dwType
);
2795 ok(!msg
.dwVoiceID
, "got %ld\n", msg
.dwVoiceID
);
2796 ok(!msg
.dwGroupID
, "got %ld\n", msg
.dwGroupID
);
2797 ok(!msg
.punkUser
, "got %p\n", msg
.punkUser
);
2799 hr
= IDirectMusicGraph_StampPMsg(graph
, &msg
);
2800 ok(hr
== S_OK
, "got %#lx\n", hr
);
2801 ok(msg
.pGraph
== NULL
, "got %p\n", msg
.pGraph
);
2802 ok(msg
.pTool
!= NULL
, "got %p\n", msg
.pTool
);
2803 check_interface(msg
.pTool
, &IID_IDirectMusicPerformance
, TRUE
);
2805 IDirectMusicTool_Release(msg
.pTool
);
2808 IDirectMusicGraph_Release(graph
);
2811 IDirectMusicPerformance_Release(performance
);
2812 IDirectMusicTool_Release(tool
);
2815 #define check_music_time(a, b) check_music_time_(__LINE__, a, b)
2816 static void check_music_time_(int line
, MUSIC_TIME time
, MUSIC_TIME expect
)
2818 ok_(__FILE__
, line
)(abs(time
- expect
) <= 1, "got %ld, expected %ld\n", time
, expect
);
2821 static void test_performance_time(void)
2823 IDirectMusicPerformance
*performance
;
2824 REFERENCE_TIME init_time
, time
;
2825 IReferenceClock
*clock
;
2826 MUSIC_TIME music_time
;
2827 IDirectMusic
*dmusic
;
2830 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
2831 &IID_IDirectMusicPerformance
, (void **)&performance
);
2832 ok(hr
== S_OK
, "got %#lx\n", hr
);
2835 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 0, NULL
);
2836 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2838 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 0, &time
);
2839 ok(hr
== DMUS_E_NO_MASTER_CLOCK
, "got %#lx\n", hr
);
2840 ok(time
== 0, "got %I64d\n", time
);
2842 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, 0, NULL
);
2843 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2844 music_time
= 0xdeadbeef;
2845 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, 0, &music_time
);
2846 ok(hr
== DMUS_E_NO_MASTER_CLOCK
, "got %#lx\n", hr
);
2847 ok(music_time
== 0, "got %ld\n", music_time
);
2851 hr
= IDirectMusicPerformance_Init(performance
, &dmusic
, NULL
, NULL
);
2852 ok(hr
== S_OK
, "got %#lx\n", hr
);
2853 hr
= IDirectMusic_GetMasterClock(dmusic
, NULL
, &clock
);
2854 ok(hr
== S_OK
, "got %#lx\n", hr
);
2855 IDirectMusic_Release(dmusic
);
2856 hr
= IReferenceClock_GetTime(clock
, &init_time
);
2857 ok(hr
== S_OK
, "got %#lx\n", hr
);
2858 IReferenceClock_Release(clock
);
2862 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 0, &time
);
2863 ok(hr
== S_OK
, "got %#lx\n", hr
);
2864 ok(time
- init_time
<= 100 * 10000, "got %I64d\n", time
- init_time
);
2868 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 1, &time
);
2869 ok(hr
== S_OK
, "got %#lx\n", hr
);
2870 check_music_time(time
- init_time
, scale_music_time(1, 120));
2872 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 1000, &time
);
2873 ok(hr
== S_OK
, "got %#lx\n", hr
);
2874 check_music_time(time
- init_time
, scale_music_time(1000, 120));
2876 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 2000, &time
);
2877 ok(hr
== S_OK
, "got %#lx\n", hr
);
2878 check_music_time(time
- init_time
, scale_music_time(2000, 120));
2880 music_time
= 0xdeadbeef;
2881 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, init_time
, &music_time
);
2882 ok(hr
== S_OK
, "got %#lx\n", hr
);
2883 ok(music_time
== 0, "got %ld\n", music_time
);
2884 music_time
= 0xdeadbeef;
2885 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, init_time
+ scale_music_time(1000, 120), &music_time
);
2886 ok(hr
== S_OK
, "got %#lx\n", hr
);
2887 ok(music_time
== 1000, "got %ld\n", music_time
);
2888 music_time
= 0xdeadbeef;
2889 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, init_time
+ scale_music_time(2000, 120), &music_time
);
2890 ok(hr
== S_OK
, "got %#lx\n", hr
);
2891 ok(music_time
== 2000, "got %ld\n", music_time
);
2894 music_time
= 0xdeadbeef;
2895 hr
= IDirectMusicPerformance_GetTime(performance
, &time
, &music_time
);
2896 ok(hr
== S_OK
, "got %#lx\n", hr
);
2897 ok(time
- init_time
<= 200 * 10000, "got %I64d\n", time
- init_time
);
2898 ok(music_time
== (time
- init_time
) / 6510, "got %ld\n", music_time
);
2901 hr
= IDirectMusicPerformance_CloseDown(performance
);
2902 ok(hr
== S_OK
, "got %#lx\n", hr
);
2904 IDirectMusicPerformance_Release(performance
);
2908 static void test_performance_pmsg(void)
2910 static const DWORD delivery_flags
[] = {DMUS_PMSGF_TOOL_IMMEDIATE
, DMUS_PMSGF_TOOL_QUEUE
, DMUS_PMSGF_TOOL_ATTIME
};
2911 static const DWORD message_types
[] = {DMUS_PMSGT_MIDI
, DMUS_PMSGT_USER
};
2912 IDirectMusicPerformance
*performance
;
2913 IDirectMusicGraph
*graph
, *performance_graph
;
2914 IDirectMusicTool
*tool
;
2915 DMUS_PMSG
*msg
, *clone
;
2916 MUSIC_TIME music_time
;
2917 REFERENCE_TIME time
;
2922 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
2923 ok(hr
== S_OK
, "got %#lx\n", hr
);
2925 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
2926 &IID_IDirectMusicPerformance
, (void **)&performance
);
2927 ok(hr
== S_OK
, "got %#lx\n", hr
);
2928 hr
= IDirectMusicPerformance_QueryInterface(performance
, &IID_IDirectMusicGraph
, (void **)&performance_graph
);
2929 ok(hr
== S_OK
, "got %#lx\n", hr
);
2932 hr
= IDirectMusicPerformance_AllocPMsg(performance
, 0, NULL
);
2933 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2934 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
) - 1, &msg
);
2935 ok(hr
== E_INVALIDARG
, "got %#lx\n", hr
);
2937 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
), &msg
);
2938 ok(hr
== S_OK
, "got %#lx\n", hr
);
2939 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
2940 ok(!msg
->rtTime
, "got %I64d\n", msg
->rtTime
);
2941 ok(!msg
->mtTime
, "got %ld\n", msg
->mtTime
);
2942 ok(!msg
->dwFlags
, "got %#lx\n", msg
->dwFlags
);
2943 ok(!msg
->dwPChannel
, "got %ld\n", msg
->dwPChannel
);
2944 ok(!msg
->dwVirtualTrackID
, "got %ld\n", msg
->dwVirtualTrackID
);
2945 ok(!msg
->dwType
, "got %#lx\n", msg
->dwType
);
2946 ok(!msg
->dwVoiceID
, "got %ld\n", msg
->dwVoiceID
);
2947 ok(!msg
->dwGroupID
, "got %ld\n", msg
->dwGroupID
);
2948 ok(!msg
->punkUser
, "got %p\n", msg
->punkUser
);
2950 hr
= IDirectMusicPerformance_SendPMsg(performance
, NULL
);
2951 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2952 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
2953 ok(hr
== DMUS_E_NO_MASTER_CLOCK
, "got %#lx\n", hr
);
2955 hr
= IDirectMusicPerformance_FreePMsg(performance
, NULL
);
2956 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2957 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
2958 ok(hr
== S_OK
, "got %#lx\n", hr
);
2961 hr
= IDirectMusicPerformance_Init(performance
, NULL
, 0, 0);
2962 ok(hr
== S_OK
, "got %#lx\n", hr
);
2964 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
2965 &IID_IDirectMusicGraph
, (void **)&graph
);
2966 ok(hr
== S_OK
, "got %#lx\n", hr
);
2967 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
2968 ok(hr
== S_OK
, "got %#lx\n", hr
);
2969 hr
= IDirectMusicGraph_InsertTool(graph
, tool
, NULL
, 0, -1);
2970 ok(hr
== S_OK
, "got %#lx\n", hr
);
2971 IDirectMusicGraph_Release(graph
);
2973 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
), &msg
);
2974 ok(hr
== S_OK
, "got %#lx\n", hr
);
2975 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
2976 ok(!msg
->rtTime
, "got %I64d\n", msg
->rtTime
);
2977 ok(!msg
->mtTime
, "got %ld\n", msg
->mtTime
);
2978 ok(!msg
->dwFlags
, "got %#lx\n", msg
->dwFlags
);
2979 ok(!msg
->dwPChannel
, "got %ld\n", msg
->dwPChannel
);
2980 ok(!msg
->dwVirtualTrackID
, "got %ld\n", msg
->dwVirtualTrackID
);
2981 ok(!msg
->pTool
, "got %p\n", msg
->pTool
);
2982 ok(!msg
->pGraph
, "got %p\n", msg
->pGraph
);
2983 ok(!msg
->dwType
, "got %#lx\n", msg
->dwType
);
2984 ok(!msg
->dwVoiceID
, "got %ld\n", msg
->dwVoiceID
);
2985 ok(!msg
->dwGroupID
, "got %ld\n", msg
->dwGroupID
);
2986 ok(!msg
->punkUser
, "got %p\n", msg
->punkUser
);
2987 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
2988 ok(hr
== E_INVALIDARG
, "got %#lx\n", hr
);
2990 hr
= IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8
*)performance
, msg
, NULL
);
2991 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2992 hr
= IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8
*)performance
, NULL
, &clone
);
2993 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
2995 hr
= IDirectMusicPerformance8_ClonePMsg((IDirectMusicPerformance8
*)performance
, msg
, &clone
);
2996 ok(hr
== S_OK
, "got %#lx\n", hr
);
2997 ok(clone
!= NULL
, "got %p\n", clone
);
3000 msg
->dwFlags
= DMUS_PMSGF_MUSICTIME
| DMUS_PMSGF_TOOL_QUEUE
;
3001 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
3002 ok(hr
== S_OK
, "got %#lx\n", hr
);
3003 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
3004 ok(hr
== DMUS_E_ALREADY_SENT
, "got %#lx\n", hr
);
3005 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3006 ok(hr
== DMUS_E_CANNOT_FREE
, "got %#lx\n", hr
);
3008 hr
= IDirectMusicPerformance_FreePMsg(performance
, clone
);
3009 ok(hr
== S_OK
, "got %#lx\n", hr
);
3012 /* SendPMsg skips all the tools unless messages are stamped beforehand */
3014 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
), &msg
);
3015 ok(hr
== S_OK
, "got %#lx\n", hr
);
3016 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
3018 msg
->dwFlags
= DMUS_PMSGF_MUSICTIME
;
3019 msg
->dwType
= DMUS_PMSGT_USER
;
3020 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
3021 ok(hr
== S_OK
, "got %#lx\n", hr
);
3023 ret
= test_tool_wait_message(tool
, 10, &msg
);
3024 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3025 ok(!msg
, "got %p\n", msg
);
3028 /* SendPMsg converts music time to reference time if it is missing */
3030 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
), &msg
);
3031 ok(hr
== S_OK
, "got %#lx\n", hr
);
3032 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
3034 msg
->dwFlags
= DMUS_PMSGF_MUSICTIME
;
3035 msg
->dwType
= DMUS_PMSGT_USER
;
3036 hr
= IDirectMusicGraph_StampPMsg(performance_graph
, msg
);
3037 ok(hr
== S_OK
, "got %#lx\n", hr
);
3038 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
3039 ok(hr
== S_OK
, "got %#lx\n", hr
);
3041 ret
= test_tool_wait_message(tool
, 50, &msg
);
3042 ok(!ret
, "got %#lx\n", ret
);
3043 ok(msg
!= NULL
, "got %p\n", msg
);
3046 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, msg
->mtTime
, &time
);
3047 ok(hr
== S_OK
, "got %#lx\n", hr
);
3048 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
3049 ok(msg
->rtTime
== time
, "got %I64d\n", msg
->rtTime
);
3050 ok(msg
->mtTime
== 500, "got %ld\n", msg
->mtTime
);
3051 ok(msg
->dwFlags
& DMUS_PMSGF_REFTIME
, "got %#lx\n", msg
->dwFlags
);
3052 ok(msg
->dwFlags
& DMUS_PMSGF_MUSICTIME
, "got %#lx\n", msg
->dwFlags
);
3053 ok(msg
->dwFlags
& (DMUS_PMSGF_TOOL_QUEUE
| DMUS_PMSGF_TOOL_IMMEDIATE
), "got %#lx\n", msg
->dwFlags
);
3054 ok(!msg
->dwPChannel
, "got %ld\n", msg
->dwPChannel
);
3055 ok(!msg
->dwVirtualTrackID
, "got %ld\n", msg
->dwVirtualTrackID
);
3056 ok(msg
->pTool
== tool
, "got %p\n", msg
->pTool
);
3057 ok(msg
->pGraph
== performance_graph
, "got %p\n", msg
->pGraph
);
3058 ok(msg
->dwType
== DMUS_PMSGT_USER
, "got %#lx\n", msg
->dwType
);
3059 ok(!msg
->dwVoiceID
, "got %ld\n", msg
->dwVoiceID
);
3060 ok(!msg
->dwGroupID
, "got %ld\n", msg
->dwGroupID
);
3061 ok(!msg
->punkUser
, "got %p\n", msg
->punkUser
);
3063 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3064 ok(hr
== S_OK
, "got %#lx\n", hr
);
3067 /* SendPMsg converts reference time to music time if it is missing */
3069 hr
= IDirectMusicPerformance_GetTime(performance
, &time
, &music_time
);
3070 ok(hr
== S_OK
, "got %#lx\n", hr
);
3072 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
), &msg
);
3073 ok(hr
== S_OK
, "got %#lx\n", hr
);
3074 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
3076 msg
->dwFlags
= DMUS_PMSGF_REFTIME
;
3077 msg
->dwType
= DMUS_PMSGT_USER
;
3078 hr
= IDirectMusicGraph_StampPMsg(performance_graph
, msg
);
3079 ok(hr
== S_OK
, "got %#lx\n", hr
);
3080 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
3081 ok(hr
== S_OK
, "got %#lx\n", hr
);
3083 ret
= test_tool_wait_message(tool
, 50, &msg
);
3084 ok(!ret
, "got %#lx\n", ret
);
3085 ok(msg
!= NULL
, "got %p\n", msg
);
3087 music_time
= 0xdeadbeef;
3088 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, msg
->rtTime
, &music_time
);
3089 ok(hr
== S_OK
, "got %#lx\n", hr
);
3090 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
3091 ok(msg
->rtTime
== time
, "got %I64d\n", msg
->rtTime
);
3092 ok(msg
->mtTime
== music_time
, "got %ld\n", msg
->mtTime
);
3093 ok(msg
->dwFlags
& DMUS_PMSGF_REFTIME
, "got %#lx\n", msg
->dwFlags
);
3094 ok(msg
->dwFlags
& DMUS_PMSGF_MUSICTIME
, "got %#lx\n", msg
->dwFlags
);
3095 ok(msg
->dwFlags
& (DMUS_PMSGF_TOOL_QUEUE
| DMUS_PMSGF_TOOL_IMMEDIATE
), "got %#lx\n", msg
->dwFlags
);
3096 ok(!msg
->dwPChannel
, "got %ld\n", msg
->dwPChannel
);
3097 ok(!msg
->dwVirtualTrackID
, "got %ld\n", msg
->dwVirtualTrackID
);
3098 ok(msg
->pTool
== tool
, "got %p\n", msg
->pTool
);
3099 ok(msg
->pGraph
== performance_graph
, "got %p\n", msg
->pGraph
);
3100 ok(msg
->dwType
== DMUS_PMSGT_USER
, "got %#lx\n", msg
->dwType
);
3101 ok(!msg
->dwVoiceID
, "got %ld\n", msg
->dwVoiceID
);
3102 ok(!msg
->dwGroupID
, "got %ld\n", msg
->dwGroupID
);
3103 ok(!msg
->punkUser
, "got %p\n", msg
->punkUser
);
3105 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3106 ok(hr
== S_OK
, "got %#lx\n", hr
);
3109 for (i
= 0; i
< ARRAY_SIZE(delivery_flags
); i
++)
3113 hr
= IDirectMusicPerformance_GetTime(performance
, &time
, NULL
);
3114 ok(hr
== S_OK
, "got %#lx\n", hr
);
3115 hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(DMUS_PMSG
), &msg
);
3116 ok(hr
== S_OK
, "got %#lx\n", hr
);
3117 ok(msg
->dwSize
== sizeof(DMUS_PMSG
), "got %ld\n", msg
->dwSize
);
3118 msg
->rtTime
= time
+ 150 * 10000;
3119 msg
->dwFlags
= DMUS_PMSGF_REFTIME
;
3120 msg
->dwType
= DMUS_PMSGT_USER
;
3121 hr
= IDirectMusicGraph_StampPMsg(performance_graph
, msg
);
3122 ok(hr
== S_OK
, "got %#lx\n", hr
);
3124 msg
->dwFlags
&= ~(DMUS_PMSGF_TOOL_IMMEDIATE
| DMUS_PMSGF_TOOL_QUEUE
| DMUS_PMSGF_TOOL_ATTIME
);
3125 msg
->dwFlags
|= delivery_flags
[i
];
3127 duration
-= GetTickCount();
3128 hr
= IDirectMusicPerformance_SendPMsg(performance
, msg
);
3129 ok(hr
== S_OK
, "got %#lx\n", hr
);
3131 ret
= test_tool_wait_message(tool
, 1000, &msg
);
3132 ok(!ret
, "got %#lx\n", ret
);
3133 ok(msg
!= NULL
, "got %p\n", msg
);
3134 duration
+= GetTickCount();
3136 if (msg
) hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3137 ok(hr
== S_OK
, "got %#lx\n", hr
);
3139 switch (delivery_flags
[i
])
3141 case DMUS_PMSGF_TOOL_IMMEDIATE
: ok(duration
<= 50, "got %lu\n", duration
); break;
3142 case DMUS_PMSGF_TOOL_QUEUE
: ok(duration
>= 50 && duration
<= 125, "got %lu\n", duration
); break;
3143 case DMUS_PMSGF_TOOL_ATTIME
: ok(duration
>= 125 && duration
<= 500, "got %lu\n", duration
); break;
3148 hr
= IDirectMusicPerformance_CloseDown(performance
);
3149 ok(hr
== S_OK
, "got %#lx\n", hr
);
3152 IDirectMusicGraph_Release(performance_graph
);
3154 IDirectMusicPerformance_Release(performance
);
3155 IDirectMusicTool_Release(tool
);
3158 #define check_dmus_dirty_pmsg(a, b) check_dmus_dirty_pmsg_(__LINE__, a, b)
3159 static void check_dmus_dirty_pmsg_(int line
, DMUS_PMSG
*msg
, MUSIC_TIME music_time
)
3161 ok_(__FILE__
, line
)(msg
->dwSize
== sizeof(*msg
), "got dwSize %#lx\n", msg
->dwSize
);
3162 ok_(__FILE__
, line
)(abs(msg
->mtTime
- music_time
) <= 100, "got mtTime %ld\n", msg
->mtTime
);
3163 ok_(__FILE__
, line
)(msg
->dwFlags
== (DMUS_PMSGF_MUSICTIME
| DMUS_PMSGF_REFTIME
| DMUS_PMSGF_TOOL_IMMEDIATE
),
3164 "got dwFlags %#lx\n", msg
->dwFlags
);
3165 ok_(__FILE__
, line
)(msg
->dwPChannel
== 0, "got dwPChannel %#lx\n", msg
->dwPChannel
);
3166 ok_(__FILE__
, line
)(msg
->dwVirtualTrackID
== 0, "got dwVirtualTrackID %#lx\n", msg
->dwVirtualTrackID
);
3167 ok_(__FILE__
, line
)(msg
->pTool
!= 0, "got pTool %p\n", msg
->pTool
);
3168 ok_(__FILE__
, line
)(msg
->pGraph
!= 0, "got pGraph %p\n", msg
->pGraph
);
3169 ok_(__FILE__
, line
)(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got dwType %#lx\n", msg
->dwType
);
3170 ok_(__FILE__
, line
)(msg
->dwVoiceID
== 0, "got dwVoiceID %#lx\n", msg
->dwVoiceID
);
3171 todo_wine
ok_(__FILE__
, line
)(msg
->dwGroupID
== -1, "got dwGroupID %#lx\n", msg
->dwGroupID
);
3172 ok_(__FILE__
, line
)(msg
->punkUser
== 0, "got punkUser %p\n", msg
->punkUser
);
3175 #define check_dmus_notification_pmsg(a, b, c, d, e, f) check_dmus_notification_pmsg_(__LINE__, a, b, c, d, e, f)
3176 static void check_dmus_notification_pmsg_(int line
, DMUS_NOTIFICATION_PMSG
*msg
, MUSIC_TIME music_time
, DWORD flags
,
3177 const GUID
*type
, DWORD option
, void *user
)
3179 ok_(__FILE__
, line
)(msg
->dwSize
== sizeof(*msg
), "got dwSize %#lx\n", msg
->dwSize
);
3180 ok_(__FILE__
, line
)(msg
->rtTime
> 0, "got rtTime %I64d\n", msg
->rtTime
);
3181 ok_(__FILE__
, line
)(abs(msg
->mtTime
- music_time
) <= 100, "got mtTime %ld\n", msg
->mtTime
);
3182 todo_wine_if(flags
== DMUS_PMSGF_TOOL_ATTIME
)
3183 ok_(__FILE__
, line
)(msg
->dwFlags
== (DMUS_PMSGF_MUSICTIME
| DMUS_PMSGF_REFTIME
| flags
),
3184 "got dwFlags %#lx\n", msg
->dwFlags
);
3185 ok_(__FILE__
, line
)(msg
->dwPChannel
== 0, "got dwPChannel %#lx\n", msg
->dwPChannel
);
3186 ok_(__FILE__
, line
)(msg
->dwVirtualTrackID
== 0, "got dwVirtualTrackID %#lx\n", msg
->dwVirtualTrackID
);
3187 if (flags
== DMUS_PMSGF_TOOL_ATTIME
)
3189 todo_wine
ok_(__FILE__
, line
)(msg
->pTool
== 0, "got pTool %p\n", msg
->pTool
);
3190 ok_(__FILE__
, line
)(msg
->pGraph
== 0, "got pGraph %p\n", msg
->pGraph
);
3194 ok_(__FILE__
, line
)(msg
->pTool
!= 0, "got pTool %p\n", msg
->pTool
);
3195 ok_(__FILE__
, line
)(msg
->pGraph
!= 0, "got pGraph %p\n", msg
->pGraph
);
3197 ok_(__FILE__
, line
)(msg
->dwType
== DMUS_PMSGT_NOTIFICATION
, "got dwType %#lx\n", msg
->dwType
);
3198 ok_(__FILE__
, line
)(msg
->dwVoiceID
== 0, "got dwVoiceID %#lx\n", msg
->dwVoiceID
);
3199 todo_wine
ok_(__FILE__
, line
)(msg
->dwGroupID
== -1, "got dwGroupID %#lx\n", msg
->dwGroupID
);
3200 ok_(__FILE__
, line
)(msg
->punkUser
== (IUnknown
*)user
, "got punkUser %p\n", msg
->punkUser
);
3202 ok_(__FILE__
, line
)(IsEqualGUID(&msg
->guidNotificationType
, type
),
3203 "got guidNotificationType %s\n", debugstr_guid(&msg
->guidNotificationType
));
3204 ok_(__FILE__
, line
)(msg
->dwNotificationOption
== option
,
3205 "got dwNotificationOption %#lx\n", msg
->dwNotificationOption
);
3206 ok_(__FILE__
, line
)(!msg
->dwField1
, "got dwField1 %lu\n", msg
->dwField1
);
3207 ok_(__FILE__
, line
)(!msg
->dwField2
, "got dwField2 %lu\n", msg
->dwField2
);
3209 if (!IsEqualGUID(&msg
->guidNotificationType
, &GUID_NOTIFICATION_SEGMENT
))
3210 ok_(__FILE__
, line
)(!msg
->punkUser
, "got punkUser %p\n", msg
->punkUser
);
3213 check_interface_(line
, msg
->punkUser
, &IID_IDirectMusicSegmentState
, TRUE
, FALSE
);
3214 check_interface_(line
, msg
->punkUser
, &IID_IDirectMusicSegmentState8
, TRUE
, FALSE
);
3218 static void test_notification_pmsg(void)
3220 static const DWORD message_types
[] =
3223 DMUS_PMSGT_NOTIFICATION
,
3226 IDirectMusicPerformance
*performance
;
3227 IDirectMusicSegmentState
*state
;
3228 DMUS_NOTIFICATION_PMSG
*notif
;
3229 MUSIC_TIME music_time
, length
;
3230 IDirectMusicSegment
*segment
;
3231 IDirectMusicTrack
*track
;
3232 IDirectMusicGraph
*graph
;
3233 IDirectMusicTool
*tool
;
3238 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
3239 ok(hr
== S_OK
, "got %#lx\n", hr
);
3241 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
3242 &IID_IDirectMusicPerformance
, (void **)&performance
);
3243 ok(hr
== S_OK
, "got %#lx\n", hr
);
3245 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
3246 &IID_IDirectMusicGraph
, (void **)&graph
);
3247 ok(hr
== S_OK
, "got %#lx\n", hr
);
3248 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
3249 ok(hr
== S_OK
, "got %#lx\n", hr
);
3250 hr
= IDirectMusicGraph_InsertTool(graph
, tool
, NULL
, 0, -1);
3251 ok(hr
== S_OK
, "got %#lx\n", hr
);
3252 IDirectMusicGraph_Release(graph
);
3254 hr
= IDirectMusicPerformance_Init(performance
, NULL
, 0, 0);
3255 ok(hr
== S_OK
, "got %#lx\n", hr
);
3258 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
3259 &IID_IDirectMusicSegment
, (void **)&segment
);
3260 ok(hr
== S_OK
, "got %#lx\n", hr
);
3263 /* native needs a track or the segment will end immediately */
3265 hr
= test_track_create(&track
, FALSE
);
3266 ok(hr
== S_OK
, "got %#lx\n", hr
);
3267 hr
= IDirectMusicSegment_InsertTrack(segment
, track
, 1);
3268 ok(hr
== S_OK
, "got %#lx\n", hr
);
3269 IDirectMusicTrack_Release(track
);
3271 /* native sends dirty / notification by batch of 1s, shorter length
3272 * will cause all messages to be received immediately */
3273 length
= 10005870 / 6510;
3274 hr
= IDirectMusicSegment_SetLength(segment
, length
);
3275 ok(hr
== S_OK
, "got %#lx\n", hr
);
3277 hr
= IDirectMusicSegment8_Download((IDirectMusicSegment8
*)segment
, (IUnknown
*)performance
);
3278 ok(hr
== S_OK
, "got %#lx\n", hr
);
3279 hr
= IDirectMusicSegment8_Unload((IDirectMusicSegment8
*)segment
, (IUnknown
*)performance
);
3280 ok(hr
== S_OK
, "got %#lx\n", hr
);
3282 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 0, NULL
);
3283 ok(hr
== S_OK
, "got %#lx\n", hr
);
3284 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, &music_time
);
3285 ok(hr
== S_OK
, "got %#lx\n", hr
);
3287 ret
= test_tool_wait_message(tool
, 50, &msg
);
3288 ok(!ret
, "got %#lx\n", ret
);
3289 check_dmus_dirty_pmsg(msg
, music_time
);
3290 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3291 ok(hr
== S_OK
, "got %#lx\n", hr
);
3293 ret
= test_tool_wait_message(tool
, 50, &msg
);
3294 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3295 ret
= test_tool_wait_message(tool
, 500, &msg
);
3296 ok(!ret
, "got %#lx\n", ret
);
3297 check_dmus_dirty_pmsg(msg
, music_time
+ length
);
3298 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3299 ok(hr
== S_OK
, "got %#lx\n", hr
);
3301 ret
= test_tool_wait_message(tool
, 100, &msg
);
3302 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3303 ok(!msg
, "got %p\n", msg
);
3306 /* AddNotificationType is necessary to receive notification messages */
3308 hr
= IDirectMusicPerformance_AddNotificationType(performance
, &GUID_NOTIFICATION_PERFORMANCE
);
3309 ok(hr
== S_OK
, "got %#lx\n", hr
);
3310 hr
= IDirectMusicPerformance_AddNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3311 ok(hr
== S_OK
, "got %#lx\n", hr
);
3312 hr
= IDirectMusicPerformance_AddNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3313 ok(hr
== S_FALSE
, "got %#lx\n", hr
);
3315 /* avoid discarding older notifications */
3316 hr
= IDirectMusicPerformance_SetNotificationHandle(performance
, 0, 100000000);
3317 ok(hr
== S_OK
, "got %#lx\n", hr
);
3319 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 0, &state
);
3320 ok(hr
== S_OK
, "got %#lx\n", hr
);
3321 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, &music_time
);
3322 ok(hr
== S_OK
, "got %#lx\n", hr
);
3324 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3325 ok(!ret
, "got %#lx\n", ret
);
3326 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_PERFORMANCE
,
3327 DMUS_NOTIFICATION_MUSICSTARTED
, NULL
);
3328 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3329 ok(hr
== S_OK
, "got %#lx\n", hr
);
3331 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3332 ok(!ret
, "got %#lx\n", ret
);
3333 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_SEGMENT
,
3334 DMUS_NOTIFICATION_SEGSTART
, state
);
3335 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3336 ok(hr
== S_OK
, "got %#lx\n", hr
);
3338 ret
= test_tool_wait_message(tool
, 50, &msg
);
3339 ok(!ret
, "got %#lx\n", ret
);
3340 check_dmus_dirty_pmsg(msg
, music_time
);
3341 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3342 ok(hr
== S_OK
, "got %#lx\n", hr
);
3344 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)¬if
);
3345 ok(!ret
, "got %#lx\n", ret
);
3346 check_dmus_notification_pmsg(notif
, music_time
+ length
- 1450, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_SEGMENT
,
3347 DMUS_NOTIFICATION_SEGALMOSTEND
, state
);
3348 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3349 ok(hr
== S_OK
, "got %#lx\n", hr
);
3351 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3352 ok(!ret
, "got %#lx\n", ret
);
3353 check_dmus_notification_pmsg(notif
, music_time
+ length
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_SEGMENT
,
3354 DMUS_NOTIFICATION_SEGEND
, state
);
3355 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3356 ok(hr
== S_OK
, "got %#lx\n", hr
);
3358 ret
= test_tool_wait_message(tool
, 50, &msg
);
3359 ok(!ret
, "got %#lx\n", ret
);
3360 check_dmus_dirty_pmsg(msg
, music_time
+ length
);
3361 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3362 ok(hr
== S_OK
, "got %#lx\n", hr
);
3364 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3365 ok(!ret
, "got %#lx\n", ret
);
3366 check_dmus_notification_pmsg(notif
, music_time
+ length
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_PERFORMANCE
,
3367 DMUS_NOTIFICATION_MUSICSTOPPED
, NULL
);
3368 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3369 ok(hr
== S_OK
, "got %#lx\n", hr
);
3372 /* wait enough time for notifications to be delivered */
3374 ret
= test_tool_wait_message(tool
, 2000, &msg
);
3375 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3376 ok(!msg
, "got %p\n", msg
);
3379 /* notification messages are also queued for direct access */
3381 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3382 ok(hr
== S_OK
, "got %#lx\n", hr
);
3383 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_ATTIME
, &GUID_NOTIFICATION_PERFORMANCE
,
3384 DMUS_NOTIFICATION_MUSICSTARTED
, NULL
);
3385 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3386 ok(hr
== S_OK
, "got %#lx\n", hr
);
3388 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3389 ok(hr
== S_OK
, "got %#lx\n", hr
);
3390 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_ATTIME
, &GUID_NOTIFICATION_SEGMENT
,
3391 DMUS_NOTIFICATION_SEGSTART
, state
);
3392 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3393 ok(hr
== S_OK
, "got %#lx\n", hr
);
3395 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3396 ok(hr
== S_OK
, "got %#lx\n", hr
);
3397 check_dmus_notification_pmsg(notif
, music_time
+ length
- 1450, DMUS_PMSGF_TOOL_ATTIME
, &GUID_NOTIFICATION_SEGMENT
,
3398 DMUS_NOTIFICATION_SEGALMOSTEND
, state
);
3399 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3400 ok(hr
== S_OK
, "got %#lx\n", hr
);
3402 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3403 ok(hr
== S_OK
, "got %#lx\n", hr
);
3404 check_dmus_notification_pmsg(notif
, music_time
+ length
, DMUS_PMSGF_TOOL_ATTIME
, &GUID_NOTIFICATION_SEGMENT
,
3405 DMUS_NOTIFICATION_SEGEND
, state
);
3406 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3407 ok(hr
== S_OK
, "got %#lx\n", hr
);
3409 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3410 ok(hr
== S_OK
, "got %#lx\n", hr
);
3411 check_dmus_notification_pmsg(notif
, music_time
+ length
, DMUS_PMSGF_TOOL_ATTIME
, &GUID_NOTIFICATION_PERFORMANCE
,
3412 DMUS_NOTIFICATION_MUSICSTOPPED
, NULL
);
3413 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3414 ok(hr
== S_OK
, "got %#lx\n", hr
);
3416 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3417 ok(hr
== S_FALSE
, "got %#lx\n", hr
);
3419 IDirectMusicSegmentState_Release(state
);
3421 hr
= IDirectMusicPerformance_RemoveNotificationType(performance
, &GUID_NOTIFICATION_PERFORMANCE
);
3422 ok(hr
== S_OK
, "got %#lx\n", hr
);
3423 hr
= IDirectMusicPerformance_RemoveNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3424 ok(hr
== S_OK
, "got %#lx\n", hr
);
3427 /* RemoveNotificationType returns S_FALSE if already removed */
3429 hr
= IDirectMusicPerformance_RemoveNotificationType(performance
, &GUID_NOTIFICATION_PERFORMANCE
);
3430 ok(hr
== S_FALSE
, "got %#lx\n", hr
);
3433 /* Stop finishes segment immediately and skips notification messages */
3435 hr
= IDirectMusicPerformance_AddNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3436 ok(hr
== S_OK
, "got %#lx\n", hr
);
3437 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 0, &state
);
3438 ok(hr
== S_OK
, "got %#lx\n", hr
);
3439 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, &music_time
);
3440 ok(hr
== S_OK
, "got %#lx\n", hr
);
3442 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3443 ok(!ret
, "got %#lx\n", ret
);
3444 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_SEGMENT
,
3445 DMUS_NOTIFICATION_SEGSTART
, state
);
3446 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3447 ok(hr
== S_OK
, "got %#lx\n", hr
);
3449 hr
= IDirectMusicPerformance_Stop(performance
, NULL
, NULL
, 0, DMUS_SEGF_DEFAULT
);
3450 ok(hr
== S_OK
, "got %#lx\n", hr
);
3451 hr
= IDirectMusicPerformance_RemoveNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3452 ok(hr
== S_OK
, "got %#lx\n", hr
);
3454 ret
= test_tool_wait_message(tool
, 50, &msg
);
3455 ok(!ret
, "got %#lx\n", ret
);
3456 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
3457 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3458 ok(hr
== S_OK
, "got %#lx\n", hr
);
3460 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3461 ok(!ret
, "got %#lx\n", ret
);
3462 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_SEGMENT
,
3463 DMUS_NOTIFICATION_SEGABORT
, state
);
3464 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3465 ok(hr
== S_OK
, "got %#lx\n", hr
);
3467 ret
= test_tool_wait_message(tool
, 500, &msg
);
3468 ok(!ret
, "got %#lx\n", ret
);
3469 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got dwType %#lx\n", msg
->dwType
);
3470 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3471 ok(hr
== S_OK
, "got %#lx\n", hr
);
3473 ret
= test_tool_wait_message(tool
, 100, &msg
);
3474 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3476 IDirectMusicSegmentState_Release(state
);
3479 /* CloseDown removes all notifications and notification messages */
3481 hr
= IDirectMusicPerformance_AddNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3482 ok(hr
== S_OK
, "got %#lx\n", hr
);
3483 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 0, &state
);
3484 ok(hr
== S_OK
, "got %#lx\n", hr
);
3485 hr
= IDirectMusicPerformance_GetTime(performance
, NULL
, &music_time
);
3486 ok(hr
== S_OK
, "got %#lx\n", hr
);
3488 ret
= test_tool_wait_message(tool
, 50, (DMUS_PMSG
**)¬if
);
3489 ok(!ret
, "got %#lx\n", ret
);
3490 check_dmus_notification_pmsg(notif
, music_time
, DMUS_PMSGF_TOOL_IMMEDIATE
, &GUID_NOTIFICATION_SEGMENT
,
3491 DMUS_NOTIFICATION_SEGSTART
, state
);
3492 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)notif
);
3493 ok(hr
== S_OK
, "got %#lx\n", hr
);
3495 hr
= IDirectMusicPerformance_CloseDown(performance
);
3496 ok(hr
== S_OK
, "got %#lx\n", hr
);
3497 hr
= IDirectMusicPerformance_GetNotificationPMsg(performance
, ¬if
);
3498 ok(hr
== S_FALSE
, "got %#lx\n", hr
);
3499 hr
= IDirectMusicPerformance_RemoveNotificationType(performance
, &GUID_NOTIFICATION_SEGMENT
);
3500 ok(hr
== S_FALSE
, "got %#lx\n", hr
);
3502 ret
= test_tool_wait_message(tool
, 50, &msg
);
3503 ok(!ret
, "got %#lx\n", ret
);
3504 check_dmus_dirty_pmsg(msg
, music_time
);
3505 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3506 ok(hr
== S_OK
, "got %#lx\n", hr
);
3508 ret
= test_tool_wait_message(tool
, 500, &msg
);
3509 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3511 IDirectMusicSegmentState_Release(state
);
3512 IDirectMusicSegment_Release(segment
);
3515 IDirectMusicPerformance_Release(performance
);
3516 IDirectMusicTool_Release(tool
);
3519 static void test_wave_pmsg(void)
3521 static const DWORD message_types
[] =
3526 IDirectMusicPerformance
*performance
;
3527 IDirectMusicSegment
*segment
;
3528 IDirectMusicLoader8
*loader
;
3529 IDirectMusicGraph
*graph
;
3530 WCHAR test_wav
[MAX_PATH
];
3531 IDirectMusicTool
*tool
;
3532 DMUS_WAVE_PMSG
*wave
;
3538 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
3539 ok(hr
== S_OK
, "got %#lx\n", hr
);
3541 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
3542 &IID_IDirectMusicPerformance
, (void **)&performance
);
3543 ok(hr
== S_OK
, "got %#lx\n", hr
);
3545 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
3546 &IID_IDirectMusicGraph
, (void **)&graph
);
3547 ok(hr
== S_OK
, "got %#lx\n", hr
);
3548 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
3549 ok(hr
== S_OK
, "got %#lx\n", hr
);
3550 hr
= IDirectMusicGraph_InsertTool(graph
, tool
, NULL
, 0, -1);
3551 ok(hr
== S_OK
, "got %#lx\n", hr
);
3552 IDirectMusicGraph_Release(graph
);
3554 hr
= IDirectMusicPerformance8_InitAudio((IDirectMusicPerformance8
*)performance
, NULL
, NULL
, NULL
,
3555 DMUS_APATH_SHARED_STEREOPLUSREVERB
, 64, DMUS_AUDIOF_ALL
, NULL
);
3556 ok(hr
== S_OK
, "got %#lx\n", hr
);
3559 load_resource(L
"test.wav", test_wav
);
3561 hr
= CoCreateInstance(&CLSID_DirectMusicLoader
, NULL
, CLSCTX_INPROC_SERVER
,
3562 &IID_IDirectMusicLoader8
, (void **)&loader
);
3563 ok(hr
== S_OK
, "got %#lx\n", hr
);
3564 hr
= IDirectMusicLoader8_LoadObjectFromFile(loader
, &CLSID_DirectMusicSegment
,
3565 &IID_IDirectMusicSegment
, test_wav
, (void **)&segment
);
3566 ok(hr
== S_OK
, "got %#lx\n", hr
);
3567 IDirectMusicLoader8_Release(loader
);
3570 length
= 0xdeadbeef;
3571 hr
= IDirectMusicSegment_GetLength(segment
, &length
);
3572 ok(hr
== S_OK
, "got %#lx\n", hr
);
3573 ok(length
== 1, "got %lu\n", length
);
3576 /* without Download, no DMUS_PMSGT_WAVE is sent */
3578 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 0, NULL
);
3579 ok(hr
== S_OK
, "got %#lx\n", hr
);
3581 ret
= test_tool_wait_message(tool
, 500, &msg
);
3582 ok(!ret
, "got %#lx\n", ret
);
3583 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %p\n", msg
);
3584 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3585 ok(hr
== S_OK
, "got %#lx\n", hr
);
3587 ret
= test_tool_wait_message(tool
, 500, &msg
);
3588 ok(!ret
, "got %#lx\n", ret
);
3589 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %p\n", msg
);
3590 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3591 ok(hr
== S_OK
, "got %#lx\n", hr
);
3593 ret
= test_tool_wait_message(tool
, 100, &msg
);
3594 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3595 ok(!msg
, "got %p\n", msg
);
3598 /* a single DMUS_PMSGT_WAVE message is sent with punkUser set */
3600 hr
= IDirectMusicSegment8_Download((IDirectMusicSegment8
*)segment
, (IUnknown
*)performance
);
3601 ok(hr
== S_OK
, "got %#lx\n", hr
);
3603 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 0, NULL
);
3604 ok(hr
== S_OK
, "got %#lx\n", hr
);
3606 ret
= test_tool_wait_message(tool
, 500, &msg
);
3607 ok(!ret
, "got %#lx\n", ret
);
3608 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %p\n", msg
);
3609 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3610 ok(hr
== S_OK
, "got %#lx\n", hr
);
3612 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)&wave
);
3613 ok(!ret
, "got %#lx\n", ret
);
3614 ok(wave
->dwType
== DMUS_PMSGT_WAVE
, "got %p\n", wave
);
3615 ok(!!wave
->punkUser
, "got %p\n", wave
->punkUser
);
3616 ok(wave
->rtStartOffset
== 0, "got %I64d\n", wave
->rtStartOffset
);
3617 ok(wave
->rtDuration
== 1000000, "got %I64d\n", wave
->rtDuration
);
3618 ok(wave
->lOffset
== 0, "got %lu\n", wave
->lOffset
);
3619 ok(wave
->lVolume
== 0, "got %lu\n", wave
->lVolume
);
3620 ok(wave
->lPitch
== 0, "got %lu\n", wave
->lPitch
);
3621 ok(wave
->bFlags
== 0, "got %#x\n", wave
->bFlags
);
3622 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)wave
);
3623 ok(hr
== S_OK
, "got %#lx\n", hr
);
3625 ret
= test_tool_wait_message(tool
, 500, &msg
);
3626 ok(!ret
, "got %#lx\n", ret
);
3627 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %p\n", msg
);
3628 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3629 ok(hr
== S_OK
, "got %#lx\n", hr
);
3631 hr
= IDirectMusicSegment8_Unload((IDirectMusicSegment8
*)segment
, (IUnknown
*)performance
);
3632 ok(hr
== S_OK
, "got %#lx\n", hr
);
3634 ret
= test_tool_wait_message(tool
, 100, &msg
);
3635 ok(ret
== WAIT_TIMEOUT
, "got %#lx\n", ret
);
3636 ok(!msg
, "got %p\n", msg
);
3639 IDirectMusicSegment_Release(segment
);
3642 hr
= IDirectMusicPerformance_CloseDown(performance
);
3643 ok(hr
== S_OK
, "got %#lx\n", hr
);
3645 IDirectMusicPerformance_Release(performance
);
3646 IDirectMusicTool_Release(tool
);
3649 static void test_sequence_track(void)
3651 static const DWORD message_types
[] =
3658 static const LARGE_INTEGER zero
= {0};
3659 IDirectMusicPerformance
*performance
;
3660 IDirectMusicSegment
*segment
;
3661 IDirectMusicGraph
*graph
;
3662 IDirectMusicTrack
*track
;
3663 IPersistStream
*persist
;
3664 IDirectMusicTool
*tool
;
3665 DMUS_NOTE_PMSG
*note
;
3671 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
3672 ok(hr
== S_OK
, "got %#lx\n", hr
);
3674 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
3675 &IID_IDirectMusicPerformance
, (void **)&performance
);
3676 ok(hr
== S_OK
, "got %#lx\n", hr
);
3678 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
3679 &IID_IDirectMusicGraph
, (void **)&graph
);
3680 ok(hr
== S_OK
, "got %#lx\n", hr
);
3681 hr
= IDirectMusicGraph_InsertTool(graph
, (IDirectMusicTool
*)tool
, NULL
, 0, -1);
3682 ok(hr
== S_OK
, "got %#lx\n", hr
);
3683 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
3684 ok(hr
== S_OK
, "got %#lx\n", hr
);
3685 IDirectMusicGraph_Release(graph
);
3688 /* create a segment and load a simple RIFF stream */
3690 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
3691 &IID_IDirectMusicSegment
, (void **)&segment
);
3692 ok(hr
== S_OK
, "got %#lx\n", hr
);
3694 hr
= IDirectMusicSegment_QueryInterface(segment
, &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
, "DMSG")
3701 /* set a non-zero segment length, or nothing will be played */
3702 DMUS_IO_SEGMENT_HEADER head
= {.mtLength
= 2000};
3703 CHUNK_DATA(stream
, "segh", head
);
3704 CHUNK_DATA(stream
, "guid", CLSID_DirectMusicSegment
);
3708 hr
= IStream_Seek(stream
, zero
, 0, NULL
);
3709 ok(hr
== S_OK
, "got %#lx\n", hr
);
3710 hr
= IPersistStream_Load(persist
, stream
);
3711 ok(hr
== S_OK
, "got %#lx\n", hr
);
3712 IPersistStream_Release(persist
);
3713 IStream_Release(stream
);
3716 /* add a sequence track to our segment */
3718 hr
= CoCreateInstance(&CLSID_DirectMusicSeqTrack
, NULL
, CLSCTX_INPROC_SERVER
,
3719 &IID_IDirectMusicTrack
, (void **)&track
);
3720 ok(hr
== S_OK
, "got %#lx\n", hr
);
3722 hr
= IDirectMusicSegment_QueryInterface(track
, &IID_IPersistStream
, (void **)&persist
);
3723 ok(hr
== S_OK
, "got %#lx\n", hr
);
3724 hr
= CreateStreamOnHGlobal(0, TRUE
, &stream
);
3725 ok(hr
== S_OK
, "got %#lx\n", hr
);
3727 CHUNK_BEGIN(stream
, "seqt")
3729 DMUS_IO_SEQ_ITEM items
[] =
3731 {.mtTime
= 0, .mtDuration
= 500, .dwPChannel
= 0, .bStatus
= 0x90, .bByte1
= 60, .bByte2
= 120},
3732 {.mtTime
= 1000, .mtDuration
= 200, .dwPChannel
= 1, .bStatus
= 0x90, .bByte1
= 50, .bByte2
= 100},
3734 CHUNK_ARRAY(stream
, "evtl", items
);
3738 hr
= IStream_Seek(stream
, zero
, 0, NULL
);
3739 ok(hr
== S_OK
, "got %#lx\n", hr
);
3740 hr
= IPersistStream_Load(persist
, stream
);
3741 ok(hr
== S_OK
, "got %#lx\n", hr
);
3742 IPersistStream_Release(persist
);
3743 IStream_Release(stream
);
3745 hr
= IDirectMusicSegment_InsertTrack(segment
, (IDirectMusicTrack
*)track
, 1);
3746 ok(hr
== S_OK
, "got %#lx\n", hr
);
3747 IDirectMusicTrack_Release(track
);
3750 /* now play the segment, and check produced messages */
3752 hr
= IDirectMusicPerformance_Init(performance
, NULL
, 0, 0);
3753 ok(hr
== S_OK
, "got %#lx\n", hr
);
3755 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0x800, 0, NULL
);
3756 ok(hr
== S_OK
, "got %#lx\n", hr
);
3758 ret
= test_tool_wait_message(tool
, 500, &msg
);
3759 ok(!ret
, "got %#lx\n", ret
);
3760 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
3761 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3762 ok(hr
== S_OK
, "got %#lx\n", hr
);
3764 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)¬e
);
3765 ok(!ret
, "got %#lx\n", ret
);
3766 check_dmus_note_pmsg(note
, 0, 0, 500, 60, 120, DMUS_NOTEF_NOTEON
);
3767 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)note
);
3768 ok(hr
== S_OK
, "got %#lx\n", hr
);
3770 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)¬e
);
3771 ok(!ret
, "got %#lx\n", ret
);
3772 check_dmus_note_pmsg(note
, 1000, 1, 200, 50, 100, DMUS_NOTEF_NOTEON
);
3773 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)note
);
3774 ok(hr
== S_OK
, "got %#lx\n", hr
);
3776 ret
= test_tool_wait_message(tool
, 500, &msg
);
3777 ok(!ret
, "got %#lx\n", ret
);
3778 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
3779 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
3780 ok(hr
== S_OK
, "got %#lx\n", hr
);
3782 IDirectMusicSegment_Release(segment
);
3785 hr
= IDirectMusicPerformance_CloseDown(performance
);
3786 ok(hr
== S_OK
, "got %#lx\n", hr
);
3788 IDirectMusicPerformance_Release(performance
);
3789 IDirectMusicTool_Release(tool
);
3792 #define check_dmus_patch_pmsg(a, b, c, d, e) check_dmus_patch_pmsg_(__LINE__, a, b, c, d, e)
3793 static void check_dmus_patch_pmsg_(int line
, DMUS_PATCH_PMSG
*msg
, MUSIC_TIME time
, UINT chan
,
3794 UINT bank
, UINT patch
)
3796 ok_(__FILE__
, line
)(msg
->dwSize
== sizeof(*msg
), "got dwSize %lu\n", msg
->dwSize
);
3797 ok_(__FILE__
, line
)(msg
->rtTime
!= 0, "got rtTime %I64u\n", msg
->rtTime
);
3798 ok_(__FILE__
, line
)(abs(msg
->mtTime
- time
) < 10, "got mtTime %lu\n", msg
->mtTime
);
3799 ok_(__FILE__
, line
)(msg
->dwPChannel
== chan
, "got dwPChannel %lu\n", msg
->dwPChannel
);
3800 ok_(__FILE__
, line
)(!!msg
->dwVirtualTrackID
, "got dwVirtualTrackID %lu\n", msg
->dwVirtualTrackID
);
3801 ok_(__FILE__
, line
)(msg
->dwType
== DMUS_PMSGT_PATCH
, "got %#lx\n", msg
->dwType
);
3802 ok_(__FILE__
, line
)(!msg
->dwVoiceID
, "got dwVoiceID %lu\n", msg
->dwVoiceID
);
3803 ok_(__FILE__
, line
)(msg
->dwGroupID
== 1, "got dwGroupID %lu\n", msg
->dwGroupID
);
3804 ok_(__FILE__
, line
)(!msg
->punkUser
, "got punkUser %p\n", msg
->punkUser
);
3805 ok_(__FILE__
, line
)(msg
->byInstrument
== patch
, "got byInstrument %u\n", msg
->byInstrument
);
3806 ok_(__FILE__
, line
)(msg
->byMSB
== bank
>> 8, "got byMSB %u\n", msg
->byMSB
);
3807 ok_(__FILE__
, line
)(msg
->byLSB
== (bank
& 0xff), "got byLSB %u\n", msg
->byLSB
);
3810 static void test_band_track_play(void)
3812 static const DWORD message_types
[] =
3817 DMUS_PMSGT_NOTIFICATION
,
3822 DMUS_PMSGT_TRANSPOSE
,
3823 DMUS_PMSGT_CHANNEL_PRIORITY
,
3828 DMUS_PMSGT_SCRIPTLYRIC
,
3831 DMUS_OBJECTDESC desc
=
3833 .dwSize
= sizeof(DMUS_OBJECTDESC
),
3834 .dwValidData
= DMUS_OBJ_OBJECT
| DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH
,
3835 .guidClass
= CLSID_DirectMusicCollection
,
3836 .guidObject
= GUID_DefaultGMCollection
,
3837 .wszFileName
= L
"C:\\windows\\system32\\drivers\\gm.dls",
3839 static const LARGE_INTEGER zero
= {0};
3840 IDirectMusicPerformance
*performance
;
3841 IStream
*stream
, *loader_stream
;
3842 IDirectMusicSegment
*segment
;
3843 IDirectMusicLoader
*loader
;
3844 IDirectMusicGraph
*graph
;
3845 IDirectMusicTrack
*track
;
3846 IPersistStream
*persist
;
3847 IDirectMusicTool
*tool
;
3848 DMUS_PATCH_PMSG
*patch
;
3853 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
3854 ok(hr
== S_OK
, "got %#lx\n", hr
);
3856 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
3857 &IID_IDirectMusicPerformance
, (void **)&performance
);
3858 ok(hr
== S_OK
, "got %#lx\n", hr
);
3860 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
3861 &IID_IDirectMusicGraph
, (void **)&graph
);
3862 ok(hr
== S_OK
, "got %#lx\n", hr
);
3863 hr
= IDirectMusicGraph_InsertTool(graph
, (IDirectMusicTool
*)tool
, NULL
, 0, -1);
3864 ok(hr
== S_OK
, "got %#lx\n", hr
);
3865 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
3866 ok(hr
== S_OK
, "got %#lx\n", hr
);
3867 IDirectMusicGraph_Release(graph
);
3870 /* create a segment and load a simple RIFF stream */
3872 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
3873 &IID_IDirectMusicSegment
, (void **)&segment
);
3874 ok(hr
== S_OK
, "got %#lx\n", hr
);
3876 hr
= IDirectMusicSegment_QueryInterface(segment
, &IID_IPersistStream
, (void **)&persist
);
3877 ok(hr
== S_OK
, "got %#lx\n", hr
);
3878 hr
= CreateStreamOnHGlobal(0, TRUE
, &stream
);
3879 ok(hr
== S_OK
, "got %#lx\n", hr
);
3881 CHUNK_RIFF(stream
, "DMSG")
3883 /* set a non-zero segment length, or nothing will be played */
3884 DMUS_IO_SEGMENT_HEADER head
= {.mtLength
= 2000};
3885 CHUNK_DATA(stream
, "segh", head
);
3886 CHUNK_DATA(stream
, "guid", CLSID_DirectMusicSegment
);
3890 hr
= IStream_Seek(stream
, zero
, 0, NULL
);
3891 ok(hr
== S_OK
, "got %#lx\n", hr
);
3892 hr
= IPersistStream_Load(persist
, stream
);
3893 ok(hr
== S_OK
, "got %#lx\n", hr
);
3894 IPersistStream_Release(persist
);
3895 IStream_Release(stream
);
3898 /* add a sequence track to our segment */
3900 hr
= CoCreateInstance(&CLSID_DirectMusicBandTrack
, NULL
, CLSCTX_INPROC_SERVER
,
3901 &IID_IDirectMusicTrack
, (void **)&track
);
3902 ok(hr
== S_OK
, "got %#lx\n", hr
);
3904 hr
= IDirectMusicSegment_QueryInterface(track
, &IID_IPersistStream
, (void **)&persist
);
3905 ok(hr
== S_OK
, "got %#lx\n", hr
);
3906 hr
= CreateStreamOnHGlobal(0, TRUE
, &stream
);
3907 ok(hr
== S_OK
, "got %#lx\n", hr
);
3909 CHUNK_RIFF(stream
, "DMBT")
3911 DMUS_IO_BAND_TRACK_HEADER head
= {.bAutoDownload
= TRUE
};
3913 CHUNK_DATA(stream
, "bdth", head
);
3914 CHUNK_LIST(stream
, "lbdl")
3916 CHUNK_LIST(stream
, "lbnd")
3918 DMUS_IO_BAND_ITEM_HEADER head
= {.lBandTime
= 0};
3919 CHUNK_DATA(stream
, "bdih", head
);
3921 CHUNK_RIFF(stream
, "DMBD")
3923 GUID guid
= CLSID_DirectMusicBand
;
3924 CHUNK_DATA(stream
, "guid", guid
);
3926 CHUNK_LIST(stream
, "lbil")
3928 CHUNK_LIST(stream
, "lbin")
3930 DMUS_IO_INSTRUMENT head
= {.dwPatch
= 1, .dwPChannel
= 1, .dwFlags
= DMUS_IO_INST_PATCH
};
3931 CHUNK_DATA(stream
, "bins", head
);
3941 CHUNK_LIST(stream
, "lbnd")
3943 DMUS_IO_BAND_ITEM_HEADER head
= {.lBandTime
= 1000};
3944 CHUNK_DATA(stream
, "bdih", head
);
3946 CHUNK_RIFF(stream
, "DMBD")
3948 GUID guid
= CLSID_DirectMusicBand
;
3949 CHUNK_DATA(stream
, "guid", guid
);
3951 CHUNK_LIST(stream
, "lbil")
3953 CHUNK_LIST(stream
, "lbin")
3955 DMUS_IO_INSTRUMENT head
= {.dwPatch
= 2, .dwPChannel
= 1, .dwFlags
= DMUS_IO_INST_PATCH
};
3956 CHUNK_DATA(stream
, "bins", head
);
3960 CHUNK_LIST(stream
, "lbin")
3962 DMUS_IO_INSTRUMENT head
= {.dwPatch
= 3, .dwPChannel
= 2, .dwFlags
= DMUS_IO_INST_PATCH
};
3963 CHUNK_DATA(stream
, "bins", head
);
3977 hr
= IStream_Seek(stream
, zero
, 0, NULL
);
3978 ok(hr
== S_OK
, "got %#lx\n", hr
);
3980 /* band track requires the stream to implement IDirectMusicGetLoader */
3982 hr
= CoCreateInstance(&CLSID_DirectMusicLoader
, NULL
, CLSCTX_INPROC_SERVER
,
3983 &IID_IDirectMusicLoader8
, (void **)&loader
);
3984 ok(hr
== S_OK
, "got %#lx\n", hr
);
3985 hr
= IDirectMusicLoader_SetObject(loader
, &desc
);
3986 if (hr
== DMUS_E_LOADER_FAILEDOPEN
)
3987 skip("Failed to open gm.dls, missing system SoundFont?\n");
3989 ok(hr
== S_OK
, "got %#lx\n", hr
);
3991 hr
= test_loader_stream_create(stream
, loader
, &loader_stream
);
3992 ok(hr
== S_OK
, "got %#lx\n", hr
);
3993 IDirectMusicLoader8_Release(loader
);
3995 hr
= IPersistStream_Load(persist
, loader_stream
);
3996 ok(hr
== S_OK
, "got %#lx\n", hr
);
3997 IStream_Release(loader_stream
);
3999 IPersistStream_Release(persist
);
4000 IStream_Release(stream
);
4002 hr
= IDirectMusicSegment_InsertTrack(segment
, (IDirectMusicTrack
*)track
, 1);
4003 ok(hr
== S_OK
, "got %#lx\n", hr
);
4004 IDirectMusicTrack_Release(track
);
4007 /* now play the segment, and check produced messages */
4009 hr
= IDirectMusicPerformance_Init(performance
, NULL
, 0, 0);
4010 ok(hr
== S_OK
, "got %#lx\n", hr
);
4012 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0x800, 0, NULL
);
4013 ok(hr
== S_OK
, "got %#lx\n", hr
);
4015 ret
= test_tool_wait_message(tool
, 500, &msg
);
4016 ok(!ret
, "got %#lx\n", ret
);
4017 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
4018 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
4019 ok(hr
== S_OK
, "got %#lx\n", hr
);
4021 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)&patch
);
4022 ok(!ret
, "got %#lx\n", ret
);
4023 check_dmus_patch_pmsg(patch
, 0, 1, 0, 1);
4024 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)patch
);
4025 ok(hr
== S_OK
, "got %#lx\n", hr
);
4027 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)&patch
);
4028 ok(!ret
, "got %#lx\n", ret
);
4029 check_dmus_patch_pmsg(patch
, 1000, 2, 0, 3);
4030 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)patch
);
4031 ok(hr
== S_OK
, "got %#lx\n", hr
);
4033 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)&patch
);
4034 ok(!ret
, "got %#lx\n", ret
);
4035 check_dmus_patch_pmsg(patch
, 1000, 1, 0, 2);
4036 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)patch
);
4037 ok(hr
== S_OK
, "got %#lx\n", hr
);
4039 ret
= test_tool_wait_message(tool
, 500, &msg
);
4040 ok(!ret
, "got %#lx\n", ret
);
4041 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
4042 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
4043 ok(hr
== S_OK
, "got %#lx\n", hr
);
4045 IDirectMusicSegment_Release(segment
);
4048 hr
= IDirectMusicPerformance_CloseDown(performance
);
4049 ok(hr
== S_OK
, "got %#lx\n", hr
);
4051 IDirectMusicPerformance_Release(performance
);
4052 IDirectMusicTool_Release(tool
);
4055 #define check_dmus_tempo_pmsg(a, b, c) check_dmus_tempo_pmsg_(__LINE__, a, b, c)
4056 static void check_dmus_tempo_pmsg_(int line
, DMUS_TEMPO_PMSG
*msg
, MUSIC_TIME time
, double tempo
)
4058 ok_(__FILE__
, line
)(msg
->dwSize
== sizeof(*msg
), "got dwSize %lu\n", msg
->dwSize
);
4059 ok_(__FILE__
, line
)(msg
->rtTime
!= 0, "got rtTime %I64u\n", msg
->rtTime
);
4060 ok_(__FILE__
, line
)(abs(msg
->mtTime
- time
) < 10, "got mtTime %lu\n", msg
->mtTime
);
4061 ok_(__FILE__
, line
)(!msg
->dwPChannel
, "got dwPChannel %lu\n", msg
->dwPChannel
);
4062 ok_(__FILE__
, line
)(!!msg
->dwVirtualTrackID
, "got dwVirtualTrackID %lu\n", msg
->dwVirtualTrackID
);
4063 ok_(__FILE__
, line
)(msg
->dwType
== DMUS_PMSGT_TEMPO
, "got dwType %#lx\n", msg
->dwType
);
4064 ok_(__FILE__
, line
)(!msg
->dwVoiceID
, "got dwVoiceID %lu\n", msg
->dwVoiceID
);
4065 ok_(__FILE__
, line
)(msg
->dwGroupID
== -1, "got dwGroupID %lu\n", msg
->dwGroupID
);
4066 ok_(__FILE__
, line
)(!msg
->punkUser
, "got punkUser %p\n", msg
->punkUser
);
4067 ok_(__FILE__
, line
)(msg
->dblTempo
== tempo
, "got tempo %f\n", msg
->dblTempo
);
4070 static void test_tempo_track_play(void)
4072 static const DWORD message_types
[] =
4077 DMUS_PMSGT_NOTIFICATION
,
4082 DMUS_PMSGT_TRANSPOSE
,
4083 DMUS_PMSGT_CHANNEL_PRIORITY
,
4088 DMUS_PMSGT_SCRIPTLYRIC
,
4091 static const LARGE_INTEGER zero
= {0};
4092 DMUS_IO_TEMPO_ITEM tempo_items
[] =
4094 {.lTime
= 100, .dblTempo
= 80},
4095 {.lTime
= 300, .dblTempo
= 60},
4096 {.lTime
= 200, .dblTempo
= 20},
4097 {.lTime
= 4000, .dblTempo
= 50},
4099 IDirectMusicPerformance
*performance
;
4100 MUSIC_TIME music_time
, next_time
;
4101 REFERENCE_TIME init_time
, time
;
4102 IDirectMusicSegment
*segment
;
4103 IDirectMusicGraph
*graph
;
4104 IDirectMusicTrack
*track
;
4105 IPersistStream
*persist
;
4106 IDirectMusicTool
*tool
;
4107 DMUS_TEMPO_PMSG
*tempo
;
4108 DMUS_TEMPO_PARAM param
;
4114 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
4115 ok(hr
== S_OK
, "got %#lx\n", hr
);
4117 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
4118 &IID_IDirectMusicPerformance
, (void **)&performance
);
4119 ok(hr
== S_OK
, "got %#lx\n", hr
);
4121 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
4122 &IID_IDirectMusicGraph
, (void **)&graph
);
4123 ok(hr
== S_OK
, "got %#lx\n", hr
);
4124 hr
= IDirectMusicGraph_InsertTool(graph
, (IDirectMusicTool
*)tool
, NULL
, 0, -1);
4125 ok(hr
== S_OK
, "got %#lx\n", hr
);
4126 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
4127 ok(hr
== S_OK
, "got %#lx\n", hr
);
4128 IDirectMusicGraph_Release(graph
);
4131 /* create a segment and load a simple RIFF stream */
4133 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
4134 &IID_IDirectMusicSegment
, (void **)&segment
);
4135 ok(hr
== S_OK
, "got %#lx\n", hr
);
4137 hr
= IDirectMusicSegment_QueryInterface(segment
, &IID_IPersistStream
, (void **)&persist
);
4138 ok(hr
== S_OK
, "got %#lx\n", hr
);
4139 hr
= CreateStreamOnHGlobal(0, TRUE
, &stream
);
4140 ok(hr
== S_OK
, "got %#lx\n", hr
);
4142 CHUNK_RIFF(stream
, "DMSG")
4144 /* set a non-zero segment length, or nothing will be played */
4145 DMUS_IO_SEGMENT_HEADER head
= {.mtLength
= 1000};
4146 CHUNK_DATA(stream
, "segh", head
);
4147 CHUNK_DATA(stream
, "guid", CLSID_DirectMusicSegment
);
4151 hr
= IStream_Seek(stream
, zero
, 0, NULL
);
4152 ok(hr
== S_OK
, "got %#lx\n", hr
);
4153 hr
= IPersistStream_Load(persist
, stream
);
4154 ok(hr
== S_OK
, "got %#lx\n", hr
);
4155 IPersistStream_Release(persist
);
4156 IStream_Release(stream
);
4159 /* add a tempo track to our segment */
4161 hr
= CoCreateInstance(&CLSID_DirectMusicTempoTrack
, NULL
, CLSCTX_INPROC_SERVER
,
4162 &IID_IDirectMusicTrack
, (void **)&track
);
4163 ok(hr
== S_OK
, "got %#lx\n", hr
);
4165 hr
= IDirectMusicSegment_QueryInterface(track
, &IID_IPersistStream
, (void **)&persist
);
4166 ok(hr
== S_OK
, "got %#lx\n", hr
);
4167 hr
= CreateStreamOnHGlobal(0, TRUE
, &stream
);
4168 ok(hr
== S_OK
, "got %#lx\n", hr
);
4169 CHUNK_ARRAY(stream
, "tetr", tempo_items
);
4170 hr
= IStream_Seek(stream
, zero
, 0, NULL
);
4171 ok(hr
== S_OK
, "got %#lx\n", hr
);
4172 hr
= IPersistStream_Load(persist
, stream
);
4173 ok(hr
== S_OK
, "got %#lx\n", hr
);
4174 IPersistStream_Release(persist
);
4175 IStream_Release(stream
);
4177 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 0, NULL
, ¶m
);
4178 ok(hr
== DMUS_E_TRACK_NOT_FOUND
, "got %#lx\n", hr
);
4180 hr
= IDirectMusicSegment_InsertTrack(segment
, (IDirectMusicTrack
*)track
, 1);
4181 ok(hr
== S_OK
, "got %#lx\n", hr
);
4182 IDirectMusicTrack_Release(track
);
4184 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 0, NULL
, NULL
);
4185 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
4186 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 0, NULL
, ¶m
);
4187 ok(hr
== S_OK
, "got %#lx\n", hr
);
4189 memset(¶m
, 0xcd, sizeof(param
));
4190 next_time
= 0xdeadbeef;
4191 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 0, &next_time
, ¶m
);
4192 ok(hr
== S_OK
, "got %#lx\n", hr
);
4193 ok(next_time
== 100, "got next_time %lu\n", next_time
);
4194 ok(param
.mtTime
== 100, "got mtTime %ld\n", param
.mtTime
);
4195 ok(param
.dblTempo
== 80, "got dblTempo %f\n", param
.dblTempo
);
4196 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 100, &next_time
, ¶m
);
4197 ok(hr
== S_OK
, "got %#lx\n", hr
);
4198 ok(next_time
== 200, "got next_time %lu\n", next_time
);
4199 ok(param
.mtTime
== 0, "got mtTime %ld\n", param
.mtTime
);
4200 ok(param
.dblTempo
== 80, "got dblTempo %f\n", param
.dblTempo
);
4201 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 199, &next_time
, ¶m
);
4202 ok(hr
== S_OK
, "got %#lx\n", hr
);
4203 ok(next_time
== 101, "got next_time %lu\n", next_time
);
4204 ok(param
.mtTime
== -99, "got mtTime %ld\n", param
.mtTime
);
4205 ok(param
.dblTempo
== 80, "got dblTempo %f\n", param
.dblTempo
);
4206 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 200, &next_time
, ¶m
);
4207 ok(hr
== S_OK
, "got %#lx\n", hr
);
4208 ok(next_time
== 100, "got next_time %lu\n", next_time
);
4209 ok(param
.mtTime
== -100, "got mtTime %ld\n", param
.mtTime
);
4210 ok(param
.dblTempo
== 80, "got dblTempo %f\n", param
.dblTempo
);
4211 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 299, &next_time
, ¶m
);
4212 ok(hr
== S_OK
, "got %#lx\n", hr
);
4213 ok(next_time
== 1, "got next_time %lu\n", next_time
);
4214 ok(param
.mtTime
== -199, "got mtTime %ld\n", param
.mtTime
);
4215 ok(param
.dblTempo
== 80, "got dblTempo %f\n", param
.dblTempo
);
4216 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 300, &next_time
, ¶m
);
4217 ok(hr
== S_OK
, "got %#lx\n", hr
);
4218 ok(next_time
== 3700, "got next_time %lu\n", next_time
);
4219 ok(param
.mtTime
== -100, "got mtTime %ld\n", param
.mtTime
);
4220 ok(param
.dblTempo
== 20, "got dblTempo %f\n", param
.dblTempo
);
4221 hr
= IDirectMusicSegment_GetParam(segment
, &GUID_TempoParam
, -1, DMUS_SEG_ALLTRACKS
, 5000, &next_time
, ¶m
);
4222 ok(hr
== S_OK
, "got %#lx\n", hr
);
4223 ok(next_time
== 0, "got next_time %lu\n", next_time
);
4224 ok(param
.mtTime
== -1000, "got mtTime %ld\n", param
.mtTime
);
4225 ok(param
.dblTempo
== 50, "got dblTempo %f\n", param
.dblTempo
);
4228 /* now play the segment, and check produced messages */
4230 hr
= IDirectMusicPerformance_Init(performance
, NULL
, 0, 0);
4231 ok(hr
== S_OK
, "got %#lx\n", hr
);
4233 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0x800, 0, NULL
);
4234 ok(hr
== S_OK
, "got %#lx\n", hr
);
4236 /* the tempo track only takes effect after DMUS_PMSGT_DIRTY */
4238 ret
= test_tool_wait_message(tool
, 500, &msg
);
4239 ok(!ret
, "got %#lx\n", ret
);
4240 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
4241 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
4242 ok(hr
== S_OK
, "got %#lx\n", hr
);
4246 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 0, &time
);
4247 ok(hr
== S_OK
, "got %#lx\n", hr
);
4251 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 1, &time
);
4252 ok(hr
== S_OK
, "got %#lx\n", hr
);
4253 check_music_time(time
- init_time
, scale_music_time(1, 120));
4255 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 100, &time
);
4256 ok(hr
== S_OK
, "got %#lx\n", hr
);
4257 check_music_time(time
- init_time
, scale_music_time(100, 120));
4259 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 150, &time
);
4260 ok(hr
== S_OK
, "got %#lx\n", hr
);
4261 check_music_time(time
- init_time
, scale_music_time(100, 120) + scale_music_time(50, 80));
4263 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 200, &time
);
4264 ok(hr
== S_OK
, "got %#lx\n", hr
);
4265 check_music_time(time
- init_time
, scale_music_time(100, 120) + scale_music_time(100, 80));
4267 hr
= IDirectMusicPerformance_MusicToReferenceTime(performance
, 400, &time
);
4268 ok(hr
== S_OK
, "got %#lx\n", hr
);
4269 check_music_time(time
- init_time
, scale_music_time(100, 120) + scale_music_time(200, 80) + scale_music_time(100, 20));
4271 music_time
= 0xdeadbeef;
4272 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, init_time
, &music_time
);
4273 ok(hr
== S_OK
, "got %#lx\n", hr
);
4274 ok(music_time
== 0, "got %ld\n", music_time
);
4275 music_time
= 0xdeadbeef;
4276 time
= scale_music_time(100, 120) + scale_music_time(50, 80);
4277 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, init_time
+ time
, &music_time
);
4278 ok(hr
== S_OK
, "got %#lx\n", hr
);
4279 ok(music_time
== 150, "got %ld\n", music_time
);
4280 music_time
= 0xdeadbeef;
4281 time
= scale_music_time(100, 120) + scale_music_time(200, 80) + scale_music_time(100, 20);
4282 hr
= IDirectMusicPerformance_ReferenceToMusicTime(performance
, init_time
+ time
, &music_time
);
4283 ok(hr
== S_OK
, "got %#lx\n", hr
);
4284 ok(music_time
== 400, "got %ld\n", music_time
);
4287 ret
= test_tool_wait_message(tool
, 2000, (DMUS_PMSG
**)&tempo
);
4288 ok(!ret
, "got %#lx\n", ret
);
4289 todo_wine
ok(tempo
->dwType
== DMUS_PMSGT_TEMPO
, "got %#lx\n", tempo
->dwType
);
4290 if (tempo
->dwType
!= DMUS_PMSGT_TEMPO
) goto skip_tests
;
4291 check_dmus_tempo_pmsg(tempo
, 100, 80);
4292 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)tempo
);
4293 ok(hr
== S_OK
, "got %#lx\n", hr
);
4295 ret
= test_tool_wait_message(tool
, 500, (DMUS_PMSG
**)&tempo
);
4296 todo_wine
ok(!ret
, "got %#lx\n", ret
);
4297 check_dmus_tempo_pmsg(tempo
, 300, 60);
4298 hr
= IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)tempo
);
4299 ok(hr
== S_OK
, "got %#lx\n", hr
);
4301 ret
= test_tool_wait_message(tool
, 500, &msg
);
4302 todo_wine
ok(!ret
, "got %#lx\n", ret
);
4303 ok(msg
->dwType
== DMUS_PMSGT_DIRTY
, "got %#lx\n", msg
->dwType
);
4304 hr
= IDirectMusicPerformance_FreePMsg(performance
, msg
);
4305 ok(hr
== S_OK
, "got %#lx\n", hr
);
4308 IDirectMusicSegment_Release(segment
);
4311 hr
= IDirectMusicPerformance_CloseDown(performance
);
4312 ok(hr
== S_OK
, "got %#lx\n", hr
);
4314 IDirectMusicPerformance_Release(performance
);
4315 IDirectMusicTool_Release(tool
);
4318 static void test_connect_to_collection(void)
4320 IDirectMusicCollection
*collection
;
4321 IDirectMusicSegment
*segment
;
4322 IDirectMusicTrack
*track
;
4326 hr
= CoCreateInstance(&CLSID_DirectMusicCollection
, NULL
, CLSCTX_INPROC_SERVER
,
4327 &IID_IDirectMusicCollection
, (void **)&collection
);
4328 ok(hr
== S_OK
, "got %#lx\n", hr
);
4329 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
4330 &IID_IDirectMusicSegment
, (void **)&segment
);
4331 ok(hr
== S_OK
, "got %#lx\n", hr
);
4332 hr
= CoCreateInstance(&CLSID_DirectMusicBandTrack
, NULL
, CLSCTX_INPROC_SERVER
,
4333 &IID_IDirectMusicTrack
, (void **)&track
);
4334 ok(hr
== S_OK
, "got %#lx\n", hr
);
4336 hr
= IDirectMusicSegment_InsertTrack(segment
, track
, 1);
4337 ok(hr
== S_OK
, "got %#lx\n", hr
);
4339 /* it is possible to connect the band track to another collection, but not to disconnect it */
4340 hr
= IDirectMusicTrack_IsParamSupported(track
, &GUID_ConnectToDLSCollection
);
4341 ok(hr
== S_OK
, "got %#lx\n", hr
);
4343 hr
= IDirectMusicTrack_SetParam(track
, &GUID_ConnectToDLSCollection
, 0, NULL
);
4344 todo_wine
ok(hr
== E_POINTER
, "got %#lx\n", hr
);
4345 hr
= IDirectMusicTrack_SetParam(track
, &GUID_ConnectToDLSCollection
, 0, collection
);
4346 ok(hr
== S_OK
, "got %#lx\n", hr
);
4348 hr
= IDirectMusicTrack_GetParam(track
, &GUID_ConnectToDLSCollection
, 0, NULL
, NULL
);
4349 todo_wine
ok(hr
== E_POINTER
, "got %#lx\n", hr
);
4350 hr
= IDirectMusicTrack_GetParam(track
, &GUID_ConnectToDLSCollection
, 0, NULL
, ¶m
);
4351 ok(hr
== DMUS_E_GET_UNSUPPORTED
, "got %#lx\n", hr
);
4353 hr
= IDirectMusicSegment_SetParam(segment
, &GUID_ConnectToDLSCollection
, -1, DMUS_SEG_ALLTRACKS
, 0, NULL
);
4354 todo_wine
ok(hr
== E_POINTER
, "got %#lx\n", hr
);
4355 hr
= IDirectMusicSegment_SetParam(segment
, &GUID_ConnectToDLSCollection
, -1, DMUS_SEG_ALLTRACKS
, 0, collection
);
4356 ok(hr
== S_OK
, "got %#lx\n", hr
);
4358 IDirectMusicTrack_Release(track
);
4359 IDirectMusicSegment_Release(segment
);
4360 IDirectMusicCollection_Release(collection
);
4363 static void test_segment_state(void)
4365 static const DWORD message_types
[] =
4368 DMUS_PMSGT_NOTIFICATION
,
4371 IDirectMusicSegmentState
*state
, *tmp_state
;
4372 IDirectMusicSegment
*segment
, *tmp_segment
;
4373 IDirectMusicPerformance
*performance
;
4374 IDirectMusicTrack
*track
;
4375 IDirectMusicGraph
*graph
;
4376 IDirectMusicTool
*tool
;
4381 hr
= test_tool_create(message_types
, ARRAY_SIZE(message_types
), &tool
);
4382 ok(hr
== S_OK
, "got %#lx\n", hr
);
4383 hr
= test_track_create(&track
, TRUE
);
4384 ok(hr
== S_OK
, "got %#lx\n", hr
);
4386 hr
= CoCreateInstance(&CLSID_DirectMusicPerformance
, NULL
, CLSCTX_INPROC_SERVER
,
4387 &IID_IDirectMusicPerformance
, (void **)&performance
);
4388 ok(hr
== S_OK
, "got %#lx\n", hr
);
4390 hr
= CoCreateInstance(&CLSID_DirectMusicGraph
, NULL
, CLSCTX_INPROC_SERVER
,
4391 &IID_IDirectMusicGraph
, (void **)&graph
);
4392 ok(hr
== S_OK
, "got %#lx\n", hr
);
4393 hr
= IDirectMusicPerformance_SetGraph(performance
, graph
);
4394 ok(hr
== S_OK
, "got %#lx\n", hr
);
4395 hr
= IDirectMusicGraph_InsertTool(graph
, tool
, NULL
, 0, -1);
4396 ok(hr
== S_OK
, "got %#lx\n", hr
);
4397 IDirectMusicGraph_Release(graph
);
4400 hr
= CoCreateInstance(&CLSID_DirectMusicSegment
, NULL
, CLSCTX_INPROC_SERVER
,
4401 &IID_IDirectMusicSegment
, (void **)&segment
);
4402 ok(hr
== S_OK
, "got %#lx\n", hr
);
4404 check_track_state(track
, inserted
, FALSE
);
4405 hr
= IDirectMusicSegment_InsertTrack(segment
, track
, 1);
4406 ok(hr
== S_OK
, "got %#lx\n", hr
);
4407 check_track_state(track
, inserted
, TRUE
);
4409 check_track_state(track
, downloaded
, FALSE
);
4410 hr
= IDirectMusicSegment8_Download((IDirectMusicSegment8
*)segment
, (IUnknown
*)performance
);
4411 ok(hr
== S_OK
, "got %#lx\n", hr
);
4412 check_track_state(track
, downloaded
, TRUE
);
4413 hr
= IDirectMusicSegment8_Unload((IDirectMusicSegment8
*)segment
, (IUnknown
*)performance
);
4414 ok(hr
== S_OK
, "got %#lx\n", hr
);
4415 check_track_state(track
, downloaded
, FALSE
);
4418 /* by default the segment length is 1 */
4421 hr
= IDirectMusicSegment_GetLength(segment
, &time
);
4422 ok(hr
== S_OK
, "got %#lx\n", hr
);
4423 todo_wine
ok(time
== 1, "got %lu\n", time
);
4424 hr
= IDirectMusicSegment_SetStartPoint(segment
, 50);
4425 ok(hr
== DMUS_E_OUT_OF_RANGE
, "got %#lx\n", hr
);
4426 hr
= IDirectMusicSegment_SetRepeats(segment
, 10);
4427 ok(hr
== S_OK
, "got %#lx\n", hr
);
4428 hr
= IDirectMusicSegment_SetLoopPoints(segment
, 10, 70);
4429 ok(hr
== DMUS_E_OUT_OF_RANGE
, "got %#lx\n", hr
);
4431 /* Setting a larger length will cause PlayEx to be called multiple times,
4432 * as native splits the segment into chunks and play each chunk separately */
4433 hr
= IDirectMusicSegment_SetLength(segment
, 100);
4434 ok(hr
== S_OK
, "got %#lx\n", hr
);
4435 hr
= IDirectMusicSegment_SetStartPoint(segment
, 50);
4436 ok(hr
== S_OK
, "got %#lx\n", hr
);
4437 hr
= IDirectMusicSegment_SetRepeats(segment
, 0);
4438 ok(hr
== S_OK
, "got %#lx\n", hr
);
4439 hr
= IDirectMusicSegment_SetLoopPoints(segment
, 0, 0);
4440 ok(hr
== S_OK
, "got %#lx\n", hr
);
4443 /* InitPlay returns a dummy segment state */
4445 state
= (void *)0xdeadbeef;
4446 hr
= IDirectMusicSegment_InitPlay(segment
, &state
, performance
, 0);
4447 ok(hr
== S_OK
, "got %#lx\n", hr
);
4448 ok(state
!= NULL
, "got %p\n", state
);
4449 ok(state
!= (void *)0xdeadbeef, "got %p\n", state
);
4450 check_track_state(track
, initialized
, FALSE
);
4452 tmp_segment
= (void *)0xdeadbeef;
4453 hr
= IDirectMusicSegmentState_GetSegment(state
, &tmp_segment
);
4454 ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
4455 ok(tmp_segment
== NULL
, "got %p\n", tmp_segment
);
4457 hr
= IDirectMusicSegmentState_GetStartPoint(state
, &time
);
4458 ok(hr
== S_OK
, "got %#lx\n", hr
);
4459 ok(time
== 0, "got %#lx\n", time
);
4461 hr
= IDirectMusicSegmentState_GetRepeats(state
, &value
);
4462 ok(hr
== S_OK
, "got %#lx\n", hr
);
4463 ok(time
== 0xdeadbeef, "got %#lx\n", time
);
4465 hr
= IDirectMusicSegmentState_GetStartTime(state
, &time
);
4466 ok(hr
== S_OK
, "got %#lx\n", hr
);
4467 ok(time
== -1, "got %#lx\n", time
);
4469 hr
= IDirectMusicSegmentState_GetSeek(state
, &time
);
4470 ok(hr
== S_OK
, "got %#lx\n", hr
);
4471 ok(time
== 0, "got %#lx\n", time
);
4474 /* PlaySegment returns a different, genuine segment state */
4476 hr
= IDirectMusicPerformance_Init(performance
, NULL
, 0, 0);
4477 ok(hr
== S_OK
, "got %#lx\n", hr
);
4479 check_track_state(track
, downloaded
, FALSE
);
4480 check_track_state(track
, initialized
, FALSE
);
4481 check_track_state(track
, playing
, FALSE
);
4483 hr
= IDirectMusicPerformance_GetSegmentState(performance
, NULL
, 0);
4484 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
4485 hr
= IDirectMusicPerformance_GetSegmentState(performance
, &tmp_state
, 0);
4486 ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
4490 state
= (void *)0xdeadbeef;
4491 hr
= IDirectMusicPerformance_PlaySegment(performance
, segment
, 0, 20, &state
);
4492 ok(hr
== S_OK
, "got %#lx\n", hr
);
4493 ok(state
!= NULL
, "got %p\n", state
);
4494 ok(state
!= (void *)0xdeadbeef, "got %p\n", state
);
4495 ok(state
!= tmp_state
, "got %p\n", state
);
4496 IDirectMusicSegmentState_Release(tmp_state
);
4498 tmp_state
= (void *)0xdeadbeef;
4499 hr
= IDirectMusicPerformance_GetSegmentState(performance
, &tmp_state
, 0);
4500 ok(hr
== S_OK
, "got %#lx\n", hr
);
4501 ok(state
== tmp_state
, "got %p\n", state
);
4502 IDirectMusicSegmentState_Release(tmp_state
);
4504 tmp_state
= (void *)0xdeadbeef;
4505 hr
= IDirectMusicPerformance_GetSegmentState(performance
, &tmp_state
, 69);
4506 ok(hr
== S_OK
, "got %#lx\n", hr
);
4507 ok(state
== tmp_state
, "got %p\n", state
);
4508 IDirectMusicSegmentState_Release(tmp_state
);
4510 hr
= IDirectMusicPerformance_GetSegmentState(performance
, &tmp_state
, 70);
4511 todo_wine
ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
4514 check_track_state(track
, downloaded
, FALSE
);
4515 check_track_state(track
, initialized
, TRUE
);
4518 /* The track can be removed from the segment */
4519 hr
= IDirectMusicSegment_RemoveTrack(segment
, track
);
4520 ok(hr
== S_OK
, "got %#lx\n", hr
);
4523 ret
= test_track_wait_playing(track
, 50);
4524 ok(ret
== 0, "got %#lx\n", ret
);
4526 hr
= IDirectMusicPerformance_GetSegmentState(performance
, &tmp_state
, 0);
4527 todo_wine
ok(hr
== DMUS_E_NOT_FOUND
, "got %#lx\n", hr
);
4530 tmp_segment
= (void *)0xdeadbeef;
4531 hr
= IDirectMusicSegmentState_GetSegment(state
, &tmp_segment
);
4532 ok(hr
== S_OK
, "got %#lx\n", hr
);
4533 ok(tmp_segment
== segment
, "got %p\n", tmp_segment
);
4534 IDirectMusicSegment_Release(tmp_segment
);
4537 hr
= IDirectMusicSegmentState_GetStartPoint(state
, &time
);
4538 ok(hr
== S_OK
, "got %#lx\n", hr
);
4539 ok(time
== 50, "got %lu\n", time
);
4541 hr
= IDirectMusicSegmentState_GetRepeats(state
, &value
);
4542 ok(hr
== S_OK
, "got %#lx\n", hr
);
4543 ok(time
== 0xdeadbeef, "got %#lx\n", time
);
4545 hr
= IDirectMusicSegmentState_GetStartTime(state
, &time
);
4546 ok(hr
== S_OK
, "got %#lx\n", hr
);
4547 ok(time
== 20, "got %#lx\n", time
);
4550 /* The seek value is also dependent on whether the tracks are playing.
4551 * It is initially 0, then start_point right before playing, then length.
4553 hr
= IDirectMusicSegmentState_GetSeek(state
, &time
);
4554 ok(hr
== S_OK
, "got %#lx\n", hr
);
4555 todo_wine
ok(time
== 100, "got %#lx\n", time
);
4557 /* changing the segment values doesn't change the segment state */
4559 hr
= IDirectMusicSegment_SetStartPoint(segment
, 0);
4560 ok(hr
== S_OK
, "got %#lx\n", hr
);
4561 hr
= IDirectMusicSegment_SetRepeats(segment
, 10);
4562 ok(hr
== S_OK
, "got %#lx\n", hr
);
4563 hr
= IDirectMusicSegment_SetLoopPoints(segment
, 50, 70);
4564 ok(hr
== S_OK
, "got %#lx\n", hr
);
4567 hr
= IDirectMusicSegmentState_GetStartPoint(state
, &time
);
4568 ok(hr
== S_OK
, "got %#lx\n", hr
);
4569 ok(time
== 50, "got %#lx\n", time
);
4571 hr
= IDirectMusicSegmentState_GetRepeats(state
, &value
);
4572 ok(hr
== S_OK
, "got %#lx\n", hr
);
4573 ok(time
== 0xdeadbeef, "got %#lx\n", time
);
4575 hr
= IDirectMusicSegmentState_GetStartTime(state
, &time
);
4576 ok(hr
== S_OK
, "got %#lx\n", hr
);
4577 ok(time
== 20, "got %#lx\n", time
);
4579 hr
= IDirectMusicSegmentState_GetSeek(state
, &time
);
4580 ok(hr
== S_OK
, "got %#lx\n", hr
);
4581 todo_wine
ok(time
== 100, "got %#lx\n", time
);
4583 IDirectMusicSegment_Release(segment
);
4586 check_track_state(track
, downloaded
, FALSE
);
4587 check_track_state(track
, initialized
, TRUE
);
4588 check_track_state(track
, playing
, TRUE
);
4590 hr
= IDirectMusicPerformance_CloseDown(performance
);
4591 ok(hr
== S_OK
, "got %#lx\n", hr
);
4593 check_track_state(track
, downloaded
, FALSE
);
4594 check_track_state(track
, initialized
, TRUE
);
4595 check_track_state(track
, playing
, FALSE
);
4598 IDirectMusicPerformance_Release(performance
);
4599 IDirectMusicTrack_Release(track
);
4600 IDirectMusicTool_Release(tool
);
4607 if (missing_dmime())
4609 skip("dmime not available\n");
4613 test_COM_audiopath();
4614 test_COM_audiopathconfig();
4617 test_COM_segmentstate();
4619 test_COM_performance();
4620 test_audiopathconfig();
4624 test_segment_param();
4626 test_parsedescriptor();
4627 test_performance_InitAudio();
4628 test_performance_createport();
4629 test_performance_pchannel();
4630 test_performance_tool();
4631 test_performance_graph();
4632 test_performance_time();
4633 test_performance_pmsg();
4634 test_notification_pmsg();
4636 test_sequence_track();
4637 test_band_track_play();
4638 test_tempo_track_play();
4639 test_connect_to_collection();
4640 test_segment_state();