Release 4.0.
[wine.git] / dlls / dmime / performance.c
blob6e4dae6be7f152dddba9f92e84b41056e637edce
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"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
25 typedef struct IDirectMusicPerformance8Impl {
26 IDirectMusicPerformance8 IDirectMusicPerformance8_iface;
27 LONG ref;
28 IDirectMusic8 *dmusic;
29 IDirectSound *dsound;
30 IDirectMusicGraph *pToolGraph;
31 DMUS_AUDIOPARAMS params;
32 BOOL fAutoDownload;
33 char cMasterGrooveLevel;
34 float fMasterTempo;
35 long lMasterVolume;
36 /* performance channels */
37 DMUSIC_PRIVATE_PCHANNEL PChannel[32];
38 /* IDirectMusicPerformance8Impl fields */
39 IDirectMusicAudioPath *pDefaultPath;
40 HANDLE hNotification;
41 REFERENCE_TIME rtMinimum;
42 REFERENCE_TIME rtLatencyTime;
43 DWORD dwBumperLength;
44 DWORD dwPrepareTime;
45 /** Message Processing */
46 HANDLE procThread;
47 DWORD procThreadId;
48 REFERENCE_TIME procThreadStartTime;
49 BOOL procThreadTicStarted;
50 CRITICAL_SECTION safe;
51 struct DMUS_PMSGItem *head;
52 struct DMUS_PMSGItem *imm_head;
53 } IDirectMusicPerformance8Impl;
55 typedef struct DMUS_PMSGItem DMUS_PMSGItem;
56 struct DMUS_PMSGItem {
57 DMUS_PMSGItem* next;
58 DMUS_PMSGItem* prev;
60 REFERENCE_TIME rtItemTime;
61 BOOL bInUse;
62 DWORD cb;
63 DMUS_PMSG pMsg;
66 #define DMUS_PMSGToItem(pMSG) ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) - offsetof(DMUS_PMSGItem, pMsg)))
67 #define DMUS_ItemToPMSG(pItem) (&(pItem->pMsg))
68 #define DMUS_ItemRemoveFromQueue(This,pItem) \
70 if (pItem->prev) pItem->prev->next = pItem->next;\
71 if (pItem->next) pItem->next->prev = pItem->prev;\
72 if (This->head == pItem) This->head = pItem->next;\
73 if (This->imm_head == pItem) This->imm_head = pItem->next;\
74 pItem->bInUse = FALSE;\
77 #define PROCESSMSG_START (WM_APP + 0)
78 #define PROCESSMSG_EXIT (WM_APP + 1)
79 #define PROCESSMSG_REMOVE (WM_APP + 2)
80 #define PROCESSMSG_ADD (WM_APP + 4)
83 static DMUS_PMSGItem* ProceedMsg(IDirectMusicPerformance8Impl* This, DMUS_PMSGItem* cur) {
84 if (cur->pMsg.dwType == DMUS_PMSGT_NOTIFICATION) {
85 SetEvent(This->hNotification);
87 DMUS_ItemRemoveFromQueue(This, cur);
88 switch (cur->pMsg.dwType) {
89 case DMUS_PMSGT_WAVE:
90 case DMUS_PMSGT_TEMPO:
91 case DMUS_PMSGT_STOP:
92 default:
93 FIXME("Unhandled PMsg Type: 0x%x\n", cur->pMsg.dwType);
94 break;
96 return cur;
99 static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
100 IDirectMusicPerformance8Impl* This = lpParam;
101 DWORD timeOut = INFINITE;
102 MSG msg;
103 HRESULT hr;
104 REFERENCE_TIME rtCurTime;
105 DMUS_PMSGItem* it = NULL;
106 DMUS_PMSGItem* cur = NULL;
107 DMUS_PMSGItem* it_next = NULL;
109 while (TRUE) {
110 DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;
112 if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
113 timeOut = INFINITE;
115 EnterCriticalSection(&This->safe);
116 hr = IDirectMusicPerformance8_GetTime(&This->IDirectMusicPerformance8_iface, &rtCurTime, NULL);
117 if (FAILED(hr)) {
118 goto outrefresh;
121 for (it = This->imm_head; NULL != it; ) {
122 it_next = it->next;
123 cur = ProceedMsg(This, it);
124 HeapFree(GetProcessHeap(), 0, cur);
125 it = it_next;
128 for (it = This->head; NULL != it && it->rtItemTime < rtCurTime + dwDec; ) {
129 it_next = it->next;
130 cur = ProceedMsg(This, it);
131 HeapFree(GetProcessHeap(), 0, cur);
132 it = it_next;
134 if (NULL != it) {
135 timeOut = ( it->rtItemTime - rtCurTime ) + This->rtLatencyTime;
138 outrefresh:
139 LeaveCriticalSection(&This->safe);
141 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
142 /** if hwnd we suppose that is a windows event ... */
143 if (NULL != msg.hwnd) {
144 TranslateMessage(&msg);
145 DispatchMessageA(&msg);
146 } else {
147 switch (msg.message) {
148 case WM_QUIT:
149 case PROCESSMSG_EXIT:
150 goto outofthread;
151 case PROCESSMSG_START:
152 break;
153 case PROCESSMSG_ADD:
154 break;
155 case PROCESSMSG_REMOVE:
156 break;
157 default:
158 ERR("Unhandled message %u. Critical Path\n", msg.message);
159 break;
164 /** here we should run a little of current AudioPath */
168 outofthread:
169 TRACE("(%p): Exiting\n", This);
171 return 0;
174 static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UINT iMsg) {
175 if (FALSE == This->procThreadTicStarted && PROCESSMSG_EXIT != iMsg) {
176 BOOL res;
177 This->procThread = CreateThread(NULL, 0, ProcessMsgThread, This, 0, &This->procThreadId);
178 if (NULL == This->procThread) return FALSE;
179 SetThreadPriority(This->procThread, THREAD_PRIORITY_TIME_CRITICAL);
180 This->procThreadTicStarted = TRUE;
181 while(1) {
182 res = PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
183 /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
184 if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID))
185 Sleep(0);
186 else
187 break;
189 return res;
191 return PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
194 static inline IDirectMusicPerformance8Impl *impl_from_IDirectMusicPerformance8(IDirectMusicPerformance8 *iface)
196 return CONTAINING_RECORD(iface, IDirectMusicPerformance8Impl, IDirectMusicPerformance8_iface);
199 /* IDirectMusicPerformance8 IUnknown part: */
200 static HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface(IDirectMusicPerformance8 *iface,
201 REFIID riid, void **ppv)
203 TRACE("(%p, %s,%p)\n", iface, debugstr_dmguid(riid), ppv);
205 if (IsEqualIID (riid, &IID_IUnknown) ||
206 IsEqualIID (riid, &IID_IDirectMusicPerformance) ||
207 IsEqualIID (riid, &IID_IDirectMusicPerformance2) ||
208 IsEqualIID (riid, &IID_IDirectMusicPerformance8)) {
209 *ppv = iface;
210 IUnknown_AddRef(iface);
211 return S_OK;
214 WARN("(%p, %s,%p): not found\n", iface, debugstr_dmguid(riid), ppv);
215 return E_NOINTERFACE;
218 static ULONG WINAPI IDirectMusicPerformance8Impl_AddRef(IDirectMusicPerformance8 *iface)
220 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
221 ULONG ref = InterlockedIncrement(&This->ref);
223 TRACE("(%p): AddRef from %d\n", This, ref - 1);
225 DMIME_LockModule();
227 return ref;
230 static ULONG WINAPI IDirectMusicPerformance8Impl_Release(IDirectMusicPerformance8 *iface)
232 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
233 ULONG ref = InterlockedDecrement(&This->ref);
235 TRACE("(%p): ReleaseRef to %d\n", This, ref);
237 if (ref == 0) {
238 This->safe.DebugInfo->Spare[0] = 0;
239 DeleteCriticalSection(&This->safe);
240 HeapFree(GetProcessHeap(), 0, This);
243 DMIME_UnlockModule();
245 return ref;
248 /* IDirectMusicPerformanceImpl IDirectMusicPerformance Interface part: */
249 static HRESULT WINAPI IDirectMusicPerformance8Impl_Init(IDirectMusicPerformance8 *iface,
250 IDirectMusic **dmusic, IDirectSound *dsound, HWND hwnd)
252 TRACE("(%p, %p, %p, %p)\n", iface, dmusic, dsound, hwnd);
254 return IDirectMusicPerformance8_InitAudio(iface, dmusic, dsound ? &dsound : NULL, hwnd, 0, 0,
255 0, NULL);
258 static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegment(IDirectMusicPerformance8 *iface,
259 IDirectMusicSegment *pSegment, DWORD dwFlags, __int64 i64StartTime,
260 IDirectMusicSegmentState **ppSegmentState)
262 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
264 FIXME("(%p, %p, %d, 0x%s, %p): stub\n", This, pSegment, dwFlags,
265 wine_dbgstr_longlong(i64StartTime), ppSegmentState);
266 if (ppSegmentState)
267 return create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**)ppSegmentState);
268 return S_OK;
271 static HRESULT WINAPI IDirectMusicPerformance8Impl_Stop(IDirectMusicPerformance8 *iface,
272 IDirectMusicSegment *pSegment, IDirectMusicSegmentState *pSegmentState, MUSIC_TIME mtTime,
273 DWORD dwFlags)
275 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
277 FIXME("(%p, %p, %p, %d, %d): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags);
278 return S_OK;
281 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState(IDirectMusicPerformance8 *iface,
282 IDirectMusicSegmentState **ppSegmentState, MUSIC_TIME mtTime)
284 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
286 FIXME("(%p,%p, %d): stub\n", This, ppSegmentState, mtTime);
287 return S_OK;
290 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime(IDirectMusicPerformance8 *iface,
291 DWORD dwMilliSeconds)
293 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
295 TRACE("(%p, %d)\n", This, dwMilliSeconds);
296 This->dwPrepareTime = dwMilliSeconds;
297 return S_OK;
300 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime(IDirectMusicPerformance8 *iface,
301 DWORD *pdwMilliSeconds)
303 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
305 TRACE("(%p, %p)\n", This, pdwMilliSeconds);
306 if (NULL == pdwMilliSeconds) {
307 return E_POINTER;
309 *pdwMilliSeconds = This->dwPrepareTime;
310 return S_OK;
313 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength(IDirectMusicPerformance8 *iface,
314 DWORD dwMilliSeconds)
316 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
318 TRACE("(%p, %d)\n", This, dwMilliSeconds);
319 This->dwBumperLength = dwMilliSeconds;
320 return S_OK;
323 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength(IDirectMusicPerformance8 *iface,
324 DWORD *pdwMilliSeconds)
326 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
328 TRACE("(%p, %p)\n", This, pdwMilliSeconds);
329 if (NULL == pdwMilliSeconds) {
330 return E_POINTER;
332 *pdwMilliSeconds = This->dwBumperLength;
333 return S_OK;
336 static HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg(IDirectMusicPerformance8 *iface,
337 DMUS_PMSG *pPMSG)
339 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
340 DMUS_PMSGItem* pItem = NULL;
341 DMUS_PMSGItem* it = NULL;
342 DMUS_PMSGItem* prev_it = NULL;
343 DMUS_PMSGItem** queue = NULL;
345 FIXME("(%p, %p): stub\n", This, pPMSG);
347 if (NULL == pPMSG) {
348 return E_POINTER;
350 pItem = DMUS_PMSGToItem(pPMSG);
351 if (pItem->bInUse) {
352 return DMUS_E_ALREADY_SENT;
355 /* TODO: Valid Flags */
356 /* TODO: DMUS_PMSGF_MUSICTIME */
357 pItem->rtItemTime = pPMSG->rtTime;
359 if (pPMSG->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) {
360 queue = &This->imm_head;
361 } else {
362 queue = &This->head;
365 EnterCriticalSection(&This->safe);
366 for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
367 prev_it = it;
369 if (NULL == prev_it) {
370 pItem->prev = NULL;
371 if (NULL != *queue) pItem->next = (*queue)->next;
372 /*assert( NULL == pItem->next->prev );*/
373 if (NULL != pItem->next) pItem->next->prev = pItem;
374 *queue = pItem;
375 } else {
376 pItem->prev = prev_it;
377 pItem->next = prev_it->next;
378 prev_it->next = pItem;
379 if (NULL != pItem->next) pItem->next->prev = pItem;
381 LeaveCriticalSection(&This->safe);
383 /** now in use, prevent from stupid Frees */
384 pItem->bInUse = TRUE;
385 return S_OK;
388 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToReferenceTime(IDirectMusicPerformance8 *iface,
389 MUSIC_TIME mtTime, REFERENCE_TIME *prtTime)
391 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
393 FIXME("(%p, %d, %p): stub\n", This, mtTime, prtTime);
394 return S_OK;
397 static HRESULT WINAPI IDirectMusicPerformance8Impl_ReferenceToMusicTime(IDirectMusicPerformance8 *iface,
398 REFERENCE_TIME rtTime, MUSIC_TIME *pmtTime)
400 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
402 FIXME("(%p, 0x%s, %p): stub\n", This, wine_dbgstr_longlong(rtTime), pmtTime);
403 return S_OK;
406 static HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying(IDirectMusicPerformance8 *iface,
407 IDirectMusicSegment *pSegment, IDirectMusicSegmentState *pSegState)
409 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
411 FIXME("(%p, %p, %p): stub\n", This, pSegment, pSegState);
412 return S_FALSE;
415 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime(IDirectMusicPerformance8 *iface,
416 REFERENCE_TIME *prtNow, MUSIC_TIME *pmtNow)
418 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
419 HRESULT hr = S_OK;
420 REFERENCE_TIME rtCur = 0;
422 /*TRACE("(%p, %p, %p)\n", This, prtNow, pmtNow); */
423 if (This->procThreadTicStarted) {
424 rtCur = ((REFERENCE_TIME) GetTickCount() * 10000) - This->procThreadStartTime;
425 } else {
426 /*return DMUS_E_NO_MASTER_CLOCK;*/
428 if (NULL != prtNow) {
429 *prtNow = rtCur;
431 if (NULL != pmtNow) {
432 hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, rtCur, pmtNow);
434 return hr;
437 static HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg(IDirectMusicPerformance8 *iface,
438 ULONG cb, DMUS_PMSG **ppPMSG)
440 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
441 DMUS_PMSGItem* pItem = NULL;
443 FIXME("(%p, %d, %p): stub\n", This, cb, ppPMSG);
445 if (sizeof(DMUS_PMSG) > cb) {
446 return E_INVALIDARG;
448 if (NULL == ppPMSG) {
449 return E_POINTER;
451 pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb - sizeof(DMUS_PMSG) + sizeof(DMUS_PMSGItem));
452 if (NULL == pItem) {
453 return E_OUTOFMEMORY;
455 pItem->pMsg.dwSize = cb;
456 *ppPMSG = DMUS_ItemToPMSG(pItem);
457 return S_OK;
460 static HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg(IDirectMusicPerformance8 *iface,
461 DMUS_PMSG *pPMSG)
463 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
464 DMUS_PMSGItem* pItem = NULL;
466 FIXME("(%p, %p): stub\n", This, pPMSG);
468 if (NULL == pPMSG) {
469 return E_POINTER;
471 pItem = DMUS_PMSGToItem(pPMSG);
472 if (pItem->bInUse) {
473 /** prevent for freeing PMsg in queue (ie to be processed) */
474 return DMUS_E_CANNOT_FREE;
476 /** now we can remove it safely */
477 EnterCriticalSection(&This->safe);
478 DMUS_ItemRemoveFromQueue( This, pItem );
479 LeaveCriticalSection(&This->safe);
481 /** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */
482 HeapFree(GetProcessHeap(), 0, pItem);
483 return S_OK;
486 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGraph(IDirectMusicPerformance8 *iface,
487 IDirectMusicGraph **ppGraph)
489 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
491 FIXME("(%p, %p): to check\n", This, ppGraph);
492 if (NULL != This->pToolGraph) {
493 *ppGraph = This->pToolGraph;
494 IDirectMusicGraph_AddRef(*ppGraph);
495 } else {
496 return E_FAIL;
498 return S_OK;
501 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGraph(IDirectMusicPerformance8 *iface,
502 IDirectMusicGraph *pGraph)
504 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
506 FIXME("(%p, %p): to check\n", This, pGraph);
508 if (NULL != This->pToolGraph) {
509 /* Todo clean buffers and tools before */
510 IDirectMusicGraph_Release(This->pToolGraph);
512 This->pToolGraph = pGraph;
513 if (NULL != This->pToolGraph) {
514 IDirectMusicGraph_AddRef(This->pToolGraph);
516 return S_OK;
519 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetNotificationHandle(IDirectMusicPerformance8 *iface,
520 HANDLE hNotification, REFERENCE_TIME rtMinimum)
522 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
524 FIXME("(%p, %p, 0x%s): stub\n", This, hNotification, wine_dbgstr_longlong(rtMinimum));
525 This->hNotification = hNotification;
526 if (rtMinimum) This->rtMinimum = rtMinimum;
527 return S_OK;
530 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetNotificationPMsg(IDirectMusicPerformance8 *iface,
531 DMUS_NOTIFICATION_PMSG **ppNotificationPMsg)
533 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
535 FIXME("(%p, %p): stub\n", This, ppNotificationPMsg);
536 if (NULL == ppNotificationPMsg) {
537 return E_POINTER;
542 return S_FALSE;
543 /*return S_OK;*/
546 static HRESULT WINAPI IDirectMusicPerformance8Impl_AddNotificationType(IDirectMusicPerformance8 *iface,
547 REFGUID rguidNotificationType)
549 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
551 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
552 return S_OK;
555 static HRESULT WINAPI IDirectMusicPerformance8Impl_RemoveNotificationType(IDirectMusicPerformance8 *iface,
556 REFGUID rguidNotificationType)
558 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
560 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
561 return S_OK;
564 static HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort(IDirectMusicPerformance8 *iface,
565 IDirectMusicPort *pPort)
567 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
568 HRESULT hr = E_FAIL;
570 FIXME("(%p, %p): stub\n", This, pPort);
571 if (!This->dmusic)
572 return DMUS_E_NOT_INIT;
573 if (NULL == pPort) {
574 GUID port_guid;
575 IDirectMusicPort* pDefaultPort = NULL;
576 DMUS_PORTPARAMS params;
577 int i, j;
578 hr = IDirectMusic8_GetDefaultPort(This->dmusic, &port_guid);
579 if (FAILED(hr)) return hr;
580 ZeroMemory(&params, sizeof(params));
581 params.dwSize = sizeof(params);
582 params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_SHARE;
583 params.dwChannelGroups = 1;
584 params.fShare = TRUE;
585 hr = IDirectMusic8_CreatePort(This->dmusic, &port_guid, &params, &pDefaultPort, NULL);
586 if (FAILED(hr)) return hr;
587 hr = IDirectMusicPort_Activate(pDefaultPort, TRUE);
588 if (FAILED(hr)) { IDirectMusicPort_Release(pDefaultPort); return hr; }
589 j = 0;
590 for (i = 0; i < 16; ++i) {
591 if (NULL == This->PChannel[i].port) {
592 This->PChannel[i].port = pPort;
593 This->PChannel[i].group = 0;
594 This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
595 j++;
598 } else {
599 IDirectMusicPort_AddRef(pPort);
602 * We should remember added Ports (for example using a list)
603 * and control if Port is registered for each api who use ports
605 return S_OK;
608 static HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort(IDirectMusicPerformance8 *iface,
609 IDirectMusicPort *pPort)
611 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
613 FIXME("(%p, %p): stub\n", This, pPort);
614 IDirectMusicPort_Release (pPort);
615 return S_OK;
618 static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMusicPerformance8 *iface,
619 DWORD dwBlockNum, IDirectMusicPort *pPort, DWORD dwGroup)
621 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
622 int i, j, range /* min value in range */;
624 FIXME("(%p, %d, %p, %d): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1);
625 if (NULL == pPort) return E_POINTER;
627 range = 16 * dwBlockNum;
628 j = 0;
629 for (i = range; i < range+16; i++) {
630 /*TRACE("Setting PChannel[%i] to port %p, group %ld, MIDI port %i\n", i, pPort, dwGroup-1, j); */
631 This->PChannel[i].port = pPort;
632 This->PChannel[i].group = dwGroup - 1; /* first index is always zero */
633 This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
634 j++;
636 /*if (dwGroup > 2) return S_FALSE;*/
638 return S_OK;
641 static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel(IDirectMusicPerformance8 *iface,
642 DWORD PChannel, IDirectMusicPort *port, DWORD group, DWORD MChannel)
644 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
646 TRACE("(%p)->(%d, %p, %d, %d)\n", This, PChannel, port, group, MChannel);
648 if (!port)
649 return E_POINTER;
651 This->PChannel[PChannel].port = port;
652 This->PChannel[PChannel].group = group;
653 This->PChannel[PChannel].channel = MChannel;
655 return S_OK;
658 static HRESULT WINAPI IDirectMusicPerformance8Impl_PChannelInfo(IDirectMusicPerformance8 *iface,
659 DWORD PChannel, IDirectMusicPort **port, DWORD *group, DWORD *MChannel)
661 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
662 DMUS_PORTPARAMS8 port_params;
663 GUID default_port;
665 FIXME("(%p)->(%d, %p, %p, %p): stub\n", This, PChannel, port, group, MChannel);
667 port_params.dwSize = sizeof(DMUS_PORTPARAMS8);
668 port_params.dwValidParams = 0;
669 IDirectMusic8_GetDefaultPort(This->dmusic, &default_port);
670 IDirectMusic8_CreatePort(This->dmusic, &default_port, &port_params, port, NULL);
672 return S_OK;
675 static HRESULT WINAPI IDirectMusicPerformance8Impl_DownloadInstrument(IDirectMusicPerformance8 *iface,
676 IDirectMusicInstrument *pInst, DWORD dwPChannel,
677 IDirectMusicDownloadedInstrument **ppDownInst, DMUS_NOTERANGE *pNoteRanges,
678 DWORD dwNumNoteRanges, IDirectMusicPort **ppPort, DWORD *pdwGroup, DWORD *pdwMChannel)
680 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
682 FIXME("(%p, %p, %d, %p, %p, %d, %p, %p, %p): stub\n", This, pInst, dwPChannel, ppDownInst, pNoteRanges, dwNumNoteRanges, ppPort, pdwGroup, pdwMChannel);
683 return S_OK;
686 static HRESULT WINAPI IDirectMusicPerformance8Impl_Invalidate(IDirectMusicPerformance8 *iface,
687 MUSIC_TIME mtTime, DWORD dwFlags)
689 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
691 FIXME("(%p, %d, %d): stub\n", This, mtTime, dwFlags);
692 return S_OK;
695 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParam(IDirectMusicPerformance8 *iface,
696 REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime,
697 MUSIC_TIME *pmtNext, void *pParam)
699 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
701 FIXME("(%p, %s, %d, %d, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
702 return S_OK;
705 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetParam(IDirectMusicPerformance8 *iface,
706 REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void *pParam)
708 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
710 FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
711 return S_OK;
714 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGlobalParam(IDirectMusicPerformance8 *iface,
715 REFGUID rguidType, void *pParam, DWORD dwSize)
717 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
719 TRACE("(%p, %s, %p, %d): stub\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
721 if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload))
722 memcpy(pParam, &This->fAutoDownload, sizeof(This->fAutoDownload));
723 if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel))
724 memcpy(pParam, &This->cMasterGrooveLevel, sizeof(This->cMasterGrooveLevel));
725 if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo))
726 memcpy(pParam, &This->fMasterTempo, sizeof(This->fMasterTempo));
727 if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume))
728 memcpy(pParam, &This->lMasterVolume, sizeof(This->lMasterVolume));
730 return S_OK;
733 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam(IDirectMusicPerformance8 *iface,
734 REFGUID rguidType, void *pParam, DWORD dwSize)
736 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
738 TRACE("(%p, %s, %p, %d)\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
740 if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload)) {
741 memcpy(&This->fAutoDownload, pParam, dwSize);
742 TRACE("=> AutoDownload set to %d\n", This->fAutoDownload);
744 if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel)) {
745 memcpy(&This->cMasterGrooveLevel, pParam, dwSize);
746 TRACE("=> MasterGrooveLevel set to %i\n", This->cMasterGrooveLevel);
748 if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo)) {
749 memcpy(&This->fMasterTempo, pParam, dwSize);
750 TRACE("=> MasterTempo set to %f\n", This->fMasterTempo);
752 if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) {
753 memcpy(&This->lMasterVolume, pParam, dwSize);
754 TRACE("=> MasterVolume set to %li\n", This->lMasterVolume);
757 return S_OK;
760 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime(IDirectMusicPerformance8 *iface,
761 REFERENCE_TIME *prtTime)
763 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
765 TRACE("(%p, %p): stub\n", This, prtTime);
766 *prtTime = This->rtLatencyTime;
767 return S_OK;
770 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetQueueTime(IDirectMusicPerformance8 *iface,
771 REFERENCE_TIME *prtTime)
774 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
776 FIXME("(%p, %p): stub\n", This, prtTime);
777 return S_OK;
780 static HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime(IDirectMusicPerformance8 *iface,
781 REFERENCE_TIME rtAmount)
783 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
785 FIXME("(%p, 0x%s): stub\n", This, wine_dbgstr_longlong(rtAmount));
786 return S_OK;
789 static HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown(IDirectMusicPerformance8 *iface)
791 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
793 FIXME("(%p): semi-stub\n", This);
795 if (PostMessageToProcessMsgThread(This, PROCESSMSG_EXIT)) {
796 WaitForSingleObject(This->procThread, INFINITE);
797 This->procThreadTicStarted = FALSE;
798 CloseHandle(This->procThread);
800 if (This->dsound) {
801 IDirectSound_Release(This->dsound);
802 This->dsound = NULL;
804 if (This->dmusic) {
805 IDirectMusic_SetDirectSound(This->dmusic, NULL, NULL);
806 IDirectMusic8_Release(This->dmusic);
807 This->dmusic = NULL;
809 return S_OK;
812 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetResolvedTime(IDirectMusicPerformance8 *iface,
813 REFERENCE_TIME rtTime, REFERENCE_TIME *prtResolved, DWORD dwTimeResolveFlags)
815 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
817 FIXME("(%p, 0x%s, %p, %d): stub\n", This, wine_dbgstr_longlong(rtTime),
818 prtResolved, dwTimeResolveFlags);
819 return S_OK;
822 static HRESULT WINAPI IDirectMusicPerformance8Impl_MIDIToMusic(IDirectMusicPerformance8 *iface,
823 BYTE bMIDIValue, DMUS_CHORD_KEY *pChord, BYTE bPlayMode, BYTE bChordLevel,
824 WORD *pwMusicValue)
826 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
828 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, bMIDIValue, pChord, bPlayMode, bChordLevel, pwMusicValue);
829 return S_OK;
832 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToMIDI(IDirectMusicPerformance8 *iface,
833 WORD wMusicValue, DMUS_CHORD_KEY *pChord, BYTE bPlayMode, BYTE bChordLevel,
834 BYTE *pbMIDIValue)
836 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
838 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, wMusicValue, pChord, bPlayMode, bChordLevel, pbMIDIValue);
839 return S_OK;
842 static HRESULT WINAPI IDirectMusicPerformance8Impl_TimeToRhythm(IDirectMusicPerformance8 *iface,
843 MUSIC_TIME mtTime, DMUS_TIMESIGNATURE *pTimeSig, WORD *pwMeasure, BYTE *pbBeat,
844 BYTE *pbGrid, short *pnOffset)
846 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
848 FIXME("(%p, %d, %p, %p, %p, %p, %p): stub\n", This, mtTime, pTimeSig, pwMeasure, pbBeat, pbGrid, pnOffset);
849 return S_OK;
852 static HRESULT WINAPI IDirectMusicPerformance8Impl_RhythmToTime(IDirectMusicPerformance8 *iface,
853 WORD wMeasure, BYTE bBeat, BYTE bGrid, short nOffset, DMUS_TIMESIGNATURE *pTimeSig,
854 MUSIC_TIME *pmtTime)
856 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
858 FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This, wMeasure, bBeat, bGrid, nOffset, pTimeSig, pmtTime);
859 return S_OK;
862 /* IDirectMusicPerformance8 Interface part follow: */
863 static HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio(IDirectMusicPerformance8 *iface,
864 IDirectMusic **dmusic, IDirectSound **dsound, HWND hwnd, DWORD default_path_type,
865 DWORD num_channels, DWORD flags, DMUS_AUDIOPARAMS *params)
867 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
868 HRESULT hr = S_OK;
870 TRACE("(%p, %p, %p, %p, %x, %u, %x, %p)\n", This, dmusic, dsound, hwnd, default_path_type,
871 num_channels, flags, params);
873 if (This->dmusic)
874 return DMUS_E_ALREADY_INITED;
876 if (!dmusic || !*dmusic) {
877 hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8,
878 (void **)&This->dmusic);
879 if (FAILED(hr))
880 return hr;
881 } else {
882 This->dmusic = (IDirectMusic8 *)*dmusic;
883 IDirectMusic8_AddRef(This->dmusic);
886 if (!dsound || !*dsound) {
887 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&This->dsound, NULL);
888 if (FAILED(hr))
889 goto error;
890 hr = IDirectSound_SetCooperativeLevel(This->dsound, hwnd ? hwnd : GetForegroundWindow(),
891 DSSCL_PRIORITY);
892 if (FAILED(hr))
893 goto error;
894 } else {
895 This->dsound = *dsound;
896 IDirectSound_AddRef(This->dsound);
899 hr = IDirectMusic8_SetDirectSound(This->dmusic, This->dsound, NULL);
900 if (FAILED(hr))
901 goto error;
903 if (!params) {
904 This->params.dwSize = sizeof(DMUS_AUDIOPARAMS);
905 This->params.fInitNow = FALSE;
906 This->params.dwValidData = DMUS_AUDIOPARAMS_FEATURES | DMUS_AUDIOPARAMS_VOICES |
907 DMUS_AUDIOPARAMS_SAMPLERATE | DMUS_AUDIOPARAMS_DEFAULTSYNTH;
908 This->params.dwVoices = 64;
909 This->params.dwSampleRate = 22050;
910 This->params.dwFeatures = flags;
911 This->params.clsidDefaultSynth = CLSID_DirectMusicSynthSink;
912 } else
913 This->params = *params;
915 if (default_path_type) {
916 hr = IDirectMusicPerformance8_CreateStandardAudioPath(iface, default_path_type,
917 num_channels, FALSE, &This->pDefaultPath);
918 if (FAILED(hr)) {
919 IDirectMusic8_SetDirectSound(This->dmusic, NULL, NULL);
920 goto error;
924 if (dsound && !*dsound) {
925 *dsound = This->dsound;
926 IDirectSound_AddRef(*dsound);
928 if (dmusic && !*dmusic) {
929 *dmusic = (IDirectMusic *)This->dmusic;
930 IDirectMusic_AddRef(*dmusic);
932 PostMessageToProcessMsgThread(This, PROCESSMSG_START);
934 return S_OK;
936 error:
937 if (This->dsound) {
938 IDirectSound_Release(This->dsound);
939 This->dsound = NULL;
941 if (This->dmusic) {
942 IDirectMusic8_Release(This->dmusic);
943 This->dmusic = NULL;
945 return hr;
948 static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegmentEx(IDirectMusicPerformance8 *iface,
949 IUnknown *pSource, WCHAR *pwzSegmentName, IUnknown *pTransition, DWORD dwFlags,
950 __int64 i64StartTime, IDirectMusicSegmentState **ppSegmentState, IUnknown *pFrom,
951 IUnknown *pAudioPath)
953 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
955 FIXME("(%p, %p, %p, %p, %d, 0x%s, %p, %p, %p): stub\n", This, pSource, pwzSegmentName,
956 pTransition, dwFlags, wine_dbgstr_longlong(i64StartTime), ppSegmentState, pFrom, pAudioPath);
957 if (ppSegmentState)
958 return create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**)ppSegmentState);
959 return S_OK;
962 static HRESULT WINAPI IDirectMusicPerformance8Impl_StopEx(IDirectMusicPerformance8 *iface,
963 IUnknown *pObjectToStop, __int64 i64StopTime, DWORD dwFlags)
965 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
967 FIXME("(%p, %p, 0x%s, %d): stub\n", This, pObjectToStop,
968 wine_dbgstr_longlong(i64StopTime), dwFlags);
969 return S_OK;
972 static HRESULT WINAPI IDirectMusicPerformance8Impl_ClonePMsg(IDirectMusicPerformance8 *iface,
973 DMUS_PMSG *pSourcePMSG, DMUS_PMSG **ppCopyPMSG)
975 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
977 FIXME("(%p, %p, %p): stub\n", This, pSourcePMSG, ppCopyPMSG);
978 return S_OK;
981 static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateAudioPath(IDirectMusicPerformance8 *iface,
982 IUnknown *pSourceConfig, BOOL fActivate, IDirectMusicAudioPath **ppNewPath)
984 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
985 IDirectMusicAudioPath *pPath;
987 FIXME("(%p, %p, %d, %p): stub\n", This, pSourceConfig, fActivate, ppNewPath);
989 if (NULL == ppNewPath) {
990 return E_POINTER;
993 create_dmaudiopath(&IID_IDirectMusicAudioPath, (void**)&pPath);
994 set_audiopath_perf_pointer(pPath, iface);
996 /** TODO */
998 *ppNewPath = pPath;
1000 return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate);
1003 static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateStandardAudioPath(IDirectMusicPerformance8 *iface,
1004 DWORD dwType, DWORD dwPChannelCount, BOOL fActivate, IDirectMusicAudioPath **ppNewPath)
1006 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1007 IDirectMusicAudioPath *pPath;
1008 DSBUFFERDESC desc;
1009 WAVEFORMATEX format;
1010 IDirectSoundBuffer *buffer, *primary_buffer;
1011 HRESULT hr = S_OK;
1013 FIXME("(%p)->(%d, %d, %d, %p): semi-stub\n", This, dwType, dwPChannelCount, fActivate, ppNewPath);
1015 if (NULL == ppNewPath) {
1016 return E_POINTER;
1019 *ppNewPath = NULL;
1021 /* Secondary buffer description */
1022 memset(&format, 0, sizeof(format));
1023 format.wFormatTag = WAVE_FORMAT_PCM;
1024 format.nChannels = 1;
1025 format.nSamplesPerSec = 44000;
1026 format.nAvgBytesPerSec = 44000*2;
1027 format.nBlockAlign = 2;
1028 format.wBitsPerSample = 16;
1029 format.cbSize = 0;
1031 memset(&desc, 0, sizeof(desc));
1032 desc.dwSize = sizeof(desc);
1033 desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
1034 desc.dwBufferBytes = DSBSIZE_MIN;
1035 desc.dwReserved = 0;
1036 desc.lpwfxFormat = &format;
1037 desc.guid3DAlgorithm = GUID_NULL;
1039 switch(dwType) {
1040 case DMUS_APATH_DYNAMIC_3D:
1041 desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
1042 break;
1043 case DMUS_APATH_DYNAMIC_MONO:
1044 desc.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
1045 break;
1046 case DMUS_APATH_SHARED_STEREOPLUSREVERB:
1047 /* normally we have to create 2 buffers (one for music other for reverb)
1048 * in this case. See msdn
1050 case DMUS_APATH_DYNAMIC_STEREO:
1051 desc.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
1052 format.nChannels = 2;
1053 format.nBlockAlign *= 2;
1054 format.nAvgBytesPerSec *=2;
1055 break;
1056 default:
1057 return E_INVALIDARG;
1060 /* FIXME: Should we create one secondary buffer for each PChannel? */
1061 hr = IDirectSound_CreateSoundBuffer(This->dsound, &desc, &buffer, NULL);
1062 if (FAILED(hr))
1063 return DSERR_BUFFERLOST;
1065 /* Update description for creating primary buffer */
1066 desc.dwFlags |= DSBCAPS_PRIMARYBUFFER;
1067 desc.dwBufferBytes = 0;
1068 desc.lpwfxFormat = NULL;
1070 hr = IDirectSound_CreateSoundBuffer(This->dsound, &desc, &primary_buffer, NULL);
1071 if (FAILED(hr)) {
1072 IDirectSoundBuffer_Release(buffer);
1073 return DSERR_BUFFERLOST;
1076 create_dmaudiopath(&IID_IDirectMusicAudioPath, (void**)&pPath);
1077 set_audiopath_perf_pointer(pPath, iface);
1078 set_audiopath_dsound_buffer(pPath, buffer);
1079 set_audiopath_primary_dsound_buffer(pPath, primary_buffer);
1081 *ppNewPath = pPath;
1083 TRACE(" returning IDirectMusicAudioPath interface at %p.\n", *ppNewPath);
1085 return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate);
1088 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetDefaultAudioPath(IDirectMusicPerformance8 *iface,
1089 IDirectMusicAudioPath *pAudioPath)
1091 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1093 FIXME("(%p, %p): semi-stub\n", This, pAudioPath);
1095 if (This->pDefaultPath) {
1096 IDirectMusicAudioPath_Release(This->pDefaultPath);
1097 This->pDefaultPath = NULL;
1099 This->pDefaultPath = pAudioPath;
1100 if (This->pDefaultPath) {
1101 IDirectMusicAudioPath_AddRef(This->pDefaultPath);
1102 set_audiopath_perf_pointer(This->pDefaultPath, iface);
1105 return S_OK;
1108 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetDefaultAudioPath(IDirectMusicPerformance8 *iface,
1109 IDirectMusicAudioPath **ppAudioPath)
1111 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1113 FIXME("(%p, %p): semi-stub (%p)\n", This, ppAudioPath, This->pDefaultPath);
1115 if (NULL != This->pDefaultPath) {
1116 *ppAudioPath = This->pDefaultPath;
1117 IDirectMusicAudioPath_AddRef(*ppAudioPath);
1118 } else {
1119 *ppAudioPath = NULL;
1121 return S_OK;
1124 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParamEx(IDirectMusicPerformance8 *iface,
1125 REFGUID rguidType, DWORD dwTrackID, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime,
1126 MUSIC_TIME *pmtNext, void *pParam)
1128 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1130 FIXME("(%p, %s, %d, %d, %d, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwTrackID, dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
1132 return S_OK;
1135 static const IDirectMusicPerformance8Vtbl DirectMusicPerformance8_Vtbl = {
1136 IDirectMusicPerformance8Impl_QueryInterface,
1137 IDirectMusicPerformance8Impl_AddRef,
1138 IDirectMusicPerformance8Impl_Release,
1139 IDirectMusicPerformance8Impl_Init,
1140 IDirectMusicPerformance8Impl_PlaySegment,
1141 IDirectMusicPerformance8Impl_Stop,
1142 IDirectMusicPerformance8Impl_GetSegmentState,
1143 IDirectMusicPerformance8Impl_SetPrepareTime,
1144 IDirectMusicPerformance8Impl_GetPrepareTime,
1145 IDirectMusicPerformance8Impl_SetBumperLength,
1146 IDirectMusicPerformance8Impl_GetBumperLength,
1147 IDirectMusicPerformance8Impl_SendPMsg,
1148 IDirectMusicPerformance8Impl_MusicToReferenceTime,
1149 IDirectMusicPerformance8Impl_ReferenceToMusicTime,
1150 IDirectMusicPerformance8Impl_IsPlaying,
1151 IDirectMusicPerformance8Impl_GetTime,
1152 IDirectMusicPerformance8Impl_AllocPMsg,
1153 IDirectMusicPerformance8Impl_FreePMsg,
1154 IDirectMusicPerformance8Impl_GetGraph,
1155 IDirectMusicPerformance8Impl_SetGraph,
1156 IDirectMusicPerformance8Impl_SetNotificationHandle,
1157 IDirectMusicPerformance8Impl_GetNotificationPMsg,
1158 IDirectMusicPerformance8Impl_AddNotificationType,
1159 IDirectMusicPerformance8Impl_RemoveNotificationType,
1160 IDirectMusicPerformance8Impl_AddPort,
1161 IDirectMusicPerformance8Impl_RemovePort,
1162 IDirectMusicPerformance8Impl_AssignPChannelBlock,
1163 IDirectMusicPerformance8Impl_AssignPChannel,
1164 IDirectMusicPerformance8Impl_PChannelInfo,
1165 IDirectMusicPerformance8Impl_DownloadInstrument,
1166 IDirectMusicPerformance8Impl_Invalidate,
1167 IDirectMusicPerformance8Impl_GetParam,
1168 IDirectMusicPerformance8Impl_SetParam,
1169 IDirectMusicPerformance8Impl_GetGlobalParam,
1170 IDirectMusicPerformance8Impl_SetGlobalParam,
1171 IDirectMusicPerformance8Impl_GetLatencyTime,
1172 IDirectMusicPerformance8Impl_GetQueueTime,
1173 IDirectMusicPerformance8Impl_AdjustTime,
1174 IDirectMusicPerformance8Impl_CloseDown,
1175 IDirectMusicPerformance8Impl_GetResolvedTime,
1176 IDirectMusicPerformance8Impl_MIDIToMusic,
1177 IDirectMusicPerformance8Impl_MusicToMIDI,
1178 IDirectMusicPerformance8Impl_TimeToRhythm,
1179 IDirectMusicPerformance8Impl_RhythmToTime,
1180 IDirectMusicPerformance8Impl_InitAudio,
1181 IDirectMusicPerformance8Impl_PlaySegmentEx,
1182 IDirectMusicPerformance8Impl_StopEx,
1183 IDirectMusicPerformance8Impl_ClonePMsg,
1184 IDirectMusicPerformance8Impl_CreateAudioPath,
1185 IDirectMusicPerformance8Impl_CreateStandardAudioPath,
1186 IDirectMusicPerformance8Impl_SetDefaultAudioPath,
1187 IDirectMusicPerformance8Impl_GetDefaultAudioPath,
1188 IDirectMusicPerformance8Impl_GetParamEx
1191 /* for ClassFactory */
1192 HRESULT WINAPI create_dmperformance(REFIID lpcGUID, void **ppobj)
1194 IDirectMusicPerformance8Impl *obj;
1196 TRACE("(%s, %p)\n", debugstr_guid(lpcGUID), ppobj);
1198 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicPerformance8Impl));
1199 if (NULL == obj) {
1200 *ppobj = NULL;
1201 return E_OUTOFMEMORY;
1203 obj->IDirectMusicPerformance8_iface.lpVtbl = &DirectMusicPerformance8_Vtbl;
1204 obj->ref = 0; /* will be inited by QueryInterface */
1205 obj->pDefaultPath = NULL;
1206 InitializeCriticalSection(&obj->safe);
1207 obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectMusicPerformance8Impl*->safe");
1209 obj->rtLatencyTime = 100; /* 100 ms TO FIX */
1210 obj->dwBumperLength = 50; /* 50 ms default */
1211 obj->dwPrepareTime = 1000; /* 1000 ms default */
1212 return IDirectMusicPerformance8Impl_QueryInterface(&obj->IDirectMusicPerformance8_iface,
1213 lpcGUID, ppobj);