[beast/wip/soundfont: 825/832] Merge branch 'master' of github.com/tim-janik/beast into soundfont



commit 097d42eb78bb563bb1686993ab6af6327a32e084
Merge: b61afd0 a613470
Author: Stefan Westerfeld <timj gnu org>
Date:   Wed Sep 21 20:28:31 2016 +0200

    Merge branch 'master' of github.com/tim-janik/beast into soundfont
    
    This merge creates a version of the soundfont branch that cleanly applies
    to the current master branch.

 .travis.docker                                  |   91 +
 .travis.yml                                     |   78 +
 HACKING.md                                      |   71 +
 Makefile.am                                     |   88 +-
 Makefile.decl                                   |   64 +-
 NEWS                                            |   37 +
 README                                          |   42 -
 README.md                                       |   70 +
 autogen.sh                                      |   16 +-
 autotools/glib-gettext.m4                       |   17 +-
 beast-gtk/Makefile.am                           |  135 +-
 beast-gtk/bstapi.idl                            |  188 +
 beast-gtk/bstapp.cc                             |  175 +-
 beast-gtk/bstapp.hh                             |    4 +-
 beast-gtk/bstasciipixbuf.cc                     |    8 +-
 beast-gtk/bstasciipixbuf.hh                     |    2 +-
 beast-gtk/bstbseutils.cc                        |   66 +-
 beast-gtk/bstbseutils.hh                        |   17 +-
 beast-gtk/bstbuseditor.cc                       |    6 +-
 beast-gtk/bstbusmixer.cc                        |   25 +-
 beast-gtk/bstbusview.cc                         |   14 +-
 beast-gtk/bstcanvaslink.cc                      |   25 +-
 beast-gtk/bstcanvassource.cc                    |   86 +-
 beast-gtk/bstcluehunter.cc                      |   46 +-
 beast-gtk/bstdbmeter.cc                         |   30 +-
 beast-gtk/bstdefs.hh                            |    8 +-
 beast-gtk/bstdial.cc                            |   42 +-
 beast-gtk/bstdial.hh                            |    3 +-
 beast-gtk/bsteffectview.cc                      |  417 -
 beast-gtk/bsteffectview.hh                      |   62 -
 beast-gtk/bsteventroll.cc                       |  111 +-
 beast-gtk/bsteventroll.hh                       |   11 +-
 beast-gtk/bsteventrollctrl.cc                   |  284 +-
 beast-gtk/bsteventrollctrl.hh                   |    6 +-
 beast-gtk/bstfiledialog.cc                      |  208 +-
 beast-gtk/bstfiledialog.hh                      |   37 +-
 beast-gtk/bstgconfig.cc                         |   73 +-
 beast-gtk/bstgconfig.hh                         |    4 +-
 beast-gtk/bstitemseqdialog.cc                   |   16 +-
 beast-gtk/bstitemseqdialog.hh                   |   10 +-
 beast-gtk/bstitemview.cc                        |   45 +-
 beast-gtk/bstitemview.hh                        |    1 +
 beast-gtk/bstkeybindings.cc                     |   99 +-
 beast-gtk/bstkeybindings.hh                     |   14 +-
 beast-gtk/bstknob.cc                            |   26 +-
 beast-gtk/bstlogadjustment.cc                   |   16 +-
 beast-gtk/bstmain.cc                            |  766 +-
 beast-gtk/bstmenus.cc                           |   22 +-
 beast-gtk/bstmenus.hh                           |    2 +-
 beast-gtk/bstmsgabsorb.cc                       |  211 +-
 beast-gtk/bstmsgabsorb.hh                       |   11 +-
 beast-gtk/bstparam-color-spinner.cc             |    9 +-
 beast-gtk/bstparam-item-seq.cc                  |   14 +-
 beast-gtk/bstparam-note-spinner.cc              |    9 +-
 beast-gtk/bstparam-proxy.cc                     |    8 +-
 beast-gtk/bstparam-searchpath.cc                |    5 +-
 beast-gtk/bstparam.cc                           |  158 +-
 beast-gtk/bstparam.hh                           |    2 +
 beast-gtk/bstparamview.cc                       |   80 +-
 beast-gtk/bstpartdialog.cc                      |   77 +-
 beast-gtk/bstpartdialog.hh                      |    5 +-
 beast-gtk/bstpartview.cc                        |   18 +-
 beast-gtk/bstpatterncolumns.cc                  |  131 +-
 beast-gtk/bstpatternctrl.cc                     |  195 +-
 beast-gtk/bstpatternview.cc                     |   70 +-
 beast-gtk/bstpatternview.hh                     |    5 +-
 beast-gtk/bstpianoroll.cc                       |  139 +-
 beast-gtk/bstpianoroll.hh                       |   13 +-
 beast-gtk/bstpianorollctrl.cc                   |  326 +-
 beast-gtk/bstpianorollctrl.hh                   |    6 +-
 beast-gtk/bstplayback.cc                        |   52 +-
 beast-gtk/bstplayback.hh                        |    4 +-
 beast-gtk/bstplaylist.cc                        |  554 -
 beast-gtk/bstplaylist.hh                        |   53 -
 beast-gtk/bstpreferences.cc                     |   95 +-
 beast-gtk/bstprocbrowser.cc                     |  257 -
 beast-gtk/bstprocbrowser.hh                     |   57 -
 beast-gtk/bstprocedure.cc                       |   32 +-
 beast-gtk/bstprofiler.cc                        |    2 +-
 beast-gtk/bstprojectctrl.cc                     |   30 +-
 beast-gtk/bstprojectctrl.hh                     |    5 +-
 beast-gtk/bstqsampler.cc                        |  109 +-
 beast-gtk/bstqsampler.hh                        |   17 +-
 beast-gtk/bstrackeditor-covers.cc               |  177 -
 beast-gtk/bstrackeditor.cc                      |  297 -
 beast-gtk/bstrackeditor.hh                      |   55 -
 beast-gtk/bstrackitem.cc                        |  248 -
 beast-gtk/bstrackitem.hh                        |   48 -
 beast-gtk/bstracktable.cc                       | 1001 -
 beast-gtk/bstracktable.hh                       |   96 -
 beast-gtk/bstrackview.cc                        |  252 -
 beast-gtk/bstrackview.hh                        |   43 -
 beast-gtk/bstrecords.idl                        |  168 -
 beast-gtk/bstrtest.cc                           |    8 +-
 beast-gtk/bstsampleeditor.cc                    |   31 +-
 beast-gtk/bstscrollgraph.cc                     |   70 +-
 beast-gtk/bstscrollgraph.hh                     |    7 +-
 beast-gtk/bstsegment.cc                         |    6 +-
 beast-gtk/bstsequence.cc                        |   10 +-
 beast-gtk/bstservermonitor.cc                   |    6 +-
 beast-gtk/bstskinconfig.cc                      |   59 +-
 beast-gtk/bstskinconfig.hh                      |    8 +-
 beast-gtk/bstsnetrouter.cc                      |  248 +-
 beast-gtk/bstsnetrouter.hh                      |   12 +-
 beast-gtk/bstsnifferscope.cc                    |    4 +-
 beast-gtk/bstsplash.cc                          |    9 +-
 beast-gtk/bststest.cc                           |  754 -
 beast-gtk/bstsupershell.cc                      |   60 +-
 beast-gtk/bstsupershell.hh                      |    5 +-
 beast-gtk/bsttrackroll.cc                       |  128 +-
 beast-gtk/bsttrackroll.hh                       |   38 +-
 beast-gtk/bsttrackrollctrl.cc                   |  115 +-
 beast-gtk/bsttrackrollctrl.hh                   |    5 +-
 beast-gtk/bsttracksynthdialog.cc                |    8 +-
 beast-gtk/bsttracksynthdialog.hh                |    4 +-
 beast-gtk/bsttrackview.cc                       |   79 +-
 beast-gtk/bsttreestores.cc                      |   48 +-
 beast-gtk/bsttreestores.hh                      |    6 +-
 beast-gtk/bstusermessage.cc                     |   27 +-
 beast-gtk/bstusermessage.hh                     |    8 +-
 beast-gtk/bstutils.cc                           |  382 +-
 beast-gtk/bstutils.hh                           |   28 +-
 beast-gtk/bstwaveeditor.cc                      |   56 +-
 beast-gtk/bstwaveeditor.hh                      |    2 +-
 beast-gtk/bstwaveview.cc                        |    4 +-
 beast-gtk/bstxframe.cc                          |    4 +-
 beast-gtk/bstxkb.cc                             |   12 +-
 beast-gtk/bstzoomedwindow.cc                    |    2 +-
 beast-gtk/dialogs/.gitignore                    |    1 -
 beast-gtk/dialogs/Makefile.am                   |   24 -
 beast-gtk/gxk/Makefile.am                       |    4 +-
 beast-gtk/gxk/glewidgets.c                      |   20 +-
 beast-gtk/gxk/gxkaction.cc                      |   56 +-
 beast-gtk/gxk/gxkassortment.cc                  |   60 +-
 beast-gtk/gxk/gxkauxwidgets.cc                  |   15 +-
 beast-gtk/gxk/gxkcanvas.cc                      |   26 +-
 beast-gtk/gxk/gxkcellrendererpopup.cc           |   12 +-
 beast-gtk/gxk/gxkdialog.cc                      |   20 +-
 beast-gtk/gxk/gxkglobals.cc                     |   10 +-
 beast-gtk/gxk/gxkimagecache.cc                  |    4 +-
 beast-gtk/gxk/gxkled.cc                         |    4 +-
 beast-gtk/gxk/gxklistwrapper.cc                 |   53 +-
 beast-gtk/gxk/gxklistwrapper.hh                 |    2 +-
 beast-gtk/gxk/gxklogadjustment.cc               |   30 +-
 beast-gtk/gxk/gxkmenubutton.cc                  |    4 +-
 beast-gtk/gxk/gxknotebook.cc                    |    2 +-
 beast-gtk/gxk/gxkparam.cc                       |   86 +-
 beast-gtk/gxk/gxkpolygon.cc                     |   12 +-
 beast-gtk/gxk/gxkrackcovers.cc                  |    8 +-
 beast-gtk/gxk/gxkrackeditor.cc                  |   12 +-
 beast-gtk/gxk/gxkrackitem.cc                    |    4 +-
 beast-gtk/gxk/gxkracktable.cc                   |   12 +-
 beast-gtk/gxk/gxkradget.cc                      |   66 +-
 beast-gtk/gxk/gxkradgetfactory.cc               |    8 +-
 beast-gtk/gxk/gxkscrollcanvas.cc                |   64 +-
 beast-gtk/gxk/gxksimplelabel.cc                 |    6 +-
 beast-gtk/gxk/gxkspline.cc                      |   26 +-
 beast-gtk/gxk/gxkstatusbar.cc                   |    6 +-
 beast-gtk/gxk/gxkstock.cc                       |   24 +-
 beast-gtk/gxk/gxktest.cc                        |    3 -
 beast-gtk/gxk/gxktexttools.cc                   |   81 +-
 beast-gtk/gxk/gxkutils.cc                       |  183 +-
 beast-gtk/gxk/splinetest.cc                     |    9 +-
 beast-gtk/icons/Makefile.am                     |    2 +-
 beast-gtk/res/.gitignore                        |    1 +
 beast-gtk/res/Makefile.am                       |   20 +
 beast-gtk/{dialogs => res}/radgets-beast.xml    |    0
 beast-gtk/{dialogs => res}/radgets-standard.xml |    0
 beast-gtk/testgui.cc                            |   12 +-
 beast-gtk/tsmview.cc                            |   12 +-
 bse/Makefile.am                                 |  219 +-
 bse/bse.hh                                      |   20 +-
 bse/bseapi.idl                                  |  882 +-
 bse/bseautodoc.cc                               |  606 -
 bse/bsebasics.idl                               |  401 +-
 bse/bsebiquadfilter.cc                          |   12 +-
 bse/bseblockutils.cc                            |    2 +-
 bse/bsebus.cc                                   |  228 +-
 bse/bsebus.hh                                   |   33 +-
 bse/bsebus.proc                                 |  194 -
 bse/bsecategories.cc                            |   65 +-
 bse/bsecategories.hh                            |    1 -
 bse/bsecategories.proc                          |   81 +-
 bse/bsecompat.hh                                |    2 +-
 bse/bseconfig.h.in                              |    6 +-
 bse/bseconstant.cc                              |    2 +-
 bse/bsecontainer.cc                             |  198 +-
 bse/bsecontainer.hh                             |   14 +-
 bse/bsecontainer.proc                           |   35 +-
 bse/bsecontextmerger.cc                         |   28 +-
 bse/bsecontextmerger.hh                         |   12 +
 bse/bsecsynth.cc                                |   16 +
 bse/bsecsynth.hh                                |   23 +-
 bse/bsecsynth.proc                              |   11 -
 bse/bsecxxbase.cc                               |   14 +-
 bse/bsecxxclosure.cc                            |   12 +-
 bse/bsecxxmodule.cc                             |   12 +-
 bse/bsecxxmodule.hh                             |    2 +-
 bse/bsecxxplugin.hh                             |    2 +-
 bse/bsecxxutils.cc                              |    5 +-
 bse/bsecxxutils.hh                              |    6 +-
 bse/bsedatahandle-fir.cc                        |   18 +-
 bse/bsedatahandle-flac.cc                       |   30 +-
 bse/bsedatahandle-resample.cc                   |   26 +-
 bse/bsedatapocket.cc                            |  673 -
 bse/bsedatapocket.hh                            |   81 -
 bse/bsedatapocket.proc                          |  419 -
 bse/bsedefs.hh                                  |   15 +-
 bse/bsedevice.cc                                |   84 +-
 bse/bsedevice.hh                                |    8 +-
 bse/bseeditablesample.cc                        |   17 +-
 bse/bseeditablesample.hh                        |   12 +
 bse/bseeditablesample.proc                      |   82 +-
 bse/bseengine.cc                                |  177 +-
 bse/bseenginemaster.cc                          |  137 +-
 bse/bseenginemaster.hh                          |    8 +-
 bse/bseenginenode.hh                            |    2 +-
 bse/bseengineschedule.cc                        |  164 +-
 bse/bseengineutils.cc                           |   80 +-
 bse/bseenums.cc                                 |  125 +-
 bse/bseenums.hh                                 |  349 +-
 bse/bseenums.proc                               |   57 -
 bse/bsefilter-ellf.cc                           |   30 +-
 bse/bsefilter.hh                                |   18 +-
 bse/bsegconfig.cc                               |   16 +-
 bse/bseglobals.cc                               |    6 +-
 bse/bseglue.cc                                  |   37 +-
 bse/bseieee754.hh                               |    2 +-
 bse/bseinfo.cc                                  |  104 -
 bse/bseinstrumentinput.cc                       |   10 +-
 bse/bseinstrumentoutput.cc                      |   10 +-
 bse/bseitem.cc                                  |  302 +-
 bse/bseitem.hh                                  |  107 +-
 bse/bseitem.proc                                |  213 +-
 bse/bsejanitor.cc                               |   40 +-
 bse/bsejanitor.proc                             |   83 +-
 bse/bseladspa.cc                                |   18 +-
 bse/bseladspamodule.cc                          |   16 +-
 bse/bseloader-aiff.cc                           |   84 +-
 bse/bseloader-bsewave.cc                        |   56 +-
 bse/bseloader-flac.cc                           |   20 +-
 bse/bseloader-guspatch.cc                       |   68 +-
 bse/bseloader-mad.cc                            |   20 +-
 bse/bseloader-oggvorbis.cc                      |   22 +-
 bse/bseloader-wav.cc                            |   80 +-
 bse/bseloader.cc                                |  116 +-
 bse/bseloader.hh                                |   14 +-
 bse/bsemain.cc                                  |  394 +-
 bse/bsemain.hh                                  |   13 +-
 bse/bsemathsignal.cc                            |   45 +-
 bse/bsemathsignal.hh                            |    5 +-
 bse/bsemidicontroller.cc                        |   40 +-
 bse/bsemidicontroller.hh                        |    2 +-
 bse/bsemididecoder.cc                           |   26 +-
 bse/bsemididecoder.hh                           |    4 +-
 bse/bsemididevice-null.cc                       |    8 +-
 bse/bsemididevice-oss.cc                        |   25 +-
 bse/bsemididevice.cc                            |    2 +-
 bse/bsemidievent.cc                             |  128 +-
 bse/bsemidievent.hh                             |  194 +-
 bse/bsemidifile.cc                              |  108 +-
 bse/bsemidifile.hh                              |    4 +-
 bse/bsemidiinput.cc                             |    8 +-
 bse/bsemidinotifier.cc                          |   20 +-
 bse/bsemidinotifier.hh                          |   13 +
 bse/bsemidinotifier.proc                        |   39 -
 bse/bsemidireceiver.cc                          |  254 +-
 bse/bsemidireceiver.hh                          |   10 +-
 bse/bsemidisynth.cc                             |   17 +-
 bse/bsemidisynth.hh                             |   12 +
 bse/bsemidivoice.cc                             |   46 +-
 bse/bsenote.cc                                  |   75 +-
 bse/bsenote.hh                                  |   31 +-
 bse/bseobject.cc                                |  229 +-
 bse/bseobject.hh                                |   64 +-
 bse/bseparam.cc                                 |   18 +-
 bse/bseparasite.cc                              |  709 -
 bse/bseparasite.hh                              |   46 -
 bse/bseparasite.proc                            |   90 -
 bse/bsepart.cc                                  |  615 +-
 bse/bsepart.hh                                  |   71 +-
 bse/bsepart.proc                                | 1075 -
 bse/bsepcmdevice-null.cc                        |    6 +-
 bse/bsepcmdevice-oss.cc                         |   82 +-
 bse/bsepcmdevice.cc                             |   40 +-
 bse/bsepcminput.cc                              |    4 +-
 bse/bsepcmmodule.cc                             |   26 +-
 bse/bsepcmoutput.cc                             |    4 +-
 bse/bsepcmwriter.cc                             |   39 +-
 bse/bsepcmwriter.hh                             |   13 +-
 bse/bseplugin.cc                                |   46 +-
 bse/bseplugin.hh                                |    1 -
 bse/bseprobe.cc                                 |   42 +-
 bse/bseprobe.idl                                |    1 -
 bse/bseprocedure.cc                             |   97 +-
 bse/bseprocedure.hh                             |   18 +-
 bse/bseprocedure.proc                           |  366 -
 bse/bseprocidl.cc                               |   12 +-
 bse/bseproject.cc                               |  391 +-
 bse/bseproject.genprc.cc                        |  674 +
 bse/bseproject.hh                               |   39 +-
 bse/bseproject.proc                             |  764 +-
 bse/bsequery.cc                                 |  349 -
 bse/bseresampler.hh                             |    2 +-
 bse/bseresamplerimpl.hh                         |    8 +-
 bse/bsescripthelper.cc                          |   27 +-
 bse/bsescripthelper.hh                          |    2 +-
 bse/bsescripthelper.proc                        |   41 -
 bse/bsesequencer.cc                             |   50 +-
 bse/bsesequencer.hh                             |    1 +
 bse/bseserver.cc                                |  678 +-
 bse/bseserver.hh                                |   57 +-
 bse/bseserver.proc                              |  618 -
 bse/bseserverinsert.hh                          |   35 +
 bse/bsesnet.cc                                  |  306 +-
 bse/bsesnet.hh                                  |   19 +-
 bse/bsesnet.proc                                |  148 -
 bse/bsesnooper.cc                               |   22 +-
 bse/bsesong.cc                                  |  309 +-
 bse/bsesong.hh                                  |   48 +-
 bse/bsesong.proc                                |  312 +-
 bse/bsesoundfont.cc                             |   22 +-
 bse/bsesoundfont.hh                             |    4 +-
 bse/bsesoundfontosc.cc                          |    2 +-
 bse/bsesoundfontrepo.cc                         |    6 +-
 bse/bsesoundfontrepo.hh                         |    2 +-
 bse/bsesoundfontrepo.proc                       |   26 +-
 bse/bsesource.cc                                |  364 +-
 bse/bsesource.hh                                |   28 +-
 bse/bsesource.proc                              |  186 +-
 bse/bsestandardosc.cc                           |   12 +-
 bse/bsestandardsynths.cc                        |   94 +-
 bse/bsestandardsynths.hh                        |    1 -
 bse/{bsecore.cc => bsestartup.cc}               |   49 +-
 bse/{bsecore.hh => bsestartup.hh}               |    5 +-
 bse/bsestorage.cc                               |  393 +-
 bse/bsestorage.hh                               |    4 +-
 bse/bsesubiport.cc                              |    4 +-
 bse/bsesuboport.cc                              |    4 +-
 bse/bsesubsynth.cc                              |   32 +-
 bse/bsesubsynth.hh                              |   22 +-
 bse/bsesuper.cc                                 |   14 +
 bse/bsesuper.hh                                 |   12 +
 bse/bsetool.cc                                  |  515 +
 bse/bsetrack.cc                                 |  255 +-
 bse/bsetrack.hh                                 |   26 +-
 bse/bsetrack.proc                               |  323 -
 bse/bsetype.cc                                  |   47 +-
 bse/bsetype.hh                                  |   11 +-
 bse/bseundostack.cc                             |   34 +-
 bse/bseundostack.hh                             |    1 -
 bse/bseutils.cc                                 |  260 +-
 bse/bseutils.hh                                 |   55 +-
 bse/bsewave.cc                                  |  105 +-
 bse/bsewave.hh                                  |   13 +-
 bse/bsewave.proc                                |   53 +-
 bse/bsewaveosc.cc                               |   24 +-
 bse/bsewaveosc.proc                             |   17 +-
 bse/bsewaverepo.cc                              |   14 +
 bse/bsewaverepo.hh                              |   11 +
 bse/bsewaverepo.proc                            |   77 +-
 bse/{bse-internals.hh => effectbase.hh}         |    7 +-
 bse/gsl-fftconf.sh                              |   22 +-
 bse/gsl-fftgen.pl                               |   19 +-
 bse/gslcommon.cc                                |   86 +-
 bse/gslcommon.hh                                |   12 +-
 bse/gsldatacache.cc                             |   74 +-
 bse/gsldatahandle-mad.cc                        |  125 +-
 bse/gsldatahandle-mad.hh                        |    4 +-
 bse/gsldatahandle-vorbis.cc                     |   83 +-
 bse/gsldatahandle.cc                            |  217 +-
 bse/gsldatahandle.hh                            |    4 +-
 bse/gsldatautils.cc                             |  150 +-
 bse/gsldatautils.hh                             |   16 +-
 bse/gslfilehash.cc                              |   34 +-
 bse/gslfilter.cc                                |  126 +-
 bse/gslmagic.cc                                 |   30 +-
 bse/gsloscillator-aux.cc                        |    1 +
 bse/gsloscillator.cc                            |   20 +-
 bse/gslosctable.cc                              |   20 +-
 bse/gslvorbis-cutter.cc                         |   16 +-
 bse/gslvorbis-enc.cc                            |  116 +-
 bse/gslvorbis-enc.hh                            |    4 +-
 bse/gslwavechunk.cc                             |  110 +-
 bse/gslwavechunk.hh                             |    2 +-
 bse/gslwaveosc.cc                               |   30 +-
 bse/icons/Makefile.am                           |    5 +-
 bse/ldscript.map                                |    7 +-
 bse/mkcproc.pl                                  |    2 +-
 bse/oldidl.idl                                  |    4 -
 bse/patch-bseserverapi.cc.diff                  |   23 -
 bse/pybse/Bse.pyx                               |   16 +
 bse/pybse/Makefile.am                           |   43 +
 bse/pybse/pysupport.hh                          |   57 +
 bse/res/.gitignore                              |    1 +
 bse/res/Makefile.am                             |   26 +
 bse/{zintern => res}/adsr-wave-1.bse            |    0
 bse/{zintern => res}/adsr-wave-2.bse            |    0
 bse/{zintern => res}/gus-patch.bse              |    0
 bse/{zintern => res}/plain-wave-1.bse           |    0
 bse/{zintern => res}/plain-wave-2.bse           |    0
 bse/testobject.cc                               |    2 +-
 bse/tests/Makefile.am                           |   27 +-
 bse/tests/arrows.gp                             |    2 +-
 bse/tests/blocktests.cc                         |  315 +-
 bse/tests/filter-defs.gp                        |    2 +-
 bse/tests/filtertest.cc                         |   17 +-
 bse/tests/firhandle.cc                          |   66 +-
 bse/tests/loophandle.cc                         |   28 +-
 bse/tests/misctests.cc                          |   29 +-
 bse/tests/resamplehandle.cc                     |  141 +-
 bse/tests/subnormals-aux.cc                     |    1 +
 bse/tests/subnormals.cc                         |   33 +-
 bse/tests/subnormals.hh                         |    8 +
 bse/tests/testcxx.cc                            |    6 +-
 bse/tests/testfft.cc                            |   99 +-
 bse/zintern/.gitignore                          |    1 -
 buildtool.sh                                    |  142 +
 configure.ac                                    |  384 +-
 data/.gitignore                                 |    1 -
 data/Makefile.am                                |   59 +-
 data/beast.desktop.in                           |    5 +-
 data/bse.pc.in                                  |   29 +-
 debian/README.Debian                            |    7 -
 debian/beast-doc.install                        |    1 +
 debian/beast.install                            |   17 +
 debian/beast.postinst                           |   33 +
 debian/changelog                                |  456 +-
 debian/compat                                   |    2 +-
 debian/control                                  |   69 +-
 debian/copyright                                |  160 +-
 debian/libbse-0-10.install                      |    3 +
 debian/libbse-dev.install                       |    8 +
 debian/menu                                     |    2 -
 debian/patches/10-skip-update-mime.patch        |   33 +
 debian/patches/series                           |    1 +
 debian/postinst                                 |   22 -
 debian/rules                                    |  146 +-
 debian/source/format                            |    1 +
 debian/watch                                    |    7 +
 docs/Makefile.am                                |   76 +-
 docs/doxygen.cfg                                |    2 +-
 docs/images/Makefile.am                         |    4 +-
 docs/imports/Makefile.am                        |    2 +-
 docs/imports/beast.1.html                       |    4 +-
 docs/imports/bse.5.html                         |    6 +-
 docs/imports/bsescm.1.html                      |    2 +-
 docs/imports/cppreference-doxygen-web.tag.xml   |35489 +++++++++++++++++++++++
 docs/main.dox                                   |    4 +-
 drivers/Makefile.am                             |    6 +-
 drivers/bse-portaudio/Makefile.am               |    2 +-
 drivers/bse-portaudio/README                    |   20 +-
 drivers/bse-portaudio/bsepcmdevice-portaudio.cc |   56 +-
 drivers/bsemididevice-alsa.cc                   |   27 +-
 drivers/bsepcmdevice-alsa.cc                    |   81 +-
 launchers/Makefile.am                           |   14 +-
 launchers/beaststart.c                          |    9 +-
 launchers/bseshstart.c                          |    4 +-
 launchers/suidmain.c                            |   14 +-
 library/Makefile.am                             |    2 +-
 library/demo/Makefile.am                        |    4 +-
 library/effects/Makefile.am                     |    4 +-
 library/instruments/Makefile.am                 |    4 +-
 library/keys/Makefile.am                        |    4 +-
 library/samples/Makefile.am                     |    4 +-
 library/scripts/Makefile.am                     |    4 +-
 library/skins/Makefile.am                       |    4 +-
 library/skins/images/Makefile.am                |    4 +-
 mkrelease.sh                                    |  402 -
 plugins/Makefile.am                             |   14 +-
 plugins/bseadder.cc                             |   12 +-
 plugins/bseadder.hh                             |    2 +-
 plugins/bseatandistort.cc                       |    4 +-
 plugins/bseblockutils.cc                        |    6 +-
 plugins/bsefirfilter.c                          |   10 +-
 plugins/bseiirfilter.cc                         |   30 +-
 plugins/bseiirfilter.hh                         |    3 +-
 plugins/bsemixer.cc                             |    4 +-
 plugins/bsemult.cc                              |   10 +-
 plugins/bsenoise.cc                             |    4 +-
 plugins/bsesequencer.cc                         |   14 +-
 plugins/bsesimpleadsr.cc                        |    8 +-
 plugins/davcanyondelay.cc                       |   10 +-
 plugins/davguitar.c                             |    6 +-
 plugins/davorgan.cc                             |    2 +-
 plugins/davsyndrum.cc                           |   10 +-
 plugins/davxtalstrings.cc                       |    6 +-
 plugins/evaluator/Makefile.am                   |    6 +-
 plugins/evaluator/bseevaluator.idl              |    4 +-
 plugins/evaluator/compiler.cc                   |    1 -
 plugins/evaluator/cpu.cc                        |    5 +-
 plugins/evaluator/symbols.hh                    |    4 +-
 plugins/freeverb/Makefile.am                    |    6 +-
 plugins/icons/Makefile.am                       |    2 +-
 plugins/standardsaturator.cc                    |    2 +-
 po/Makefile.am                                  |   47 +-
 po/POTIGNORE                                    |    2 +-
 po/POTSCAN                                      |   14 +-
 po/POTSKIP                                      |    8 +-
 po/ar.po                                        | 2423 +-
 po/az.po                                        | 2326 +-
 po/bg.po                                        | 2349 +-
 po/ca.po                                        | 2445 +-
 po/cs.po                                        | 2429 +-
 po/da.po                                        | 2407 +-
 po/de.po                                        | 2438 +-
 po/el.po                                        | 2397 +-
 po/en_CA.po                                     | 2434 +-
 po/en_GB.po                                     | 2438 +-
 po/eo.po                                        | 2311 +-
 po/es.po                                        | 2441 +-
 po/eu.po                                        | 2397 +-
 po/fi.po                                        | 2346 +-
 po/fr.po                                        | 2449 +-
 po/hr.po                                        | 2345 +-
 po/it.po                                        | 2426 +-
 po/ja.po                                        | 2419 +-
 po/mn.po                                        | 2344 +-
 po/nb.po                                        | 2317 +-
 po/ne.po                                        | 2437 +-
 po/nl.po                                        | 2457 +-
 po/oc.po                                        | 2328 +-
 po/pa.po                                        | 2317 +-
 po/pt.po                                        | 2417 +-
 po/pt_BR.po                                     | 2420 +-
 po/ru.po                                        | 2385 +-
 po/rw.po                                        | 2400 +-
 po/sl.po                                        | 2419 +-
 po/sq.po                                        | 2432 +-
 po/sr.po                                        | 2393 +-
 po/sr Latn po                                   | 2394 +-
 po/sv.po                                        | 2407 +-
 po/te.po                                        | 2316 +-
 po/uk.po                                        | 2339 +-
 po/zh_CN.po                                     | 2362 +-
 pybeast/Makefile.am                             |    5 +
 pybeast/main.py                                 |    4 +
 r+d-files/bse-ellf.c                            |    8 +-
 sfi/Makefile.am                                 |   20 +-
 sfi/gbsearcharray.hh                            |   10 +-
 sfi/glib-extra.cc                               |  160 +-
 sfi/glib-extra.hh                               |   54 +-
 sfi/sfi.hh                                      |   15 +-
 sfi/sficomport.cc                               |   62 +-
 sfi/sficomwire.cc                               |   98 +-
 sfi/sficxx.cc                                   |   23 -
 sfi/sficxx.hh                                   |   65 +-
 sfi/sfidl-cbase.cc                              |   40 +-
 sfi/sfidl-clientcxx.cc                          |   10 +-
 sfi/sfidl-corec.cc                              |    6 +-
 sfi/sfidl-corecxx.cc                            |   30 +-
 sfi/sfidl-cxxbase.cc                            |    2 +
 sfi/sfidl-factory.cc                            |    2 +-
 sfi/sfidl-generator.cc                          |    4 +-
 sfi/sfidl-namespace.cc                          |    2 +-
 sfi/sfidl-options.cc                            |   17 +-
 sfi/sfidl-parser.cc                             |   30 +-
 sfi/sfidl-utils.cc                              |    2 +-
 sfi/sfifilecrawler.cc                           |   38 +-
 sfi/sfiglue.cc                                  |  104 +-
 sfi/sfigluecodec.cc                             |   30 +-
 sfi/sfiglueproxy.cc                             |   84 +-
 sfi/sfimemory.cc                                |   10 +-
 sfi/sfinote.cc                                  |    4 +-
 sfi/sfiparams.cc                                |  139 +-
 sfi/sfiparams.hh                                |   28 +-
 sfi/sfiprimitives.cc                            |  142 +-
 sfi/sfiring.cc                                  |   26 +-
 sfi/sfiserial.cc                                |   93 +-
 sfi/sfistore.cc                                 |  102 +-
 sfi/sfitests.hh                                 |   14 +-
 sfi/sfitime.cc                                  |   11 +-
 sfi/sfitypes.cc                                 |   10 +-
 sfi/sfitypes.hh                                 |    6 +-
 sfi/sfiustore.cc                                |   22 +-
 sfi/sfivalues.cc                                |   90 +-
 sfi/sfivalues.hh                                |    4 +-
 sfi/sfivisitors.cc                              |   65 +
 sfi/sfivisitors.hh                              |  365 +
 sfi/sfivmarshal.cc                              |    6 +-
 sfi/sfiwrapper.cc                               |    7 +-
 sfi/sfiwrapper.hh                               |    2 +-
 sfi/tests/Makefile.am                           |   13 +-
 sfi/tests/misctests.cc                          |   60 +-
 sfi/tests/ring.cc                               |   14 +-
 sfi/tests/testcxx.cc                            |   10 +-
 sfi/tests/testsfidl.cc                          |    2 +-
 shell/Makefile.am                               |   12 +-
 shell/bsescm.cc                                 |  132 +-
 shell/bsescminterp.cc                           |   33 +-
 taptool.sh                                      |  216 +
 tests/Makefile.am                               |   39 +-
 tests/audio/Makefile.am                         |  243 +-
 tests/audio/bse2wav.scm                         |   90 -
 tests/audio/freak-noise.bse                     |    2 +-
 tests/audio/osc-test.bse                        |    9 +-
 tests/audio/simple-loop.bse                     |    9 +-
 tests/bse/Makefile.am                           |   55 +-
 tests/bse/cxxbinding.cc                         |   34 +-
 tests/bse/filtertest.cc                         |   59 +-
 tests/bse/testplugin.cc                         |    6 +-
 tests/bse/testplugin.idl                        |    2 +-
 tests/filecheck/Makefile.am                     |   65 +-
 tests/filecheck/checkproject.scm                |   28 -
 tests/latency/Makefile.am                       |    6 +-
 tests/latency/bselatencytest.idl                |    4 +-
 tests/perftest.cc                               |   39 -
 tests/scripts/Makefile.am                       |    2 +-
 tests/testresampler.cc                          |   25 +-
 tests/testresamplerq.cc                         |    7 +-
 tests/testwavechunk.cc                          |   44 +-
 tools/Makefile.am                               |   10 +-
 tools/bsefcompare.cc                            |   54 +-
 tools/bsefextract.cc                            |   36 +-
 tools/bseloopfuncs.cc                           |  100 +-
 tools/bsewavetool.cc                            |  610 +-
 tools/bwtwave.cc                                |   36 +-
 tools/bwtwave.hh                                |    8 +-
 tools/cutvorbis.cc                              |   22 +-
 tools/magictest.cc                              |   19 +-
 tools/mathtool.cc                               |    2 +-
 tools/scripts/Makefile.am                       |    4 +-
 tools/sfiutils.cc                               |   20 +-
 topconfig.h                                     |    6 -
 624 files changed, 94848 insertions(+), 68454 deletions(-)
