summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pcm/sound.c')
-rw-r--r--sys/dev/sound/pcm/sound.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index caa7841..958065f 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -51,7 +51,7 @@ int pcm_veto_load = 1;
int snd_unit = -1;
TUNABLE_INT("hw.snd.default_unit", &snd_unit);
-static int snd_unit_auto = 0;
+static int snd_unit_auto = -1;
TUNABLE_INT("hw.snd.default_auto", &snd_unit_auto);
SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RW,
&snd_unit_auto, 0, "assign default unit to a newly attached device");
@@ -443,6 +443,7 @@ sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm))
return EINVAL;
snd_unit = unit;
+ snd_unit_auto = 0;
}
return (error);
}
@@ -737,6 +738,32 @@ pcm_killchan(device_t dev)
return (pcm_chn_destroy(ch));
}
+static int
+pcm_best_unit(int old)
+{
+ struct snddev_info *d;
+ int i, best, bestprio, prio;
+
+ best = -1;
+ bestprio = -100;
+ for (i = 0; pcm_devclass != NULL &&
+ i < devclass_get_maxunit(pcm_devclass); i++) {
+ d = devclass_get_softc(pcm_devclass, i);
+ if (!PCM_REGISTERED(d))
+ continue;
+ prio = 0;
+ if (d->playcount == 0)
+ prio -= 10;
+ if (d->reccount == 0)
+ prio -= 2;
+ if (prio > bestprio || (prio == bestprio && i == old)) {
+ best = i;
+ bestprio = prio;
+ }
+ }
+ return (best);
+}
+
int
pcm_setstatus(device_t dev, char *str)
{
@@ -770,8 +797,12 @@ pcm_setstatus(device_t dev, char *str)
PCM_UNLOCK(d);
- if (snd_unit < 0 || snd_unit_auto != 0)
+ if (snd_unit_auto < 0)
+ snd_unit_auto = (snd_unit < 0) ? 1 : 0;
+ if (snd_unit < 0 || snd_unit_auto > 1)
snd_unit = device_get_unit(dev);
+ else if (snd_unit_auto == 1)
+ snd_unit = pcm_best_unit(snd_unit);
return (0);
}
@@ -1113,7 +1144,6 @@ pcm_unregister(device_t dev)
struct snddev_info *d;
struct pcm_channel *ch;
struct thread *td;
- int i;
td = curthread;
d = device_get_softc(dev);
@@ -1216,21 +1246,9 @@ pcm_unregister(device_t dev)
sndstat_release(td);
if (snd_unit == device_get_unit(dev)) {
- /*
- * Reassign default unit to the next available dev, but
- * first, reset snd_unit to something ridiculous.
- */
- snd_unit = -1;
- for (i = 0; pcm_devclass != NULL &&
- i < devclass_get_maxunit(pcm_devclass); i++) {
- if (device_get_unit(dev) == i)
- continue;
- d = devclass_get_softc(pcm_devclass, i);
- if (PCM_REGISTERED(d)) {
- snd_unit = i;
- break;
- }
- }
+ snd_unit = pcm_best_unit(-1);
+ if (snd_unit_auto == 0)
+ snd_unit_auto = 1;
}
return (0);
OpenPOWER on IntegriCloud