performance.c 39.7 KB
Newer Older
1 2
/* IDirectMusicPerformance Implementation
 *
3
 * Copyright (C) 2003-2004 Rok Mandeljc
4
 * Copyright (C) 2003-2004 Raphael Junqueira
5
 *
6 7 8 9
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
10 11 12
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
15
 *
16 17 18
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * 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 26 27 28 29 30 31 32 33 34
typedef struct DMUS_PMSGItem DMUS_PMSGItem;
struct DMUS_PMSGItem {
  DMUS_PMSGItem* next;
  DMUS_PMSGItem* prev;

  REFERENCE_TIME rtItemTime;
  BOOL bInUse;
  DWORD cb;
  DMUS_PMSG pMsg;
};
35

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#define DMUS_PMSGToItem(pMSG)   ((DMUS_PMSGItem*) (((unsigned char*) pPMSG) -  offsetof(DMUS_PMSGItem, pMsg)))
#define DMUS_ItemToPMSG(pItem)  (&(pItem->pMsg))
#define DMUS_ItemRemoveFromQueue(This,pItem) \
{\
  if (pItem->prev) pItem->prev->next = pItem->next;\
  if (pItem->next) pItem->next->prev = pItem->prev;\
  if (This->head == pItem) This->head = pItem->next;\
  if (This->imm_head == pItem) This->imm_head = pItem->next;\
  pItem->bInUse = FALSE;\
}

#define PROCESSMSG_START           (WM_APP + 0)
#define PROCESSMSG_EXIT            (WM_APP + 1)
#define PROCESSMSG_REMOVE          (WM_APP + 2)
#define PROCESSMSG_ADD             (WM_APP + 4)


53
static DMUS_PMSGItem* ProceedMsg(IDirectMusicPerformance8Impl* This, DMUS_PMSGItem* cur) {
54 55 56 57 58
  if (cur->pMsg.dwType == DMUS_PMSGT_NOTIFICATION) {
    SetEvent(This->hNotification);
  }	
  DMUS_ItemRemoveFromQueue(This, cur);
  switch (cur->pMsg.dwType) {
59 60
  case DMUS_PMSGT_WAVE:
  case DMUS_PMSGT_TEMPO:   
61 62
  case DMUS_PMSGT_STOP:
  default:
63
    FIXME("Unhandled PMsg Type: 0x%x\n", cur->pMsg.dwType);
64 65
    break;
  }
66
  return cur;
67 68 69
}

static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
70
  IDirectMusicPerformance8Impl* This = lpParam;
71
  DWORD timeOut = INFINITE;
72 73 74 75
  MSG msg;
  HRESULT hr;
  REFERENCE_TIME rtCurTime;
  DMUS_PMSGItem* it = NULL;
76
  DMUS_PMSGItem* cur = NULL;
77 78 79 80 81
  DMUS_PMSGItem* it_next = NULL;

  while (TRUE) {
    DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;

82 83 84
    if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
    timeOut = INFINITE;

85
    EnterCriticalSection(&This->safe);
86
    hr = IDirectMusicPerformance8_GetTime((IDirectMusicPerformance8*) This, &rtCurTime, NULL);
87 88 89 90 91 92
    if (FAILED(hr)) {
      goto outrefresh;
    }
    
    for (it = This->imm_head; NULL != it; ) {
      it_next = it->next;
93
      cur = ProceedMsg(This, it);  
94
      HeapFree(GetProcessHeap(), 0, cur); 
95 96 97 98 99
      it = it_next;
    }

    for (it = This->head; NULL != it && it->rtItemTime < rtCurTime + dwDec; ) {
      it_next = it->next;
100
      cur = ProceedMsg(This, it);
101
      HeapFree(GetProcessHeap(), 0, cur);
102 103
      it = it_next;
    }
104 105 106
    if (NULL != it) {
      timeOut = ( it->rtItemTime - rtCurTime ) + This->rtLatencyTime;
    }
107 108 109 110

outrefresh:
    LeaveCriticalSection(&This->safe);
    
111
    while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
      /** if hwnd we suppose that is a windows event ... */
      if  (NULL != msg.hwnd) {
	TranslateMessage(&msg);
	DispatchMessageA(&msg);
      } else {
	switch (msg.message) {	    
	case WM_QUIT:
	case PROCESSMSG_EXIT:
	  goto outofthread;
	case PROCESSMSG_START:
	  break;
	case PROCESSMSG_ADD:
	  break;
	case PROCESSMSG_REMOVE:
	  break;
	default:
	  ERR("Unhandled message %u. Critical Path\n", msg.message);
	  break;
130
	}
131 132
      }
    }
133 134 135

    /** here we should run a little of current AudioPath */

136 137 138 139 140 141 142 143 144 145
  }

outofthread:
  TRACE("(%p): Exiting\n", This);
  
  return 0;
}

static BOOL PostMessageToProcessMsgThread(IDirectMusicPerformance8Impl* This, UINT iMsg) {
  if (FALSE == This->procThreadTicStarted && PROCESSMSG_EXIT != iMsg) {
146
    BOOL res;
147 148 149 150
    This->procThread = CreateThread(NULL, 0, ProcessMsgThread, This, 0, &This->procThreadId);
    if (NULL == This->procThread) return FALSE;
    SetThreadPriority(This->procThread, THREAD_PRIORITY_TIME_CRITICAL);
    This->procThreadTicStarted = TRUE;
151 152 153 154 155 156 157 158 159
    while(1) {
      res = PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
      /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
      if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID))
	Sleep(0);
      else
	break;
    }
    return res;
160 161 162 163 164
  }
  return PostThreadMessageA(This->procThreadId, iMsg, 0, 0);
}

/* IDirectMusicPerformance8 IUnknown part: */
165
static HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface (LPDIRECTMUSICPERFORMANCE8 iface, REFIID riid, LPVOID *ppobj) {
166
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
167 168 169 170
  TRACE("(%p, %s,%p)\n", This, debugstr_dmguid(riid), ppobj);

  if (IsEqualIID (riid, &IID_IUnknown) || 
      IsEqualIID (riid, &IID_IDirectMusicPerformance) ||
171
      IsEqualIID (riid, &IID_IDirectMusicPerformance2) ||
172
      IsEqualIID (riid, &IID_IDirectMusicPerformance8)) {
173
    IUnknown_AddRef(iface);
174 175 176
    *ppobj = This;
    return S_OK;
  }
177
	
178 179
  WARN("(%p, %s,%p): not found\n", This, debugstr_dmguid(riid), ppobj);
  return E_NOINTERFACE;
180 181
}

182
static ULONG WINAPI IDirectMusicPerformance8Impl_AddRef (LPDIRECTMUSICPERFORMANCE8 iface) {
183
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
184 185
  ULONG ref = InterlockedIncrement(&This->ref);

186
  TRACE("(%p): AddRef from %d\n", This, ref - 1);
187

188 189
  DMIME_LockModule();

190
  return ref;
191 192
}

Mike McCormack's avatar
Mike McCormack committed
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 201 202
    DeleteCriticalSection(&This->safe);
    HeapFree(GetProcessHeap(), 0, This);
  }
203 204 205

  DMIME_UnlockModule();

206
  return ref;
207 208
}

209
/* IDirectMusicPerformanceImpl IDirectMusicPerformance Interface part: */
Mike McCormack's avatar
Mike McCormack committed
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 216
	  return DMUS_E_ALREADY_INITED;
	
217 218 219 220
	if (NULL == hWnd) {
	  hWnd = GetForegroundWindow();
	}

221
	if (NULL != pDirectSound) {
222 223
	  This->pDirectSound = pDirectSound;
	  IDirectSound_AddRef(This->pDirectSound);
224
	} else {
225
	  DirectSoundCreate8(NULL, (LPDIRECTSOUND8*) &This->pDirectSound, NULL);
226
	  if (!This->pDirectSound) return DSERR_NODRIVER;
227

228 229 230 231 232 233
	  if (NULL != hWnd) {
	    IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);
	  } else {
	    /* how to get the ForeGround window handle ? */
            /*IDirectSound8_SetCooperativeLevel(This->pDirectSound, hWnd, DSSCL_PRIORITY);*/
	  }
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 {
Austin English's avatar
Austin English committed
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 245
	    *ppDirectMusic = (LPDIRECTMUSIC) This->pDirectMusic;
	    IDirectMusic8_AddRef((LPDIRECTMUSIC8) *ppDirectMusic);
246
	  }
Rok Mandeljc's avatar
Rok Mandeljc committed
247 248 249
	}
	
	return S_OK;
250 251
}

Mike McCormack's avatar
Mike McCormack committed
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 257
	if (ppSegmentState)
	  return DMUSIC_CreateDirectMusicSegmentStateImpl(&IID_IDirectMusicSegmentState, (LPVOID*)ppSegmentState, NULL);
Rok Mandeljc's avatar
Rok Mandeljc committed
258
	return S_OK;
259 260
}

Mike McCormack's avatar
Mike McCormack committed
261
static HRESULT WINAPI IDirectMusicPerformance8Impl_Stop (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, IDirectMusicSegmentState* pSegmentState, MUSIC_TIME mtTime, DWORD dwFlags) {
262
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
263
	FIXME("(%p, %p, %p, %d, %d): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags);
Rok Mandeljc's avatar
Rok Mandeljc committed
264
	return S_OK;
265 266
}

Mike McCormack's avatar
Mike McCormack committed
267
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetSegmentState (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegmentState** ppSegmentState, MUSIC_TIME mtTime) {
268
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
269
	FIXME("(%p,%p, %d): stub\n", This, ppSegmentState, mtTime);
Rok Mandeljc's avatar
Rok Mandeljc committed
270
	return S_OK;
271 272
}

Mike McCormack's avatar
Mike McCormack committed
273
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
274
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
275
  TRACE("(%p, %d)\n", This, dwMilliSeconds);
276 277
  This->dwPrepareTime = dwMilliSeconds;
  return S_OK;
278 279
}

Mike McCormack's avatar
Mike McCormack committed
280
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetPrepareTime (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
281
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
282 283 284 285 286 287
  TRACE("(%p, %p)\n", This, pdwMilliSeconds);
  if (NULL == pdwMilliSeconds) {
    return E_POINTER;
  }
  *pdwMilliSeconds = This->dwPrepareTime;
  return S_OK;
288 289
}

Mike McCormack's avatar
Mike McCormack committed
290
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwMilliSeconds) {
291
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
292
  TRACE("(%p, %d)\n", This, dwMilliSeconds);
293 294
  This->dwBumperLength =  dwMilliSeconds;
  return S_OK;
295 296
}

Mike McCormack's avatar
Mike McCormack committed
297
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetBumperLength (LPDIRECTMUSICPERFORMANCE8 iface, DWORD* pdwMilliSeconds) {
298
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
299 300 301 302 303 304
  TRACE("(%p, %p)\n", This, pdwMilliSeconds);
  if (NULL == pdwMilliSeconds) {
    return E_POINTER;
  }
  *pdwMilliSeconds = This->dwBumperLength;
  return S_OK;
305 306
}

Mike McCormack's avatar
Mike McCormack committed
307
static HRESULT WINAPI IDirectMusicPerformance8Impl_SendPMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pPMSG) {
308
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
309 310 311 312 313 314 315 316 317 318 319 320 321 322
  DMUS_PMSGItem* pItem = NULL;
  DMUS_PMSGItem* it = NULL;
  DMUS_PMSGItem* prev_it = NULL;
  DMUS_PMSGItem** queue = NULL;

  FIXME("(%p, %p): stub\n", This, pPMSG);
	 
  if (NULL == pPMSG) {
    return E_POINTER;
  }
  pItem = DMUS_PMSGToItem(pPMSG);
  if (NULL == pItem) {
    return E_POINTER;
  }
323
  if (pItem->bInUse) {
324 325 326 327 328 329 330 331 332 333 334 335 336
    return DMUS_E_ALREADY_SENT;
  }
  
  /* TODO: Valid Flags */
  /* TODO: DMUS_PMSGF_MUSICTIME */
  pItem->rtItemTime = pPMSG->rtTime;

  if (pPMSG->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) {
    queue = &This->imm_head;
  } else {
    queue = &This->head;
  }

337
  EnterCriticalSection(&This->safe);
338 339 340 341 342
  for (it = *queue; NULL != it && it->rtItemTime < pItem->rtItemTime; it = it->next) {
    prev_it = it;
  }
  if (NULL == prev_it) {
    pItem->prev = NULL;
343
    if (NULL != *queue) pItem->next = (*queue)->next;
344 345 346 347 348 349 350 351
    /*assert( NULL == pItem->next->prev );*/
    if (NULL != pItem->next) pItem->next->prev = pItem;
    *queue = pItem;
  } else {
    pItem->prev = prev_it;
    pItem->next = prev_it->next;
    prev_it->next = pItem;
    if (NULL != pItem->next) pItem->next->prev = pItem;
352 353 354
  } 
  LeaveCriticalSection(&This->safe);

355 356 357
  /** now in use, prevent from stupid Frees */
  pItem->bInUse = TRUE;
  return S_OK;
358 359
}

Mike McCormack's avatar
Mike McCormack committed
360
static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToReferenceTime (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, REFERENCE_TIME* prtTime) {
361
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
362
	FIXME("(%p, %d, %p): stub\n", This, mtTime, prtTime);
Rok Mandeljc's avatar
Rok Mandeljc committed
363
	return S_OK;
364 365
}

Mike McCormack's avatar
Mike McCormack committed
366
static HRESULT WINAPI IDirectMusicPerformance8Impl_ReferenceToMusicTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtTime, MUSIC_TIME* pmtTime) {
367
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
368
	FIXME("(%p, 0x%s, %p): stub\n", This, wine_dbgstr_longlong(rtTime), pmtTime);
Rok Mandeljc's avatar
Rok Mandeljc committed
369
	return S_OK;
370 371
}

Mike McCormack's avatar
Mike McCormack committed
372
static HRESULT WINAPI IDirectMusicPerformance8Impl_IsPlaying (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicSegment* pSegment, IDirectMusicSegmentState* pSegState) {
373
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
374
	FIXME("(%p, %p, %p): stub\n", This, pSegment, pSegState);
375
	return S_FALSE;
376 377
}

378
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtNow, MUSIC_TIME* pmtNow) {
379
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
380 381 382 383
  HRESULT hr = S_OK;
  REFERENCE_TIME rtCur = 0;

  /*TRACE("(%p, %p, %p)\n", This, prtNow, pmtNow); */
384
  if (This->procThreadTicStarted) {
385 386 387 388 389 390 391 392 393 394 395
    rtCur = ((REFERENCE_TIME) GetTickCount() * 10000) - This->procThreadStartTime;
  } else {
    /*return DMUS_E_NO_MASTER_CLOCK;*/
  }
  if (NULL != prtNow) {
    *prtNow = rtCur;
  }
  if (NULL != pmtNow) {
    hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, rtCur, pmtNow);
  }
  return hr;
396 397
}

Mike McCormack's avatar
Mike McCormack committed
398
static HRESULT WINAPI IDirectMusicPerformance8Impl_AllocPMsg (LPDIRECTMUSICPERFORMANCE8 iface, ULONG cb, DMUS_PMSG** ppPMSG) {
399
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
400 401
  DMUS_PMSGItem* pItem = NULL;
  
402
  FIXME("(%p, %d, %p): stub\n", This, cb, ppPMSG);
403 404 405 406 407 408 409 410 411 412 413 414
	
  if (sizeof(DMUS_PMSG) > cb) {
    return E_INVALIDARG;
  }
  if (NULL == ppPMSG) {
    return E_POINTER;
  }
  pItem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb - sizeof(DMUS_PMSG)  + sizeof(DMUS_PMSGItem));
  if (NULL == pItem) {
    return E_OUTOFMEMORY;
  }
  pItem->pMsg.dwSize = cb;
415
  *ppPMSG = DMUS_ItemToPMSG(pItem);
416
  return S_OK;
417 418
}

Mike McCormack's avatar
Mike McCormack committed
419
static HRESULT WINAPI IDirectMusicPerformance8Impl_FreePMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pPMSG) {
420
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
421 422 423 424 425 426 427
  DMUS_PMSGItem* pItem = NULL;
  
  FIXME("(%p, %p): stub\n", This, pPMSG);
  
  if (NULL == pPMSG) {
    return E_POINTER;
  }
428
  pItem = DMUS_PMSGToItem(pPMSG);
429 430 431
  if (NULL == pItem) {
    return E_POINTER;
  }
432
  if (pItem->bInUse) {
433
    /** prevent for freeing PMsg in queue (ie to be processed) */
434
    return DMUS_E_CANNOT_FREE;
435 436
  }
  /** now we can remove it safely */
437
  EnterCriticalSection(&This->safe);
438
  DMUS_ItemRemoveFromQueue( This, pItem );
439 440
  LeaveCriticalSection(&This->safe);

441
  /** TODO: see if we should Release the pItem->pMsg->punkUser and others Interfaces */
442 443
  HeapFree(GetProcessHeap(), 0, pItem);  
  return S_OK;
444 445
}

446
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGraph (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicGraph** ppGraph) {
447
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
448 449
  FIXME("(%p, %p): to check\n", This, ppGraph);
  if (NULL != This->pToolGraph) {
450 451
    *ppGraph = This->pToolGraph;
    IDirectMusicGraph_AddRef(*ppGraph);
452 453
  } else {
    return E_FAIL;
454 455
  }
  return S_OK;
456 457
}

458
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGraph (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicGraph* pGraph) {
459
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
460 461 462 463 464
  
  FIXME("(%p, %p): to check\n", This, pGraph);
  
  if (NULL != This->pToolGraph) {
    /* Todo clean buffers and tools before */
465
    IDirectMusicGraph_Release(This->pToolGraph);
466 467 468
  }
  This->pToolGraph = pGraph;
  if (NULL != This->pToolGraph) {
469
    IDirectMusicGraph_AddRef(This->pToolGraph);
470 471
  }
  return S_OK;
472 473
}

Mike McCormack's avatar
Mike McCormack committed
474
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetNotificationHandle (LPDIRECTMUSICPERFORMANCE8 iface, HANDLE hNotification, REFERENCE_TIME rtMinimum) {
475
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
476
  FIXME("(%p, %p, 0x%s): stub\n", This, hNotification, wine_dbgstr_longlong(rtMinimum));
477 478 479
  This->hNotification = hNotification;
  if (rtMinimum) This->rtMinimum = rtMinimum;
  return S_OK;
480 481
}

Mike McCormack's avatar
Mike McCormack committed
482
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetNotificationPMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_NOTIFICATION_PMSG** ppNotificationPMsg) {
483
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
484 485
  
  
486 487 488 489
  FIXME("(%p, %p): stub\n", This, ppNotificationPMsg);
  if (NULL == ppNotificationPMsg) {
    return E_POINTER;
  }
490 491 492
  
  

493 494
  return S_FALSE;
  /*return S_OK;*/
495 496
}

Mike McCormack's avatar
Mike McCormack committed
497
static HRESULT WINAPI IDirectMusicPerformance8Impl_AddNotificationType (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidNotificationType) {
498
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
499
	FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
Rok Mandeljc's avatar
Rok Mandeljc committed
500
	return S_OK;
501 502
}

Mike McCormack's avatar
Mike McCormack committed
503
static HRESULT WINAPI IDirectMusicPerformance8Impl_RemoveNotificationType (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidNotificationType) {
504
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
505
	FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
Rok Mandeljc's avatar
Rok Mandeljc committed
506
	return S_OK;
507 508
}

Mike McCormack's avatar
Mike McCormack committed
509
static HRESULT WINAPI IDirectMusicPerformance8Impl_AddPort (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicPort* pPort) {
510
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
511
	HRESULT hr = E_FAIL;
Rok Mandeljc's avatar
Rok Mandeljc committed
512
	FIXME("(%p, %p): stub\n", This, pPort);
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
	if (!This->pDirectMusic || !This->pDirectSound) return DMUS_E_NOT_INIT;
	if (NULL == pPort) {
	  GUID port_guid;
	  IDirectMusicPort* pDefaultPort = NULL;
	  DMUS_PORTPARAMS params;
	  int i, j;
	  hr = IDirectMusic8_GetDefaultPort(This->pDirectMusic, &port_guid);
	  if (FAILED(hr)) return hr;
	  ZeroMemory(&params, sizeof(params)); 
	  params.dwSize = sizeof(params);
	  params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS | DMUS_PORTPARAMS_SHARE;
	  params.dwChannelGroups = 1;
	  params.fShare = TRUE;
	  hr = IDirectMusic8_CreatePort(This->pDirectMusic, &port_guid, &params, &pDefaultPort, NULL);
	  if (FAILED(hr)) return hr;
	  hr = IDirectMusicPort_Activate(pDefaultPort, TRUE);
	  if (FAILED(hr)) { IDirectMusicPort_Release(pDefaultPort); return hr; }
	  j = 0;
	  for (i = 0; i < 16; ++i) {
	    if (NULL == This->PChannel[i].port) {
	      This->PChannel[i].port = pPort; 
	      This->PChannel[i].group = 0; 
	      This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
	      j++;
	    }
	  }
	} else {
	  IDirectMusicPort_AddRef(pPort);	  
	}
	/**
	 * We should remember added Ports (for example using a list)
	 * and control if Port is registered for each api who use ports
	 */
Rok Mandeljc's avatar
Rok Mandeljc committed
546
	return S_OK;
547 548
}

Mike McCormack's avatar
Mike McCormack committed
549
static HRESULT WINAPI IDirectMusicPerformance8Impl_RemovePort (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicPort* pPort) {
550
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
551
	FIXME("(%p, %p): stub\n", This, pPort);
552
	IDirectMusicPort_Release (pPort);
Rok Mandeljc's avatar
Rok Mandeljc committed
553
	return S_OK;
554 555
}

Mike McCormack's avatar
Mike McCormack committed
556
static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannelBlock (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwBlockNum, IDirectMusicPort* pPort, DWORD dwGroup) {
557
	int i, j, range /* min value in range */;
558
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
559

560
	FIXME("(%p, %d, %p, %d): semi-stub\n", This, dwBlockNum, pPort, dwGroup-1);
561 562
	if (NULL == pPort) return E_POINTER;

563 564 565 566 567 568 569 570 571
	range = 16 * dwBlockNum;
	j = 0;
	for (i = range; i < range+16; i++) {
		/*TRACE("Setting PChannel[%i] to port %p, group %ld, MIDI port %i\n", i, pPort, dwGroup-1, j); */
		This->PChannel[i].port = pPort; 
		This->PChannel[i].group = dwGroup - 1; /* first index is always zero */
		This->PChannel[i].channel = j; /* FIXME: should this be assigned? */
		j++;
	}
572
	/*if (dwGroup > 2) return S_FALSE;*/
573 574

	return S_OK;
575 576
}

Mike McCormack's avatar
Mike McCormack committed
577
static HRESULT WINAPI IDirectMusicPerformance8Impl_AssignPChannel (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwPChannel, IDirectMusicPort* pPort, DWORD dwGroup, DWORD dwMChannel) {
578
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
579

580
	TRACE("(%p, %d, %p, %d, %d)\n", This, dwPChannel, pPort, dwGroup, dwMChannel);
581
	if (NULL == pPort) return E_POINTER;
582 583 584
	This->PChannel[dwPChannel].port = pPort; 
	This->PChannel[dwPChannel].group = dwGroup; 
	This->PChannel[dwPChannel].channel = dwMChannel;
Rok Mandeljc's avatar
Rok Mandeljc committed
585 586

	return S_OK;
587 588
}

Mike McCormack's avatar
Mike McCormack committed
589
static HRESULT WINAPI IDirectMusicPerformance8Impl_PChannelInfo (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwPChannel, IDirectMusicPort** ppPort, DWORD* pdwGroup, DWORD* pdwMChannel) {
590
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
591
	FIXME("(%p, %d, %p, %p, %p): stub\n", This, dwPChannel, ppPort, pdwGroup, pdwMChannel);
Rok Mandeljc's avatar
Rok Mandeljc committed
592
	return S_OK;
593 594
}

Mike McCormack's avatar
Mike McCormack committed
595
static HRESULT WINAPI IDirectMusicPerformance8Impl_DownloadInstrument (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicInstrument* pInst, DWORD dwPChannel, IDirectMusicDownloadedInstrument** ppDownInst, DMUS_NOTERANGE* pNoteRanges, DWORD dwNumNoteRanges, IDirectMusicPort** ppPort, DWORD* pdwGroup, DWORD* pdwMChannel) {
596
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
597
	FIXME("(%p, %p, %d, %p, %p, %d, %p, %p, %p): stub\n", This, pInst, dwPChannel, ppDownInst, pNoteRanges, dwNumNoteRanges, ppPort, pdwGroup, pdwMChannel);
Rok Mandeljc's avatar
Rok Mandeljc committed
598
	return S_OK;
599 600
}