---
diff --cc beast-gtk/Makefile.am
index c745979,686a488..c90d106
--- a/beast-gtk/Makefile.am
+++ b/beast-gtk/Makefile.am
@@@ -35,8 -36,8 +36,9 @@@ beast_headers = $(strip 
        bstsnetrouter.hh                bstsplash.hh    bsttrackview.hh         bstsupershell.hh            \
        bstusermessage.hh       bstdial.hh      bsttracksynthdialog.hh  bstwaveeditor.hh            \
        bstzoomedwindow.hh      bstskinconfig.hh        bstmsgabsorb.hh         bstsampleeditor.hh   \
-       bstrackview.hh          bsttreestores.hh        bstbseutils.hh          bstutils.hh         \
-       bstdefs.hh              bstsoundfontview.hh     bstsoundfontpresetview.hh  \
+                               bsttreestores.hh        bstbseutils.hh          bstutils.hh         \
+       bstdefs.hh \
++      bstsoundfontview.hh     bstsoundfontpresetview.hh  \
  )
  EXTRA_DIST += $(beast_headers)
  # BEAST sources to build the program from
@@@ -57,8 -57,7 +58,8 @@@ bst_cc_sources = $(strip 
        bstsnetrouter.cc        bstsplash.cc    bsttrackview.cc         bstsupershell.cc    \
        bstusermessage.cc       bstdial.cc      bsttracksynthdialog.cc  bstwaveeditor.cc    \
        bstzoomedwindow.cc     bstskinconfig.cc bstmsgabsorb.cc         bstsampleeditor.cc  \
-       bstrackview.cc         bsttreestores.cc bstbseutils.cc          bstutils.cc         \
-       bstsoundfontview.cc     bstsoundfontpresetview.cc               $(PROFILE_SOURCE)   \
+                              bsttreestores.cc bstbseutils.cc          bstutils.cc         \
++      bstsoundfontview.cc     bstsoundfontpresetview.cc               \
  )
  # BEAST sources that get included (don't have own .lo rules)
  beast_extra_files = $(strip                                           \
diff --cc beast-gtk/bstfiledialog.cc
index 05669f1,11ad834..05cd582
--- a/beast-gtk/bstfiledialog.cc
+++ b/beast-gtk/bstfiledialog.cc
@@@ -280,11 -273,8 +283,8 @@@ parent_window_destroyed (BstFileDialog 
  }
  
  void
- bst_file_dialog_set_mode (BstFileDialog    *self,
-                         gpointer          parent_widget,
-                         BstFileDialogMode mode,
-                         const gchar      *fs_title,
-                         SfiProxy          proxy)
+ bst_file_dialog_set_mode (BstFileDialog *self, gpointer parent_widget, BstFileDialogMode mode,
 -                        const gchar *fs_title, Bse::ProjectH project, SfiProxy wave_repo)
++                        const gchar *fs_title, Bse::ProjectH project, SfiProxy wave_repo, SfiProxy 
sound_font_repo)
  {
    GtkWindow *window = GTK_WINDOW (self);
  
@@@ -297,9 -287,10 +297,11 @@@
    self->selected = NULL;
  
    /* reset proxy handling */
-   bst_window_sync_title_to_proxy (self, proxy, fs_title);
-   self->proxy = proxy;
+   bst_window_sync_title_to_proxy (self, project ? project.proxy_id() : wave_repo, fs_title);
+   self->project = project;
    self->super = 0;
+   self->wave_repo = wave_repo;
++  self->sound_font_repo = sound_font_repo;
  
    /* cleanup connections to old parent_window */
    if (self->parent_window)
@@@ -327,19 -318,17 +329,19 @@@
    /* handle tree visibility */
    switch (mode & BST_FILE_DIALOG_MODE_MASK)
      {
 +    case BST_FILE_DIALOG_LOAD_SOUND_FONT:
      case BST_FILE_DIALOG_LOAD_WAVE:
        g_free (self->search_path);
-       self->search_path = g_strdup (bse_server_get_sample_path (BSE_SERVER));
+       self->search_path = g_strdup (bse_server.get_sample_path().c_str());
        self->search_filter = NULL;
        gtk_widget_show (self->spage);
        gxk_notebook_set_current_page_widget (GTK_NOTEBOOK (self->notebook), self->fpage);
        g_object_set (self->notebook, "show_border", TRUE, "show_tabs", TRUE, NULL);
        break;
 +    case BST_FILE_DIALOG_LOAD_SOUND_FONT_LIB:
      case BST_FILE_DIALOG_LOAD_WAVE_LIB:
        g_free (self->search_path);
-       self->search_path = g_strdup (bse_server_get_sample_path (BSE_SERVER));
+       self->search_path = g_strdup (bse_server.get_sample_path().c_str());
        self->search_filter = NULL;
        gtk_widget_show (self->spage);
        gxk_notebook_set_current_page_widget (GTK_NOTEBOOK (self->notebook), self->spage);
@@@ -780,37 -739,6 +752,37 @@@ bst_file_dialog_load_wave (BstFileDialo
  }
  
  GtkWidget*
 +bst_file_dialog_popup_load_sound_font (gpointer parent_widget,
 +                                     SfiProxy sound_font_repo,
 +                                     gboolean show_lib)
 +{
 +  BstFileDialog *self = bst_file_dialog_global_sound_font ();
 +  GtkWidget *widget = GTK_WIDGET (self);
 +
 +  bst_file_dialog_set_mode (self, parent_widget,
 +                          show_lib ? BST_FILE_DIALOG_LOAD_SOUND_FONT_LIB : BST_FILE_DIALOG_LOAD_SOUND_FONT,
-                           _("Load Sound Font"), sound_font_repo);
++                          _("Load Sound Font"), Bse::ProjectH(), 0, sound_font_repo);
 +  gxk_widget_showraise (widget);
 +
 +  return widget;
 +}
 +
 +static gboolean
 +bst_file_dialog_load_sound_font (BstFileDialog *self,
 +                               const gchar   *file_name)
 +{
-   BseErrorType error;
++  Bse::Error error;
 +
 +  gxk_status_printf (0, NULL, _("Loading sound font `%s'"), file_name);
-   error = bse_sound_font_repo_load_file (self->proxy, file_name);
++  error = bse_sound_font_repo_load_file (self->sound_font_repo, file_name);
 +  bst_status_eprintf (error, _("Loading sound font `%s'"), file_name);
-   if (error)
-     sfi_error (_("Failed to load sound font \"%s\": %s"), file_name, bse_error_blurb (error));
++  if (error != 0)
++    sfi_error (_("Failed to load sound font \"%s\": %s"), file_name, Bse::error_blurb (error));
 +
 +  return TRUE;
 +}
 +
 +GtkWidget*
  bst_file_dialog_create (void)
  {
    BstFileDialog *self = (BstFileDialog*) g_object_new (BST_TYPE_FILE_DIALOG, NULL);
diff --cc beast-gtk/bstfiledialog.hh
index 9290588,22006f8..926d5e4
--- a/beast-gtk/bstfiledialog.hh
+++ b/beast-gtk/bstfiledialog.hh
@@@ -62,7 -60,8 +62,8 @@@ struct _BstFileDialo
    gchar            *search_path;
    const gchar      *search_filter;
    GtkWindow      *parent_window;
-   SfiProxy        proxy, super;
 -  SfiProxy        super, wave_repo;
++  SfiProxy        super, wave_repo, sound_font_repo;
+   Bse::ProjectH     project;
  };
  struct _BstFileDialogClass
  {
@@@ -96,14 -85,9 +87,12 @@@ GtkWidget*  bst_file_dialog_popup_select
  GtkWidget*    bst_file_dialog_popup_load_wave         (gpointer          parent_widget,
                                                         SfiProxy          wave_repo,
                                                         gboolean          show_lib);
 +GtkWidget*    bst_file_dialog_popup_load_sound_font   (gpointer          parent_widget,
 +                                                         SfiProxy          sound_font_repo,
 +                                                         gboolean          show_lib);
- void          bst_file_dialog_set_mode                (BstFileDialog    *self,
-                                                        gpointer          parent_widget,
-                                                        BstFileDialogMode mode,
-                                                        const gchar      *fs_title,
-                                                        SfiProxy          project);
+ void          bst_file_dialog_set_mode                (BstFileDialog *self, gpointer parent_widget, 
BstFileDialogMode mode,
+                                                          const gchar *fs_title, Bse::ProjectH project = 
Bse::ProjectH(),
 -                                                         SfiProxy wave_repo = 0);
++                                                         SfiProxy wave_repo = 0, SfiProxy sound_font_repo = 
0);
  GtkWidget*      bst_file_dialog_create                  (void);
  void            bst_file_dialog_setup                   (GtkWidget        *widget,
                                                           gpointer          parent_widget,
diff --cc beast-gtk/bstsupershell.cc
index a0166cb,16a3a41..6f2bc1f
--- a/beast-gtk/bstsupershell.cc
+++ b/beast-gtk/bstsupershell.cc
@@@ -6,8 -6,6 +6,7 @@@
  #include "bstbusmixer.hh"
  #include "bstbusview.hh"
  #include "bstwaveview.hh"
- #include "bstrackview.hh"
 +#include "bstsoundfontview.hh"
  #include "bstsnetrouter.hh"
  #include "bstgconfig.hh"
  #include <string.h>
@@@ -221,20 -212,6 +213,20 @@@ super_shell_build_wave_repo (BstSuperSh
                              gxk_notebook_create_tabulator (_("Properties"), BST_STOCK_PROPERTIES, NULL));
  }
  
 +static void
 +super_shell_build_sound_font_repo (BstSuperShell *self,
 +                                   GtkNotebook   *notebook)
 +{
-   SfiProxy sfrepo = self->super;
++  SfiProxy sfrepo = self->super.proxy_id();
 +
 +  gtk_notebook_append_page (notebook,
 +                            bst_sound_font_view_new (sfrepo),
 +                            gxk_notebook_create_tabulator (_("Sound Fonts"), BST_STOCK_MINI_WAVE_REPO, 
NULL));
 +  gtk_notebook_append_page (notebook,
 +                            bst_param_view_new (sfrepo),
 +                            gxk_notebook_create_tabulator (_("Properties"), BST_STOCK_PROPERTIES, NULL));
 +}
 +
  static GtkNotebook*
  create_notebook (BstSuperShell *self)
  {
@@@ -255,12 -232,10 +247,12 @@@
  static void
  super_shell_add_views (BstSuperShell *self)
  {
-   if (BSE_IS_SONG (self->super))
+   if (BSE_IS_SONG (self->super.proxy_id()))
      super_shell_build_song (self, create_notebook (self));
-   else if (BSE_IS_WAVE_REPO (self->super))
+   else if (BSE_IS_WAVE_REPO (self->super.proxy_id()))
      super_shell_build_wave_repo (self, create_notebook (self));
-   else if (BSE_IS_SOUND_FONT_REPO (self->super))
++  else if (BSE_IS_SOUND_FONT_REPO (self->super.proxy_id()))
 +    super_shell_build_sound_font_repo (self, create_notebook (self));
    else /* BSE_IS_SNET (self->super) */
      super_shell_build_snet (self, create_notebook (self));
  }
diff --cc beast-gtk/bsttracksynthdialog.cc
index f696599,b8cc109..58ab677
--- a/beast-gtk/bsttracksynthdialog.cc
+++ b/beast-gtk/bsttracksynthdialog.cc
@@@ -265,18 -255,15 +265,18 @@@ bst_track_synth_dialog_popup (gpointe
  
  void
  bst_track_synth_dialog_set (BstTrackSynthDialog *self,
-                             BseItemSeq          *iseq,
+                             BseIt3mSeq          *iseq,
 -                            SfiProxy             wrepo)
 +                            SfiProxy             wrepo,
 +                          SfiProxy             sfrepo)
  {
-   g_return_if_fail (BST_IS_TRACK_SYNTH_DIALOG (self));
+   assert_return (BST_IS_TRACK_SYNTH_DIALOG (self));
  
    bst_item_view_set_container (BST_ITEM_VIEW (self->wpage), wrepo);
 +  bst_item_view_set_container (BST_ITEM_VIEW (self->sfont_page), sfrepo);
    bst_item_seq_store_set (self->pstore, iseq);
 -  g_object_set (self->wpage, "visible", wrepo != 0, NULL);
    g_object_set (self->spage, "visible", iseq != NULL, NULL);
 +  g_object_set (self->wpage, "visible", wrepo != 0, NULL);
 +  g_object_set (self->sfont_page, "visible", sfrepo != 0, NULL);
  }
  
  static void
diff --cc beast-gtk/bsttracksynthdialog.hh
index ca106eb,df5dd67..655756e
--- a/beast-gtk/bsttracksynthdialog.hh
+++ b/beast-gtk/bsttracksynthdialog.hh
@@@ -63,9 -58,9 +63,9 @@@ GtkWidget* bst_track_synth_dialog_popu
                                              gpointer                     selected_data,
                                              GxkFreeFunc                  selected_cleanup);
  void       bst_track_synth_dialog_set      (BstTrackSynthDialog         *self,
-                                             BseItemSeq                  *iseq,
+                                             BseIt3mSeq                  *iseq,
 -                                            SfiProxy                     wrepo);
 -
 +                                            SfiProxy                     wrepo,
 +                                          SfiProxy                     sfrepo);
  
  
  G_END_DECLS
