void CDAudio_Play(int track, qboolean looping) { // set a loop counter so that this track will change to the // looptrack later loopcounter = 0; CDAudio_Play2(track, looping); }
LONG CDAudio_MessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (lParam != wDeviceID) return 1; switch (wParam) { case MCI_NOTIFY_SUCCESSFUL: if (playing) { playing = false; if (playLooping) { // if the track has played the given number of times, // go to the ambient track if (++loopcounter >= cd_loopcount->value) CDAudio_Play2(cd_looptrack->value, true); else CDAudio_Play2(playTrack, true); } } break; case MCI_NOTIFY_ABORTED: case MCI_NOTIFY_SUPERSEDED: break; case MCI_NOTIFY_FAILURE: Com_DPrintf("MCI_NOTIFY_FAILURE\n"); CDAudio_Stop (); cdValid = false; break; default: Com_DPrintf("Unexpected MM_MCINOTIFY type (%i)\n", wParam); return 1; } return 0; }
static unsigned int __stdcall PlayingThreadProc(void *arglist) { struct ThreadArgList_t *tal = arglist; DSBPOSITIONNOTIFY notifies[BUFFER_PARTS]; HANDLE events[BUFFER_PARTS+1]; // +1 for StopEvent HANDLE endevents[2]; char *ptr; int i; DWORD dummy, fillpart; DWORD part_size; HRESULT hr; qboolean more_data; qboolean trackPlayedToEnd = false; CDAudio_WaitForFinish(); ResetEvent(cdPlayingFinishedEvent); ResetEvent(cdStopEvent); part_size = gCDBufSize / BUFFER_PARTS; for (i=0; i<BUFFER_PARTS; i++) { events[i] = CreateEvent(NULL, FALSE, FALSE, NULL); notifies[i].dwOffset = i * part_size; notifies[i].hEventNotify = events[i]; } events[i] = cdStopEvent; pDSBufCD->lpVtbl->GetStatus(pDSBufCD, &dummy); if (dummy & DSBSTATUS_BUFFERLOST) pDSBufCD->lpVtbl->Restore(pDSBufCD); pDSBufCDNotify->lpVtbl->SetNotificationPositions(pDSBufCDNotify, BUFFER_PARTS, notifies); if (FAILED(pDSBufCD->lpVtbl->Lock(pDSBufCD, 0, 0, &ptr, &dummy, NULL, NULL, DSBLOCK_ENTIREBUFFER))) { Com_DPrintf("CDAudio: cannot lock sound buffer.\n"); return -1; } if (!PaintSoundOGG(tal, ptr, (BUFFER_PARTS-1)*part_size)) SetEvent(cdStopEvent); pDSBufCD->lpVtbl->Unlock(pDSBufCD, ptr, dummy, NULL, 0); pDSBufCD->lpVtbl->SetCurrentPosition(pDSBufCD, 0); pDSBufCD->lpVtbl->Play(pDSBufCD, 0, 0, DSBPLAY_LOOPING); while(true) { fillpart = WaitForMultipleObjects(BUFFER_PARTS+1, events, FALSE, 2000); if (fillpart >= WAIT_OBJECT_0 && fillpart < WAIT_OBJECT_0 + BUFFER_PARTS) { fillpart = (fillpart - WAIT_OBJECT_0 + BUFFER_PARTS - 1) % BUFFER_PARTS; hr = pDSBufCD->lpVtbl->Lock(pDSBufCD, part_size * fillpart, part_size, &ptr, &dummy, NULL, NULL, 0); if (hr == DSERR_BUFFERLOST) { pDSBufCD->lpVtbl->Restore(pDSBufCD); pDSBufCD->lpVtbl->Lock(pDSBufCD, part_size * fillpart, part_size, &ptr, &dummy, NULL, NULL, 0); } more_data = PaintSoundOGG(tal, ptr, part_size); pDSBufCD->lpVtbl->Unlock(pDSBufCD, ptr, dummy, NULL, 0); if (!more_data) { endevents[0] = events[fillpart]; endevents[1] = cdStopEvent; if (WaitForMultipleObjects(2, endevents, FALSE, 2000) == WAIT_OBJECT_0) trackPlayedToEnd = true; break; } } else break; } pDSBufCD->lpVtbl->Stop(pDSBufCD); pDSBufCDNotify->lpVtbl->SetNotificationPositions(pDSBufCDNotify, 0, NULL); for (i=0; i<BUFFER_PARTS; i++) CloseHandle(events[i]); CloseOGG(tal); playing = false; free(arglist); SetEvent(cdPlayingFinishedEvent); if (trackPlayedToEnd && playLooping) { // if the track has played the given number of times, // go to the ambient track if (++loopcounter >= cd_loopcount->value) CDAudio_Play2(cd_looptrack->value, true); else CDAudio_Play2(playTrack, true); } return 0; }