Mike McCormack's avatar
Mike McCormack committed
601
static HRESULT WINAPI IDirectMusicPerformance8Impl_Invalidate (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, DWORD dwFlags) {
602
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
603
	FIXME("(%p, %d, %d): stub\n", This, mtTime, dwFlags);
Rok Mandeljc's avatar
Rok Mandeljc committed
604
	return S_OK;
605 606
}

Mike McCormack's avatar
Mike McCormack committed
607
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
608
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
609
	FIXME("(%p, %s, %d, %d, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
Rok Mandeljc's avatar
Rok Mandeljc committed
610
	return S_OK;
611 612
}

Mike McCormack's avatar
Mike McCormack committed
613
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void* pParam) {
614
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
615
	FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
Rok Mandeljc's avatar
Rok Mandeljc committed
616
	return S_OK;
617 618
}

Mike McCormack's avatar
Mike McCormack committed
619
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetGlobalParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, void* pParam, DWORD dwSize) {
620
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
621

622
	TRACE("(%p, %s, %p, %d): stub\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
623
	
624
	if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload))
625
		memcpy(pParam, &This->fAutoDownload, sizeof(This->fAutoDownload));
626
	if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel))
627
		memcpy(pParam, &This->cMasterGrooveLevel, sizeof(This->cMasterGrooveLevel));
628
	if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo))
629
		memcpy(pParam, &This->fMasterTempo, sizeof(This->fMasterTempo));
630
	if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume))
631
		memcpy(pParam, &This->lMasterVolume, sizeof(This->lMasterVolume));
Rok Mandeljc's avatar
Rok Mandeljc committed
632 633

	return S_OK;
634 635
}

Mike McCormack's avatar
Mike McCormack committed
636
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetGlobalParam (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, void* pParam, DWORD dwSize) {
637
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
638

639
	TRACE("(%p, %s, %p, %d)\n", This, debugstr_dmguid(rguidType), pParam, dwSize);
640
	
641
	if (IsEqualGUID (rguidType, &GUID_PerfAutoDownload)) {
642 643
		memcpy(&This->fAutoDownload, pParam, dwSize);
		TRACE("=> AutoDownload set to %d\n", This->fAutoDownload);
644
	}
645
	if (IsEqualGUID (rguidType, &GUID_PerfMasterGrooveLevel)) {
646 647
		memcpy(&This->cMasterGrooveLevel, pParam, dwSize);
		TRACE("=> MasterGrooveLevel set to %i\n", This->cMasterGrooveLevel);
648
	}
649
	if (IsEqualGUID (rguidType, &GUID_PerfMasterTempo)) {
650 651
		memcpy(&This->fMasterTempo, pParam, dwSize);
		TRACE("=> MasterTempo set to %f\n", This->fMasterTempo);
652
	}
653
	if (IsEqualGUID (rguidType, &GUID_PerfMasterVolume)) {
654 655
		memcpy(&This->lMasterVolume, pParam, dwSize);
		TRACE("=> MasterVolume set to %li\n", This->lMasterVolume);
656
	}
Rok Mandeljc's avatar
Rok Mandeljc committed
657 658

	return S_OK;
659 660
}

Mike McCormack's avatar
Mike McCormack committed
661
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetLatencyTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
662
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
663 664
	TRACE("(%p, %p): stub\n", This, prtTime);
	*prtTime = This->rtLatencyTime;
Rok Mandeljc's avatar
Rok Mandeljc committed
665
	return S_OK;
666 667
}

Mike McCormack's avatar
Mike McCormack committed
668
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetQueueTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME* prtTime) {
669
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
670 671
	FIXME("(%p, %p): stub\n", This, prtTime);
	return S_OK;
672 673
}

Mike McCormack's avatar
Mike McCormack committed
674
static HRESULT WINAPI IDirectMusicPerformance8Impl_AdjustTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtAmount) {
675
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
676
	FIXME("(%p, 0x%s): stub\n", This, wine_dbgstr_longlong(rtAmount));
Rok Mandeljc's avatar
Rok Mandeljc committed
677
	return S_OK;
678 679
}

Mike McCormack's avatar
Mike McCormack committed
680
static HRESULT WINAPI IDirectMusicPerformance8Impl_CloseDown (LPDIRECTMUSICPERFORMANCE8 iface) {
681
  IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
682 683 684 685 686 687 688
  FIXME("(%p): stub\n", This);
  if (PostMessageToProcessMsgThread(This, PROCESSMSG_EXIT)) {
    WaitForSingleObject(This->procThread, INFINITE);
    This->procThreadTicStarted = FALSE;
    CloseHandle(This->procThread);
  }
  if (NULL != This->pDirectSound) {
689
    IDirectSound_Release(This->pDirectSound);
690 691 692
    This->pDirectSound = NULL;
  }
  if (NULL != This->pDirectMusic) {
693
    IDirectMusic8_Release(This->pDirectMusic);
694 695 696
    This->pDirectMusic = NULL;
  }
  return S_OK;
697 698
}

Mike McCormack's avatar
Mike McCormack committed
699
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetResolvedTime (LPDIRECTMUSICPERFORMANCE8 iface, REFERENCE_TIME rtTime, REFERENCE_TIME* prtResolved, DWORD dwTimeResolveFlags) {
700
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
701
	FIXME("(%p, 0x%s, %p, %d): stub\n", This, wine_dbgstr_longlong(rtTime),
702
	    prtResolved, dwTimeResolveFlags);
Rok Mandeljc's avatar
Rok Mandeljc committed
703
	return S_OK;
704 705
}

Mike McCormack's avatar
Mike McCormack committed
706
static HRESULT WINAPI IDirectMusicPerformance8Impl_MIDIToMusic (LPDIRECTMUSICPERFORMANCE8 iface, BYTE bMIDIValue, DMUS_CHORD_KEY* pChord, BYTE bPlayMode, BYTE bChordLevel, WORD* pwMusicValue) {
707
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
708 709
	FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, bMIDIValue, pChord, bPlayMode, bChordLevel, pwMusicValue);
	return S_OK;
710 711
}

Mike McCormack's avatar
Mike McCormack committed
712
static HRESULT WINAPI IDirectMusicPerformance8Impl_MusicToMIDI (LPDIRECTMUSICPERFORMANCE8 iface, WORD wMusicValue, DMUS_CHORD_KEY* pChord, BYTE bPlayMode, BYTE bChordLevel, BYTE* pbMIDIValue) {
713
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
714 715
	FIXME("(%p, %d, %p, %d, %d, %p): stub\n", This, wMusicValue, pChord, bPlayMode, bChordLevel, pbMIDIValue);
	return S_OK;
716 717
}

Mike McCormack's avatar
Mike McCormack committed
718
static HRESULT WINAPI IDirectMusicPerformance8Impl_TimeToRhythm (LPDIRECTMUSICPERFORMANCE8 iface, MUSIC_TIME mtTime, DMUS_TIMESIGNATURE* pTimeSig, WORD* pwMeasure, BYTE* pbBeat, BYTE* pbGrid, short* pnOffset) {
719
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
720
	FIXME("(%p, %d, %p, %p, %p, %p, %p): stub\n", This, mtTime, pTimeSig, pwMeasure, pbBeat, pbGrid, pnOffset);
Rok Mandeljc's avatar
Rok Mandeljc committed
721
	return S_OK;
722 723
}

Mike McCormack's avatar
Mike McCormack committed
724
static HRESULT WINAPI IDirectMusicPerformance8Impl_RhythmToTime (LPDIRECTMUSICPERFORMANCE8 iface, WORD wMeasure, BYTE bBeat, BYTE bGrid, short nOffset, DMUS_TIMESIGNATURE* pTimeSig, MUSIC_TIME* pmtTime) {
725
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
726 727
	FIXME("(%p, %d, %d, %d, %i, %p, %p): stub\n", This, wMeasure, bBeat, bGrid, nOffset, pTimeSig, pmtTime);
	return S_OK;
728 729 730
}

/* IDirectMusicPerformance8 Interface part follow: */
Mike McCormack's avatar
Mike McCormack committed
731
static HRESULT WINAPI IDirectMusicPerformance8Impl_InitAudio (LPDIRECTMUSICPERFORMANCE8 iface, 
732 733 734 735 736 737
						      IDirectMusic** ppDirectMusic, 
						      IDirectSound** ppDirectSound, 
						      HWND hWnd, 
						      DWORD dwDefaultPathType, 
						      DWORD dwPChannelCount, 
						      DWORD dwFlags, 
738
						      DMUS_AUDIOPARAMS* pParams) {
739 740

	IDirectSound* dsound = NULL;
741
	HRESULT hr = S_OK;
742
	
743
        IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
744
	FIXME("(%p, %p, %p, %p, %x, %u, %x, %p): to check\n", This, ppDirectMusic, ppDirectSound, hWnd, dwDefaultPathType, dwPChannelCount, dwFlags, pParams);
745

746
	if (This->pDirectMusic || This->pDirectSound)
747 748
	  return DMUS_E_ALREADY_INITED;

749
	if (NULL != ppDirectSound && NULL != *ppDirectSound) {
750
	  dsound = *ppDirectSound;
751
	} else {
752
	  hr = DirectSoundCreate8 (NULL, (LPDIRECTSOUND8*) &dsound, NULL);
753
          FIXME("return dsound(%p,%d)\n", dsound, hr);
754
	  if (FAILED(hr) || !dsound)
755
	    return DSERR_NODRIVER;
756
	  if (ppDirectSound)
757
	    *ppDirectSound = dsound;  
758
	}
759
	
760
	IDirectMusicPerformance8Impl_Init(iface, ppDirectMusic, dsound, hWnd);
761

Austin English's avatar
Austin English committed
762
	/* Init increases the ref count of the dsound object. Decrement it if the app doesn't want a pointer to the object. */
763
	if (NULL == ppDirectSound) {
764
	  IDirectSound_Release(This->pDirectSound);
765 766
	}

767 768
	/* as seen in msdn we need params init before audio path creation */
	if (NULL != pParams) {
769
	  This->pParams = *pParams;
770
	} else {
771
	  /* TODO, how can i fill the struct as seen on msdn */
772
	  memset(&This->pParams, 0, sizeof(DMUS_AUDIOPARAMS));
773 774 775 776 777 778 779
	  This->pParams.dwSize = sizeof(DMUS_AUDIOPARAMS);
	  This->pParams.fInitNow = FALSE;
	  This->pParams.dwValidData = DMUS_AUDIOPARAMS_FEATURES | DMUS_AUDIOPARAMS_VOICES | DMUS_AUDIOPARAMS_SAMPLERATE | DMUS_AUDIOPARAMS_DEFAULTSYNTH;
	  This->pParams.dwVoices = 64;
	  This->pParams.dwSampleRate = (DWORD) 22.050; 
	  This->pParams.dwFeatures = dwFlags;
	  This->pParams.clsidDefaultSynth = CLSID_DirectMusicSynthSink;
780
	}
781
	hr = IDirectMusicPerformance8_CreateStandardAudioPath(iface, dwDefaultPathType, dwPChannelCount, FALSE, &This->pDefaultPath);
Rok Mandeljc's avatar
Rok Mandeljc committed
782

783 784
	PostMessageToProcessMsgThread(This, PROCESSMSG_START);

785
	return hr;
786 787
}

Mike McCormack's avatar
Mike McCormack committed
788
static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegmentEx (LPDIRECTMUSICPERFORMANCE8 iface, IUnknown* pSource, WCHAR* pwzSegmentName, IUnknown* pTransition, DWORD dwFlags, __int64 i64StartTime, IDirectMusicSegmentState** ppSegmentState, IUnknown* pFrom, IUnknown* pAudioPath) {
789
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
790
	FIXME("(%p, %p, %p, %p, %d, 0x%s, %p, %p, %p): stub\n", This, pSource, pwzSegmentName,
791
	    pTransition, dwFlags, wine_dbgstr_longlong(i64StartTime), ppSegmentState, pFrom, pAudioPath);
792 793 794
	if (ppSegmentState)
	  return DMUSIC_CreateDirectMusicSegmentStateImpl(&IID_IDirectMusicSegmentState, (LPVOID*)ppSegmentState, NULL);
	return S_OK;
795 796
}

Mike McCormack's avatar
Mike McCormack committed
797
static HRESULT WINAPI IDirectMusicPerformance8Impl_StopEx (LPDIRECTMUSICPERFORMANCE8 iface, IUnknown* pObjectToStop, __int64 i64StopTime, DWORD dwFlags) {
798
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
799
	FIXME("(%p, %p, 0x%s, %d): stub\n", This, pObjectToStop,
800
	    wine_dbgstr_longlong(i64StopTime), dwFlags);
Rok Mandeljc's avatar
Rok Mandeljc committed
801
	return S_OK;
802 803
}