diff --cc beast-gtk/bsttrackview.cc
index fa94ea0,f9c4383..1cc8ea9
--- a/beast-gtk/bsttrackview.cc
+++ b/beast-gtk/bsttrackview.cc
@@@ -120,8 -120,8 +120,8 @@@ track_view_fill_value (BstItemView *ivi
        const gchar *string;
        gboolean vbool;
        SfiInt vint;
 -      SfiProxy snet, wave;
 +      SfiProxy snet, wave, sound_font_preset;
-       BseItemSeq *iseq;
+       BseIt3mSeq *iseq;
        SfiSeq *seq;
      case COL_SEQID:
        sfi_value_take_string (value, g_strdup_format ("%03d", seqid));
diff --cc bse/Makefile.am
index e752016,4dbc514..02f8f9d
--- a/bse/Makefile.am
+++ b/bse/Makefile.am
@@@ -115,11 -115,10 +117,11 @@@ idl_dummy_files = $(strip       
  )
  # BSE procedure sources
  bse_proc_sources = $(strip \
-       bsecategories.proc      bsecontainer.proc       bsedatapocket.proc      bseeditablesample.proc  
bseenums.proc   bsemidinotifier.proc    \
-       bsejanitor.proc         bsepart.proc            bseparasite.proc        bseprocedure.proc       
bseproject.proc bsescripthelper.proc    \
-       bseserver.proc          bsesong.proc            bsebus.proc             bsesource.proc          
bsecsynth.proc  bsesnet.proc            \
-       bsetrack.proc           bseitem.proc            bsewave.proc            bsewaveosc.proc         
bsewaverepo.proc                        \
+       bsecategories.proc      bsecontainer.proc                               bseeditablesample.proc  \
+       bsejanitor.proc                                                         bseproject.proc         \
+                               bsesong.proc                                    bsesource.proc          \
+                               bseitem.proc            bsewave.proc            bsewaveosc.proc         
bsewaverepo.proc \
 +      bsesoundfontrepo.proc   \
  )
  bse_proc_gen_sources = $(bse_proc_sources:.proc=.genprc.cc)
  # non-compile and non-install sources required
diff --cc bse/bsemidireceiver.cc
index 5ce7e47,78d78da..118b0bc
--- a/bse/bsemidireceiver.cc
+++ b/bse/bsemidireceiver.cc
@@@ -2062,85 -1938,79 +2062,85 @@@ midi_receiver_process_event_L (BseMidiR
    if (event->delta_time <= max_tick_stamp)
      {
        BseTrans *trans = bse_trans_open ();
 +      MidiChannel *mchannel = self->peek_channel (event->channel);
        self->events = sfi_ring_remove_node (self->events, self->events);
 -      switch (event->status)
 +
 +      bool event_handled = false;
 +      if (mchannel)
 +      event_handled = mchannel->call_event_handlers (event, trans);
 +
 +      if (!event_handled)
        {
 -          MidiChannel *mchannel;
 -        case BSE_MIDI_NOTE_ON:
 -          mchannel = self->peek_channel (event->channel);
 -        EDEBUG ("MidiChannel[%u]: NoteOn  %fHz Velo=%f (stamp:%llu)", event->channel,
 -                        event->data.note.frequency, event->data.note.velocity, event->delta_time);
 -        if (mchannel)
 -            mchannel->start_note (event->delta_time,
 -                                  event->data.note.frequency,
 -                                  event->data.note.velocity,
 -                                  trans);
 -          else
 -            sfi_diag ("ignoring note-on (%fHz) for foreign midi channel: %u", event->data.note.frequency, 
event->channel);
 -        break;
 -      case BSE_MIDI_KEY_PRESSURE:
 -      case BSE_MIDI_NOTE_OFF:
 -          mchannel = self->peek_channel (event->channel);
 -          EDEBUG ("MidiChannel[%u]: %s %fHz (stamp:%llu)", event->channel,
 -                        event->status == BSE_MIDI_NOTE_OFF ? "NoteOff" : "NotePressure",
 -                        event->data.note.frequency, event->delta_time);
 -          if (mchannel)
 -            {
 -              gboolean sustained_note = event->status == BSE_MIDI_NOTE_OFF &&
 -                                        (BSE_GCONFIG (invert_sustain) ^
 -                                         (self->get_control (event->channel, Bse::MidiSignal::CONTROL_64) 
= 0.5));
 -              mchannel->adjust_note (event->delta_time,
 -                                     event->data.note.frequency, event->status,
 -                                     event->data.note.velocity, sustained_note, trans);
 -            }
 -        break;
 -      case BSE_MIDI_CONTROL_CHANGE:
 -        EDEBUG ("MidiChannel[%u]: Control %2u Value=%f (stamp:%llu)", event->channel,
 -                        event->data.control.control, event->data.control.value, event->delta_time);
 -        process_midi_control_L (self, event->channel, event->delta_time,
 -                                event->data.control.control, event->data.control.value,
 -                                FALSE,
 -                                  trans);
 -        break;
 -      case BSE_MIDI_X_CONTINUOUS_CHANGE:
 -        EDEBUG ("MidiChannel[%u]: X Continuous Control %2u Value=%f (stamp:%llu)", event->channel,
 -                        event->data.control.control, event->data.control.value, event->delta_time);
 -        process_midi_control_L (self, event->channel, event->delta_time,
 -                                event->data.control.control, event->data.control.value,
 -                                  TRUE,
 -                                trans);
 -        break;
 -      case BSE_MIDI_PROGRAM_CHANGE:
 -        EDEBUG ("MidiChannel[%u]: Program %u (Value=%f) (stamp:%llu)", event->channel,
 -                        event->data.program, event->data.program / (gfloat) 0x7f, event->delta_time);
 -        update_midi_signal_L (self, event->channel, event->delta_time,
 -                              Bse::MidiSignal::PROGRAM, event->data.program / (gfloat) 0x7f,
 -                              trans);
 -        break;
 -      case BSE_MIDI_CHANNEL_PRESSURE:
 -        EDEBUG ("MidiChannel[%u]: Channel Pressure Value=%f (stamp:%llu)", event->channel,
 -                        event->data.intensity, event->delta_time);
 -        update_midi_signal_L (self, event->channel, event->delta_time,
 -                              Bse::MidiSignal::PRESSURE, event->data.intensity,
 -                              trans);
 -        break;
 -      case BSE_MIDI_PITCH_BEND:
 -        EDEBUG ("MidiChannel[%u]: Pitch Bend Value=%f (stamp:%llu)", event->channel,
 -                        event->data.pitch_bend, event->delta_time);
 -        update_midi_signal_L (self, event->channel, event->delta_time,
 -                              Bse::MidiSignal::PITCH_BEND, event->data.pitch_bend,
 -                              trans);
 -        break;
 -      default:
 -        EDEBUG ("MidiChannel[%u]: Ignoring Event %u (stamp:%llu)", event->channel,
 -                        event->status, event->delta_time);
 -        break;
 +        switch (event->status)
 +          {
 +          case BSE_MIDI_NOTE_ON:
 +            EDEBUG ("MidiChannel[%u]: NoteOn  %fHz Velo=%f (stamp:%llu)", event->channel,
 +                      event->data.note.frequency, event->data.note.velocity, event->delta_time);
 +            if (mchannel)
 +              mchannel->start_note (event->delta_time,
 +                                    event->data.note.frequency,
 +                                    event->data.note.velocity,
 +                                    trans);
 +            else
 +              sfi_diag ("ignoring note-on (%fHz) for foreign midi channel: %u", event->data.note.frequency, 
event->channel);
 +            break;
 +          case BSE_MIDI_KEY_PRESSURE:
 +          case BSE_MIDI_NOTE_OFF:
 +            EDEBUG ("MidiChannel[%u]: %s %fHz (stamp:%llu)", event->channel,
 +                      event->status == BSE_MIDI_NOTE_OFF ? "NoteOff" : "NotePressure",
 +                      event->data.note.frequency, event->delta_time);
 +            if (mchannel)
 +              {
 +                gboolean sustained_note = event->status == BSE_MIDI_NOTE_OFF &&
 +                                          (BSE_GCONFIG (invert_sustain) ^
-                                            (self->get_control (event->channel, BSE_MIDI_SIGNAL_CONTROL_64) 
= 0.5));
++                                           (self->get_control (event->channel, Bse::MidiSignal::CONTROL_64) 
= 0.5));
 +                mchannel->adjust_note (event->delta_time,
 +                                       event->data.note.frequency, event->status,
 +                                       event->data.note.velocity, sustained_note, trans);
 +              }
 +            break;
 +          case BSE_MIDI_CONTROL_CHANGE:
 +            EDEBUG ("MidiChannel[%u]: Control %2u Value=%f (stamp:%llu)", event->channel,
 +                      event->data.control.control, event->data.control.value, event->delta_time);
 +            process_midi_control_L (self, event->channel, event->delta_time,
 +                                    event->data.control.control, event->data.control.value,
 +                                    FALSE,
 +                                    trans);
 +            break;
 +          case BSE_MIDI_X_CONTINUOUS_CHANGE:
 +            EDEBUG ("MidiChannel[%u]: X Continuous Control %2u Value=%f (stamp:%llu)", event->channel,
 +                      event->data.control.control, event->data.control.value, event->delta_time);
 +            process_midi_control_L (self, event->channel, event->delta_time,
 +                                    event->data.control.control, event->data.control.value,
 +                                    TRUE,
 +                                    trans);
 +            break;
 +          case BSE_MIDI_PROGRAM_CHANGE:
 +            EDEBUG ("MidiChannel[%u]: Program %u (Value=%f) (stamp:%llu)", event->channel,
 +                      event->data.program, event->data.program / (gfloat) 0x7f, event->delta_time);
 +            update_midi_signal_L (self, event->channel, event->delta_time,
-                                   BSE_MIDI_SIGNAL_PROGRAM, event->data.program / (gfloat) 0x7f,
++                                  Bse::MidiSignal::PROGRAM, event->data.program / (gfloat) 0x7f,
 +                                  trans);
 +            break;
 +          case BSE_MIDI_CHANNEL_PRESSURE:
 +            EDEBUG ("MidiChannel[%u]: Channel Pressure Value=%f (stamp:%llu)", event->channel,
 +                      event->data.intensity, event->delta_time);
 +            update_midi_signal_L (self, event->channel, event->delta_time,
-                                   BSE_MIDI_SIGNAL_PRESSURE, event->data.intensity,
++                                  Bse::MidiSignal::PRESSURE, event->data.intensity,
 +                                  trans);
 +            break;
 +          case BSE_MIDI_PITCH_BEND:
 +            EDEBUG ("MidiChannel[%u]: Pitch Bend Value=%f (stamp:%llu)", event->channel,
 +                      event->data.pitch_bend, event->delta_time);
 +            update_midi_signal_L (self, event->channel, event->delta_time,
-                                   BSE_MIDI_SIGNAL_PITCH_BEND, event->data.pitch_bend,
++                                  Bse::MidiSignal::PITCH_BEND, event->data.pitch_bend,
 +                                  trans);
 +            break;
 +          default:
 +            EDEBUG ("MidiChannel[%u]: Ignoring Event %u (stamp:%llu)", event->channel,
 +                      event->status, event->delta_time);
 +            break;
 +          }
        }
        if (self->notifier)
        {
diff --cc bse/bseproject.cc
index 61c1dd3,2b6570c..b38b6ca
--- a/bse/bseproject.cc
+++ b/bse/bseproject.cc
@@@ -16,7 -16,7 +16,8 @@@
  #include "bsemidinotifier.hh"
  #include "gslcommon.hh"
  #include "bseengine.hh"
+ #include "bsemidifile.hh"
 +#include "bsesoundfontrepo.hh"
  #include <string.h>
  #include <stdlib.h>
  #include <fcntl.h>
diff --cc bse/bseproject.genprc.cc
index 0000000,0000000..a05c398
new file mode 100644
--- /dev/null
+++ b/bse/bseproject.genprc.cc
@@@ -1,0 -1,0 +1,674 @@@
++
++/*
++ * Generated data (by mkcproc.pl)
++ */
++#line 1 "bseproject.proc"
++// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
++#include <bse/bseplugin.hh>
++#include <bse/bseprocedure.hh>
++#include <bse/bseproject.hh>
++#include <bse/bsestorage.hh>
++#include <bse/bsesong.hh>
++#include <bse/bseundostack.hh>
++#include <bse/bsewaverepo.hh>
++#include <bse/bsesoundfontrepo.hh>
++#include <bse/bsecsynth.hh>
++#include <bse/bsemidisynth.hh>
++#include <bse/bsemidifile.hh>
++#include <bse/bsemidireceiver.hh>
++#include <bse/bsemidinotifier.hh>
++#include <bse/bseengine.hh>
++#include "bsecxxplugin.hh"
++#include "bsebuiltin_externs.cc"
++
++#line 21 "bseproject.proc"
++
++
++
++/* --- get-midi-notifier --- */
++static void
++get_midi_notifier_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 24 "bseproject.proc"
++ {
++#line 26 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", NULL, BSE_TYPE_PROJECT, 
SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_object ("midi_notifier", NULL, NULL, BSE_TYPE_MIDI_NOTIFIER, 
SFI_PARAM_STANDARD);
++#line 28 "bseproject.proc"
++}  }
++static Bse::Error
++#line 28 "bseproject.proc"
++get_midi_notifier_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 31 "bseproject.proc"
++{
++#line 32 "bseproject.proc"
++  
++  BseProject *self = (BseProject*) bse_value_get_object (in_values++);
++
++#line 35 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (self))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++  BseMidiNotifier *notifier = bse_project_get_midi_notifier (self);
++
++#line 41 "bseproject.proc"
++  
++  bse_value_set_object (out_values++, G_OBJECT (notifier));
++
++  return Bse::Error::NONE;
++}
++
++
++
++/* --- store-bse --- */
++static void
++store_bse_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 49 "bseproject.proc"
++ {
++#line 52 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", NULL,
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = bse_param_spec_object ("super", "Super", NULL,
++                                 BSE_TYPE_SUPER, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = sfi_pspec_string ("file-name", "File", "Destination file name",
++                            NULL, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = sfi_pspec_bool ("self-contained", "Self Contained",
++                          "Whether references to other objects (e.g. samples) should "
++                          "be stored or whether to include everything in a self-contained .bse file",
++                          FALSE, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_genum ("error", "Error", "Error indicating possible failures",
++                                BSE_TYPE_ERROR_TYPE, Bse::Error::NONE,
++                                SFI_PARAM_STANDARD);
++#line 65 "bseproject.proc"
++}  }
++static Bse::Error
++#line 65 "bseproject.proc"
++store_bse_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 68 "bseproject.proc"
++{
++#line 69 "bseproject.proc"
++  
++  BseProject *project = (BseProject*) bse_value_get_object (in_values++);
++  BseSuper *super = (BseSuper*) bse_value_get_object (in_values++);
++  const char *file_name = sfi_value_get_string (in_values++);
++  gboolean self_contained = sfi_value_get_bool (in_values++);
++  Bse::Error error;
++
++#line 76 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (project) || !file_name)
++    return Bse::Error::PROC_PARAM_INVAL;
++  if (super && BSE_ITEM (super)->parent != BSE_ITEM (project))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++  error = bse_project_store_bse (project, super, file_name, self_contained);
++
++#line 84 "bseproject.proc"
++  
++  g_value_set_enum (out_values++, int (error));
++
++  return Bse::Error::NONE;
++}
++
++/* --- create-song --- */
++static void
++create_song_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 90 "bseproject.proc"
++ {
++#line 92 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = sfi_pspec_string ("name", "Name", "Song name",
++                            NULL, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_object ("song", "Song", "The new song",
++                                 BSE_TYPE_SONG, SFI_PARAM_STANDARD);
++#line 98 "bseproject.proc"
++}  }
++static Bse::Error
++#line 98 "bseproject.proc"
++create_song_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 101 "bseproject.proc"
++{
++#line 102 "bseproject.proc"
++  
++  BseContainer *container = (BseContainer*) bse_value_get_object (in_values++);
++  const char *name = sfi_value_get_string (in_values++);
++  BseUndoStack *ustack;
++  BseItem *child;
++
++#line 108 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (container))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 112 "bseproject.proc"
++  
++  ustack = bse_item_undo_open (container, "create-song");
++  child = (BseItem*) bse_container_new_child (container, BSE_TYPE_SONG, NULL);
++  if (name)
++    bse_item_set (child, "uname", name, NULL);
++  bse_item_push_undo_proc (container, "remove-snet", child);
++  bse_item_undo_close (ustack);
++
++#line 120 "bseproject.proc"
++  
++  bse_value_set_object (out_values++, child);
++
++  return Bse::Error::NONE;
++}
++
++/* --- get-wave-repo --- */
++static void
++get_wave_repo_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 126 "bseproject.proc"
++ {
++#line 128 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_object ("wrepo", "Wave Repo", "The project's unique wave repo",
++                                 BSE_TYPE_WAVE_REPO, SFI_PARAM_STANDARD);
++#line 132 "bseproject.proc"
++}  }
++static Bse::Error
++#line 132 "bseproject.proc"
++get_wave_repo_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 135 "bseproject.proc"
++{
++#line 136 "bseproject.proc"
++  
++  BseProject *project = (BseProject*) bse_value_get_object (in_values++);
++  BseWaveRepo *wrepo = NULL;
++
++#line 140 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (project))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 144 "bseproject.proc"
++  
++  wrepo = bse_project_get_wave_repo (project);
++
++#line 147 "bseproject.proc"
++  
++  bse_value_set_object (out_values++, wrepo);
++
++  return Bse::Error::NONE;
++}
++
++/* --- get-sound-font-repo --- */
++static void
++get_sound_font_repo_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 153 "bseproject.proc"
++ {
++#line 155 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_object ("sfrepo", "Sound Font Repo", "The project's unique sound font 
repo",
++                                 BSE_TYPE_SOUND_FONT_REPO, SFI_PARAM_STANDARD);
++
++#line 160 "bseproject.proc"
++}  }
++static Bse::Error
++#line 160 "bseproject.proc"
++get_sound_font_repo_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 163 "bseproject.proc"
++{
++#line 164 "bseproject.proc"
++  
++  BseProject *project = BSE_PROJECT (bse_value_get_object (in_values++));
++  BseSoundFontRepo *sfrepo = NULL;
++
++#line 168 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (project))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 172 "bseproject.proc"
++  
++  sfrepo = bse_project_get_sound_font_repo (project);
++
++#line 175 "bseproject.proc"
++  
++  bse_value_set_object (out_values++, sfrepo);
++
++  return Bse::Error::NONE;
++}
++
++/* --- create-csynth --- */
++static void
++create_csynth_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 181 "bseproject.proc"
++ {
++#line 183 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = sfi_pspec_string ("name", "Name", "Synth network name",
++                            NULL, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_object ("csynth", "Synthesizer Network", "New synth network",
++                                 BSE_TYPE_CSYNTH, SFI_PARAM_STANDARD);
++#line 189 "bseproject.proc"
++}  }
++static Bse::Error
++#line 189 "bseproject.proc"
++create_csynth_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 192 "bseproject.proc"
++{
++#line 193 "bseproject.proc"
++  
++  BseContainer *container = (BseContainer*) bse_value_get_object (in_values++);
++  const char *name = sfi_value_get_string (in_values++);
++  BseUndoStack *ustack;
++  BseItem *child;
++
++#line 199 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (container))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 203 "bseproject.proc"
++  
++  ustack = bse_item_undo_open (container, "create-csynth");
++  child = (BseItem*) bse_container_new_child (container, BSE_TYPE_CSYNTH, NULL);
++  if (name)
++    bse_item_set (child, "uname", name, NULL);
++  bse_item_push_undo_proc (container, "remove-snet", child);
++  bse_item_undo_close (ustack);
++
++#line 211 "bseproject.proc"
++  
++  bse_value_set_object (out_values++, child);
++
++  return Bse::Error::NONE;
++}
++
++/* --- create-midi-synth --- */
++static void
++create_midi_synth_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 217 "bseproject.proc"
++ {
++#line 219 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = sfi_pspec_string ("name", "Name", "MIDI synth name",
++                            NULL, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_object ("midi_synth", "MIDI Synthesizer", "New MIDI synth",
++                                 BSE_TYPE_MIDI_SYNTH, SFI_PARAM_STANDARD);
++#line 225 "bseproject.proc"
++}  }
++static Bse::Error
++#line 225 "bseproject.proc"
++create_midi_synth_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 228 "bseproject.proc"
++{
++#line 229 "bseproject.proc"
++  
++  BseContainer *container = (BseContainer*) bse_value_get_object (in_values++);
++  const char *name = sfi_value_get_string (in_values++);
++  BseUndoStack *ustack;
++  BseItem *child;
++
++#line 235 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (container))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 239 "bseproject.proc"
++  
++  ustack = bse_item_undo_open (container, "create-midi-synth");
++  child = (BseItem*) bse_container_new_child (container, BSE_TYPE_MIDI_SYNTH, NULL);
++  if (name)
++    bse_item_set (child, "uname", name, NULL);
++  bse_item_push_undo_proc (container, "remove-snet", child);
++  bse_item_undo_close (ustack);
++
++#line 247 "bseproject.proc"
++  
++  bse_value_set_object (out_values++, child);
++
++  return Bse::Error::NONE;
++}
++
++/* --- remove-snet --- */
++static void
++remove_snet_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 253 "bseproject.proc"
++ {
++#line 255 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(in_pspecs++)    = bse_param_spec_object ("snet", "SNet", "Synthesizer Network",
++                                 BSE_TYPE_SNET, SFI_PARAM_STANDARD);
++#line 259 "bseproject.proc"
++}  }
++static Bse::Error
++#line 259 "bseproject.proc"
++remove_snet_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 262 "bseproject.proc"
++{
++#line 263 "bseproject.proc"
++  
++  BseContainer *self = (BseContainer*) bse_value_get_object (in_values++);
++  BseItem *child = (BseItem*) bse_value_get_object (in_values++);
++  BseUndoStack *ustack;
++
++#line 268 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (self) || !BSE_IS_SNET (child) || child->parent != (BseItem*) self)
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 272 "bseproject.proc"
++  
++  if (!BSE_SOURCE_PREPARED (self))
++    {
++      ustack = bse_item_undo_open (self, "remove-child %s", bse_object_debug_name (child));
++#line 276 "bseproject.proc"
++      
++      bse_container_uncross_undoable (BSE_CONTAINER (self), child);
++#line 278 "bseproject.proc"
++      
++      bse_item_push_redo_proc (self, "remove-snet", child);
++#line 280 "bseproject.proc"
++      
++      bse_container_remove_backedup (BSE_CONTAINER (self), child, ustack);
++#line 282 "bseproject.proc"
++      
++      bse_item_undo_close (ustack);
++    }
++
++  return Bse::Error::NONE;
++}
++
++/* --- get-supers --- */
++static void
++get_supers_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 289 "bseproject.proc"
++ {
++#line 291 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", NULL, NULL,
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_boxed ("super_list", NULL, NULL, BSE_TYPE_IT3M_SEQ, 
SFI_PARAM_STANDARD);
++#line 294 "bseproject.proc"
++}  }
++static Bse::Error
++#line 294 "bseproject.proc"
++get_supers_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 297 "bseproject.proc"
++{
++#line 298 "bseproject.proc"
++  
++  BseProject *project = (BseProject*) bse_value_get_object (in_values++);
++  BseIt3mSeq *iseq;
++  GSList *slist;
++
++#line 303 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (project))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 307 "bseproject.proc"
++  
++  iseq = bse_it3m_seq_new ();
++  for (slist = project->supers; slist; slist = slist->next)
++    bse_it3m_seq_append (iseq, (BseItem*) slist->data);
++
++#line 312 "bseproject.proc"
++  
++  bse_value_take_boxed (out_values++, iseq);
++
++  return Bse::Error::NONE;
++}
++
++
++/* --- get-state --- */
++static void
++get_state_setup (BseProcedureClass *proc, GParamSpec **in_pspecs, GParamSpec **out_pspecs) {
++#line 319 "bseproject.proc"
++ {
++#line 321 "bseproject.proc"
++  *(in_pspecs++)    = bse_param_spec_object ("project", "Project", "The project",
++                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
++  *(out_pspecs++)   = bse_param_spec_genum ("state", "State", "Project playback/activation state",
++                                BSE_TYPE_PROJECT_STATE, BSE_PROJECT_INACTIVE, SFI_PARAM_STANDARD);
++#line 325 "bseproject.proc"
++}  }
++static Bse::Error
++#line 325 "bseproject.proc"
++get_state_exec (BseProcedureClass *proc,
++        const GValue      *in_values,
++        GValue            *out_values)
++#line 328 "bseproject.proc"
++{
++#line 329 "bseproject.proc"
++  
++  BseProject *self = (BseProject*) bse_value_get_object (in_values++);
++
++#line 332 "bseproject.proc"
++  
++  if (!BSE_IS_PROJECT (self))
++    return Bse::Error::PROC_PARAM_INVAL;
++
++#line 336 "bseproject.proc"
++  
++  g_value_set_enum (out_values++, self->state);
++
++  return Bse::Error::NONE;
++}
++
++/* --- Export to BSE --- */
++static void
++__enode_get_midi_notifier__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Retrieve the project's midi notifier object.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 25;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_get_midi_notifier = {
++  { NULL, BSE_EXPORT_NODE_PROC,
++    "BseProject+get-midi-notifier", 
++    NULL,
++    "/Methods/BseProject/General/Get Midi Notifier",
++    NULL,
++    __enode_get_midi_notifier__fill_strings,
++  },
++  0, get_midi_notifier_setup, get_midi_notifier_exec, 
++};
++static void
++__enode_store_bse__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Save supers of a project into a BSE file. "
++          "If no super is specified, the project itself is stored.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 50;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_store_bse = {
++  { (BseExportNode*) &__enode_get_midi_notifier, BSE_EXPORT_NODE_PROC,
++    "BseProject+store-bse", 
++    NULL,
++    "/Methods/BseProject/File/Store",
++    NULL,
++    __enode_store_bse__fill_strings,
++  },
++  0, store_bse_setup, store_bse_exec, 
++};
++static void
++__enode_create_song__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Create a song for this project.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 91;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_create_song = {
++  { (BseExportNode*) &__enode_store_bse, BSE_EXPORT_NODE_PROC,
++    "BseProject+create-song", 
++    NULL,
++    "/Methods/BseProject/General/Create Song",
++    NULL,
++    __enode_create_song__fill_strings,
++  },
++  0, create_song_setup, create_song_exec, 
++};
++static void
++__enode_get_wave_repo__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Ensure the project has a wave repository";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 127;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_get_wave_repo = {
++  { (BseExportNode*) &__enode_create_song, BSE_EXPORT_NODE_PROC,
++    "BseProject+get-wave-repo", 
++    NULL,
++    "/Methods/BseProject/General/Get Wave Repo",
++    NULL,
++    __enode_get_wave_repo__fill_strings,
++  },
++  0, get_wave_repo_setup, get_wave_repo_exec, 
++};
++static void
++__enode_get_sound_font_repo__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Get sound font repository for project";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 154;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_get_sound_font_repo = {
++  { (BseExportNode*) &__enode_get_wave_repo, BSE_EXPORT_NODE_PROC,
++    "BseProject+get-sound-font-repo", 
++    NULL,
++    "/Methods/BseProject/General/Get Sound Font Repo",
++    NULL,
++    __enode_get_sound_font_repo__fill_strings,
++  },
++  0, get_sound_font_repo_setup, get_sound_font_repo_exec, 
++};
++static void
++__enode_create_csynth__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Create a synthsizer network for this project.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 182;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_create_csynth = {
++  { (BseExportNode*) &__enode_get_sound_font_repo, BSE_EXPORT_NODE_PROC,
++    "BseProject+create-csynth", 
++    NULL,
++    "/Methods/BseProject/General/Create Csynth",
++    NULL,
++    __enode_create_csynth__fill_strings,
++  },
++  0, create_csynth_setup, create_csynth_exec, 
++};
++static void
++__enode_create_midi_synth__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Create a MIDI synthesizer network for this project.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 218;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_create_midi_synth = {
++  { (BseExportNode*) &__enode_create_csynth, BSE_EXPORT_NODE_PROC,
++    "BseProject+create-midi-synth", 
++    NULL,
++    "/Methods/BseProject/General/Create Midi Synth",
++    NULL,
++    __enode_create_midi_synth__fill_strings,
++  },
++  0, create_midi_synth_setup, create_midi_synth_exec, 
++};
++static void
++__enode_remove_snet__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Remove an existing synthesizer network from this project.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 254;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_remove_snet = {
++  { (BseExportNode*) &__enode_create_midi_synth, BSE_EXPORT_NODE_PROC,
++    "BseProject+remove-snet", 
++    NULL,
++    "/Methods/BseProject/General/Remove Snet",
++    NULL,
++    __enode_remove_snet__fill_strings,
++  },
++  0, remove_snet_setup, remove_snet_exec, 
++};
++static void
++__enode_get_supers__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Retrieve all supers of this project.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 290;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_get_supers = {
++  { (BseExportNode*) &__enode_remove_snet, BSE_EXPORT_NODE_PROC,
++    "BseProject+get-supers", 
++    NULL,
++    "/Methods/BseProject/General/Get Supers",
++    NULL,
++    __enode_get_supers__fill_strings,
++  },
++  0, get_supers_setup, get_supers_exec, 
++};
++static void
++__enode_get_state__fill_strings (BseExportStrings *es)
++{
++  es->blurb = "Retrieve the current project state.";
++  es->file = "/home/stefan/src/stwbeast/bse/bseproject.proc";
++  es->line = 320;
++  es->authors = "Tim Janik <timj gtk org>";
++  es->license = "GNU Lesser General Public License";
++}
++static BseExportNodeProc __enode_get_state = {
++  { (BseExportNode*) &__enode_get_supers, BSE_EXPORT_NODE_PROC,
++    "BseProject+get-state", 
++    NULL,
++    "/Methods/BseProject/General/Get State",
++    NULL,
++    __enode_get_state__fill_strings,
++  },
++  0, get_state_setup, get_state_exec, 
++};
++extern "C" BseExportNode* bse__builtin_init_bseproject_genprc_cc (void)
++{
++  return (BseExportNode*) &__enode_get_state;
++}
++
++/*
++ * Generated data ends here
++ */
diff --cc bse/bseproject.proc
index 7fe99a0,a219f1c..bca7a6f
--- a/bse/bseproject.proc
+++ b/bse/bseproject.proc
@@@ -6,16 -6,16 +6,16 @@@
  #include <bse/bsesong.hh>
  #include <bse/bseundostack.hh>
  #include <bse/bsewaverepo.hh>
 +#include <bse/bsesoundfontrepo.hh>
  #include <bse/bsecsynth.hh>
  #include <bse/bsemidisynth.hh>
- #include <bse/bsedatapocket.hh>
  #include <bse/bsemidifile.hh>
  #include <bse/bsemidireceiver.hh>
  #include <bse/bsemidinotifier.hh>
  #include <bse/bseengine.hh>
  #include "bsecxxplugin.hh"
+ #include "bsebuiltin_externs.cc"
  
 -
  AUTHORS = "Tim Janik <timj gtk org>";
  LICENSE = "GNU Lesser General Public License";
  
@@@ -283,69 -147,9 +147,37 @@@ METHOD (BseProject, get-wave-repo) 
    /* set output parameters */
    bse_value_set_object (out_values++, wrepo);
  
-   return BSE_ERROR_NONE;
+   return Bse::Error::NONE;
  }
  
 +METHOD (BseProject, get-sound-font-repo) {
 +  HELP  = "Get sound font repository for project";
 +  IN    = bse_param_spec_object ("project", "Project", "The project",
 +                                 BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
 +  OUT   = bse_param_spec_object ("sfrepo", "Sound Font Repo", "The project's unique sound font repo",
 +                                 BSE_TYPE_SOUND_FONT_REPO, SFI_PARAM_STANDARD);
 +
 +} BODY (BseProcedureClass *proc,
 +        const GValue      *in_values,
 +        GValue            *out_values)
 +{
 +  /* extract parameter values */
 +  BseProject *project = BSE_PROJECT (bse_value_get_object (in_values++));
 +  BseSoundFontRepo *sfrepo = NULL;
 +
 +  /* check parameters */
 +  if (!BSE_IS_PROJECT (project))
-     return BSE_ERROR_PROC_PARAM_INVAL;
++    return Bse::Error::PROC_PARAM_INVAL;
 +
 +  /* action */
 +  sfrepo = bse_project_get_sound_font_repo (project);
 +
 +  /* set output parameters */
 +  bse_value_set_object (out_values++, sfrepo);
 +
-   return BSE_ERROR_NONE;
- }
- 
- METHOD (BseProject, get-data-pocket) {
-   HELP  = "Retrieve a specifically named data pocket for this project";
-   IN    = bse_param_spec_object ("project", "Project", "The project",
-                                  BSE_TYPE_PROJECT, SFI_PARAM_STANDARD);
-   IN    = sfi_pspec_string ("name", "Name", "Name of the data pocket",
-                             NULL, SFI_PARAM_STANDARD);
-   OUT   = bse_param_spec_object ("data_pocket", "Data Pocket", "The data pocket",
-                                  BSE_TYPE_DATA_POCKET, SFI_PARAM_STANDARD);
- } BODY (BseProcedureClass *proc,
-         const GValue      *in_values,
-         GValue            *out_values)
- {
-   /* extract parameter values */
-   BseProject *project = (BseProject*) bse_value_get_object (in_values++);
-   const char *name = sfi_value_get_string (in_values++);
-   BseItem *item;
- 
-   /* check parameters */
-   if (!BSE_IS_PROJECT (project) || !name)
-     return BSE_ERROR_PROC_PARAM_INVAL;
- 
-   /* action */
-   item = bse_project_lookup_typed_item (project, BSE_TYPE_DATA_POCKET, name);
-   if (!item)
-     item = (BseItem*) bse_container_new_child (BSE_CONTAINER (project), BSE_TYPE_DATA_POCKET, "uname", 
name, NULL);
- 
-   /* set output parameters */
-   bse_value_set_object (out_values++, item);
- 
-   return BSE_ERROR_NONE;
++  return Bse::Error::NONE;
 +}
 +
  METHOD (BseProject, create-csynth) {
    HELP  = "Create a synthsizer network for this project.";
    IN    = bse_param_spec_object ("project", "Project", "The project",
diff --cc bse/bsesoundfont.cc
index 9768890,0000000..38dcfa0
mode 100644,000000..100644
--- a/bse/bsesoundfont.cc
+++ b/bse/bsesoundfont.cc
@@@ -1,379 -1,0 +1,379 @@@
 +// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
 +#include "bsesoundfont.hh"
 +#include "bsesoundfontrepo.hh"
 +#include "bsesoundfontpreset.hh"
 +#include "bsemain.hh"
 +#include "bsestorage.hh"
 +#include "bseprocedure.hh"
 +#include "gsldatahandle.hh"
 +#include "bseserver.hh"
 +#include "bseloader.hh"
 +
 +#include <string.h>
 +
 +#define parse_or_return         bse_storage_scanner_parse_or_return
 +
 +enum {
 +  PARAM_0,
 +  PARAM_FILE_NAME,
 +};
 +
 +/* --- prototypes --- */
 +
 +
 +/* --- variables --- */
 +static void       *parent_class = NULL;
 +static GQuark      quark_load_sound_font = 0;
 +
 +
 +/* --- functions --- */
 +static void
 +bse_sound_font_init (BseSoundFont *sound_font)
 +{
 +  sound_font->blob = NULL;
 +  sound_font->sfont_id = -1;
 +  sound_font->sfrepo = NULL;
 +}
 +
 +static void
 +bse_sound_font_set_property (GObject      *object,
 +                           guint         param_id,
 +                           const GValue *value,
 +                           GParamSpec   *pspec)
 +{
 +  switch (param_id)
 +    {
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +static void
 +bse_sound_font_get_property (GObject    *object,
 +                           guint       param_id,
 +                           GValue     *value,
 +                           GParamSpec *pspec)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (object);
 +  switch (param_id)
 +    {
 +    case PARAM_FILE_NAME:
 +      if (sound_font->blob)
 +        sfi_value_set_string (value, bse_storage_blob_file_name (sound_font->blob));
 +      else
 +        sfi_value_set_string (value, NULL);
 +      break;
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +static void
 +bse_sound_font_dispose (GObject *object)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (object);
 +  if (sound_font->sfont_id != -1)
 +    bse_sound_font_unload (sound_font);
 +  if (sound_font->sfrepo)
 +    {
 +      g_object_unref (sound_font->sfrepo);
 +      sound_font->sfrepo = NULL;
 +    }
 +  /* chain parent class' handler */
 +  G_OBJECT_CLASS (parent_class)->dispose (object);
 +}
 +
 +static void
 +bse_sound_font_finalize (GObject *object)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (object);
 +
 +  /* free blob */
 +  if (sound_font->blob)
 +    {
 +      bse_storage_blob_unref (sound_font->blob);
 +      sound_font->blob = NULL;
 +    }
 +
 +  if (sound_font->sfrepo != NULL || sound_font->blob != NULL || sound_font->sfont_id != -1)
 +    g_warning (G_STRLOC ": some resources could not be freed.");
 +
 +  /* chain parent class' handler */
 +  G_OBJECT_CLASS (parent_class)->finalize (object);
 +}
 +
- BseErrorType
++Bse::Error
 +bse_sound_font_load_blob (BseSoundFont    *self,
 +                          BseStorageBlob  *blob,
 +                        gboolean         init_presets)
 +{
 +  if (self->sfrepo == NULL)
 +    {
 +      self->sfrepo = BSE_SOUND_FONT_REPO (BSE_ITEM (self)->parent);
 +      g_object_ref (self->sfrepo);
 +    }
 +
-   g_return_val_if_fail (blob != NULL, BSE_ERROR_INTERNAL);
-   g_return_val_if_fail (self->sfrepo != NULL, BSE_ERROR_INTERNAL);
-   g_return_val_if_fail (self->sfont_id == -1, BSE_ERROR_INTERNAL);
++  g_return_val_if_fail (blob != NULL, Bse::Error::INTERNAL);
++  g_return_val_if_fail (self->sfrepo != NULL, Bse::Error::INTERNAL);
++  g_return_val_if_fail (self->sfont_id == -1, Bse::Error::INTERNAL);
 +
 +  bse_storage_blob_ref (blob);
 +  if (self->blob)
 +    {
 +      bse_storage_blob_unref (self->blob);
 +      self->blob = NULL;
 +    }
 +
 +  fluid_synth_t *fluid_synth = bse_sound_font_repo_lock_fluid_synth (self->sfrepo);
 +  int sfont_id = fluid_synth_sfload (fluid_synth, bse_storage_blob_file_name (blob), 0);
-   BseErrorType error;
++  Bse::Error error;
 +  if (sfont_id != -1)
 +    {
 +      if (init_presets)
 +      {
 +        fluid_sfont_t *fluid_sfont = fluid_synth_get_sfont_by_id (fluid_synth, sfont_id);
 +        fluid_preset_t fluid_preset;
 +
 +        fluid_sfont->iteration_start (fluid_sfont);
 +        while (fluid_sfont->iteration_next (fluid_sfont, &fluid_preset))
 +          {
 +            BseSoundFontPreset *sound_font_preset;
 +              sound_font_preset = (BseSoundFontPreset *) g_object_new (BSE_TYPE_SOUND_FONT_PRESET,
 +                                                                     "uname", fluid_preset.get_name 
(&fluid_preset),
 +                                                                     NULL);
 +            bse_container_add_item (BSE_CONTAINER (self), BSE_ITEM (sound_font_preset));
 +            bse_sound_font_preset_init_preset (sound_font_preset, &fluid_preset);
 +          }
 +      }
 +      self->sfont_id = sfont_id;
 +      self->blob = blob;
-       error = BSE_ERROR_NONE;
++      error = Bse::Error::NONE;
 +    }
 +  else
 +    {
 +      bse_storage_blob_unref (blob);
-       error = BSE_ERROR_WAVE_NOT_FOUND;
++      error = Bse::Error::WAVE_NOT_FOUND;
 +    }
 +  bse_sound_font_repo_unlock_fluid_synth (self->sfrepo);
 +  return error;
 +}
 +
 +void
 +bse_sound_font_unload (BseSoundFont *sound_font)
 +{
 +  g_return_if_fail (sound_font->sfrepo != NULL);
 +
 +  if (sound_font->sfont_id != -1)
 +    {
 +      fluid_synth_t *fluid_synth = bse_sound_font_repo_lock_fluid_synth (sound_font->sfrepo);
 +      fluid_synth_sfunload (fluid_synth, sound_font->sfont_id, 1 /* reset presets */);
 +      bse_sound_font_repo_unlock_fluid_synth (sound_font->sfrepo);
 +    }
 +  sound_font->sfont_id = -1;
 +}
 +
- BseErrorType
++Bse::Error
 +bse_sound_font_reload (BseSoundFont *sound_font)
 +{
-   g_return_val_if_fail (sound_font->sfont_id == -1, BSE_ERROR_INTERNAL);
++  g_return_val_if_fail (sound_font->sfont_id == -1, Bse::Error::INTERNAL);
 +
 +  return bse_sound_font_load_blob (sound_font, sound_font->blob, FALSE);
 +}
 +
 +static void
 +bse_sound_font_store_private (BseObject  *object,
 +                            BseStorage *storage)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (object);
 +  /* chain parent class' handler */
 +  BSE_OBJECT_CLASS (parent_class)->store_private (object, storage);
 +
 +  if (!BSE_STORAGE_SELF_CONTAINED (storage) && !bse_storage_blob_is_temp_file (sound_font->blob))
 +    {
 +      bse_storage_break (storage);
 +      bse_storage_printf (storage, "(load-sound-font \"%s\")", bse_storage_blob_file_name 
(sound_font->blob));
 +    }
 +  else
 +    {
 +      bse_storage_break (storage);
 +      bse_storage_printf (storage, "(load-sound-font ");
 +      bse_storage_put_blob (storage, sound_font->blob);
 +      bse_storage_printf (storage, ")");
 +    }
 +}
 +
 +static GTokenType
 +bse_sound_font_restore_private (BseObject  *object,
 +                              BseStorage *storage,
 +                                GScanner   *scanner)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (object);
 +  GTokenType expected_token;
 +  GQuark quark;
 +
 +  /* chain parent class' handler */
 +  if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
 +    return BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner);
 +
 +  /* parse storage commands */
 +  quark = g_quark_try_string (scanner->next_value.v_identifier);
 +  if (quark == quark_load_sound_font)
 +    {
 +      BseStorageBlob *blob;
-       BseErrorType error;
++      Bse::Error error;
 +
 +      g_scanner_get_next_token (scanner); /* eat quark identifier */
 +      if (g_scanner_peek_next_token (scanner) == G_TOKEN_STRING)
 +      {
 +        parse_or_return (scanner, G_TOKEN_STRING);
 +        blob = bse_storage_blob_new_from_file (scanner->value.v_string, FALSE);
 +      }
 +      else
 +      {
 +          GTokenType token = bse_storage_parse_blob (storage, &blob);
 +        if (token != G_TOKEN_NONE)
 +          {
 +            if (blob)
 +              bse_storage_blob_unref (blob);
 +              return token;
 +          }
 +      }
 +      if (g_scanner_peek_next_token (scanner) != ')')
 +      {
 +        bse_storage_blob_unref (blob);
 +        return GTokenType (')');
 +      }
 +      parse_or_return (scanner, ')');
 +      error = bse_sound_font_load_blob (sound_font, blob, FALSE);
-       if (error)
++      if (error != 0)
 +      bse_storage_warn (storage, "failed to load sound font \"%s\": %s",
 +                                  bse_storage_blob_file_name (blob), bse_error_blurb (error));
 +      bse_storage_blob_unref (blob);
 +      expected_token = G_TOKEN_NONE; /* got ')' */
 +    }
 +  else /* chain parent class' handler */
 +    expected_token = BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner);
 +
 +  return expected_token;
 +}
 +
 +
 +static void
 +bse_sound_font_add_item (BseContainer *container,
 +                       BseItem      *item)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (container);
 +
 +  if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT_PRESET))
 +    sound_font->presets = g_list_append (sound_font->presets, item);
 +  else
 +    g_warning ("BseSoundFont: cannot hold non-sound-font-preset item type `%s'",
 +             BSE_OBJECT_TYPE_NAME (item));
 +
 +  /* chain parent class' add_item handler */
 +  BSE_CONTAINER_CLASS (parent_class)->add_item (container, item);
 +}
 +
 +static void
 +bse_sound_font_forall_items (BseContainer      *container,
 +                           BseForallItemsFunc func,
 +                           gpointer           data)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (container);
 +  GList *list;
 +
 +  list = sound_font->presets;
 +  while (list)
 +    {
 +      BseItem *item;
 +
 +      item = BSE_ITEM (list->data);
 +      list = list->next;
 +      if (!func (item, data))
 +      return;
 +    }
 +}
 +
 +static void
 +bse_sound_font_remove_item (BseContainer *container,
 +                          BseItem      *item)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (container);
 +
 +  if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT_PRESET))
 +    sound_font->presets = g_list_remove (sound_font->presets, item);
 +  else
 +    g_warning ("BseSoundFontRepo: cannot hold non-sound-font-preset item type `%s'",
 +             BSE_OBJECT_TYPE_NAME (item));
 +
 +  /* chain parent class' remove_item handler */
 +  BSE_CONTAINER_CLASS (parent_class)->remove_item (container, item);
 +}
 +
 +static void
 +bse_sound_font_release_children (BseContainer *container)
 +{
 +  BseSoundFont *self = BSE_SOUND_FONT (container);
 +
 +  while (self->presets)
 +    bse_container_remove_item (container, BSE_ITEM (self->presets->data));
 +
 +  /* chain parent class' handler */
 +  BSE_CONTAINER_CLASS (parent_class)->release_children (container);
 +}
 +
 +
 +static void
 +bse_sound_font_class_init (BseSoundFontClass *klass)
 +{
 +  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 +  BseObjectClass *object_class = BSE_OBJECT_CLASS (klass);
 +  BseContainerClass *container_class = BSE_CONTAINER_CLASS (klass);
 +
 +  parent_class = g_type_class_peek_parent (klass);
 +
 +  gobject_class->set_property = bse_sound_font_set_property;
 +  gobject_class->get_property = bse_sound_font_get_property;
 +  gobject_class->dispose = bse_sound_font_dispose;
 +  gobject_class->finalize = bse_sound_font_finalize;
 +
 +  container_class->add_item = bse_sound_font_add_item;
 +  container_class->remove_item = bse_sound_font_remove_item;
 +  container_class->forall_items = bse_sound_font_forall_items;
 +  container_class->release_children = bse_sound_font_release_children;
 +
 +  object_class->store_private = bse_sound_font_store_private;
 +  object_class->restore_private = bse_sound_font_restore_private;
 +
 +  quark_load_sound_font = g_quark_from_static_string ("load-sound-font");
 +
 +  bse_object_class_add_param (object_class, "Locator",
 +                            PARAM_FILE_NAME,
 +                            sfi_pspec_string ("file_name", "File Name", NULL,
 +                                              NULL, "G:r"));
 +}
 +
 +BSE_BUILTIN_TYPE (BseSoundFont)
 +{
 +  static const GTypeInfo sound_font_info = {
 +    sizeof (BseSoundFontClass),
 +
 +    (GBaseInitFunc) NULL,
 +    (GBaseFinalizeFunc) NULL,
 +    (GClassInitFunc) bse_sound_font_class_init,
 +    (GClassFinalizeFunc) NULL,
 +    NULL /* class_data */,
 +
 +    sizeof (BseSoundFont),
 +    0  /* n_preallocs */,
 +    (GInstanceInitFunc) bse_sound_font_init,
 +  };
 +
 +  return bse_type_register_static (BSE_TYPE_CONTAINER,
 +                                 "BseSoundFont",
 +                                 "BSE sound_font type",
 +                                   __FILE__, __LINE__,
 +                                   &sound_font_info);
 +}
