svn commit: r222826 - head/sys/dev/sound/pcm
Alexander Motin
mav at FreeBSD.org
Tue Jun 7 17:01:52 UTC 2011
Author: mav
Date: Tue Jun 7 17:01:52 2011
New Revision: 222826
URL: http://svn.freebsd.org/changeset/base/222826
Log:
Make automatic hw.snd.default_unit choice a bit more intelligent. Instead
of just setting it to the first registered device, reevaluate it for each
device registered, trying to choose best candidate, unless one was forced.
For now use such preference order: play&rec, play, rec.
As side effect, this should workaround the situation when HDMI audio output
of the video card, usually not connected to anything, becomes default, that
requires manual user intervention to make sound working. If at some point
this won't be enough, we can try to fetch some additional priority flags
from the device driver.
Modified:
head/sys/dev/sound/pcm/sound.c
Modified: head/sys/dev/sound/pcm/sound.c
==============================================================================
--- head/sys/dev/sound/pcm/sound.c Tue Jun 7 16:23:27 2011 (r222825)
+++ head/sys/dev/sound/pcm/sound.c Tue Jun 7 17:01:52 2011 (r222826)
@@ -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_HANDLE
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);
More information about the svn-src-all
mailing list