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

📄 audio.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 5 页
字号:
        if ((ret = OSS_RawOpenDevice(ossdev,strict_format)) != MMSYSERR_NOERROR) return ret;    }    else    {        /* check we really open with the same parameters */        if (ossdev->open_access != req_access)        {            ERR("FullDuplex: Mismatch in access. Your sound device is not full duplex capable.\n");            return WAVERR_BADFORMAT;        }	/* check if the audio parameters are the same */        if (ossdev->sample_rate != sample_rate ||            ossdev->stereo != stereo ||            ossdev->format != fmt)        {	    /* This is not a fatal error because MSACM might do the remapping */             WARN("FullDuplex: mismatch in PCM parameters for input and output\n"                 "OSS doesn't allow us different parameters\n"                 "audio_frag(%x/%x) sample_rate(%d/%d) stereo(%d/%d) fmt(%d/%d)\n",                 ossdev->audio_fragment, frag ? *frag : 0,                 ossdev->sample_rate, sample_rate,                 ossdev->stereo, stereo,                 ossdev->format, fmt);            return WAVERR_BADFORMAT;        }	/* check if the fragment sizes are the same */        if (ossdev->audio_fragment != (frag ? *frag : 0) ) {	    ERR("FullDuplex: Playback and Capture hardware acceleration levels are different.\n"		"Use: \"HardwareAcceleration\" = \"Emulation\" in the [dsound] section of your config file.\n");	    return WAVERR_BADFORMAT;	}        if (GetCurrentThreadId() != ossdev->owner_tid)        {            WARN("Another thread is trying to access audio...\n");            return MMSYSERR_ERROR;        }    }    ossdev->open_count++;    return MMSYSERR_NOERROR;}/****************************************************************** *		OSS_CloseDevice * * */static void	OSS_CloseDevice(OSS_DEVICE* ossdev){    TRACE("(%p)\n",ossdev);    if (ossdev->open_count>0) {        ossdev->open_count--;    } else {        WARN("OSS_CloseDevice called too many times\n");    }    if (ossdev->open_count == 0)    {       /* reset the device before we close it in case it is in a bad state */       ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);       close(ossdev->fd);    }}/****************************************************************** *		OSS_ResetDevice * * Resets the device. OSS Commercial requires the device to be closed * after a SNDCTL_DSP_RESET ioctl call... this function implements * this behavior... * FIXME: This causes problems when doing full duplex so we really * only reset when not doing full duplex. We need to do this better * someday.  */static DWORD     OSS_ResetDevice(OSS_DEVICE* ossdev){    DWORD       ret = MMSYSERR_NOERROR;    int         old_fd = ossdev->fd;    TRACE("(%p)\n", ossdev);    if (ossdev->open_count == 1) {	if (ioctl(ossdev->fd, SNDCTL_DSP_RESET, NULL) == -1) 	{	    perror("ioctl SNDCTL_DSP_RESET");            return -1;	}	close(ossdev->fd);	ret = OSS_RawOpenDevice(ossdev, 1);	TRACE("Changing fd from %d to %d\n", old_fd, ossdev->fd);    } else 	WARN("Not resetting device because it is in full duplex mode!\n");        return ret;}const static int win_std_oss_fmts[2]={AFMT_U8,AFMT_S16_LE};const static int win_std_rates[5]={96000,48000,44100,22050,11025};const static int win_std_formats[2][2][5]=    {{{WAVE_FORMAT_96M08, WAVE_FORMAT_48M08, WAVE_FORMAT_4M08,       WAVE_FORMAT_2M08,  WAVE_FORMAT_1M08},      {WAVE_FORMAT_96S08, WAVE_FORMAT_48S08, WAVE_FORMAT_4S08,       WAVE_FORMAT_2S08,  WAVE_FORMAT_1S08}},     {{WAVE_FORMAT_96M16, WAVE_FORMAT_48M16, WAVE_FORMAT_4M16,       WAVE_FORMAT_2M16,  WAVE_FORMAT_1M16},      {WAVE_FORMAT_96S16, WAVE_FORMAT_48S16, WAVE_FORMAT_4S16,       WAVE_FORMAT_2S16,  WAVE_FORMAT_1S16}},    };/****************************************************************** *		OSS_WaveOutInit * * */static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev){    int rc,arg;    int f,c,r;    TRACE("(%p) %s\n", ossdev, ossdev->dev_name);    if (OSS_OpenDevice(ossdev, O_WRONLY, NULL, 0,-1,-1,-1) != 0) return FALSE;    ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);#ifdef SOUND_MIXER_INFO    {        int mixer;        if ((mixer = open(ossdev->mixer_name, O_RDONLY|O_NDELAY)) >= 0) {            mixer_info info;            if (ioctl(mixer, SOUND_MIXER_INFO, &info) >= 0) {                close(mixer);                strncpy(ossdev->ds_desc.szDesc, info.name, sizeof(info.name));                strcpy(ossdev->ds_desc.szDrvName, "wineoss.drv");                strncpy(ossdev->out_caps.szPname, info.name, sizeof(info.name));                TRACE("%s\n", ossdev->ds_desc.szDesc);            } else {                ERR("%s: can't read info!\n", ossdev->mixer_name);                OSS_CloseDevice(ossdev);                close(mixer);                return FALSE;            }        } else {            ERR("%s: %s\n", ossdev->mixer_name , strerror( errno ));            OSS_CloseDevice(ossdev);            return FALSE;        }    }#endif /* SOUND_MIXER_INFO */    /* FIXME: some programs compare this string against the content of the     * registry for MM drivers. The names have to match in order for the     * program to work (e.g. MS win9x mplayer.exe)     */#ifdef EMULATE_SB16    ossdev->out_caps.wMid = 0x0002;    ossdev->out_caps.wPid = 0x0104;    strcpy(ossdev->out_caps.szPname, "SB16 Wave Out");#else    ossdev->out_caps.wMid = 0x00FF; /* Manufac ID */    ossdev->out_caps.wPid = 0x0001; /* Product ID */#endif    ossdev->out_caps.vDriverVersion = 0x0100;    ossdev->out_caps.wChannels = 1;    ossdev->out_caps.dwFormats = 0x00000000;    ossdev->out_caps.wReserved1 = 0;    ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;    /* direct sound caps */    ossdev->ds_caps.dwFlags = 0;    ossdev->ds_caps.dwPrimaryBuffers = 1;    ossdev->ds_caps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;    ossdev->ds_caps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;                                                                                    if (WINE_TRACE_ON(wave)) {        /* Note that this only reports the formats supported by the hardware.         * The driver may support other formats and do the conversions in         * software which is why we don't use this value         */        int oss_mask;        ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &oss_mask);        TRACE("OSS dsp out mask=%08x\n", oss_mask);    }    /* We must first set the format and the stereo mode as some sound cards     * may support 44kHz mono but not 44kHz stereo. Also we must     * systematically check the return value of these ioctls as they will     * always succeed (see OSS Linux) but will modify the parameter to match     * whatever they support. The OSS specs also say we must first set the     * sample size, then the stereo and then the sample rate.     */    for (f=0;f<2;f++) {        arg=win_std_oss_fmts[f];        rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);        if (rc!=0 || arg!=win_std_oss_fmts[f]) {            TRACE("DSP_SAMPLESIZE: rc=%d returned %d for %d\n",                  rc,arg,win_std_oss_fmts[f]);            continue;        }	if (f == 0) 	    ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARY8BIT;	else if (f == 1)	    ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARY16BIT;        for (c=0;c<2;c++) {            arg=c;            rc=ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &arg);            if (rc!=0 || arg!=c) {                TRACE("DSP_STEREO: rc=%d returned %d for %d\n",rc,arg,c);                continue;            }	    if (c == 0) {		ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARYMONO;	    } else if (c==1) {                ossdev->out_caps.wChannels=2;                ossdev->out_caps.dwSupport|=WAVECAPS_LRVOLUME;		ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARYSTEREO;            }            for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) {                arg=win_std_rates[r];                rc=ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &arg);                TRACE("DSP_SPEED: rc=%d returned %d for %dx%dx%d\n",                      rc,arg,win_std_rates[r],win_std_oss_fmts[f],c+1);                if (rc==0 && arg!=0 && NEAR_MATCH(arg,win_std_rates[r]))                    ossdev->out_caps.dwFormats|=win_std_formats[f][c][r];            }        }    }    if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &arg) == 0) {        TRACE("OSS dsp out caps=%08X\n", arg);        if (arg & DSP_CAP_TRIGGER)            ossdev->bTriggerSupport = TRUE;        if ((arg & DSP_CAP_REALTIME) && !(arg & DSP_CAP_BATCH)) {            ossdev->out_caps.dwSupport |= WAVECAPS_SAMPLEACCURATE;        }        /* well, might as well use the DirectSound cap flag for something */        if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) &&            !(arg & DSP_CAP_BATCH)) {            ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;	} else {	    ossdev->ds_caps.dwFlags |= DSCAPS_EMULDRIVER;	}    }    OSS_CloseDevice(ossdev);    TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",          ossdev->out_caps.dwFormats, ossdev->out_caps.dwSupport);    return TRUE;}/****************************************************************** *		OSS_WaveInInit * * */static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev){    int rc,arg;    int f,c,r;    TRACE("(%p) %s\n", ossdev, ossdev->dev_name);    if (OSS_OpenDevice(ossdev, O_RDONLY, NULL, 0,-1,-1,-1) != 0)	return FALSE;    ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);#ifdef SOUND_MIXER_INFO    {        int mixer;        if ((mixer = open(ossdev->mixer_name, O_RDONLY|O_NDELAY)) >= 0) {            mixer_info info;            if (ioctl(mixer, SOUND_MIXER_INFO, &info) >= 0) {                close(mixer);                strncpy(ossdev->in_caps.szPname, info.name, sizeof(info.name));                TRACE("%s\n", ossdev->ds_desc.szDesc);            } else {                ERR("%s: can't read info!\n", ossdev->mixer_name);                OSS_CloseDevice(ossdev);                close(mixer);                return FALSE;            }        } else {            ERR("%s: %s\n", ossdev->mixer_name, strerror(errno));            OSS_CloseDevice(ossdev);            return FALSE;        }    }#endif /* SOUND_MIXER_INFO */    /* See comment in OSS_WaveOutInit */#ifdef EMULATE_SB16    ossdev->in_caps.wMid = 0x0002;    ossdev->in_caps.wPid = 0x0004;    strcpy(ossdev->in_caps.szPname, "SB16 Wave In");#else    ossdev->in_caps.wMid = 0x00FF; /* Manufac ID */    ossdev->in_caps.wPid = 0x0001; /* Product ID */#endif    ossdev->in_caps.dwFormats = 0x00000000;    ossdev->in_caps.wChannels = 1;    ossdev->in_caps.wReserved1 = 0;    /* direct sound caps */    ossdev->dsc_caps.dwSize = sizeof(ossdev->dsc_caps);    ossdev->dsc_caps.dwFlags = 0;    ossdev->dsc_caps.dwFormats = 0x00000000;    ossdev->dsc_caps.dwChannels = 1;    if (WINE_TRACE_ON(wave)) {        /* Note that this only reports the formats supported by the hardware.         * The driver may support other formats and do the conversions in         * software which is why we don't use this value         */        int oss_mask;        ioctl(ossdev->fd, SNDCTL_DSP_GETFMTS, &oss_mask);        TRACE("OSS dsp out mask=%08x\n", oss_mask);    }    /* See the comment in OSS_WaveOutInit */    for (f=0;f<2;f++) {        arg=win_std_oss_fmts[f];        rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);        if (rc!=0 || arg!=win_std_oss_fmts[f]) {            TRACE("DSP_SAMPLESIZE: rc=%d returned 0x%x for 0x%x\n",                  rc,arg,win_std_oss_fmts[f]);            continue;        }        for (c=0;c<2;c++) {            arg=c;            rc=ioctl(ossdev->fd, SNDCTL_DSP_STEREO, &arg);            if (rc!=0 || arg!=c) {                TRACE("DSP_STEREO: rc=%d returned %d for %d\n",rc,arg,c);                continue;            }            if (c==1) {                ossdev->in_caps.wChannels=2;    		ossdev->dsc_caps.dwChannels=2;            }            for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) {                arg=win_std_rates[r];                rc=ioctl(ossdev->fd, SNDCTL_DSP_SPEED, &arg);                TRACE("DSP_SPEED: rc=%d returned %d for %dx%dx%d\n",rc,arg,win_std_rates[r],win_std_oss_fmts[f],c+1);                if (rc==0 && NEAR_MATCH(arg,win_std_rates[r]))                    ossdev->in_caps.dwFormats|=win_std_formats[f][c][r];		    ossdev->dsc_caps.dwFormats|=win_std_formats[f][c][r];            }        }    }    if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &arg) == 0) {        TRACE("OSS dsp in caps=%08X\n", arg);        if (arg & DSP_CAP_TRIGGER)            ossdev->bTriggerSupport = TRUE;        if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) &&            !(arg & DSP_CAP_BATCH)) {	    /* FIXME: enable the next statement if you want to work on the driver */#if 0            ossdev->in_caps_support |= WAVECAPS_DIRECTSOUND;#endif	}	if ((arg & DSP_CAP_REALTIME) && !(arg & DSP_CAP_BATCH))	    ossdev->in_caps_support |= WAVECAPS_SAMPLEACCURATE;    }    OSS_CloseDevice(ossdev);    TRACE("in dwFormats = %08lX\n", ossdev->in_caps.dwFormats);    return TRUE;}/****************************************************************** *		OSS_WaveFullDuplexInit * * */static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev){    int 	caps;    TRACE("(%p)\n",ossdev);    if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0,-1,-1,-1) != 0) return;    if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0)    {	ossdev->full_duplex = (caps & DSP_CAP_DUPLEX);    }    OSS_CloseDevice(ossdev);}

⌨️ 快捷键说明

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