diff --cc bse/bsesoundfont.hh
index 13f724c,0000000..ab0784b
mode 100644,000000..100644
--- a/bse/bsesoundfont.hh
+++ b/bse/bsesoundfont.hh
@@@ -1,35 -1,0 +1,35 @@@
 +// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
 +#ifndef __BSE_SOUND_FONT_HH__
 +#define __BSE_SOUND_FONT_HH__
 +
 +#include      <bse/bsecontainer.hh>
 +#include        <bse/bsestorage.hh>
 +
 +G_BEGIN_DECLS
 +
 +/* --- BSE type macros --- */
 +#define BSE_TYPE_SOUND_FONT             (BSE_TYPE_ID (BseSoundFont))
 +#define BSE_SOUND_FONT(object)                  (G_TYPE_CHECK_INSTANCE_CAST ((object), BSE_TYPE_SOUND_FONT, 
BseSoundFont))
 +#define BSE_SOUND_FONT_CLASS(class)     (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_SOUND_FONT, 
BseSoundFontClass))
 +#define BSE_IS_SOUND_FONT(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), BSE_TYPE_SOUND_FONT))
 +#define BSE_IS_SOUND_FONT_CLASS(class)          (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_SOUND_FONT))
 +#define BSE_SOUND_FONT_GET_CLASS(object)  (G_TYPE_INSTANCE_GET_CLASS ((object), BSE_TYPE_SOUND_FONT, 
BseSoundFontClass))
 +
 +struct BseSoundFont : BseContainer {
 +  BseStorageBlob    *blob;
 +  int                sfont_id;
 +  BseSoundFontRepo  *sfrepo;
 +  GList             *presets;
 +};
 +struct BseSoundFontClass : BseContainerClass
 +{};
 +
- BseErrorType    bse_sound_font_load_blob      (BseSoundFont       *sound_font,
++Bse::Error      bse_sound_font_load_blob      (BseSoundFont       *sound_font,
 +                                               BseStorageBlob     *blob,
 +                                               gboolean            init_presets);
 +void          bse_sound_font_unload           (BseSoundFont       *sound_font);
- BseErrorType    bse_sound_font_reload           (BseSoundFont       *sound_font);
++Bse::Error      bse_sound_font_reload           (BseSoundFont       *sound_font);
 +
 +G_END_DECLS
 +
 +#endif /* __BSE_SOUND_FONT_HH__ */
diff --cc bse/bsesoundfontosc.cc
index c289f0a,0000000..8e23fb2
mode 100644,000000..100644
--- a/bse/bsesoundfontosc.cc
+++ b/bse/bsesoundfontosc.cc
@@@ -1,672 -1,0 +1,672 @@@
 +// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
 +#include "bsesoundfontosc.hh"
 +
 +#include <bse/bsecategories.hh>
 +#include <bse/bseengine.hh>
 +#include <bse/bseproject.hh>
 +#include <bse/bsesoundfontrepo.hh>
 +#include <bse/bsesoundfont.hh>
 +#include <bse/bsesnet.hh>
 +#include <bse/bsemidireceiver.hh>
 +#include "gslcommon.hh"
 +
 +#include <string.h>
 +
 +/*------------------------------------------------------------------------------------------------
 + * overview of how soundfont support is implemented
 + *------------------------------------------------------------------------------------------------
 + * what we want:
 + *  - use existing soundfonts & fluidsynth replay code
 + *  - be able to use soundfont presets (instruments) instead of synthesis instruments on a
 + *    per-track basis
 + *  - multiple tracks should be able to share the same soundfont (as these are huge)
 + *  - use the standard beast mixer with tracks that use soundfonts
 + *
 + * To be able to use the fluidsynth API, and let fluidsynth render the output,
 + * this code will simply relay the events from the midi receiver to the
 + * fluidsynth engine using bse_midi_receiver_add_event_handler. The fluidsynth
 + * engine itself has no concept of what tracks exist in BEAST. In fact, to be
 + * able to share the same soundfont for many tracks, we have to pass all events
 + * from all tracks that use the same soundfont to fluidsynth in one step.
 + *
 + * To be able to still get many mixer tracks, the code below will create
 + * multiple fluidsynth channels, each containing the sample data for one beast
 + * track. This make post-processing networks and using the beast mixer work.
 + * However, we cannot use fluidsynth effects. This is because fluidsynth can
 + * only render one effect track containing the accumulated effects of all input
 + * events, whereas we want to be able to process every beast track seperately.
 + *
 + * However this limitation can be workarounded by using beast to render the
 + * effects, either in per-beast-track postprocessing networks or using per-song
 + * post-processing network.
 + *
 + * Now that we have a mapping from the midi events to the fluidsynth output
 + * tracks, the only thing that needs to be done is getting the sample data into
 + * the bse engine. To do that, we create standard engine modules. These do not
 + * compute any sample data.  Instead, they just access memory that is shared
 + * between all osc modules. The first sound font osc module that is scheduled
 + * by the engine calls process_fluid_L, to update the shared memory containing
 + * the fluidsynth output. All other sound font osc engine modules that are
 + * called after that simply read the samples that was already computed when the
 + * first engine module's process function was called.
 + *
 + * The check:
 + *
 + *   gint64 now_tick_stamp = Bse::TickStamp::current();
 + *   if (sfrepo->channel_values_tick_stamp != now_tick_stamp)
 + *        ...
 + *
 + * ensures this. Here the shared state is managed by the sound font repo, and
 + * only updated once for all sound font engine modules. Locking is used to
 + * ensure that there are no races,
 + *
 + *   bse_sound_font_repo_lock_fluid_synth (sfrepo); 
 + *
 + * ensures that there is always at most one sound font engine module that has access
 + * to the shared state, and so the actual fluidsynth code to process the events and
 + * update the shared sample data is also executed exactly once.
 + *
 + * Note that IF the bse engine WOULD use multiple CPUs (it currently doesn't),
 + * the locking forces the sound font osc engine modules to wait for the
 + * computation of the first module that got the lock. This may be undesirable
 + * since it could block the computations on all CPUs, although other engine
 + * modules that are unrelated to fluidsynth could be processed. One possibility
 + * to solve this problem would be to enhance the engine and allow the sound
 + * font osc modules to use some "CPU affinity" setting which lets the engine
 + * know that all these modules should be processed on the same CPU.
 + *
 + * CPU affinity will also enhance performance (with a muli core bse engine)
 + * since then the actual fluid synth rendering code will always run on the same
 + * CPU (instead of the CPU that the first engine module runs on, which will can
 + * change from engine block to engine block).
 + *------------------------------------------------------------------------------------------------
 + */
 +
 +/* --- parameters --- */
 +enum
 +{
 +  PARAM_0,
 +  PARAM_PRESET
 +};
 +
 +
 +/* --- prototypes --- */
 +static void    bse_sound_font_osc_init          (BseSoundFontOsc       *sound_font_osc);
 +static void    bse_sound_font_osc_class_init    (BseSoundFontOscClass  *klass);
 +static void    bse_sound_font_osc_set_property  (GObject               *object,
 +                                                 guint                  param_id,
 +                                                 const GValue          *value,
 +                                                 GParamSpec            *pspec);
 +static void    bse_sound_font_osc_get_property  (GObject               *object,
 +                                                 guint                  param_id,
 +                                                 GValue                *value,
 +                                                 GParamSpec            *pspec);
 +static void    bse_sound_font_osc_get_candidates (BseItem              *item,
 +                                                  guint                 param_id,
 +                                                  BsePropertyCandidates *pc,
 +                                                  GParamSpec           *pspec);
 +static void    bse_sound_font_osc_context_create (BseSource            *source,
 +                                                  guint                 context_handle,
 +                                                  BseTrans             *trans);
 +static void    bse_sound_font_osc_context_dismiss (BseSource           *source,
 +                                                   guint                context_handle,
 +                                                   BseTrans            *trans);
 +static void    bse_sound_font_osc_update_modules (BseSoundFontOsc      *sound_font_osc,
 +                                                  BseTrans             *trans);
 +static void      bse_sound_font_osc_dispose        (GObject              *object);
 +static void      bse_sound_font_osc_finalize       (GObject              *object);
 +
 +
 +/* --- variables --- */
 +static gpointer        parent_class = NULL;
 +
 +
 +/* --- functions --- */
 +BSE_BUILTIN_TYPE (BseSoundFontOsc)
 +{
 +  static const GTypeInfo type_info = {
 +    sizeof (BseSoundFontOscClass),
 +
 +    (GBaseInitFunc) NULL,
 +    (GBaseFinalizeFunc) NULL,
 +    (GClassInitFunc) bse_sound_font_osc_class_init,
 +    (GClassFinalizeFunc) NULL,
 +    NULL /* class_data */,
 +
 +    sizeof (BseSoundFontOsc),
 +    0 /* n_preallocs */,
 +    (GInstanceInitFunc) bse_sound_font_osc_init,
 +  };
 +  GType type_id;
 +
 +  type_id = bse_type_register_static (BSE_TYPE_SOURCE,
 +                                    "BseSoundFontOsc",
 +                                    "This internal module wraps fluid synth which plays sound font 
contents",
 +                                      __FILE__, __LINE__,
 +                                      &type_info);
 +  return type_id;
 +}
 +
 +static void
 +bse_sound_font_osc_class_init (BseSoundFontOscClass *klass)
 +{
 +  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 +  BseObjectClass *object_class = BSE_OBJECT_CLASS (klass);
 +  BseSourceClass *source_class = BSE_SOURCE_CLASS (klass);
 +  BseItemClass *item_class = BSE_ITEM_CLASS (klass);
 +  guint ochannel;
 +
 +  parent_class = g_type_class_peek_parent (klass);
 +
 +  gobject_class->set_property = bse_sound_font_osc_set_property;
 +  gobject_class->get_property = bse_sound_font_osc_get_property;
 +  gobject_class->finalize = bse_sound_font_osc_finalize;
 +  gobject_class->dispose = bse_sound_font_osc_dispose;
 +
 +  item_class->get_candidates = bse_sound_font_osc_get_candidates;
 +
 +  source_class->context_create = bse_sound_font_osc_context_create;
 +  source_class->context_dismiss = bse_sound_font_osc_context_dismiss;
 +
 +  bse_object_class_add_param (object_class, _("Sound Font Preset"),
 +                              PARAM_PRESET,
 +                              bse_param_spec_object ("preset", _("Preset"), _("Sound Font Preset to be used 
during replay"),
 +                                                     BSE_TYPE_SOUND_FONT_PRESET, SFI_PARAM_STANDARD));
 +
 +  ochannel = bse_source_class_add_ochannel (source_class, "left-out", _("Left Out"), _("Output of the fluid 
synth soundfont synthesizer"));
 +  g_assert (ochannel == BSE_SOUND_FONT_OSC_OCHANNEL_LEFT_OUT);
 +  ochannel = bse_source_class_add_ochannel (source_class, "right-out", _("Right Out"), _("Output of the 
fluid synth soundfont synthesizer"));
 +  g_assert (ochannel == BSE_SOUND_FONT_OSC_OCHANNEL_RIGHT_OUT);
 +  ochannel = bse_source_class_add_ochannel (source_class, "done-out", _("Done Out"), _("Done Output"));
 +  g_assert (ochannel == BSE_SOUND_FONT_OSC_OCHANNEL_DONE_OUT);
 +}
 +
 +static void
 +bse_sound_font_osc_init (BseSoundFontOsc *self)
 +{
 +  memset (&self->config, 0, sizeof (self->config));
 +  self->config.silence_bound = bse_engine_sample_freq() * 0.020;  /* output is zero for 20 ms => set done 
output */
 +  self->preset = NULL;
 +}
 +
 +static void
 +bse_sound_font_osc_dispose (GObject *object)
 +{
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (object);
 +
 +  if (self->config.sfrepo)
 +    {
 +      bse_sound_font_repo_remove_osc (self->config.sfrepo, self->config.osc_id);
 +
 +      self->config.sfrepo = NULL;
 +    }
 +
 +  /* chain parent class' handler */
 +  G_OBJECT_CLASS (parent_class)->dispose (object);
 +}
 +
 +static void
 +bse_sound_font_osc_finalize (GObject *object)
 +{
 +  //BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (object);
 +
 +  /* chain parent class' handler */
 +  G_OBJECT_CLASS (parent_class)->finalize (object);
 +}
 +
 +
 +static BseSoundFontRepo*
 +get_sfrepo (BseSoundFontOsc *self)
 +{
 +  if (!self->config.sfrepo)
 +    {
 +      BseProject *project = bse_item_get_project (BSE_ITEM (self));
 +      if (project)
 +      {
 +        self->config.sfrepo = bse_project_get_sound_font_repo (project);
 +        self->config.osc_id = bse_sound_font_repo_add_osc (self->config.sfrepo, self);
 +      }
 +      else
 +      {
 +        g_warning ("BseSoundFontOsc: could not find sfrepo\n");
 +        self->config.sfrepo = NULL;
 +      }
 +    }
 +  return self->config.sfrepo;
 +}
 +
 +static void
 +bse_sound_font_osc_uncross_preset (BseItem *owner,
 +                                 BseItem *ref_item)
 +{
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (owner);
 +  bse_item_set (self, "preset", NULL, NULL);
 +}
 +
 +
 +static void
 +bse_sound_font_osc_set_property (GObject      *object,
 +                               guint         param_id,
 +                               const GValue *value,
 +                               GParamSpec   *pspec)
 +{
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (object);
 +
 +  switch (param_id)
 +    {
 +      BseSoundFontPreset *preset;
 +    case PARAM_PRESET:
 +      preset = BSE_SOUND_FONT_PRESET (bse_value_get_object (value));
 +      if (preset != self->preset)
 +        {
 +          self->preset = preset;
 +          if (self->preset)
 +            {
 +              bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->preset), 
bse_sound_font_osc_uncross_preset);
 +              bse_object_proxy_notifies (self->preset, self, "notify::preset");
 +            self->config.sfont_id = BSE_SOUND_FONT (BSE_ITEM (self->preset)->parent)->sfont_id;
 +            self->config.bank = self->preset->bank;
 +            self->config.program = self->preset->program;
 +            self->config.update_preset++;
 +              bse_sound_font_osc_update_modules (self, NULL);
 +            }
 +        }
 +      break;
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +static void
 +bse_sound_font_osc_get_property (GObject     *object,
 +                               guint        param_id,
 +                               GValue      *value,
 +                               GParamSpec  *pspec)
 +{
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (object);
 +
 +  switch (param_id)
 +    {
 +    case PARAM_PRESET:
 +      bse_value_set_object (value, self->preset);
 +      break;
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +
 +static void
 +bse_sound_font_osc_get_candidates (BseItem               *item,
 +                                   guint                  param_id,
 +                                   BsePropertyCandidates *pc,
 +                                   GParamSpec            *pspec)
 +{
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (item);
 +  switch (param_id)
 +    {
 +    case PARAM_PRESET:
 +      bse_property_candidate_relabel (pc, _("Available Presets"), _("List of available sound font presets 
to choose as fluid synth preset"));
 +      bse_sound_font_repo_list_all_presets (get_sfrepo (self), pc->items);
 +      break;
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +
 +typedef struct
 +{
 +  BseSoundFontOscConfig       config;
 +  int                 last_update_preset;
 +  guint64               n_silence_samples;    // for done detection
 +} SoundFontOscModule;
 +
 +static void
 +bse_sound_font_osc_update_modules (BseSoundFontOsc *sound_font_osc,
 +                                 BseTrans        *trans)
 +{
 +  get_sfrepo (sound_font_osc);
 +
 +  if (BSE_SOURCE_PREPARED (sound_font_osc))
 +    {
 +      bse_source_update_modules (BSE_SOURCE (sound_font_osc),
 +                               G_STRUCT_OFFSET (SoundFontOscModule, config),
 +                               &sound_font_osc->config,
 +                               sizeof (sound_font_osc->config),
 +                               trans);
 +    }
 +}
 +
 +static void
 +sound_font_osc_reset (BseModule *module)
 +{
 +  SoundFontOscModule *flmod = (SoundFontOscModule *) module->user_data;
 +
 +  flmod->last_update_preset = -1;
 +}
 +
 +/* process_fluid is only called once per block, not once per module
 + */
 +static void
 +process_fluid_L (BseSoundFontRepo   *sfrepo,
 +               fluid_synth_t      *fluid_synth,
 +                 guint64           now_tick_stamp)
 +{
 +  float **channel_values_left = (float **) g_alloca (sfrepo->n_fluid_channels * sizeof (float *));
 +  float **channel_values_right = (float **) g_alloca (sfrepo->n_fluid_channels * sizeof (float *));
 +  float null_fx[BSE_STREAM_MAX_VALUES];
 +  float *channel_fx_null[2] = { null_fx, null_fx };
 +  int i;
 +
 +  g_return_if_fail (now_tick_stamp > sfrepo->channel_values_tick_stamp);
 +  sfrepo->channel_values_tick_stamp = now_tick_stamp;
 +
 +  /* Sample precise timing: If events don't occur at block boundary, the block
 +     is partially calculated, then the event is executed, and then the rest of
 +     the block (until the next event) is calculated, and so on */
 +  for (i = 0; i < sfrepo->n_fluid_channels; i++)
 +    {
 +      channel_values_left[i] = sfrepo->channel_values_left[i];
 +      channel_values_right[i] = sfrepo->channel_values_right[i];
 +    }
 +  guint values_remaining = bse_engine_block_size();
 +  while (values_remaining)
 +    {
 +      /* get 1st event tick stamp */
 +      BseFluidEvent *event = NULL;
 +      guint64 event_tick_stamp;
 +      if (sfrepo->fluid_events)
 +      {
 +        event = (BseFluidEvent *) sfrepo->fluid_events->data;
 +        event_tick_stamp = event->tick_stamp;
 +      }
 +      else
 +      {
 +        /* if no event is present, the earliest event that can occur is after this block */
 +        event_tick_stamp = now_tick_stamp + values_remaining;
 +      }
 +      if (event_tick_stamp <= now_tick_stamp)      /* past or present event -> process it */
 +      {
 +        switch (event->command)
 +          {
 +            case BSE_MIDI_NOTE_ON:    fluid_synth_noteon (fluid_synth, event->channel, event->arg1, 
event->arg2);
 +                                      sfrepo->n_silence_samples[event->channel] = 0;
 +                                      break;
 +            case BSE_MIDI_NOTE_OFF:   fluid_synth_noteoff (fluid_synth, event->channel, event->arg1);
 +                                      break;
 +            case BSE_MIDI_PITCH_BEND: fluid_synth_pitch_bend (fluid_synth, event->channel, event->arg1);
 +                                      break;
 +            case BSE_FLUID_SYNTH_PROGRAM_SELECT:
 +                                      fluid_synth_program_select (fluid_synth, event->channel,
 +                                                                  event->sfont_id,
 +                                                                  event->arg1, event->arg2);
 +                                      break;
 +            case BSE_MIDI_X_CONTINUOUS_CHANGE:
 +                                      fluid_synth_cc (fluid_synth, event->channel,
 +                                                      event->arg1, event->arg2);
 +                                      break;
 +          }
 +        sfrepo->fluid_events = sfi_ring_remove_node (sfrepo->fluid_events, sfrepo->fluid_events);
 +        g_free (event);
 +      }
 +      else                                                 /* future event tick stamp: process audio until 
then */
 +      {
 +        gint64 values_todo = MIN (values_remaining, event_tick_stamp - now_tick_stamp);
 +        fluid_synth_nwrite_float (fluid_synth, values_todo,
 +                                  channel_values_left, channel_values_right,
 +                                  channel_fx_null, channel_fx_null);
 +        values_remaining -= values_todo;
 +        now_tick_stamp += values_todo;
 +        for (i = 0; i < sfrepo->n_fluid_channels; i++)          /* increment fluid synth output buffer 
pointers */
 +          {
 +            channel_values_left[i] += values_todo;
 +            channel_values_right[i] += values_todo;
 +          }
 +      }
 +    }
 +}
 +
 +static void
 +sound_font_osc_process (BseModule *module,
 +                      guint      n_values)
 +{
 +  SoundFontOscModule *flmod = (SoundFontOscModule *) module->user_data;
 +  BseSoundFontRepo *sfrepo = flmod->config.sfrepo;
 +  fluid_synth_t *fluid_synth = bse_sound_font_repo_lock_fluid_synth (sfrepo);
 +  guint i;
 +  if (flmod->config.update_preset != flmod->last_update_preset)
 +    {
 +      fluid_synth_program_select (fluid_synth,        
flmod->config.sfrepo->channel_map[flmod->config.osc_id],
 +                                              flmod->config.sfont_id, flmod->config.bank, 
flmod->config.program);
 +      flmod->last_update_preset = flmod->config.update_preset;
 +    }
 +  gint64 now_tick_stamp = Bse::TickStamp::current();
 +  if (sfrepo->channel_values_tick_stamp != now_tick_stamp)
 +    process_fluid_L (sfrepo, fluid_synth, now_tick_stamp);
 +
 +  float *left_output = sfrepo->channel_values_left[sfrepo->channel_map[flmod->config.osc_id]];
 +  float *right_output = sfrepo->channel_values_right[sfrepo->channel_map[flmod->config.osc_id]];
 +
 +  int delta = bse_module_tick_stamp (module) - now_tick_stamp;
 +  if (delta + n_values <= bse_engine_block_size())    /* paranoid check, should always pass */
 +    {
 +      left_output += delta;
 +      right_output += delta;
 +      BSE_MODULE_OSTREAM (module, BSE_SOUND_FONT_OSC_OCHANNEL_LEFT_OUT).values = left_output;
 +      BSE_MODULE_OSTREAM (module, BSE_SOUND_FONT_OSC_OCHANNEL_RIGHT_OUT).values = right_output;
 +    }
 +  else
 +    {
 +      g_warning (G_STRLOC ": access past end of channel_values buffer");
 +    }
 +  if (BSE_MODULE_OSTREAM (module, BSE_SOUND_FONT_OSC_OCHANNEL_DONE_OUT).connected)
 +    {
 +      for (i = 0; i < n_values && left_output[i] == 0.0 && right_output[i] == 0.0; i++)
 +      ;
 +      if (i == n_values)
 +      sfrepo->n_silence_samples[sfrepo->channel_map[flmod->config.osc_id]] += n_values;
 +      else
 +      sfrepo->n_silence_samples[sfrepo->channel_map[flmod->config.osc_id]] = 0;
 +      float done = (sfrepo->n_silence_samples[sfrepo->channel_map[flmod->config.osc_id]] > 
flmod->config.silence_bound && sfrepo->fluid_events == NULL) ? 1.0 : 0.0;
 +      BSE_MODULE_OSTREAM (module, BSE_SOUND_FONT_OSC_OCHANNEL_DONE_OUT).values = bse_engine_const_values 
(done);
 +    }
 +
 +  bse_sound_font_repo_unlock_fluid_synth (sfrepo);
 +}
 +
 +static int
 +event_cmp (gconstpointer  a,
 +           gconstpointer  b,
 +           gpointer       data)
 +{
 +  const BseFluidEvent *event1 = (const BseFluidEvent *) a;
 +  const BseFluidEvent *event2 = (const BseFluidEvent *) b;
 +
 +  if (event1->tick_stamp < event2->tick_stamp)
 +    return -1;
 +  return (event1->tick_stamp > event2->tick_stamp);
 +}
 +
 +static void
 +sound_font_osc_process_midi (gpointer            null,
 +                             BseModule          *module,
 +                             const BseMidiEvent *event,
 +                             BseTrans           *trans)
 +{
 +  SoundFontOscModule *flmod = (SoundFontOscModule *) module->user_data;
 +  bse_sound_font_repo_lock_fluid_synth (flmod->config.sfrepo);
-   int note = bse_note_from_freq (BSE_MUSICAL_TUNING_12_TET, event->data.note.frequency);
++  int note = bse_note_from_freq (Bse::MusicalTuning::OD_12_TET, event->data.note.frequency);
 +  BseFluidEvent *fluid_event = NULL;
 +  switch (event->status)
 +    {
 +      case BSE_MIDI_NOTE_ON:
 +      fluid_event = g_new0 (BseFluidEvent, 1);
 +      fluid_event->command = BSE_MIDI_NOTE_ON;
 +      fluid_event->arg1 = note;
 +      fluid_event->arg2 = event->data.note.velocity * 127;
 +      break;
 +      case BSE_MIDI_NOTE_OFF:
 +      fluid_event = g_new0 (BseFluidEvent, 1);
 +      fluid_event->command = BSE_MIDI_NOTE_OFF;
 +      fluid_event->arg1 = note;
 +      break;
 +      case BSE_MIDI_PITCH_BEND:
 +      fluid_event = g_new0 (BseFluidEvent, 1);
 +      fluid_event->command = BSE_MIDI_PITCH_BEND;
 +      /* since midi uses 14 bits, the range is 0x0000 ... 0x3fff
 +       * however, since beast uses -1 ... 0 ...  1, we use the formula
 +       * below with an output range of  0x0000 ... 0x4000 (but fluid synth
 +       * seems to accept these values without trouble) - its also the
 +       * inverse of whats done to the input in bsemididecoder.c
 +       */
 +      fluid_event->arg1 = (event->data.pitch_bend * 0x2000) + 0x2000;
 +      break;
 +      case BSE_MIDI_CONTROL_CHANGE:
 +      case BSE_MIDI_X_CONTINUOUS_CHANGE:
 +      fluid_event = g_new0 (BseFluidEvent, 1);
 +      fluid_event->command = BSE_MIDI_X_CONTINUOUS_CHANGE;
 +      fluid_event->arg1 = event->data.control.control;
 +      /* we do the inverse of what the BEAST midi file reading code does;
 +         * this means we should be able to replay midi files without loosing
 +         * any information - however, since midi information has no sign,
 +         * we truncate negative numbers to zero
 +         *
 +         * FIXME: it would be possible to do an almost loss free conversion
 +         * if the beast representation of controls would be more MIDI like
 +         */
 +      fluid_event->arg2 = CLAMP (event->data.control.value * 127, 0, 127);
 +      break;
 +      case BSE_MIDI_PROGRAM_CHANGE:
 +      /* programs should be set at track level, and are thus not changeable here */
 +      break;
 +      default:
 +      printf ("BseSoundFontOsc: unhandled status %02x\n", event->status);
 +      break;
 +    }
 +  if (fluid_event)
 +    {
 +      fluid_event->tick_stamp = event->delta_time;
 +      fluid_event->channel = flmod->config.sfrepo->channel_map[flmod->config.osc_id];
 +      flmod->config.sfrepo->fluid_events = sfi_ring_insert_sorted (flmod->config.sfrepo->fluid_events, 
fluid_event, event_cmp, NULL);
 +    }
 +  bse_sound_font_repo_unlock_fluid_synth (flmod->config.sfrepo);
 +}
 +
 +typedef struct
 +{
 +  BseMidiReceiver  *midi_receiver;
 +  guint                   midi_channel;
 +  BseModule        *module;
 +} EventHandlerSetup;
 +
 +static void
 +event_handler_setup_func (BseModule *module,
 +                          void *ehs_data)
 +{
 +  EventHandlerSetup *ehs = (EventHandlerSetup *)ehs_data;
 +  bse_midi_receiver_add_event_handler (ehs->midi_receiver,
 +                                       ehs->midi_channel,
 +                                       sound_font_osc_process_midi,
 +                                       NULL,
 +                                       ehs->module);
 +
 +  /* setup program before first midi event */
 +  SoundFontOscModule *flmod = (SoundFontOscModule *) module->user_data;
 +
 +  BseFluidEvent *fluid_event = g_new0 (BseFluidEvent, 1);
 +  fluid_event->command = BSE_FLUID_SYNTH_PROGRAM_SELECT;
 +  fluid_event->channel = flmod->config.sfrepo->channel_map[flmod->config.osc_id];
 +  fluid_event->arg1 = flmod->config.bank;
 +  fluid_event->arg2 = flmod->config.program;
 +  fluid_event->sfont_id = flmod->config.sfont_id;
 +  fluid_event->tick_stamp = 0; /* now */
 +  flmod->config.sfrepo->fluid_events = sfi_ring_insert_sorted (flmod->config.sfrepo->fluid_events, 
fluid_event, event_cmp, NULL);
 +}
 +
 +static void
 +bse_sound_font_osc_context_create (BseSource *source,
 +                                 guint      context_handle,
 +                                 BseTrans  *trans)
 +{
 +  static const BseModuleClass sound_font_osc_class = {
 +    0,                                    /* n_istreams */
 +    0,                                    /* n_jstreams */
 +    BSE_SOUND_FONT_OSC_N_OCHANNELS, /* n_ostreams */
 +    sound_font_osc_process,       /* process */
 +    NULL,                         /* process_defer */
 +    sound_font_osc_reset,         /* reset */
 +    (BseModuleFreeFunc) g_free,           /* free */
 +    BSE_COST_CHEAP,               /* flags */
 +  };
 +  SoundFontOscModule *sound_font_osc = g_new0 (SoundFontOscModule, 1);
 +  BseModule *module;
 +
 +  module = bse_module_new (&sound_font_osc_class, sound_font_osc);
 +
 +  /* setup module i/o streams with BseSource i/o channels */
 +  bse_source_set_context_module (source, context_handle, module);
 +
 +  /* commit module to engine */
 +  bse_trans_add (trans, bse_job_integrate (module));
 +
 +  /* chain parent class' handler */
 +  BSE_SOURCE_CLASS (parent_class)->context_create (source, context_handle, trans);
 +
 +  /* update (initialize) module data */
 +  bse_sound_font_osc_update_modules (BSE_SOUND_FONT_OSC (source), trans);
 +
 +  /* setup midi event handler */
 +  EventHandlerSetup *ehs = g_new0 (EventHandlerSetup, 1);
 +  BseMidiContext mc = bse_snet_get_midi_context (bse_item_get_snet (BSE_ITEM (source)), context_handle);
 +  ehs->midi_receiver = mc.midi_receiver;
 +  ehs->midi_channel = mc.midi_channel;
 +  ehs->module = module;
 +  bse_trans_add (trans, bse_job_access (module, event_handler_setup_func, ehs, g_free));
 +
 +  /* reset fluid synth if necessary */
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (source);
 +  fluid_synth_t *fluid_synth = bse_sound_font_repo_lock_fluid_synth (self->config.sfrepo);
 +  if (self->config.sfrepo->n_channel_oscs_active == 0)
 +    fluid_synth_system_reset (fluid_synth);
 +  self->config.sfrepo->n_channel_oscs_active++;
 +  bse_sound_font_repo_unlock_fluid_synth (self->config.sfrepo);
 +}
 +
 +static void
 +bse_sound_font_osc_context_dismiss (BseSource          *source,
 +                                  guint                 context_handle,
 +                                  BseTrans             *trans)
 +{
 +  BseSoundFontOsc *self = BSE_SOUND_FONT_OSC (source);
 +  BseModule *module = bse_source_get_context_omodule (source, context_handle);
 +  BseMidiContext mc = bse_snet_get_midi_context (bse_item_get_snet (BSE_ITEM (source)), context_handle);
 +  bse_midi_receiver_remove_event_handler (mc.midi_receiver,
 +                                          mc.midi_channel,
 +                                        sound_font_osc_process_midi,
 +                                          NULL,
 +                                          module);
 +  /* remove old events from the event queue */
 +  bse_sound_font_repo_lock_fluid_synth (self->config.sfrepo);
 +  SfiRing *fluid_events = self->config.sfrepo->fluid_events;
 +  SfiRing *node = fluid_events;
 +  while (node)
 +    {
 +      SfiRing *next_node = sfi_ring_walk (node, fluid_events);
 +      BseFluidEvent *event = (BseFluidEvent *) node->data;
 +      if (event->channel == self->config.sfrepo->channel_map[self->config.osc_id])
 +      {
 +        g_free (event);
 +        fluid_events = sfi_ring_remove_node (fluid_events, node);
 +      }
 +      node = next_node;
 +    }
 +  self->config.sfrepo->n_channel_oscs_active--;
 +  self->config.sfrepo->fluid_events = fluid_events;
 +  bse_sound_font_repo_unlock_fluid_synth (self->config.sfrepo);
 +  /* chain parent class' handler */
 +  BSE_SOURCE_CLASS (parent_class)->context_dismiss (source, context_handle, trans);
 +}
diff --cc bse/bsesoundfontrepo.cc
index 9d83461,0000000..1dd8e94
mode 100644,000000..100644
--- a/bse/bsesoundfontrepo.cc
+++ b/bse/bsesoundfontrepo.cc
@@@ -1,387 -1,0 +1,387 @@@
 +// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
 +#include        "bsesoundfontrepo.hh"
 +#include        "bsesoundfont.hh"
 +#include        "bsesoundfontpreset.hh"
 +#include        "bsedefs.hh"
 +#include        "bseblockutils.hh"
 +
 +
 +/* --- parameters --- */
 +enum
 +{
 +  PARAM_0,
 +};
 +
 +
 +/* --- prototypes --- */
 +static void   bse_sound_font_repo_class_init          (BseSoundFontRepoClass  *klass);
 +static void   bse_sound_font_repo_init                (BseSoundFontRepo       *wrepo);
 +static void   bse_sound_font_repo_dispose             (GObject                *object);
 +static void     bse_sound_font_repo_release_children    (BseContainer         *container);
 +static void   bse_sound_font_repo_set_property        (GObject                *object,
 +                                                       guint                   param_id,
 +                                                       const GValue           *value,
 +                                                       GParamSpec             *pspec);
 +static void   bse_sound_font_repo_get_property (GObject               *object,
 +                                                guint                  param_id,
 +                                                GValue                *value,
 +                                                GParamSpec            *pspec);
 +static void     bse_sound_font_repo_add_item     (BseContainer                *container,
 +                                                BseItem               *item);
 +static void     bse_sound_font_repo_forall_items (BseContainer                *container,
 +                                                BseForallItemsFunc     func,
 +                                                gpointer               data);
 +static void     bse_sound_font_repo_remove_item        (BseContainer          *container,
 +                                                BseItem               *item);
 +static void     bse_sound_font_repo_prepare      (BseSource             *source);
 +
 +
 +/* --- variables --- */
 +static gpointer parent_class = NULL;
 +
 +
 +/* --- functions --- */
 +BSE_BUILTIN_TYPE (BseSoundFontRepo)
 +{
 +  GType sound_font_repo_type;
 +
 +  static const GTypeInfo sfrepo_info = {
 +    sizeof (BseSoundFontRepoClass),
 +
 +    (GBaseInitFunc) NULL,
 +    (GBaseFinalizeFunc) NULL,
 +    (GClassInitFunc) bse_sound_font_repo_class_init,
 +    (GClassFinalizeFunc) NULL,
 +    NULL /* class_data */,
 +
 +    sizeof (BseSoundFontRepo),
 +    0,
 +    (GInstanceInitFunc) bse_sound_font_repo_init,
 +  };
 +
 +  sound_font_repo_type = bse_type_register_static (BSE_TYPE_SUPER,
 +                                                 "BseSoundFontRepo",
 +                                                 "BSE Sound Font Repository",
 +                                                   __FILE__, __LINE__,
 +                                                   &sfrepo_info);
 +  return sound_font_repo_type;
 +}
 +
 +static void
 +bse_sound_font_repo_finalize (GObject *object)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
 +  G_OBJECT_CLASS (parent_class)->finalize (object);
 +  sfrepo->fluid_synth_mutex.~Mutex();
 +}
 +
 +static void
 +bse_sound_font_repo_class_init (BseSoundFontRepoClass *klass)
 +{
 +  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 +  BseContainerClass *container_class = BSE_CONTAINER_CLASS (klass);
 +  BseSourceClass *source_class = BSE_SOURCE_CLASS (klass);
 +
 +  parent_class = g_type_class_peek_parent (klass);
 +
 +  gobject_class->set_property = bse_sound_font_repo_set_property;
 +  gobject_class->get_property = bse_sound_font_repo_get_property;
 +  gobject_class->dispose = bse_sound_font_repo_dispose;
 +  gobject_class->finalize = bse_sound_font_repo_finalize;
 +
 +  container_class->add_item = bse_sound_font_repo_add_item;
 +  container_class->remove_item = bse_sound_font_repo_remove_item;
 +  container_class->forall_items = bse_sound_font_repo_forall_items;
 +  container_class->release_children = bse_sound_font_repo_release_children;
 +
 +  source_class->prepare = bse_sound_font_repo_prepare;
 +}
 +
 +static void
 +bse_sound_font_repo_init (BseSoundFontRepo *sfrepo)
 +{
 +  new (&sfrepo->fluid_synth_mutex) Bse::Mutex();
 +
 +  sfrepo->n_oscs = 0;
 +  sfrepo->oscs = NULL;
 +  sfrepo->channel_map = NULL;
 +
 +  sfrepo->fluid_settings = new_fluid_settings();
 +  sfrepo->fluid_synth = new_fluid_synth (sfrepo->fluid_settings);
 +  sfrepo->fluid_events = NULL;
 +  sfrepo->sound_fonts = NULL;
 +  sfrepo->fluid_mix_freq = 0;
 +
 +  sfrepo->n_fluid_channels = 0;
 +  sfrepo->channel_values_left = NULL;
 +  sfrepo->channel_values_right = NULL;
 +  sfrepo->n_silence_samples = NULL;
 +
 +  sfrepo->n_channel_oscs_active = 0;
 +  sfrepo->channel_values_tick_stamp = 0;
 +}
 +
 +static gboolean
 +reload_sound_font (BseItem *item,
 +                   gpointer data)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (item);
 +  bse_sound_font_reload (sound_font);
 +  return TRUE;
 +}
 +
 +static gboolean
 +unload_sound_font (BseItem *item,
 +                   gpointer data)
 +{
 +  BseSoundFont *sound_font = BSE_SOUND_FONT (item);
 +  bse_sound_font_unload (sound_font);
 +  return TRUE;
 +}
 +
 +static void
 +bse_sound_font_repo_prepare (BseSource *source)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (source);
 +  int i, channels_required = 0;
 +  for (i = 0; i < sfrepo->n_oscs; i++)
 +    {
 +      if (sfrepo->oscs[i])
 +      sfrepo->channel_map[i] = channels_required++;
 +    }
 +  int mix_freq = bse_engine_sample_freq();
 +  if (sfrepo->n_fluid_channels != channels_required || sfrepo->fluid_mix_freq != mix_freq)
 +    {
 +      for (i = channels_required; i < sfrepo->n_fluid_channels; i++) // n_fluid_channels > channels_required
 +      {
 +        g_free (sfrepo->channel_values_left[i]);
 +        g_free (sfrepo->channel_values_right[i]);
 +      }
 +      sfrepo->channel_values_left = (float **)g_realloc (sfrepo->channel_values_left, sizeof (float *) * 
channels_required);
 +      sfrepo->channel_values_right = (float **)g_realloc (sfrepo->channel_values_right, sizeof (float *) * 
channels_required);
 +      sfrepo->n_silence_samples = (gint *) g_realloc (sfrepo->n_silence_samples, sizeof (gint) * 
channels_required);
 +      for (i = sfrepo->n_fluid_channels; i < channels_required; i++) // n_fluid_channels < channels_required
 +      {
 +        sfrepo->channel_values_left[i] = g_new0 (float, BSE_STREAM_MAX_VALUES);
 +        sfrepo->channel_values_right[i] = g_new0 (float, BSE_STREAM_MAX_VALUES);
 +        sfrepo->n_silence_samples[i] = 0;
 +      }
 +      sfrepo->n_fluid_channels = channels_required;
 +      sfrepo->fluid_mix_freq = mix_freq;
 +
 +      fluid_settings_setnum (sfrepo->fluid_settings, "synth.sample-rate", mix_freq);
 +      fluid_settings_setint (sfrepo->fluid_settings, "synth.midi-channels", channels_required);
 +      fluid_settings_setint (sfrepo->fluid_settings, "synth.audio-channels", channels_required);
 +      fluid_settings_setint (sfrepo->fluid_settings, "synth.audio-groups", channels_required);
 +      fluid_settings_setstr (sfrepo->fluid_settings, "synth.reverb.active", "no");
 +      fluid_settings_setstr (sfrepo->fluid_settings, "synth.chorus.active", "no");
 +
 +      bse_sound_font_repo_forall_items (BSE_CONTAINER (sfrepo), unload_sound_font, sfrepo);
 +      if (sfrepo->fluid_synth)
 +      delete_fluid_synth (sfrepo->fluid_synth);
 +
 +      sfrepo->fluid_synth = new_fluid_synth (sfrepo->fluid_settings);
 +      bse_sound_font_repo_forall_items (BSE_CONTAINER (sfrepo), reload_sound_font, sfrepo);
 +    }
 +
 +  /* chain parent class' handler */
 +  BSE_SOURCE_CLASS (parent_class)->prepare (source);
 +}
 +
 +static void
 +bse_sound_font_repo_release_children (BseContainer *container)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
 +
 +  while (sfrepo->sound_fonts)
 +    bse_container_remove_item (container, BSE_ITEM (sfrepo->sound_fonts->data));
 +
 +  /* chain parent class' handler */
 +  BSE_CONTAINER_CLASS (parent_class)->release_children (container);
 +}
 +
 +static void
 +bse_sound_font_repo_dispose (GObject *object)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
 +  int i;
 +
 +  bse_sound_font_repo_forall_items (BSE_CONTAINER (sfrepo), unload_sound_font, sfrepo);
 +
 +  if (sfrepo->fluid_synth)
 +    {
 +      delete_fluid_synth (sfrepo->fluid_synth);
 +      sfrepo->fluid_synth = NULL;
 +    }
 +  if (sfrepo->fluid_settings)
 +    {
 +      delete_fluid_settings (sfrepo->fluid_settings);
 +      sfrepo->fluid_settings = NULL;
 +    }
 +  g_free (sfrepo->channel_map);
 +  sfrepo->channel_map = NULL;
 +  g_free (sfrepo->oscs);
 +  sfrepo->oscs = NULL;
 +  for (i = 0; i < sfrepo->n_fluid_channels; i++)
 +    {
 +      g_free (sfrepo->channel_values_left[i]);
 +      g_free (sfrepo->channel_values_right[i]);
 +    }
 +  sfrepo->n_fluid_channels = 0;
 +  g_free (sfrepo->channel_values_left);
 +  sfrepo->channel_values_left = NULL;
 +  g_free (sfrepo->channel_values_right);
 +  sfrepo->channel_values_right = NULL;
 +  g_free (sfrepo->n_silence_samples);
 +  sfrepo->n_silence_samples = NULL;
 +
 +  if (sfrepo->fluid_events != NULL)
 +    g_warning (G_STRLOC ": fluid event queue should be empty in dispose");
 +
 +  /* chain parent class' handler */
 +  G_OBJECT_CLASS (parent_class)->dispose (object);
 +}
 +
 +static void
 +bse_sound_font_repo_set_property (GObject      *object,
 +                                guint         param_id,
 +                                const GValue *value,
 +                                GParamSpec   *pspec)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
 +  switch (param_id)
 +    {
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (sfrepo, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +static void
 +bse_sound_font_repo_get_property (GObject      *object,
 +                                guint         param_id,
 +                                GValue       *value,
 +                                GParamSpec   *pspec)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (object);
 +  switch (param_id)
 +    {
 +    default:
 +      G_OBJECT_WARN_INVALID_PROPERTY_ID (sfrepo, param_id, pspec);
 +      break;
 +    }
 +}
 +
 +static void
 +bse_sound_font_repo_add_item (BseContainer *container,
 +                            BseItem      *item)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
 +
 +  if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT))
 +    sfrepo->sound_fonts = g_list_append (sfrepo->sound_fonts, item);
 +  else
 +    g_warning ("BseSoundFontRepo: cannot hold non-sound-font item type `%s'",
 +             BSE_OBJECT_TYPE_NAME (item));
 +
 +  /* chain parent class' add_item handler */
 +  BSE_CONTAINER_CLASS (parent_class)->add_item (container, item);
 +}
 +
 +static void
 +bse_sound_font_repo_forall_items (BseContainer      *container,
 +                                BseForallItemsFunc func,
 +                                gpointer           data)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
 +  GList *list;
 +
 +  list = sfrepo->sound_fonts;
 +  while (list)
 +    {
 +      BseItem *item;
 +
 +      item = BSE_ITEM (list->data);
 +      list = list->next;
 +      if (!func (item, data))
 +      return;
 +    }
 +}
 +
 +static void
 +bse_sound_font_repo_remove_item (BseContainer *container,
 +                               BseItem      *item)
 +{
 +  BseSoundFontRepo *sfrepo = BSE_SOUND_FONT_REPO (container);
 +
 +  if (g_type_is_a (BSE_OBJECT_TYPE (item), BSE_TYPE_SOUND_FONT))
 +    sfrepo->sound_fonts = g_list_remove (sfrepo->sound_fonts, item);
 +  else
 +    g_warning ("BseSoundFontRepo: cannot hold non-sound-font item type `%s'",
 +             BSE_OBJECT_TYPE_NAME (item));
 +
 +  /* chain parent class' remove_item handler */
 +  BSE_CONTAINER_CLASS (parent_class)->remove_item (container, item);
 +}
 +
 +static gboolean
 +gather_presets (BseItem    *item,
 +                void       *pitems)
 +{
-   BseItemSeq *items = (BseItemSeq *) pitems;
++  BseIt3mSeq *items = (BseIt3mSeq *) pitems;
 +  if (BSE_IS_SOUND_FONT (item) || BSE_IS_SOUND_FONT_REPO (item))
 +    bse_container_forall_items (BSE_CONTAINER (item), gather_presets, items);
 +  else if (BSE_IS_SOUND_FONT_PRESET (item))
-     bse_item_seq_append (items, item);
++    bse_it3m_seq_append (items, item);
 +  else
 +    g_warning ("Searching for sound font presets, an unexpected `%s' item was found", BSE_OBJECT_TYPE_NAME 
(item));
 +  return TRUE;
 +}
 +
 +void
 +bse_sound_font_repo_list_all_presets (BseSoundFontRepo *sfrepo,
-                                       BseItemSeq       *items)
++                                      BseIt3mSeq       *items)
 +{
 +  gather_presets (BSE_ITEM (sfrepo), items);
 +}
 +
 +fluid_synth_t *
 +bse_sound_font_repo_lock_fluid_synth (BseSoundFontRepo *sfrepo)
 +{
 +  sfrepo->fluid_synth_mutex.lock();
 +  return sfrepo->fluid_synth;
 +}
 +
 +void
 +bse_sound_font_repo_unlock_fluid_synth (BseSoundFontRepo *sfrepo)
 +{
 +  sfrepo->fluid_synth_mutex.unlock();
 +}
 +
 +int
 +bse_sound_font_repo_add_osc (BseSoundFontRepo *sfrepo,
 +                             BseSoundFontOsc  *osc)
 +{
 +  int i;
 +  for (i = 0; i < sfrepo->n_oscs; i++)
 +    {
 +      if (sfrepo->oscs[i] == 0)
 +      {
 +        sfrepo->oscs[i] = osc;
 +        return i;
 +      }
 +    }
 +  sfrepo->oscs = (BseSoundFontOsc **)g_realloc (sfrepo->oscs, sizeof (BseSoundFontOsc *) * (i + 1));
 +  sfrepo->oscs[i] = osc;
 +  sfrepo->channel_map = (guint *) g_realloc (sfrepo->channel_map, sizeof (guint) * (i + 1));
 +  return sfrepo->n_oscs++;
 +}
 +
 +void
 +bse_sound_font_repo_remove_osc (BseSoundFontRepo *sfrepo,
 +                                int               osc_id)
 +{
 +  g_return_if_fail (osc_id >= 0 && osc_id < sfrepo->n_oscs);
 +
 +  sfrepo->oscs[osc_id] = 0;
 +}
diff --cc bse/bsesoundfontrepo.hh
index d69cb6a,0000000..f76831b
mode 100644,000000..100644
--- a/bse/bsesoundfontrepo.hh
+++ b/bse/bsesoundfontrepo.hh
@@@ -1,68 -1,0 +1,68 @@@
 +// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
 +#ifndef       __BSE_SOUND_FONT_REPO_HH__
 +#define       __BSE_SOUND_FONT_REPO_HH__
 +
 +#include      <bse/bsesuper.hh>
 +#include        <fluidsynth.h>
 +#include        <bse/bsesoundfontosc.hh>
 +#include        <bse/bseengine.hh>
 +
 +G_BEGIN_DECLS
 +
 +#define BSE_TYPE_SOUND_FONT_REPO              (BSE_TYPE_ID (BseSoundFontRepo))
 +#define BSE_SOUND_FONT_REPO(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), 
BSE_TYPE_SOUND_FONT_REPO, BseSoundFontRepo))
 +#define BSE_SOUND_FONT_REPO_CLASS(class)      (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_SOUND_FONT_REPO, 
BseSoundFontRepoClass))
 +#define BSE_IS_SOUND_FONT_REPO(object)                (G_TYPE_CHECK_INSTANCE_TYPE ((object), 
