On Thu, 2013-04-04 at 10:32 +0200, David Henningsson wrote: > With all these configuration discussions, there's one more aspect I'd > like to throw into the mix. > > We have a lot of global parameters that should really be configured by > card, or by sink/source. > > In daemon.conf, we have these: > > ; default-sample-format = s16le > ; default-sample-rate = 44100 > ; alternate-sample-rate = 48000 > ; default-sample-channels = 2 > ; default-channel-map = front-left,front-right > ; default-fragments = 4 > ; default-fragment-size-msec = 25 > > ...all the above should be configurable per sink/source, rather than set > globally. Maybe you can override some of them by loading a sink or > source module manually, but then you lose the hotplug ability, so that's > not a good option. > > And all the parameters to module-udev-detect: > > tsched=<enable system timer based scheduling mode?> > tsched_buffer_size=<buffer size when using timer based scheduling> > fixed_latency_range=<disable latency range changes on underrun?> > ignore_dB=<ignore dB information from the device?> > deferred_volume=<syncronize sw and hw volume changes in IO-thread?> > use_ucm=<use ALSA UCM for card configuration?> > > All these are really per card or per sink/source [1]. The only reason we > have these parameters in module-udev-detect, is because it's simpler to > configure things from default.pa that way. That's a bit stupid IMO. Yes, it's a bit stupid. > When you're thinking about configuration interfaces and such, would it > be possible to design in a solution to this too? :-) I have thought about this lately and also not-so-lately. I'll present my latest design idea, which I'm sure will again be shot down as over-engineered... I'd like to have these per-sink options in configuration files, like this: [AlsaSink foo] scheduling-type = interrupt-driven There's a problem: what should "foo" be? The obvious answer is that it should be the sink name, but I don't really like that, because it looks like we occasionally change the naming scheme, which breaks configuration files if they use sink names for identification. I propose that we don't match the objects in the configuration file with runtime objects using the identifier in the configuration file ("foo" in the example). Instead, those identifiers only exist to tell the different objects of the same class apart. For matching with runtime objects, "identification properties" are used, as opposed to "normal properties" and "pointer properties" (there's no syntactic difference). "scheduling-type" is a normal property, i.e. something that the user might want to change. Pointer properties are used just for linking objects in the configuration file. An identification property would be something like serial number or vendor name: something that we can expect to never change, unlike our sink naming scheme. A serial number or vendor name should be a property of the card, not sink, though, so I'll expand the example: [AlsaCard c] serial = 123 # identification property, matched with udev data ports = p1 p2 # pointer property [AlsaPort p1] name = analog-output-speaker # identification property, # matched with names of # runtime port objects sinks = s1 # pointer property [AlsaPort p2] name = analog-output-headphones sinks = s2 [AlsaSink s1] # There's no need for any identification properties, because p1 # has only one sink. Having multiple sinks for one port is very # rare with alsa, but not impossible: remember that N9 example # where headphones could be used via two different alsa sinks? # I'm not sure what data should be used for identification in # that case, but it could be e.g. the alsa device number. scheduling-type = interrupt-driven # normal property [AlsaSink s2] scheduling-type = timer-driven This adds some complexity compared to just using the card/port/sink names for identification. If "we may change the naming scheme" is not a good enough reason for this complexity, I'll give another use case: two identical USB sound cards. We may have all possible identification information available to be used in the card name, but the problem is that it's all identical for the two cards, and the user wants to use both cards at the same time, and to configure them differently, and the configuration should be remembered. This can be solved with using the USB bus address (or whatever it's called) in the card name, but that isn't a good general solution, because those users that only have one USB sound card want PulseAudio to recognize it as the same card regardless of the USB port that it's plugged in. The identification properties can be used to solve this problem: the bus addresses wouldn't be added to the configuration file until PulseAudio detects that there are two sound cards in the system that can't be distinguished in any other way (yes, I expect the server to modify the configuration file at runtime). After the bus addresses have been added to the configuration, the configuration becomes tied to the USB port (for that particular sound card model only). -- Tanu