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

📄 pcm_oss.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	runtime->oss.format = snd_pcm_oss_format_to(params_format(&params));	runtime->oss.channels = params_channels(&params);	runtime->oss.rate = params_rate(&params);	runtime->oss.params = 0;	runtime->oss.prepare = 1;	if (runtime->oss.buffer != NULL)		vfree(runtime->oss.buffer);	runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);	runtime->oss.buffer_used = 0;	snd_assert(runtime->dma_area != NULL, return -EIO);	snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));	return 0;}static int snd_pcm_oss_get_active_substream(snd_pcm_oss_file_t *pcm_oss_file, snd_pcm_substream_t **r_substream){	int idx, err;	snd_pcm_substream_t *asubstream = NULL, *substream;	for (idx = 0; idx < 2; idx++) {		substream = pcm_oss_file->streams[idx];		if (substream == NULL)			continue;		if (asubstream == NULL)			asubstream = substream;		if (substream->runtime->oss.params) {			err = snd_pcm_oss_change_params(substream);			if (err < 0)				return err;		}	}	snd_assert(asubstream != NULL, return -EIO);	if (r_substream)		*r_substream = asubstream;	return 0;}static int snd_pcm_oss_prepare(snd_pcm_substream_t *substream){	int err;	snd_pcm_runtime_t *runtime = substream->runtime;	err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, 0);	if (err < 0) {		snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n");		return err;	}	runtime->oss.prepare = 0;	runtime->oss.prev_hw_ptr_interrupt = 0;	return 0;}static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream){	snd_pcm_runtime_t *runtime;	int err;	if (substream == NULL)		return 0;	runtime = substream->runtime;	if (runtime->oss.params) {		err = snd_pcm_oss_change_params(substream);		if (err < 0)			return err;	}	if (runtime->oss.prepare) {		err = snd_pcm_oss_prepare(substream);		if (err < 0)			return err;	}	return 0;}snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel){	snd_pcm_runtime_t *runtime = substream->runtime;	int ret;	while (1) {		if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {			ret = snd_pcm_oss_prepare(substream);			if (ret < 0)				break;		}		if (in_kernel) {			mm_segment_t fs;			fs = snd_enter_user();			ret = snd_pcm_lib_write(substream, ptr, frames);			snd_leave_user(fs);		} else {			ret = snd_pcm_lib_write(substream, ptr, frames);		}		if (ret != -EPIPE && ret != -ESTRPIPE)			break;		/* test, if we can't store new data, because the stream */		/* has not been started */		if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)			return -EAGAIN;	}	return ret;}snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel){	snd_pcm_runtime_t *runtime = substream->runtime;	int ret;	while (1) {		if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);			if (ret < 0)				break;		} else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {			ret = snd_pcm_oss_prepare(substream);			if (ret < 0)				break;		}		ret = snd_pcm_lib_read(substream, ptr, frames);		if (in_kernel) {			mm_segment_t fs;			fs = snd_enter_user();			ret = snd_pcm_lib_read(substream, ptr, frames);			snd_leave_user(fs);		} else {			ret = snd_pcm_lib_read(substream, ptr, frames);		}		if (ret != -EPIPE && ret != -ESTRPIPE)			break;	}	return ret;}snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel){	snd_pcm_runtime_t *runtime = substream->runtime;	int ret;	while (1) {		if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {			ret = snd_pcm_oss_prepare(substream);			if (ret < 0)				break;		}		if (in_kernel) {			mm_segment_t fs;			fs = snd_enter_user();			ret = snd_pcm_lib_writev(substream, bufs, frames);			snd_leave_user(fs);		} else {			ret = snd_pcm_lib_writev(substream, bufs, frames);		}		if (ret != -EPIPE && ret != -ESTRPIPE)			break;		/* test, if we can't store new data, because the stream */		/* has not been started */		if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)			return -EAGAIN;	}	return ret;}	snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel){	snd_pcm_runtime_t *runtime = substream->runtime;	int ret;	while (1) {		if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);			if (ret < 0)				break;		} else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {			ret = snd_pcm_oss_prepare(substream);			if (ret < 0)				break;		}		if (in_kernel) {			mm_segment_t fs;			fs = snd_enter_user();			ret = snd_pcm_lib_readv(substream, bufs, frames);			snd_leave_user(fs);		} else {			ret = snd_pcm_lib_readv(substream, bufs, frames);		}		if (ret != -EPIPE && ret != -ESTRPIPE)			break;	}	return ret;}static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *buf, size_t bytes, int in_kernel){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_pcm_sframes_t frames, frames1;	if (runtime->oss.plugin_first) {		snd_pcm_plugin_channel_t *channels;		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;		if (!in_kernel) {			if (copy_from_user(runtime->oss.buffer, buf, bytes))				return -EFAULT;			buf = runtime->oss.buffer;		}		frames = bytes / oss_frame_bytes;		frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels);		if (frames1 < 0)			return frames1;		frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1);		if (frames1 <= 0)			return frames1;		bytes = frames1 * oss_frame_bytes;	} else {		frames = bytes_to_frames(runtime, bytes);		frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel);		if (frames1 <= 0)			return frames1;		bytes = frames_to_bytes(runtime, frames1);	}	return bytes;}static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char *buf, size_t bytes){	size_t xfer = 0;	ssize_t tmp;	snd_pcm_runtime_t *runtime = substream->runtime;	if (atomic_read(&runtime->mmap_count))		return -ENXIO;	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)		return tmp;	while (bytes > 0) {		if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {			tmp = bytes;			if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes)				tmp = runtime->oss.period_bytes - runtime->oss.buffer_used;			if (tmp > 0) {				if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp))					return xfer > 0 ? xfer : -EFAULT;			}			runtime->oss.buffer_used += tmp;			buf += tmp;			bytes -= tmp;			xfer += tmp;			if (runtime->oss.buffer_used == runtime->oss.period_bytes) {				tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);				if (tmp <= 0)					return xfer > 0 ? xfer : tmp;				runtime->oss.bytes += tmp;				runtime->oss.buffer_used = 0;			}		} else {			tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0);			if (tmp <= 0)				return xfer > 0 ? xfer : tmp;			runtime->oss.bytes += tmp;			buf += tmp;			bytes -= tmp;			xfer += tmp;		}	}	return xfer;}static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size_t bytes, int in_kernel){	snd_pcm_runtime_t *runtime = substream->runtime;	snd_pcm_sframes_t frames, frames1;	char *final_dst = buf;	if (runtime->oss.plugin_first) {		snd_pcm_plugin_channel_t *channels;		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;		if (!in_kernel)			buf = runtime->oss.buffer;		frames = bytes / oss_frame_bytes;		frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels);		if (frames1 < 0)			return frames1;		frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1);		if (frames1 <= 0)			return frames1;		bytes = frames1 * oss_frame_bytes;		if (!in_kernel && copy_to_user(final_dst, buf, bytes))			return -EFAULT;	} else {		frames = bytes_to_frames(runtime, bytes);		frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel);		if (frames1 <= 0)			return frames1;		bytes = frames_to_bytes(runtime, frames1);	}	return bytes;}static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char *buf, size_t bytes){	size_t xfer = 0;	ssize_t tmp;	snd_pcm_runtime_t *runtime = substream->runtime;	if (atomic_read(&runtime->mmap_count))		return -ENXIO;	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)		return tmp;	while (bytes > 0) {		if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) {			if (runtime->oss.buffer_used == 0) {				tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);				if (tmp <= 0)					return xfer > 0 ? xfer : tmp;				runtime->oss.bytes += tmp;				runtime->oss.buffer_used = runtime->oss.period_bytes;			}			tmp = bytes;			if ((size_t) tmp > runtime->oss.buffer_used)				tmp = runtime->oss.buffer_used;			if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_bytes - runtime->oss.buffer_used), tmp))				return xfer > 0 ? xfer : -EFAULT;			buf += tmp;			bytes -= tmp;			xfer += tmp;			runtime->oss.buffer_used -= tmp;		} else {			tmp = snd_pcm_oss_read2(substream, (char *)buf, runtime->oss.period_bytes, 0);			if (tmp <= 0)				return xfer > 0 ? xfer : tmp;			runtime->oss.bytes += tmp;			buf += tmp;			bytes -= tmp;			xfer += tmp;		}	}	return xfer;}static int snd_pcm_oss_reset(snd_pcm_oss_file_t *pcm_oss_file){	snd_pcm_substream_t *substream;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream != NULL) {		snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);		substream->runtime->oss.prepare = 1;	}	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (substream != NULL) {		snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);		substream->runtime->oss.prepare = 1;	}	return 0;}static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file){	int err = 0;	unsigned int saved_f_flags;	snd_pcm_substream_t *substream;	snd_pcm_runtime_t *runtime;	ssize_t result;	wait_queue_t wait;	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];	if (substream != NULL) {		if ((err = snd_pcm_oss_make_ready(substream)) < 0)			return err;				runtime = substream->runtime;		if (runtime->oss.buffer_used > 0) {			snd_pcm_format_set_silence(runtime->format,						   runtime->oss.buffer + runtime->oss.buffer_used,						   bytes_to_samples(runtime, runtime->oss.period_bytes - runtime->oss.buffer_used));			init_waitqueue_entry(&wait, current);			add_wait_queue(&runtime->sleep, &wait);			while (1) {				result = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1);				if (result > 0) {					runtime->oss.buffer_used = 0;					break;				}				if (result != 0 && result != -EAGAIN)					break;				set_current_state(TASK_INTERRUPTIBLE);				schedule();				if (signal_pending(current)) {					result = -ERESTARTSYS;					break;				}			}			set_current_state(TASK_RUNNING);			remove_wait_queue(&runtime->sleep, &wait);			if (result < 0)				return result;		}		saved_f_flags = substream->ffile->f_flags;		substream->ffile->f_flags &= ~O_NONBLOCK;		err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0);		substream->ffile->f_flags = saved_f_flags;		if (err < 0)			return err;		runtime->oss.prepare = 1;	}	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];	if (substream != NULL) {		if ((err = snd_pcm_oss_make_ready(substream)) < 0)			return err;		runtime = substream->runtime;		err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, 0);		if (err < 0)			return err;		runtime->oss.buffer_used = 0;		runtime->oss.prepare = 1;	}	return 0;}static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate){	int idx;	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 (rate < 1000)			rate = 1000;		else if (rate > 48000)			rate = 48000;		if (runtime->oss.rate != rate) {			runtime->oss.params = 1;			runtime->oss.rate = rate;		}	}	return snd_pcm_oss_get_rate(pcm_oss_file);

⌨️ 快捷键说明

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