BSE_TYPE_SOUND_FONT_REPO))
 +#define BSE_IS_SOUND_FONT_REPO_CLASS(class)   (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_SOUND_FONT_REPO))
 +#define BSE_SOUND_FONT_REPO_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), 
BSE_TYPE_SOUND_FONT_REPO, BseSoundFontRepoClass))
 +
 +#define BSE_FLUID_SYNTH_PROGRAM_SELECT -1
 +
 +struct BseFluidEvent {
 +  guint64            tick_stamp;
 +  int                channel;
 +  int              command;
 +  int              arg1;
 +  int              arg2;
 +  int                sfont_id;          /* required for program selection only */
 +};
 +
 +struct BseSoundFontRepo : BseSuper {
 +  Bse::Mutex       fluid_synth_mutex;
 +  fluid_settings_t  *fluid_settings;
 +  fluid_synth_t     *fluid_synth;
 +  SfiRing           *fluid_events;
 +  guint              fluid_mix_freq;
 +
 +  guint              n_fluid_channels;
 +  float                  **channel_values_left;     /* [0..n_fluid_channels-1] */
 +  float                  **channel_values_right;    /* [0..n_fluid_channels-1] */
 +  guint64          channel_values_tick_stamp;
 +  gint              *n_silence_samples;       /* [0..n_fluid_channels-1] */
 +
 +  guint              n_oscs;
 +  BseSoundFontOsc  **oscs;                  /* [0..n_oscs-1] */
 +  guint                   *channel_map;             /* [0..n_oscs-1] */
 +
 +  int              n_channel_oscs_active;       /* SoundFontOscs with an active module in the engine thread 
*/
 +
 +  GList             *sound_fonts;
 +};
 +
 +struct BseSoundFontRepoClass : BseSuperClass
 +{};
 +
 +
 +/* --- prototypes --- */
 +void         bse_sound_font_repo_list_all_presets   (BseSoundFontRepo *sfrepo,
-                                                      BseItemSeq       *items);
++                                                     BseIt3mSeq       *items);
 +fluid_synth_t *bse_sound_font_repo_lock_fluid_synth   (BseSoundFontRepo *sfrepo);
 +void           bse_sound_font_repo_unlock_fluid_synth (BseSoundFontRepo *sfrepo);
 +int          bse_sound_font_repo_add_osc            (BseSoundFontRepo *sfrepo,
 +                                                     BseSoundFontOsc  *osc);
 +void           bse_sound_font_repo_remove_osc         (BseSoundFontRepo *sfrepo,
 +                                                     int               osc_id);
 +
 +G_END_DECLS
 +
 +#endif /* __BSE_SOUND_FONT_REPO_HH__ */
diff --cc bse/bsesoundfontrepo.proc
index aa2ea93,0000000..01ff77c
mode 100644,000000..100644
--- a/bse/bsesoundfontrepo.proc
+++ b/bse/bsesoundfontrepo.proc
@@@ -1,155 -1,0 +1,155 @@@
 +/* BSE - Bedevilled Sound Engine      -*-mode: c;-*-
 + * Copyright (C) 2000-2003 Tim Janik
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * A copy of the GNU Lesser General Public License should ship along
 + * with this library; if not, see http://www.gnu.org/copyleft/.
 + */
 +#include <bse/bseplugin.hh>
 +#include <bse/bseprocedure.hh>
 +#include <bse/bsesoundfontrepo.hh>
 +#include <bse/bsesoundfont.hh>
 +#include <bse/bseloader.hh>
 +
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <unistd.h>
 +#include <errno.h>
 +
 +
 +/* --- auxlillary functions --- */
