ALSA: control: Provide a helper to look for the preferred subdevice

Instead of open-coding the search over the control file loop, provide
a helper function for the preferred subdevice assigned to the current
process.

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2014-02-19 14:30:29 +01:00
parent 92b7952da8
commit 23c18d4bfd
4 changed files with 38 additions and 29 deletions

View File

@ -93,12 +93,17 @@ struct snd_kctl_event {
struct pid;
enum {
SND_CTL_SUBDEV_PCM,
SND_CTL_SUBDEV_RAWMIDI,
SND_CTL_SUBDEV_ITEMS,
};
struct snd_ctl_file {
struct list_head list; /* list of all control files */
struct snd_card *card;
struct pid *pid;
int prefer_pcm_subdevice;
int prefer_rawmidi_subdevice;
int preferred_subdevice[SND_CTL_SUBDEV_ITEMS];
wait_queue_head_t change_sleep;
spinlock_t read_lock;
struct fasync_struct *fasync;
@ -138,6 +143,8 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
#define snd_ctl_unregister_ioctl_compat(fcn)
#endif
int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{
return id->numid - kctl->id.numid;

View File

@ -50,7 +50,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
unsigned long flags;
struct snd_card *card;
struct snd_ctl_file *ctl;
int err;
int i, err;
err = nonseekable_open(inode, file);
if (err < 0)
@ -79,8 +79,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
init_waitqueue_head(&ctl->change_sleep);
spin_lock_init(&ctl->read_lock);
ctl->card = card;
ctl->prefer_pcm_subdevice = -1;
ctl->prefer_rawmidi_subdevice = -1;
for (i = 0; i < SND_CTL_SUBDEV_ITEMS; i++)
ctl->preferred_subdevice[i] = -1;
ctl->pid = get_pid(task_pid(current));
file->private_data = ctl;
write_lock_irqsave(&card->ctl_files_rwlock, flags);
@ -1607,6 +1607,27 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
return fasync_helper(fd, file, on, &ctl->fasync);
}
/* return the preferred subdevice number if already assigned;
* otherwise return -1
*/
int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type)
{
struct snd_ctl_file *kctl;
int subdevice = -1;
read_lock(&card->ctl_files_rwlock);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
subdevice = kctl->preferred_subdevice[type];
if (subdevice != -1)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
return subdevice;
}
EXPORT_SYMBOL_GPL(snd_ctl_get_preferred_subdevice);
/*
* ioctl32 compat
*/

View File

@ -161,7 +161,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
if (get_user(val, (int __user *)arg))
return -EFAULT;
control->prefer_pcm_subdevice = val;
control->preferred_subdevice[SND_CTL_SUBDEV_PCM] = val;
return 0;
}
}
@ -901,9 +901,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
struct snd_pcm_str * pstr;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
struct snd_ctl_file *kctl;
struct snd_card *card;
int prefer_subdevice = -1;
int prefer_subdevice;
size_t size;
if (snd_BUG_ON(!pcm || !rsubstream))
@ -914,15 +913,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
return -ENODEV;
card = pcm->card;
read_lock(&card->ctl_files_rwlock);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
prefer_subdevice = kctl->prefer_pcm_subdevice;
if (prefer_subdevice != -1)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
switch (stream) {
case SNDRV_PCM_STREAM_PLAYBACK:

View File

@ -369,7 +369,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
struct snd_rawmidi *rmidi;
struct snd_rawmidi_file *rawmidi_file = NULL;
wait_queue_t wait;
struct snd_ctl_file *kctl;
if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
return -EINVAL; /* invalid combination */
@ -413,16 +412,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
init_waitqueue_entry(&wait, current);
add_wait_queue(&rmidi->open_wait, &wait);
while (1) {
subdevice = -1;
read_lock(&card->ctl_files_rwlock);
list_for_each_entry(kctl, &card->ctl_files, list) {
if (kctl->pid == task_pid(current)) {
subdevice = kctl->prefer_rawmidi_subdevice;
if (subdevice != -1)
break;
}
}
read_unlock(&card->ctl_files_rwlock);
subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_RAWMIDI);
err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
if (err >= 0)
break;
@ -862,7 +852,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
if (get_user(val, (int __user *)argp))
return -EFAULT;
control->prefer_rawmidi_subdevice = val;
control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val;
return 0;
}
case SNDRV_CTL_IOCTL_RAWMIDI_INFO: