Hi, I have written a proposal about a new configuration system to the wiki: http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/ConfigurationSystem
For easier commenting on the mailing list, I'll copy the wiki markup here: = Configuration System = Status: '''draft'''. This is the initial proposal by Tanu, so there may be many opinions that are only held by him. The idea is to keep this page as a reference while discussing the configuration system, and record the results of the discussion here. == Introduction == One of the [[Software/PulseAudio/GSoC2012|Google Summer of Code project ideas for 2012]] was a "configuration system". The configuration system was not among the selected projects, but the system was seen as a priority, so the plan now is to design and implement the important bits (the client API and the server-side infrastructure) ourselves within May 2012 or so (the reason for the tight schedule is that we'd like the GSoC students to benefit from this new system). Porting the existing configuration to the new system is not a matter of urgency. All the existing stuff has to be kept in mind while doing the design, though, so that the porting work is possible to do when that time comes. The configuration system should make it easy to implement runtime-modifiable persistent configuration options in the core and modules. Currently that involves writing protocol extensions (for multiple protocols, if you aim for completeness) and managing the data storage yourself. The goal is to reduce that work, and also to make life easier for applications. There are some notes from previous discussion at [[http://piratepad.net/BLGxYG2lf3]]. == Goals == * The client API should be easy to use. * The set of supported configuration options should be easy to extend. * No protocol extensions. * Make it as easy as possible to add a new option. * Support also other things than statically named global options. * For example, options for ports requires dynamic keys to identify the port. * We want (or do we?) to support also persistent data that is less configuration-like, like the stream-restore database or the equalizer data. * Support change notifications both at client side and at server side. * Support reading and modifying client.conf. (?) == Design == The configuration system stores "options". Options have a value and a (multi-part) identifier. The options need at least two pieces of identification information: the object id and the option name. For example, the maximum volume of a port could have object id "foocard:barport" and option id "max-volume". Objects have also a type (e.g. card, port, stream-restore entry). The object ids could have the type information encoded into them, or the type could be a separate identifier. A separate identifier is better, because otherwise you need to store the known options for each object, while it would be easier and more efficient to store the known options for the type of the objects. So, option values can be referenced by giving three identifiers: object type, object id and option name. These can be encoded in a single key string (e.g. "core.Port/cardname:portname/max-volume") if so desired, but the configuration system has to have concepts for these three things. We might want to also have a type namespace concept, for example to split the configuration into one file per namespace (core could have its own namespace and each module could have theirs). In the client API it's probably best to encode the namespace into the object type. >From the configuration system's point of view, all option values are strings. Adding type information would add a lot of complexity and not have very big benefits (is it so?). The options will of course have an implicit type to be useful. The actual users of the options (applications and code in the server) have to validate the values themselves. This means that we should provide parsing functions for clients, at least for any complex types, but preferably also for simple stuff like integers. At server side, values are validated when they are read from the disk and when they are set by clients or by some other code in the server than the "option owner". Since validation is done by the option owner code, and since modules can implement options, some of the options can be only validated when a specific module is loaded. The way to handle the case, where an application sets an option for a module that is not loaded, is to refuse to set any such options. If the module isn't loaded, from the configuration system's point of view the option doesn't exist. == Client API == This is how the client API will look like: {{{ typedef void (*pa_server_configuration_cb_t)( pa_context *c, const char *object_type, const char *object_id, const char *option, const char *value, int eol, void *userdata); pa_operation *pa_server_configuration_set( pa_context *c, const char *object_type, const char *object_id, const char *option, const char *value, pa_context_success_cb_t cb, void *userdata); /* object_type, object_id and option can be NULL for wildcard selection. If * object_type is NULL, then all other identifiers have to be NULL also. In * case of wildcards, the callback may get called multiple times. The last call * has the object_type, object_id, option and value parameters of * pa_server_configuration_cb_t set to NULL and eol set to 1. */ pa_operation *pa_server_configuration_get( pa_context *c, const char *object_type, const char *object_id, const char *option, pa_server_configuration_cb_t cb, void *userdata); /* The wildcard rules described with pa_server_configuration_get apply with * the subscribe items too. */ typedef struct pa_server_configuration_subscribe_item { const char *object_type; const char *object_id; const char *option; } pa_server_configuration_subscribe_item; /* The items parameter is an array with n_items elements. If there are multiple * subscribe items given, then the subscribe callback is called when any of the * items match the event. If called multiple times, the subscribe items of the * last call will replace all the previous items. */ pa_operation *pa_server_configuration_subscribe( pa_context *c, const pa_server_configuration_subscribe_item *items, unsigned n_items, pa_context_success_cb_t cb, void *userdata); /* When there are configuration changes that match the subscription, the * callback that is set here will be called multiple times. The last call has * the object_type, object_id, option and value parameters of * pa_server_configuration_cb_t set to NULL and eol set to 1. */ void pa_server_configuration_set_subscribe_callback( pa_context *c, pa_server_configuration_cb_t cb, void *userdata); }}} There has been some discussion about supporting also reading and modifying client.conf. client.conf is not centrally managed, it stores simple key-value pairs with static keys, it doesn't support change notifications and working with it probably doesn't require an asynchronous API. Therefore, the API is quite different, and maybe it doesn't need to be a part of this configuration system effort. The main point is that we '''might''' want such API now or in the future, so we should think how the configuration system API can co-exist with the client.conf API. That means basically that we probably don't want to use "pa_configuration_" as the server configuration prefix, because it's too generic. === Parsing functions === TODO == Storage format == TODO I like ini files as described here: http://article.gmane.org/gmane.comp.audio.pulseaudio.general/12845 --Tanu == Open issues == The namespace concept might need some refinement. The idea of splitting the storage into one file per module sounds nice, but it might not sense to dedicate each object type to one module. Modules may want add options to their own object types and to core object types, and possibly also to other modules' types. Let's say there's an object type "Card" in namespace "core", i.e. "core.Card". The alsa modules might want to add an option to core.Cards for enabling and disabling timer-based scheduling. Maybe the options should have namespacing too, i.e. the new option would be "core.Card/foocard/alsa.tsched"? Would every option name have a namespace part? That would be very ugly. How would this example be handled in storage? Is splitting the storage into many files a bad idea anyway? Is there need for adding an API for clients for querying whether a specific option is supported? Such API could be added also later, if we are not certain yet. One limitation with this proposal is that the client API supports only modifying existing objects. For example, adding a new entry to stream-restore is not possible in a nice way. You could set an option of a non-existent object, but that would leave the other fields of the entry uninitialized. Maybe that's tolerable, but if we want to support object creation, it should probably be done in a better way. I'm a bit against supporting object creation through the configuration API. Protocol extensions are still needed for that then. And maybe exposing the stream-restore database to clients through the configuration API isn't so good idea in the first place. The storage part of the system could still be useful also for stream-restore. --Tanu _______________________________________________ pulseaudio-discuss mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
