📄 pcm_oss.c
字号:
}static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) return err; return substream->runtime->oss.rate;}static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, int channels){ int idx; if (channels < 1) channels = 1; if (channels > 128) return -EINVAL; for (idx = 1; idx >= 0; --idx) { snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; snd_pcm_runtime_t *runtime; if (substream == NULL) continue; runtime = substream->runtime; if (runtime->oss.channels != channels) { runtime->oss.params = 1; runtime->oss.channels = channels; } } return snd_pcm_oss_get_channels(pcm_oss_file);}static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) return err; return substream->runtime->oss.channels;}static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) return err; return substream->runtime->oss.period_bytes;}static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *substream; int err; int direct; snd_pcm_hw_params_t params; unsigned int formats = 0; unsigned int format_mask; int fmt; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) return err; if (atomic_read(&substream->runtime->mmap_count)) { direct = 1; } else { snd_pcm_oss_setup_t *setup = substream->oss.setup; direct = (setup != NULL && setup->direct); } if (!direct) return AFMT_MU_LAW | AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE; _snd_pcm_hw_params_any(¶ms); err = snd_pcm_hw_refine(substream, ¶ms); snd_assert(err >= 0, return err); format_mask = *hw_param_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT); for (fmt = 0; fmt < 32; ++fmt) { if (format_mask & (1 << fmt)) { int f = snd_pcm_oss_format_to(fmt); if (f >= 0) formats |= f; } } return formats;}static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format){ int formats, idx; if (format != AFMT_QUERY) { formats = snd_pcm_oss_get_formats(pcm_oss_file); if (!(formats & format)) format = AFMT_U8; for (idx = 1; idx >= 0; --idx) { snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; snd_pcm_runtime_t *runtime; if (substream == NULL) continue; runtime = substream->runtime; if (runtime->oss.format != format) { runtime->oss.params = 1; runtime->oss.format = format; } } } return snd_pcm_oss_get_format(pcm_oss_file);}static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *substream; int err; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) return err; return substream->runtime->oss.format;}static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdivide){ snd_pcm_runtime_t *runtime; if (substream == NULL) return 0; runtime = substream->runtime; if (subdivide == 0) { subdivide = runtime->oss.subdivision; if (subdivide == 0) subdivide = 1; return subdivide; } if (runtime->oss.subdivision || runtime->oss.fragshift) return -EINVAL; if (subdivide != 1 && subdivide != 2 && subdivide != 4 && subdivide != 8 && subdivide != 16) return -EINVAL; runtime->oss.subdivision = subdivide; runtime->oss.params = 1; return subdivide;}static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdivide){ int err = -EINVAL, idx; for (idx = 1; idx >= 0; --idx) { snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; if (substream == NULL) continue; if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) return err; } return err;}static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned int val){ snd_pcm_runtime_t *runtime; if (substream == NULL) return 0; runtime = substream->runtime; if (runtime->oss.subdivision || runtime->oss.fragshift) return -EINVAL; runtime->oss.fragshift = val & 0xffff; runtime->oss.maxfrags = (val >> 16) & 0xffff; if (runtime->oss.fragshift < 4) /* < 16 */ runtime->oss.fragshift = 4; if (runtime->oss.maxfrags < 2) runtime->oss.maxfrags = 2; runtime->oss.params = 1; return 0;}static int snd_pcm_oss_set_fragment(snd_pcm_oss_file_t *pcm_oss_file, unsigned int val){ int err = -EINVAL, idx; for (idx = 1; idx >= 0; --idx) { snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; if (substream == NULL) continue; if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) return err; } return err;}static int snd_pcm_oss_nonblock(struct file * file){ file->f_flags |= O_NONBLOCK; return 0;}static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res){ if (substream == NULL) { res &= ~DSP_CAP_DUPLEX; return res; }#ifdef DSP_CAP_MULTI if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->pstr->substream_count > 1) res |= DSP_CAP_MULTI;#endif /* DSP_CAP_REALTIME is set all times: */ /* all ALSA drivers can return actual pointer in ring buffer */#if defined(DSP_CAP_REALTIME) && 0 { snd_pcm_runtime_t *runtime = substream->runtime; if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH)) res &= ~DSP_CAP_REALTIME; }#endif return res;}static int snd_pcm_oss_get_caps(snd_pcm_oss_file_t *pcm_oss_file){ int result, idx; result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME; for (idx = 0; idx < 2; idx++) { snd_pcm_substream_t *substream = pcm_oss_file->streams[idx]; result = snd_pcm_oss_get_caps1(substream, result); } result |= 0x0001; /* revision - same as SB AWE 64 */ return result;}static void snd_pcm_oss_simulate_fill(snd_pcm_substream_t *substream){ snd_pcm_runtime_t *runtime = substream->runtime; snd_pcm_uframes_t appl_ptr; appl_ptr = runtime->hw_ptr_interrupt + runtime->buffer_size; appl_ptr %= runtime->boundary; runtime->control->appl_ptr = appl_ptr;}static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger){ snd_pcm_runtime_t *runtime; snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; int err, cmd; psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (psubstream) { if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) return err; if (atomic_read(&psubstream->runtime->mmap_count)) snd_pcm_oss_simulate_fill(psubstream); } if (csubstream) { if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) return err; } if (psubstream) { runtime = psubstream->runtime; if (trigger & PCM_ENABLE_OUTPUT) { if (runtime->oss.trigger) goto _skip1; runtime->oss.trigger = 1; runtime->start_threshold = 1; cmd = SNDRV_PCM_IOCTL_START; } else { if (!runtime->oss.trigger) goto _skip1; runtime->oss.trigger = 0; runtime->start_threshold = runtime->boundary; cmd = SNDRV_PCM_IOCTL_DROP; runtime->oss.prepare = 1; } err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, 0); if (err < 0) return err; } _skip1: if (csubstream) { runtime = csubstream->runtime; if (trigger & PCM_ENABLE_INPUT) { if (runtime->oss.trigger) goto _skip2; runtime->oss.trigger = 1; runtime->start_threshold = 1; cmd = SNDRV_PCM_IOCTL_START; } else { if (!runtime->oss.trigger) goto _skip2; runtime->oss.trigger = 0; runtime->start_threshold = runtime->boundary; cmd = SNDRV_PCM_IOCTL_DROP; runtime->oss.prepare = 1; } err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, 0); if (err < 0) return err; } _skip2: return 0;}static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; int result = 0; psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger) result |= PCM_ENABLE_OUTPUT; if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger) result |= PCM_ENABLE_INPUT; return result;}static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file){ snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; snd_pcm_sframes_t delay; int err; substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; if (substream == NULL) return -EINVAL; if ((err = snd_pcm_oss_make_ready(substream)) < 0) return err; runtime = substream->runtime; if (runtime->oss.params || runtime->oss.prepare) return 0; err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); if (err == -EPIPE) delay = 0; /* hack for broken OSS applications */ else if (err < 0) return err; return snd_pcm_oss_bytes(substream, delay);}static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct count_info * _info){ snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; snd_pcm_status_t status; struct count_info info; int err; if (_info == NULL) return -EFAULT; substream = pcm_oss_file->streams[stream]; if (substream == NULL) return -EINVAL; if ((err = snd_pcm_oss_make_ready(substream)) < 0) return err; runtime = substream->runtime; if (runtime->oss.params || runtime->oss.prepare) { memset(&info, 0, sizeof(info)); if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; return 0; } memset(&status, 0, sizeof(status)); err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status); if (err < 0) return err; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, runtime->buffer_size - status.avail); } else { info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, status.avail); } info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); if (atomic_read(&runtime->mmap_count)) { snd_pcm_sframes_t n; n = runtime->hw_ptr_interrupt - runtime->oss.prev_hw_ptr_interrupt; if (n < 0) n += runtime->boundary; info.blocks = n / runtime->period_size; runtime->oss.prev_hw_ptr_interrupt = runtime->hw_ptr_interrupt; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_pcm_oss_simulate_fill(substream); } else { if (stream == SNDRV_PCM_STREAM_PLAYBACK) info.blocks = (runtime->buffer_size - status.avail) / runtime->period_size; else info.blocks = status.avail / runtime->period_size; } if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; return 0;}static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct audio_buf_info *_info){ snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; snd_pcm_status_t status; struct audio_buf_info info; int err; if (_info == NULL) return -EFAULT; substream = pcm_oss_file->streams[stream]; if (substream == NULL) return -EINVAL; runtime = substream->runtime; if (runtime->oss.params && (err = snd_pcm_oss_change_params(substream)) < 0) return err; info.fragsize = runtime->oss.period_bytes; info.fragstotal = runtime->periods; memset(&status, 0, sizeof(status)); if (runtime->oss.prepare) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { info.bytes = runtime->oss.period_bytes * runtime->periods; info.fragments = runtime->periods; } else { info.bytes = 0; info.fragments = 0; } } else { err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status); if (err < 0) return err; info.bytes = snd_pcm_oss_bytes(substream, status.avail); info.fragments = status.avail / runtime->period_size; }#if 0 /* very experimental stuff to get Quake2 working */ runtime->oss.period = (info.periods - 1) << 16; for (tmp = info.fragsize; tmp > 1; tmp >>= 1) runtime->oss.period++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -