~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dmime/performance.c

Version: ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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 DMUS_PMSGItem DMUS_PMSGItem;
 26 struct DMUS_PMSGItem {
 27   DMUS_PMSGItem* next;
 28   DMUS_PMSGItem* prev;
 29 
 30   REFERENCE_TIME rtItemTime;
 31   BOOL bInUse;
 32   DWORD cb;
 33   DMUS_PMSG pMsg;
 34 };
 35 
 36 #define DMUS_PMSGToItem(pMSG)   ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) -  offsetof(DMUS_PMSGItem, pMsg)))
 37 #define DMUS_ItemToPMSG(pItem)  (&(pItem->pMsg))
 38 #define DMUS_ItemRemoveFromQueue(This,pItem) \
 39 {\
 40   if (pItem->prev) pItem->prev->next = pItem->next;\
 41   if (pItem->next) pItem->next->prev = pItem->prev;\
 42   if (This->head == pItem) This->head = pItem->next;\
 43   if (This->imm_head == pItem) This->imm_head = pItem->next;\
 44   pItem->bInUse = FALSE;\
 45 }
 46 
 47 #define PROCESSMSG_START           (WM_APP + 0)
 48 #define PROCESSMSG_EXIT            (WM_APP + 1)
 49 #define PROCESSMSG_REMOVE          (WM_APP + 2)
 50 #define PROCESSMSG_ADD             (WM_APP + 4)
 51 
 52 
 53 static DMUS_PMSGItem* ProceedMsg(IDirectMusicPerformance8Impl* This, DMUS_PMSGItem* cur) {
 54   if (cur->pMsg.dwType == DMUS_PMSGT_NOTIFICATION) {
 55     SetEvent(This->hNotification);
 56   }     
 57   DMUS_ItemRemoveFromQueue(This, cur);
 58   switch (cur->pMsg.dwType) {
 59   case DMUS_PMSGT_WAVE:
 60   case DMUS_PMSGT_TEMPO:   
 61   case DMUS_PMSGT_STOP:
 62   default:
 63     FIXME("Unhandled PMsg Type: 0x%x\n", cur->pMsg.dwType);
 64     break;
 65   }
 66   return cur;
 67 }
 68 
 69 static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
 70   IDirectMusicPerformance8Impl* This = (IDirectMusicPerformance8Impl*) lpParam;
 71   DWORD timeOut = INFINITE;
 72   MSG msg;
 73   HRESULT hr;
 74   REFERENCE_TIME rtCurTime;
 75   DMUS_PMSGItem* it = NULL;
 76   DMUS_PMSGItem* cur = NULL;
 77   DMUS_PMSGItem* it_next = NULL;
 78 
 79   while (TRUE) {
 80     DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;
 81 
 82     if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
 83     timeOut = INFINITE;
 84 
 85     EnterCriticalSection(&This->safe);
 86     hr = IDirectMusicPerformance8_GetTime((IDirectMusicPerformance8*) This, &rtCurTime, NULL);
 87     if (FAILED(hr)) {
 88       goto outrefresh;
 89     }
 90     
 91     for (it = This->imm_head; NULL != it; ) {
 92       it_next = it->next;
 93       cur = ProceedMsg(This, it);  
 94       HeapFree(GetProcessHeap(), 0, cur); 
 95       it = it_next;
 96     }
 97 
 98     for (it = This->head; NULL != it && it->rtItemTime < rtCurTime + dwDec; ) {
 99       it_next = it->next;
100       cur = ProceedMsg(This, it);
101       HeapFree(GetProcessHeap(), 0, cur);
102       it = it_next;
103     }
104     if (NULL != it) {
105       timeOut = ( it->rtItemTime - rtCurTime ) + This->rtLatencyTime;
106     }
107 
108 outrefresh:
109     LeaveCriticalSection(&This->safe);
110     
111     while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
112       /** if hwnd we suppose that is a windows event ... */
113       if  (NULL != msg.hwnd) {
114         TranslateMessage(&msg);
115         DispatchMessageA(&msg);
116       } else {
117         switch (msg.message) {      
118         case WM_QUIT:
119         case PROCESSMSG_EXIT:
120           goto outofthread;
121         case PROCESSMSG_START:
122           break;
123         case PROCESSMSG_ADD:
124           break;
125         case PROCESSMSG_REMOVE:
126           break;
127         default:
128           ERR("Unhandled message %u. Critical Path\n", msg.message);
129           break;
130         }
131       }
132     }
133 
134     /** here we should run a little of current AudioPath */
135 
136   }
137 
138 outofthread:
139   TRACE("(%p): Exiting\n", This);
140   
141   return 0;
142 }
143 
144 static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UINT iMsg) {
145   if (FALSE == This->procThreadTicStarted && PROCESSMSG_EXIT != iMsg) {
146     BOOL res;
147     This->procThread = CreateThread(NULL, 0, ProcessMsgThread, This, 0, &This->procThreadId);
148     if (NULL == This->procThread) return FALSE;
149     SetThreadPriority(This->procThread, THREAD_PRIORITY_TIME_CRITICAL);
150     This->procThreadTicStarted = TRUE;
151     while(1) {
152       res = PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
153       /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
154       if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID))
155         Sleep(0);
156       else
157         break;
158     }
159     return res;
160   }
161   return PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
162 }
163 
164 /* IDirectMusicPerformance8 IUnknown part: */
165 static HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface (LPDIRECTMUSICPERFORMANCE8 iface, REFIID riid, LPVOID *ppobj) {
166   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
167   TRACE("(%p, %s,%p)\n", This, debugstr_dmguid(riid), ppobj);
168 
169   if (IsEqualIID (riid, &IID_IUnknown) || 
170       IsEqualIID (riid, &IID_IDirectMusicPerformance) ||
171       IsEqualIID (riid, &IID_IDirectMusicPerformance2) ||
172       IsEqualIID (riid, &IID_IDirectMusicPerformance8)) {
173     IUnknown_AddRef(iface);
174     *ppobj = This;
175     return S_OK;
176   }
177         
178   WARN("(%p, %s,%p): not found\n", This, debugstr_dmguid(riid), ppobj);
179   return E_NOINTERFACE;
180 }
181 
182 static ULONG WINAPI IDirectMusicPerformance8Impl_AddRef (LPDIRECTMUSICPERFORMANCE8 iface) {
183   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
184   ULONG ref = InterlockedIncrement(&This->ref);
185 
186   TRACE("(%p): AddRef from %d\n", This, ref - 1);
187 
188   DMIME_LockModule();
189 
190   return ref;
191 }
192 
193 static ULONG WINAPI IDirectMusicPerformance8Impl_Release (LPDIRECTMUSICPERFORMANCE8 iface) {
194   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
195   ULONG ref = InterlockedDecrement(&This->ref);
196   TRACE("(%p): ReleaseRef to %d\n", This, ref);
197   
198   if (ref == 0) {
199     This->safe.DebugInfo->Spare[0] = 0;
200     DeleteCriticalSection(&This->safe);
201     HeapFree(GetProcessHeap(), 0, This);
202   }
203 
204   DMIME_UnlockModule();
205 
206   return ref;
207 }
208 
209 /* IDirectMusicPerformanceImpl IDirectMusicPerformance Interface part: */
210 static HRESULT WINAPI IDirectMusicPerformance8Impl_Init (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusic** ppDirectMusic, LPDIRECTSOUND pDirectSound, HWND hWnd) {
211         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
212 
213         FIXME("(iface = %p, dmusic = %p, dsound = %p, hwnd = %p)\n", This, ppDirectMusic, pDirectSound, hWnd);
214         if (This->pDirectMusic || This->pDirectSound)
215           return DMUS_E_ALREADY_INITED;
216         
217         if (NULL == hWnd) {
218           hWnd = GetForegroundWindow();
219         }
220 
221         if (NULL != pDirectSound) {
222           This->pDirectSound = pDirectSound;
223           IDirectSound_AddRef(This->pDirectSound);
224         } else {
225           DirectSoundCreate8(NULL, (LPDIRECTSOUND8*) &This->pDirectSound, NULL);
226           if (!This->pDirectSound) return DSERR_NODRIVER;
227 
228           if (NULL != hWnd) {
229             IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);
230           } else {
231             /* how to get the ForeGround window handle ? */
232             /*IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);*/
233           }
234         }
235 
236         if (NULL != ppDirectMusic && NULL != *ppDirectMusic) {
237           /* app creates it's own dmusic object and gives it to performance */
238           This->pDirectMusic = (IDirectMusic8*) *ppDirectMusic;
239           IDirectMusic8_AddRef(This->pDirectMusic);
240         } else {
241           /* app allows the performance to initialise itself and needs a pointer to object*/
242           CoCreateInstance (&CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusic8, (void**)&This->pDirectMusic);
243           if (ppDirectMusic) {
244             *ppDirectMusic = (LPDIRECTMUSIC) This->pDirectMusic;
245             IDirectMusic8_AddRef((LPDIRECTMUSIC8) *ppDirectMusic);
246           }
247         }
248         
249         return S_OK;
250 }
251 
252 static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegment (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, DWORD dwFlags, __int64 i64StartTime, IDirectMusicSegmentState** ppSegmentState) {
253         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
254         FIXME("(%p, %p, %d, 0x%s, %p): stub\n", This, pSegment, dwFlags,
255             wine_dbgstr_longlong(i64StartTime), ppSegmentState);
256         return S_OK;
257 }
258 
259 static HRESULT WINAPI IDirectMusicPerformance8Impl_Stop (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, IDirectMusicSegmentState* pSegmentState, MUSIC_TIME mtTime, DWORD dwFlags) {
260         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
261         FIXME("(%p, %p, %p, %ld, %d): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags);
262         return S_OK;
263 }
264 
265 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegmentState** ppSegmentState, MUSIC_TIME mtTime) {
266         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
267         FIXME("(%p,%p, %ld): stub\n", This, ppSegmentState, mtTime);
268         return S_OK;
269 }
270 
271 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
272   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
273   TRACE("(%p, %d)\n", This, dwMilliSeconds);
274   This->dwPrepareTime = dwMilliSeconds;
275   return S_OK;
276 }
277 
278 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
279   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
280   TRACE("(%p, %p)\n", This, pdwMilliSeconds);
281   if (NULL == pdwMilliSeconds) {
282     return E_POINTER;
283   }
284   *pdwMilliSeconds = This->dwPrepareTime;
285   return S_OK;
286 }
287 
288 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
289   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
290   TRACE("(%p, %d)\n", This, dwMilliSeconds);
291   This->dwBumperLength =  dwMilliSeconds;
292   return S_OK;
293 }
294 
295 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
296   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
297   TRACE("(%p, %p)\n", This, pdwMilliSeconds);
298   if (NULL == pdwMilliSeconds) {
299     return E_POINTER;
300   }
301   *pdwMilliSeconds = This->dwBumperLength;
302   return S_OK;
303 }
304 
305 static HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pPMSG) {
306   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
307   DMUS_PMSGItem* pItem = NULL;
308   DMUS_PMSGItem* it = NULL;
309   DMUS_PMSGItem* prev_it = NULL;
310   DMUS_PMSGItem** queue = NULL;
311 
312   FIXME("(%p, %p): stub\n", This, pPMSG);
313          
314   if (NULL == pPMSG) {
315     return E_POINTER;
316   }
317   pItem = DMUS_PMSGToItem(pPMSG);
318   if (NULL == pItem) {
319     return E_POINTER;
320   }
321   if (pItem->bInUse) {
322     return DMUS_E_ALREADY_SENT;
323   }
324   
325   /* TODO: Valid Flags */
326   /* TODO: DMUS_PMSGF_MUSICTIME */
327   pItem->rtItemTime = pPMSG->rtTime;
328 
329   if (pPMSG->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) {
330     queue = &This->imm_head;
331   } else {
332     queue = &This->head;
333   }
334 
335   EnterCriticalSection(&This->safe);
336   for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
337     prev_it = it;
338   }
339   if (NULL == prev_it) {
340     pItem->prev = NULL;
341     if (NULL != *queue) pItem->next = (*queue)->next;
342     /*assert( NULL == pItem->next->prev );*/
343     if (NULL != pItem->next) pItem->next->prev = pItem;
344     *queue = pItem;
345   } else {
346     pItem->prev = prev_it;
347     pItem->next = prev_it->next;
348     prev_it->next = pItem;
349     if (NULL != pItem->next) pItem->next->prev = pItem;
350   } 
351   LeaveCriticalSection(&This->safe);
352 
353   /** now in use, prevent from stupid Frees */
354   pItem->bInUse = TRUE;
355   return S_OK;
356 }
357 
358 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToReferenceTime (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, REFERENCE_TIME* prtTime) {
359         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
360         FIXME("(%p, %ld, %p): stub\n", This, mtTime, prtTime);
361         return S_OK;
362 }
363 
364 static HRESULT WINAPI IDirectMusicPerformance8Impl_ReferenceToMusicTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtTime, MUSIC_TIME* pmtTime) {
365         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
366         FIXME("(%p, 0x%s, %p): stub\n", This, wine_dbgstr_longlong(rtTime), pmtTime);
367         return S_OK;
368 }
369 
370 static HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, IDirectMusicSegmentState* pSegState) {
371         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
372         FIXME("(%p, %p, %p): stub\n", This, pSegment, pSegState);
373         return S_FALSE;
374 }
375 
376 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtNow, MUSIC_TIME* pmtNow) {
377   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
378   HRESULT hr = S_OK;
379   REFERENCE_TIME rtCur = 0;
380 
381   /*TRACE("(%p, %p, %p)\n", This, prtNow, pmtNow); */
382   if (This->procThreadTicStarted) {
383     rtCur = ((REFERENCE_TIME) GetTickCount() * 10000) - This->procThreadStartTime;
384   } else {
385     /*return DMUS_E_NO_MASTER_CLOCK;*/
386   }
387   if (NULL != prtNow) {
388     *prtNow = rtCur;
389   }
390   if (NULL != pmtNow) {
391     hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, rtCur, pmtNow);
392   }
393   return hr;
394 }
395 
396 static HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg (LPDIRECTMUSICPERFORMANCE8 iface, ULONG cb, DMUS_PMSG** ppPMSG) {
397   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
398   DMUS_PMSGItem* pItem = NULL;
399   
400   FIXME("(%p, %d, %p): stub\n", This, cb, ppPMSG);
401         
402   if (sizeof(DMUS_PMSG) > cb) {
403     return E_INVALIDARG;
404   }
405   if (NULL == ppPMSG) {
406     return E_POINTER;
407   }
408   pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb - sizeof(DMUS_PMSG)  + sizeof(DMUS_PMSGItem));
409   if (NULL == pItem) {
410     return E_OUTOFMEMORY;
411   }
412   pItem->pMsg.dwSize = cb;
413   *ppPMSG = DMUS_ItemToPMSG(pItem);
414   return S_OK;
415 }
416 
417 static HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pPMSG) {
418   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
419   DMUS_PMSGItem* pItem = NULL;
420   
421   FIXME("(%p, %p): stub\n", This, pPMSG);
422   
423   if (NULL == pPMSG) {
424     return E_POINTER;
425   }
426   pItem = DMUS_PMSGToItem(pPMSG);
427   if (NULL == pItem) {
428     return E_POINTER;
429   }
430   if (pItem->bInUse) {
431     /** prevent for freeing PMsg in queue (ie to be processed) */
432     return DMUS_E_CANNOT_FREE;
433   }
434   /** now we can remove it safely */
435   EnterCriticalSection(&This->safe);
436   DMUS_ItemRemoveFromQueue( This, pItem );
437   LeaveCriticalSection(&This->safe);
438 
439   /** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */
440   HeapFree(GetProcessHeap(), 0, pItem);  
441   return S_OK;
442 }
443 
444 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGraph (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicGraph** ppGraph) {
445   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
446   FIXME("(%p, %p): to check\n", This, ppGraph);
447   if (NULL != This->pToolGraph) {
448     *ppGraph = This->pToolGraph;
449     IDirectMusicGraph_AddRef(*ppGraph);
450   } else {
451     return E_FAIL;
452   }
453   return S_OK;
454 }
455 
456 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGraph (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicGraph* pGraph) {
457   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
458   
459   FIXME("(%p, %p): to check\n", This, pGraph);
460   
461   if (NULL != This->pToolGraph) {
462     /* Todo clean buffers and tools before */
463     IDirectMusicGraph_Release(This->pToolGraph);
464   }
465   This->pToolGraph = pGraph;
466   if (NULL != This->pToolGraph) {
467     IDirectMusicGraph_AddRef(This->pToolGraph);
468   }
469   return S_OK;
470 }
471 
472 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetNotificationHandle (LPDIRECTMUSICPERFORMANCE8 iface, HANDLE hNotification, REFERENCE_TIME rtMinimum) {
473   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
474   FIXME("(%p, %p, 0x%s): stub\n", This, hNotification, wine_dbgstr_longlong(rtMinimum));
475   This->hNotification = hNotification;
476   if (rtMinimum) This->rtMinimum = rtMinimum;
477   return S_OK;
478 }
479 
480 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetNotificationPMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_NOTIFICATION_PMSG** ppNotificationPMsg) {
481   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
482   
483   
484   FIXME("(%p, %p): stub\n", This, ppNotificationPMsg);
485   if (NULL == ppNotificationPMsg) {
486     return E_POINTER;
487   }
488   
489   
490 
491   return S_FALSE;
492   /*return S_OK;*/
493 }
494 
495 static HRESULT WINAPI IDirectMusicPerformance8Impl_AddNotificationType (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidNotificationType) {
496         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
497         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
498         return S_OK;
499 }
500 
501 static HRESULT WINAPI IDirectMusicPerformance8Impl_RemoveNotificationType (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidNotificationType) {
502         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
503         FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
504         return S_OK;
505 }
506 
507 static HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicPort* pPort) {
508         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
509         HRESULT hr = E_FAIL;
510         FIXME("(%p, %p): stub\n", This, pPort);
511         if (!This->pDirectMusic || !This->pDirectSound) return DMUS_E_NOT_INIT;
512         if (NULL == pPort) {
513           GUID port_guid;
514           IDirectMusicPort* pDefaultPort = NULL;
515           DMUS_PORTPARAMS params;
516           int i, j;
517           hr = IDirectMusic8_GetDefaultPort(This->pDirectMusic, &port_guid);
518           if (FAILED(hr)) return hr;
519           ZeroMemory(&params, sizeof(params)); 
520           params.dwSize = sizeof(params);
521           params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_SHARE;
522           params.dwChannelGroups = 1;
523           params.fShare = TRUE;
524           hr = IDirectMusic8_CreatePort(This->pDirectMusic, &port_guid, &params, &pDefaultPort, NULL);
525           if (FAILED(hr)) return hr;
526           hr = IDirectMusicPort_Activate(pDefaultPort, TRUE);
527           if (FAILED(hr)) { IDirectMusicPort_Release(pDefaultPort); return hr; }
528           j = 0;
529           for (i = 0; i < 16; ++i) {
530             if (NULL == This->PChannel[i].port) {
531               This->PChannel[i].port = pPort; 
532               This->PChannel[i].group = 0; 
533               This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
534               j++;
535             }
536           }
537         } else {
538           IDirectMusicPort_AddRef(pPort);         
539         }
540         /**
541          * We should remember added Ports (for example using a list)
542          * and control if Port is registered for each api who use ports
543          */
544         return S_OK;
545 }
546 
547 static HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicPort* pPort) {
548         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
549         FIXME("(%p, %p): stub\n", This, pPort);
550         IDirectMusicPort_Release (pPort);
551         return S_OK;
552 }
553 
554 static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwBlockNum, IDirectMusicPort* pPort, DWORD dwGroup) {
555         int i, j, range /* min value in range */;
556         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
557 
558         FIXME("(%p, %d, %p, %d): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1);
559         if (NULL == pPort) return E_POINTER;
560 
561         range = 16 * dwBlockNum;
562         j = 0;
563         for (i = range; i < range+16; i++) {
564                 /*TRACE("Setting PChannel[%i] to port %p, group %ld, MIDI port %i\n", i, pPort, dwGroup-1, j); */
565                 This->PChannel[i].port = pPort; 
566                 This->PChannel[i].group = dwGroup - 1; /* first index is always zero */
567                 This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
568                 j++;
569         }
570         /*if (dwGroup > 2) return S_FALSE;*/
571 
572         return S_OK;
573 }
574 
575 static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwPChannel, IDirectMusicPort* pPort, DWORD dwGroup, DWORD dwMChannel) {
576         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
577 
578         TRACE("(%p, %d, %p, %d, %d)\n", This, dwPChannel, pPort, dwGroup, dwMChannel);
579         if (NULL == pPort) return E_POINTER;
580         This->PChannel[dwPChannel].port = pPort; 
581         This->PChannel[dwPChannel].group = dwGroup; 
582         This->PChannel[dwPChannel].channel = dwMChannel;
583 
584         return S_OK;
585 }
586 
587 static HRESULT WINAPI IDirectMusicPerformance8Impl_PChannelInfo (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwPChannel, IDirectMusicPort** ppPort, DWORD* pdwGroup, DWORD* pdwMChannel) {
588         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
589         FIXME("(%p, %d, %p, %p, %p): stub\n", This, dwPChannel, ppPort, pdwGroup, pdwMChannel);
590         return S_OK;
591 }
592 
593 static HRESULT WINAPI IDirectMusicPerformance8Impl_DownloadInstrument (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicInstrument* pInst, DWORD dwPChannel, IDirectMusicDownloadedInstrument** ppDownInst, DMUS_NOTERANGE* pNoteRanges, DWORD dwNumNoteRanges, IDirectMusicPort** ppPort, DWORD* pdwGroup, DWORD* pdwMChannel) {
594         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
595         FIXME("(%p, %p, %d, %p, %p, %d, %p, %p, %p): stub\n", This, pInst, dwPChannel, ppDownInst, pNoteRanges, dwNumNoteRanges, ppPort, pdwGroup, pdwMChannel);
596         return S_OK;
597 }
598 
599 static HRESULT WINAPI IDirectMusicPerformance8Impl_Invalidate (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, DWORD dwFlags) {
600         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
601         FIXME("(%p, %ld, %d): stub\n", This, mtTime, dwFlags);
602         return S_OK;
603 }
604 
605 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
606         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
607         FIXME("(%p, %s, %d, %d, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
608         return S_OK;
609 }
610 
611 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void* pParam) {
612         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
613         FIXME("(%p, %s, %d, %d, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
614         return S_OK;
615 }
616 
617 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGlobalParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, void* pParam, DWORD dwSize) {
618         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
619 
620         TRACE("(%p, %s, %p, %d): stub\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
621         
622         if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload))
623                 memcpy(pParam, &This->fAutoDownload, sizeof(&This->fAutoDownload));
624         if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel))
625                 memcpy(pParam, &This->cMasterGrooveLevel, sizeof(&This->cMasterGrooveLevel));
626         if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo))
627                 memcpy(pParam, &This->fMasterTempo, sizeof(&This->fMasterTempo));
628         if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume))
629                 memcpy(pParam, &This->lMasterVolume, sizeof(&This->lMasterVolume));
630 
631         return S_OK;
632 }
633 
634 static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, void* pParam, DWORD dwSize) {
635         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
636 
637         TRACE("(%p, %s, %p, %d)\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
638         
639         if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload)) {
640                 memcpy(&This->fAutoDownload, pParam, dwSize);
641                 TRACE("=> AutoDownload set to %d\n", This->fAutoDownload);
642         }
643         if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel)) {
644                 memcpy(&This->cMasterGrooveLevel, pParam, dwSize);
645                 TRACE("=> MasterGrooveLevel set to %i\n", This->cMasterGrooveLevel);
646         }
647         if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo)) {
648                 memcpy(&This->fMasterTempo, pParam, dwSize);
649                 TRACE("=> MasterTempo set to %f\n", This->fMasterTempo);
650         }
651         if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) {
652                 memcpy(&This->lMasterVolume, pParam, dwSize);
653                 TRACE("=> MasterVolume set to %li\n", This->lMasterVolume);
654         }
655 
656         return S_OK;
657 }
658 
659 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
660         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
661         TRACE("(%p, %p): stub\n", This, prtTime);
662         *prtTime = This->rtLatencyTime;
663         return S_OK;
664 }
665 
666 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetQueueTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
667         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
668         FIXME("(%p, %p): stub\n", This, prtTime);
669         return S_OK;
670 }
671 
672 static HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtAmount) {
673         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
674         FIXME("(%p, 0x%s): stub\n", This, wine_dbgstr_longlong(rtAmount));
675         return S_OK;
676 }
677 
678 static HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown (LPDIRECTMUSICPERFORMANCE8 iface) {
679   IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
680   FIXME("(%p): stub\n", This);
681   if (PostMessageToProcessMsgThread(This, PROCESSMSG_EXIT)) {
682     WaitForSingleObject(This->procThread, INFINITE);
683     This->procThreadTicStarted = FALSE;
684     CloseHandle(This->procThread);
685   }
686   if (NULL != This->pDirectSound) {
687     IDirectSound_Release(This->pDirectSound);
688     This->pDirectSound = NULL;
689   }
690   if (NULL != This->pDirectMusic) {
691     IDirectMusic8_Release(This->pDirectMusic);
692     This->pDirectMusic = NULL;
693   }
694   return S_OK;
695 }
696 
697 static HRESULT WINAPI IDirectMusicPerformance8Impl_GetResolvedTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtTime, REFERENCE_TIME* prtResolved, DWORD dwTimeResolveFlags) {
698         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
699         FIXME("(%p, 0x%s, %p, %d): stub\n", This, wine_dbgstr_longlong(rtTime),
700             prtResolved, dwTimeResolveFlags);
701         return S_OK;
702 }
703 
704 static HRESULT WINAPI IDirectMusicPerformance8Impl_MIDIToMusic (LPDIRECTMUSICPERFORMANCE8 iface, BYTE bMIDIValue, DMUS_CHORD_KEY* pChord, BYTE bPlayMode, BYTE bChordLevel, WORD* pwMusicValue) {
705         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
706         FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, bMIDIValue, pChord, bPlayMode, bChordLevel, pwMusicValue);
707         return S_OK;
708 }
709 
710 static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToMIDI (LPDIRECTMUSICPERFORMANCE8 iface, WORD wMusicValue, DMUS_CHORD_KEY* pChord, BYTE bPlayMode, BYTE bChordLevel, BYTE* pbMIDIValue) {
711         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
712         FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, wMusicValue, pChord, bPlayMode, bChordLevel, pbMIDIValue);
713         return S_OK;
714 }
715 
716 static HRESULT WINAPI IDirectMusicPerformance8Impl_TimeToRhythm (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, DMUS_TIMESIGNATURE* pTimeSig, WORD* pwMeasure, BYTE* pbBeat, BYTE* pbGrid, short* pnOffset) {
717         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
718         FIXME("(%p, %ld, %p, %p, %p, %p, %p): stub\n", This, mtTime, pTimeSig, pwMeasure, pbBeat, pbGrid, pnOffset);
719         return S_OK;
720 }
721 
722 static HRESULT WINAPI IDirectMusicPerformance8Impl_RhythmToTime (LPDIRECTMUSICPERFORMANCE8 iface, WORD wMeasure, BYTE bBeat, BYTE bGrid, short nOffset, DMUS_TIMESIGNATURE* pTimeSig, MUSIC_TIME* pmtTime) {
723         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
724         FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This, wMeasure, bBeat, bGrid, nOffset, pTimeSig, pmtTime);
725         return S_OK;
726 }
727 
728 /* IDirectMusicPerformance8 Interface part follow: */
729 static HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio (LPDIRECTMUSICPERFORMANCE8 iface, 
730                                                       IDirectMusic** ppDirectMusic, 
731                                                       IDirectSound** ppDirectSound, 
732                                                       HWND hWnd, 
733                                                       DWORD dwDefaultPathType, 
734                                                       DWORD dwPChannelCount, 
735                                                       DWORD dwFlags, 
736                                                       DMUS_AUDIOPARAMS* pParams) {
737 
738         IDirectSound* dsound = NULL;
739         HRESULT hr = S_OK;
740         
741         IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
742         FIXME("(%p, %p, %p, %p, %x, %u, %x, %p): to check\n", This, ppDirectMusic, ppDirectSound, hWnd, dwDefaultPathType, dwPChannelCount, dwFlags, pParams);
743 
744         if (This->pDirectMusic || This->pDirectSound)
745           return DMUS_E_ALREADY_INITED;
746 
747         if (NULL != ppDirectSound && NULL != *ppDirectSound) {
748           dsound = *ppDirectSound;
749         } else {
750           hr = DirectSoundCreate8 (NULL, (LPDIRECTSOUND8*) &dsound, NULL);
751           FIXME("return dsound(%p,%d)\n", dsound, hr);
752           if (FAILED(hr) || !dsound)
753             return DSERR_NODRIVER</