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