- static BseErrorType
++static Bse::Error
 +load_file (BseSoundFontRepo *sfrepo,
 +         const gchar      *file_name,
 +           BseSoundFont    **sound_font_p)
 +{
 +  gchar *fname = g_path_get_basename (file_name);
 +  BseSoundFont *sound_font = (BseSoundFont *) g_object_new (BSE_TYPE_SOUND_FONT, "uname", fname, NULL);
 +  g_free (fname);
 +  bse_container_add_item (BSE_CONTAINER (sfrepo), BSE_ITEM (sound_font));
 +
 +  BseStorageBlob *blob = bse_storage_blob_new_from_file (file_name, FALSE);
-   BseErrorType error = bse_sound_font_load_blob (sound_font, blob, TRUE);
++  Bse::Error error = bse_sound_font_load_blob (sound_font, blob, TRUE);
 +  bse_storage_blob_unref (blob);
-   if (error == BSE_ERROR_NONE)
++  if (error == Bse::Error::NONE)
 +    {
 +      *sound_font_p = sound_font;
 +    }
 +  else
 +    {
 +      bse_container_remove_item (BSE_CONTAINER (sfrepo), BSE_ITEM (sound_font));
 +      *sound_font_p = NULL;
 +    }
 +  g_object_unref (sound_font);
 +  return error;
 +}
 +
 +/* --- procedures --- */
 +AUTHORS       = "Tim Janik <timj gtk org>";
 +LICENSE = "GNU Lesser General Public License";
 +
 +
 +METHOD (BseSoundFontRepo, load-file) {
 +  HELP        = "Load sound font from file";
 +  IN    = bse_param_spec_object ("sound_font_repo", "Sound Font Repo", NULL,
 +                               BSE_TYPE_SOUND_FONT_REPO, SFI_PARAM_STANDARD);
 +  IN  = sfi_pspec_string ("file_name", "File Name", "The file to import sound fonts from",
 +                          NULL, SFI_PARAM_STANDARD);
 +  OUT   = bse_param_spec_genum ("error", "Error", NULL,
-                               BSE_TYPE_ERROR_TYPE, BSE_ERROR_NONE,
++                              BSE_TYPE_ERROR_TYPE, Bse::Error::NONE,
 +                              SFI_PARAM_STANDARD);
 +}
 +BODY (BseProcedureClass *proc,
 +      const GValue      *in_values,
 +      GValue            *out_values)
 +{
 +  /* extract parameter values */
 +  BseSoundFontRepo *self    = (BseSoundFontRepo*) bse_value_get_object (in_values++);
 +  const gchar *file_name    = sfi_value_get_string (in_values++);
 +  BseUndoStack *ustack;
-   BseErrorType error;
++  Bse::Error error;
 +  BseSoundFont *sound_font;
 +
 +  /* check parameters */
 +  if (!BSE_IS_SOUND_FONT_REPO (self) || !file_name)
-     return BSE_ERROR_PROC_PARAM_INVAL;
++    return Bse::Error::PROC_PARAM_INVAL;
 +
 +  if (BSE_SOURCE_PREPARED (self))
 +    {
 +      /* In theory, its possible to allow loading sound fonts while
 +       * the project is playing; in practice, the sound font repo
 +       * lock would be locked for a very long time, which would stall
 +       * the audio production ...
 +       */
-       error = BSE_ERROR_SOURCE_BUSY;
++      error = Bse::Error::SOURCE_BUSY;
 +    }
 +  else
 +    {
 +      ustack = bse_item_undo_open (self, "load-sound-font");
 +      error = load_file (self, file_name, &sound_font);
 +      if (sound_font)
 +      bse_item_push_undo_proc (self, "remove-sound-font", sound_font);
 +      bse_item_undo_close (ustack);
 +   }
 +
 +  /* set output parameters */
-   g_value_set_enum (out_values++, error);
++  g_value_set_enum (out_values++, int (error));
 +
-   return BSE_ERROR_NONE;
++  return Bse::Error::NONE;
 +}
 +
 +METHOD (BseSoundFontRepo, remove-sound-font) {
 +  HELP  = "Remove a sound font from repository";
 +  IN    = bse_param_spec_object ("sound_font_repo", "Sound Font Repo", NULL,
 +                               BSE_TYPE_SOUND_FONT_REPO, SFI_PARAM_STANDARD);
 +  IN    = bse_param_spec_object ("sound_font", "Sound Font", NULL,
 +                               BSE_TYPE_SOUND_FONT, SFI_PARAM_STANDARD);
 +} BODY (BseProcedureClass *proc,
 +      const GValue      *in_values,
 +      GValue            *out_values)
 +{
 +  /* extract parameter values */
 +  BseSoundFontRepo *self = (BseSoundFontRepo*) bse_value_get_object (in_values++);
 +  BseItem *child         = (BseItem*) bse_value_get_object (in_values++);
 +  BseUndoStack *ustack;
-   BseErrorType error;
++  Bse::Error error;
 +
 +  /* check parameters */
 +  if (!BSE_IS_SOUND_FONT_REPO (self) || !BSE_IS_SOUND_FONT (child) ||
 +      child->parent != BSE_ITEM (self))
-     return BSE_ERROR_PROC_PARAM_INVAL;
++    return Bse::Error::PROC_PARAM_INVAL;
 +
 +  if (BSE_SOURCE_PREPARED (self))
 +    {
 +      /* Don't allow unloading sound fonts which could be required by engine
 +       * modules in the DSP thread currently producing audio output.
 +       */
-       error = BSE_ERROR_SOURCE_BUSY;
++      error = Bse::Error::SOURCE_BUSY;
 +    }
 +  else
 +    {
 +      /* action */
 +      ustack = bse_item_undo_open (self, "remove-sound-font %s", bse_object_debug_name (child));
 +      /* remove object references */
 +      bse_container_uncross_undoable (BSE_CONTAINER (self), child);
 +      /* how to get rid of the item once backed up */
 +      bse_item_push_redo_proc (self, "remove-sound-font", child);
 +      /* remove (without redo queueing) */
 +      bse_container_remove_backedup (BSE_CONTAINER (self), child, ustack);
 +      /* done */
 +      bse_item_undo_close (ustack);
 +
-       error = BSE_ERROR_NONE;
++      error = Bse::Error::NONE;
 +    }
 +
 +  return error;
 +}
diff --cc bse/bsestorage.cc
index 31ad4b2,4ff5ed5..370349d
--- a/bse/bsestorage.cc
+++ b/bse/bsestorage.cc
@@@ -166,17 -148,16 +165,17 @@@ bse_storage_turn_readable (BseStorage  
                             const gchar *storage_name)
  {
    BseStorageDBlock *dblocks;
 +  BseStorageBlob **blobs;
    const gchar *cmem;
    gchar *text;
 -  guint n_dblocks, l;
 +  guint n_dblocks, n_blobs, l;
  
-   g_return_if_fail (BSE_IS_STORAGE (self));
-   g_return_if_fail (BSE_STORAGE_DBLOCK_CONTAINED (self));
-   g_return_if_fail (self->wstore);
-   g_return_if_fail (self->wstore->flushed == FALSE);
-   g_return_if_fail (self->wstore->bblocks == NULL);
-   g_return_if_fail (self->free_me == NULL);
+   assert_return (BSE_IS_STORAGE (self));
+   assert_return (BSE_STORAGE_DBLOCK_CONTAINED (self));
+   assert_return (self->wstore);
+   assert_return (self->wstore->flushed == FALSE);
+   assert_return (self->wstore->bblocks == NULL);
+   assert_return (self->free_me == NULL);
  
    bse_storage_break (self);
  
@@@ -1612,310 -1775,7 +1821,310 @@@ bse_storage_parse_data_handle_rest (Bse
    return parse_data_handle_trampoline (self, TRUE, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
  }
  
 +// == blobs ==
 +
 +BseStorageBlob *
 +bse_storage_blob_ref (BseStorageBlob *blob)
 +{
 +  g_return_val_if_fail (blob != NULL, NULL);
 +  g_return_val_if_fail (blob->ref_count > 0, NULL);
 +
 +  blob->mutex.lock();
 +  blob->ref_count++;
 +  blob->mutex.unlock();
 +
 +  return blob;
 +}
 +
 +const gchar *
 +bse_storage_blob_file_name (BseStorageBlob *blob)
 +{
 +  g_return_val_if_fail (blob != NULL, NULL);
 +  g_return_val_if_fail (blob->ref_count > 0, NULL);
 +
 +  blob->mutex.lock();
 +  const gchar *file_name = blob->file_name;
 +  blob->mutex.unlock();
 +
 +  return file_name;
 +}
 +
 +void
 +bse_storage_blob_unref (BseStorageBlob *blob)
 +{
 +  g_return_if_fail (blob != NULL);
 +  g_return_if_fail (blob->ref_count > 0);
 +
 +  blob->mutex.lock();
 +  blob->ref_count--;
 +  gboolean destroy = blob->ref_count == 0;
 +  blob->mutex.unlock();
 +  if (destroy)
 +    {
 +      if (blob->is_temp_file)
 +      {
 +        unlink (blob->file_name);
 +        /* FIXME: check error code and do what? */
 +      }
 +      g_free (blob->file_name);
 +      blob->file_name = NULL;
 +      bse_id_free (blob->id);
 +      blob->mutex.~Mutex();
 +      g_free (blob);
 +    }
 +}
 +
 +/* search in /tmp for files called "bse-<user>-<pid>*"
 + * delete files if the pid does not exist any longer
 + */
 +void
 +bse_storage_blob_clean_files()
 +{
 +  GError *error;
 +  const char *tmp_dir = g_get_tmp_dir();
 +  GDir *dir = g_dir_open (tmp_dir, 0, &error);
 +  if (dir)
 +    {
 +      char *pattern = g_strdup_format ("bse-%s-", g_get_user_name());
 +      const char *file_name;
 +      while ((file_name = g_dir_read_name (dir)))
 +      {
 +        if (strncmp (pattern, file_name, strlen (pattern)) == 0)
 +          {
 +            int pid = atoi (file_name + strlen (pattern));
 +
 +              if (kill (pid, 0) == -1 && errno == ESRCH)
 +              {
 +                char *path = g_strdup_format ("%s/%s", tmp_dir, file_name);
 +                unlink (path);
 +                g_free (path);
 +              }
 +          }
 +      }
 +      g_free (pattern);
 +      g_dir_close (dir);
 +    }
 +}
 +
 +BseStorageBlob *
 +bse_storage_blob_new_from_file (const char *file_name,
 +                                gboolean    is_temp_file)
 +{
 +  BseStorageBlob *blob = g_new0 (BseStorageBlob, 1);
 +  new (&blob->mutex) Bse::Mutex();
 +  blob->file_name = g_strdup (file_name);
 +  blob->ref_count = 1;
 +  blob->is_temp_file = is_temp_file;
 +  blob->id = bse_id_alloc();
 +  return blob;
 +}
 +
 +gboolean
 +bse_storage_blob_is_temp_file (BseStorageBlob *blob)
 +{
 +  g_return_val_if_fail (blob != NULL, FALSE);
 +  g_return_val_if_fail (blob->ref_count > 0, FALSE);
 +
 +  blob->mutex.lock();
 +  gboolean is_temp_file = blob->is_temp_file;
 +  blob->mutex.unlock();
 +
 +  return is_temp_file;
 +}
 +
 +typedef struct
 +{
 +  BseStorageBlob *blob;
 +  BseStorage     *storage;
 +  int             fd;
 +} WStoreBlob;
 +
 +static WStoreBlob *
 +wstore_blob_new (BseStorage *storage,
 +                 BseStorageBlob *blob)
 +{
 +  WStoreBlob *wsb = (WStoreBlob *) g_new0 (WStoreBlob, 1);
 +  wsb->blob = bse_storage_blob_ref (blob);
 +  wsb->storage = storage;
 +  wsb->fd = -1;
 +  return wsb;
 +}
 +
 +static gint /* -errno || length */
 +wstore_blob_reader (gpointer data,
 +                  void    *buffer,
 +                  guint    blength)
 +{
 +  WStoreBlob *wsb = (WStoreBlob *) data;
 +  if (wsb->fd == -1)
 +    {
 +      do
 +      wsb->fd = open (bse_storage_blob_file_name (wsb->blob), O_RDONLY);
 +      while (wsb->fd == -1 && errno == EINTR);
 +      if (wsb->fd == -1)
 +      {
 +        bse_storage_error (wsb->storage, "file %s could not be opened: %s", bse_storage_blob_file_name 
(wsb->blob), strerror (errno));
 +        return -errno;
 +      }
 +    }
 +  int n;
 +  do
 +    n = read (wsb->fd, buffer, blength);
 +  while (n == -1 && errno == EINTR);
 +  if (n < 0)
 +    return -errno;
 +  else
 +    return n;
 +}
 +
 +static void
 +wstore_blob_destroy (gpointer data)
 +{
 +  WStoreBlob *wblob = (WStoreBlob *) data;
 +  if (wblob->fd >= 0)
 +    close (wblob->fd);
 +  bse_storage_blob_unref (wblob->blob);
 +}
 +
 +void
 +bse_storage_put_blob (BseStorage      *self,
 +                      BseStorageBlob  *blob)
 +{
 +  if (BSE_STORAGE_DBLOCK_CONTAINED (self))
 +    {
 +      gulong id = bse_storage_add_blob (self, blob);
 +      bse_storage_break (self);
 +      bse_storage_printf (self, "(%s %lu)", g_quark_to_string (quark_blob_id), id);
 +    }
 +  else
 +    {
 +      bse_storage_break (self);
 +      bse_storage_printf (self, "(%s ", g_quark_to_string (quark_blob));
 +      bse_storage_push_level (self);
 +      bse_storage_break (self);
 +      sfi_wstore_put_binary (self->wstore, wstore_blob_reader, wstore_blob_new (self, blob), 
wstore_blob_destroy);
 +      bse_storage_pop_level (self);
 +      bse_storage_putc (self, ')');
 +    }
 +}
 +
 +GTokenType
 +bse_storage_parse_blob (BseStorage             *self,
 +                        BseStorageBlob        **blob)
 +{
 +  GScanner *scanner = bse_storage_get_scanner (self);
 +  int bse_fd = -1;
 +  int tmp_fd = -1;
 +  char *file_name = g_strdup_format ("%s/bse-%s-%u-%08x", g_get_tmp_dir(), g_get_user_name(), getpid(), 
g_random_int());
 +
 +  *blob = NULL; /* on error, the resulting blob should be NULL */
 +
 +  parse_or_return (scanner, '(');
 +  parse_or_return (scanner, G_TOKEN_IDENTIFIER);
 +  if (g_quark_try_string (scanner->value.v_identifier) == quark_blob)
 +    {
 +      SfiNum offset, length;
 +      GTokenType token = sfi_rstore_parse_binary (self->rstore, &offset, &length);
 +      if (token != G_TOKEN_NONE)
 +      return token;
 +
 +      char buffer[1024];
 +      bse_fd = open (self->rstore->fname, O_RDONLY);
 +      if (bse_fd < 0)
 +      {
 +        bse_storage_error (self, "couldn't open file %s for reading: %s\n", self->rstore->fname, strerror 
(errno));
 +        goto return_with_error;
 +      }
 +      tmp_fd = open (file_name, O_CREAT | O_WRONLY, 0600);
 +      if (tmp_fd < 0)
 +      {
 +        bse_storage_error (self, "couldn't open file %s for writing: %s\n", file_name, strerror (errno));
 +        goto return_with_error;
 +      }
 +      int result = lseek (bse_fd, offset, SEEK_SET);
 +      if (result != offset)
 +      {
 +        bse_storage_error (self, "could not seek to position %lld in bse file %s\n", offset, 
self->rstore->fname);
 +        goto return_with_error;
 +      }
 +      int bytes_todo = length;
 +      while (bytes_todo > 0)
 +      {
 +        int rbytes, wbytes;
 +
 +          do
 +            rbytes = read (bse_fd, buffer, MIN (bytes_todo, 1024));
 +          while (rbytes == -1 && errno == EINTR);
 +
 +        if (rbytes == -1)
 +          {
 +            bse_storage_error (self, "error while reading file %s: %s\n", self->rstore->fname, strerror 
(errno));
 +            goto return_with_error;
 +          }
 +        if (rbytes == 0)
 +          {
 +            bse_storage_error (self, "end-of-file occured too early in file %s\n", self->rstore->fname);
 +            goto return_with_error;
 +          }
 +
 +        int bytes_written = 0;
 +        while (bytes_written != rbytes)
 +          {
 +            do
 +              wbytes = write (tmp_fd, &buffer[bytes_written], rbytes - bytes_written);
 +            while (wbytes == -1 && errno == EINTR);
 +            if (wbytes == -1)
 +              {
 +                bse_storage_error (self, "error while writing file %s: %s\n", self->rstore->fname, strerror 
(errno));
 +                goto return_with_error;
 +              }
 +            bytes_written += wbytes;
 +          }
 +
 +        bytes_todo -= rbytes;
 +      }
 +      close (bse_fd);
 +      close (tmp_fd);
 +      *blob = bse_storage_blob_new_from_file (file_name, TRUE);
 +      g_free (file_name);
 +    }
 +  else if (g_quark_try_string (scanner->value.v_identifier) == quark_blob_id)
 +    {
 +      gulong id;
 +      parse_or_return (scanner, G_TOKEN_INT);
 +      id = scanner->value.v_int64;
 +      *blob = NULL;
 +      for (size_t i = 0; i < self->n_blobs; i++)
 +      {
 +        if (self->blobs[i]->id == id)
 +          *blob = bse_storage_blob_ref (self->blobs[i]);
 +      }
 +      if (!*blob)
 +      {
 +        g_warning ("failed to lookup storage blob with id=%ld\n", id);
 +        goto return_with_error;
 +      }
 +     }
 +  else
 +    {
 +      goto return_with_error;
 +    }
 +  parse_or_return (scanner, ')');
 +
 +  return G_TOKEN_NONE;
 +
 +return_with_error:
 +  if (bse_fd != -1)
 +    close (bse_fd);
 +  if (tmp_fd != -1)
 +    {
 +      close (tmp_fd);
 +      unlink (file_name);
 +    }
 +  return G_TOKEN_ERROR;
 +}
 +
- BseErrorType
+ Bse::Error
  bse_storage_flush_fd (BseStorage *self,
                        gint        fd)
  {
diff --cc bse/bsestorage.hh
index c7f8645,67d0f8e..30e432c
--- a/bse/bsestorage.hh
+++ b/bse/bsestorage.hh
@@@ -121,11 -118,9 +121,11 @@@ void         bse_storage_put_item_lin
  void         bse_storage_put_data_handle        (BseStorage             *self,
                                                   guint                   significant_bits,
                                                   GslDataHandle          *dhandle);
 +void         bse_storage_put_blob               (BseStorage             *self,
 +                                                 BseStorageBlob         *blob);
  void         bse_storage_put_xinfos             (BseStorage             *self,
                                                   gchar                 **xinfos);
- BseErrorType bse_storage_flush_fd               (BseStorage             *self,
+ Bse::Error bse_storage_flush_fd               (BseStorage             *self,
                                                   gint                    fd);
  
  
diff --cc bse/bsetrack.cc
index 824b6f1,579cf51..45ec612
--- a/bse/bsetrack.cc
+++ b/bse/bsetrack.cc
@@@ -427,32 -404,9 +428,32 @@@ create_wnet (BseTrack *self
  }
  
  static void
 -clear_snet_and_wave (BseTrack *self)
 +create_sound_font_net (BseTrack           *self,
 +                       BseSoundFontPreset *preset)
 +{
 +  g_return_if_fail (self->sound_font_net == NULL);
 +
 +  self->sound_font_net =  bse_project_create_intern_synth (bse_item_get_project (BSE_ITEM (self)),
 +                                                         "sound-font-snet",
 +                                                         BSE_TYPE_SNET);
 +
 +  bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->sound_font_net), track_uncross_sound_font_preset);
 +
 +  if (self->sub_synth)
 +    {
 +      g_object_set (self->sub_synth, /* no undo */
 +                  "snet", self->sound_font_net,
 +                  NULL);
 +    }
 +
 +  g_object_set (bse_container_resolve_upath (BSE_CONTAINER (self->sound_font_net), "sound-font-osc"), /* no 
undo */
 +              "preset", preset,
 +              NULL);
 +}
 +static void
 +clear_snet_and_wave_and_sfpreset (BseTrack *self)
  {
-   g_return_if_fail (!self->sub_synth || !BSE_SOURCE_PREPARED (self->sub_synth));
+   assert_return (!self->sub_synth || !BSE_SOURCE_PREPARED (self->sub_synth));
  
    if (self->sub_synth)
      g_object_set (self->sub_synth, /* no undo */
@@@ -967,11 -884,11 +966,11 @@@ bse_track_context_dismiss (BseSourc
  
  void
  bse_track_remove_modules (BseTrack     *self,
 -                        BseContainer *container)
 +                          BseContainer *container)
  {
-   g_return_if_fail (BSE_IS_TRACK (self));
-   g_return_if_fail (BSE_IS_CONTAINER (container));
-   g_return_if_fail (self->sub_synth != NULL);
+   assert_return (BSE_IS_TRACK (self));
+   assert_return (BSE_IS_CONTAINER (container));
+   assert_return (self->sub_synth != NULL);
  
    bse_container_remove_item (container, BSE_ITEM (self->sub_synth));
    self->sub_synth = NULL;
@@@ -992,14 -909,12 +991,15 @@@ bse_track_clone_voices (BseTrack       
  {
    guint i;
  
-   g_return_if_fail (BSE_IS_TRACK (self));
-   g_return_if_fail (BSE_IS_SNET (snet));
-   g_return_if_fail (trans != NULL);
+   assert_return (BSE_IS_TRACK (self));
+   assert_return (BSE_IS_SNET (snet));
+   assert_return (trans != NULL);
+ 
 -  for (i = 0; i < self->max_voices - 1; i++)
 -    bse_snet_context_clone_branch (snet, context, BSE_SOURCE (self), mcontext, trans);
 +  if (!self->sound_font_preset)
 +    {
 +      for (i = 0; i < self->max_voices - 1; i++)
 +      bse_snet_context_clone_branch (snet, context, BSE_SOURCE (self), mcontext, trans);
 +    }
  }
  
  static void
diff --cc configure.ac
index 1ae3882,81186a2..bb91f33
--- a/configure.ac
+++ b/configure.ac
@@@ -367,14 -369,9 +369,14 @@@ AC_DEFUN([MC_BSE_REQUIREMENTS]
        AC_MSG_ERROR([Ogg/Vorbis is missing, but required])
      fi
  
 +    dnl Check for FluidSynth
 +    PKG_CHECK_MODULES(FLUID, fluidsynth >= 1.0.6)
 +
      dnl # --- complete CFLAGS/LIBS setup ---
      BSE_CFLAGS="$MAD_CFLAGS $FLAC_CFLAGS $SFI_CPPFLAGS"
-     BSE_LIBS="$OV_LIBS $MAD_LIBS $FLAC_LIBS $SFI_LIBS"
+     BSE_LIBS="$OGGVORBIS_LIBS $MAD_LIBS $FLAC_LIBS $SFI_LIBS"
 +    BSE_CFLAGS="$FLUID_CFLAGS $BSE_CFLAGS"
 +    BSE_LIBS="$FLUID_LIBS $BSE_LIBS"
      AC_SUBST(BSE_CFLAGS)
      AC_SUBST(BSE_LIBS)
      dnl # --- figure stuff for bse.pc ---


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]