pcm.headset { # The "plug" plugin is misleadingly named; it has nothing to do with being # a plugin. What it should really be named is the "auto-re-sample" plugin. # It allows this device to be used at any sample rate. type plug # A "plug" plugin needs a "slave" PCM, which is a definition of another # "pcm" configuration that corresponds to the device which will be # re-sampled to. slave.pcm { # The "asym" plugin is a virtual "asymmetric" device; where capture and # playback on the same virtual device may be going to two different # underlying devices. In fact, we are sending both playback and # capture to the same device in this case, but we need to use two # different plugins ("dmix" and "dsnoop") to do it. It requires a # "playback.pcm" and "capture.pcm" argument to describe the two halves # of the device. type asym playback.pcm { # The "dmix" plugin is our automatic playback-mixing device. type dmix # Now, need to specify a number to identify the shared memory area # where this dmix plugin will do its mixing. This is meaningless, # it just needs to be unique. ipc_key 4321 # When naming that shared-memory area, don't add the current user's # ID in there, so that other users can find it. ipc_key_add_uid false # Allow other users in my group to access that area so they can # also open this device. This is especially important if you want # to put this device into a global configuration file. ipc_perm 0660 # Similar to "plug", "dmix" needs a description of the actual audio # device it's doing mixing to. The usual ALSA idiom is to use # 'hw:2' or somesuch, but that's not very stable in the face of # unplugging USB devices, rebooting, or moving the device to a # different machine. This identifier appears to be unique, and you # can get it from 'aplay -l'. slave.pcm "hw:U0x47f0xad01" } capture.pcm { # This is the recording half of the device. The "dsnoop" plugin is # just like "dmix" except it does capture rather than playback. type dsnoop ipc_key 5432 ipc_key_add_uid false ipc_perm 0660 slave.pcm "hw:U0x47f0xad01" } } } # Finally, we need to describe a 'control' interface (for volume knobs and # such) whose name corresponds exactly. This is important because VoIP # programs and the like will assume they can tweak the volume on their input or # output devices by looking for a similarly-named ctl device once they have a # pcm. # Unlike with playback and capture, ALSA *does* allow multiple processes to # access the same control device simultaneously, so we don't need to do # anything special here. ctl.headset { type hw card "U0x47f0xad01" } # A list of 'hooks' is effectively a list of additional files to load. I don't # really understand the nuances of 'func' vs. '@func', but this seems to work. @hooks [ { func load files [ { # I'm loading exactly one file, based on an environment # variable. If ALSA_BONUS_CONFIG is defined, then its value # goes into this list. @func getenv vars [ ALSA_BONUS_CONFIG ] default { # Otherwise, I look for a file named ".asoundrc.empty" in # the user's home directory (or /tmp, if the user has no # home directory, although that isn't likely). This file # should be present but empty, but if it doesn't exist the # only consequence will be some ugly warning messages from # programs that use ALSA. @func concat strings [ { @func getenv vars [ HOME ] default "/tmp" } "/.asoundrc.empty" ] } } ] } ]