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: %#lx\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): ref=%ld\n", This
, ref
);
286 static ULONG WINAPI
IDirectMusicPerformance8Impl_Release(IDirectMusicPerformance8
*iface
)
288 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
289 ULONG ref
= InterlockedDecrement(&This
->ref
);
291 TRACE("(%p): ref=%ld\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, %ld, 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, %ld, %ld): 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, %ld): 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, %ld)\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, %ld)\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, %ld, %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, %ld, %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 if (FAILED(hr
= IDirectMusic8_CreatePort(perf
->dmusic
, &guid
, params
, &port
, NULL
)))
648 if (FAILED(hr
= IDirectMusicPort_Activate(port
, TRUE
))) {
649 IDirectMusicPort_Release(port
);
652 for (i
= 0; i
< params
->dwChannelGroups
; i
++)
653 pchannel_block_set(&perf
->pchannels
, i
, port
, i
+ 1, FALSE
);
658 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AddPort(IDirectMusicPerformance8
*iface
,
659 IDirectMusicPort
*port
)
661 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
663 FIXME("(%p, %p): semi-stub\n", This
, port
);
666 return DMUS_E_NOT_INIT
;
669 DMUS_PORTPARAMS params
= {
670 .dwSize
= sizeof(params
),
671 .dwValidParams
= DMUS_PORTPARAMS_CHANNELGROUPS
,
675 return perf_dmport_create(This
, ¶ms
);
678 IDirectMusicPort_AddRef(port
);
680 * We should remember added Ports (for example using a list)
681 * and control if Port is registered for each api who use ports
686 static HRESULT WINAPI
IDirectMusicPerformance8Impl_RemovePort(IDirectMusicPerformance8
*iface
,
687 IDirectMusicPort
*pPort
)
689 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
691 FIXME("(%p, %p): stub\n", This
, pPort
);
692 IDirectMusicPort_Release (pPort
);
696 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMusicPerformance8
*iface
,
697 DWORD block_num
, IDirectMusicPort
*port
, DWORD group
)
699 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
701 FIXME("(%p, %ld, %p, %ld): semi-stub\n", This
, block_num
, port
, group
);
705 if (block_num
> MAXDWORD
/ 16)
708 pchannel_block_set(&This
->pchannels
, block_num
, port
, group
, FALSE
);
713 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AssignPChannel(IDirectMusicPerformance8
*iface
,
714 DWORD pchannel
, IDirectMusicPort
*port
, DWORD group
, DWORD channel
)
716 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
717 struct pchannel_block
*block
;
719 FIXME("(%p)->(%ld, %p, %ld, %ld) semi-stub\n", This
, pchannel
, port
, group
, channel
);
724 block
= pchannel_block_set(&This
->pchannels
, pchannel
/ 16, port
, 0, TRUE
);
726 block
->pchannel
[pchannel
% 16].group
= group
;
727 block
->pchannel
[pchannel
% 16].channel
= channel
;
733 static HRESULT WINAPI
IDirectMusicPerformance8Impl_PChannelInfo(IDirectMusicPerformance8
*iface
,
734 DWORD pchannel
, IDirectMusicPort
**port
, DWORD
*group
, DWORD
*channel
)
736 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
737 struct pchannel_block
*block
;
738 struct wine_rb_entry
*entry
;
739 DWORD block_num
= pchannel
/ 16;
740 unsigned int index
= pchannel
% 16;
742 TRACE("(%p)->(%ld, %p, %p, %p)\n", This
, pchannel
, port
, group
, channel
);
744 entry
= wine_rb_get(&This
->pchannels
, &block_num
);
747 block
= WINE_RB_ENTRY_VALUE(entry
, struct pchannel_block
, entry
);
750 *port
= block
->pchannel
[index
].port
;
751 IDirectMusicPort_AddRef(*port
);
754 *group
= block
->pchannel
[index
].group
;
756 *channel
= block
->pchannel
[index
].channel
;
761 static HRESULT WINAPI
IDirectMusicPerformance8Impl_DownloadInstrument(IDirectMusicPerformance8
*iface
,
762 IDirectMusicInstrument
*pInst
, DWORD dwPChannel
,
763 IDirectMusicDownloadedInstrument
**ppDownInst
, DMUS_NOTERANGE
*pNoteRanges
,
764 DWORD dwNumNoteRanges
, IDirectMusicPort
**ppPort
, DWORD
*pdwGroup
, DWORD
*pdwMChannel
)
766 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
768 FIXME("(%p, %p, %ld, %p, %p, %ld, %p, %p, %p): stub\n", This
, pInst
, dwPChannel
, ppDownInst
, pNoteRanges
, dwNumNoteRanges
, ppPort
, pdwGroup
, pdwMChannel
);
772 static HRESULT WINAPI
IDirectMusicPerformance8Impl_Invalidate(IDirectMusicPerformance8
*iface
,
773 MUSIC_TIME mtTime
, DWORD dwFlags
)
775 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
777 FIXME("(%p, %ld, %ld): stub\n", This
, mtTime
, dwFlags
);
781 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetParam(IDirectMusicPerformance8
*iface
,
782 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
,
783 MUSIC_TIME
*pmtNext
, void *pParam
)
785 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
787 FIXME("(%p, %s, %ld, %ld, %ld, %p, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
791 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetParam(IDirectMusicPerformance8
*iface
,
792 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, void *pParam
)
794 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
796 FIXME("(%p, %s, %ld, %ld, %ld, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pParam
);
800 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetGlobalParam(IDirectMusicPerformance8
*iface
,
801 REFGUID rguidType
, void *pParam
, DWORD dwSize
)
803 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
805 TRACE("(%p, %s, %p, %ld): stub\n", This
, debugstr_dmguid(rguidType
), pParam
, dwSize
);
807 if (IsEqualGUID (rguidType
, &GUID_PerfAutoDownload
))
808 memcpy(pParam
, &This
->fAutoDownload
, sizeof(This
->fAutoDownload
));
809 if (IsEqualGUID (rguidType
, &GUID_PerfMasterGrooveLevel
))
810 memcpy(pParam
, &This
->cMasterGrooveLevel
, sizeof(This
->cMasterGrooveLevel
));
811 if (IsEqualGUID (rguidType
, &GUID_PerfMasterTempo
))
812 memcpy(pParam
, &This
->fMasterTempo
, sizeof(This
->fMasterTempo
));
813 if (IsEqualGUID (rguidType
, &GUID_PerfMasterVolume
))
814 memcpy(pParam
, &This
->lMasterVolume
, sizeof(This
->lMasterVolume
));
819 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetGlobalParam(IDirectMusicPerformance8
*iface
,
820 REFGUID rguidType
, void *pParam
, DWORD dwSize
)
822 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
824 TRACE("(%p, %s, %p, %ld)\n", This
, debugstr_dmguid(rguidType
), pParam
, dwSize
);
826 if (IsEqualGUID (rguidType
, &GUID_PerfAutoDownload
)) {
827 memcpy(&This
->fAutoDownload
, pParam
, dwSize
);
828 TRACE("=> AutoDownload set to %d\n", This
->fAutoDownload
);
830 if (IsEqualGUID (rguidType
, &GUID_PerfMasterGrooveLevel
)) {
831 memcpy(&This
->cMasterGrooveLevel
, pParam
, dwSize
);
832 TRACE("=> MasterGrooveLevel set to %i\n", This
->cMasterGrooveLevel
);
834 if (IsEqualGUID (rguidType
, &GUID_PerfMasterTempo
)) {
835 memcpy(&This
->fMasterTempo
, pParam
, dwSize
);
836 TRACE("=> MasterTempo set to %f\n", This
->fMasterTempo
);
838 if (IsEqualGUID (rguidType
, &GUID_PerfMasterVolume
)) {
839 memcpy(&This
->lMasterVolume
, pParam
, dwSize
);
840 TRACE("=> MasterVolume set to %li\n", This
->lMasterVolume
);
846 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetLatencyTime(IDirectMusicPerformance8
*iface
,
847 REFERENCE_TIME
*prtTime
)
849 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
851 TRACE("(%p, %p): stub\n", This
, prtTime
);
852 *prtTime
= This
->rtLatencyTime
;
856 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetQueueTime(IDirectMusicPerformance8
*iface
,
857 REFERENCE_TIME
*prtTime
)
860 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
862 FIXME("(%p, %p): stub\n", This
, prtTime
);
866 static HRESULT WINAPI
IDirectMusicPerformance8Impl_AdjustTime(IDirectMusicPerformance8
*iface
,
867 REFERENCE_TIME rtAmount
)
869 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
871 FIXME("(%p, 0x%s): stub\n", This
, wine_dbgstr_longlong(rtAmount
));
875 static HRESULT WINAPI
IDirectMusicPerformance8Impl_CloseDown(IDirectMusicPerformance8
*iface
)
877 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
879 FIXME("(%p): semi-stub\n", This
);
881 if (PostMessageToProcessMsgThread(This
, PROCESSMSG_EXIT
)) {
882 WaitForSingleObject(This
->procThread
, INFINITE
);
883 This
->procThreadTicStarted
= FALSE
;
884 CloseHandle(This
->procThread
);
887 IDirectSound_Release(This
->dsound
);
891 IDirectMusic_SetDirectSound(This
->dmusic
, NULL
, NULL
);
892 IDirectMusic8_Release(This
->dmusic
);
898 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetResolvedTime(IDirectMusicPerformance8
*iface
,
899 REFERENCE_TIME rtTime
, REFERENCE_TIME
*prtResolved
, DWORD dwTimeResolveFlags
)
901 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
903 FIXME("(%p, 0x%s, %p, %ld): stub\n", This
, wine_dbgstr_longlong(rtTime
),
904 prtResolved
, dwTimeResolveFlags
);
908 static HRESULT WINAPI
IDirectMusicPerformance8Impl_MIDIToMusic(IDirectMusicPerformance8
*iface
,
909 BYTE bMIDIValue
, DMUS_CHORD_KEY
*pChord
, BYTE bPlayMode
, BYTE bChordLevel
,
912 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
914 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This
, bMIDIValue
, pChord
, bPlayMode
, bChordLevel
, pwMusicValue
);
918 static HRESULT WINAPI
IDirectMusicPerformance8Impl_MusicToMIDI(IDirectMusicPerformance8
*iface
,
919 WORD wMusicValue
, DMUS_CHORD_KEY
*pChord
, BYTE bPlayMode
, BYTE bChordLevel
,
922 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
924 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This
, wMusicValue
, pChord
, bPlayMode
, bChordLevel
, pbMIDIValue
);
928 static HRESULT WINAPI
IDirectMusicPerformance8Impl_TimeToRhythm(IDirectMusicPerformance8
*iface
,
929 MUSIC_TIME mtTime
, DMUS_TIMESIGNATURE
*pTimeSig
, WORD
*pwMeasure
, BYTE
*pbBeat
,
930 BYTE
*pbGrid
, short *pnOffset
)
932 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
934 FIXME("(%p, %ld, %p, %p, %p, %p, %p): stub\n", This
, mtTime
, pTimeSig
, pwMeasure
, pbBeat
, pbGrid
, pnOffset
);
938 static HRESULT WINAPI
IDirectMusicPerformance8Impl_RhythmToTime(IDirectMusicPerformance8
*iface
,
939 WORD wMeasure
, BYTE bBeat
, BYTE bGrid
, short nOffset
, DMUS_TIMESIGNATURE
*pTimeSig
,
942 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
944 FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This
, wMeasure
, bBeat
, bGrid
, nOffset
, pTimeSig
, pmtTime
);
948 /* IDirectMusicPerformance8 Interface part follow: */
949 static HRESULT WINAPI
IDirectMusicPerformance8Impl_InitAudio(IDirectMusicPerformance8
*iface
,
950 IDirectMusic
**dmusic
, IDirectSound
**dsound
, HWND hwnd
, DWORD default_path_type
,
951 DWORD num_channels
, DWORD flags
, DMUS_AUDIOPARAMS
*params
)
953 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
956 TRACE("(%p, %p, %p, %p, %lx, %lu, %lx, %p)\n", This
, dmusic
, dsound
, hwnd
, default_path_type
,
957 num_channels
, flags
, params
);
960 return DMUS_E_ALREADY_INITED
;
962 if (!dmusic
|| !*dmusic
) {
963 hr
= CoCreateInstance(&CLSID_DirectMusic
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusic8
,
964 (void **)&This
->dmusic
);
968 This
->dmusic
= (IDirectMusic8
*)*dmusic
;
969 IDirectMusic8_AddRef(This
->dmusic
);
972 if (!dsound
|| !*dsound
) {
973 hr
= DirectSoundCreate8(NULL
, (IDirectSound8
**)&This
->dsound
, NULL
);
976 hr
= IDirectSound_SetCooperativeLevel(This
->dsound
, hwnd
? hwnd
: GetForegroundWindow(),
981 This
->dsound
= *dsound
;
982 IDirectSound_AddRef(This
->dsound
);
985 hr
= IDirectMusic8_SetDirectSound(This
->dmusic
, This
->dsound
, NULL
);
990 This
->params
.dwSize
= sizeof(DMUS_AUDIOPARAMS
);
991 This
->params
.fInitNow
= FALSE
;
992 This
->params
.dwValidData
= DMUS_AUDIOPARAMS_FEATURES
| DMUS_AUDIOPARAMS_VOICES
|
993 DMUS_AUDIOPARAMS_SAMPLERATE
| DMUS_AUDIOPARAMS_DEFAULTSYNTH
;
994 This
->params
.dwVoices
= 64;
995 This
->params
.dwSampleRate
= 22050;
996 This
->params
.dwFeatures
= flags
;
997 This
->params
.clsidDefaultSynth
= CLSID_DirectMusicSynthSink
;
999 This
->params
= *params
;
1001 if (default_path_type
) {
1002 hr
= IDirectMusicPerformance8_CreateStandardAudioPath(iface
, default_path_type
,
1003 num_channels
, FALSE
, &This
->pDefaultPath
);
1005 IDirectMusic8_SetDirectSound(This
->dmusic
, NULL
, NULL
);
1010 if (dsound
&& !*dsound
) {
1011 *dsound
= This
->dsound
;
1012 IDirectSound_AddRef(*dsound
);
1014 if (dmusic
&& !*dmusic
) {
1015 *dmusic
= (IDirectMusic
*)This
->dmusic
;
1016 IDirectMusic_AddRef(*dmusic
);
1018 PostMessageToProcessMsgThread(This
, PROCESSMSG_START
);
1024 IDirectSound_Release(This
->dsound
);
1025 This
->dsound
= NULL
;
1028 IDirectMusic8_Release(This
->dmusic
);
1029 This
->dmusic
= NULL
;
1034 static HRESULT WINAPI
IDirectMusicPerformance8Impl_PlaySegmentEx(IDirectMusicPerformance8
*iface
,
1035 IUnknown
*pSource
, WCHAR
*pwzSegmentName
, IUnknown
*pTransition
, DWORD dwFlags
,
1036 __int64 i64StartTime
, IDirectMusicSegmentState
**ppSegmentState
, IUnknown
*pFrom
,
1037 IUnknown
*pAudioPath
)
1039 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1041 FIXME("(%p, %p, %p, %p, %ld, 0x%s, %p, %p, %p): stub\n", This
, pSource
, pwzSegmentName
,
1042 pTransition
, dwFlags
, wine_dbgstr_longlong(i64StartTime
), ppSegmentState
, pFrom
, pAudioPath
);
1044 return create_dmsegmentstate(&IID_IDirectMusicSegmentState
,(void**)ppSegmentState
);
1048 static HRESULT WINAPI
IDirectMusicPerformance8Impl_StopEx(IDirectMusicPerformance8
*iface
,
1049 IUnknown
*pObjectToStop
, __int64 i64StopTime
, DWORD dwFlags
)
1051 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1053 FIXME("(%p, %p, 0x%s, %ld): stub\n", This
, pObjectToStop
,
1054 wine_dbgstr_longlong(i64StopTime
), dwFlags
);
1058 static HRESULT WINAPI
IDirectMusicPerformance8Impl_ClonePMsg(IDirectMusicPerformance8
*iface
,
1059 DMUS_PMSG
*pSourcePMSG
, DMUS_PMSG
**ppCopyPMSG
)
1061 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1063 FIXME("(%p, %p, %p): stub\n", This
, pSourcePMSG
, ppCopyPMSG
);
1067 static HRESULT WINAPI
IDirectMusicPerformance8Impl_CreateAudioPath(IDirectMusicPerformance8
*iface
,
1068 IUnknown
*pSourceConfig
, BOOL fActivate
, IDirectMusicAudioPath
**ppNewPath
)
1070 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1071 IDirectMusicAudioPath
*pPath
;
1073 FIXME("(%p, %p, %d, %p): stub\n", This
, pSourceConfig
, fActivate
, ppNewPath
);
1075 if (NULL
== ppNewPath
) {
1079 create_dmaudiopath(&IID_IDirectMusicAudioPath
, (void**)&pPath
);
1080 set_audiopath_perf_pointer(pPath
, iface
);
1086 return IDirectMusicAudioPath_Activate(*ppNewPath
, fActivate
);
1089 static HRESULT WINAPI
IDirectMusicPerformance8Impl_CreateStandardAudioPath(IDirectMusicPerformance8
*iface
,
1090 DWORD dwType
, DWORD pchannel_count
, BOOL fActivate
, IDirectMusicAudioPath
**ppNewPath
)
1092 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1093 IDirectMusicAudioPath
*pPath
;
1095 WAVEFORMATEX format
;
1096 DMUS_PORTPARAMS params
= {0};
1097 IDirectSoundBuffer
*buffer
, *primary_buffer
;
1100 FIXME("(%p)->(%ld, %ld, %d, %p): semi-stub\n", This
, dwType
, pchannel_count
, fActivate
, ppNewPath
);
1102 if (NULL
== ppNewPath
) {
1108 /* Secondary buffer description */
1109 memset(&format
, 0, sizeof(format
));
1110 format
.wFormatTag
= WAVE_FORMAT_PCM
;
1111 format
.nChannels
= 1;
1112 format
.nSamplesPerSec
= 44000;
1113 format
.nAvgBytesPerSec
= 44000*2;
1114 format
.nBlockAlign
= 2;
1115 format
.wBitsPerSample
= 16;
1118 memset(&desc
, 0, sizeof(desc
));
1119 desc
.dwSize
= sizeof(desc
);
1120 desc
.dwFlags
= DSBCAPS_CTRLFX
| DSBCAPS_CTRLVOLUME
| DSBCAPS_GLOBALFOCUS
;
1121 desc
.dwBufferBytes
= DSBSIZE_MIN
;
1122 desc
.dwReserved
= 0;
1123 desc
.lpwfxFormat
= &format
;
1124 desc
.guid3DAlgorithm
= GUID_NULL
;
1127 case DMUS_APATH_DYNAMIC_3D
:
1128 desc
.dwFlags
|= DSBCAPS_CTRL3D
| DSBCAPS_CTRLFREQUENCY
| DSBCAPS_MUTE3DATMAXDISTANCE
;
1130 case DMUS_APATH_DYNAMIC_MONO
:
1131 desc
.dwFlags
|= DSBCAPS_CTRLPAN
| DSBCAPS_CTRLFREQUENCY
;
1133 case DMUS_APATH_SHARED_STEREOPLUSREVERB
:
1134 /* normally we have to create 2 buffers (one for music other for reverb)
1135 * in this case. See msdn
1137 case DMUS_APATH_DYNAMIC_STEREO
:
1138 desc
.dwFlags
|= DSBCAPS_CTRLPAN
| DSBCAPS_CTRLFREQUENCY
;
1139 format
.nChannels
= 2;
1140 format
.nBlockAlign
*= 2;
1141 format
.nAvgBytesPerSec
*=2;
1144 return E_INVALIDARG
;
1148 params
.dwSize
= sizeof(params
);
1149 params
.dwValidParams
= DMUS_PORTPARAMS_CHANNELGROUPS
| DMUS_PORTPARAMS_AUDIOCHANNELS
;
1150 params
.dwChannelGroups
= (pchannel_count
+ 15) / 16;
1151 params
.dwAudioChannels
= format
.nChannels
;
1152 if (FAILED(hr
= perf_dmport_create(This
, ¶ms
)))
1155 hr
= IDirectSound_CreateSoundBuffer(This
->dsound
, &desc
, &buffer
, NULL
);
1157 return DSERR_BUFFERLOST
;
1159 /* Update description for creating primary buffer */
1160 desc
.dwFlags
|= DSBCAPS_PRIMARYBUFFER
;
1161 desc
.dwFlags
&= ~DSBCAPS_CTRLFX
;
1162 desc
.dwBufferBytes
= 0;
1163 desc
.lpwfxFormat
= NULL
;
1165 hr
= IDirectSound_CreateSoundBuffer(This
->dsound
, &desc
, &primary_buffer
, NULL
);
1167 IDirectSoundBuffer_Release(buffer
);
1168 return DSERR_BUFFERLOST
;
1171 create_dmaudiopath(&IID_IDirectMusicAudioPath
, (void**)&pPath
);
1172 set_audiopath_perf_pointer(pPath
, iface
);
1173 set_audiopath_dsound_buffer(pPath
, buffer
);
1174 set_audiopath_primary_dsound_buffer(pPath
, primary_buffer
);
1178 TRACE(" returning IDirectMusicAudioPath interface at %p.\n", *ppNewPath
);
1180 return IDirectMusicAudioPath_Activate(*ppNewPath
, fActivate
);
1183 static HRESULT WINAPI
IDirectMusicPerformance8Impl_SetDefaultAudioPath(IDirectMusicPerformance8
*iface
,
1184 IDirectMusicAudioPath
*pAudioPath
)
1186 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1188 FIXME("(%p, %p): semi-stub\n", This
, pAudioPath
);
1190 if (This
->pDefaultPath
) {
1191 IDirectMusicAudioPath_Release(This
->pDefaultPath
);
1192 This
->pDefaultPath
= NULL
;
1194 This
->pDefaultPath
= pAudioPath
;
1195 if (This
->pDefaultPath
) {
1196 IDirectMusicAudioPath_AddRef(This
->pDefaultPath
);
1197 set_audiopath_perf_pointer(This
->pDefaultPath
, iface
);
1203 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetDefaultAudioPath(IDirectMusicPerformance8
*iface
,
1204 IDirectMusicAudioPath
**ppAudioPath
)
1206 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1208 FIXME("(%p, %p): semi-stub (%p)\n", This
, ppAudioPath
, This
->pDefaultPath
);
1210 if (NULL
!= This
->pDefaultPath
) {
1211 *ppAudioPath
= This
->pDefaultPath
;
1212 IDirectMusicAudioPath_AddRef(*ppAudioPath
);
1214 *ppAudioPath
= NULL
;
1219 static HRESULT WINAPI
IDirectMusicPerformance8Impl_GetParamEx(IDirectMusicPerformance8
*iface
,
1220 REFGUID rguidType
, DWORD dwTrackID
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
,
1221 MUSIC_TIME
*pmtNext
, void *pParam
)
1223 IDirectMusicPerformance8Impl
*This
= impl_from_IDirectMusicPerformance8(iface
);
1225 FIXME("(%p, %s, %ld, %ld, %ld, %ld, %p, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwTrackID
, dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
1230 static const IDirectMusicPerformance8Vtbl DirectMusicPerformance8_Vtbl
= {
1231 IDirectMusicPerformance8Impl_QueryInterface
,
1232 IDirectMusicPerformance8Impl_AddRef
,
1233 IDirectMusicPerformance8Impl_Release
,
1234 IDirectMusicPerformance8Impl_Init
,
1235 IDirectMusicPerformance8Impl_PlaySegment
,
1236 IDirectMusicPerformance8Impl_Stop
,
1237 IDirectMusicPerformance8Impl_GetSegmentState
,
1238 IDirectMusicPerformance8Impl_SetPrepareTime
,
1239 IDirectMusicPerformance8Impl_GetPrepareTime
,
1240 IDirectMusicPerformance8Impl_SetBumperLength
,
1241 IDirectMusicPerformance8Impl_GetBumperLength
,
1242 IDirectMusicPerformance8Impl_SendPMsg
,
1243 IDirectMusicPerformance8Impl_MusicToReferenceTime
,
1244 IDirectMusicPerformance8Impl_ReferenceToMusicTime
,
1245 IDirectMusicPerformance8Impl_IsPlaying
,
1246 IDirectMusicPerformance8Impl_GetTime
,
1247 IDirectMusicPerformance8Impl_AllocPMsg
,
1248 IDirectMusicPerformance8Impl_FreePMsg
,
1249 IDirectMusicPerformance8Impl_GetGraph
,
1250 IDirectMusicPerformance8Impl_SetGraph
,
1251 IDirectMusicPerformance8Impl_SetNotificationHandle
,
1252 IDirectMusicPerformance8Impl_GetNotificationPMsg
,
1253 IDirectMusicPerformance8Impl_AddNotificationType
,
1254 IDirectMusicPerformance8Impl_RemoveNotificationType
,
1255 IDirectMusicPerformance8Impl_AddPort
,
1256 IDirectMusicPerformance8Impl_RemovePort
,
1257 IDirectMusicPerformance8Impl_AssignPChannelBlock
,
1258 IDirectMusicPerformance8Impl_AssignPChannel
,
1259 IDirectMusicPerformance8Impl_PChannelInfo
,
1260 IDirectMusicPerformance8Impl_DownloadInstrument
,
1261 IDirectMusicPerformance8Impl_Invalidate
,
1262 IDirectMusicPerformance8Impl_GetParam
,
1263 IDirectMusicPerformance8Impl_SetParam
,
1264 IDirectMusicPerformance8Impl_GetGlobalParam
,
1265 IDirectMusicPerformance8Impl_SetGlobalParam
,
1266 IDirectMusicPerformance8Impl_GetLatencyTime
,
1267 IDirectMusicPerformance8Impl_GetQueueTime
,
1268 IDirectMusicPerformance8Impl_AdjustTime
,
1269 IDirectMusicPerformance8Impl_CloseDown
,
1270 IDirectMusicPerformance8Impl_GetResolvedTime
,
1271 IDirectMusicPerformance8Impl_MIDIToMusic
,
1272 IDirectMusicPerformance8Impl_MusicToMIDI
,
1273 IDirectMusicPerformance8Impl_TimeToRhythm
,
1274 IDirectMusicPerformance8Impl_RhythmToTime
,
1275 IDirectMusicPerformance8Impl_InitAudio
,
1276 IDirectMusicPerformance8Impl_PlaySegmentEx
,
1277 IDirectMusicPerformance8Impl_StopEx
,
1278 IDirectMusicPerformance8Impl_ClonePMsg
,
1279 IDirectMusicPerformance8Impl_CreateAudioPath
,
1280 IDirectMusicPerformance8Impl_CreateStandardAudioPath
,
1281 IDirectMusicPerformance8Impl_SetDefaultAudioPath
,
1282 IDirectMusicPerformance8Impl_GetDefaultAudioPath
,
1283 IDirectMusicPerformance8Impl_GetParamEx
1286 /* for ClassFactory */
1287 HRESULT WINAPI
create_dmperformance(REFIID lpcGUID
, void **ppobj
)
1289 IDirectMusicPerformance8Impl
*obj
;
1291 TRACE("(%s, %p)\n", debugstr_guid(lpcGUID
), ppobj
);
1293 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicPerformance8Impl
));
1296 return E_OUTOFMEMORY
;
1298 obj
->IDirectMusicPerformance8_iface
.lpVtbl
= &DirectMusicPerformance8_Vtbl
;
1299 obj
->ref
= 0; /* will be inited by QueryInterface */
1300 obj
->pDefaultPath
= NULL
;
1301 InitializeCriticalSection(&obj
->safe
);
1302 obj
->safe
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IDirectMusicPerformance8Impl*->safe");
1303 wine_rb_init(&obj
->pchannels
, pchannel_block_compare
);
1305 obj
->rtLatencyTime
= 100; /* 100 ms TO FIX */
1306 obj
->dwBumperLength
= 50; /* 50 ms default */
1307 obj
->dwPrepareTime
= 1000; /* 1000 ms default */
1308 return IDirectMusicPerformance8Impl_QueryInterface(&obj
->IDirectMusicPerformance8_iface
,