diff options
-rw-r--r-- | sys/dev/sound/pcm/datatypes.h | 6 | ||||
-rw-r--r-- | sys/dev/sound/pcm/mixer.c | 75 | ||||
-rw-r--r-- | sys/dev/sound/pcm/mixer.h | 1 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.c | 13 |
4 files changed, 86 insertions, 9 deletions
diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h index 55f4111..bf6d73d 100644 --- a/sys/dev/sound/pcm/datatypes.h +++ b/sys/dev/sound/pcm/datatypes.h @@ -40,6 +40,10 @@ struct _snd_mixer { const char *name; void *devinfo; int busy; + int muted; + int hwvol_mixer; + int hwvol_step; + u_int32_t mute_level; u_int32_t devs; u_int32_t recdevs; u_int32_t recsrc; @@ -133,6 +137,8 @@ struct _snddev_info { void *devinfo; device_t dev; char status[SND_STATUSLEN]; + struct sysctl_ctx_list sysctl_tree; + struct sysctl_oid *sysctl_tree_top; }; /*****************************************************************************/ diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index b8bbef7..c9d4ae8 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -48,6 +48,20 @@ static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = { [SOUND_MIXER_OGAIN] = 50, }; +static char* snd_mixernames[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; + +static int +mixer_lookup(char *devname) +{ + int i; + + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + if (strncmp(devname, snd_mixernames[i], + strlen(snd_mixernames[i])) == 0) + return i; + return -1; +} + static int mixer_set(snd_mixer *mixer, unsigned dev, unsigned lev) { @@ -254,39 +268,82 @@ mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg) return ENXIO; } -static int hwvol_step = 5; -SYSCTL_INT(_hw_snd, OID_AUTO, hwvol_step, CTLFLAG_RW, &hwvol_step, 0, ""); +static int +sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) +{ + char devname[32]; + int error, dev; + snd_mixer *m; + + m = oidp->oid_arg1; + strncpy(devname, snd_mixernames[m->hwvol_mixer], sizeof(devname)); + error = sysctl_handle_string(oidp, &devname[0], sizeof(devname), req); + if (error == 0 && req->newptr != NULL) { + dev = mixer_lookup(devname); + if (dev == -1) + return EINVAL; + else + m->hwvol_mixer = dev; + } + return error; +} + +int +mixer_hwinit(device_t dev) +{ + snddev_info *d; + snd_mixer *m; -static int hwvol_mixer = SOUND_MIXER_VOLUME; -SYSCTL_INT(_hw_snd, OID_AUTO, hwvol_mixer, CTLFLAG_RW, &hwvol_mixer, 0, ""); + d = device_get_softc(dev); + m = d->mixer; + m->hwvol_mixer = SOUND_MIXER_VOLUME; + m->hwvol_step = 5; + SYSCTL_ADD_INT(&d->sysctl_tree, SYSCTL_CHILDREN(d->sysctl_tree_top), + OID_AUTO, "hwvol_step", CTLFLAG_RW, &m->hwvol_step, 0, ""); + SYSCTL_ADD_PROC(&d->sysctl_tree, SYSCTL_CHILDREN(d->sysctl_tree_top), + OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0, + sysctl_hw_snd_hwvol_mixer, "A", "") + return 0; +} void mixer_hwmute(device_t dev) { snddev_info *d; + snd_mixer *m; d = device_get_softc(dev); - mixer_set(d->mixer, hwvol_mixer, 0); + m = d->mixer; + if (m->muted) { + m->muted = 0; + mixer_set(m, m->hwvol_mixer, m->mute_level); + } else { + m->muted++; + m->mute_level = mixer_get(m, m->hwvol_mixer); + mixer_set(m, m->hwvol_mixer, 0); + } } void mixer_hwstep(device_t dev, int left_step, int right_step) { snddev_info *d; + snd_mixer *m; int level, left, right; d = device_get_softc(dev); - level = mixer_get(d->mixer, hwvol_mixer); + m = d->mixer; + level = mixer_get(m, m->hwvol_mixer); if (level != -1) { left = level & 0xff; right = level >> 8; - left += left_step * hwvol_step; + left += left_step * m->hwvol_step; if (left < 0) left = 0; - right += right_step * hwvol_step; + right += right_step * m->hwvol_step; if (right < 0) right = 0; - mixer_set(d->mixer, hwvol_mixer, left | right << 8); + mixer_set(m, m->hwvol_mixer, left | right << 8); } } diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h index b29cc14..f7ad35c 100644 --- a/sys/dev/sound/pcm/mixer.h +++ b/sys/dev/sound/pcm/mixer.h @@ -33,6 +33,7 @@ extern int mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg); extern int mixer_busy(snd_mixer *m, int busy); extern int mixer_isbusy(snd_mixer *m); +int mixer_hwinit(device_t dev); void mixer_hwmute(device_t dev); void mixer_hwstep(device_t dev, int left_step, int right_step); diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index 7e110772..6c8d468 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -302,6 +302,15 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) } else d->rec = NULL; + sysctl_ctx_init(&d->sysctl_tree); + d->sysctl_tree_top = SYSCTL_ADD_NODE(&d->sysctl_tree, + &sysctl__hw_snd_children, OID_AUTO, + device_get_nameunit(dev), CTLFLAG_RD, 0, ""); + if (!d->sysctl_tree_top) { + sysctl_ctx_free(&d->sysctl_tree); + goto no; + } + if (numplay == 0 || numrec == 0) d->flags |= SD_F_SIMPLEX; @@ -326,6 +335,10 @@ pcm_unregister(device_t dev) snddev_info *d = device_get_softc(dev); dev_t pdev; + sysctl_remove_oid(d->sysctl_tree_top, 1, 1); + d->sysctl_tree_top = NULL; + sysctl_ctx_free(&d->sysctl_tree); + r = 0; for (i = 0; i < d->chancount; i++) if (d->ref[i]) r = EBUSY; |