Mike McCormack's avatar
Mike McCormack committed
804
static HRESULT WINAPI IDirectMusicPerformance8Impl_ClonePMsg (LPDIRECTMUSICPERFORMANCE8 iface, DMUS_PMSG* pSourcePMSG, DMUS_PMSG** ppCopyPMSG) {
805
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
806 807
	FIXME("(%p, %p, %p): stub\n", This, pSourcePMSG, ppCopyPMSG);
	return S_OK;
808 809
}

Mike McCormack's avatar
Mike McCormack committed
810
static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, IUnknown* pSourceConfig, BOOL fActivate, IDirectMusicAudioPath** ppNewPath) {
811 812 813
	IDirectMusicAudioPathImpl *default_path;
	IDirectMusicAudioPath *pPath;

814
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
815
	FIXME("(%p, %p, %d, %p): stub\n", This, pSourceConfig, fActivate, ppNewPath);
816 817 818 819 820 821 822 823 824 825 826

	if (NULL == ppNewPath) {
	  return E_POINTER;
	}

	DMUSIC_CreateDirectMusicAudioPathImpl (&IID_IDirectMusicAudioPath, (LPVOID*)&pPath, NULL);
	default_path = (IDirectMusicAudioPathImpl*)((char*)(pPath) - offsetof(IDirectMusicAudioPathImpl,AudioPathVtbl));
	default_path->pPerf = (IDirectMusicPerformance8*) This;

	/** TODO */
	
827
	*ppNewPath = pPath;
828

829
	return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate);
830 831
}

832
static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateStandardAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwType, DWORD dwPChannelCount, BOOL fActivate, IDirectMusicAudioPath** ppNewPath) {
833
	IDirectMusicAudioPathImpl *default_path;
834
	IDirectMusicAudioPath *pPath;
835 836
	DSBUFFERDESC desc;
	WAVEFORMATEX format;
Alexandre Julliard's avatar
Alexandre Julliard committed
837
	LPDIRECTSOUNDBUFFER buffer;
838
	HRESULT hr = S_OK;
Rok Mandeljc's avatar
Rok Mandeljc committed
839

840
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
841
	
842
	FIXME("(%p)->(%d, %d, %d, %p): semi-stub\n", This, dwType, dwPChannelCount, fActivate, ppNewPath);
Rok Mandeljc's avatar
Rok Mandeljc committed
843

844 845 846
	if (NULL == ppNewPath) {
	  return E_POINTER;
	}
847
	
848 849
	DMUSIC_CreateDirectMusicAudioPathImpl (&IID_IDirectMusicAudioPath, (LPVOID*)&pPath, NULL);
	default_path = (IDirectMusicAudioPathImpl*)((char*)(pPath) - offsetof(IDirectMusicAudioPathImpl,AudioPathVtbl));
850
	default_path->pPerf = (IDirectMusicPerformance8*) This;
851
	
852
	/* Secondary buffer description */
853
	memset(&format, 0, sizeof(format));
854 855 856 857 858 859 860 861
	format.wFormatTag = WAVE_FORMAT_PCM;
	format.nChannels = 1;
	format.nSamplesPerSec = 44000;
	format.nAvgBytesPerSec = 44000*2;
	format.nBlockAlign = 2;
	format.wBitsPerSample = 16;
	format.cbSize = 0;
	
862
	memset(&desc, 0, sizeof(desc));
863
	desc.dwSize = sizeof(desc);
864
	desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS;
865 866 867 868 869 870
	desc.dwBufferBytes = DSBSIZE_MIN;
	desc.dwReserved = 0;
	desc.lpwfxFormat = &format;
	desc.guid3DAlgorithm = GUID_NULL;
	
	switch(dwType) {
871
	case DMUS_APATH_DYNAMIC_3D:
872
                desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE;
873
		break;
874
	case DMUS_APATH_DYNAMIC_MONO:
875
	        desc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
876
		break;
877
	case DMUS_APATH_SHARED_STEREOPLUSREVERB:
Austin English's avatar
Austin English committed
878
	        /* normally we have to create 2 buffers (one for music other for reverb)
879 880
		 * in this case. See msdn
                 */
881
	case DMUS_APATH_DYNAMIC_STEREO:
882
		desc.dwFlags |= DSBCAPS_CTRLFREQUENCY;
883 884 885 886
		format.nChannels = 2;
		format.nBlockAlign *= 2;
		format.nAvgBytesPerSec *=2;
		break;
887
	default:
888 889 890
	        HeapFree(GetProcessHeap(), 0, default_path); 
	        *ppNewPath = NULL;
	        return E_INVALIDARG;
891
	}
892

893
	/* FIXME: Should we create one secondary buffer for each PChannel? */
894 895 896 897 898 899
	hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL);
	if (FAILED(hr)) {
	        HeapFree(GetProcessHeap(), 0, default_path); 
	        *ppNewPath = NULL;
	        return DSERR_BUFFERLOST;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
900
	default_path->pDSBuffer = buffer;
901

902 903 904 905 906
	/* Update description for creating primary buffer */
	desc.dwFlags |= DSBCAPS_PRIMARYBUFFER;
	desc.dwBufferBytes = 0;
	desc.lpwfxFormat = NULL;

907 908 909 910 911 912 913
	hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL);
	if (FAILED(hr)) {
                IDirectSoundBuffer_Release(default_path->pDSBuffer);
	        HeapFree(GetProcessHeap(), 0, default_path); 
	        *ppNewPath = NULL;
	        return DSERR_BUFFERLOST;
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
914
	default_path->pPrimary = buffer;
915

916
	*ppNewPath = pPath;
917 918
	
	TRACE(" returning IDirectMusicPerformance interface at %p.\n", *ppNewPath);
919

920
	return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate);
921 922
}

Mike McCormack's avatar
Mike McCormack committed
923
static HRESULT WINAPI IDirectMusicPerformance8Impl_SetDefaultAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicAudioPath* pAudioPath) {
924
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
925

926 927
	FIXME("(%p, %p): semi-stub\n", This, pAudioPath);
	if (NULL != This->pDefaultPath) {
928
		IDirectMusicAudioPath_Release(This->pDefaultPath);
929 930 931 932 933
		((IDirectMusicAudioPathImpl*) This->pDefaultPath)->pPerf = NULL;
		This->pDefaultPath = NULL;
	}
	This->pDefaultPath = pAudioPath;
	if (NULL != This->pDefaultPath) {
934
		IDirectMusicAudioPath_AddRef(This->pDefaultPath);
935
		((IDirectMusicAudioPathImpl*) This->pDefaultPath)->pPerf = (IDirectMusicPerformance8*) This;	
936 937 938
	}
	
	return S_OK;
939 940
}

