Preset handling interface

From Buzztrax

Jump to: navigation, search

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).

iface design

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

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

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].

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?

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)


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

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 '/')

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

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.

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

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 }

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.
Support Us

Collaboration

GStreamer Logo
Become a Friend of GNOME
Linux Sound Logo
MediaWiki
Valgrind
GNU Library Public Licence
GNU Free Documentation License 1.2