svn commit: r236745 - stable/8/sys/dev/sound/pcm
Alexander Motin
mav at FreeBSD.org
Fri Jun 8 11:58:29 UTC 2012
Author: mav
Date: Fri Jun 8 11:58:28 2012
New Revision: 236745
URL: http://svn.freebsd.org/changeset/base/236745
Log:
MFC r222826:
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:
stable/8/sys/dev/sound/pcm/sound.c
Directory Properties:
stable/8/sys/ (props changed)
Modified: stable/8/sys/dev/sound/pcm/sound.c
==============================================================================
--- stable/8/sys/dev/sound/pcm/sound.c Fri Jun 8 11:53:51 2012 (r236744)
+++ stable/8/sys/dev/sound/pcm/sound.c Fri Jun 8 11:58:28 2012 (r236745)
@@ -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-stable-8
mailing list