Mike McCormack's avatar
Mike McCormack committed
941
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetDefaultAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, IDirectMusicAudioPath** ppAudioPath) {
942
    IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
943

944
	FIXME("(%p, %p): semi-stub (%p)\n", This, ppAudioPath, This->pDefaultPath);
Rok Mandeljc's avatar
Rok Mandeljc committed
945

946
	if (NULL != This->pDefaultPath) {
947
	  *ppAudioPath = This->pDefaultPath;
948
          IDirectMusicAudioPath_AddRef(*ppAudioPath);
949 950 951
        } else {
	  *ppAudioPath = NULL;
        }
952
	return S_OK;
953 954
}

Mike McCormack's avatar
Mike McCormack committed
955
static HRESULT WINAPI IDirectMusicPerformance8Impl_GetParamEx (LPDIRECTMUSICPERFORMANCE8 iface, REFGUID rguidType, DWORD dwTrackID, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
956
	IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface;
Rok Mandeljc's avatar
Rok Mandeljc committed
957

958
	FIXME("(%p, %s, %d, %d, %d, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), dwTrackID, dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
Rok Mandeljc's avatar
Rok Mandeljc committed
959 960

	return S_OK;
961 962
}

963
static const IDirectMusicPerformance8Vtbl DirectMusicPerformance8_Vtbl = {
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
	IDirectMusicPerformance8Impl_QueryInterface,
	IDirectMusicPerformance8Impl_AddRef,
	IDirectMusicPerformance8Impl_Release,
	IDirectMusicPerformance8Impl_Init,
	IDirectMusicPerformance8Impl_PlaySegment,
	IDirectMusicPerformance8Impl_Stop,
	IDirectMusicPerformance8Impl_GetSegmentState,
	IDirectMusicPerformance8Impl_SetPrepareTime,
	IDirectMusicPerformance8Impl_GetPrepareTime,
	IDirectMusicPerformance8Impl_SetBumperLength,
	IDirectMusicPerformance8Impl_GetBumperLength,
	IDirectMusicPerformance8Impl_SendPMsg,
	IDirectMusicPerformance8Impl_MusicToReferenceTime,
	IDirectMusicPerformance8Impl_ReferenceToMusicTime,
	IDirectMusicPerformance8Impl_IsPlaying,
	IDirectMusicPerformance8Impl_GetTime,
	IDirectMusicPerformance8Impl_AllocPMsg,
	IDirectMusicPerformance8Impl_FreePMsg,
	IDirectMusicPerformance8Impl_GetGraph,
	IDirectMusicPerformance8Impl_SetGraph,
	IDirectMusicPerformance8Impl_SetNotificationHandle,
	IDirectMusicPerformance8Impl_GetNotificationPMsg,
	IDirectMusicPerformance8Impl_AddNotificationType,
	IDirectMusicPerformance8Impl_RemoveNotificationType,
	IDirectMusicPerformance8Impl_AddPort,
	IDirectMusicPerformance8Impl_RemovePort,
	IDirectMusicPerformance8Impl_AssignPChannelBlock,
	IDirectMusicPerformance8Impl_AssignPChannel,
	IDirectMusicPerformance8Impl_PChannelInfo,
	IDirectMusicPerformance8Impl_DownloadInstrument,
	IDirectMusicPerformance8Impl_Invalidate,
	IDirectMusicPerformance8Impl_GetParam,
	IDirectMusicPerformance8Impl_SetParam,
	IDirectMusicPerformance8Impl_GetGlobalParam,
	IDirectMusicPerformance8Impl_SetGlobalParam,
	IDirectMusicPerformance8Impl_GetLatencyTime,
	IDirectMusicPerformance8Impl_GetQueueTime,
	IDirectMusicPerformance8Impl_AdjustTime,
	IDirectMusicPerformance8Impl_CloseDown,
	IDirectMusicPerformance8Impl_GetResolvedTime,
	IDirectMusicPerformance8Impl_MIDIToMusic,
	IDirectMusicPerformance8Impl_MusicToMIDI,
	IDirectMusicPerformance8Impl_TimeToRhythm,
	IDirectMusicPerformance8Impl_RhythmToTime,
1008 1009 1010 1011 1012 1013 1014 1015 1016
	IDirectMusicPerformance8Impl_InitAudio,
	IDirectMusicPerformance8Impl_PlaySegmentEx,
	IDirectMusicPerformance8Impl_StopEx,
	IDirectMusicPerformance8Impl_ClonePMsg,
	IDirectMusicPerformance8Impl_CreateAudioPath,
	IDirectMusicPerformance8Impl_CreateStandardAudioPath,
	IDirectMusicPerformance8Impl_SetDefaultAudioPath,
	IDirectMusicPerformance8Impl_GetDefaultAudioPath,
	IDirectMusicPerformance8Impl_GetParamEx
1017
};
1018 1019

/* for ClassFactory */
1020 1021 1022 1023 1024 1025 1026
HRESULT WINAPI DMUSIC_CreateDirectMusicPerformanceImpl (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
	IDirectMusicPerformance8Impl *obj;

	TRACE("(%p,%p,%p)\n", lpcGUID, ppobj, pUnkOuter);

	obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicPerformance8Impl));
	if (NULL == obj) 	{
1027
		*ppobj = NULL;
1028
		return E_OUTOFMEMORY;
1029
	}
1030
	obj->lpVtbl = &DirectMusicPerformance8_Vtbl;
1031
	obj->ref = 0;  /* will be inited by QueryInterface */
1032 1033 1034
	obj->pDirectMusic = NULL;
	obj->pDirectSound = NULL;
	obj->pDefaultPath = NULL;
1035
	InitializeCriticalSection(&obj->safe);
1036
	obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectMusicPerformance8Impl*->safe");
1037

1038
	obj->rtLatencyTime  = 100;  /* 100ms TO FIX */
1039 1040
	obj->dwBumperLength =   50; /* 50ms default */
	obj->dwPrepareTime  = 1000; /* 1000ms default */
1041
	return IDirectMusicPerformance8Impl_QueryInterface ((LPDIRECTMUSICPERFORMANCE8)obj, lpcGUID, ppobj);
1042
}