- fix cRef Leak (init to 1, should be 0) of IDMPerformance
[wine] / dlls / dmime / performance.c
1 /* IDirectMusicPerformance Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include "dmime_private.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
23
24 /* IDirectMusicPerformance8 IUnknown part: */
25 HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface (LPDIRECTMUSICPERFORMANCE8 iface, REFIID riid, LPVOID *ppobj) {
26         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
27         TRACE("(%p, %s,%p)\n", This, debugstr_dmguid(riid), ppobj);
28
29         if (IsEqualIID (riid, &IID_IUnknown) || 
30             IsEqualIID (riid, &IID_IDirectMusicPerformance) ||
31             IsEqualIID (riid, &IID_IDirectMusicPerformance8)) {
32                 IDirectMusicPerformance8Impl_AddRef(iface);
33                 *ppobj = This;
34                 return S_OK;
35         }
36         
37         WARN("(%p, %s,%p): not found\n", This, debugstr_dmguid(riid), ppobj);
38         return E_NOINTERFACE;
39 }
40
41 ULONG WINAPI IDirectMusicPerformance8Impl_AddRef (LPDIRECTMUSICPERFORMANCE8 iface) {
42         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
43         TRACE("(%p): AddRef from %ld\n", This, This->ref);
44         return ++(This->ref);
45 }
46
47 ULONG WINAPI IDirectMusicPerformance8Impl_Release (LPDIRECTMUSICPERFORMANCE8 iface) {
48         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
49         ULONG ref = --This->ref;
50         TRACE("(%p): ReleaseRef to %ld\n", This, This->ref);
51         if (ref == 0) {
52                 HeapFree(GetProcessHeap(), 0, This);
53         }
54         return ref;
55 }
56
57 /* IDirectMusicPerformanceImpl IDirectMusicPerformance Interface part: */
58 HRESULT WINAPI IDirectMusicPerformance8Impl_Init (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusic** ppDirectMusic, LPDIRECTSOUND pDirectSound, HWND hWnd) {
59         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
60
61         FIXME("(iface = %p, dmusic = %p, dsound = %p, hwnd = %p)\n", This, ppDirectMusic, pDirectSound, hWnd);
62         if (This->pDirectMusic || This->pDirectSound)
63           return DMUS_E_ALREADY_INITED;
64         
65         if (NULL == hWnd) {
66           hWnd = GetForegroundWindow();
67         }
68
69         if (NULL != pDirectSound) {
70           This->pDirectSound = (IDirectSound*) pDirectSound;
71           IDirectSound_AddRef((LPDIRECTSOUND) This->pDirectSound);
72         } else {
73           DirectSoundCreate8(NULL, (LPDIRECTSOUND8*) &This->pDirectSound, NULL);
74           /** 
75            * as seen in msdn
76            * 
77            *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directX/htm/idirectmusicperformance8initaudio.asp
78            */
79           if (NULL != hWnd) {
80             IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);
81           } else {
82             /* how to get the ForeGround window handle ? */
83             /*IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);*/
84           }
85           if (!This->pDirectSound)
86             return DSERR_NODRIVER;
87         }
88
89         if (NULL != ppDirectMusic && NULL != *ppDirectMusic) {
90           /* app creates it's own dmusic object and gives it to performance */
91           This->pDirectMusic = (IDirectMusic8*) *ppDirectMusic;
92           IDirectMusic8_AddRef((LPDIRECTMUSIC8) This->pDirectMusic);
93         } else {
94           /* app allows the performance to initialise itfself and needs a pointer to object*/
95           CoCreateInstance (&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8, (void**)&This->pDirectMusic);
96           if (ppDirectMusic) {
97             *ppDirectMusic = (LPDIRECTMUSIC) This->pDirectMusic;
98             IDirectMusic8_AddRef((LPDIRECTMUSIC8) *ppDirectMusic);
99           }
100         }
101         
102         return S_OK;
103 }
104
105 HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegment (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, DWORD dwFlags, __int64 i64StartTime, IDirectMusicSegmentState** ppSegmentState) {
106         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
107         FIXME("(%p, %p, %ld, %lli, %p): stub\n", This, pSegment, dwFlags, i64StartTime, ppSegmentState);
108         return S_OK;
109 }
110
111 HRESULT WINAPI IDirectMusicPerformance8Impl_Stop (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, IDirectMusicSegmentState* pSegmentState, MUSIC_TIME mtTime, DWORD dwFlags) {
112         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
113         FIXME("(%p, %p, %p, %ld, %ld): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags);
114         return S_OK;
115 }
116
117 HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegmentState** ppSegmentState, MUSIC_TIME mtTime) {
118         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
119         FIXME("(%p,%p, %ld): stub\n", This, ppSegmentState, mtTime);
120         return S_OK;
121 }
122
123 HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
124         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
125         FIXME("(%p, %ld): stub\n", This, dwMilliSeconds);
126         return S_OK;
127 }
128
129 HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
130         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
131         FIXME("(%p, %p): stub\n", This, pdwMilliSeconds);
132         return S_OK;
133 }
134
135 HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
136         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
137         FIXME("(%p, %ld): stub\n", This, dwMilliSeconds);
138         return S_OK;
139 }
140
141 HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
142         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
143         FIXME("(%p, %p): stub\n", This, pdwMilliSeconds);
144         return S_OK;
145 }
146
147 HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pPMSG) {
148   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
149   DMUS_PMSGItem* pItem = NULL;
150   DMUS_PMSGItem* it = NULL;
151   DMUS_PMSGItem* prev_it = NULL;
152   DMUS_PMSGItem** queue = NULL;
153
154   FIXME("(%p, %p): stub\n", This, pPMSG);
155          
156   if (NULL == pPMSG) {
157     return E_POINTER;
158   }
159   pItem = DMUS_PMSGToItem(pPMSG);
160   if (NULL == pItem) {
161     return E_POINTER;
162   }
163   if (TRUE == pItem->bInUse) {
164     return DMUS_E_ALREADY_SENT;
165   }
166   
167   /* TODO: Valid Flags */
168   /* TODO: DMUS_PMSGF_MUSICTIME */
169   pItem->rtItemTime = pPMSG->rtTime;
170
171   if (pPMSG->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) {
172     queue = &This->imm_head;
173   } else {
174     queue = &This->head;
175   }
176
177   for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
178     prev_it = it;
179   }
180   if (NULL == prev_it) {
181     pItem->prev = NULL;
182     pItem->next = (*queue)->next;
183     /*assert( NULL == pItem->next->prev );*/
184     if (NULL != pItem->next) pItem->next->prev = pItem;
185     *queue = pItem;
186   } else {
187     pItem->prev = prev_it;
188     pItem->next = prev_it->next;
189     prev_it->next = pItem;
190     if (NULL != pItem->next) pItem->next->prev = pItem;
191   }
192   /** now in use, prevent from stupid Frees */
193   pItem->bInUse = TRUE;
194   return S_OK;
195 }
196
197 HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToReferenceTime (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, REFERENCE_TIME* prtTime) {
198         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
199         FIXME("(%p, %ld, %p): stub\n", This, mtTime, prtTime);
200         return S_OK;
201 }
202
203 HRESULT WINAPI IDirectMusicPerformance8Impl_ReferenceToMusicTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtTime, MUSIC_TIME* pmtTime) {
204         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
205         FIXME("(%p, %lli, %p): stub\n", This, rtTime, pmtTime);
206         return S_OK;
207 }
208
209 HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, IDirectMusicSegmentState* pSegState) {
210         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
211         FIXME("(%p, %p, %p): stub\n", This, pSegment, pSegState);
212         return S_FALSE;
213 }
214
215 HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtNow, MUSIC_TIME* pmtNow) {
216         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
217         FIXME("(%p, %p, %p): stub\n", This, prtNow, pmtNow);    
218         return S_OK;
219 }
220
221 HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg (LPDIRECTMUSICPERFORMANCE8 iface, ULONG cb, DMUS_PMSG** ppPMSG) {
222   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
223   DMUS_PMSGItem* pItem = NULL;
224   
225   FIXME("(%p, %ld, %p): stub\n", This, cb, ppPMSG);
226         
227   if (sizeof(DMUS_PMSG) > cb) {
228     return E_INVALIDARG;
229   }
230   if (NULL == ppPMSG) {
231     return E_POINTER;
232   }
233   pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb - sizeof(DMUS_PMSG)  + sizeof(DMUS_PMSGItem));
234   if (NULL == pItem) {
235     return E_OUTOFMEMORY;
236   }
237   pItem->pMsg.dwSize = cb;
238   *ppPMSG = DMUS_ItemToPMSG(pItem);
239   return S_OK;
240 }
241
242 HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pPMSG) {
243   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
244   DMUS_PMSGItem* pItem = NULL;
245   
246   FIXME("(%p, %p): stub\n", This, pPMSG);
247   
248   if (NULL == pPMSG) {
249     return E_POINTER;
250   }
251   pItem = DMUS_PMSGToItem(pPMSG);
252   if (NULL == pItem) {
253     return E_POINTER;
254   }
255   if (TRUE == pItem->bInUse) {
256     /** prevent for freeing PMsg in queue (ie to be processed) */
257     return DMUS_E_CANNOT_FREE;
258   }
259   /** now we can remove it safely */
260   DMUS_ItemRemoveFromQueue( This, pItem );
261   /** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */
262   HeapFree(GetProcessHeap(), 0, pItem);  
263   return S_OK;
264 }
265
266 HRESULT WINAPI IDirectMusicPerformance8Impl_GetGraph (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicGraph** ppGraph) {
267   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
268   FIXME("(%p, %p): to check\n", This, ppGraph);
269   if (NULL != This->pToolGraph) {
270     *ppGraph = (LPDIRECTMUSICGRAPH) This->pToolGraph; 
271     IDirectMusicGraph_AddRef((LPDIRECTMUSICGRAPH) *ppGraph);
272   }
273   return S_OK;
274 }
275
276 HRESULT WINAPI IDirectMusicPerformance8Impl_SetGraph (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicGraph* pGraph) {
277   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
278   
279   FIXME("(%p, %p): to check\n", This, pGraph);
280   
281   if (NULL != This->pToolGraph) {
282     /* Todo clean buffers and tools before */
283     IDirectMusicGraph_Release((LPDIRECTMUSICGRAPH) This->pToolGraph);
284   }
285   This->pToolGraph = pGraph;
286   if (NULL != This->pToolGraph) {
287     IDirectMusicGraph_AddRef((LPDIRECTMUSICGRAPH) This->pToolGraph);
288   }
289   return S_OK;
290 }
291
292 HRESULT WINAPI IDirectMusicPerformance8Impl_SetNotificationHandle (LPDIRECTMUSICPERFORMANCE8 iface, HANDLE hNotification, REFERENCE_TIME rtMinimum) {
293   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
294   FIXME("(%p, %p, %lli): stub\n", This, hNotification, rtMinimum);
295   This->hNotification = hNotification;
296   if (rtMinimum) This->rtMinimum = rtMinimum;
297   return S_OK;
298 }
299
300 HRESULT WINAPI IDirectMusicPerformance8Impl_GetNotificationPMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_NOTIFICATION_PMSG** ppNotificationPMsg) {
301   ICOM_THIS(IDirectMusicPerformance8Impl,iface);
302   
303   
304   FIXME("(%p, %p): stub\n", This, ppNotificationPMsg);
305   if (NULL == ppNotificationPMsg) {
306     return E_POINTER;
307   }
308   
309   
310
311   return S_FALSE;
312   /*return S_OK;*/
313 }
314
315 HRESULT WINAPI IDirectMusicPerformance8Impl_AddNotificationType (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidNotificationType) {
316         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
317         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
318         return S_OK;
319 }
320
321 HRESULT WINAPI IDirectMusicPerformance8Impl_RemoveNotificationType (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidNotificationType) {
322         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
323         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
324         return S_OK;
325 }
326
327 HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicPort* pPort) {
328         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
329         FIXME("(%p, %p): stub\n", This, pPort);
330         IDirectMusicPort_AddRef (pPort);
331         return S_OK;
332 }
333
334 HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicPort* pPort) {
335         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
336         FIXME("(%p, %p): stub\n", This, pPort);
337         IDirectMusicPort_Release (pPort);
338         return S_OK;
339 }
340
341 HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwBlockNum, IDirectMusicPort* pPort, DWORD dwGroup) {
342         int i, j, range /* min value in range */;
343         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
344
345         FIXME("(%p, %ld, %p, %ld): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1);
346         range = 16 * dwBlockNum;
347         j = 0;
348                 
349         for (i = range; i < range+16; i++) {
350                 /*TRACE("Setting PChannel[%i] to port %p, group %ld, MIDI port %i\n", i, pPort, dwGroup-1, j); */
351                 This->PChannel[i].port = pPort; 
352                 This->PChannel[i].group = dwGroup - 1; /* first index is always zero */
353                 This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
354                 j++;
355         }
356
357         return S_OK;
358 }
359
360 HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwPChannel, IDirectMusicPort* pPort, DWORD dwGroup, DWORD dwMChannel) {
361         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
362
363         TRACE("(%p, %ld, %p, %ld, %ld)\n", This, dwPChannel, pPort, dwGroup, dwMChannel);
364         This->PChannel[dwPChannel].port = pPort; 
365         This->PChannel[dwPChannel].group = dwGroup; 
366         This->PChannel[dwPChannel].channel = dwMChannel;
367
368         return S_OK;
369 }
370
371 HRESULT WINAPI IDirectMusicPerformance8Impl_PChannelInfo (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwPChannel, IDirectMusicPort** ppPort, DWORD* pdwGroup, DWORD* pdwMChannel) {
372         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
373         FIXME("(%p, %ld, %p, %p, %p): stub\n", This, dwPChannel, ppPort, pdwGroup, pdwMChannel);
374         return S_OK;
375 }
376
377 HRESULT WINAPI IDirectMusicPerformance8Impl_DownloadInstrument (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicInstrument* pInst, DWORD dwPChannel, IDirectMusicDownloadedInstrument** ppDownInst, DMUS_NOTERANGE* pNoteRanges, DWORD dwNumNoteRanges, IDirectMusicPort** ppPort, DWORD* pdwGroup, DWORD* pdwMChannel) {
378         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
379         FIXME("(%p, %p, %ld, %p, %p, %ld, %p, %p, %p): stub\n", This, pInst, dwPChannel, ppDownInst, pNoteRanges, dwNumNoteRanges, ppPort, pdwGroup, pdwMChannel);
380         return S_OK;
381 }
382
383 HRESULT WINAPI IDirectMusicPerformance8Impl_Invalidate (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, DWORD dwFlags) {
384         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
385         FIXME("(%p, %ld, %ld): stub\n", This, mtTime, dwFlags);
386         return S_OK;
387 }
388
389 HRESULT WINAPI IDirectMusicPerformance8Impl_GetParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
390         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
391         FIXME("(%p, %s, %ld, %ld, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
392         return S_OK;
393 }
394
395 HRESULT WINAPI IDirectMusicPerformance8Impl_SetParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void* pParam) {
396         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
397         FIXME("(%p, %s, %ld, %ld, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
398         return S_OK;
399 }
400
401 HRESULT WINAPI IDirectMusicPerformance8Impl_GetGlobalParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, void* pParam, DWORD dwSize) {
402         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
403
404         TRACE("(%p, %s, %p, %ld): stub\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
405         
406         if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload))
407                 memcpy(pParam, &This->fAutoDownload, sizeof(&This->fAutoDownload));
408         if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel))
409                 memcpy(pParam, &This->cMasterGrooveLevel, sizeof(&This->cMasterGrooveLevel));
410         if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo))
411                 memcpy(pParam, &This->fMasterTempo, sizeof(&This->fMasterTempo));
412         if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume))
413                 memcpy(pParam, &This->lMasterVolume, sizeof(&This->lMasterVolume));
414
415         return S_OK;
416 }
417
418 HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, void* pParam, DWORD dwSize) {
419         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
420
421         TRACE("(%p, %s, %p, %ld)\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
422         
423         if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload)) {
424                 memcpy(&This->fAutoDownload, pParam, dwSize);
425                 TRACE("=> AutoDownload set to %d\n", This->fAutoDownload);
426         }
427         if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel)) {
428                 memcpy(&This->cMasterGrooveLevel, pParam, dwSize);
429                 TRACE("=> MasterGrooveLevel set to %i\n", This->cMasterGrooveLevel);
430         }
431         if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo)) {
432                 memcpy(&This->fMasterTempo, pParam, dwSize);
433                 TRACE("=> MasterTempo set to %f\n", This->fMasterTempo);
434         }
435         if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) {
436                 memcpy(&This->lMasterVolume, pParam, dwSize);
437                 TRACE("=> MasterVolume set to %li\n", This->lMasterVolume);
438         }
439
440         return S_OK;
441 }
442
443 HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
444         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
445         FIXME("(%p, %p): stub\n", This, prtTime);
446         return S_OK;
447 }
448
449 HRESULT WINAPI IDirectMusicPerformance8Impl_GetQueueTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
450         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
451         FIXME("(%p, %p): stub\n", This, prtTime);
452         return S_OK;
453 }
454
455 HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtAmount) {
456         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
457         FIXME("(%p, %lli): stub\n", This, rtAmount);
458         return S_OK;
459 }
460
461 HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown (LPDIRECTMUSICPERFORMANCE8 iface) {
462         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
463         FIXME("(%p): stub\n", This);
464         return S_OK;
465 }
466
467 HRESULT WINAPI IDirectMusicPerformance8Impl_GetResolvedTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtTime, REFERENCE_TIME* prtResolved, DWORD dwTimeResolveFlags) {
468         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
469         FIXME("(%p, %lli, %p, %ld): stub\n", This, rtTime, prtResolved, dwTimeResolveFlags);
470         return S_OK;
471 }
472
473 HRESULT WINAPI IDirectMusicPerformance8Impl_MIDIToMusic (LPDIRECTMUSICPERFORMANCE8 iface, BYTE bMIDIValue, DMUS_CHORD_KEY* pChord, BYTE bPlayMode, BYTE bChordLevel, WORD* pwMusicValue) {
474         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
475         FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, bMIDIValue, pChord, bPlayMode, bChordLevel, pwMusicValue);
476         return S_OK;
477 }
478
479 HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToMIDI (LPDIRECTMUSICPERFORMANCE8 iface, WORD wMusicValue, DMUS_CHORD_KEY* pChord, BYTE bPlayMode, BYTE bChordLevel, BYTE* pbMIDIValue) {
480         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
481         FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, wMusicValue, pChord, bPlayMode, bChordLevel, pbMIDIValue);
482         return S_OK;
483 }
484
485 HRESULT WINAPI IDirectMusicPerformance8Impl_TimeToRhythm (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, DMUS_TIMESIGNATURE* pTimeSig, WORD* pwMeasure, BYTE* pbBeat, BYTE* pbGrid, short* pnOffset) {
486         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
487         FIXME("(%p, %ld, %p, %p, %p, %p, %p): stub\n", This, mtTime, pTimeSig, pwMeasure, pbBeat, pbGrid, pnOffset);
488         return S_OK;
489 }
490
491 HRESULT WINAPI IDirectMusicPerformance8Impl_RhythmToTime (LPDIRECTMUSICPERFORMANCE8 iface, WORD wMeasure, BYTE bBeat, BYTE bGrid, short nOffset, DMUS_TIMESIGNATURE* pTimeSig, MUSIC_TIME* pmtTime) {
492         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
493         FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This, wMeasure, bBeat, bGrid, nOffset, pTimeSig, pmtTime);
494         return S_OK;
495 }
496
497 /* IDirectMusicPerformance8 Interface part follow: */
498 HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio (LPDIRECTMUSICPERFORMANCE8 iface, 
499                                                       IDirectMusic** ppDirectMusic, 
500                                                       IDirectSound** ppDirectSound, 
501                                                       HWND hWnd, 
502                                                       DWORD dwDefaultPathType, 
503                                                       DWORD dwPChannelCount, 
504                                                       DWORD dwFlags, 
505                                                       DMUS_AUDIOPARAMS* pParams) {
506
507         IDirectSound* dsound = NULL;
508         HRESULT hr = S_OK;
509         
510         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
511         FIXME("(%p, %p, %p, %p, %lx, %lu, %lx, %p): to check\n", This, ppDirectMusic, ppDirectSound, hWnd, dwDefaultPathType, dwPChannelCount, dwFlags, pParams);
512
513         if (This->pDirectMusic || This->pDirectSound)
514           return DMUS_E_ALREADY_INITED;
515
516         if (NULL != ppDirectSound && NULL != *ppDirectSound) {
517           dsound = *ppDirectSound;
518         } else {
519           hr = DirectSoundCreate8 (NULL, (LPDIRECTSOUND8*) &dsound, NULL);
520           FIXME("return dsound(%p,%ld)\n", dsound, hr);
521           if (FAILED(hr) || !dsound)
522             return DSERR_NODRIVER;
523           if (ppDirectSound)
524             *ppDirectSound = dsound;  
525         }
526         
527         IDirectMusicPerformance8Impl_Init(iface, ppDirectMusic, dsound, hWnd);
528
529         /* Init increases the ref count of the dsound object. Decremente it if the app don't want a pointer to the object. */
530         if (NULL == ppDirectSound) {
531           IDirectSound_Release(This->pDirectSound);
532         }
533
534         /* as seen in msdn we need params init before audio path creation */
535         if (NULL != pParams) {
536           memcpy(&This->pParams, pParams, sizeof(DMUS_AUDIOPARAMS));
537         } else {
538           /**
539            * TODO, how can i fill the struct 
540            * as seen at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directX/htm/dmusaudioparams.asp
541            */
542           This->pParams.dwSize = sizeof(DMUS_AUDIOPARAMS);
543           This->pParams.fInitNow = FALSE;
544           This->pParams.dwValidData = DMUS_AUDIOPARAMS_FEATURES | DMUS_AUDIOPARAMS_VOICES | DMUS_AUDIOPARAMS_SAMPLERATE | DMUS_AUDIOPARAMS_DEFAULTSYNTH;
545           This->pParams.dwVoices = 64;
546           This->pParams.dwSampleRate = (DWORD) 22.050; 
547           This->pParams.dwFeatures = dwFlags;
548           This->pParams.clsidDefaultSynth = CLSID_DirectMusicSynthSink;
549         }
550         hr = IDirectMusicPerformance8Impl_CreateStandardAudioPath(iface, dwDefaultPathType, dwPChannelCount, FALSE, (IDirectMusicAudioPath**) &This->pDefaultPath);
551
552         return hr;
553 }
554
555 HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegmentEx (LPDIRECTMUSICPERFORMANCE8 iface, IUnknown* pSource, WCHAR* pwzSegmentName, IUnknown* pTransition, DWORD dwFlags, __int64 i64StartTime, IDirectMusicSegmentState** ppSegmentState, IUnknown* pFrom, IUnknown* pAudioPath) {
556         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
557         FIXME("(%p, %p, %p, %p, %ld, %lli, %p, %p, %p): stub\n", This, pSource, pwzSegmentName, pTransition, dwFlags, i64StartTime, ppSegmentState, pFrom, pAudioPath);
558         return S_OK;
559 }
560
561 HRESULT WINAPI IDirectMusicPerformance8Impl_StopEx (LPDIRECTMUSICPERFORMANCE8 iface, IUnknown* pObjectToStop, __int64 i64StopTime, DWORD dwFlags) {
562         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
563         FIXME("(%p, %p, %lli, %ld): stub\n", This, pObjectToStop, i64StopTime, dwFlags);
564         return S_OK;
565 }
566
567 HRESULT WINAPI IDirectMusicPerformance8Impl_ClonePMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pSourcePMSG, DMUS_PMSG** ppCopyPMSG) {
568         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
569         FIXME("(%p, %p, %p): stub\n", This, pSourcePMSG, ppCopyPMSG);
570         return S_OK;
571 }
572
573 HRESULT WINAPI IDirectMusicPerformance8Impl_CreateAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, IUnknown* pSourceConfig, BOOL fActivate, IDirectMusicAudioPath** ppNewPath) {
574         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
575         FIXME("(%p, %p, %d, %p): stub\n", This, pSourceConfig, fActivate, ppNewPath);
576         return S_OK;
577 }
578
579 /**
580  * see  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directX/htm/standardaudiopaths.asp
581  */
582 HRESULT WINAPI IDirectMusicPerformance8Impl_CreateStandardAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwType, DWORD dwPChannelCount, BOOL fActivate, IDirectMusicAudioPath** ppNewPath) {
583         IDirectMusicAudioPathImpl *default_path;
584         IDirectMusicAudioPath *pPath;
585         DSBUFFERDESC desc;
586         WAVEFORMATEX format;
587         LPDIRECTSOUNDBUFFER8 buffer;
588         HRESULT hr = S_OK;
589
590         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
591         
592         FIXME("(%p)->(%ld, %ld, %d, %p): semi-stub\n", This, dwType, dwPChannelCount, fActivate, ppNewPath);
593
594         if (NULL == ppNewPath) {
595           return E_POINTER;
596         }
597         
598         DMUSIC_CreateDirectMusicAudioPathImpl (&IID_IDirectMusicAudioPath, (LPVOID*)&pPath, NULL);
599         default_path = (IDirectMusicAudioPathImpl*)((char*)(pPath) - offsetof(IDirectMusicAudioPathImpl,AudioPathVtbl));
600         default_path->pPerf = (IDirectMusicPerformance8*) This;
601         
602         /* Secondary buffer description */
603         format.wFormatTag = WAVE_FORMAT_PCM;
604         format.nChannels = 1;
605         format.nSamplesPerSec = 44000;
606         format.nAvgBytesPerSec = 44000*2;
607         format.nBlockAlign = 2;
608         format.wBitsPerSample = 16;
609         format.cbSize = 0;
610         
611         desc.dwSize = sizeof(desc);
612         desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
613         desc.dwBufferBytes = DSBSIZE_MIN;
614         desc.dwReserved = 0;
615         desc.lpwfxFormat = &format;
616         desc.guid3DAlgorithm = GUID_NULL;
617         
618         switch(dwType) {
619         case DMUS_APATH_DYNAMIC_3D:
620                 desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
621                 break;
622         case DMUS_APATH_DYNAMIC_MONO:
623                 desc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
624                 break;
625         case DMUS_APATH_SHARED_STEREOPLUSREVERB:
626                 /* normally we havet to create 2 buffers (one for music other for reverb) 
627                  * in this case. See msdn
628                  */
629         case DMUS_APATH_DYNAMIC_STEREO:
630                 desc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
631                 format.nChannels = 2;
632                 format.nBlockAlign *= 2;
633                 format.nAvgBytesPerSec *=2;
634                 break;
635         default:
636                 HeapFree(GetProcessHeap(), 0, default_path); 
637                 *ppNewPath = NULL;
638                 return E_INVALIDARG;
639                 break;
640         }
641
642         /* FIXME: Should we create one secondary buffer for each PChannel? */
643         hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL);
644         if (FAILED(hr)) {
645                 HeapFree(GetProcessHeap(), 0, default_path); 
646                 *ppNewPath = NULL;
647                 return DSERR_BUFFERLOST;
648         }
649         default_path->pDSBuffer = (IDirectSoundBuffer*) buffer;
650
651         /* Update description for creating primary buffer */
652         desc.dwFlags |= DSBCAPS_PRIMARYBUFFER;
653         desc.dwBufferBytes = 0;
654         desc.lpwfxFormat = NULL;
655
656         hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL);
657         if (FAILED(hr)) {
658                 IDirectSoundBuffer_Release(default_path->pDSBuffer);
659                 HeapFree(GetProcessHeap(), 0, default_path); 
660                 *ppNewPath = NULL;
661                 return DSERR_BUFFERLOST;
662         }
663         default_path->pPrimary = (IDirectSoundBuffer*) buffer;
664
665         *ppNewPath = (LPDIRECTMUSICAUDIOPATH) pPath;
666         
667         TRACE(" returning IDirectMusicPerformance interface at %p.\n", *ppNewPath);
668
669         return S_OK;
670 }
671
672 HRESULT WINAPI IDirectMusicPerformance8Impl_SetDefaultAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicAudioPath* pAudioPath) {
673         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
674
675         FIXME("(%p, %p): semi-stub\n", This, pAudioPath);
676         if (NULL != This->pDefaultPath) {
677                 IDirectMusicAudioPath_Release((LPDIRECTMUSICAUDIOPATH) This->pDefaultPath);
678                 ((IDirectMusicAudioPathImpl*) This->pDefaultPath)->pPerf = NULL;
679                 This->pDefaultPath = NULL;
680         }
681         This->pDefaultPath = pAudioPath;
682         if (NULL != This->pDefaultPath) {
683                 IDirectMusicAudioPath_AddRef((LPDIRECTMUSICAUDIOPATH) This->pDefaultPath);
684                 ((IDirectMusicAudioPathImpl*) This->pDefaultPath)->pPerf = (IDirectMusicPerformance8*) This;    
685         }
686         
687         return S_OK;
688 }
689
690 HRESULT WINAPI IDirectMusicPerformance8Impl_GetDefaultAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicAudioPath** ppAudioPath) {
691     ICOM_THIS(IDirectMusicPerformance8Impl,iface);
692
693         FIXME("(%p, %p): semi-stub (%p)\n", This, ppAudioPath, This->pDefaultPath);
694
695         if (NULL != This->pDefaultPath) {
696           *ppAudioPath = (LPDIRECTMUSICAUDIOPATH) This->pDefaultPath;
697           IDirectMusicAudioPath_AddRef(*ppAudioPath);
698         } else {
699           *ppAudioPath = NULL;
700         }
701         return S_OK;
702 }
703
704 HRESULT WINAPI IDirectMusicPerformance8Impl_GetParamEx (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwTrackID, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
705         ICOM_THIS(IDirectMusicPerformance8Impl,iface);
706
707         FIXME("(%p, %s, %ld, %ld, %ld, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwTrackID, dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
708
709         return S_OK;
710 }
711
712 ICOM_VTABLE(IDirectMusicPerformance8) DirectMusicPerformance8_Vtbl = {
713     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
714         IDirectMusicPerformance8Impl_QueryInterface,
715         IDirectMusicPerformance8Impl_AddRef,
716         IDirectMusicPerformance8Impl_Release,
717         IDirectMusicPerformance8Impl_Init,
718         IDirectMusicPerformance8Impl_PlaySegment,
719         IDirectMusicPerformance8Impl_Stop,
720         IDirectMusicPerformance8Impl_GetSegmentState,
721         IDirectMusicPerformance8Impl_SetPrepareTime,
722         IDirectMusicPerformance8Impl_GetPrepareTime,
723         IDirectMusicPerformance8Impl_SetBumperLength,
724         IDirectMusicPerformance8Impl_GetBumperLength,
725         IDirectMusicPerformance8Impl_SendPMsg,
726         IDirectMusicPerformance8Impl_MusicToReferenceTime,
727         IDirectMusicPerformance8Impl_ReferenceToMusicTime,
728         IDirectMusicPerformance8Impl_IsPlaying,
729         IDirectMusicPerformance8Impl_GetTime,
730         IDirectMusicPerformance8Impl_AllocPMsg,
731         IDirectMusicPerformance8Impl_FreePMsg,
732         IDirectMusicPerformance8Impl_GetGraph,
733         IDirectMusicPerformance8Impl_SetGraph,
734         IDirectMusicPerformance8Impl_SetNotificationHandle,
735         IDirectMusicPerformance8Impl_GetNotificationPMsg,
736         IDirectMusicPerformance8Impl_AddNotificationType,
737         IDirectMusicPerformance8Impl_RemoveNotificationType,
738         IDirectMusicPerformance8Impl_AddPort,
739         IDirectMusicPerformance8Impl_RemovePort,
740         IDirectMusicPerformance8Impl_AssignPChannelBlock,
741         IDirectMusicPerformance8Impl_AssignPChannel,
742         IDirectMusicPerformance8Impl_PChannelInfo,
743         IDirectMusicPerformance8Impl_DownloadInstrument,
744         IDirectMusicPerformance8Impl_Invalidate,
745         IDirectMusicPerformance8Impl_GetParam,
746         IDirectMusicPerformance8Impl_SetParam,
747         IDirectMusicPerformance8Impl_GetGlobalParam,
748         IDirectMusicPerformance8Impl_SetGlobalParam,
749         IDirectMusicPerformance8Impl_GetLatencyTime,
750         IDirectMusicPerformance8Impl_GetQueueTime,
751         IDirectMusicPerformance8Impl_AdjustTime,
752         IDirectMusicPerformance8Impl_CloseDown,
753         IDirectMusicPerformance8Impl_GetResolvedTime,
754         IDirectMusicPerformance8Impl_MIDIToMusic,
755         IDirectMusicPerformance8Impl_MusicToMIDI,
756         IDirectMusicPerformance8Impl_TimeToRhythm,
757         IDirectMusicPerformance8Impl_RhythmToTime,
758         IDirectMusicPerformance8Impl_InitAudio,
759         IDirectMusicPerformance8Impl_PlaySegmentEx,
760         IDirectMusicPerformance8Impl_StopEx,
761         IDirectMusicPerformance8Impl_ClonePMsg,
762         IDirectMusicPerformance8Impl_CreateAudioPath,
763         IDirectMusicPerformance8Impl_CreateStandardAudioPath,
764         IDirectMusicPerformance8Impl_SetDefaultAudioPath,
765         IDirectMusicPerformance8Impl_GetDefaultAudioPath,
766         IDirectMusicPerformance8Impl_GetParamEx
767 };
768
769 /* for ClassFactory */
770 HRESULT WINAPI DMUSIC_CreateDirectMusicPerformanceImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
771         IDirectMusicPerformance8Impl *obj;
772
773         TRACE("(%p,%p,%p)\n", lpcGUID, ppobj, pUnkOuter);
774
775         obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicPerformance8Impl));
776         if (NULL == obj)        {
777                 *ppobj = (LPDIRECTMUSICPERFORMANCE8)NULL;
778                 return E_OUTOFMEMORY;
779         }
780         obj->lpVtbl = &DirectMusicPerformance8_Vtbl;
781         obj->ref = 0;  /* will be inited by QueryInterface */
782         obj->pDirectMusic = NULL;
783         obj->pDirectSound = NULL;
784         obj->pDefaultPath = NULL;
785         
786         return IDirectMusicPerformance8Impl_QueryInterface ((LPDIRECTMUSICPERFORMANCE8)obj, lpcGUID, ppobj);
787 }