[beast/wip/soundfont: 825/832] Merge branch 'master' of github.com/tim-janik/beast into soundfont
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast/wip/soundfont: 825/832] Merge branch 'master' of github.com/tim-janik/beast into soundfont
- Date: Sun, 6 Nov 2016 11:52:03 +0000 (UTC)
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]