⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
 */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 || AuServ == NULL)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    TRACE("imhere[3-PAUSING]\n");    NAS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_PAUSING, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 			wodRestart				[internal] */static DWORD wodRestart(WORD wDevID){    TRACE("(%u);\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || AuServ == NULL)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (WOutDev[wDevID].state == WINE_WS_PAUSED) {	TRACE("imhere[3-RESTARTING]\n");	NAS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESTARTING, 0, TRUE);    }    /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */    /* FIXME: Myst crashes with this ... hmm -MM       return wodNotifyClient(wwo, WOM_DONE, 0L, 0L);    */    return MMSYSERR_NOERROR;}/************************************************************************** * 			wodReset				[internal] */static DWORD wodReset(WORD wDevID){    TRACE("(%u);\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || AuServ == NULL)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    TRACE("imhere[3-RESET]\n");    NAS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetPosition			[internal] */static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize){    int			time;    DWORD		val;    WINE_WAVEOUT*	wwo;    TRACE("%u, %p, %lu);\n", wDevID, lpTime, uSize);    if (wDevID >= MAX_WAVEOUTDRV || AuServ == NULL)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpTime == NULL)	return MMSYSERR_INVALPARAM;    wwo = &WOutDev[wDevID];#if 0    NAS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);#endif    val = wwo->WrittenTotal;    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("PlayedTotal=%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 || AuServ == NULL)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    NAS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);    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);    WOutDev[wDevID].volume_left = left;    WOutDev[wDevID].volume_right = right;    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetNumDevs			[internal] */static	DWORD	wodGetNumDevs(void){    return MAX_WAVEOUTDRV;}/************************************************************************** * 				wodMessage (WINENAS.@) */DWORD WINAPI NAS_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:    case DRVM_EXIT:    case DRVM_ENABLE:    case DRVM_DISABLE:	/* FIXME: Pretend this is supported */	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			* *======================================================================*/static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv){    /* we can't perform memory mapping as we don't have a file stream	interface with nas 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 NAS DirectSound Driver");    strcpy(desc->szDrvName, "winenas.drv");    return MMSYSERR_NOERROR;}static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid){    memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));    return MMSYSERR_NOERROR;}static int nas_init(void) {    TRACE("NAS INIT\n");    if (!(AuServ = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL)))       return 0;    return 1;}static int nas_finddev(WINE_WAVEOUT* wwo) {   int i;    for (i = 0; i < AuServerNumDevices(wwo->AuServ); i++) {        if ((AuDeviceKind(AuServerDevice(wwo->AuServ, i)) ==             AuComponentKindPhysicalOutput) &&             AuDeviceNumTracks(AuServerDevice(wwo->AuServ, i)) == wwo->format.wf.nChannels)        {            wwo->AuDev = AuDeviceIdentifier(AuServerDevice(wwo->AuServ, i));            break;        }    }    if (wwo->AuDev == AuNone)       return 0;    return 1;}static int nas_open(WINE_WAVEOUT* wwo) {    AuElement elements[3];    if (!wwo->AuServ)       return 0;    if (!nas_finddev(wwo))       return 0;    if (!(wwo->AuFlow = AuCreateFlow(wwo->AuServ, NULL)))       return 0;    wwo->BufferSize = FRAG_SIZE * FRAG_COUNT;    AuMakeElementImportClient(&elements[0], wwo->format.wf.nSamplesPerSec,           wwo->format.wBitsPerSample == 16 ? AuFormatLinearSigned16LSB : AuFormatLinearUnsigned8,           wwo->format.wf.nChannels, AuTrue, wwo->BufferSize, wwo->BufferSize / 2, 0, NULL);    AuMakeElementExportDevice(&elements[1], 0, wwo->AuDev, wwo->format.wf.nSamplesPerSec,                              AuUnlimitedSamples, 0, NULL);    AuSetElements(wwo->AuServ, wwo->AuFlow, AuTrue, 2, elements, NULL);    AuRegisterEventHandler(wwo->AuServ, AuEventHandlerIDMask, 0, wwo->AuFlow,                           event_handler, (AuPointer) wwo);    wwo->PlayedTotal = 0;    wwo->WrittenTotal = 0;    wwo->open = 1;    wwo->BufferUsed = 0;    wwo->writeBytes = 0;    wwo->freeBytes = 0;    wwo->sendBytes = 0;    wwo->SoundBuffer = NULL;    wwo->FlowStarted = 0;    AuStartFlow(wwo->AuServ, wwo->AuFlow, NULL);    AuPauseFlow(wwo->AuServ, wwo->AuFlow, NULL);    wwo->FlowStarted = 1;    return 1;}static AuBoolevent_handler(AuServer* aud, AuEvent* ev, AuEventHandlerRec* hnd){  WINE_WAVEOUT *wwo = (WINE_WAVEOUT *)hnd->data;        switch (ev->type) {        case AuEventTypeElementNotify: {                AuElementNotifyEvent* event = (AuElementNotifyEvent *)ev;                switch (event->kind) {                   case AuElementNotifyKindLowWater:                     wwo->freeBytes += event->num_bytes;                     if (wwo->writeBytes > 0)                        wwo->sendBytes += event->num_bytes;                    if (wwo->freeBytes && wwo->BufferUsed)                        nas_send_buffer(wwo);                   break;                   case AuElementNotifyKindState:                     TRACE("ev: kind %s state %s->%s reason %s numbytes %ld freeB %lu\n",                                     nas_elementnotify_kind(event->kind),                                     nas_state(event->prev_state),                                     nas_state(event->cur_state),                                     nas_reason(event->reason),                                     event->num_bytes, wwo->freeBytes);                     if (event->cur_state ==  AuStatePause && event->reason != AuReasonUser) {                        wwo->freeBytes += event->num_bytes;                        if (wwo->writeBytes > 0)                           wwo->sendBytes += event->num_bytes;                        if (wwo->sendBytes > wwo->writeBytes)                           wwo->sendBytes = wwo->writeBytes;                       if (wwo->freeBytes && wwo->BufferUsed)                           nas_send_buffer(wwo);                     }                   break;                }           }        }        return AuTrue;}static voidbuffer_resize(WINE_WAVEOUT* wwo, int len){        void *newbuf = malloc(wwo->BufferUsed + len);        void *oldbuf = wwo->SoundBuffer;        memcpy(newbuf, oldbuf, wwo->BufferUsed);        wwo->SoundBuffer = newbuf;        if (oldbuf != NULL)           free(oldbuf);}static int nas_add_buffer(WINE_WAVEOUT* wwo) {    int len = wwo->lpPlayPtr->dwBufferLength;    buffer_resize(wwo, len);    memcpy(wwo->SoundBuffer + wwo->BufferUsed, wwo->lpPlayPtr->lpData, len);    wwo->BufferUsed += len;    wwo->WrittenTotal += len;    return len;}static int nas_send_buffer(WINE_WAVEOUT* wwo) {  int oldb , len;  char *ptr, *newdata;  newdata = NULL;  oldb = len = 0;  if (wwo->freeBytes <= 0)     return 0;  if (wwo->SoundBuffer == NULL || wwo->BufferUsed == 0) {     return 0;  }  if (wwo->BufferUsed <= wwo->freeBytes) {     len = wwo->BufferUsed;     ptr = wwo->SoundBuffer;  } else {     len = wwo->freeBytes;     ptr = malloc(len);     memcpy(ptr,wwo->SoundBuffer,len);     newdata = malloc(wwo->BufferUsed - len);     memcpy(newdata, wwo->SoundBuffer + len, wwo->BufferUsed - len);  } TRACE("envoye de %d bytes / %lu bytes / freeBytes %lu\n", len, wwo->BufferUsed, wwo->freeBytes); AuWriteElement(wwo->AuServ, wwo->AuFlow, 0, len, ptr, AuFalse, NULL); wwo->BufferUsed -= len; wwo->freeBytes -= len; wwo->writeBytes += len; free(ptr); wwo->SoundBuffer = NULL; if (newdata != NULL)    wwo->SoundBuffer = newdata; return len;}static int nas_free(WINE_WAVEOUT* wwo){  if (!wwo->FlowStarted && wwo->BufferUsed) {     AuStartFlow(wwo->AuServ, wwo->AuFlow, NULL);     wwo->FlowStarted = 1;  }  while (wwo->BufferUsed || wwo->writeBytes != wwo->sendBytes) {    if (wwo->freeBytes)       nas_send_buffer(wwo);    AuHandleEvents(wwo->AuServ);  }  AuFlush(wwo->AuServ);  return TRUE;}static int nas_close(WINE_WAVEOUT* wwo){  AuEvent ev;  nas_free(wwo);  AuStopFlow(wwo->AuServ, wwo->AuFlow, NULL);  AuDestroyFlow(wwo->AuServ, wwo->AuFlow, NULL);  AuFlush(wwo->AuServ);  AuNextEvent(wwo->AuServ, AuTrue, &ev);  AuDispatchEvent(wwo->AuServ, &ev);  wwo->AuFlow = 0;  wwo->open = 0;  wwo->BufferUsed = 0;  wwo->freeBytes = 0;  wwo->SoundBuffer = NULL;  return 1;}static int nas_end(void){  AuCloseServer(AuServ);  AuServ = 0;  return 1;}#else /* !HAVE_NAS *//************************************************************************** * 				wodMessage (WINENAS.@) */DWORD WINAPI NAS_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2){    FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);    return MMSYSERR_NOTENABLED;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -