1 /* IDirectMusicPerformance Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2003-2004 Raphael Junqueira
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "dmime_private.h"
22 #include "wine/heap.h"
23 #include "wine/rbtree.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dmime
);
28 struct pchannel_block
{
29 DWORD block_num
; /* Block 0 is PChannels 0-15, Block 1 is PChannels 16-31, etc */
31 DWORD channel
; /* MIDI channel */
32 DWORD group
; /* MIDI group */
33 IDirectMusicPort
*port
;
35 struct wine_rb_entry entry
;
38 typedef struct IDirectMusicPerformance8Impl
{
39 IDirectMusicPerformance8 IDirectMusicPerformance8_iface
;
41 IDirectMusic8
*dmusic
;
43 IDirectMusicGraph
*pToolGraph
;
44 DMUS_AUDIOPARAMS params
;
46 char cMasterGrooveLevel
;
49 /* performance channels */
50 struct wine_rb_tree pchannels
;
51 /* IDirectMusicPerformance8Impl fields */
52 IDirectMusicAudioPath
*pDefaultPath
;
54 REFERENCE_TIME rtMinimum
;
55 REFERENCE_TIME rtLatencyTime
;
58 /** Message Processing */
61 REFERENCE_TIME procThreadStartTime
;
62 BOOL procThreadTicStarted
;
63 CRITICAL_SECTION safe
;
64 struct DMUS_PMSGItem
*head
;
65 struct DMUS_PMSGItem
*imm_head
;
66 } IDirectMusicPerformance8Impl
;
68 typedef struct DMUS_PMSGItem DMUS_PMSGItem
;
69 struct DMUS_PMSGItem
{
73 REFERENCE_TIME rtItemTime
;
79 #define DMUS_PMSGToItem(pMSG) ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) - offsetof(DMUS_PMSGItem, pMsg)))
80 #define DMUS_ItemToPMSG(pItem) (&(pItem->pMsg))
81 #define DMUS_ItemRemoveFromQueue(This,pItem) \
83 if (pItem->prev) pItem->prev->next = pItem->next;\
84 if (pItem->next) pItem->next->prev = pItem->prev;\
85 if (This->head == pItem) This->head = pItem->next;\
86 if (This->imm_head == pItem) This->imm_head = pItem->next;\
87 pItem->bInUse = FALSE;\
90 #define PROCESSMSG_START (WM_APP + 0)
91 #define PROCESSMSG_EXIT (WM_APP + 1)
92 #define PROCESSMSG_REMOVE (WM_APP + 2)
93 #define PROCESSMSG_ADD (WM_APP + 4)
96 static DMUS_PMSGItem
* ProceedMsg(IDirectMusicPerformance8Impl
* This
, DMUS_PMSGItem
* cur
) {
97 if (cur
->pMsg
.dwType
== DMUS_PMSGT_NOTIFICATION
) {
98 SetEvent(This
->hNotification
);
100 DMUS_ItemRemoveFromQueue(This
, cur
);
101 switch (cur
->pMsg
.dwType
) {
102 case DMUS_PMSGT_WAVE
:
103 case DMUS_PMSGT_TEMPO
:
104 case DMUS_PMSGT_STOP
:
106 FIXME("Unhandled PMsg Type: 0x%x\n", cur
->pMsg
.dwType
);
112 static DWORD WINAPI
ProcessMsgThread(LPVOID lpParam
) {
113 IDirectMusicPerformance8Impl
* This
= lpParam
;
114 DWORD timeOut
= INFINITE
;
117 REFERENCE_TIME rtCurTime
;
118 DMUS_PMSGItem
* it
= NULL
;
119 DMUS_PMSGItem
* cur
= NULL
;
120 DMUS_PMSGItem
* it_next
= NULL
;
123 DWORD dwDec
= This
->rtLatencyTime
+ This
->dwBumperLength
;
125 if (timeOut
> 0) MsgWaitForMultipleObjects(0, NULL
, FALSE
, timeOut
, QS_POSTMESSAGE
|QS_SENDMESSAGE
|QS_TIMER
);
128 EnterCriticalSection(&This
->safe
);
129 hr
= IDirectMusicPerformance8_GetTime(&This
->IDirectMusicPerformance8_iface
, &rtCurTime
, NULL
);
134 for (it
= This
->imm_head
; NULL
!= it
; ) {
136 cur
= ProceedMsg(This
, it
);
137 HeapFree(GetProcessHeap(), 0, cur
);
141 for (it
= This
->head
; NULL
!= it
&& it
->rtItemTime
< rtCurTime
+ dwDec
; ) {
143 cur
= ProceedMsg(This
, it
);
144 HeapFree(GetProcessHeap(), 0, cur
);
148 timeOut
= ( it
->rtItemTime
- rtCurTime
) + This
->rtLatencyTime
;
152 LeaveCriticalSection(&This
->safe
);
154 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
)) {
155 /** if hwnd we suppose that is a windows event ... */
156 if (NULL
!= msg
.hwnd
) {
157 TranslateMessage(&msg
);
158 DispatchMessageA(&msg
);
160 switch (msg
.message
) {
162 case PROCESSMSG_EXIT
:
164 case PROCESSMSG_START
:
168 case PROCESSMSG_REMOVE
:
171 ERR("Unhandled message %u. Critical Path\n", msg
.message
);
177 /** here we should run a little of current AudioPath */
182 TRACE("(%p): Exiting\n", This
);
187 static BOOL
PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl
* This
, UINT iMsg
) {
188 if (FALSE
== This
->procThreadTicStarted
&& PROCESSMSG_EXIT
!= iMsg
) {
190 This
->procThread
= CreateThread(NULL
, 0, ProcessMsgThread
, This
, 0, &This
->procThreadId
);
191 if (NULL
== This
->procThread
) return FALSE
;
192 SetThreadPriority(This
->procThread
, THREAD_PRIORITY_TIME_CRITICAL
);
193 This
->procThreadTicStarted
= TRUE
;
195 res
= PostThreadMessageA(This
->procThreadId
, iMsg
, 0, 0);
196 /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
197 if (!res
&& (GetLastError() == ERROR_INVALID_THREAD_ID
))
204 return PostThreadMessageA(This
->procThreadId
, iMsg
, 0, 0);
207 static int pchannel_block_compare(const void *key
, const struct wine_rb_entry
*entry
)
209 const struct pchannel_block
*b
= WINE_RB_ENTRY_VALUE(entry
, const struct pchannel_block
, entry
);
211 return *(DWORD
*)key
- b
->block_num
;
214 static void pchannel_block_free(struct wine_rb_entry
*entry
, void *context
)
216 struct pchannel_block
*b
= WINE_RB_ENTRY_VALUE(entry
, struct pchannel_block
, entry
);
221 static struct pchannel_block
*pchannel_block_set(struct wine_rb_tree
*tree
, DWORD block_num
,
222 IDirectMusicPort
*port
, DWORD group
, BOOL only_set_new
)
224 struct pchannel_block
*block
;
225 struct wine_rb_entry
*entry
;
228 entry
= wine_rb_get(tree
, &block_num
);
230 block
= WINE_RB_ENTRY_VALUE(entry
, struct pchannel_block
, entry
);
234 if (!(block
= heap_alloc(sizeof(*block
))))
236 block
->block_num
= block_num
;
239 for (i
= 0; i
< 16; ++i
) {
240 block
->pchannel
[i
].port
= port
;
241 block
->pchannel
[i
].group
= group
;
242 block
->pchannel
[i
].channel
= i
;
245 wine_rb_put(tree
, &block
->block_num
, &block
->entry
);
250 static inline IDirectMusicPerformance8Impl
*impl_from_IDirectMusicPerformance8(IDirectMusicPerformance8
*iface
)
252 return CONTAINING_RECORD(iface
, IDirectMusicPerformance8Impl
, IDirectMusicPerformance8_iface
);
255 /* IDirectMusicPerformance8 IUnknown part: */
256 static HRESULT WINAPI
IDirectMusicPerformance8Impl_QueryInterface(IDirectMusicPerformance8
*iface
,
257 REFIID riid
, void **ppv
)
259 TRACE("(%p, %s,%p)\n", iface
, debugstr_dmguid(riid
), ppv
);
261 if (IsEqualIID (riid
, &IID_IUnknown
) ||
262 IsEqualIID (riid
, &IID_IDirectMusicPerformance
) ||
263 IsEqualIID (riid
, &IID_IDirectMusicPerformance2
) ||
264 IsEqualIID (riid
, &IID_IDirectMusicPerformance8
)) {
266 IUnknown_AddRef(iface
);
270 WARN("(%p, %s,%p): not found\n", iface
, debugstr_dmguid(riid
), ppv
);
271 return E_NOINTERFACE
;
274 static ULONG WINAPI
IDirectMusicPerformance8Impl_AddRef(IDirectMusicPerformance8
*iface
)
276 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
277 ULONG ref
= InterlockedIncrement(&This
->ref
);
279 TRACE("(%p): AddRef from %d\n", This
, ref
- 1);
286 static ULONG WINAPI
IDirectMusicPerformance8Impl_Release(IDirectMusicPerformance8
*iface
)
288 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
289 ULONG ref
= InterlockedDecrement(&This
->ref
);
291 TRACE("(%p): ReleaseRef to %d\n", This
, ref
);
294 wine_rb_destroy(&This
->pchannels
, pchannel_block_free
, NULL
);
295 This
->safe
.DebugInfo
->Spare
[0] = 0;
296 DeleteCriticalSection(&This
->safe
);
297 HeapFree(GetProcessHeap(), 0, This
);
300 DMIME_UnlockModule();
305 /* IDirectMusicPerformanceImpl IDirectMusicPerformance Interface part: */
306 static HRESULT WINAPI
IDirectMusicPerformance8Impl_Init(IDirectMusicPerformance8
*iface
,
307 IDirectMusic
**dmusic
, IDirectSound
*dsound
, HWND hwnd
)
309 TRACE("(%p, %p, %p, %p)\n", iface
, dmusic
, dsound
, hwnd
);
311 return IDirectMusicPerformance8_InitAudio(iface
, dmusic
, dsound
? &dsound
: NULL
, hwnd
, 0, 0,
315 static HRESULT WINAPI
IDirectMusicPerformance8Impl_PlaySegment(IDirectMusicPerformance8
*iface
,
316 IDirectMusicSegment
*pSegment
, DWORD dwFlags
, __int64 i64StartTime
,
317 IDirectMusicSegmentState
**ppSegmentState
)
319 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
321 FIXME("(%p, %p, %d, 0x%s, %p): stub\n", This
, pSegment
, dwFlags
,
322 wine_dbgstr_longlong(i64StartTime
), ppSegmentState
);
324 return create_dmsegmentstate(&IID_IDirectMusicSegmentState
,(void**)ppSegmentState
);
328 static HRESULT WINAPI
IDirectMusicPerformance8Impl_Stop(IDirectMusicPerformance8
*iface
,
329 IDirectMusicSegment
*pSegment
, IDirectMusicSegmentState
*pSegmentState
, MUSIC_TIME mtTime
,
332 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
334 FIXME("(%p, %p, %p, %d, %d): stub\n", This
, pSegment
, pSegmentState
, mtTime
, dwFlags
);
338 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetSegmentState(IDirectMusicPerformance8
*iface
,
339 IDirectMusicSegmentState
**ppSegmentState
, MUSIC_TIME mtTime
)
341 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
343 FIXME("(%p,%p, %d): stub\n", This
, ppSegmentState
, mtTime
);
347 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetPrepareTime(IDirectMusicPerformance8
*iface
,
348 DWORD dwMilliSeconds
)
350 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
352 TRACE("(%p, %d)\n", This
, dwMilliSeconds
);
353 This
->dwPrepareTime
= dwMilliSeconds
;
357 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetPrepareTime(IDirectMusicPerformance8
*iface
,
358 DWORD
*pdwMilliSeconds
)
360 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
362 TRACE("(%p, %p)\n", This
, pdwMilliSeconds
);
363 if (NULL
== pdwMilliSeconds
) {
366 *pdwMilliSeconds
= This
->dwPrepareTime
;
370 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetBumperLength(IDirectMusicPerformance8
*iface
,
371 DWORD dwMilliSeconds
)
373 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
375 TRACE("(%p, %d)\n", This
, dwMilliSeconds
);
376 This
->dwBumperLength
= dwMilliSeconds
;
380 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetBumperLength(IDirectMusicPerformance8
*iface
,
381 DWORD
*pdwMilliSeconds
)
383 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
385 TRACE("(%p, %p)\n", This
, pdwMilliSeconds
);
386 if (NULL
== pdwMilliSeconds
) {
389 *pdwMilliSeconds
= This
->dwBumperLength
;
393 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SendPMsg(IDirectMusicPerformance8
*iface
,
396 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
397 DMUS_PMSGItem
* pItem
= NULL
;
398 DMUS_PMSGItem
* it
= NULL
;
399 DMUS_PMSGItem
* prev_it
= NULL
;
400 DMUS_PMSGItem
** queue
= NULL
;
402 FIXME("(%p, %p): stub\n", This
, pPMSG
);
407 pItem
= DMUS_PMSGToItem(pPMSG
);
409 return DMUS_E_ALREADY_SENT
;
412 /* TODO: Valid Flags */
413 /* TODO: DMUS_PMSGF_MUSICTIME */
414 pItem
->rtItemTime
= pPMSG
->rtTime
;
416 if (pPMSG
->dwFlags
& DMUS_PMSGF_TOOL_IMMEDIATE
) {
417 queue
= &This
->imm_head
;
422 EnterCriticalSection(&This
->safe
);
423 for (it
= *queue
; NULL
!= it
&& it
->rtItemTime
< pItem
->rtItemTime
; it
= it
->next
) {
426 if (NULL
== prev_it
) {
428 if (NULL
!= *queue
) pItem
->next
= (*queue
)->next
;
429 /*assert( NULL == pItem->next->prev );*/
430 if (NULL
!= pItem
->next
) pItem
->next
->prev
= pItem
;
433 pItem
->prev
= prev_it
;
434 pItem
->next
= prev_it
->next
;
435 prev_it
->next
= pItem
;
436 if (NULL
!= pItem
->next
) pItem
->next
->prev
= pItem
;
438 LeaveCriticalSection(&This
->safe
);
440 /** now in use, prevent from stupid Frees */
441 pItem
->bInUse
= TRUE
;
445 static HRESULT WINAPI
IDirectMusicPerformance8Impl_MusicToReferenceTime(IDirectMusicPerformance8
*iface
,
446 MUSIC_TIME mtTime
, REFERENCE_TIME
*prtTime
)
448 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
450 FIXME("(%p, %d, %p): stub\n", This
, mtTime
, prtTime
);
454 static HRESULT WINAPI
IDirectMusicPerformance8Impl_ReferenceToMusicTime(IDirectMusicPerformance8
*iface
,
455 REFERENCE_TIME rtTime
, MUSIC_TIME
*pmtTime
)
457 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
459 FIXME("(%p, 0x%s, %p): stub\n", This
, wine_dbgstr_longlong(rtTime
), pmtTime
);
463 static HRESULT WINAPI
IDirectMusicPerformance8Impl_IsPlaying(IDirectMusicPerformance8
*iface
,
464 IDirectMusicSegment
*pSegment
, IDirectMusicSegmentState
*pSegState
)
466 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
468 FIXME("(%p, %p, %p): stub\n", This
, pSegment
, pSegState
);
472 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetTime(IDirectMusicPerformance8
*iface
,
473 REFERENCE_TIME
*prtNow
, MUSIC_TIME
*pmtNow
)
475 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
477 REFERENCE_TIME rtCur
= 0;
479 /*TRACE("(%p, %p, %p)\n", This, prtNow, pmtNow); */
480 if (This
->procThreadTicStarted
) {
481 rtCur
= ((REFERENCE_TIME
) GetTickCount() * 10000) - This
->procThreadStartTime
;
483 /*return DMUS_E_NO_MASTER_CLOCK;*/
485 if (NULL
!= prtNow
) {
488 if (NULL
!= pmtNow
) {
489 hr
= IDirectMusicPerformance8_ReferenceToMusicTime(iface
, rtCur
, pmtNow
);
494 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AllocPMsg(IDirectMusicPerformance8
*iface
,
495 ULONG cb
, DMUS_PMSG
**ppPMSG
)
497 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
498 DMUS_PMSGItem
* pItem
= NULL
;
500 FIXME("(%p, %d, %p): stub\n", This
, cb
, ppPMSG
);
502 if (sizeof(DMUS_PMSG
) > cb
) {
505 if (NULL
== ppPMSG
) {
508 pItem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cb
- sizeof(DMUS_PMSG
) + sizeof(DMUS_PMSGItem
));
510 return E_OUTOFMEMORY
;
512 pItem
->pMsg
.dwSize
= cb
;
513 *ppPMSG
= DMUS_ItemToPMSG(pItem
);
517 static HRESULT WINAPI
IDirectMusicPerformance8Impl_FreePMsg(IDirectMusicPerformance8
*iface
,
520 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
521 DMUS_PMSGItem
* pItem
= NULL
;
523 FIXME("(%p, %p): stub\n", This
, pPMSG
);
528 pItem
= DMUS_PMSGToItem(pPMSG
);
530 /** prevent for freeing PMsg in queue (ie to be processed) */
531 return DMUS_E_CANNOT_FREE
;
533 /** now we can remove it safely */
534 EnterCriticalSection(&This
->safe
);
535 DMUS_ItemRemoveFromQueue( This
, pItem
);
536 LeaveCriticalSection(&This
->safe
);
539 IDirectMusicTool_Release(pPMSG
->pTool
);
542 IDirectMusicGraph_Release(pPMSG
->pGraph
);
545 IUnknown_Release(pPMSG
->punkUser
);
547 HeapFree(GetProcessHeap(), 0, pItem
);
551 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetGraph(IDirectMusicPerformance8
*iface
,
552 IDirectMusicGraph
**graph
)
554 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
556 TRACE("(%p, %p)\n", This
, graph
);
561 *graph
= This
->pToolGraph
;
562 if (This
->pToolGraph
) {
563 IDirectMusicGraph_AddRef(*graph
);
566 return *graph
? S_OK
: DMUS_E_NOT_FOUND
;
569 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetGraph(IDirectMusicPerformance8
*iface
,
570 IDirectMusicGraph
*pGraph
)
572 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
574 FIXME("(%p, %p): to check\n", This
, pGraph
);
576 if (NULL
!= This
->pToolGraph
) {
577 /* Todo clean buffers and tools before */
578 IDirectMusicGraph_Release(This
->pToolGraph
);
580 This
->pToolGraph
= pGraph
;
581 if (NULL
!= This
->pToolGraph
) {
582 IDirectMusicGraph_AddRef(This
->pToolGraph
);
587 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetNotificationHandle(IDirectMusicPerformance8
*iface
,
588 HANDLE hNotification
, REFERENCE_TIME rtMinimum
)
590 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
592 TRACE("(%p, %p, 0x%s)\n", This
, hNotification
, wine_dbgstr_longlong(rtMinimum
));
594 This
->hNotification
= hNotification
;
596 This
->rtMinimum
= rtMinimum
;
597 else if (!This
->rtMinimum
)
598 This
->rtMinimum
= 20000000; /* 2 seconds */
602 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetNotificationPMsg(IDirectMusicPerformance8
*iface
,
603 DMUS_NOTIFICATION_PMSG
**ppNotificationPMsg
)
605 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
607 FIXME("(%p, %p): stub\n", This
, ppNotificationPMsg
);
608 if (NULL
== ppNotificationPMsg
) {
618 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AddNotificationType(IDirectMusicPerformance8
*iface
,
619 REFGUID rguidNotificationType
)
621 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
623 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
627 static HRESULT WINAPI
IDirectMusicPerformance8Impl_RemoveNotificationType(IDirectMusicPerformance8
*iface
,
628 REFGUID rguidNotificationType
)
630 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
632 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
636 static HRESULT
perf_dmport_create(IDirectMusicPerformance8Impl
*perf
, DMUS_PORTPARAMS
*params
)
638 IDirectMusicPort
*port
;
643 if (FAILED(hr
= IDirectMusic8_GetDefaultPort(perf
->dmusic
, &guid
)))
646 params
->dwSize
= sizeof(params
);
647 params
->dwValidParams
|= DMUS_PORTPARAMS_SHARE
;
648 params
->fShare
= TRUE
;
650 if (FAILED(hr
= IDirectMusic8_CreatePort(perf
->dmusic
, &guid
, params
, &port
, NULL
)))
652 if (FAILED(hr
= IDirectMusicPort_Activate(port
, TRUE
))) {
653 IDirectMusicPort_Release(port
);
656 for (i
= 0; i
< params
->dwChannelGroups
; i
++)
657 pchannel_block_set(&perf
->pchannels
, i
, port
, i
+ 1, FALSE
);
662 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AddPort(IDirectMusicPerformance8
*iface
,
663 IDirectMusicPort
*port
)
665 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
667 FIXME("(%p, %p): semi-stub\n", This
, port
);
670 return DMUS_E_NOT_INIT
;
673 DMUS_PORTPARAMS params
= {
674 .dwValidParams
= DMUS_PORTPARAMS_CHANNELGROUPS
,
678 return perf_dmport_create(This
, ¶ms
);
681 IDirectMusicPort_AddRef(port
);
683 * We should remember added Ports (for example using a list)
684 * and control if Port is registered for each api who use ports
689 static HRESULT WINAPI
IDirectMusicPerformance8Impl_RemovePort(IDirectMusicPerformance8
*iface
,
690 IDirectMusicPort
*pPort
)
692 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
694 FIXME("(%p, %p): stub\n", This
, pPort
);
695 IDirectMusicPort_Release (pPort
);
699 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMusicPerformance8
*iface
,
700 DWORD block_num
, IDirectMusicPort
*port
, DWORD group
)
702 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
704 FIXME("(%p, %d, %p, %d): semi-stub\n", This
, block_num
, port
, group
);
708 if (block_num
> MAXDWORD
/ 16)
711 pchannel_block_set(&This
->pchannels
, block_num
, port
, group
, FALSE
);
716 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AssignPChannel(IDirectMusicPerformance8
*iface
,
717 DWORD pchannel
, IDirectMusicPort
*port
, DWORD group
, DWORD channel
)
719 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
720 struct pchannel_block
*block
;
722 FIXME("(%p)->(%d, %p, %d, %d) semi-stub\n", This
, pchannel
, port
, group
, channel
);
727 block
= pchannel_block_set(&This
->pchannels
, pchannel
/ 16, port
, 0, TRUE
);
729 block
->pchannel
[pchannel
% 16].group
= group
;
730 block
->pchannel
[pchannel
% 16].channel
= channel
;
736 static HRESULT WINAPI
IDirectMusicPerformance8Impl_PChannelInfo(IDirectMusicPerformance8
*iface
,
737 DWORD pchannel
, IDirectMusicPort
**port
, DWORD
*group
, DWORD
*channel
)
739 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
740 struct pchannel_block
*block
;
741 struct wine_rb_entry
*entry
;
742 DWORD block_num
= pchannel
/ 16;
743 unsigned int index
= pchannel
% 16;
745 TRACE("(%p)->(%d, %p, %p, %p)\n", This
, pchannel
, port
, group
, channel
);
747 entry
= wine_rb_get(&This
->pchannels
, &block_num
);
750 block
= WINE_RB_ENTRY_VALUE(entry
, struct pchannel_block
, entry
);
753 *port
= block
->pchannel
[index
].port
;
754 IDirectMusicPort_AddRef(*port
);
757 *group
= block
->pchannel
[index
].group
;
759 *channel
= block
->pchannel
[index
].channel
;
764 static HRESULT WINAPI
IDirectMusicPerformance8Impl_DownloadInstrument(IDirectMusicPerformance8
*iface
,
765 IDirectMusicInstrument
*pInst
, DWORD dwPChannel
,
766 IDirectMusicDownloadedInstrument
**ppDownInst
, DMUS_NOTERANGE
*pNoteRanges
,
767 DWORD dwNumNoteRanges
, IDirectMusicPort
**ppPort
, DWORD
*pdwGroup
, DWORD
*pdwMChannel
)
769 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
771 FIXME("(%p, %p, %d, %p, %p, %d, %p, %p, %p): stub\n", This
, pInst
, dwPChannel
, ppDownInst
, pNoteRanges
, dwNumNoteRanges
, ppPort
, pdwGroup
, pdwMChannel
);
775 static HRESULT WINAPI
IDirectMusicPerformance8Impl_Invalidate(IDirectMusicPerformance8
*iface
,
776 MUSIC_TIME mtTime
, DWORD dwFlags
)
778 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
780 FIXME("(%p, %d, %d): stub\n", This
, mtTime
, dwFlags
);
784 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetParam(IDirectMusicPerformance8
*iface
,
785 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
,
786 MUSIC_TIME
*pmtNext
, void *pParam
)
788 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
790 FIXME("(%p, %s, %d, %d, %d, %p, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
794 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetParam(IDirectMusicPerformance8
*iface
,
795 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, void *pParam
)
797 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
799 FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pParam
);
803 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetGlobalParam(IDirectMusicPerformance8
*iface
,
804 REFGUID rguidType
, void *pParam
, DWORD dwSize
)
806 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
808 TRACE("(%p, %s, %p, %d): stub\n", This
, debugstr_dmguid(rguidType
), pParam
, dwSize
);
810 if (IsEqualGUID (rguidType
, &GUID_PerfAutoDownload
))
811 memcpy(pParam
, &This
->fAutoDownload
, sizeof(This
->fAutoDownload
));
812 if (IsEqualGUID (rguidType
, &GUID_PerfMasterGrooveLevel
))
813 memcpy(pParam
, &This
->cMasterGrooveLevel
, sizeof(This
->cMasterGrooveLevel
));
814 if (IsEqualGUID (rguidType
, &GUID_PerfMasterTempo
))
815 memcpy(pParam
, &This
->fMasterTempo
, sizeof(This
->fMasterTempo
));
816 if (IsEqualGUID (rguidType
, &GUID_PerfMasterVolume
))
817 memcpy(pParam
, &This
->lMasterVolume
, sizeof(This
->lMasterVolume
));
822 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetGlobalParam(IDirectMusicPerformance8
*iface
,
823 REFGUID rguidType
, void *pParam
, DWORD dwSize
)
825 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
827 TRACE("(%p, %s, %p, %d)\n", This
, debugstr_dmguid(rguidType
), pParam
, dwSize
);
829 if (IsEqualGUID (rguidType
, &GUID_PerfAutoDownload
)) {
830 memcpy(&This
->fAutoDownload
, pParam
, dwSize
);
831 TRACE("=> AutoDownload set to %d\n", This
->fAutoDownload
);
833 if (IsEqualGUID (rguidType
, &GUID_PerfMasterGrooveLevel
)) {
834 memcpy(&This
->cMasterGrooveLevel
, pParam
, dwSize
);
835 TRACE("=> MasterGrooveLevel set to %i\n", This
->cMasterGrooveLevel
);
837 if (IsEqualGUID (rguidType
, &GUID_PerfMasterTempo
)) {
838 memcpy(&This
->fMasterTempo
, pParam
, dwSize
);
839 TRACE("=> MasterTempo set to %f\n", This
->fMasterTempo
);
841 if (IsEqualGUID (rguidType
, &GUID_PerfMasterVolume
)) {
842 memcpy(&This
->lMasterVolume
, pParam
, dwSize
);
843 TRACE("=> MasterVolume set to %li\n", This
->lMasterVolume
);
849 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetLatencyTime(IDirectMusicPerformance8
*iface
,
850 REFERENCE_TIME
*prtTime
)
852 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
854 TRACE("(%p, %p): stub\n", This
, prtTime
);
855 *prtTime
= This
->rtLatencyTime
;
859 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetQueueTime(IDirectMusicPerformance8
*iface
,
860 REFERENCE_TIME
*prtTime
)
863 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
865 FIXME("(%p, %p): stub\n", This
, prtTime
);
869 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AdjustTime(IDirectMusicPerformance8
*iface
,
870 REFERENCE_TIME rtAmount
)
872 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
874 FIXME("(%p, 0x%s): stub\n", This
, wine_dbgstr_longlong(rtAmount
));
878 static HRESULT WINAPI
IDirectMusicPerformance8Impl_CloseDown(IDirectMusicPerformance8
*iface
)
880 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
882 FIXME("(%p): semi-stub\n", This
);
884 if (PostMessageToProcessMsgThread(This
, PROCESSMSG_EXIT
)) {
885 WaitForSingleObject(This
->procThread
, INFINITE
);
886 This
->procThreadTicStarted
= FALSE
;
887 CloseHandle(This
->procThread
);
890 IDirectSound_Release(This
->dsound
);
894 IDirectMusic_SetDirectSound(This
->dmusic
, NULL
, NULL
);
895 IDirectMusic8_Release(This
->dmusic
);
901 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetResolvedTime(IDirectMusicPerformance8
*iface
,
902 REFERENCE_TIME rtTime
, REFERENCE_TIME
*prtResolved
, DWORD dwTimeResolveFlags
)
904 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
906 FIXME("(%p, 0x%s, %p, %d): stub\n", This
, wine_dbgstr_longlong(rtTime
),
907 prtResolved
, dwTimeResolveFlags
);
911 static HRESULT WINAPI
IDirectMusicPerformance8Impl_MIDIToMusic(IDirectMusicPerformance8
*iface
,
912 BYTE bMIDIValue
, DMUS_CHORD_KEY
*pChord
, BYTE bPlayMode
, BYTE bChordLevel
,
915 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
917 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This
, bMIDIValue
, pChord
, bPlayMode
, bChordLevel
, pwMusicValue
);
921 static HRESULT WINAPI
IDirectMusicPerformance8Impl_MusicToMIDI(IDirectMusicPerformance8
*iface
,
922 WORD wMusicValue
, DMUS_CHORD_KEY
*pChord
, BYTE bPlayMode
, BYTE bChordLevel
,
925 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
927 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This
, wMusicValue
, pChord
, bPlayMode
, bChordLevel
, pbMIDIValue
);
931 static HRESULT WINAPI
IDirectMusicPerformance8Impl_TimeToRhythm(IDirectMusicPerformance8
*iface
,
932 MUSIC_TIME mtTime
, DMUS_TIMESIGNATURE
*pTimeSig
, WORD
*pwMeasure
, BYTE
*pbBeat
,
933 BYTE
*pbGrid
, short *pnOffset
)
935 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
937 FIXME("(%p, %d, %p, %p, %p, %p, %p): stub\n", This
, mtTime
, pTimeSig
, pwMeasure
, pbBeat
, pbGrid
, pnOffset
);
941 static HRESULT WINAPI
IDirectMusicPerformance8Impl_RhythmToTime(IDirectMusicPerformance8
*iface
,
942 WORD wMeasure
, BYTE bBeat
, BYTE bGrid
, short nOffset
, DMUS_TIMESIGNATURE
*pTimeSig
,
945 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
947 FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This
, wMeasure
, bBeat
, bGrid
, nOffset
, pTimeSig
, pmtTime
);
951 /* IDirectMusicPerformance8 Interface part follow: */
952 static HRESULT WINAPI
IDirectMusicPerformance8Impl_InitAudio(IDirectMusicPerformance8
*iface
,
953 IDirectMusic
**dmusic
, IDirectSound
**dsound
, HWND hwnd
, DWORD default_path_type
,
954 DWORD num_channels
, DWORD flags
, DMUS_AUDIOPARAMS
*params
)
956 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
959 TRACE("(%p, %p, %p, %p, %x, %u, %x, %p)\n", This
, dmusic
, dsound
, hwnd
, default_path_type
,
960 num_channels
, flags
, params
);
963 return DMUS_E_ALREADY_INITED
;
965 if (!dmusic
|| !*dmusic
) {
966 hr
= CoCreateInstance(&CLSID_DirectMusic
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusic8
,
967 (void **)&This
->dmusic
);
971 This
->dmusic
= (IDirectMusic8
*)*dmusic
;
972 IDirectMusic8_AddRef(This
->dmusic
);
975 if (!dsound
|| !*dsound
) {
976 hr
= DirectSoundCreate8(NULL
, (IDirectSound8
**)&This
->dsound
, NULL
);
979 hr
= IDirectSound_SetCooperativeLevel(This
->dsound
, hwnd
? hwnd
: GetForegroundWindow(),
984 This
->dsound
= *dsound
;
985 IDirectSound_AddRef(This
->dsound
);
988 hr
= IDirectMusic8_SetDirectSound(This
->dmusic
, This
->dsound
, NULL
);
993 This
->params
.dwSize
= sizeof(DMUS_AUDIOPARAMS
);
994 This
->params
.fInitNow
= FALSE
;
995 This
->params
.dwValidData
= DMUS_AUDIOPARAMS_FEATURES
| DMUS_AUDIOPARAMS_VOICES
|
996 DMUS_AUDIOPARAMS_SAMPLERATE
| DMUS_AUDIOPARAMS_DEFAULTSYNTH
;
997 This
->params
.dwVoices
= 64;
998 This
->params
.dwSampleRate
= 22050;
999 This
->params
.dwFeatures
= flags
;
1000 This
->params
.clsidDefaultSynth
= CLSID_DirectMusicSynthSink
;
1002 This
->params
= *params
;
1004 if (default_path_type
) {
1005 hr
= IDirectMusicPerformance8_CreateStandardAudioPath(iface
, default_path_type
,
1006 num_channels
, FALSE
, &This
->pDefaultPath
);
1008 IDirectMusic8_SetDirectSound(This
->dmusic
, NULL
, NULL
);
1013 if (dsound
&& !*dsound
) {
1014 *dsound
= This
->dsound
;
1015 IDirectSound_AddRef(*dsound
);
1017 if (dmusic
&& !*dmusic
) {
1018 *dmusic
= (IDirectMusic
*)This
->dmusic
;
1019 IDirectMusic_AddRef(*dmusic
);
1021 PostMessageToProcessMsgThread(This
, PROCESSMSG_START
);
1027 IDirectSound_Release(This
->dsound
);
1028 This
->dsound
= NULL
;
1031 IDirectMusic8_Release(This
->dmusic
);
1032 This
->dmusic
= NULL
;
1037 static HRESULT WINAPI
IDirectMusicPerformance8Impl_PlaySegmentEx(IDirectMusicPerformance8
*iface
,
1038 IUnknown
*pSource
, WCHAR
*pwzSegmentName
, IUnknown
*pTransition
, DWORD dwFlags
,
1039 __int64 i64StartTime
, IDirectMusicSegmentState
**ppSegmentState
, IUnknown
*pFrom
,
1040 IUnknown
*pAudioPath
)
1042 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1044 FIXME("(%p, %p, %p, %p, %d, 0x%s, %p, %p, %p): stub\n", This
, pSource
, pwzSegmentName
,
1045 pTransition
, dwFlags
, wine_dbgstr_longlong(i64StartTime
), ppSegmentState
, pFrom
, pAudioPath
);
1047 return create_dmsegmentstate(&IID_IDirectMusicSegmentState
,(void**)ppSegmentState
);
1051 static HRESULT WINAPI
IDirectMusicPerformance8Impl_StopEx(IDirectMusicPerformance8
*iface
,
1052 IUnknown
*pObjectToStop
, __int64 i64StopTime
, DWORD dwFlags
)
1054 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1056 FIXME("(%p, %p, 0x%s, %d): stub\n", This
, pObjectToStop
,
1057 wine_dbgstr_longlong(i64StopTime
), dwFlags
);
1061 static HRESULT WINAPI
IDirectMusicPerformance8Impl_ClonePMsg(IDirectMusicPerformance8
*iface
,
1062 DMUS_PMSG
*pSourcePMSG
, DMUS_PMSG
**ppCopyPMSG
)
1064 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1066 FIXME("(%p, %p, %p): stub\n", This
, pSourcePMSG
, ppCopyPMSG
);
1070 static HRESULT WINAPI
IDirectMusicPerformance8Impl_CreateAudioPath(IDirectMusicPerformance8
*iface
,
1071 IUnknown
*pSourceConfig
, BOOL fActivate
, IDirectMusicAudioPath
**ppNewPath
)
1073 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1074 IDirectMusicAudioPath
*pPath
;
1076 FIXME("(%p, %p, %d, %p): stub\n", This
, pSourceConfig
, fActivate
, ppNewPath
);
1078 if (NULL
== ppNewPath
) {
1082 create_dmaudiopath(&IID_IDirectMusicAudioPath
, (void**)&pPath
);
1083 set_audiopath_perf_pointer(pPath
, iface
);
1089 return IDirectMusicAudioPath_Activate(*ppNewPath
, fActivate
);
1092 static HRESULT WINAPI
IDirectMusicPerformance8Impl_CreateStandardAudioPath(IDirectMusicPerformance8
*iface
,
1093 DWORD dwType
, DWORD pchannel_count
, BOOL fActivate
, IDirectMusicAudioPath
**ppNewPath
)
1095 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1096 IDirectMusicAudioPath
*pPath
;
1098 WAVEFORMATEX format
;
1099 DMUS_PORTPARAMS params
= {0};
1100 IDirectSoundBuffer
*buffer
, *primary_buffer
;
1103 FIXME("(%p)->(%d, %d, %d, %p): semi-stub\n", This
, dwType
, pchannel_count
, fActivate
, ppNewPath
);
1105 if (NULL
== ppNewPath
) {
1111 /* Secondary buffer description */
1112 memset(&format
, 0, sizeof(format
));
1113 format
.wFormatTag
= WAVE_FORMAT_PCM
;
1114 format
.nChannels
= 1;
1115 format
.nSamplesPerSec
= 44000;
1116 format
.nAvgBytesPerSec
= 44000*2;
1117 format
.nBlockAlign
= 2;
1118 format
.wBitsPerSample
= 16;
1121 memset(&desc
, 0, sizeof(desc
));
1122 desc
.dwSize
= sizeof(desc
);
1123 desc
.dwFlags
= DSBCAPS_CTRLFX
| DSBCAPS_CTRLVOLUME
| DSBCAPS_GLOBALFOCUS
;
1124 desc
.dwBufferBytes
= DSBSIZE_MIN
;
1125 desc
.dwReserved
= 0;
1126 desc
.lpwfxFormat
= &format
;
1127 desc
.guid3DAlgorithm
= GUID_NULL
;
1130 case DMUS_APATH_DYNAMIC_3D
:
1131 desc
.dwFlags
|= DSBCAPS_CTRL3D
| DSBCAPS_CTRLFREQUENCY
| DSBCAPS_MUTE3DATMAXDISTANCE
;
1133 case DMUS_APATH_DYNAMIC_MONO
:
1134 desc
.dwFlags
|= DSBCAPS_CTRLPAN
| DSBCAPS_CTRLFREQUENCY
;
1136 case DMUS_APATH_SHARED_STEREOPLUSREVERB
:
1137 /* normally we have to create 2 buffers (one for music other for reverb)
1138 * in this case. See msdn
1140 case DMUS_APATH_DYNAMIC_STEREO
:
1141 desc
.dwFlags
|= DSBCAPS_CTRLPAN
| DSBCAPS_CTRLFREQUENCY
;
1142 format
.nChannels
= 2;
1143 format
.nBlockAlign
*= 2;
1144 format
.nAvgBytesPerSec
*=2;
1147 return E_INVALIDARG
;
1151 params
.dwValidParams
= DMUS_PORTPARAMS_CHANNELGROUPS
| DMUS_PORTPARAMS_AUDIOCHANNELS
;
1152 params
.dwChannelGroups
= (pchannel_count
+ 15) / 16;
1153 params
.dwAudioChannels
= format
.nChannels
;
1154 if (FAILED(hr
= perf_dmport_create(This
, ¶ms
)))
1157 hr
= IDirectSound_CreateSoundBuffer(This
->dsound
, &desc
, &buffer
, NULL
);
1159 return DSERR_BUFFERLOST
;
1161 /* Update description for creating primary buffer */
1162 desc
.dwFlags
|= DSBCAPS_PRIMARYBUFFER
;
1163 desc
.dwFlags
&= ~DSBCAPS_CTRLFX
;
1164 desc
.dwBufferBytes
= 0;
1165 desc
.lpwfxFormat
= NULL
;
1167 hr
= IDirectSound_CreateSoundBuffer(This
->dsound
, &desc
, &primary_buffer
, NULL
);
1169 IDirectSoundBuffer_Release(buffer
);
1170 return DSERR_BUFFERLOST
;
1173 create_dmaudiopath(&IID_IDirectMusicAudioPath
, (void**)&pPath
);
1174 set_audiopath_perf_pointer(pPath
, iface
);
1175 set_audiopath_dsound_buffer(pPath
, buffer
);
1176 set_audiopath_primary_dsound_buffer(pPath
, primary_buffer
);
1180 TRACE(" returning IDirectMusicAudioPath interface at %p.\n", *ppNewPath
);
1182 return IDirectMusicAudioPath_Activate(*ppNewPath
, fActivate
);
1185 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetDefaultAudioPath(IDirectMusicPerformance8
*iface
,
1186 IDirectMusicAudioPath
*pAudioPath
)
1188 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1190 FIXME("(%p, %p): semi-stub\n", This
, pAudioPath
);
1192 if (This
->pDefaultPath
) {
1193 IDirectMusicAudioPath_Release(This
->pDefaultPath
);
1194 This
->pDefaultPath
= NULL
;
1196 This
->pDefaultPath
= pAudioPath
;
1197 if (This
->pDefaultPath
) {
1198 IDirectMusicAudioPath_AddRef(This
->pDefaultPath
);
1199 set_audiopath_perf_pointer(This
->pDefaultPath
, iface
);
1205 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetDefaultAudioPath(IDirectMusicPerformance8
*iface
,
1206 IDirectMusicAudioPath
**ppAudioPath
)
1208 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1210 FIXME("(%p, %p): semi-stub (%p)\n", This
, ppAudioPath
, This
->pDefaultPath
);
1212 if (NULL
!= This
->pDefaultPath
) {
1213 *ppAudioPath
= This
->pDefaultPath
;
1214 IDirectMusicAudioPath_AddRef(*ppAudioPath
);
1216 *ppAudioPath
= NULL
;
1221 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetParamEx(IDirectMusicPerformance8
*iface
,
1222 REFGUID rguidType
, DWORD dwTrackID
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
,
1223 MUSIC_TIME
*pmtNext
, void *pParam
)
1225 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1227 FIXME("(%p, %s, %d, %d, %d, %d, %p, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwTrackID
, dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
1232 static const IDirectMusicPerformance8Vtbl DirectMusicPerformance8_Vtbl
= {
1233 IDirectMusicPerformance8Impl_QueryInterface
,
1234 IDirectMusicPerformance8Impl_AddRef
,
1235 IDirectMusicPerformance8Impl_Release
,
1236 IDirectMusicPerformance8Impl_Init
,
1237 IDirectMusicPerformance8Impl_PlaySegment
,
1238 IDirectMusicPerformance8Impl_Stop
,
1239 IDirectMusicPerformance8Impl_GetSegmentState
,
1240 IDirectMusicPerformance8Impl_SetPrepareTime
,
1241 IDirectMusicPerformance8Impl_GetPrepareTime
,
1242 IDirectMusicPerformance8Impl_SetBumperLength
,
1243 IDirectMusicPerformance8Impl_GetBumperLength
,
1244 IDirectMusicPerformance8Impl_SendPMsg
,
1245 IDirectMusicPerformance8Impl_MusicToReferenceTime
,
1246 IDirectMusicPerformance8Impl_ReferenceToMusicTime
,
1247 IDirectMusicPerformance8Impl_IsPlaying
,
1248 IDirectMusicPerformance8Impl_GetTime
,
1249 IDirectMusicPerformance8Impl_AllocPMsg
,
1250 IDirectMusicPerformance8Impl_FreePMsg
,
1251 IDirectMusicPerformance8Impl_GetGraph
,
1252 IDirectMusicPerformance8Impl_SetGraph
,
1253 IDirectMusicPerformance8Impl_SetNotificationHandle
,
1254 IDirectMusicPerformance8Impl_GetNotificationPMsg
,
1255 IDirectMusicPerformance8Impl_AddNotificationType
,
1256 IDirectMusicPerformance8Impl_RemoveNotificationType
,
1257 IDirectMusicPerformance8Impl_AddPort
,
1258 IDirectMusicPerformance8Impl_RemovePort
,
1259 IDirectMusicPerformance8Impl_AssignPChannelBlock
,
1260 IDirectMusicPerformance8Impl_AssignPChannel
,
1261 IDirectMusicPerformance8Impl_PChannelInfo
,
1262 IDirectMusicPerformance8Impl_DownloadInstrument
,
1263 IDirectMusicPerformance8Impl_Invalidate
,
1264 IDirectMusicPerformance8Impl_GetParam
,
1265 IDirectMusicPerformance8Impl_SetParam
,
1266 IDirectMusicPerformance8Impl_GetGlobalParam
,
1267 IDirectMusicPerformance8Impl_SetGlobalParam
,
1268 IDirectMusicPerformance8Impl_GetLatencyTime
,
1269 IDirectMusicPerformance8Impl_GetQueueTime
,
1270 IDirectMusicPerformance8Impl_AdjustTime
,
1271 IDirectMusicPerformance8Impl_CloseDown
,
1272 IDirectMusicPerformance8Impl_GetResolvedTime
,
1273 IDirectMusicPerformance8Impl_MIDIToMusic
,
1274 IDirectMusicPerformance8Impl_MusicToMIDI
,
1275 IDirectMusicPerformance8Impl_TimeToRhythm
,
1276 IDirectMusicPerformance8Impl_RhythmToTime
,
1277 IDirectMusicPerformance8Impl_InitAudio
,
1278 IDirectMusicPerformance8Impl_PlaySegmentEx
,
1279 IDirectMusicPerformance8Impl_StopEx
,
1280 IDirectMusicPerformance8Impl_ClonePMsg
,
1281 IDirectMusicPerformance8Impl_CreateAudioPath
,
1282 IDirectMusicPerformance8Impl_CreateStandardAudioPath
,
1283 IDirectMusicPerformance8Impl_SetDefaultAudioPath
,
1284 IDirectMusicPerformance8Impl_GetDefaultAudioPath
,
1285 IDirectMusicPerformance8Impl_GetParamEx
1288 /* for ClassFactory */
1289 HRESULT WINAPI
create_dmperformance(REFIID lpcGUID
, void **ppobj
)
1291 IDirectMusicPerformance8Impl
*obj
;
1293 TRACE("(%s, %p)\n", debugstr_guid(lpcGUID
), ppobj
);
1295 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicPerformance8Impl
));
1298 return E_OUTOFMEMORY
;
1300 obj
->IDirectMusicPerformance8_iface
.lpVtbl
= &DirectMusicPerformance8_Vtbl
;
1301 obj
->ref
= 0; /* will be inited by QueryInterface */
1302 obj
->pDefaultPath
= NULL
;
1303 InitializeCriticalSection(&obj
->safe
);
1304 obj
->safe
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectMusicPerformance8Impl*->safe");
1305 wine_rb_init(&obj
->pchannels
, pchannel_block_compare
);
1307 obj
->rtLatencyTime
= 100; /* 100 ms TO FIX */
1308 obj
->dwBumperLength
= 50; /* 50 ms default */
1309 obj
->dwPrepareTime
= 1000; /* 1000 ms default */
1310 return IDirectMusicPerformance8Impl_QueryInterface(&obj
->IDirectMusicPerformance8_iface
,