Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0df63e44 authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] Add O_APPEND flag support to PCM



Added O_APPEND flag support to PCM to enable shared substreams
among multiple processes.  This mechanism is used by dmix and
dsnoop plugins.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f001c3ac
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ enum {
 *                                                                           *
 *****************************************************************************/

#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 7)
#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 8)

typedef unsigned long snd_pcm_uframes_t;
typedef signed long snd_pcm_sframes_t;
+3 −2
Original line number Diff line number Diff line
@@ -368,7 +368,8 @@ struct snd_pcm_substream {
	struct snd_pcm_group *group;		/* pointer to current group */
	/* -- assigned files -- */
	void *file;
	struct file *ffile;
	int ref_count;
	unsigned int f_flags;
	void (*pcm_release)(struct snd_pcm_substream *);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
	/* -- OSS things -- */
@@ -387,7 +388,7 @@ struct snd_pcm_substream {
	unsigned int hw_opened: 1;
};

#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
#define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0)


struct snd_pcm_str {
+10 −7
Original line number Diff line number Diff line
@@ -1331,7 +1331,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
				if (runtime->oss.period_ptr == 0 ||
				    runtime->oss.period_ptr == runtime->oss.buffer_used)
					runtime->oss.buffer_used = 0;
				else if ((substream->ffile->f_flags & O_NONBLOCK) != 0)
				else if ((substream->f_flags & O_NONBLOCK) != 0)
					return xfer > 0 ? xfer : -EAGAIN;
			}
		} else {
@@ -1344,7 +1344,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha
			buf += tmp;
			bytes -= tmp;
			xfer += tmp;
			if ((substream->ffile->f_flags & O_NONBLOCK) != 0 &&
			if ((substream->f_flags & O_NONBLOCK) != 0 &&
			    tmp != runtime->oss.period_bytes)
				break;
		}
@@ -1582,10 +1582,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
		 * finish sync: drain the buffer
		 */
	      __direct:
		saved_f_flags = substream->ffile->f_flags;
		substream->ffile->f_flags &= ~O_NONBLOCK;
		saved_f_flags = substream->f_flags;
		substream->f_flags &= ~O_NONBLOCK;
		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
		substream->ffile->f_flags = saved_f_flags;
		substream->f_flags = saved_f_flags;
		if (err < 0)
			return err;
		runtime->oss.prepare = 1;
@@ -2164,9 +2164,9 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
	substream->oss.oss = 1;
	substream->oss.setup = *setup;
	if (setup->nonblock)
		substream->ffile->f_flags |= O_NONBLOCK;
		substream->f_flags |= O_NONBLOCK;
	else if (setup->block)
		substream->ffile->f_flags &= ~O_NONBLOCK;
		substream->f_flags &= ~O_NONBLOCK;
	runtime = substream->runtime;
	runtime->oss.params = 1;
	runtime->oss.trigger = 1;
@@ -2223,6 +2223,7 @@ static int snd_pcm_oss_open_file(struct file *file,
	    (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
		f_mode = FMODE_WRITE;

	file->f_flags &= ~O_APPEND;
	for (idx = 0; idx < 2; idx++) {
		if (setup[idx].disable)
			continue;
@@ -2540,6 +2541,7 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun
	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
	if (substream == NULL)
		return -ENXIO;
	substream->f_flags = file->f_flags & O_NONBLOCK;
#ifndef OSS_DEBUG
	return snd_pcm_oss_read1(substream, buf, count);
#else
@@ -2561,6 +2563,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
	if (substream == NULL)
		return -ENXIO;
	substream->f_flags = file->f_flags & O_NONBLOCK;
	result = snd_pcm_oss_write1(substream, buf, count);
#ifdef OSS_DEBUG
	printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
+23 −2
Original line number Diff line number Diff line
@@ -829,6 +829,26 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
		return -EINVAL;
	}

	if (file->f_flags & O_APPEND) {
		if (prefer_subdevice < 0) {
			if (pstr->substream_count > 1)
				return -EINVAL; /* must be unique */
			substream = pstr->substream;
		} else {
			for (substream = pstr->substream; substream;
			     substream = substream->next)
				if (substream->number == prefer_subdevice)
					break;
		}
		if (! substream)
			return -ENODEV;
		if (! SUBSTREAM_BUSY(substream))
			return -EBADFD;
		substream->ref_count++;
		*rsubstream = substream;
		return 0;
	}

	if (prefer_subdevice >= 0) {
		for (substream = pstr->substream; substream; substream = substream->next)
			if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
@@ -873,7 +893,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,

	substream->runtime = runtime;
	substream->private_data = pcm->private_data;
	substream->ffile = file;
	substream->ref_count = 1;
	substream->f_flags = file->f_flags;
	pstr->substream_opened++;
	*rsubstream = substream;
	return 0;
@@ -882,7 +903,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime;
	substream->file = NULL;

	runtime = substream->runtime;
	snd_assert(runtime != NULL, return);
	if (runtime->private_free != NULL)
+2 −2
Original line number Diff line number Diff line
@@ -497,9 +497,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
	case SNDRV_PCM_IOCTL_LINK:
	case SNDRV_PCM_IOCTL_UNLINK:
		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
			return snd_pcm_playback_ioctl1(substream, cmd, argp);
			return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
		else
			return snd_pcm_capture_ioctl1(substream, cmd, argp);
			return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
	case SNDRV_PCM_IOCTL_HW_REFINE32:
		return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
	case SNDRV_PCM_IOCTL_HW_PARAMS32:
Loading