Goals - Logical device based policy decision making was one of our main motivation to utilize UCM. Use of logical devices allows abstract policy rules that are independent of the actual hardware. The policy decisions are made in terms of 'speakers', 'headsets', 'HDMI' connected external TV sets etc. instead of dealing with sinks like 'alsa_output.usb-Logitech_Logitech_USB_Headset-00-Headset.analog-stereo'. The main idea is to prototype a device-manager that would accept logical device names (instead of sink names) for role based preferences. - Profiles and ports should be automatically added based on the UCM configuration. - For notification purposes policy might need to route certain streams to both headphones and speakers, in other words we would need in some cases ports that represent roots to dual devices. Ports for such dual devices should also be added automatically. - On the other hand it did not appeared to be a good idea to break existing things so * the UCM based configuration should integrate smootly to the existing configuration and co-exist with it. * the automatically generated profile/port names should make sense when showing up in the existing desktop applets for audio control. * the UCM based configuration should utilize upcoming port detection mechanism (ie. work with David Henningsson's Jack Detection Patches) - Due to the complexity of the things I wanted to build a prototype that could serve as a basis for discussing the possible issues, challenges etc. Another goal with prototyping was to gain deeper understanding of UCM and generate some requirements or patches to the ALSA folks if needed. The prototype - If the ALSA card has corresponding UCM configuration (ie. a directory under /usr/share/alsa/ucm) the UCM configuration will be used. Otherwise business is as usual. I did not bother to add module parameters to the alsa card that would enforce/disable what method should be used. Such mechanisms can be easily added later on however. - The automatically generated profiles are like {verb}-{direction}-for-{modifier}[-and-{modifier}] e.g. profile name 'hifi-output-for-music' and in the sound applets it would show up as 'music playback in HiFi mode' - The generated ports are like {device}-{verb}-{direction} e.g. port name 'Headset-HiFi-output' and in the sound applets it would show up as 'Headset' - If the UCM configuration contains a "Play Tone" modifier a corresponding dual device port is automaticaly generated based on the 'SupportedDevice' entries. The pattern is {device}+Speaker-{verb}-output For the above example the dual device would be 'Headset+Speaker-HiFi-output' and in the sound applet it would appear as 'Headset+Speaker' - The proto is built top on David's earlier patches where the actual jack detection worked. We needed some extra entries in the UCM values: InputDeviceName "HDA Intel PCH Headphone" InputDeviceCode "Headphone" They seemed to work. However, the input device based jack detection is history, and we have new patches to work top on. The old one is still there behind the INPUT_DEVICE_BASED_JACK_DETECTION define. - currently we have two patches: * '0001-new-files-for-ALSA-UCM-support.patch' that contains alsa-ucm.[hc] that is basic UCM stuff * '0002-chnages-in-pulseaudio-alsa-module-to-support-UCM.patch' that contains the modifications needed to integrate the UCM stuff. Basically those changes are: - some new members to the data structures to store UCM related things - some static alsa mixer functions needed to be accessed from alsa-ucm.c; so those are not static any more and prefixed with 'pa_alsa_'. - the logic to call the UCM stuff. - we also prototyped UCM configuration to a 'HDA Intel PCH' card. - this is just a prototype to see how things might work. So it might leak, crash, etc. The next step is to see what kind of facelift the device manager might need to have to support logical device based routing and to support dual devices (that are not all ALSA) e.g. route ringtone to a bluetooth headset and to the 'speaker'. UCM config files here are the files we used for testing (the author was Jaska Uimonen) ----------- /usr/share/alsa/ucm/HDA Intel PCH/HDA Intel PCH.conf -------------- # UCM configuration for HDA Intel PCH SectionUseCase."HiFi" { File "hifi" Comment "Play HiFi quality music." } ValueDefaults { PlaybackCTL "hw:PCH" CaptureCTL "hw:PCH" } SectionDefaults [ cdev "hw:PCH" exec "echo Setting defaults for PCH" cset "name='Master Playback Volume' 0,0" cset "name='Master Playback Switch' off,off" cset "name='Headphone Playback Volume' 0,0" cset "name='Headphone Playback Switch' off,off" cset "name='PCM Playback Volume' 0,0" cset "name='Front Mic Boost Volume' 0,0" cset "name='Front Mic Playback Volume' 0,0" cset "name='Front Mic Playback Switch' off,off" cset "name='Front Playback Volume' 0,0" cset "name='Front Playback Switch', off,off" cset "name='Surround Playback Volume' 0,0" cset "name='Surround Playback Switch' off,off" cset "name='Center Playback Volume' 0,0" cset "name='Center Playback Switch' off,off" cset "name='LFE Playback Volume' 0,0" cset "name='LFE Playback Switch' off,off" cset "name='Line Playback Volume' 0,0" cset "name='Line Playback Switch' off,off" cset "name='Capture Volume' 0,0" cset "name='Capture Switch' off,off" cset "name='Capture Volume',index=1, 0" cset "name='Capture Switch',index=1, off,off" cset "name='IEC958 Default PCM Playback Switch', off" cset "name='IEC958 Playback Switch', off" cset "name='IEC958 Playback Switch',index=1, off" cset "name='Auto-Mute Mode', 0" cset "name='Input Source', 0" cset "name='Input Source',index=1, 0" cset "name='Rear Mic Boost Volume', 0" cset "name='Rear Mic Playback Volume' 0,0" cset "name='Rear Mic Playback Switch' off,off" cset "name='Side Playback Volume' 0,0" cset "name='Side Playback Switch' off,off" ] ------------------ /usr/share/alsa/ucm/HDA Intel PCH/hifi -------------------- # Use case Configuration for HDA Intel PCH / HiFi Music SectionVerb { EnableSequence [ exec "echo HiFi enable sequence" ] DisableSequence [ exec "echo HiFi disable sequence" cdev "hw:PCH" ] # QoS and ALSA PCMs Value { TQ Music CapturePCM "hw:PCH" PlaybackPCM "hw:PCH" } } SectionDevice."Headphones" { Comment "PCH 3.5mm Headphone" EnableSequence [ exec "echo Enabling headphones" cdev "hw:PCH" cset "name='Headphone Playback Switch' on,on" cset "name='Master Playback Switch' on,on" cset "name='Master Playback Volume' 64,64" cset "name='PCM Playback Volume' 255,255" ] DisableSequence [ exec "echo Disabling headphones" cdev "hw:PCH" cset "name='Headphone Playback Volume' 0,0" cset "name='Master Playback Volume' 0,0" cset "name='PCM Playback Volume' 0,0" cset "name='Headphone Playback Switch' off,off" cset "name='Master Playback Switch' off,off" ] Value { PlaybackVolume "Headphone" CaptureVolume "Capture" InputDeviceName "HDA Intel PCH Headphone" InputDeviceCode "Headphone" } } SectionDevice."Headset" { Comment "PCH 3.5mm Headset" EnableSequence [ exec "echo Enabling headset" cdev "hw:PCH" cset "name='Headphone Playback Switch' on,on" cset "name='Master Playback Switch' on,on" cset "name='Master Playback Volume' 64,64" cset "name='PCM Playback Volume' 255,255" ] DisableSequence [ exec "echo Disabling headset" cdev "hw:PCH" cset "name='Headphone Playback Volume' 0,0" cset "name='Master Playback Volume' 0,0" cset "name='PCM Playback Volume' 0,0" cset "name='Headphone Playback Switch' off,off" cset "name='Master Playback Switch' off,off" ] Value { PlaybackVolume "Headphone" CaptureVolume "Capture" InputDeviceName "HDA Intel PCH Headphone" InputDeviceCode "Headphone" } } SectionDevice."Speaker" { Comment "PCH external speakers" EnableSequence [ exec "echo Enabling Speakers" cdev "hw:PCH" cset "name='Front Playback Switch' on,on" cset "name='Master Playback Switch' on,on" cset "name='Master Playback Volume' 64,64" cset "name='PCM Playback Volume' 255,255" ] DisableSequence [ exec "echo Disabling Speakers" cdev "hw:PCH" cset "name='Front Playback Volume' 0,0" cset "name='Front Playback Switch' off,off" cset "name='Master Playback Volume' 0,0" cset "name='Master Playback Switch' off,off" cset "name='PCM Playback Volume' 0,0" ] Value { PlaybackVolume "Front" } } SectionModifier."Play Tone" { Comment "Playing notifications dual" SupportedDevice [ "Headset" "Headphones" ] EnableSequence [ exec "echo 'Go to Speaker and Headset mode'" cset "name='Front Playback Switch' on,on" cset "name='Front Playback Volume' 255,255" cset "name='Headphone Playback Switch' on,on" cset "name='Headphone Playback Volume' 64,64" ] DisableSequence [ exec "echo 'Leave Speaker & Headset mode'" cset "name='Front Playback Volume' 0,0" cset "name='Front Playback Switch' off,off" cset "name='Headphone Playback Switch' off,off" cset "name='Headphone Playback Volume' 0,0" ] Value { PlaybackVolume "Master" } } SectionModifier."Play Music" { Comment "Playing music" SupportedDevice [ "Headphones" "Headset" "Speaker" ] EnableSequence [ exec "echo 'Enable music playback'" ] DisableSequence [ exec "echo 'Disable music playback'" ] } SectionModifier."Capture Music" { Comment "Playing music" SupportedDevice [ "Headset" ] EnableSequence [ exec "echo 'Enable music capturing'" ] DisableSequence [ exec "echo 'Disable music capturing'" ] }