📄 audio.c
字号:
TRACE("still playing\n"); return WAVERR_STILLPLAYING; } lpWaveHdr->dwFlags &= ~WHDR_DONE; lpWaveHdr->dwFlags |= WHDR_INQUEUE; lpWaveHdr->lpNext = 0; EnterCriticalSection(&wwo->access_crst); /* insert buffer at the end of queue */ for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext)); *wh = lpWaveHdr; LeaveCriticalSection(&wwo->access_crst); EnterCriticalSection(&wwo->access_crst); if (!wwo->lpPlayPtr) wodHelper_BeginWaveHdr(wwo,lpWaveHdr); if (wwo->state == WINE_WS_STOPPED) wwo->state = WINE_WS_PLAYING; LeaveCriticalSection(&wwo->access_crst); return MMSYSERR_NOERROR;}/************************************************************************** * wodPrepare [internal] */static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize){ TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize); if (wDevID >= MAX_WAVEOUTDRV) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING; lpWaveHdr->dwFlags |= WHDR_PREPARED; lpWaveHdr->dwFlags &= ~WHDR_DONE; return MMSYSERR_NOERROR;}/************************************************************************** * wodUnprepare [internal] */static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize){ TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize); if (wDevID >= MAX_WAVEOUTDRV) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING; lpWaveHdr->dwFlags &= ~WHDR_PREPARED; lpWaveHdr->dwFlags |= WHDR_DONE; return MMSYSERR_NOERROR;}/************************************************************************** * wodPause [internal] */static DWORD wodPause(WORD wDevID){ TRACE("(%u);!\n", wDevID); if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } TRACE("[3-PAUSING]\n"); EnterCriticalSection(&(WOutDev[wDevID].access_crst)); wodHelper_Reset(&WOutDev[wDevID], FALSE); LeaveCriticalSection(&(WOutDev[wDevID].access_crst)); return MMSYSERR_NOERROR;}/************************************************************************** * wodRestart [internal] */static DWORD wodRestart(WORD wDevID){ TRACE("(%u);\n", wDevID); if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } if (WOutDev[wDevID].state == WINE_WS_PAUSED) { EnterCriticalSection(&(WOutDev[wDevID].access_crst)); WOutDev[wDevID].state = WINE_WS_PLAYING; LeaveCriticalSection(&(WOutDev[wDevID].access_crst)); } return MMSYSERR_NOERROR;}/************************************************************************** * wodReset [internal] */static DWORD wodReset(WORD wDevID){ TRACE("(%u);\n", wDevID); if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } EnterCriticalSection(&(WOutDev[wDevID].access_crst)); wodHelper_Reset(&WOutDev[wDevID], TRUE); LeaveCriticalSection(&(WOutDev[wDevID].access_crst)); return MMSYSERR_NOERROR;}/************************************************************************** * wodGetPosition [internal] */static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize){ int time; DWORD val; WINE_WAVEOUT* wwo; DWORD elapsedMS; TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } /* if null pointer to time structure return error */ if (lpTime == NULL) return MMSYSERR_INVALPARAM; wwo = &WOutDev[wDevID]; EnterCriticalSection(&(WOutDev[wDevID].access_crst)); val = wwo->dwPlayedTotal; elapsedMS = GetTickCount() - wwo->tickCountMS; LeaveCriticalSection(&(WOutDev[wDevID].access_crst)); /* account for the bytes played since the last JACK_Callback() */ val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000); TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n", lpTime->wType, wwo->format.wBitsPerSample, wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels, wwo->format.wf.nAvgBytesPerSec); TRACE("dwPlayedTotal=%lu\n", val); switch (lpTime->wType) { case TIME_BYTES: lpTime->u.cb = val; TRACE("TIME_BYTES=%lu\n", lpTime->u.cb); break; case TIME_SAMPLES: lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels; TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample); break; case TIME_SMPTE: time = val / (wwo->format.wf.nAvgBytesPerSec / 1000); lpTime->u.smpte.hour = time / 108000; time -= lpTime->u.smpte.hour * 108000; lpTime->u.smpte.min = time / 1800; time -= lpTime->u.smpte.min * 1800; lpTime->u.smpte.sec = time / 30; time -= lpTime->u.smpte.sec * 30; lpTime->u.smpte.frame = time; lpTime->u.smpte.fps = 30; TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n", lpTime->u.smpte.hour, lpTime->u.smpte.min, lpTime->u.smpte.sec, lpTime->u.smpte.frame); break; default: FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType); lpTime->wType = TIME_MS; case TIME_MS: lpTime->u.ms = val / (wwo->format.wf.nAvgBytesPerSec / 1000); TRACE("TIME_MS=%lu\n", lpTime->u.ms); break; } return MMSYSERR_NOERROR;}/************************************************************************** * wodBreakLoop [internal] */static DWORD wodBreakLoop(WORD wDevID){ TRACE("(%u);\n", wDevID); if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client) { WARN("bad device ID !\n"); return MMSYSERR_BADDEVICEID; } EnterCriticalSection(&(WOutDev[wDevID].access_crst)); if (WOutDev[wDevID].state == WINE_WS_PLAYING && WOutDev[wDevID].lpLoopPtr != NULL) { /* ensure exit at end of current loop */ WOutDev[wDevID].dwLoops = 1; } LeaveCriticalSection(&(WOutDev[wDevID].access_crst)); return MMSYSERR_NOERROR;} /************************************************************************** * wodGetVolume [internal] */static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol){ DWORD left, right; left = WOutDev[wDevID].volume_left; right = WOutDev[wDevID].volume_right; TRACE("(%u, %p);\n", wDevID, lpdwVol); *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) << 16); return MMSYSERR_NOERROR;}/************************************************************************** * wodSetVolume [internal] */static DWORD wodSetVolume(WORD wDevID, DWORD dwParam){ DWORD left, right; left = (LOWORD(dwParam) * 100) / 0xFFFFl; right = (HIWORD(dwParam) * 100) / 0xFFFFl; TRACE("(%u, %08lX);\n", wDevID, dwParam); EnterCriticalSection(&(WOutDev[wDevID].access_crst)); WOutDev[wDevID].volume_left = left; WOutDev[wDevID].volume_right = right; LeaveCriticalSection(&(WOutDev[wDevID].access_crst)); return MMSYSERR_NOERROR;}/************************************************************************** * wodGetNumDevs [internal] */static DWORD wodGetNumDevs(void){ return MAX_WAVEOUTDRV;}/************************************************************************** * wodMessage (WINEJACK.7) */DWORD WINAPI JACK_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2){ TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); switch (wMsg) { case DRVM_INIT: TRACE("DRVM_INIT\n"); return JACK_WaveInit(); case DRVM_EXIT: TRACE("DRVM_EXIT\n"); return JACK_WaveRelease(); case DRVM_ENABLE: /* FIXME: Pretend this is supported */ TRACE("DRVM_ENABLE\n"); return 0; case DRVM_DISABLE: /* FIXME: Pretend this is supported */ TRACE("DRVM_DISABLE\n"); return 0; case WODM_OPEN: return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2); case WODM_CLOSE: return wodClose(wDevID); case WODM_WRITE: return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2); case WODM_PAUSE: return wodPause(wDevID); case WODM_GETPOS: return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2); case WODM_BREAKLOOP: return wodBreakLoop(wDevID); case WODM_PREPARE: return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2); case WODM_UNPREPARE: return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2); case WODM_GETDEVCAPS: return wodGetDevCaps(wDevID, (LPWAVEOUTCAPSA)dwParam1, dwParam2); case WODM_GETNUMDEVS: return wodGetNumDevs(); case WODM_GETPITCH: return MMSYSERR_NOTSUPPORTED; case WODM_SETPITCH: return MMSYSERR_NOTSUPPORTED; case WODM_GETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED; case WODM_SETPLAYBACKRATE: return MMSYSERR_NOTSUPPORTED; case WODM_GETVOLUME: return wodGetVolume(wDevID, (LPDWORD)dwParam1); case WODM_SETVOLUME: return wodSetVolume(wDevID, dwParam1); case WODM_RESTART: return wodRestart(wDevID); case WODM_RESET: return wodReset(wDevID); case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1); case DRV_QUERYDSOUNDDESC: return wodDsDesc(wDevID, (PDSDRIVERDESC)dwParam1); case DRV_QUERYDSOUNDGUID: return wodDsGuid(wDevID, (LPGUID)dwParam1); default: FIXME("unknown message %d!\n", wMsg); } return MMSYSERR_NOTSUPPORTED;}/*======================================================================* * Low level DSOUND implementation * *======================================================================*/typedef struct IDsDriverImpl IDsDriverImpl;typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;struct IDsDriverImpl{ /* IUnknown fields */ ICOM_VFIELD(IDsDriver); DWORD ref; /* IDsDriverImpl fields */ UINT wDevID; IDsDriverBufferImpl*primary;};struct IDsDriverBufferImpl{ /* IUnknown fields */ ICOM_VFIELD(IDsDriverBuffer); DWORD ref; /* IDsDriverBufferImpl fields */ IDsDriverImpl* drv; DWORD buflen;};static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv){ /* we can't perform memory mapping as we don't have a file stream interface with jack like we do with oss */ MESSAGE("This sound card's driver does not support direct access\n"); MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n"); return MMSYSERR_NOTSUPPORTED;}static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc){ memset(desc, 0, sizeof(*desc)); strcpy(desc->szDesc, "Wine jack DirectSound Driver"); strcpy(desc->szDrvName, "winejack.drv"); return MMSYSERR_NOERROR;}static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid){ memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID)); return MMSYSERR_NOERROR;}/*======================================================================* * Low level WAVE IN implementation * *======================================================================*//************************************************************************** * widMessage (WINEJACK.6) */DWORD WINAPI JACK_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2){ TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); return MMSYSERR_NOTSUPPORTED;}#else /* !HAVE_JACK_JACK_H *//************************************************************************** * wodMessage (WINEJACK.7) */DWORD WINAPI JACK_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2){ FIXME("(%u, %04X, %08lX, %08lX, %08lX):jack support not compiled into wine\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); return MMSYSERR_NOTENABLED;}#endif /* HAVE_JACK_JACK_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -