shell32: Resize Run program window.
[wine.git] / dlls / dmime / performance.c
blob8b38e12eb289e498986c7c2ad8f3f86549deabd9
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"
24 #include "dmobject.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 */
30 struct {
31 DWORD channel; /* MIDI channel */
32 DWORD group; /* MIDI group */
33 IDirectMusicPort *port;
34 } pchannel[16];
35 struct wine_rb_entry entry;
38 typedef struct IDirectMusicPerformance8Impl {
39 IDirectMusicPerformance8 IDirectMusicPerformance8_iface;
40 LONG ref;
41 IDirectMusic8 *dmusic;
42 IDirectSound *dsound;
43 IDirectMusicGraph *pToolGraph;
44 DMUS_AUDIOPARAMS params;
45 BOOL fAutoDownload;
46 char cMasterGrooveLevel;
47 float fMasterTempo;
48 long lMasterVolume;
49 /* performance channels */
50 struct wine_rb_tree pchannels;
51 /* IDirectMusicPerformance8Impl fields */
52 IDirectMusicAudioPath *pDefaultPath;
53 HANDLE hNotification;
54 REFERENCE_TIME rtMinimum;
55 REFERENCE_TIME rtLatencyTime;
56 DWORD dwBumperLength;
57 DWORD dwPrepareTime;
58 /** Message Processing */
59 HANDLE procThread;
60 DWORD procThreadId;
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 {
70 DMUS_PMSGItem* next;
71 DMUS_PMSGItem* prev;
73 REFERENCE_TIME rtItemTime;
74 BOOL bInUse;
75 DWORD cb;
76 DMUS_PMSG pMsg;
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:
105 default:
106 FIXME("Unhandled PMsg Type: 0x%x\n", cur->pMsg.dwType);
107 break;
109 return cur;
112 static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
113 IDirectMusicPerformance8Impl* This = lpParam;
114 DWORD timeOut = INFINITE;
115 MSG msg;
116 HRESULT hr;
117 REFERENCE_TIME rtCurTime;
118 DMUS_PMSGItem* it = NULL;
119 DMUS_PMSGItem* cur = NULL;
120 DMUS_PMSGItem* it_next = NULL;
122 while (TRUE) {
123 DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;
125 if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
126 timeOut = INFINITE;
128 EnterCriticalSection(&This->safe);
129 hr = IDirectMusicPerformance8_GetTime(&This->IDirectMusicPerformance8_iface, &rtCurTime, NULL);
130 if (FAILED(hr)) {
131 goto outrefresh;
134 for (it = This->imm_head; NULL != it; ) {
135 it_next = it->next;
136 cur = ProceedMsg(This, it);
137 HeapFree(GetProcessHeap(), 0, cur);
138 it = it_next;
141 for (it = This->head; NULL != it && it->rtItemTime < rtCurTime + dwDec; ) {
142 it_next = it->next;
143 cur = ProceedMsg(This, it);
144 HeapFree(GetProcessHeap(), 0, cur);
145 it = it_next;
147 if (NULL != it) {
148 timeOut = ( it->rtItemTime - rtCurTime ) + This->rtLatencyTime;
151 outrefresh:
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);
159 } else {
160 switch (msg.message) {
161 case WM_QUIT:
162 case PROCESSMSG_EXIT:
163 goto outofthread;
164 case PROCESSMSG_START:
165 break;
166 case PROCESSMSG_ADD:
167 break;
168 case PROCESSMSG_REMOVE:
169 break;
170 default:
171 ERR("Unhandled message %u. Critical Path\n", msg.message);
172 break;
177 /** here we should run a little of current AudioPath */
181 outofthread:
182 TRACE("(%p): Exiting\n", This);
184 return 0;
187 static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UINT iMsg) {
188 if (FALSE == This->procThreadTicStarted && PROCESSMSG_EXIT != iMsg) {
189 BOOL res;
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;
194 while(1) {
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))
198 Sleep(0);
199 else
200 break;
202 return res;
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);
218 heap_free(b);
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;
226 unsigned int i;
228 entry = wine_rb_get(tree, &block_num);
229 if (entry) {
230 block = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry);
231 if (only_set_new)
232 return block;
233 } else {
234 if (!(block = heap_alloc(sizeof(*block))))
235 return NULL;
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;
244 if (!entry)
245 wine_rb_put(tree, &block->block_num, &block->entry);
247 return block;
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)) {
265 *ppv = iface;
266 IUnknown_AddRef(iface);
267 return S_OK;
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);
281 DMIME_LockModule();
283 return 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): ReleaseRef to %d\n", This, ref);
293 if (ref == 0) {
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();
302 return ref;
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,
312 0, NULL);
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);
323 if (ppSegmentState)
324 return create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**)ppSegmentState);
325 return S_OK;
328 static HRESULT WINAPI IDirectMusicPerformance8Impl_Stop(IDirectMusicPerformance8 *iface,
329 IDirectMusicSegment *pSegment, IDirectMusicSegmentState *pSegmentState, MUSIC_TIME mtTime,
330 DWORD dwFlags)
332 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
334 FIXME("(%p, %p, %p, %d, %d): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags);
335 return S_OK;
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);
344 return S_OK;
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;
354 return S_OK;
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) {
364 return E_POINTER;
366 *pdwMilliSeconds = This->dwPrepareTime;
367 return S_OK;
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;
377 return S_OK;
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) {
387 return E_POINTER;
389 *pdwMilliSeconds = This->dwBumperLength;
390 return S_OK;
393 static HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg(IDirectMusicPerformance8 *iface,
394 DMUS_PMSG *pPMSG)
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);
404 if (NULL == pPMSG) {
405 return E_POINTER;
407 pItem = DMUS_PMSGToItem(pPMSG);
408 if (pItem->bInUse) {
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;
418 } else {
419 queue = &This->head;
422 EnterCriticalSection(&This->safe);
423 for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
424 prev_it = it;
426 if (NULL == prev_it) {
427 pItem->prev = NULL;
428 if (NULL != *queue) pItem->next = (*queue)->next;
429 /*assert( NULL == pItem->next->prev );*/
430 if (NULL != pItem->next) pItem->next->prev = pItem;
431 *queue = pItem;
432 } else {
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;
442 return S_OK;
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);
451 return S_OK;
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);
460 return S_OK;
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);
469 return S_FALSE;
472 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime(IDirectMusicPerformance8 *iface,
473 REFERENCE_TIME *prtNow, MUSIC_TIME *pmtNow)
475 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
476 HRESULT hr = S_OK;
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;
482 } else {
483 /*return DMUS_E_NO_MASTER_CLOCK;*/
485 if (NULL != prtNow) {
486 *prtNow = rtCur;
488 if (NULL != pmtNow) {
489 hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, rtCur, pmtNow);
491 return hr;
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) {
503 return E_INVALIDARG;
505 if (NULL == ppPMSG) {
506 return E_POINTER;
508 pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb - sizeof(DMUS_PMSG) + sizeof(DMUS_PMSGItem));
509 if (NULL == pItem) {
510 return E_OUTOFMEMORY;
512 pItem->pMsg.dwSize = cb;
513 *ppPMSG = DMUS_ItemToPMSG(pItem);
514 return S_OK;
517 static HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg(IDirectMusicPerformance8 *iface,
518 DMUS_PMSG *pPMSG)
520 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
521 DMUS_PMSGItem* pItem = NULL;
523 FIXME("(%p, %p): stub\n", This, pPMSG);
525 if (NULL == pPMSG) {
526 return E_POINTER;
528 pItem = DMUS_PMSGToItem(pPMSG);
529 if (pItem->bInUse) {
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);
538 if (pPMSG->pTool)
539 IDirectMusicTool_Release(pPMSG->pTool);
541 if (pPMSG->pGraph)
542 IDirectMusicGraph_Release(pPMSG->pGraph);
544 if (pPMSG->punkUser)
545 IUnknown_Release(pPMSG->punkUser);
547 HeapFree(GetProcessHeap(), 0, pItem);
548 return S_OK;
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);
558 if (!graph)
559 return E_POINTER;
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);
584 return S_OK;
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;
595 if (rtMinimum)
596 This->rtMinimum = rtMinimum;
597 else if (!This->rtMinimum)
598 This->rtMinimum = 20000000; /* 2 seconds */
599 return S_OK;
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) {
609 return E_POINTER;
614 return S_FALSE;
615 /*return S_OK;*/
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));
624 return S_OK;
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));
633 return S_OK;
636 static HRESULT perf_dmport_create(IDirectMusicPerformance8Impl *perf, DMUS_PORTPARAMS *params)
638 IDirectMusicPort *port;
639 GUID guid;
640 unsigned int i;
641 HRESULT hr;
643 if (FAILED(hr = IDirectMusic8_GetDefaultPort(perf->dmusic, &guid)))
644 return hr;
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)))
651 return hr;
652 if (FAILED(hr = IDirectMusicPort_Activate(port, TRUE))) {
653 IDirectMusicPort_Release(port);
654 return hr;
656 for (i = 0; i < params->dwChannelGroups; i++)
657 pchannel_block_set(&perf->pchannels, i, port, i + 1, FALSE);
659 return S_OK;
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);
669 if (!This->dmusic)
670 return DMUS_E_NOT_INIT;
672 if (!port) {
673 DMUS_PORTPARAMS params = {
674 .dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS,
675 .dwChannelGroups = 1
678 return perf_dmport_create(This, &params);
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
686 return S_OK;
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);
696 return S_OK;
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);
706 if (!port)
707 return E_POINTER;
708 if (block_num > MAXDWORD / 16)
709 return E_INVALIDARG;
711 pchannel_block_set(&This->pchannels, block_num, port, group, FALSE);
713 return S_OK;
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);
724 if (!port)
725 return E_POINTER;
727 block = pchannel_block_set(&This->pchannels, pchannel / 16, port, 0, TRUE);
728 if (block) {
729 block->pchannel[pchannel % 16].group = group;
730 block->pchannel[pchannel % 16].channel = channel;
733 return S_OK;
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);
748 if (!entry)
749 return E_INVALIDARG;
750 block = WINE_RB_ENTRY_VALUE(entry, struct pchannel_block, entry);
752 if (port) {
753 *port = block->pchannel[index].port;
754 IDirectMusicPort_AddRef(*port);
756 if (group)
757 *group = block->pchannel[index].group;
758 if (channel)
759 *channel = block->pchannel[index].channel;
761 return S_OK;
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);
772 return S_OK;
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);
781 return S_OK;
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);
791 return S_OK;
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);
800 return S_OK;
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));
819 return S_OK;
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);
846 return S_OK;
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;
856 return S_OK;
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);
866 return S_OK;
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));
875 return S_OK;
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);
889 if (This->dsound) {
890 IDirectSound_Release(This->dsound);
891 This->dsound = NULL;
893 if (This->dmusic) {
894 IDirectMusic_SetDirectSound(This->dmusic, NULL, NULL);
895 IDirectMusic8_Release(This->dmusic);
896 This->dmusic = NULL;
898 return S_OK;
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);
908 return S_OK;
911 static HRESULT WINAPI IDirectMusicPerformance8Impl_MIDIToMusic(IDirectMusicPerformance8 *iface,
912 BYTE bMIDIValue, DMUS_CHORD_KEY *pChord, BYTE bPlayMode, BYTE bChordLevel,
913 WORD *pwMusicValue)
915 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
917 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, bMIDIValue, pChord, bPlayMode, bChordLevel, pwMusicValue);
918 return S_OK;
921 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToMIDI(IDirectMusicPerformance8 *iface,
922 WORD wMusicValue, DMUS_CHORD_KEY *pChord, BYTE bPlayMode, BYTE bChordLevel,
923 BYTE *pbMIDIValue)
925 IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
927 FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, wMusicValue, pChord, bPlayMode, bChordLevel, pbMIDIValue);
928 return S_OK;
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);
938 return S_OK;
941 static HRESULT WINAPI IDirectMusicPerformance8Impl_RhythmToTime(IDirectMusicPerformance8 *iface,
942 WORD wMeasure, BYTE bBeat, BYTE bGrid, short nOffset, DMUS_TIMESIGNATURE *pTimeSig,
943 MUSIC_TIME *pmtTime)
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);
948 return S_OK;
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);
957 HRESULT hr = S_OK;
959 TRACE("(%p, %p, %p, %p, %x, %u, %x, %p)\n", This, dmusic, dsound, hwnd, default_path_type,
960 num_channels, flags, params);
962 if (This->dmusic)
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);
968 if (FAILED(hr))
969 return hr;
970 } else {
971 This->dmusic = (IDirectMusic8 *)*dmusic;
972 IDirectMusic8_AddRef(This->dmusic);
975 if (!dsound || !*dsound) {
976 hr = DirectSoundCreate8(NULL, (IDirectSound8 **)&This->dsound, NULL);
977 if (FAILED(hr))
978 goto error;
979 hr = IDirectSound_SetCooperativeLevel(This->dsound, hwnd ? hwnd : GetForegroundWindow(),
980 DSSCL_PRIORITY);
981 if (FAILED(hr))
982 goto error;
983 } else {
984 This->dsound = *dsound;
985 IDirectSound_AddRef(This->dsound);
988 hr = IDirectMusic8_SetDirectSound(This->dmusic, This->dsound, NULL);
989 if (FAILED(hr))
990 goto error;
992 if (!params) {
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;
1001 } else
1002 This->params = *params;
1004 if (default_path_type) {
1005 hr = IDirectMusicPerformance8_CreateStandardAudioPath(iface, default_path_type,
1006 num_channels, FALSE, &This->pDefaultPath);
1007 if (FAILED(hr)) {
1008 IDirectMusic8_SetDirectSound(This->dmusic, NULL, NULL);
1009 goto error;
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);
1023 return S_OK;
1025 error:
1026 if (This->dsound) {
1027 IDirectSound_Release(This->dsound);
1028 This->dsound = NULL;
1030 if (This->dmusic) {
1031 IDirectMusic8_Release(This->dmusic);
1032 This->dmusic = NULL;
1034 return hr;
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);
1046 if (ppSegmentState)
1047 return create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**)ppSegmentState);
1048 return S_OK;
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);
1058 return S_OK;
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);
1067 return S_OK;
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) {
1079 return E_POINTER;
1082 create_dmaudiopath(&IID_IDirectMusicAudioPath, (void**)&pPath);
1083 set_audiopath_perf_pointer(pPath, iface);
1085 /** TODO */
1087 *ppNewPath = pPath;
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;
1097 DSBUFFERDESC desc;
1098 WAVEFORMATEX format;
1099 DMUS_PORTPARAMS params = {0};
1100 IDirectSoundBuffer *buffer, *primary_buffer;
1101 HRESULT hr = S_OK;
1103 FIXME("(%p)->(%d, %d, %d, %p): semi-stub\n", This, dwType, pchannel_count, fActivate, ppNewPath);
1105 if (NULL == ppNewPath) {
1106 return E_POINTER;
1109 *ppNewPath = NULL;
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;
1119 format.cbSize = 0;
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;
1129 switch(dwType) {
1130 case DMUS_APATH_DYNAMIC_3D:
1131 desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
1132 break;
1133 case DMUS_APATH_DYNAMIC_MONO:
1134 desc.dwFlags |= DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
1135 break;
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;
1145 break;
1146 default:
1147 return E_INVALIDARG;
1150 /* Create a port */
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, &params)))
1155 return hr;
1157 hr = IDirectSound_CreateSoundBuffer(This->dsound, &desc, &buffer, NULL);
1158 if (FAILED(hr))
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);
1168 if (FAILED(hr)) {
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);
1178 *ppNewPath = pPath;
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);
1202 return S_OK;
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);
1215 } else {
1216 *ppAudioPath = NULL;
1218 return S_OK;
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);
1229 return S_OK;
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));
1296 if (NULL == obj) {
1297 *ppobj = NULL;
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,
1311 lpcGUID, ppobj);