wined3d: Use ARB_internalformat_query2 for the other texture format caps too.
[wine] / dlls / dmime / performance.c
1 /* IDirectMusicPerformance Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  * Copyright (C) 2003-2004 Raphael Junqueira
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "dmime_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
24
25 typedef struct IDirectMusicPerformance8Impl {
26     IDirectMusicPerformance8 IDirectMusicPerformance8_iface;
27     LONG ref;
28     /* IDirectMusicPerformanceImpl fields */
29     IDirectMusic8 *pDirectMusic;
30     IDirectSound *pDirectSound;
31     IDirectMusicGraph *pToolGraph;
32     DMUS_AUDIOPARAMS pParams;
33     /* global parameters */
34     BOOL fAutoDownload;
35     char cMasterGrooveLevel;
36     float fMasterTempo;
37     long lMasterVolume;
38     /* performance channels */
39     DMUSIC_PRIVATE_PCHANNEL PChannel[32];
40     /* IDirectMusicPerformance8Impl fields */
41     IDirectMusicAudioPath *pDefaultPath;
42     HANDLE hNotification;
43     REFERENCE_TIME rtMinimum;
44     REFERENCE_TIME rtLatencyTime;
45     DWORD dwBumperLength;
46     DWORD dwPrepareTime;
47     /** Message Processing */
48     HANDLE procThread;
49     DWORD procThreadId;
50     REFERENCE_TIME procThreadStartTime;
51     BOOL procThreadTicStarted;
52     CRITICAL_SECTION safe;
53     struct DMUS_PMSGItem *head;
54     struct DMUS_PMSGItem *imm_head;
55 } IDirectMusicPerformance8Impl;
56
57 typedef struct DMUS_PMSGItem DMUS_PMSGItem;
58 struct DMUS_PMSGItem {
59   DMUS_PMSGItem* next;
60   DMUS_PMSGItem* prev;
61
62   REFERENCE_TIME rtItemTime;
63   BOOL bInUse;
64   DWORD cb;
65   DMUS_PMSG pMsg;
66 };
67
68 #define DMUS_PMSGToItem(pMSG)   ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) -  offsetof(DMUS_PMSGItem, pMsg)))
69 #define DMUS_ItemToPMSG(pItem)  (&(pItem->pMsg))
70 #define DMUS_ItemRemoveFromQueue(This,pItem) \
71 {\
72   if (pItem->prev) pItem->prev->next = pItem->next;\
73   if (pItem->next) pItem->next->prev = pItem->prev;\
74   if (This->head == pItem) This->head = pItem->next;\
75   if (This->imm_head == pItem) This->imm_head = pItem->next;\
76   pItem->bInUse = FALSE;\
77 }
78
79 #define PROCESSMSG_START           (WM_APP + 0)
80 #define PROCESSMSG_EXIT            (WM_APP + 1)
81 #define PROCESSMSG_REMOVE          (WM_APP + 2)
82 #define PROCESSMSG_ADD             (WM_APP + 4)
83
84
85 static DMUS_PMSGItem* ProceedMsg(IDirectMusicPerformance8Impl* This, DMUS_PMSGItem* cur) {
86   if (cur->pMsg.dwType == DMUS_PMSGT_NOTIFICATION) {
87     SetEvent(This->hNotification);
88   }     
89   DMUS_ItemRemoveFromQueue(This, cur);
90   switch (cur->pMsg.dwType) {
91   case DMUS_PMSGT_WAVE:
92   case DMUS_PMSGT_TEMPO:   
93   case DMUS_PMSGT_STOP:
94   default:
95     FIXME("Unhandled PMsg Type: 0x%x\n", cur->pMsg.dwType);
96     break;
97   }
98   return cur;
99 }
100
101 static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
102   IDirectMusicPerformance8Impl* This = lpParam;
103   DWORD timeOut = INFINITE;
104   MSG msg;
105   HRESULT hr;
106   REFERENCE_TIME rtCurTime;
107   DMUS_PMSGItem* it = NULL;
108   DMUS_PMSGItem* cur = NULL;
109   DMUS_PMSGItem* it_next = NULL;
110
111   while (TRUE) {
112     DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;
113
114     if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
115     timeOut = INFINITE;
116
117     EnterCriticalSection(&This->safe);
118     hr = IDirectMusicPerformance8_GetTime(&This->IDirectMusicPerformance8_iface, &rtCurTime, NULL);
119     if (FAILED(hr)) {
120       goto outrefresh;
121     }
122     
123     for (it = This->imm_head; NULL != it; ) {
124       it_next = it->next;
125       cur = ProceedMsg(This, it);  
126       HeapFree(GetProcessHeap(), 0, cur); 
127       it = it_next;
128     }
129
130     for (it = This->head; NULL != it && it->rtItemTime < rtCurTime + dwDec; ) {
131       it_next = it->next;
132       cur = ProceedMsg(This, it);
133       HeapFree(GetProcessHeap(), 0, cur);
134       it = it_next;
135     }
136     if (NULL != it) {
137       timeOut = ( it->rtItemTime - rtCurTime ) + This->rtLatencyTime;
138     }
139
140 outrefresh:
141     LeaveCriticalSection(&This->safe);
142     
143     while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
144       /** if hwnd we suppose that is a windows event ... */
145       if  (NULL != msg.hwnd) {
146         TranslateMessage(&msg);
147         DispatchMessageA(&msg);
148       } else {
149         switch (msg.message) {      
150         case WM_QUIT:
151         case PROCESSMSG_EXIT:
152           goto outofthread;
153         case PROCESSMSG_START:
154           break;
155         case PROCESSMSG_ADD:
156           break;
157         case PROCESSMSG_REMOVE:
158           break;
159         default:
160           ERR("Unhandled message %u. Critical Path\n", msg.message);
161           break;
162         }
163       }
164     }
165
166     /** here we should run a little of current AudioPath */
167
168   }
169
170 outofthread:
171   TRACE("(%p): Exiting\n", This);
172   
173   return 0;
174 }
175
176 static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UINT iMsg) {
177   if (FALSE == This->procThreadTicStarted && PROCESSMSG_EXIT != iMsg) {
178     BOOL res;
179     This->procThread = CreateThread(NULL, 0, ProcessMsgThread, This, 0, &This->procThreadId);
180     if (NULL == This->procThread) return FALSE;
181     SetThreadPriority(This->procThread, THREAD_PRIORITY_TIME_CRITICAL);
182     This->procThreadTicStarted = TRUE;
183     while(1) {
184       res = PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
185       /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
186       if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID))
187         Sleep(0);
188       else
189         break;
190     }
191     return res;
192   }
193   return PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
194 }
195
196 static inline IDirectMusicPerformance8Impl *impl_from_IDirectMusicPerformance8(IDirectMusicPerformance8 *iface)
197 {
198     return CONTAINING_RECORD(iface, IDirectMusicPerformance8Impl, IDirectMusicPerformance8_iface);
199 }
200
201 /* IDirectMusicPerformance8 IUnknown part: */
202 static HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface(IDirectMusicPerformance8 *iface,
203         REFIID riid, void **ppv)
204 {
205   TRACE("(%p, %s,%p)\n", iface, debugstr_dmguid(riid), ppv);
206
207   if (IsEqualIID (riid, &IID_IUnknown) ||
208       IsEqualIID (riid, &IID_IDirectMusicPerformance) ||
209       IsEqualIID (riid, &IID_IDirectMusicPerformance2) ||
210       IsEqualIID (riid, &IID_IDirectMusicPerformance8)) {
211     *ppv = iface;
212     IUnknown_AddRef(iface);
213     return S_OK;
214   }
215
216   WARN("(%p, %s,%p): not found\n", iface, debugstr_dmguid(riid), ppv);
217   return E_NOINTERFACE;
218 }
219
220 static ULONG WINAPI IDirectMusicPerformance8Impl_AddRef(IDirectMusicPerformance8 *iface)
221 {
222   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
223   ULONG ref = InterlockedIncrement(&This->ref);
224
225   TRACE("(%p): AddRef from %d\n", This, ref - 1);
226
227   DMIME_LockModule();
228
229   return ref;
230 }
231
232 static ULONG WINAPI IDirectMusicPerformance8Impl_Release(IDirectMusicPerformance8 *iface)
233 {
234   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
235   ULONG ref = InterlockedDecrement(&This->ref);
236
237   TRACE("(%p): ReleaseRef to %d\n", This, ref);
238   
239   if (ref == 0) {
240     This->safe.DebugInfo->Spare[0] = 0;
241     DeleteCriticalSection(&This->safe);
242     HeapFree(GetProcessHeap(), 0, This);
243   }
244
245   DMIME_UnlockModule();
246
247   return ref;
248 }
249
250 /* IDirectMusicPerformanceImpl IDirectMusicPerformance Interface part: */
251 static HRESULT WINAPI IDirectMusicPerformance8Impl_Init(IDirectMusicPerformance8 *iface,
252         IDirectMusic **ppDirectMusic, IDirectSound *pDirectSound, HWND hWnd)
253 {
254         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
255
256         FIXME("(iface = %p, dmusic = %p, dsound = %p, hwnd = %p)\n", This, ppDirectMusic, pDirectSound, hWnd);
257         if (This->pDirectMusic || This->pDirectSound)
258           return DMUS_E_ALREADY_INITED;
259         
260         if (NULL == hWnd) {
261           hWnd = GetForegroundWindow();
262         }
263
264         if (NULL != pDirectSound) {
265           This->pDirectSound = pDirectSound;
266           IDirectSound_AddRef(This->pDirectSound);
267         } else {
268           DirectSoundCreate8(NULL, (LPDIRECTSOUND8*) &This->pDirectSound, NULL);
269           if (!This->pDirectSound) return DSERR_NODRIVER;
270
271           if (NULL != hWnd) {
272             IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);
273           } else {
274             /* how to get the ForeGround window handle ? */
275             /*IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);*/
276           }
277         }
278
279         if (NULL != ppDirectMusic && NULL != *ppDirectMusic) {
280           /* app creates it's own dmusic object and gives it to performance */
281           This->pDirectMusic = (IDirectMusic8*) *ppDirectMusic;
282           IDirectMusic8_AddRef(This->pDirectMusic);
283         } else {
284         HRESULT hr;
285         /* App enables the performance to initialize itself and needs a pointer to object */
286         hr = CoCreateInstance(&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8, (void**)&This->pDirectMusic);
287         if (FAILED(hr))
288             return hr;
289         if (ppDirectMusic) {
290             *ppDirectMusic = (LPDIRECTMUSIC)This->pDirectMusic;
291             IDirectMusic8_AddRef((LPDIRECTMUSIC8)*ppDirectMusic);
292         }
293     }
294
295     return S_OK;
296 }
297
298 static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegment(IDirectMusicPerformance8 *iface,
299         IDirectMusicSegment *pSegment, DWORD dwFlags, __int64 i64StartTime,
300         IDirectMusicSegmentState **ppSegmentState)
301 {
302         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
303
304         FIXME("(%p, %p, %d, 0x%s, %p): stub\n", This, pSegment, dwFlags,
305             wine_dbgstr_longlong(i64StartTime), ppSegmentState);
306         if (ppSegmentState)
307           return DMUSIC_CreateDirectMusicSegmentStateImpl(&IID_IDirectMusicSegmentState, (LPVOID*)ppSegmentState, NULL);
308         return S_OK;
309 }
310
311 static HRESULT WINAPI IDirectMusicPerformance8Impl_Stop(IDirectMusicPerformance8 *iface,
312         IDirectMusicSegment *pSegment, IDirectMusicSegmentState *pSegmentState, MUSIC_TIME mtTime,
313         DWORD dwFlags)
314 {
315         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
316
317         FIXME("(%p, %p, %p, %d, %d): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags);
318         return S_OK;
319 }
320
321 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState(IDirectMusicPerformance8 *iface,
322         IDirectMusicSegmentState **ppSegmentState, MUSIC_TIME mtTime)
323 {
324         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
325
326         FIXME("(%p,%p, %d): stub\n", This, ppSegmentState, mtTime);
327         return S_OK;
328 }
329
330 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime(IDirectMusicPerformance8 *iface,
331         DWORD dwMilliSeconds)
332 {
333   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
334
335   TRACE("(%p, %d)\n", This, dwMilliSeconds);
336   This->dwPrepareTime = dwMilliSeconds;
337   return S_OK;
338 }
339
340 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime(IDirectMusicPerformance8 *iface,
341         DWORD *pdwMilliSeconds)
342 {
343   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
344
345   TRACE("(%p, %p)\n", This, pdwMilliSeconds);
346   if (NULL == pdwMilliSeconds) {
347     return E_POINTER;
348   }
349   *pdwMilliSeconds = This->dwPrepareTime;
350   return S_OK;
351 }
352
353 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength(IDirectMusicPerformance8 *iface,
354         DWORD dwMilliSeconds)
355 {
356   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
357
358   TRACE("(%p, %d)\n", This, dwMilliSeconds);
359   This->dwBumperLength =  dwMilliSeconds;
360   return S_OK;
361 }
362
363 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength(IDirectMusicPerformance8 *iface,
364         DWORD *pdwMilliSeconds)
365 {
366   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
367
368   TRACE("(%p, %p)\n", This, pdwMilliSeconds);
369   if (NULL == pdwMilliSeconds) {
370     return E_POINTER;
371   }
372   *pdwMilliSeconds = This->dwBumperLength;
373   return S_OK;
374 }
375
376 static HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg(IDirectMusicPerformance8 *iface,
377         DMUS_PMSG *pPMSG)
378 {
379   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
380   DMUS_PMSGItem* pItem = NULL;
381   DMUS_PMSGItem* it = NULL;
382   DMUS_PMSGItem* prev_it = NULL;
383   DMUS_PMSGItem** queue = NULL;
384
385   FIXME("(%p, %p): stub\n", This, pPMSG);
386          
387   if (NULL == pPMSG) {
388     return E_POINTER;
389   }
390   pItem = DMUS_PMSGToItem(pPMSG);
391   if (NULL == pItem) {
392     return E_POINTER;
393   }
394   if (pItem->bInUse) {
395     return DMUS_E_ALREADY_SENT;
396   }
397   
398   /* TODO: Valid Flags */
399   /* TODO: DMUS_PMSGF_MUSICTIME */
400   pItem->rtItemTime = pPMSG->rtTime;
401
402   if (pPMSG->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) {
403     queue = &This->imm_head;
404   } else {
405     queue = &This->head;
406   }
407
408   EnterCriticalSection(&This->safe);
409   for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
410     prev_it = it;
411   }
412   if (NULL == prev_it) {
413     pItem->prev = NULL;
414     if (NULL != *queue) pItem->next = (*queue)->next;
415     /*assert( NULL == pItem->next->prev );*/
416     if (NULL != pItem->next) pItem->next->prev = pItem;
417     *queue = pItem;
418   } else {
419     pItem->prev = prev_it;
420     pItem->next = prev_it->next;
421     prev_it->next = pItem;
422     if (NULL != pItem->next) pItem->next->prev = pItem;
423   } 
424   LeaveCriticalSection(&This->safe);
425
426   /** now in use, prevent from stupid Frees */
427   pItem->bInUse = TRUE;
428   return S_OK;
429 }
430
431 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToReferenceTime(IDirectMusicPerformance8 *iface,
432         MUSIC_TIME mtTime, REFERENCE_TIME *prtTime)
433 {
434         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
435
436         FIXME("(%p, %d, %p): stub\n", This, mtTime, prtTime);
437         return S_OK;
438 }
439
440 static HRESULT WINAPI IDirectMusicPerformance8Impl_ReferenceToMusicTime(IDirectMusicPerformance8 *iface,
441         REFERENCE_TIME rtTime, MUSIC_TIME *pmtTime)
442 {
443         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
444
445         FIXME("(%p, 0x%s, %p): stub\n", This, wine_dbgstr_longlong(rtTime), pmtTime);
446         return S_OK;
447 }
448
449 static HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying(IDirectMusicPerformance8 *iface,
450         IDirectMusicSegment *pSegment, IDirectMusicSegmentState *pSegState)
451 {
452         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
453
454         FIXME("(%p, %p, %p): stub\n", This, pSegment, pSegState);
455         return S_FALSE;
456 }
457
458 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime(IDirectMusicPerformance8 *iface,
459         REFERENCE_TIME *prtNow, MUSIC_TIME *pmtNow)
460 {
461   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
462   HRESULT hr = S_OK;
463   REFERENCE_TIME rtCur = 0;
464
465   /*TRACE("(%p, %p, %p)\n", This, prtNow, pmtNow); */
466   if (This->procThreadTicStarted) {
467     rtCur = ((REFERENCE_TIME) GetTickCount() * 10000) - This->procThreadStartTime;
468   } else {
469     /*return DMUS_E_NO_MASTER_CLOCK;*/
470   }
471   if (NULL != prtNow) {
472     *prtNow = rtCur;
473   }
474   if (NULL != pmtNow) {
475     hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, rtCur, pmtNow);
476   }
477   return hr;
478 }
479
480 static HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg(IDirectMusicPerformance8 *iface,
481         ULONG cb, DMUS_PMSG **ppPMSG)
482 {
483   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
484   DMUS_PMSGItem* pItem = NULL;
485   
486   FIXME("(%p, %d, %p): stub\n", This, cb, ppPMSG);
487         
488   if (sizeof(DMUS_PMSG) > cb) {
489     return E_INVALIDARG;
490   }
491   if (NULL == ppPMSG) {
492     return E_POINTER;
493   }
494   pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb - sizeof(DMUS_PMSG)  + sizeof(DMUS_PMSGItem));
495   if (NULL == pItem) {
496     return E_OUTOFMEMORY;
497   }
498   pItem->pMsg.dwSize = cb;
499   *ppPMSG = DMUS_ItemToPMSG(pItem);
500   return S_OK;
501 }
502
503 static HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg(IDirectMusicPerformance8 *iface,
504         DMUS_PMSG *pPMSG)
505 {
506   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
507   DMUS_PMSGItem* pItem = NULL;
508   
509   FIXME("(%p, %p): stub\n", This, pPMSG);
510   
511   if (NULL == pPMSG) {
512     return E_POINTER;
513   }
514   pItem = DMUS_PMSGToItem(pPMSG);
515   if (NULL == pItem) {
516     return E_POINTER;
517   }
518   if (pItem->bInUse) {
519     /** prevent for freeing PMsg in queue (ie to be processed) */
520     return DMUS_E_CANNOT_FREE;
521   }
522   /** now we can remove it safely */
523   EnterCriticalSection(&This->safe);
524   DMUS_ItemRemoveFromQueue( This, pItem );
525   LeaveCriticalSection(&This->safe);
526
527   /** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */
528   HeapFree(GetProcessHeap(), 0, pItem);  
529   return S_OK;
530 }
531
532 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGraph(IDirectMusicPerformance8 *iface,
533         IDirectMusicGraph **ppGraph)
534 {
535   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
536
537   FIXME("(%p, %p): to check\n", This, ppGraph);
538   if (NULL != This->pToolGraph) {
539     *ppGraph = This->pToolGraph;
540     IDirectMusicGraph_AddRef(*ppGraph);
541   } else {
542     return E_FAIL;
543   }
544   return S_OK;
545 }
546
547 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGraph(IDirectMusicPerformance8 *iface,
548         IDirectMusicGraph *pGraph)
549 {
550   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
551
552   FIXME("(%p, %p): to check\n", This, pGraph);
553   
554   if (NULL != This->pToolGraph) {
555     /* Todo clean buffers and tools before */
556     IDirectMusicGraph_Release(This->pToolGraph);
557   }
558   This->pToolGraph = pGraph;
559   if (NULL != This->pToolGraph) {
560     IDirectMusicGraph_AddRef(This->pToolGraph);
561   }
562   return S_OK;
563 }
564
565 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetNotificationHandle(IDirectMusicPerformance8 *iface,
566         HANDLE hNotification, REFERENCE_TIME rtMinimum)
567 {
568   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
569
570   FIXME("(%p, %p, 0x%s): stub\n", This, hNotification, wine_dbgstr_longlong(rtMinimum));
571   This->hNotification = hNotification;
572   if (rtMinimum) This->rtMinimum = rtMinimum;
573   return S_OK;
574 }
575
576 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetNotificationPMsg(IDirectMusicPerformance8 *iface,
577         DMUS_NOTIFICATION_PMSG **ppNotificationPMsg)
578 {
579   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
580
581   FIXME("(%p, %p): stub\n", This, ppNotificationPMsg);
582   if (NULL == ppNotificationPMsg) {
583     return E_POINTER;
584   }
585   
586   
587
588   return S_FALSE;
589   /*return S_OK;*/
590 }
591
592 static HRESULT WINAPI IDirectMusicPerformance8Impl_AddNotificationType(IDirectMusicPerformance8 *iface,
593         REFGUID rguidNotificationType)
594 {
595         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
596
597         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
598         return S_OK;
599 }
600
601 static HRESULT WINAPI IDirectMusicPerformance8Impl_RemoveNotificationType(IDirectMusicPerformance8 *iface,
602         REFGUID rguidNotificationType)
603 {
604         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
605
606         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
607         return S_OK;
608 }
609
610 static HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort(IDirectMusicPerformance8 *iface,
611         IDirectMusicPort *pPort)
612 {
613         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
614         HRESULT hr = E_FAIL;
615
616         FIXME("(%p, %p): stub\n", This, pPort);
617         if (!This->pDirectMusic || !This->pDirectSound) return DMUS_E_NOT_INIT;
618         if (NULL == pPort) {
619           GUID port_guid;
620           IDirectMusicPort* pDefaultPort = NULL;
621           DMUS_PORTPARAMS params;
622           int i, j;
623           hr = IDirectMusic8_GetDefaultPort(This->pDirectMusic, &port_guid);
624           if (FAILED(hr)) return hr;
625           ZeroMemory(&params, sizeof(params)); 
626           params.dwSize = sizeof(params);
627           params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_SHARE;
628           params.dwChannelGroups = 1;
629           params.fShare = TRUE;
630           hr = IDirectMusic8_CreatePort(This->pDirectMusic, &port_guid, &params, &pDefaultPort, NULL);
631           if (FAILED(hr)) return hr;
632           hr = IDirectMusicPort_Activate(pDefaultPort, TRUE);
633           if (FAILED(hr)) { IDirectMusicPort_Release(pDefaultPort); return hr; }
634           j = 0;
635           for (i = 0; i < 16; ++i) {
636             if (NULL == This->PChannel[i].port) {
637               This->PChannel[i].port = pPort; 
638               This->PChannel[i].group = 0; 
639               This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
640               j++;
641             }
642           }
643         } else {
644           IDirectMusicPort_AddRef(pPort);         
645         }
646         /**
647          * We should remember added Ports (for example using a list)
648          * and control if Port is registered for each api who use ports
649          */
650         return S_OK;
651 }
652
653 static HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort(IDirectMusicPerformance8 *iface,
654         IDirectMusicPort *pPort)
655 {
656         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
657
658         FIXME("(%p, %p): stub\n", This, pPort);
659         IDirectMusicPort_Release (pPort);
660         return S_OK;
661 }
662
663 static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock(IDirectMusicPerformance8 *iface,
664         DWORD dwBlockNum, IDirectMusicPort *pPort, DWORD dwGroup)
665 {
666         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
667         int i, j, range /* min value in range */;
668
669         FIXME("(%p, %d, %p, %d): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1);
670         if (NULL == pPort) return E_POINTER;
671
672         range = 16 * dwBlockNum;
673         j = 0;
674         for (i = range; i < range+16; i++) {
675                 /*TRACE("Setting PChannel[%i] to port %p, group %ld, MIDI port %i\n", i, pPort, dwGroup-1, j); */
676                 This->PChannel[i].port = pPort; 
677                 This->PChannel[i].group = dwGroup - 1; /* first index is always zero */
678                 This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
679                 j++;
680         }
681         /*if (dwGroup > 2) return S_FALSE;*/
682
683         return S_OK;
684 }
685
686 static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel(IDirectMusicPerformance8 *iface,
687         DWORD PChannel, IDirectMusicPort *port, DWORD group, DWORD MChannel)
688 {
689     IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
690
691     TRACE("(%p)->(%d, %p, %d, %d)\n", This, PChannel, port, group, MChannel);
692
693     if (!port)
694         return E_POINTER;
695
696     This->PChannel[PChannel].port = port;
697     This->PChannel[PChannel].group = group;
698     This->PChannel[PChannel].channel = MChannel;
699
700     return S_OK;
701 }
702
703 static HRESULT WINAPI IDirectMusicPerformance8Impl_PChannelInfo(IDirectMusicPerformance8 *iface,
704         DWORD PChannel, IDirectMusicPort **port, DWORD *group, DWORD *MChannel)
705 {
706     IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
707     DMUS_PORTPARAMS8 port_params;
708     GUID default_port;
709
710     FIXME("(%p)->(%d, %p, %p, %p): stub\n", This, PChannel, port, group, MChannel);
711
712     port_params.dwSize = sizeof(DMUS_PORTPARAMS8);
713     port_params.dwValidParams = 0;
714     IDirectMusic8_GetDefaultPort(This->pDirectMusic, &default_port);
715     IDirectMusic8_CreatePort(This->pDirectMusic, &default_port, &port_params, port, NULL);
716
717     return S_OK;
718 }
719
720 static HRESULT WINAPI IDirectMusicPerformance8Impl_DownloadInstrument(IDirectMusicPerformance8 *iface,
721         IDirectMusicInstrument *pInst, DWORD dwPChannel,
722         IDirectMusicDownloadedInstrument **ppDownInst, DMUS_NOTERANGE *pNoteRanges,
723         DWORD dwNumNoteRanges, IDirectMusicPort **ppPort, DWORD *pdwGroup, DWORD *pdwMChannel)
724 {
725         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
726
727         FIXME("(%p, %p, %d, %p, %p, %d, %p, %p, %p): stub\n", This, pInst, dwPChannel, ppDownInst, pNoteRanges, dwNumNoteRanges, ppPort, pdwGroup, pdwMChannel);
728         return S_OK;
729 }
730
731 static HRESULT WINAPI IDirectMusicPerformance8Impl_Invalidate(IDirectMusicPerformance8 *iface,
732         MUSIC_TIME mtTime, DWORD dwFlags)
733 {
734         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
735
736         FIXME("(%p, %d, %d): stub\n", This, mtTime, dwFlags);
737         return S_OK;
738 }
739
740 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParam(IDirectMusicPerformance8 *iface,
741         REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime,
742         MUSIC_TIME *pmtNext, void *pParam)
743 {
744         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
745
746         FIXME("(%p, %s, %d, %d, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
747         return S_OK;
748 }
749
750 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetParam(IDirectMusicPerformance8 *iface,
751         REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void *pParam)
752 {
753         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
754
755         FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
756         return S_OK;
757 }
758
759 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGlobalParam(IDirectMusicPerformance8 *iface,
760         REFGUID rguidType, void *pParam, DWORD dwSize)
761 {
762         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
763
764         TRACE("(%p, %s, %p, %d): stub\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
765         
766         if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload))
767                 memcpy(pParam, &This->fAutoDownload, sizeof(This->fAutoDownload));
768         if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel))
769                 memcpy(pParam, &This->cMasterGrooveLevel, sizeof(This->cMasterGrooveLevel));
770         if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo))
771                 memcpy(pParam, &This->fMasterTempo, sizeof(This->fMasterTempo));
772         if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume))
773                 memcpy(pParam, &This->lMasterVolume, sizeof(This->lMasterVolume));
774
775         return S_OK;
776 }
777
778 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam(IDirectMusicPerformance8 *iface,
779         REFGUID rguidType, void *pParam, DWORD dwSize)
780 {
781         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
782
783         TRACE("(%p, %s, %p, %d)\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
784         
785         if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload)) {
786                 memcpy(&This->fAutoDownload, pParam, dwSize);
787                 TRACE("=> AutoDownload set to %d\n", This->fAutoDownload);
788         }
789         if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel)) {
790                 memcpy(&This->cMasterGrooveLevel, pParam, dwSize);
791                 TRACE("=> MasterGrooveLevel set to %i\n", This->cMasterGrooveLevel);
792         }
793         if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo)) {
794                 memcpy(&This->fMasterTempo, pParam, dwSize);
795                 TRACE("=> MasterTempo set to %f\n", This->fMasterTempo);
796         }
797         if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) {
798                 memcpy(&This->lMasterVolume, pParam, dwSize);
799                 TRACE("=> MasterVolume set to %li\n", This->lMasterVolume);
800         }
801
802         return S_OK;
803 }
804
805 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime(IDirectMusicPerformance8 *iface,
806         REFERENCE_TIME *prtTime)
807 {
808         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
809
810         TRACE("(%p, %p): stub\n", This, prtTime);
811         *prtTime = This->rtLatencyTime;
812         return S_OK;
813 }
814
815 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetQueueTime(IDirectMusicPerformance8 *iface,
816         REFERENCE_TIME *prtTime)
817
818 {
819         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
820
821         FIXME("(%p, %p): stub\n", This, prtTime);
822         return S_OK;
823 }
824
825 static HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime(IDirectMusicPerformance8 *iface,
826         REFERENCE_TIME rtAmount)
827 {
828         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
829
830         FIXME("(%p, 0x%s): stub\n", This, wine_dbgstr_longlong(rtAmount));
831         return S_OK;
832 }
833
834 static HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown(IDirectMusicPerformance8 *iface)
835 {
836   IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
837
838   FIXME("(%p): stub\n", This);
839   if (PostMessageToProcessMsgThread(This, PROCESSMSG_EXIT)) {
840     WaitForSingleObject(This->procThread, INFINITE);
841     This->procThreadTicStarted = FALSE;
842     CloseHandle(This->procThread);
843   }
844   if (NULL != This->pDirectSound) {
845     IDirectSound_Release(This->pDirectSound);
846     This->pDirectSound = NULL;
847   }
848   if (NULL != This->pDirectMusic) {
849     IDirectMusic8_Release(This->pDirectMusic);
850     This->pDirectMusic = NULL;
851   }
852   return S_OK;
853 }
854
855 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetResolvedTime(IDirectMusicPerformance8 *iface,
856         REFERENCE_TIME rtTime, REFERENCE_TIME *prtResolved, DWORD dwTimeResolveFlags)
857 {
858         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
859
860         FIXME("(%p, 0x%s, %p, %d): stub\n", This, wine_dbgstr_longlong(rtTime),
861             prtResolved, dwTimeResolveFlags);
862         return S_OK;
863 }
864
865 static HRESULT WINAPI IDirectMusicPerformance8Impl_MIDIToMusic(IDirectMusicPerformance8 *iface,
866         BYTE bMIDIValue, DMUS_CHORD_KEY *pChord, BYTE bPlayMode, BYTE bChordLevel,
867         WORD *pwMusicValue)
868 {
869         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
870
871         FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, bMIDIValue, pChord, bPlayMode, bChordLevel, pwMusicValue);
872         return S_OK;
873 }
874
875 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToMIDI(IDirectMusicPerformance8 *iface,
876         WORD wMusicValue, DMUS_CHORD_KEY *pChord, BYTE bPlayMode, BYTE bChordLevel,
877         BYTE *pbMIDIValue)
878 {
879         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
880
881         FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, wMusicValue, pChord, bPlayMode, bChordLevel, pbMIDIValue);
882         return S_OK;
883 }
884
885 static HRESULT WINAPI IDirectMusicPerformance8Impl_TimeToRhythm(IDirectMusicPerformance8 *iface,
886         MUSIC_TIME mtTime, DMUS_TIMESIGNATURE *pTimeSig, WORD *pwMeasure, BYTE *pbBeat,
887         BYTE *pbGrid, short *pnOffset)
888 {
889         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
890
891         FIXME("(%p, %d, %p, %p, %p, %p, %p): stub\n", This, mtTime, pTimeSig, pwMeasure, pbBeat, pbGrid, pnOffset);
892         return S_OK;
893 }
894
895 static HRESULT WINAPI IDirectMusicPerformance8Impl_RhythmToTime(IDirectMusicPerformance8 *iface,
896         WORD wMeasure, BYTE bBeat, BYTE bGrid, short nOffset, DMUS_TIMESIGNATURE *pTimeSig,
897         MUSIC_TIME *pmtTime)
898 {
899         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
900
901         FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This, wMeasure, bBeat, bGrid, nOffset, pTimeSig, pmtTime);
902         return S_OK;
903 }
904
905 /* IDirectMusicPerformance8 Interface part follow: */
906 static HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio(IDirectMusicPerformance8 *iface,
907         IDirectMusic **ppDirectMusic, IDirectSound **ppDirectSound, HWND hWnd,
908         DWORD dwDefaultPathType, DWORD dwPChannelCount, DWORD dwFlags, DMUS_AUDIOPARAMS* pParams)
909 {
910         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
911         IDirectSound* dsound = NULL;
912         HRESULT hr = S_OK;
913
914         FIXME("(%p, %p, %p, %p, %x, %u, %x, %p): to check\n", This, ppDirectMusic, ppDirectSound, hWnd, dwDefaultPathType, dwPChannelCount, dwFlags, pParams);
915
916         if (This->pDirectMusic || This->pDirectSound)
917           return DMUS_E_ALREADY_INITED;
918
919         if (NULL != ppDirectSound && NULL != *ppDirectSound) {
920           dsound = *ppDirectSound;
921         } else {
922           hr = DirectSoundCreate8 (NULL, (LPDIRECTSOUND8*) &dsound, NULL);
923           FIXME("return dsound(%p,%d)\n", dsound, hr);
924           if (FAILED(hr) || !dsound)
925             return DSERR_NODRIVER;
926           if (ppDirectSound)
927             *ppDirectSound = dsound;  
928         }
929         
930         IDirectMusicPerformance8Impl_Init(iface, ppDirectMusic, dsound, hWnd);
931
932         /* Init increases the ref count of the dsound object. Decrement it if the app doesn't want a pointer to the object. */
933         if (NULL == ppDirectSound) {
934           IDirectSound_Release(This->pDirectSound);
935         }
936
937         /* as seen in msdn we need params init before audio path creation */
938         if (NULL != pParams) {
939           This->pParams = *pParams;
940         } else {
941           /* TODO, how can i fill the struct as seen on msdn */
942           memset(&This->pParams, 0, sizeof(DMUS_AUDIOPARAMS));
943           This->pParams.dwSize = sizeof(DMUS_AUDIOPARAMS);
944           This->pParams.fInitNow = FALSE;
945           This->pParams.dwValidData = DMUS_AUDIOPARAMS_FEATURES | DMUS_AUDIOPARAMS_VOICES | DMUS_AUDIOPARAMS_SAMPLERATE | DMUS_AUDIOPARAMS_DEFAULTSYNTH;
946           This->pParams.dwVoices = 64;
947           This->pParams.dwSampleRate = (DWORD) 22.050; 
948           This->pParams.dwFeatures = dwFlags;
949           This->pParams.clsidDefaultSynth = CLSID_DirectMusicSynthSink;
950         }
951         if(dwDefaultPathType != 0)
952                 hr = IDirectMusicPerformance8_CreateStandardAudioPath(iface, dwDefaultPathType, dwPChannelCount, FALSE, &This->pDefaultPath);
953
954         PostMessageToProcessMsgThread(This, PROCESSMSG_START);
955
956         return hr;
957 }
958
959 static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegmentEx(IDirectMusicPerformance8 *iface,
960         IUnknown *pSource, WCHAR *pwzSegmentName, IUnknown *pTransition, DWORD dwFlags,
961         __int64 i64StartTime, IDirectMusicSegmentState **ppSegmentState, IUnknown *pFrom,
962         IUnknown *pAudioPath)
963 {
964         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
965
966         FIXME("(%p, %p, %p, %p, %d, 0x%s, %p, %p, %p): stub\n", This, pSource, pwzSegmentName,
967             pTransition, dwFlags, wine_dbgstr_longlong(i64StartTime), ppSegmentState, pFrom, pAudioPath);
968         if (ppSegmentState)
969           return DMUSIC_CreateDirectMusicSegmentStateImpl(&IID_IDirectMusicSegmentState, (LPVOID*)ppSegmentState, NULL);
970         return S_OK;
971 }
972
973 static HRESULT WINAPI IDirectMusicPerformance8Impl_StopEx(IDirectMusicPerformance8 *iface,
974         IUnknown *pObjectToStop, __int64 i64StopTime, DWORD dwFlags)
975 {
976         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
977
978         FIXME("(%p, %p, 0x%s, %d): stub\n", This, pObjectToStop,
979             wine_dbgstr_longlong(i64StopTime), dwFlags);
980         return S_OK;
981 }
982
983 static HRESULT WINAPI IDirectMusicPerformance8Impl_ClonePMsg(IDirectMusicPerformance8 *iface,
984         DMUS_PMSG *pSourcePMSG, DMUS_PMSG **ppCopyPMSG)
985 {
986         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
987
988         FIXME("(%p, %p, %p): stub\n", This, pSourcePMSG, ppCopyPMSG);
989         return S_OK;
990 }
991
992 static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateAudioPath(IDirectMusicPerformance8 *iface,
993         IUnknown *pSourceConfig, BOOL fActivate, IDirectMusicAudioPath **ppNewPath)
994 {
995         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
996         IDirectMusicAudioPathImpl *default_path;
997         IDirectMusicAudioPath *pPath;
998
999         FIXME("(%p, %p, %d, %p): stub\n", This, pSourceConfig, fActivate, ppNewPath);
1000
1001         if (NULL == ppNewPath) {
1002           return E_POINTER;
1003         }
1004
1005         DMUSIC_CreateDirectMusicAudioPathImpl (&IID_IDirectMusicAudioPath, (LPVOID*)&pPath, NULL);
1006         default_path = (IDirectMusicAudioPathImpl*)((char*)(pPath) - offsetof(IDirectMusicAudioPathImpl,AudioPathVtbl));
1007         default_path->pPerf = &This->IDirectMusicPerformance8_iface;
1008
1009         /** TODO */
1010         
1011         *ppNewPath = pPath;
1012
1013         return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate);
1014 }
1015
1016 static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateStandardAudioPath(IDirectMusicPerformance8 *iface,
1017         DWORD dwType, DWORD dwPChannelCount, BOOL fActivate, IDirectMusicAudioPath **ppNewPath)
1018 {
1019         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1020         IDirectMusicAudioPathImpl *default_path;
1021         IDirectMusicAudioPath *pPath;
1022         DSBUFFERDESC desc;
1023         WAVEFORMATEX format;
1024         LPDIRECTSOUNDBUFFER buffer;
1025         HRESULT hr = S_OK;
1026
1027         FIXME("(%p)->(%d, %d, %d, %p): semi-stub\n", This, dwType, dwPChannelCount, fActivate, ppNewPath);
1028
1029         if (NULL == ppNewPath) {
1030           return E_POINTER;
1031         }
1032         
1033         DMUSIC_CreateDirectMusicAudioPathImpl (&IID_IDirectMusicAudioPath, (LPVOID*)&pPath, NULL);
1034         default_path = (IDirectMusicAudioPathImpl*)((char*)(pPath) - offsetof(IDirectMusicAudioPathImpl,AudioPathVtbl));
1035         default_path->pPerf = &This->IDirectMusicPerformance8_iface;
1036
1037         /* Secondary buffer description */
1038         memset(&format, 0, sizeof(format));
1039         format.wFormatTag = WAVE_FORMAT_PCM;
1040         format.nChannels = 1;
1041         format.nSamplesPerSec = 44000;
1042         format.nAvgBytesPerSec = 44000*2;
1043         format.nBlockAlign = 2;
1044         format.wBitsPerSample = 16;
1045         format.cbSize = 0;
1046         
1047         memset(&desc, 0, sizeof(desc));
1048         desc.dwSize = sizeof(desc);
1049         desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
1050         desc.dwBufferBytes = DSBSIZE_MIN;
1051         desc.dwReserved = 0;
1052         desc.lpwfxFormat = &format;
1053         desc.guid3DAlgorithm = GUID_NULL;
1054         
1055         switch(dwType) {
1056         case DMUS_APATH_DYNAMIC_3D:
1057                 desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
1058                 break;
1059         case DMUS_APATH_DYNAMIC_MONO:
1060                 desc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
1061                 break;
1062         case DMUS_APATH_SHARED_STEREOPLUSREVERB:
1063                 /* normally we have to create 2 buffers (one for music other for reverb)
1064                  * in this case. See msdn
1065                  */
1066         case DMUS_APATH_DYNAMIC_STEREO:
1067                 desc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
1068                 format.nChannels = 2;
1069                 format.nBlockAlign *= 2;
1070                 format.nAvgBytesPerSec *=2;
1071                 break;
1072         default:
1073                 HeapFree(GetProcessHeap(), 0, default_path); 
1074                 *ppNewPath = NULL;
1075                 return E_INVALIDARG;
1076         }
1077
1078         /* FIXME: Should we create one secondary buffer for each PChannel? */
1079         hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL);
1080         if (FAILED(hr)) {
1081                 HeapFree(GetProcessHeap(), 0, default_path); 
1082                 *ppNewPath = NULL;
1083                 return DSERR_BUFFERLOST;
1084         }
1085         default_path->pDSBuffer = buffer;
1086
1087         /* Update description for creating primary buffer */
1088         desc.dwFlags |= DSBCAPS_PRIMARYBUFFER;
1089         desc.dwBufferBytes = 0;
1090         desc.lpwfxFormat = NULL;
1091
1092         hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL);
1093         if (FAILED(hr)) {
1094                 IDirectSoundBuffer_Release(default_path->pDSBuffer);
1095                 HeapFree(GetProcessHeap(), 0, default_path); 
1096                 *ppNewPath = NULL;
1097                 return DSERR_BUFFERLOST;
1098         }
1099         default_path->pPrimary = buffer;
1100
1101         *ppNewPath = pPath;
1102         
1103         TRACE(" returning IDirectMusicAudioPath interface at %p.\n", *ppNewPath);
1104
1105         return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate);
1106 }
1107
1108 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetDefaultAudioPath(IDirectMusicPerformance8 *iface,
1109         IDirectMusicAudioPath *pAudioPath)
1110 {
1111         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1112
1113         FIXME("(%p, %p): semi-stub\n", This, pAudioPath);
1114         if (NULL != This->pDefaultPath) {
1115                 IDirectMusicAudioPath_Release(This->pDefaultPath);
1116                 ((IDirectMusicAudioPathImpl*) This->pDefaultPath)->pPerf = NULL;
1117                 This->pDefaultPath = NULL;
1118         }
1119         This->pDefaultPath = pAudioPath;
1120         if (NULL != This->pDefaultPath) {
1121                 IDirectMusicAudioPath_AddRef(This->pDefaultPath);
1122                 ((IDirectMusicAudioPathImpl*)This->pDefaultPath)->pPerf = &This->IDirectMusicPerformance8_iface;
1123         }
1124
1125         return S_OK;
1126 }
1127
1128 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetDefaultAudioPath(IDirectMusicPerformance8 *iface,
1129         IDirectMusicAudioPath **ppAudioPath)
1130 {
1131         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1132
1133         FIXME("(%p, %p): semi-stub (%p)\n", This, ppAudioPath, This->pDefaultPath);
1134
1135         if (NULL != This->pDefaultPath) {
1136           *ppAudioPath = This->pDefaultPath;
1137           IDirectMusicAudioPath_AddRef(*ppAudioPath);
1138         } else {
1139           *ppAudioPath = NULL;
1140         }
1141         return S_OK;
1142 }
1143
1144 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParamEx(IDirectMusicPerformance8 *iface,
1145         REFGUID rguidType, DWORD dwTrackID, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime,
1146         MUSIC_TIME *pmtNext, void *pParam)
1147 {
1148         IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface);
1149
1150         FIXME("(%p, %s, %d, %d, %d, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwTrackID, dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
1151
1152         return S_OK;
1153 }
1154
1155 static const IDirectMusicPerformance8Vtbl DirectMusicPerformance8_Vtbl = {
1156         IDirectMusicPerformance8Impl_QueryInterface,
1157         IDirectMusicPerformance8Impl_AddRef,
1158         IDirectMusicPerformance8Impl_Release,
1159         IDirectMusicPerformance8Impl_Init,
1160         IDirectMusicPerformance8Impl_PlaySegment,
1161         IDirectMusicPerformance8Impl_Stop,
1162         IDirectMusicPerformance8Impl_GetSegmentState,
1163         IDirectMusicPerformance8Impl_SetPrepareTime,
1164         IDirectMusicPerformance8Impl_GetPrepareTime,
1165         IDirectMusicPerformance8Impl_SetBumperLength,
1166         IDirectMusicPerformance8Impl_GetBumperLength,
1167         IDirectMusicPerformance8Impl_SendPMsg,
1168         IDirectMusicPerformance8Impl_MusicToReferenceTime,
1169         IDirectMusicPerformance8Impl_ReferenceToMusicTime,
1170         IDirectMusicPerformance8Impl_IsPlaying,
1171         IDirectMusicPerformance8Impl_GetTime,
1172         IDirectMusicPerformance8Impl_AllocPMsg,
1173         IDirectMusicPerformance8Impl_FreePMsg,
1174         IDirectMusicPerformance8Impl_GetGraph,
1175         IDirectMusicPerformance8Impl_SetGraph,
1176         IDirectMusicPerformance8Impl_SetNotificationHandle,
1177         IDirectMusicPerformance8Impl_GetNotificationPMsg,
1178         IDirectMusicPerformance8Impl_AddNotificationType,
1179         IDirectMusicPerformance8Impl_RemoveNotificationType,
1180         IDirectMusicPerformance8Impl_AddPort,
1181         IDirectMusicPerformance8Impl_RemovePort,
1182         IDirectMusicPerformance8Impl_AssignPChannelBlock,
1183         IDirectMusicPerformance8Impl_AssignPChannel,
1184         IDirectMusicPerformance8Impl_PChannelInfo,
1185         IDirectMusicPerformance8Impl_DownloadInstrument,
1186         IDirectMusicPerformance8Impl_Invalidate,
1187         IDirectMusicPerformance8Impl_GetParam,
1188         IDirectMusicPerformance8Impl_SetParam,
1189         IDirectMusicPerformance8Impl_GetGlobalParam,
1190         IDirectMusicPerformance8Impl_SetGlobalParam,
1191         IDirectMusicPerformance8Impl_GetLatencyTime,
1192         IDirectMusicPerformance8Impl_GetQueueTime,
1193         IDirectMusicPerformance8Impl_AdjustTime,
1194         IDirectMusicPerformance8Impl_CloseDown,
1195         IDirectMusicPerformance8Impl_GetResolvedTime,
1196         IDirectMusicPerformance8Impl_MIDIToMusic,
1197         IDirectMusicPerformance8Impl_MusicToMIDI,
1198         IDirectMusicPerformance8Impl_TimeToRhythm,
1199         IDirectMusicPerformance8Impl_RhythmToTime,
1200         IDirectMusicPerformance8Impl_InitAudio,
1201         IDirectMusicPerformance8Impl_PlaySegmentEx,
1202         IDirectMusicPerformance8Impl_StopEx,
1203         IDirectMusicPerformance8Impl_ClonePMsg,
1204         IDirectMusicPerformance8Impl_CreateAudioPath,
1205         IDirectMusicPerformance8Impl_CreateStandardAudioPath,
1206         IDirectMusicPerformance8Impl_SetDefaultAudioPath,
1207         IDirectMusicPerformance8Impl_GetDefaultAudioPath,
1208         IDirectMusicPerformance8Impl_GetParamEx
1209 };
1210
1211 /* for ClassFactory */
1212 HRESULT WINAPI DMUSIC_CreateDirectMusicPerformanceImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
1213         IDirectMusicPerformance8Impl *obj;
1214
1215         TRACE("(%p,%p,%p)\n", lpcGUID, ppobj, pUnkOuter);
1216
1217         if (pUnkOuter) {
1218                 *ppobj = NULL;
1219                 return CLASS_E_NOAGGREGATION;
1220         }
1221
1222         obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicPerformance8Impl));
1223         if (NULL == obj) {
1224                 *ppobj = NULL;
1225                 return E_OUTOFMEMORY;
1226         }
1227         obj->IDirectMusicPerformance8_iface.lpVtbl = &DirectMusicPerformance8_Vtbl;
1228         obj->ref = 0;  /* will be inited by QueryInterface */
1229         obj->pDirectMusic = NULL;
1230         obj->pDirectSound = NULL;
1231         obj->pDefaultPath = NULL;
1232         InitializeCriticalSection(&obj->safe);
1233         obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectMusicPerformance8Impl*->safe");
1234
1235         obj->rtLatencyTime  = 100;  /* 100ms TO FIX */
1236         obj->dwBumperLength =   50; /* 50ms default */
1237         obj->dwPrepareTime  = 1000; /* 1000ms default */
1238         return IDirectMusicPerformance8Impl_QueryInterface(&obj->IDirectMusicPerformance8_iface,
1239                                                            lpcGUID, ppobj);
1240 }