Preset handling interface
From Buzztard
ervinorobobo The objective is to be able to store and restore machine settings into/from a library. Therefore machines will implement the preset interface. There will be a default implementation for GStreamer plugins . Wrapper plugins like bml or lapdspa can override this.
Presets deal with dynamic element properties (controlable parameters). Its thinkable to have the same functionality for preferences (static settings).
Contents |
[edit] iface design
[edit] iface methods
This is the current API
GList* gst_preset_get_preset_names (GstPreset *self); gboolean gst_preset_load_preset (GstPreset *self, const gchar *name); // will overwrite a preset of the same name gboolean gst_preset_save_preset (GstPreset *self, const gchar *name); // will also overwrite a preset of the same name gboolean gst_preset_rename_preset (GstPreset *self, const gchar *old_name, const gchar *new_name); gboolean gst_preset_delete_preset (GstPreset *self, const gchar *name); gboolean gst_preset_set_meta (GstPreset *self,const gchar *name, const gchar *tag, gchar *value); gboolean gst_preset_get_meta (GstPreset *self,const gchar *name, const gchar *tag, gchar **value); void gst_preset_create_preset (GstPreset *self);
Something missing?
- import?
- or should we handle that with extra tools (users can upload their presets and they get merged into new releases)
- check if preset file is writable?
- should check for file and dir 8if there is no file yet).
- if file is not writeable, all editing will fail. the ui should make editing widget insensitive
[edit] iface properties
The iface currently does not have properties. These properties would imho be useful:
- preset-name (char *)
- then we could specify a preset via gst-launch
- preset-list (GList *)
- then UI can listen to notify::preset-list to hear about preset-changes
[edit] locking
Inside one process we need a lock for changing the list and a lock for changing a preset. Only list changes are notified. If we use filelocking + inotify this comes for free.
We also need to synchronize multiple applications writing to the presets. For that we can use flock(preset_fd, LOCK_EX); when writing. See [1] and koders.com search.
Inotify (man inotify) can be used to get a notice when a different process has changed the presets. See [2], [3].
[edit] thoughts
Should elements that want to use the default implementation, be required to specify the DATADIR? If they don't we could only handle presets in the homedir or use GStreamers DATADIR.
Using a preset-list property would not allow to maintain both presets and preferences. Or should we also have a prefs-list property?
[edit] formats
Buzz machines would support the buzz-machine binary preset format :). The presets are stored along with the dlls, but with the extension *.prs. When saving new presets and the directory is not writable, we might consider storing them elsewhere (HOMEDIR?).
GStreamer elements will use their own format:
- the format itself should be not binary (platform neutral)
- it should be easy and quick to parse
- we need subsections
- generic data for each preset (name, comments, tags)
- properties
- child-properties per child
- extra data
- what about a date-time stamp? - that could help with merging, given that the user has a proper clock setup.
- categories (under meta)
[edit] xml format
<presets version="0.10" element="GstSimSyn">
<preset name="bling">
<metadata>
<metaitem name="comment" value="short metallic tone"/>
<metaitem name="comment" lang="de" value="kurzer metallischer Klang"/>
<metaitem name="..." value="..."/>
</metadata>
<properties>
<property name="attack" value="0.1"/>
<property name="decay" value="0.1"/>
<property name="wave" value="saw"/>
</properties>
</preset>
<preset name="...>
...
</preset>
</presets>
- good
- clear structure
- established tools
- bad
- xml dependency
[edit] GKeyFile format
[_presets_] version=<gst-major-minor> element=<element name> [<presetname>] _name[lang]=<translated preset name> _meta/comment=<comment> _meta/comment[lang]=<tranlated comment> <property>=<value> <child>/<property>=<value> [<presetname>] ... |
[_presets_] version=0.10 element=GstSimSyn [bling] _name[de]=Bling _meta/comment=short metallic tone _meta/comment[de]=kurzer metallischer Klang attack=0.1 decay=0.1 wave=saw voice0/volume=100 [...] ... |
- good
- parser is part of glib
- bad
- format is not really suited (need to use a special character for private stuff '_' and hierarchies '/')
[edit] own format
<id> <<gst-major-minor> <element name> <presetname> [<lang>]:<translated presetname> <meta>:<value> <meta>[<lang>]:<translated value> <property>=<value> <property>[<child>]=<value> <presetname> ... |
GStreamer Presets 0.10 GstSimSyn bling [de]:Bling meta:short metalic sound meta[de]:kurzer metallischer Klang attack=0.1 volume[voice0]=100 |
- good
- quick to read
- no dependency
- bad
- new format
- quite ad-hoc
[edit] system wide & use local
The implementation needs to handle the layered storage, as a user application can't write to system files. Several desktop components follow the policy where local (files in user home dir) have precedence over system wide files.
[edit] version 1
When loading, it needs to load the systemwide settings and merge the user local settings on top of that. When saving it only saves the changed entries localy. Merging means to replace whole preset-entries if the exist localy.
1. install plugin, write system settings to /usr/share/gstreamer-0.10/...
sys = { a1, b1, c1 }
2. add a new setting in app and store to /home/user/.gstreamer-0.10/...
user = { d1 }
3. change setting 'c' in the app and store
user = { c2, d1 }
4. update plugin and write updated setting, it brings one changed 'a' and one new preset 'e'
sys = { a2, b1, c1, e1 }
Problems are:
- when saving, we need to figure which entries have been changed (change-flag)
- local presets shadow system ones
- user added one with a new name, later system bring one of that new name
- user changed one, update bring a change in the same one
[edit] version 2
When loading it checks for a local first, if not found it loads the system wide. When saving it saves locally.
1. install plugin, write system settings to /usr/share/gstreamer-0.10/...
sys = { a1, b1, c1 }
2. add a new setting in app and store to /home/user/.gstreamer-0.10/...
user = { a1, b1, c1, d1 }
3. change setting 'c' in the app and store
user = { a1, b1, c2, d1 }
4. update plugin and write updated setting, it brings one changed 'a' and one new preset 'e'
sys = { a2, b1, c1, e1 }
Problems are:
- we need to detect a newer system wide config and then merge changes with the local one
- how can be find those presets that have change in the system update
- how to detects and handle conflicts (presets has been changed locally and updated in the system)
5. user starts app again, sys-presets are newer then user ones -> merge (update 'a', add 'e')
user = { a2, b1, c2, d1, e1 }
[edit] questions
- Do we need hierarchies for presets (preset-names are paths like "bass/plucked")?
- Do we need additional meta data per preset (comment, author). Buzz presets ave a comment. This might be useful when searching for presets.



