[beast/wip/soundfont: 812/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: 812/832] Merge branch 'master' of github.com/tim-janik/beast into soundfont
- Date: Sun, 6 Nov 2016 11:50:57 +0000 (UTC)
commit b14b93fff1da1006a476fd0c70e02700a61ebbef
Merge: 6b6764b b4b5943
Author: Tim Janik <timj gnu org>
Date: Tue Oct 28 15:29:12 2014 +0100
Merge branch 'master' of github.com/tim-janik/beast into soundfont
Synchronize with beast master so that patches against the newer codebase can be applied.
This resolves a number of build rule and license header conflicts.
Makefile.am | 70 +-
Makefile.decl | 33 +-
NEWS | 103 +
README | 47 +-
TODO | 798 -
acbeast.m4 | 211 +
autogen.sh | 160 +-
autotools/glib-gettext.m4 | 3 +-
beast-gtk/.gitignore | 10 +-
beast-gtk/Makefile.am | 175 +-
beast-gtk/bstapp.c | 1262 --
beast-gtk/bstapp.cc | 1227 ++
beast-gtk/bstapp.h | 118 -
beast-gtk/bstapp.hh | 101 +
beast-gtk/bstasciipixbuf.c | 765 -
beast-gtk/bstasciipixbuf.cc | 749 +
beast-gtk/bstasciipixbuf.h | 39 -
beast-gtk/bstasciipixbuf.hh | 24 +
beast-gtk/bstauxdialogs.c | 412 -
beast-gtk/bstauxdialogs.cc | 398 +
beast-gtk/bstauxdialogs.h | 53 -
beast-gtk/bstauxdialogs.hh | 38 +
beast-gtk/bstbseutils.c | 88 -
beast-gtk/bstbseutils.cc | 73 +
beast-gtk/bstbseutils.h | 58 -
beast-gtk/bstbseutils.hh | 39 +
beast-gtk/bstbuseditor.c | 251 -
beast-gtk/bstbuseditor.cc | 236 +
beast-gtk/bstbuseditor.h | 58 -
beast-gtk/bstbuseditor.hh | 43 +
beast-gtk/bstbusmixer.c | 245 -
beast-gtk/bstbusmixer.cc | 230 +
beast-gtk/bstbusmixer.h | 54 -
beast-gtk/bstbusmixer.hh | 39 +
beast-gtk/bstbusview.c | 120 -
beast-gtk/bstbusview.cc | 105 +
beast-gtk/bstbusview.h | 52 -
beast-gtk/bstbusview.hh | 37 +
beast-gtk/bstcanvaslink.c | 609 -
beast-gtk/bstcanvaslink.cc | 600 +
beast-gtk/bstcanvaslink.h | 93 -
beast-gtk/bstcanvaslink.hh | 78 +
beast-gtk/bstcanvassource.c | 1082 -
beast-gtk/bstcanvassource.cc | 1067 +
beast-gtk/bstcanvassource.h | 105 -
beast-gtk/bstcanvassource.hh | 90 +
beast-gtk/bstcluehunter.c | 1027 -
beast-gtk/bstcluehunter.cc | 1007 +
beast-gtk/bstcluehunter.h | 104 -
beast-gtk/bstcluehunter.hh | 89 +
beast-gtk/bstcxxutils.cc | 74 -
beast-gtk/bstcxxutils.h | 29 -
beast-gtk/bstdbmeter.c | 1565 --
beast-gtk/bstdbmeter.cc | 1549 ++
beast-gtk/bstdbmeter.h | 148 -
beast-gtk/bstdbmeter.hh | 133 +
beast-gtk/bstdefs.h | 106 -
beast-gtk/bstdefs.hh | 85 +
beast-gtk/bstdial.c | 686 -
beast-gtk/bstdial.cc | 671 +
beast-gtk/bstdial.h | 96 -
beast-gtk/bstdial.hh | 81 +
beast-gtk/bsteffectview.c | 432 -
beast-gtk/bsteffectview.cc | 417 +
beast-gtk/bsteffectview.h | 77 -
beast-gtk/bsteffectview.hh | 62 +
beast-gtk/bsteventroll.c | 861 -
beast-gtk/bsteventroll.cc | 844 +
beast-gtk/bsteventroll.h | 137 -
beast-gtk/bsteventroll.hh | 121 +
beast-gtk/bsteventrollctrl.c | 813 -
beast-gtk/bsteventrollctrl.cc | 798 +
beast-gtk/bsteventrollctrl.h | 66 -
beast-gtk/bsteventrollctrl.hh | 51 +
beast-gtk/bstfiledialog.c | 983 -
beast-gtk/bstfiledialog.cc | 969 +
beast-gtk/bstfiledialog.h | 137 -
beast-gtk/bstfiledialog.hh | 131 +
beast-gtk/bstgconfig.c | 266 -
beast-gtk/bstgconfig.cc | 251 +
beast-gtk/bstgconfig.h | 49 -
beast-gtk/bstgconfig.hh | 34 +
beast-gtk/bstgrowbar.c | 231 -
beast-gtk/bstgrowbar.cc | 216 +
beast-gtk/bstgrowbar.h | 83 -
beast-gtk/bstgrowbar.hh | 68 +
beast-gtk/bstitemseqdialog.c | 400 -
beast-gtk/bstitemseqdialog.cc | 385 +
beast-gtk/bstitemseqdialog.h | 81 -
beast-gtk/bstitemseqdialog.hh | 66 +
beast-gtk/bstitemview.c | 402 -
beast-gtk/bstitemview.cc | 387 +
beast-gtk/bstitemview.h | 99 -
beast-gtk/bstitemview.hh | 84 +
beast-gtk/bstkeybindings.c | 720 -
beast-gtk/bstkeybindings.cc | 705 +
beast-gtk/bstkeybindings.h | 94 -
beast-gtk/bstkeybindings.hh | 79 +
beast-gtk/bstknob.c | 650 -
beast-gtk/bstknob.cc | 635 +
beast-gtk/bstknob.h | 88 -
beast-gtk/bstknob.hh | 73 +
beast-gtk/bstlogadjustment.c | 225 -
beast-gtk/bstlogadjustment.cc | 210 +
beast-gtk/bstlogadjustment.h | 69 -
beast-gtk/bstlogadjustment.hh | 54 +
beast-gtk/bstmain.c | 899 -
beast-gtk/bstmain.cc | 855 +
beast-gtk/bstmenus.c | 465 -
beast-gtk/bstmenus.cc | 448 +
beast-gtk/bstmenus.h | 91 -
beast-gtk/bstmenus.hh | 85 +
beast-gtk/bstmsgabsorb.c | 422 -
beast-gtk/bstmsgabsorb.cc | 407 +
beast-gtk/bstmsgabsorb.h | 48 -
beast-gtk/bstmsgabsorb.hh | 33 +
beast-gtk/bstparam-automation.c | 238 -
beast-gtk/bstparam-automation.cc | 223 +
beast-gtk/bstparam-choice.c | 170 -
beast-gtk/bstparam-choice.cc | 155 +
beast-gtk/bstparam-color-spinner.c | 119 -
beast-gtk/bstparam-color-spinner.cc | 104 +
beast-gtk/bstparam-item-seq.c | 149 -
beast-gtk/bstparam-item-seq.cc | 134 +
beast-gtk/bstparam-note-sequence.c | 64 -
beast-gtk/bstparam-note-sequence.cc | 49 +
beast-gtk/bstparam-note-spinner.c | 78 -
beast-gtk/bstparam-note-spinner.cc | 63 +
beast-gtk/bstparam-proxy.c | 298 -
beast-gtk/bstparam-proxy.cc | 283 +
beast-gtk/bstparam-scale.c | 98 -
beast-gtk/bstparam-scale.cc | 83 +
beast-gtk/bstparam-searchpath.c | 157 -
beast-gtk/bstparam-searchpath.cc | 142 +
beast-gtk/bstparam-time.c | 58 -
beast-gtk/bstparam-time.cc | 43 +
beast-gtk/bstparam.c | 462 -
beast-gtk/bstparam.cc | 448 +
beast-gtk/bstparam.h | 70 -
beast-gtk/bstparam.hh | 55 +
beast-gtk/bstparamview.c | 273 -
beast-gtk/bstparamview.cc | 258 +
beast-gtk/bstparamview.h | 72 -
beast-gtk/bstparamview.hh | 57 +
beast-gtk/bstpartdialog.c | 438 -
beast-gtk/bstpartdialog.cc | 421 +
beast-gtk/bstpartdialog.h | 66 -
beast-gtk/bstpartdialog.hh | 51 +
beast-gtk/bstpartview.c | 146 -
beast-gtk/bstpartview.cc | 131 +
beast-gtk/bstpartview.h | 52 -
beast-gtk/bstpartview.hh | 37 +
beast-gtk/bstpatterncolumns.c | 902 -
beast-gtk/bstpatterncolumns.cc | 890 +
beast-gtk/bstpatterncolumns.h | 167 -
beast-gtk/bstpatterncolumns.hh | 166 +
beast-gtk/bstpatternctrl.c | 561 -
beast-gtk/bstpatternctrl.cc | 564 +
beast-gtk/bstpatternctrl.h | 50 -
beast-gtk/bstpatternctrl.hh | 35 +
beast-gtk/bstpatternview.c | 1251 --
beast-gtk/bstpatternview.cc | 1231 ++
beast-gtk/bstpatternview.h | 157 -
beast-gtk/bstpatternview.hh | 138 +
beast-gtk/bstpianoroll.c | 1513 --
beast-gtk/bstpianoroll.cc | 1497 ++
beast-gtk/bstpianoroll.h | 135 -
beast-gtk/bstpianoroll.hh | 120 +
beast-gtk/bstpianorollctrl.c | 975 -
beast-gtk/bstpianorollctrl.cc | 959 +
beast-gtk/bstpianorollctrl.h | 70 -
beast-gtk/bstpianorollctrl.hh | 55 +
beast-gtk/bstplayback.c | 205 -
beast-gtk/bstplayback.cc | 190 +
beast-gtk/bstplayback.h | 74 -
beast-gtk/bstplayback.hh | 59 +
beast-gtk/bstplaylist.c | 569 -
beast-gtk/bstplaylist.cc | 554 +
beast-gtk/bstplaylist.h | 68 -
beast-gtk/bstplaylist.hh | 53 +
beast-gtk/bstpreferences.c | 400 -
beast-gtk/bstpreferences.cc | 387 +
beast-gtk/bstpreferences.h | 77 -
beast-gtk/bstpreferences.hh | 62 +
beast-gtk/bstprocbrowser.c | 272 -
beast-gtk/bstprocbrowser.cc | 257 +
beast-gtk/bstprocbrowser.h | 72 -
beast-gtk/bstprocbrowser.hh | 57 +
beast-gtk/bstprocedure.c | 594 -
beast-gtk/bstprocedure.cc | 579 +
beast-gtk/bstprocedure.h | 88 -
beast-gtk/bstprocedure.hh | 73 +
beast-gtk/bstprofiler.c | 272 -
beast-gtk/bstprofiler.cc | 164 +
beast-gtk/bstprofiler.h | 29 -
beast-gtk/bstprofiler.hh | 14 +
beast-gtk/bstprojectctrl.c | 189 -
beast-gtk/bstprojectctrl.cc | 174 +
beast-gtk/bstprojectctrl.h | 57 -
beast-gtk/bstprojectctrl.hh | 42 +
beast-gtk/bstqsampler.c | 1397 --
beast-gtk/bstqsampler.cc | 1380 ++
beast-gtk/bstqsampler.h | 204 -
beast-gtk/bstqsampler.hh | 197 +
beast-gtk/bstrackeditor-covers.c | 190 -
beast-gtk/bstrackeditor-covers.cc | 177 +
beast-gtk/bstrackeditor.c | 313 -
beast-gtk/bstrackeditor.cc | 297 +
beast-gtk/bstrackeditor.h | 70 -
beast-gtk/bstrackeditor.hh | 55 +
beast-gtk/bstrackitem.c | 267 -
beast-gtk/bstrackitem.cc | 248 +
beast-gtk/bstrackitem.h | 63 -
beast-gtk/bstrackitem.hh | 48 +
beast-gtk/bstracktable.c | 1018 -
beast-gtk/bstracktable.cc | 1001 +
beast-gtk/bstracktable.h | 111 -
beast-gtk/bstracktable.hh | 96 +
beast-gtk/bstrackview.c | 267 -
beast-gtk/bstrackview.cc | 252 +
beast-gtk/bstrackview.h | 58 -
beast-gtk/bstrackview.hh | 43 +
beast-gtk/bstrecords.idl | 206 +-
beast-gtk/bstrtest.c | 313 -
beast-gtk/bstrtest.cc | 298 +
beast-gtk/bstsampleeditor.c | 544 -
beast-gtk/bstsampleeditor.cc | 526 +
beast-gtk/bstsampleeditor.h | 76 -
beast-gtk/bstsampleeditor.hh | 61 +
beast-gtk/bstscrollgraph.c | 701 -
beast-gtk/bstscrollgraph.cc | 686 +
beast-gtk/bstscrollgraph.h | 72 -
beast-gtk/bstscrollgraph.hh | 57 +
beast-gtk/bstsegment.c | 217 -
beast-gtk/bstsegment.cc | 202 +
beast-gtk/bstsegment.h | 79 -
beast-gtk/bstsegment.hh | 64 +
beast-gtk/bstsequence.c | 295 -
beast-gtk/bstsequence.cc | 280 +
beast-gtk/bstsequence.h | 68 -
beast-gtk/bstsequence.hh | 53 +
beast-gtk/bstservermonitor.c | 98 -
beast-gtk/bstservermonitor.cc | 83 +
beast-gtk/bstservermonitor.h | 64 -
beast-gtk/bstservermonitor.hh | 49 +
beast-gtk/bstskinconfig.c | 321 -
beast-gtk/bstskinconfig.cc | 308 +
beast-gtk/bstskinconfig.h | 50 -
beast-gtk/bstskinconfig.hh | 35 +
beast-gtk/bstsnetrouter.c | 1178 --
beast-gtk/bstsnetrouter.cc | 1148 ++
beast-gtk/bstsnetrouter.h | 81 -
beast-gtk/bstsnetrouter.hh | 66 +
beast-gtk/bstsnifferscope.c | 344 -
beast-gtk/bstsnifferscope.cc | 329 +
beast-gtk/bstsnifferscope.h | 61 -
beast-gtk/bstsnifferscope.hh | 46 +
beast-gtk/bstsplash.c | 475 -
beast-gtk/bstsplash.cc | 436 +
beast-gtk/bstsplash.h | 93 -
beast-gtk/bstsplash.hh | 72 +
beast-gtk/bststest.c | 770 -
beast-gtk/bststest.cc | 754 +
beast-gtk/bstsupershell.c | 281 -
beast-gtk/bstsupershell.cc | 266 +
beast-gtk/bstsupershell.h | 56 -
beast-gtk/bstsupershell.hh | 41 +
beast-gtk/bsttrackroll.c | 1251 --
beast-gtk/bsttrackroll.cc | 1235 ++
beast-gtk/bsttrackroll.h | 149 -
beast-gtk/bsttrackroll.hh | 134 +
beast-gtk/bsttrackrollctrl.c | 725 -
beast-gtk/bsttrackrollctrl.cc | 709 +
beast-gtk/bsttrackrollctrl.h | 64 -
beast-gtk/bsttrackrollctrl.hh | 49 +
beast-gtk/bsttracksynthdialog.c | 342 -
beast-gtk/bsttracksynthdialog.cc | 326 +
beast-gtk/bsttracksynthdialog.h | 89 -
beast-gtk/bsttracksynthdialog.hh | 73 +
beast-gtk/bsttrackview.c | 792 -
beast-gtk/bsttrackview.cc | 777 +
beast-gtk/bsttrackview.h | 59 -
beast-gtk/bsttrackview.hh | 44 +
beast-gtk/bsttreestores.c | 724 -
beast-gtk/bsttreestores.cc | 704 +
beast-gtk/bsttreestores.h | 104 -
beast-gtk/bsttreestores.hh | 89 +
beast-gtk/bstusermessage.c | 852 -
beast-gtk/bstusermessage.cc | 783 +
beast-gtk/bstusermessage.h | 108 -
beast-gtk/bstusermessage.hh | 84 +
beast-gtk/bstutils.c | 1500 --
beast-gtk/bstutils.cc | 1515 ++
beast-gtk/bstutils.h | 239 -
beast-gtk/bstutils.hh | 234 +
beast-gtk/bstwaveeditor.c | 706 -
beast-gtk/bstwaveeditor.cc | 688 +
beast-gtk/bstwaveeditor.h | 95 -
beast-gtk/bstwaveeditor.hh | 80 +
beast-gtk/bstwaveview.c | 191 -
beast-gtk/bstwaveview.cc | 175 +
beast-gtk/bstwaveview.h | 56 -
beast-gtk/bstwaveview.hh | 41 +
beast-gtk/bstxframe.c | 377 -
beast-gtk/bstxframe.cc | 362 +
beast-gtk/bstxframe.h | 67 -
beast-gtk/bstxframe.hh | 52 +
beast-gtk/bstxkb.c | 198 -
beast-gtk/bstxkb.cc | 183 +
beast-gtk/bstxkb.h | 48 -
beast-gtk/bstxkb.hh | 33 +
beast-gtk/bstzoomedwindow.c | 257 -
beast-gtk/bstzoomedwindow.cc | 243 +
beast-gtk/bstzoomedwindow.h | 63 -
beast-gtk/bstzoomedwindow.hh | 48 +
beast-gtk/dialogs/.gitignore | 2 +-
beast-gtk/dialogs/Makefile.am | 14 +-
beast-gtk/dialogs/radgets-beast.xml | 12 +-
beast-gtk/dialogs/radgets-standard.xml | 12 +-
beast-gtk/gxk/Makefile.am | 77 +-
beast-gtk/gxk/gle-pull.sh | 2 +
beast-gtk/gxk/glewidgets.c | 362 +-
beast-gtk/gxk/glewidgets.h | 8 +-
beast-gtk/gxk/gxk.h | 50 -
beast-gtk/gxk/gxk.hh | 35 +
beast-gtk/gxk/gxkaction.c | 992 -
beast-gtk/gxk/gxkaction.cc | 977 +
beast-gtk/gxk/gxkaction.h | 180 -
beast-gtk/gxk/gxkaction.hh | 165 +
beast-gtk/gxk/gxkassortment.c | 646 -
beast-gtk/gxk/gxkassortment.cc | 631 +
beast-gtk/gxk/gxkassortment.h | 114 -
beast-gtk/gxk/gxkassortment.hh | 99 +
beast-gtk/gxk/gxkauxwidgets.c | 819 -
beast-gtk/gxk/gxkauxwidgets.cc | 804 +
beast-gtk/gxk/gxkauxwidgets.h | 112 -
beast-gtk/gxk/gxkauxwidgets.hh | 97 +
beast-gtk/gxk/gxkcanvas.c | 246 -
beast-gtk/gxk/gxkcanvas.cc | 231 +
beast-gtk/gxk/gxkcanvas.h | 50 -
beast-gtk/gxk/gxkcanvas.hh | 35 +
beast-gtk/gxk/gxkcellrendererpopup.c | 544 -
beast-gtk/gxk/gxkcellrendererpopup.cc | 529 +
beast-gtk/gxk/gxkcellrendererpopup.h | 91 -
beast-gtk/gxk/gxkcellrendererpopup.hh | 76 +
beast-gtk/gxk/gxkdialog.c | 734 -
beast-gtk/gxk/gxkdialog.cc | 717 +
beast-gtk/gxk/gxkdialog.h | 132 -
beast-gtk/gxk/gxkdialog.hh | 131 +
beast-gtk/gxk/gxkglobals.c | 59 -
beast-gtk/gxk/gxkglobals.cc | 44 +
beast-gtk/gxk/gxkglobals.h | 76 -
beast-gtk/gxk/gxkglobals.hh | 84 +
beast-gtk/gxk/gxkimagecache.c | 199 -
beast-gtk/gxk/gxkimagecache.cc | 184 +
beast-gtk/gxk/gxkimagecache.h | 44 -
beast-gtk/gxk/gxkimagecache.hh | 29 +
beast-gtk/gxk/gxkled.c | 332 -
beast-gtk/gxk/gxkled.cc | 317 +
beast-gtk/gxk/gxkled.h | 66 -
beast-gtk/gxk/gxkled.hh | 51 +
beast-gtk/gxk/gxklistwrapper.c | 544 -
beast-gtk/gxk/gxklistwrapper.cc | 526 +
beast-gtk/gxk/gxklistwrapper.h | 86 -
beast-gtk/gxk/gxklistwrapper.hh | 71 +
beast-gtk/gxk/gxklogadjustment.c | 460 -
beast-gtk/gxk/gxklogadjustment.cc | 445 +
beast-gtk/gxk/gxklogadjustment.h | 117 -
beast-gtk/gxk/gxklogadjustment.hh | 102 +
beast-gtk/gxk/gxkmenubutton.c | 790 -
beast-gtk/gxk/gxkmenubutton.cc | 775 +
beast-gtk/gxk/gxkmenubutton.h | 59 -
beast-gtk/gxk/gxkmenubutton.hh | 44 +
beast-gtk/gxk/gxknotebook.c | 299 -
beast-gtk/gxk/gxknotebook.cc | 284 +
beast-gtk/gxk/gxknotebook.h | 51 -
beast-gtk/gxk/gxknotebook.hh | 36 +
beast-gtk/gxk/gxkparam-entry.c | 66 -
beast-gtk/gxk/gxkparam-entry.cc | 51 +
beast-gtk/gxk/gxkparam-label.c | 80 -
beast-gtk/gxk/gxkparam-label.cc | 65 +
beast-gtk/gxk/gxkparam-scale.c | 118 -
beast-gtk/gxk/gxkparam-scale.cc | 103 +
beast-gtk/gxk/gxkparam-spinner.c | 107 -
beast-gtk/gxk/gxkparam-spinner.cc | 92 +
beast-gtk/gxk/gxkparam-toggle.c | 91 -
beast-gtk/gxk/gxkparam-toggle.cc | 76 +
beast-gtk/gxk/gxkparam.c | 1184 --
beast-gtk/gxk/gxkparam.cc | 1172 ++
beast-gtk/gxk/gxkparam.h | 194 -
beast-gtk/gxk/gxkparam.hh | 179 +
beast-gtk/gxk/gxkpolygon.c | 594 -
beast-gtk/gxk/gxkpolygon.cc | 579 +
beast-gtk/gxk/gxkpolygon.h | 88 -
beast-gtk/gxk/gxkpolygon.hh | 73 +
beast-gtk/gxk/gxkrackcovers.c | 202 -
beast-gtk/gxk/gxkrackcovers.cc | 187 +
beast-gtk/gxk/gxkrackeditor.c | 681 -
beast-gtk/gxk/gxkrackeditor.cc | 666 +
beast-gtk/gxk/gxkrackeditor.h | 77 -
beast-gtk/gxk/gxkrackeditor.hh | 62 +
beast-gtk/gxk/gxkrackitem.c | 319 -
beast-gtk/gxk/gxkrackitem.cc | 304 +
beast-gtk/gxk/gxkrackitem.h | 63 -
beast-gtk/gxk/gxkrackitem.hh | 48 +
beast-gtk/gxk/gxkracktable.c | 707 -
beast-gtk/gxk/gxkracktable.cc | 691 +
beast-gtk/gxk/gxkracktable.h | 94 -
beast-gtk/gxk/gxkracktable.hh | 79 +
beast-gtk/gxk/gxkradget.c | 2465 ---
beast-gtk/gxk/gxkradget.cc | 2448 +++
beast-gtk/gxk/gxkradget.h | 126 -
beast-gtk/gxk/gxkradget.hh | 111 +
beast-gtk/gxk/gxkradgetfactory.c | 606 -
beast-gtk/gxk/gxkradgetfactory.cc | 591 +
beast-gtk/gxk/gxkradgetfactory.h | 92 -
beast-gtk/gxk/gxkradgetfactory.hh | 77 +
beast-gtk/gxk/gxkscrollcanvas.c | 1901 --
beast-gtk/gxk/gxkscrollcanvas.cc | 1878 ++
beast-gtk/gxk/gxkscrollcanvas.h | 250 -
beast-gtk/gxk/gxkscrollcanvas.hh | 235 +
beast-gtk/gxk/gxksimplelabel.c | 704 -
beast-gtk/gxk/gxksimplelabel.cc | 677 +
beast-gtk/gxk/gxksimplelabel.h | 58 -
beast-gtk/gxk/gxksimplelabel.hh | 39 +
beast-gtk/gxk/gxkspline.c | 444 -
beast-gtk/gxk/gxkspline.cc | 429 +
beast-gtk/gxk/gxkspline.h | 58 -
beast-gtk/gxk/gxkspline.hh | 43 +
beast-gtk/gxk/gxkstatusbar.c | 391 -
beast-gtk/gxk/gxkstatusbar.cc | 315 +
beast-gtk/gxk/gxkstatusbar.h | 69 -
beast-gtk/gxk/gxkstatusbar.hh | 48 +
beast-gtk/gxk/gxkstock.c | 402 -
beast-gtk/gxk/gxkstock.cc | 387 +
beast-gtk/gxk/gxkstock.h | 80 -
beast-gtk/gxk/gxkstock.hh | 65 +
beast-gtk/gxk/gxktest.c | 370 -
beast-gtk/gxk/gxktest.cc | 353 +
beast-gtk/gxk/gxktexttools.c | 2315 ---
beast-gtk/gxk/gxktexttools.cc | 2269 +++
beast-gtk/gxk/gxktexttools.h | 109 -
beast-gtk/gxk/gxktexttools.hh | 101 +
beast-gtk/gxk/gxkutils.c | 3971 ----
beast-gtk/gxk/gxkutils.cc | 3951 ++++
beast-gtk/gxk/gxkutils.h | 365 -
beast-gtk/gxk/gxkutils.hh | 350 +
beast-gtk/gxk/splinetest.c | 186 -
beast-gtk/gxk/splinetest.cc | 170 +
beast-gtk/icons/.gitignore | 2 +-
beast-gtk/icons/Makefile.am | 13 +-
beast-gtk/testgui.c | 161 -
beast-gtk/testgui.cc | 137 +
beast-gtk/tsmview.c | 104 -
beast-gtk/tsmview.cc | 89 +
beast.doap | 4 +-
birnet/.gitignore | 4 -
birnet/COPYING.LGPL | 504 -
birnet/Makefile.am | 137 -
birnet/acbirnet.m4 | 340 -
birnet/birnet-zintern.cc | 233 -
birnet/birnet.hh | 32 -
birnet/birnetcdefs.h | 382 -
birnet/birnetcpu.cc | 309 -
birnet/birnetcpu.hh | 36 -
birnet/birnetdebugtools.cc | 112 -
birnet/birnetdebugtools.hh | 50 -
birnet/birnetmath.cc | 21 -
birnet/birnetmath.hh | 79 -
birnet/birnetmsg.cc | 627 -
birnet/birnetmsg.hh | 199 -
birnet/birnettests.h | 349 -
birnet/birnetthread.cc | 342 -
birnet/birnetthread.hh | 359 -
birnet/birnetthreadimpl.cc | 1780 --
birnet/birnetutf8.cc | 325 -
birnet/birnetutf8.hh | 210 -
birnet/birnetutils.cc | 1477 --
birnet/birnetutils.hh | 622 -
birnet/configure.inc | 160 -
birnet/examples/mkhost.sh | 370 -
birnet/tests/.gitignore | 9 -
birnet/tests/Makefile.am | 40 -
birnet/tests/datalist.cc | 126 -
birnet/tests/infotest.cc | 168 -
birnet/tests/math.cc | 179 -
birnet/tests/sorting.cc | 139 -
birnet/tests/strings.cc | 272 -
birnet/tests/systest.cc | 54 -
birnet/tests/threads.cc | 1187 --
birnet/tests/utils.cc | 102 -
bse/AuxTypes.py | 31 +
bse/Makefile.am | 324 +-
bse/bse-internals.hh | 15 +
bse/bse.h | 46 -
bse/bse.hh | 21 +
bse/bse.idl | 30 +-
bse/bseapi.idl | 41 +
bse/bseautodoc.c | 632 -
bse/bseautodoc.cc | 606 +
bse/bsebasics.cc | 16 +
bse/bsebasics.idl | 713 +
bse/bsebiquadfilter.c | 553 -
bse/bsebiquadfilter.cc | 532 +
bse/bsebiquadfilter.h | 94 -
bse/bsebiquadfilter.hh | 71 +
bse/bseblockutils.cc | 18 +-
bse/bseblockutils.hh | 79 +-
bse/bsebus.c | 937 -
bse/bsebus.cc | 923 +
bse/bsebus.h | 103 -
bse/bsebus.hh | 82 +
bse/bsebus.proc | 53 +-
bse/bsebusmodule.cc | 19 +-
bse/bsebusmodule.idl | 39 +-
bse/bsecategories.c | 366 -
bse/bsecategories.cc | 348 +
bse/bsecategories.h | 55 -
bse/bsecategories.hh | 38 +
bse/bsecategories.proc | 68 +-
bse/bsecompat.c | 100 -
bse/bsecompat.cc | 86 +
bse/bsecompat.h | 54 -
bse/bsecompat.hh | 39 +
bse/bseconfig.h.in | 35 +-
bse/bseconstant.c | 306 -
bse/bseconstant.cc | 288 +
bse/bseconstant.h | 59 -
bse/bseconstant.hh | 34 +
bse/bseconstvalues.c | 19 -
bse/bseconstvalues.cc | 4 +
bse/bseconstvalues.h | 102 -
bse/bseconstvalues.hh | 87 +
bse/bsecontainer.c | 1371 --
bse/bsecontainer.cc | 1355 ++
bse/bsecontainer.h | 128 -
bse/bsecontainer.hh | 106 +
bse/bsecontainer.proc | 46 +-
bse/bsecontextmerger.c | 226 -
bse/bsecontextmerger.cc | 211 +
bse/bsecontextmerger.h | 52 -
bse/bsecontextmerger.hh | 27 +
bse/bsecore.cc | 202 +-
bse/bsecore.hh | 36 +
bse/bsecore.idl | 833 -
bse/bsecsynth.c | 119 -
bse/bsecsynth.cc | 104 +
bse/bsecsynth.h | 50 -
bse/bsecsynth.hh | 27 +
bse/bsecsynth.proc | 25 +-
bse/bsecxxarg.cc | 17 +-
bse/bsecxxarg.hh | 23 +-
bse/bsecxxbase.cc | 23 +-
bse/bsecxxbase.hh | 19 +-
bse/bsecxxbase.idl | 27 +-
bse/bsecxxclosure.cc | 19 +-
bse/bsecxxclosure.hh | 19 +-
bse/bsecxxmodule.cc | 83 +-
bse/bsecxxmodule.hh | 65 +-
bse/bsecxxmodule.idl | 25 +-
bse/bsecxxplugin.cc | 21 +-
bse/bsecxxplugin.hh | 65 +-
bse/bsecxxutils.cc | 58 +-
bse/bsecxxutils.hh | 23 +-
bse/bsecxxvalue.cc | 21 +-
bse/bsecxxvalue.hh | 21 +-
bse/bsedatahandle-fir.cc | 53 +-
bse/bsedatahandle-flac.cc | 453 +
bse/bsedatahandle-flac.hh | 38 +
bse/bsedatahandle-resample.cc | 48 +-
bse/bsedatapocket.c | 686 -
bse/bsedatapocket.cc | 673 +
bse/bsedatapocket.h | 106 -
bse/bsedatapocket.hh | 81 +
bse/bsedatapocket.proc | 179 +-
bse/bsedefs.h | 172 -
bse/bsedefs.hh | 146 +
bse/bsedevice.c | 517 -
bse/bsedevice.cc | 502 +
bse/bsedevice.h | 139 -
bse/bsedevice.hh | 117 +
bse/bseeditablesample.c | 188 -
bse/bseeditablesample.cc | 173 +
bse/bseeditablesample.h | 66 -
bse/bseeditablesample.hh | 36 +
bse/bseeditablesample.proc | 131 +-
bse/bseengine.c | 1626 --
bse/bseengine.cc | 1515 ++
bse/bseengine.h | 242 -
bse/bseengine.hh | 225 +
bse/bseenginemaster.c | 1202 --
bse/bseenginemaster.cc | 1178 ++
bse/bseenginemaster.h | 37 -
bse/bseenginemaster.hh | 28 +
bse/bseenginenode.h | 225 -
bse/bseenginenode.hh | 203 +
bse/bseengineschedule.c | 811 -
bse/bseengineschedule.cc | 762 +
bse/bseengineschedule.h | 66 -
bse/bseengineschedule.hh | 51 +
bse/bseengineutils.c | 860 -
bse/bseengineutils.cc | 797 +
bse/bseengineutils.h | 73 -
bse/bseengineutils.hh | 57 +
bse/bseenums.c | 183 -
bse/bseenums.cc | 164 +
bse/bseenums.h | 156 -
bse/bseenums.hh | 152 +
bse/bseenums.proc | 43 +-
bse/bseexports.h | 187 -
bse/bseexports.hh | 169 +
bse/bsefilter-ellf.c | 1607 --
bse/bsefilter-ellf.cc | 1589 ++
bse/bsefilter.cc | 26 +-
bse/bsefilter.h | 110 -
bse/bsefilter.hh | 90 +
bse/bsegconfig.c | 138 -
bse/bsegconfig.cc | 218 +
bse/bsegconfig.h | 37 -
bse/bsegconfig.hh | 22 +
bse/{bsegenclosures.h => bsegenclosures.hh} | 0
bse/bseglobals.c | 228 -
bse/bseglobals.cc | 213 +
bse/bseglobals.h | 95 -
bse/bseglobals.hh | 80 +
bse/bseglue.c | 1177 --
bse/bseglue.cc | 1162 ++
bse/bseglue.h | 50 -
bse/bseglue.hh | 35 +
bse/bseieee754.h | 333 -
bse/bseieee754.hh | 317 +
bse/bseincluder.h |12343 -----------
bse/bseincluder.hh |12327 +++++++++++
bse/bseinfo.c | 122 -
bse/bseinfo.cc | 104 +
bse/bseinstrument.c | 660 -
bse/bseinstrument.h | 88 -
bse/bseinstrument.hh | 73 +
bse/bseinstrumentinput.c | 152 -
bse/bseinstrumentinput.cc | 151 +
bse/bseinstrumentinput.h | 58 -
bse/bseinstrumentinput.hh | 34 +
bse/bseinstrumentoutput.c | 152 -
bse/bseinstrumentoutput.cc | 151 +
bse/bseinstrumentoutput.h | 57 -
bse/bseinstrumentoutput.hh | 32 +
bse/bseitem.c | 1268 --
bse/bseitem.cc | 1239 ++
bse/bseitem.h | 173 -
bse/bseitem.hh | 150 +
bse/bseitem.proc | 239 +-
bse/bsejanitor.c | 582 -
bse/bsejanitor.cc | 567 +
bse/bsejanitor.h | 87 -
bse/bsejanitor.hh | 67 +
bse/bsejanitor.proc | 182 +-
bse/bseladspa.cc | 113 +-
bse/bseladspa.h | 107 -
bse/bseladspa.hh | 87 +
bse/bseladspamodule.c | 503 -
bse/bseladspamodule.cc | 488 +
bse/bseladspamodule.h | 55 -
bse/bseladspamodule.hh | 34 +
bse/bseloader-aiff.c | 567 -
bse/bseloader-aiff.cc | 549 +
bse/bseloader-bsewave.c | 842 -
bse/bseloader-bsewave.cc | 870 +
bse/bseloader-flac.cc | 189 +
bse/bseloader-guspatch.cc | 192 +-
bse/bseloader-mad.c | 218 -
bse/bseloader-mad.cc | 203 +
bse/bseloader-oggvorbis.c | 180 -
bse/bseloader-oggvorbis.cc | 165 +
bse/bseloader-wav.c | 496 -
bse/bseloader-wav.cc | 463 +
bse/bseloader.c | 402 -
bse/bseloader.cc | 387 +
bse/bseloader.h | 129 -
bse/bseloader.hh | 112 +
bse/bsemain.cc | 539 +-
bse/bsemain.h | 111 -
bse/bsemain.hh | 67 +
bse/bsemath.c | 342 -
bse/bsemath.cc | 253 +
bse/bsemath.h | 499 -
bse/bsemath.hh | 484 +
bse/bsemathsignal.c | 743 -
bse/bsemathsignal.cc | 727 +
bse/bsemathsignal.h | 730 -
bse/bsemathsignal.hh | 714 +
bse/bsemidicontroller.c | 335 -
bse/bsemidicontroller.cc | 321 +
bse/bsemidicontroller.h | 64 -
bse/bsemidicontroller.hh | 38 +
bse/bsemididecoder.c | 560 -
bse/bsemididecoder.cc | 543 +
bse/bsemididecoder.h | 77 -
bse/bsemididecoder.hh | 59 +
bse/bsemididevice-null.c | 118 -
bse/bsemididevice-null.cc | 92 +
bse/bsemididevice-null.h | 48 -
bse/bsemididevice-null.hh | 23 +
bse/bsemididevice-oss.c | 300 -
bse/bsemididevice-oss.cc | 270 +
bse/bsemididevice-oss.h | 52 -
bse/bsemididevice-oss.hh | 25 +
bse/bsemididevice.c | 97 -
bse/bsemididevice.cc | 82 +
bse/bsemididevice.h | 68 -
bse/bsemididevice.hh | 35 +
bse/bsemidievent.c | 276 -
bse/bsemidievent.cc | 262 +
bse/bsemidievent.h | 347 -
bse/bsemidievent.hh | 332 +
bse/bsemidifile.c | 367 -
bse/bsemidifile.cc | 350 +
bse/bsemidifile.h | 52 -
bse/bsemidifile.hh | 37 +
bse/bsemidiinput.c | 273 -
bse/bsemidiinput.cc | 258 +
bse/bsemidiinput.h | 63 -
bse/bsemidiinput.hh | 37 +
bse/bsemidinotifier.c | 287 -
bse/bsemidinotifier.cc | 274 +
bse/bsemidinotifier.h | 59 -
bse/bsemidinotifier.hh | 32 +
bse/bsemidinotifier.proc | 33 +-
bse/bsemidireceiver.cc | 291 +-
bse/bsemidireceiver.h | 136 -
bse/bsemidireceiver.hh | 116 +
bse/bsemidisynth.c | 485 -
bse/bsemidisynth.cc | 466 +
bse/bsemidisynth.h | 63 -
bse/bsemidisynth.hh | 35 +
bse/bsemidivoice.c | 393 -
bse/bsemidivoice.cc | 378 +
bse/bsemidivoice.h | 97 -
bse/bsemidivoice.hh | 73 +
bse/bsenote.cc | 57 +-
bse/bsenote.h | 108 -
bse/bsenote.hh | 93 +
bse/bseobject.c | 887 -
bse/bseobject.cc | 858 +
bse/bseobject.h | 181 -
bse/bseobject.hh | 151 +
bse/bseparam.c | 113 -
bse/bseparam.cc | 98 +
bse/bseparam.h | 78 -
bse/bseparam.hh | 63 +
bse/bseparasite.c | 751 -
bse/bseparasite.cc | 709 +
bse/bseparasite.h | 61 -
bse/bseparasite.hh | 46 +
bse/bseparasite.proc | 34 +-
bse/bsepart.c | 2125 --
bse/bsepart.cc | 2109 ++
bse/bsepart.h | 301 -
bse/bsepart.hh | 270 +
bse/bsepart.proc | 264 +-
bse/bsepattern.c | 1072 -
bse/bsepattern.h | 194 -
bse/bsepattern.hh | 177 +
bse/bsepattern.proc.c | 254 -
bse/bsepatterngroup.c | 374 -
bse/bsepatterngroup.h | 76 -
bse/bsepatterngroup.hh | 59 +
bse/bsepcmdevice-null.c | 169 -
bse/bsepcmdevice-null.cc | 160 +
bse/bsepcmdevice-null.h | 47 -
bse/bsepcmdevice-null.hh | 26 +
bse/bsepcmdevice-oss.c | 683 -
bse/bsepcmdevice-oss.cc | 650 +
bse/bsepcmdevice-oss.h | 55 -
bse/bsepcmdevice-oss.hh | 26 +
bse/bsepcmdevice.c | 234 -
bse/bsepcmdevice.cc | 208 +
bse/bsepcmdevice.h | 111 -
bse/bsepcmdevice.hh | 79 +
bse/bsepcminput.c | 298 -
bse/bsepcminput.cc | 283 +
bse/bsepcminput.h | 62 -
bse/bsepcminput.hh | 37 +
bse/bsepcmmodule.c | 276 -
bse/bsepcmmodule.cc | 256 +
bse/bsepcmoutput.c | 298 -
bse/bsepcmoutput.cc | 283 +
bse/bsepcmoutput.h | 70 -
bse/bsepcmoutput.hh | 43 +
bse/bsepcmwriter.c | 202 -
bse/bsepcmwriter.cc | 162 +
bse/bsepcmwriter.h | 67 -
bse/bsepcmwriter.hh | 46 +
bse/bseplugin.c | 807 -
bse/bseplugin.cc | 789 +
bse/bseplugin.h | 108 -
bse/bseplugin.hh | 43 +
bse/bseprobe.cc | 53 +-
bse/bseprobe.idl | 26 +-
bse/bseprocedure.c | 754 -
bse/bseprocedure.cc | 716 +
bse/bseprocedure.h | 111 -
bse/bseprocedure.hh | 96 +
bse/bseprocedure.proc | 84 +-
bse/bseprocidl.cc | 107 +-
bse/bseproject.c | 1015 -
bse/bseproject.cc | 990 +
bse/bseproject.h | 108 -
bse/bseproject.hh | 84 +
bse/bseproject.proc | 287 +-
bse/bsequery.c | 377 -
bse/bsequery.cc | 349 +
bse/bseresampler.cc | 19 +-
bse/bseresampler.hh | 34 +-
bse/bseresamplerimpl.hh | 92 +-
bse/bsescripthelper.c | 383 -
bse/bsescripthelper.cc | 369 +
bse/bsescripthelper.h | 64 -
bse/bsescripthelper.hh | 49 +
bse/bsescripthelper.proc | 35 +-
bse/bsesequencer.cc | 425 +-
bse/bsesequencer.h | 45 -
bse/bsesequencer.hh | 51 +
bse/bseserver.c | 1189 --
bse/bseserver.cc | 1154 ++
bse/bseserver.h | 140 -
bse/bseserver.hh | 115 +
bse/bseserver.proc | 185 +-
bse/bsesnet.c | 970 -
bse/bsesnet.cc | 951 +
bse/bsesnet.h | 136 -
bse/bsesnet.hh | 109 +
bse/bsesnet.proc | 61 +-
bse/bsesnooper.c | 244 -
bse/bsesnooper.cc | 227 +
bse/bsesnooper.h | 54 -
bse/bsesnooper.hh | 32 +
bse/bsesong.c | 806 -
bse/bsesong.cc | 780 +
bse/bsesong.h | 103 -
bse/bsesong.hh | 74 +
bse/bsesong.proc | 155 +-
bse/bsesource.c | 2082 --
bse/bsesource.cc | 2063 ++
bse/bsesource.h | 311 -
bse/bsesource.hh | 276 +
bse/bsesource.proc | 246 +-
bse/bsestandardosc.c | 515 -
bse/bsestandardosc.cc | 500 +
bse/bsestandardosc.h | 86 -
bse/bsestandardosc.hh | 55 +
bse/bsestandardsynths.c | 114 -
bse/bsestandardsynths.cc | 99 +
bse/bsestandardsynths.h | 33 -
bse/bsestandardsynths.hh | 18 +
bse/bsestorage.c | 2189 --
bse/bsestorage.cc | 2035 ++
bse/bsestorage.h | 218 -
bse/bsestorage.hh | 193 +
bse/bsesubiport.c | 336 -
bse/bsesubiport.cc | 323 +
bse/bsesubiport.h | 50 -
bse/bsesubiport.hh | 24 +
bse/bsesuboport.c | 337 -
bse/bsesuboport.cc | 324 +
bse/bsesuboport.h | 50 -
bse/bsesuboport.hh | 24 +
bse/bsesubsynth.c | 553 -
bse/bsesubsynth.cc | 538 +
bse/bsesubsynth.h | 60 -
bse/bsesubsynth.hh | 34 +
bse/bsesuper.c | 245 -
bse/bsesuper.cc | 225 +
bse/bsesuper.h | 71 -
bse/bsesuper.hh | 41 +
bse/bsetrack.c | 1131 --
bse/bsetrack.cc | 1148 ++
bse/bsetrack.h | 114 -
bse/bsetrack.hh | 88 +
bse/bsetrack.proc | 60 +-
bse/bsetype.c | 469 -
bse/bsetype.cc | 439 +
bse/bsetype.h | 207 -
bse/bsetype.hh | 201 +
bse/bseundostack.c | 425 -
bse/bseundostack.cc | 403 +
bse/bseundostack.h | 111 -
bse/bseundostack.hh | 96 +
bse/bseutils.c | 745 -
bse/bseutils.cc | 674 +
bse/bseutils.h | 141 -
bse/bseutils.hh | 124 +
bse/bsewave.c | 877 -
bse/bsewave.cc | 860 +
bse/bsewave.h | 99 -
bse/bsewave.hh | 71 +
bse/bsewave.proc | 77 +-
bse/bsewaveosc.c | 605 -
bse/bsewaveosc.cc | 587 +
bse/bsewaveosc.h | 81 -
bse/bsewaveosc.hh | 55 +
bse/bsewaveosc.proc | 48 +-
bse/bsewaverepo.c | 207 -
bse/bsewaverepo.cc | 191 +
bse/bsewaverepo.h | 53 -
bse/bsewaverepo.hh | 27 +
bse/bsewaverepo.proc | 52 +-
bse/gsl-fftconf.sh | 182 +-
bse/gsl-fftgen.pl | 136 +-
bse/gslcommon.c | 382 -
bse/gslcommon.cc | 412 +
bse/gslcommon.h | 103 -
bse/gslcommon.hh | 99 +
bse/gsldatacache.c | 640 -
bse/gsldatacache.cc | 568 +
bse/gsldatacache.h | 78 -
bse/gsldatacache.hh | 63 +
bse/gsldatahandle-mad.c | 811 -
bse/gsldatahandle-mad.cc | 778 +
bse/gsldatahandle-mad.h | 39 -
bse/gsldatahandle-mad.hh | 24 +
bse/gsldatahandle-vorbis.c | 574 -
bse/gsldatahandle-vorbis.cc | 559 +
bse/gsldatahandle-vorbis.h | 54 -
bse/gsldatahandle-vorbis.hh | 39 +
bse/gsldatahandle.c | 1812 --
bse/gsldatahandle.cc | 1745 ++
bse/gsldatahandle.h | 200 -
bse/gsldatahandle.hh | 182 +
bse/gsldatautils.c | 903 -
bse/gsldatautils.cc | 885 +
bse/gsldatautils.h | 1456 --
bse/gsldatautils.hh | 1441 ++
bse/gsldefs.h | 64 -
bse/gsldefs.hh | 50 +
bse/gslfft.h | 156 -
bse/gslfft.hh | 191 +
bse/gslfilehash.c | 510 -
bse/gslfilehash.cc | 449 +
bse/gslfilehash.h | 78 -
bse/gslfilehash.hh | 63 +
bse/gslfilter.c | 1420 --
bse/gslfilter.cc | 1401 ++
bse/gslfilter.h | 280 -
bse/gslfilter.hh | 265 +
bse/gslincluder.c |13420 ------------
bse/gslincluder.hh |13414 ++++++++++++
bse/gslmagic.c | 802 -
bse/gslmagic.cc | 775 +
bse/gslmagic.h | 77 -
bse/gslmagic.hh | 63 +
bse/gsloscillator-aux.c | 213 -
bse/gsloscillator-aux.cc | 198 +
bse/gsloscillator.c | 234 -
bse/gsloscillator.cc | 219 +
bse/gsloscillator.h | 84 -
bse/gsloscillator.hh | 69 +
bse/gslosctable.c | 654 -
bse/gslosctable.cc | 626 +
bse/gslosctable.h | 98 -
bse/gslosctable.hh | 84 +
bse/gslvorbis-cutter.c | 413 -
bse/gslvorbis-cutter.cc | 395 +
bse/gslvorbis-cutter.h | 54 -
bse/gslvorbis-cutter.hh | 39 +
bse/gslvorbis-enc.c | 520 -
bse/gslvorbis-enc.cc | 503 +
bse/gslvorbis-enc.h | 81 -
bse/gslvorbis-enc.hh | 66 +
bse/gslwavechunk.c | 815 -
bse/gslwavechunk.cc | 800 +
bse/gslwavechunk.h | 125 -
bse/gslwavechunk.hh | 110 +
bse/gslwaveosc-aux.c | 200 -
bse/gslwaveosc-aux.cc | 185 +
bse/gslwaveosc.c | 414 -
bse/gslwaveosc.cc | 387 +
bse/gslwaveosc.h | 97 -
bse/gslwaveosc.hh | 82 +
bse/icons/Makefile.am | 5 +-
bse/ladspa.h | 603 -
bse/ladspa.hh | 584 +
bse/ldscript.map | 1 +
bse/mkcalls.pl | 1 +
bse/mkcproc.pl | 6 +-
bse/mktypes.pl | 3 +-
bse/oldidl.idl | 54 +
bse/patch-bseserverapi.cc.diff | 23 +
bse/raw2bse | 1 +
bse/testobject.cc | 20 +
bse/testobject.hh | 19 +
bse/tests/Makefile.am | 17 +-
bse/tests/arrows.gp | 4 +-
bse/tests/blocktests.cc | 153 +-
bse/tests/filter-defs.gp | 4 +-
bse/tests/filtercatalog.cc | 1200 +-
bse/tests/filtertest.cc | 216 +-
bse/tests/firhandle.cc | 122 +-
bse/tests/loophandle.c | 226 -
bse/tests/loophandle.cc | 205 +
bse/tests/misctests.cc | 77 +-
bse/tests/resamplehandle.cc | 149 +-
bse/tests/subnormals-aux.cc | 21 +-
bse/tests/subnormals.cc | 111 +-
bse/tests/testcxx.cc | 26 +-
bse/tests/testfft.c | 461 -
bse/tests/testfft.cc | 577 +
bse/zintern/Makefile.am | 17 +-
bse/zintern/adsr-wave-1.bse | 4 +-
bse/zintern/adsr-wave-2.bse | 4 +-
bse/zintern/gus-patch.bse | 4 +-
bse/zintern/plain-wave-1.bse | 4 +-
bse/zintern/plain-wave-2.bse | 4 +-
configure.ac | 769 +
configure.in | 652 -
data/Makefile.am | 7 +-
data/beast-splash.png | Bin 39677 -> 39517 bytes
data/bse.pc.in | 2 +-
docs/.gitignore | 4 -
docs/ChangeLog.svn | 4 +-
docs/Makefile.am | 346 +-
docs/Makefile.doxygen | 129 +
docs/architecture.doxi | 162 -
docs/beast-index.doxi | 52 -
docs/beast.1.doxi | 121 -
docs/beastdefs.doxi | 111 -
docs/bse.5.doxi | 40 -
docs/bsescm.1.doxi | 122 -
docs/bsewavetool.1.doxi | 364 -
docs/coding-style.doxi | 255 -
docs/docextract.py | 111 +
docs/docframe.doxi | 40 -
docs/docu-template.doxi | 16 -
docs/doxygen.cfg | 82 +
docs/faq.doxi | 200 -
docs/images/Makefile.am | 25 +-
docs/images/beast-components.dia | Bin 3508 -> 0 bytes
docs/images/beast-components.png | Bin 34515 -> 0 bytes
docs/images/beast-components.svg | 2373 +++
docs/images/beast-progs.dia | Bin 2652 -> 0 bytes
docs/images/beast-progs.png | Bin 30307 -> 0 bytes
docs/images/beast-progs.svg | 665 +
docs/images/module-voices.dia | Bin 1456 -> 0 bytes
docs/images/module-voices.png | Bin 7449 -> 0 bytes
docs/images/module-voices.svg | 426 +
docs/imports/Beast-Quickstart | 260 -
docs/imports/Makefile.am | 84 +-
docs/imports/beast.1 | 146 +
docs/imports/beast.1.html | 195 +
docs/imports/beastdocs.css | 36 -
docs/imports/bse.5 | 41 +
docs/imports/bse.5.html | 81 +
docs/imports/bsescm.1 | 150 +
docs/imports/bsescm.1.html | 195 +
docs/imports/bsewavetool.1 | 501 +
docs/imports/bsewavetool.1.html | 568 +
docs/imports/sfidl.1 | 102 +
docs/imports/sfidl.1.html | 153 +
docs/imports/style-append.css | 10 -
docs/imports/tagfile-rapicorn.xml |21382 ++++++++++++++++++++
docs/imports/tagfile-susv4.xml | 2981 +++
docs/main.dox | 26 +
docs/plugin-devel.doxi | 439 -
docs/sfidl-manual.doxi | 476 -
docs/sfidl.1.doxi | 86 -
docs/site-navigation.xml | 73 -
doxer/Code2Doxi.py | 733 -
doxer/Config.py | 98 -
doxer/Data.py | 303 -
doxer/DoxiParser.py | 1426 --
doxer/HtmlGenerator.py | 1032 -
doxer/Makefile.am | 11 -
doxer/ManGenerator.py | 443 -
doxer/ScadParser.py | 148 -
doxer/Utils.py | 53 -
doxer/changelog2doxi.py | 127 -
doxer/docu-main.doxi | 161 -
doxer/doxer-standard.doxi | 109 -
doxer/doxer-style.css | 75 -
doxer/doxer.py | 536 -
doxer/linkdict.py | 393 -
doxer/linkdict_gnome.py | 7655 -------
doxer/qcomment.py | 155 -
doxer/qdoxygen.py | 325 -
doxer/qxmlparser.py | 498 -
drivers/Makefile.am | 24 +
drivers/bse-alsa/AUTHORS | 1 -
drivers/bse-alsa/COPYING | 504 -
drivers/bse-alsa/ChangeLog | 172 -
drivers/bse-alsa/Makefile.am | 37 -
drivers/bse-alsa/NEWS | 26 -
drivers/bse-alsa/README | 36 -
drivers/bse-alsa/acbeast.m4 | 340 -
drivers/bse-alsa/autogen.sh | 175 -
drivers/bse-alsa/bsemididevice-alsa.c | 323 -
drivers/bse-alsa/bsemididevice-alsa.h | 47 -
drivers/bse-alsa/bsepcmdevice-alsa.c | 567 -
drivers/bse-alsa/bsepcmdevice-alsa.h | 47 -
drivers/bse-alsa/configure.in | 222 -
drivers/bse-portaudio/Makefile.am | 17 +-
drivers/bse-portaudio/README | 6 +-
drivers/bse-portaudio/acbeast.m4 | 3 +-
drivers/bse-portaudio/bsepcmdevice-portaudio.cc | 81 +-
drivers/bse-portaudio/bsepcmdevice-portaudio.hh | 41 +-
drivers/bse-portaudio/configure.in | 1 +
drivers/bsemididevice-alsa.cc | 347 +
drivers/bsemididevice-alsa.hh | 22 +
drivers/bsepcmdevice-alsa.cc | 601 +
drivers/bsepcmdevice-alsa.hh | 22 +
launchers/Makefile.am | 13 +-
launchers/beaststart.c | 18 +-
launchers/bseshstart.c | 18 +-
launchers/suidmain.c | 18 +-
launchers/suidmain.h | 18 +-
ld-symbolic.m4 | 45 +
library/Makefile.am | 5 +-
library/demo/Makefile.am | 5 +-
library/demo/partymonster.bse | 26 +-
library/demo/stereo-through.bse | 4 +-
library/demo/x2-midi-test.bse | 12 +-
library/effects/Makefile.am | 5 +-
library/effects/atan-canyon.bse | 6 +-
library/effects/bqs-compressor.bse | 6 +-
library/effects/bqs-reverb.bse | 6 +-
library/effects/bqs-saturation-and-reverb.bse | 6 +-
library/instruments/Makefile.am | 5 +-
library/instruments/bqs-bass-drum-e8012.bse | 6 +-
library/instruments/bqs-fretless-bass.bse | 6 +-
library/instruments/bqs-merp-pad.bse | 6 +-
library/instruments/bqs-moog-saw-bass.bse | 6 +-
library/instruments/bqs-organ.bse | 10 +-
library/instruments/bqs-queek-synth.bse | 6 +-
library/instruments/bqs-slow-hum.bse | 4 +-
library/instruments/bqs-syndrum.bse | 6 +-
library/instruments/fsm-fresh-water-bass.bse | 6 +-
library/instruments/fsm-growl-bass.bse | 6 +-
library/instruments/fsm-synth-string-sweep.bse | 6 +-
library/instruments/illus-vtremolo.bse | 6 +-
library/instruments/stw-iron-string.bse | 6 +-
library/keys/Makefile.am | 5 +-
library/samples/Makefile.am | 5 +-
library/scripts/Makefile.am | 5 +-
library/scripts/mixer-splitup-by-track.scm | 18 +-
library/scripts/modules2grid.scm | 17 +-
library/scripts/part-harmonic-transposer.scm | 18 +-
library/scripts/progressor-example.scm | 17 +-
library/scripts/record-midi.scm | 17 +-
library/scripts/song-parts-operations.scm | 21 +-
library/skins/Makefile.am | 5 +-
library/skins/images/Makefile.am | 5 +-
mkrelease.sh | 295 +-
plugins/Makefile.am | 105 +-
plugins/Makefile.plugins | 233 +-
plugins/artscompressor.cc | 26 +-
plugins/artscompressor.idl | 45 +-
plugins/bseadder.c | 272 -
plugins/bseadder.cc | 247 +
plugins/bseadder.h | 75 -
plugins/bseadder.hh | 46 +
plugins/bseamplifier.cc | 21 +-
plugins/bseamplifier.idl | 49 +-
plugins/bseatandistort.c | 244 -
plugins/bseatandistort.cc | 225 +
plugins/bseatandistort.h | 71 -
plugins/bseatandistort.hh | 45 +
plugins/bsebalance.cc | 17 +-
plugins/bsebalance.idl | 39 +-
plugins/bseblockutils.cc | 18 +-
plugins/bsecontribsampleandhold.cc | 29 +-
plugins/bsecontribsampleandhold.idl | 31 +-
plugins/bsefirfilter.c | 89 +-
plugins/bsefirfilter.h | 94 -
plugins/bsefirfilter.hh | 63 +
plugins/bseiirfilter.c | 446 -
plugins/bseiirfilter.cc | 399 +
plugins/bseiirfilter.h | 101 -
plugins/bseiirfilter.hh | 49 +
plugins/bseloopback.c | 191 -
plugins/bseloopback.h | 76 -
plugins/bsemixer.c | 375 -
plugins/bsemixer.cc | 359 +
plugins/bsemixer.h | 71 -
plugins/bsemixer.hh | 36 +
plugins/bsemult.c | 139 -
plugins/bsemult.cc | 118 +
plugins/bsemult.h | 76 -
plugins/bsemult.hh | 47 +
plugins/bsenoise.cc | 22 +-
plugins/bsenoise.idl | 26 +-
plugins/bsequantizer.cc | 25 +-
plugins/bsequantizer.idl | 35 +-
plugins/bsesequencer.c | 387 -
plugins/bsesequencer.cc | 369 +
plugins/bsesequencer.h | 66 -
plugins/bsesequencer.hh | 44 +
plugins/bsesimpleadsr-aux.c | 112 -
plugins/bsesimpleadsr-aux.cc | 97 +
plugins/bsesimpleadsr.c | 443 -
plugins/bsesimpleadsr.cc | 424 +
plugins/bsesimpleadsr.h | 76 -
plugins/bsesimpleadsr.hh | 50 +
plugins/bsesummation.cc | 17 +-
plugins/bsesummation.idl | 33 +-
plugins/davbassfilter.cc | 24 +-
plugins/davbassfilter.idl | 31 +-
plugins/davcanyondelay.c | 376 -
plugins/davcanyondelay.cc | 357 +
plugins/davcanyondelay.h | 87 -
plugins/davcanyondelay.hh | 62 +
plugins/davchorus.cc | 31 +-
plugins/davchorus.idl | 27 +-
plugins/davguitar.c | 127 +-
plugins/davguitar.h | 83 -
plugins/davguitar.hh | 48 +
plugins/davorgan.c | 533 -
plugins/davorgan.cc | 265 +
plugins/davorgan.h | 91 -
plugins/davorgan.idl | 39 +
plugins/davsyndrum.c | 380 -
plugins/davsyndrum.cc | 362 +
plugins/davsyndrum.h | 76 -
plugins/davsyndrum.hh | 57 +
plugins/davxtalstrings.c | 558 -
plugins/davxtalstrings.cc | 536 +
plugins/davxtalstrings.h | 83 -
plugins/davxtalstrings.hh | 54 +
plugins/evaluator/Makefile.am | 12 +-
plugins/evaluator/bseevaluator.cc | 31 +-
plugins/evaluator/bseevaluator.idl | 23 +-
plugins/evaluator/compiler.cc | 16 +-
plugins/evaluator/compiler.hh | 19 +-
plugins/evaluator/cpu.cc | 17 +-
plugins/evaluator/cpu.hh | 17 +-
plugins/evaluator/evaluateexpr.cc | 19 +-
plugins/evaluator/instruction.cc | 17 +-
plugins/evaluator/instruction.hh | 19 +-
plugins/evaluator/symbols.hh | 17 +-
plugins/evaluator/token.hh | 17 +-
plugins/fldbsepattern.c | 283 -
plugins/freeverb/Makefile.am | 19 +-
plugins/freeverb/allpass.hpp | 2 +-
plugins/freeverb/bsefreeverb.c | 296 -
plugins/freeverb/bsefreeverb.cc | 279 +
plugins/freeverb/bsefreeverb.h | 69 -
plugins/freeverb/bsefreeverb.hh | 40 +
plugins/freeverb/bsefreeverbcpp.cpp | 19 +-
plugins/freeverb/bsefreeverbcpp.h | 70 -
plugins/freeverb/bsefreeverbcpp.hh | 55 +
plugins/freeverb/comb.hpp | 2 +-
plugins/freeverb/denormals.h | 18 -
plugins/freeverb/denormals.hh | 18 +
plugins/freeverb/readme.txt | 2 +-
plugins/freeverb/revmodel.hpp | 2 +-
plugins/freeverb/tuning.h | 60 -
plugins/freeverb/tuning.hh | 60 +
plugins/hello-space.c | 68 -
plugins/icons/Makefile.am | 5 +-
plugins/standardguspatchenvelope.cc | 23 +-
plugins/standardguspatchenvelope.idl | 47 +-
plugins/standardsaturator.cc | 21 +-
plugins/standardsaturator.idl | 60 +-
po/Makefile.am | 9 +-
po/POTIGNORE | 1 +
po/POTSCAN | 213 +-
po/POTSKIP | 4 +-
po/ar.po | 3788 ++--
po/az.po | 3704 ++--
po/bg.po | 3767 ++--
po/ca.po | 3868 ++--
po/cs.po | 3841 ++--
po/da.po | 3803 ++--
po/de.po | 3835 ++--
po/el.po | 3736 ++--
po/en_CA.po | 3824 ++--
po/en_GB.po | 3841 ++--
po/eo.po | 3706 ++--
po/es.po | 3854 ++--
po/eu.po | 3752 ++--
po/fi.po | 3735 ++--
po/fr.po | 3871 ++--
po/hr.po | 3730 ++--
po/it.po | 3842 ++--
po/ja.po | 3805 ++--
po/mn.po | 3735 ++--
po/nb.po | 3710 ++--
po/ne.po | 3825 ++--
po/nl.po | 3866 ++--
po/oc.po | 3708 ++--
po/pa.po | 3707 ++--
po/pt.po | 3808 ++--
po/pt_BR.po | 3806 ++--
po/ru.po | 3773 ++--
po/rw.po | 3811 ++--
po/sl.po | 3840 ++--
po/sq.po | 3820 ++--
po/sr.po | 3741 ++--
po/sr Latn po | 3741 ++--
po/sv.po | 3765 ++--
po/te.po | 3711 ++--
po/uk.po | 3715 ++--
po/zh_CN.po | 3731 ++--
r+d-files/bse-ellf.c | 236 +-
sfi/Makefile.am | 72 +-
sfi/gbsearcharray.h | 313 -
sfi/gbsearcharray.hh | 294 +
sfi/glib-extra.c | 1101 -
sfi/glib-extra.cc | 1051 +
sfi/glib-extra.h | 326 -
sfi/glib-extra.hh | 330 +
sfi/sfi.h | 43 -
sfi/sfi.hh | 34 +
sfi/sficomport.c | 745 -
sfi/sficomport.cc | 714 +
sfi/sficomport.h | 125 -
sfi/sficomport.hh | 108 +
sfi/sficomwire.c | 1051 -
sfi/sficomwire.cc | 1027 +
sfi/sficomwire.h | 182 -
sfi/sficomwire.hh | 167 +
sfi/sficxx.cc | 19 +-
sfi/sficxx.hh | 29 +-
sfi/sfidl-cbase.cc | 40 +-
sfi/sfidl-cbase.hh | 21 +-
sfi/sfidl-clientc.cc | 19 +-
sfi/sfidl-clientc.hh | 23 +-
sfi/sfidl-clientcxx.cc | 25 +-
sfi/sfidl-clientcxx.hh | 17 +-
sfi/sfidl-corec.cc | 119 +-
sfi/sfidl-corecxx.cc | 97 +-
sfi/sfidl-cxxbase.cc | 24 +-
sfi/sfidl-cxxbase.hh | 17 +-
sfi/sfidl-factory.cc | 19 +-
sfi/sfidl-factory.hh | 17 +-
sfi/sfidl-generator.cc | 25 +-
sfi/sfidl-generator.hh | 27 +-
sfi/sfidl-hostc.cc | 19 +-
sfi/sfidl-hostc.hh | 19 +-
sfi/sfidl-namespace.cc | 58 +-
sfi/sfidl-namespace.hh | 29 +-
sfi/sfidl-options.cc | 19 +-
sfi/sfidl-options.hh | 17 +-
sfi/sfidl-parser.cc | 337 +-
sfi/sfidl-parser.hh | 57 +-
sfi/sfidl-typelist.cc | 19 +-
sfi/sfidl-utils.cc | 65 +
sfi/sfidl-utils.hh | 32 +-
sfi/sfidl.cc | 32 +-
sfi/sfifilecrawler.c | 631 -
sfi/sfifilecrawler.cc | 614 +
sfi/sfifilecrawler.h | 77 -
sfi/sfifilecrawler.hh | 62 +
sfi/sfiglue.c | 878 -
sfi/sfiglue.cc | 848 +
sfi/sfiglue.h | 233 -
sfi/sfiglue.hh | 224 +
sfi/sfigluecodec.c | 1124 -
sfi/sfigluecodec.cc | 1063 +
sfi/sfigluecodec.h | 113 -
sfi/sfigluecodec.hh | 91 +
sfi/sfiglueproxy.c | 1017 -
sfi/sfiglueproxy.cc | 988 +
sfi/sfiglueproxy.h | 114 -
sfi/sfiglueproxy.hh | 99 +
sfi/sfimemory.c | 215 -
sfi/sfimemory.cc | 169 +
sfi/sfimemory.h | 59 -
sfi/sfimemory.hh | 38 +
sfi/sfinote.c | 186 -
sfi/sfinote.cc | 171 +
sfi/sfinote.h | 101 -
sfi/sfinote.hh | 86 +
sfi/sfiparams.c | 1774 --
sfi/sfiparams.cc | 1729 ++
sfi/sfiparams.h | 334 -
sfi/sfiparams.hh | 319 +
sfi/sfiprimitives.c | 1311 --
sfi/sfiprimitives.cc | 1325 ++
sfi/sfiprimitives.h | 251 -
sfi/sfiprimitives.hh | 236 +
sfi/sfiring.c | 1173 --
sfi/sfiring.cc | 1158 ++
sfi/sfiring.h | 179 -
sfi/sfiring.hh | 164 +
sfi/sfiserial.c | 967 -
sfi/sfiserial.cc | 989 +
sfi/sfiserial.h | 56 -
sfi/sfiserial.hh | 41 +
sfi/sfistore.c | 869 -
sfi/sfistore.cc | 801 +
sfi/sfistore.h | 160 -
sfi/sfistore.hh | 132 +
sfi/sfitests.h | 61 -
sfi/sfitests.hh | 87 +
sfi/sfitime.c | 669 -
sfi/sfitime.cc | 652 +
sfi/sfitime.h | 50 -
sfi/sfitime.hh | 35 +
sfi/sfitypes.c | 255 -
sfi/sfitypes.cc | 221 +
sfi/sfitypes.h | 95 -
sfi/sfitypes.hh | 77 +
sfi/sfiustore.c | 313 -
sfi/sfiustore.cc | 298 +
sfi/sfiustore.h | 88 -
sfi/sfiustore.hh | 73 +
sfi/sfivalues.c | 833 -
sfi/sfivalues.cc | 800 +
sfi/sfivalues.h | 194 -
sfi/sfivalues.hh | 179 +
sfi/sfivmarshal.c | 1864 --
sfi/sfivmarshal.cc | 2092 ++
sfi/sfivmarshal.h | 47 -
sfi/sfivmarshal.hh | 32 +
sfi/sfiwrapper.cc | 349 +-
sfi/sfiwrapper.h | 291 -
sfi/sfiwrapper.hh | 70 +
sfi/tests/Makefile.am | 23 +-
sfi/tests/misctests.c | 964 -
sfi/tests/misctests.cc | 761 +
sfi/tests/ring.c | 230 -
sfi/tests/ring.cc | 209 +
sfi/tests/testcxx.cc | 29 +-
sfi/tests/testidl.idl | 30 +-
sfi/tests/testsfidl.cc | 57 +-
sfi/toyprof-mem.c | 352 -
sfi/toyprof-mem.h | 41 -
sfi/toyprof.README | 68 -
sfi/toyprof.c | 608 -
sfi/toyprof.h | 61 -
sfi/toyprof.pl | 247 -
shell/Makefile.am | 25 +-
shell/bse-scm-glue.boot | 17 +-
shell/bsescm.c | 375 -
shell/bsescm.cc | 346 +
shell/bsescminterp.c | 1203 --
shell/bsescminterp.cc | 1189 ++
shell/bsescminterp.h | 78 -
shell/bsescminterp.hh | 63 +
shell/cxxdummy.cc | 1 -
tarGSL.sh | 19 -
tests/.gitignore | 1 +
tests/Makefile.am | 28 +-
tests/audio/Makefile.am | 4 +-
tests/audio/adsr-wave-1-test.bse | 2 +-
tests/audio/adsr-wave-2-test.bse | 2 +-
tests/audio/adsrtest.bse | 10 +-
tests/audio/artscompressor.bse | 18 +-
tests/audio/balance.bse | 2 +-
tests/audio/bse2wav.scm | 17 +-
tests/audio/bseadder.bse | 17 +-
tests/audio/freak-noise.bse | 6 +-
tests/audio/minisong.bse | 3 +-
tests/audio/organsong.bse | 38 +-
tests/audio/osc-test.bse | 8 +-
tests/audio/osctranspose1.bse | 10 +-
tests/audio/osctranspose2.bse | 10 +-
tests/audio/plain-wave-1-test.bse | 2 +-
tests/audio/plain-wave-2-test.bse | 2 +-
tests/audio/simple-loop.bse | 22 +-
tests/audio/sum-diff-test.bse | 10 +-
tests/audio/syndrum.bse | 16 +-
tests/audio/velocity.bse | 28 +-
tests/audio/xtalstringssong.bse | 20 +-
tests/bse/Makefile.am | 16 +-
tests/bse/cxxbinding.cc | 27 +-
tests/bse/filtertest.cc | 63 +-
tests/bse/testplugin.cc | 17 +-
tests/bse/testplugin.idl | 36 +-
tests/filecheck/Makefile.am | 13 +-
tests/filecheck/checkproject.scm | 17 +-
tests/latency/Makefile.am | 15 +-
tests/latency/bselatencytest.cc | 17 +-
tests/latency/bselatencytest.idl | 40 +-
tests/latency/bseplay.scm | 17 +-
tests/latency/midi-latency.bse | 18 +-
tests/perftest.cc | 39 +-
tests/scripts/Makefile.am | 2 -
tests/testresampler.cc | 35 +-
tests/testresamplerq.cc | 247 +
tests/testwavechunk.c | 438 -
tests/testwavechunk.cc | 371 +
tools/Makefile.am | 22 +-
tools/bsefcompare.cc | 35 +-
tools/bsefextract.cc | 96 +-
tools/bseloopfuncs.c | 934 -
tools/bseloopfuncs.cc | 919 +
tools/bseloopfuncs.h | 130 -
tools/bseloopfuncs.hh | 115 +
tools/bsewavetool.cc | 207 +-
tools/bsewavetool.hh | 24 +-
tools/bwtwave.cc | 41 +-
tools/bwtwave.hh | 23 +-
tools/cutvorbis.c | 167 -
tools/cutvorbis.cc | 146 +
tools/magictest.c | 124 -
tools/magictest.cc | 102 +
tools/mathtool.c | 739 -
tools/mathtool.cc | 716 +
tools/scripts/noteplaytest.scm | 18 +-
tools/scripts/retrokit.sh | 19 +-
tools/scripts/waveloadtest.scm | 18 +-
tools/sfiutils.c | 623 -
tools/sfiutils.cc | 608 +
tools/sfiutils.h | 102 -
tools/sfiutils.hh | 87 +
topconfig.h | 2 +-
web/Makefile.am | 295 -
web/about.doxi | 43 -
web/contact.doxi | 54 -
web/development.doxi | 65 -
web/documentation.doxi | 47 -
web/download.doxi | 116 -
web/doxer-docu.doxi | 6 -
web/file-browser.php | 164 -
web/file-upload.php | 177 -
web/gallery.php | 180 -
web/historic.doxi | 31 -
web/htaccess.in | 144 -
web/logogallery.doxi | 20 -
web/logogallerydir/anon-beast-iktome-long.png | Bin 181600 -> 0 bytes
web/logogallerydir/anon-beast-iktome.png | Bin 187905 -> 0 bytes
web/logogallerydir/cyria-bse2.png | Bin 80266 -> 0 bytes
web/logogallerydir/cyria-bse3.png | Bin 130248 -> 0 bytes
web/logogallerydir/cyria-bse4.png | Bin 105787 -> 0 bytes
web/logogallerydir/dlundin-beast2.png | Bin 44664 -> 0 bytes
web/logogallerydir/dlundin-beast2_noshades.png | Bin 42978 -> 0 bytes
web/logogallerydir/dlundin-beast_large.png | Bin 81696 -> 0 bytes
web/logogallerydir/dlundin-beast_logo.png | Bin 92014 -> 0 bytes
web/logogallerydir/dlundin-logo.png | Bin 50934 -> 0 bytes
web/logogallerydir/drc-beast.png | Bin 22009 -> 0 bytes
web/logogallerydir/jimmac-01.png | Bin 9768 -> 0 bytes
web/logogallerydir/jimmac-02.png | Bin 64894 -> 0 bytes
web/logogallerydir/jimmac-03.png | Bin 52702 -> 0 bytes
web/logogallerydir/jimmac-icon.png | Bin 59556 -> 0 bytes
web/logogallerydir/jimmac-logo.png | Bin 9194 -> 0 bytes
web/logogallerydir/jimmac-splash.png | Bin 39677 -> 0 bytes
web/logogallerydir/mrogers-beast-head.jpg | Bin 15281 -> 0 bytes
web/logogallerydir/mrogers-beast-large.jpg | Bin 23065 -> 0 bytes
web/logogallerydir/mythor-beast.png | Bin 50450 -> 0 bytes
web/logogallerydir/swamp-bse-skull.jpg | Bin 220740 -> 0 bytes
web/logogallerydir/sylane-beast-compo.png | Bin 284806 -> 0 bytes
web/logogallerydir/tk_beast_01.png | Bin 5620 -> 0 bytes
web/logogallerydir/tk_beast_02.png | Bin 4758 -> 0 bytes
web/news.doxi | 88 -
web/oldnews.doxi | 1048 -
web/overview2003de.doxi | 275 -
web/related-links.doxi | 58 -
web/resources.doxi | 22 -
web/robots.txt | 10 -
web/scanimages.sh | 44 -
web/screenshotdir/stwZ01-modular_synth_bass.DSC | 4 -
web/screenshotdir/stwZ01-modular_synth_bass.png | Bin 130393 -> 0 bytes
web/screenshotdir/stwZ02-track_view.DSC | 2 -
web/screenshotdir/stwZ02-track_view.png | Bin 83682 -> 0 bytes
web/screenshotdir/stwZ03-piano_roll.DSC | 4 -
web/screenshotdir/stwZ03-piano_roll.png | Bin 71509 -> 0 bytes
web/screenshotdir/stwZ04-fft_scopes.DSC | 7 -
web/screenshotdir/stwZ04-fft_scopes.png | Bin 668200 -> 0 bytes
web/screenshotdir/stwZ05-wave_editor.DSC | 3 -
web/screenshotdir/stwZ05-wave_editor.png | Bin 51488 -> 0 bytes
web/screenshotdir/stwZ06-skin_support.DSC | 3 -
web/screenshotdir/stwZ06-skin_support.png | Bin 415809 -> 0 bytes
web/screenshotdir/stwZ07-audio_mixer.DSC | 4 -
web/screenshotdir/stwZ07-audio_mixer.png | Bin 93290 -> 0 bytes
web/screenshotdir/stwZ08-pattern_editor.DSC | 5 -
web/screenshotdir/stwZ08-pattern_editor.png | Bin 80638 -> 0 bytes
.../stwZ09-post_processing_network.DSC | 4 -
.../stwZ09-post_processing_network.png | Bin 143815 -> 0 bytes
web/screenshotdir/z2003-01-simple-loop.DSC | 1 -
web/screenshotdir/z2003-01-simple-loop.png | Bin 115406 -> 0 bytes
web/screenshotdir/z2003-02-wave-play.DSC | 1 -
web/screenshotdir/z2003-02-wave-play.png | Bin 12450 -> 0 bytes
web/screenshotdir/z2003-03-synthnet.DSC | 1 -
web/screenshotdir/z2003-03-synthnet.png | Bin 97465 -> 0 bytes
web/screenshotdir/z2003-04-piano-roll.DSC | 1 -
web/screenshotdir/z2003-04-piano-roll.png | Bin 40815 -> 0 bytes
web/screenshotdir/z2003-05-red-flash.DSC | 1 -
web/screenshotdir/z2003-05-red-flash.png | Bin 507021 -> 0 bytes
web/screenshotdir/z2003-06-track-roll.DSC | 1 -
web/screenshotdir/z2003-06-track-roll.png | Bin 63701 -> 0 bytes
web/screenshotdir/z2003-07-patterned.DSC | 1 -
web/screenshotdir/z2003-07-patterned.png | Bin 10550 -> 0 bytes
web/screenshotdir/z2003-08-synth-fm.DSC | 1 -
web/screenshotdir/z2003-08-synth-fm.png | Bin 111058 -> 0 bytes
web/screenshotdir/z2003-95-preferences.DSC | 1 -
web/screenshotdir/z2003-95-preferences.png | Bin 52088 -> 0 bytes
web/screenshotdir/z2003-96-trackedit.DSC | 1 -
web/screenshotdir/z2003-96-trackedit.png | Bin 53722 -> 0 bytes
web/screenshots.doxi | 13 -
web/search.doxi | 43 -
web/sound-browser.doxi | 22 -
web/sound-upload.doxi | 18 -
web/style/beast-bg-h5.png | Bin 87 -> 0 bytes
web/style/beast-bg.png | Bin 159 -> 0 bytes
web/style/beast-dot.png | Bin 121 -> 0 bytes
web/style/beast-left.png | Bin 20630 -> 0 bytes
web/style/beast-right.png | Bin 7113 -> 0 bytes
web/style/beast-small.png | Bin 12508 -> 0 bytes
web/style/beast-style.css | 185 -
web/style/home-arrow-24x64.png | Bin 158 -> 0 bytes
web/style/plain.css | 6 -
web/style/square.png | Bin 137 -> 0 bytes
web/style/title-arrow-24x64.png | Bin 191 -> 0 bytes
web/style/triangle-down-blue.png | Bin 176 -> 0 bytes
web/style/triangle-right-blue.png | Bin 155 -> 0 bytes
web/synthesis-links.doxi | 188 -
web/web-images/LT-PartView512.png | Bin 40596 -> 0 bytes
web/web-images/LT-SynthView512.png | Bin 84682 -> 0 bytes
web/web-images/LT-WaveView512.png | Bin 55057 -> 0 bytes
web/web-images/back.png | Bin 190 -> 0 bytes
web/web-images/compressed.png | Bin 959 -> 0 bytes
web/web-images/favicon.ico | Bin 1150 -> 0 bytes
web/web-images/folder-open.png | Bin 210 -> 0 bytes
web/web-images/folder.png | Bin 177 -> 0 bytes
web/web-images/sound2.png | Bin 199 -> 0 bytes
web/web-images/text.png | Bin 175 -> 0 bytes
web/webframe.doxi | 42 -
web/webmenu.doxi | 133 -
web/wiki.doxi | 41 -
1618 files changed, 308039 insertions(+), 325894 deletions(-)
---
diff --cc beast-gtk/Makefile.am
index cdff047,60dcdbe..d57072f
--- a/beast-gtk/Makefile.am
+++ b/beast-gtk/Makefile.am
@@@ -22,46 -19,46 +19,46 @@@ LIBS += # -lefence # -p
#
# BEAST header files that don't get installed
beast_headers = $(strip \
- bsttrackrollctrl.h bstxframe.h bstscrollgraph.h \
- bstdbmeter.h bstbusmixer.h bstbuseditor.h bstitemseqdialog.h \
- bstcanvassource.h bstapp.h bstasciipixbuf.h bstcanvaslink.h \
- bstpatterncolumns.h bstxkb.h bstpatternview.h bstpatternctrl.h \
- bstkeybindings.h bstprofiler.h bstgrowbar.h bstbusview.h \
- bstpianorollctrl.h bstpartview.h bstpianoroll.h bstplayback.h \
- bsttrackroll.h bstcluehunter.h bstprojectctrl.h bstcxxutils.h \
- bstauxdialogs.h bstsegment.h bsteventrollctrl.h bsteventroll.h \
- bstsnifferscope.h bstwaveview.h bstfiledialog.h bstgconfig.h \
- bstlogadjustment.h bstitemview.h bstservermonitor.h bstknob.h \
- bstparamview.h bstmenus.h bstparam.h bstpartdialog.h \
- bstprocbrowser.h bstqsampler.h bstpreferences.h bstprocedure.h \
- bstrackeditor.h bstrackitem.h bstracktable.h bstsequence.h \
- bstsnetrouter.h bstsplash.h bsttrackview.h bstsupershell.h \
- bstusermessage.h bstdial.h bsttracksynthdialog.h bstwaveeditor.h \
- bstzoomedwindow.h bstskinconfig.h bstmsgabsorb.h bstsampleeditor.h \
- bstrackview.h bsttreestores.h bstbseutils.h \
- bstutils.h bstdefs.h bstsoundfontview.h bstsoundfontpresetview.h \
+ bsttrackrollctrl.hh bstxframe.hh bstscrollgraph.hh \
+ bstdbmeter.hh bstbusmixer.hh bstbuseditor.hh bstitemseqdialog.hh \
+ bstcanvassource.hh bstapp.hh bstasciipixbuf.hh bstcanvaslink.hh \
+ bstpatterncolumns.hh bstxkb.hh bstpatternview.hh bstpatternctrl.hh \
+ bstkeybindings.hh bstprofiler.hh bstgrowbar.hh bstbusview.hh \
+ bstpianorollctrl.hh bstpartview.hh bstpianoroll.hh bstplayback.hh \
+ bsttrackroll.hh bstcluehunter.hh bstprojectctrl.hh \
+ bstauxdialogs.hh bstsegment.hh bsteventrollctrl.hh bsteventroll.hh \
+ bstsnifferscope.hh bstwaveview.hh bstfiledialog.hh bstgconfig.hh \
+ bstlogadjustment.hh bstitemview.hh bstservermonitor.hh bstknob.hh \
+ bstparamview.hh bstmenus.hh bstparam.hh bstpartdialog.hh \
+ bstprocbrowser.hh bstqsampler.hh bstpreferences.hh bstprocedure.hh \
+ bstrackeditor.hh bstrackitem.hh bstracktable.hh bstsequence.hh \
+ 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 \
++ bstdefs.hh bstsoundfontview.h bstsoundfontpresetview.h \
)
EXTRA_DIST += $(beast_headers)
# BEAST sources to build the program from
beast_sources = $(strip \
- bsttrackrollctrl.c bstxframe.c bstscrollgraph.c \
- bstdbmeter.c bstbusmixer.c bstbuseditor.c bstitemseqdialog.c \
- bstcanvassource.c bstapp.c bstasciipixbuf.c bstcanvaslink.c \
- bstpatterncolumns.c bstxkb.c bstpatternview.c bstpatternctrl.c \
- bstkeybindings.c bstprofiler.c bstgrowbar.c bstbusview.c \
- bstpianorollctrl.c bstpartview.c bstpianoroll.c bstplayback.c \
- bsttrackroll.c bstcluehunter.c bstprojectctrl.c bstcxxutils.cc \
- bstauxdialogs.c bstsegment.c bsteventrollctrl.c bsteventroll.c \
- bstsnifferscope.c bstwaveview.c bstfiledialog.c bstgconfig.c \
- bstlogadjustment.c bstitemview.c bstservermonitor.c bstknob.c \
- bstparamview.c bstmenus.c bstparam.c bstpartdialog.c \
- bstprocbrowser.c bstqsampler.c bstpreferences.c bstprocedure.c \
- bstrackeditor.c bstrackitem.c bstracktable.c bstsequence.c \
- bstsnetrouter.c bstsplash.c bsttrackview.c bstsupershell.c \
- bstusermessage.c bstdial.c bsttracksynthdialog.c bstwaveeditor.c \
- bstzoomedwindow.c bstskinconfig.c bstmsgabsorb.c bstsampleeditor.c \
- bstrackview.c bsttreestores.c bstbseutils.c bstutils.c \
+ bsttrackrollctrl.cc bstxframe.cc bstscrollgraph.cc \
+ bstdbmeter.cc bstbusmixer.cc bstbuseditor.cc bstitemseqdialog.cc \
+ bstcanvassource.cc bstapp.cc bstasciipixbuf.cc bstcanvaslink.cc \
+ bstpatterncolumns.cc bstxkb.cc bstpatternview.cc bstpatternctrl.cc \
+ bstkeybindings.cc bstprofiler.cc bstgrowbar.cc bstbusview.cc \
+ bstpianorollctrl.cc bstpartview.cc bstpianoroll.cc bstplayback.cc \
+ bsttrackroll.cc bstcluehunter.cc bstprojectctrl.cc \
+ bstauxdialogs.cc bstsegment.cc bsteventrollctrl.cc bsteventroll.cc \
+ bstsnifferscope.cc bstwaveview.cc bstfiledialog.cc bstgconfig.cc \
+ bstlogadjustment.cc bstitemview.cc bstservermonitor.cc bstknob.cc \
+ bstparamview.cc bstmenus.cc bstparam.cc bstpartdialog.cc \
+ bstprocbrowser.cc bstqsampler.cc bstpreferences.cc bstprocedure.cc \
+ bstrackeditor.cc bstrackitem.cc bstracktable.cc bstsequence.cc \
+ 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 \
- $(PROFILE_SOURCE) \
+ bstsoundfontview.c bstsoundfontpresetview.c $(PROFILE_SOURCE) \
)
# BEAST sources that get included (don't have own .lo rules)
beast_extra_files = $(strip \
diff --cc beast-gtk/bstfiledialog.cc
index 0000000,231a4a9..0e0b6ee
mode 000000,100644..100644
--- a/beast-gtk/bstfiledialog.cc
+++ b/beast-gtk/bstfiledialog.cc
@@@ -1,0 -1,922 +1,969 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bstfiledialog.hh"
+ #include "bstmenus.hh"
+ #include "bsttreestores.hh"
+ #include <unistd.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <errno.h>
+
+
+ /* --- prototypes --- */
+ static void bst_file_dialog_finalize (GObject *object);
+ static void bst_file_dialog_activate (BstFileDialog *self);
+
+
+ /* --- functions --- */
+ G_DEFINE_TYPE (BstFileDialog, bst_file_dialog, GXK_TYPE_DIALOG);
+
+ static void
+ bst_file_dialog_class_init (BstFileDialogClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = bst_file_dialog_finalize;
+ }
+
+ static void
+ tree_viewable_changed (BstFileDialog *self)
+ {
+ gboolean viewable = gxk_widget_viewable (GTK_WIDGET (self->tview));
+ gboolean tvisible = GTK_WIDGET_VISIBLE (gtk_widget_get_toplevel (GTK_WIDGET (self->tview)));
+
+ if (viewable && !self->using_file_store)
+ {
+ self->using_file_store = TRUE;
+ bst_file_store_update_list (self->file_store, self->search_path, self->search_filter);
+ }
+ else if (!tvisible && self->using_file_store)
+ {
+ self->using_file_store = FALSE;
+ bst_file_store_forget_list (self->file_store);
+ }
+ }
+
+ static void
+ bst_file_dialog_init (BstFileDialog *self)
+ {
+ GtkTreeSelection *tsel;
+ GtkTreeModel *smodel;
+ GtkWidget *bbox, *vbox;
+ GtkWidget *main_box = GXK_DIALOG (self)->vbox;
+
+ self->ignore_activate = TRUE;
+
+ /* configure self */
+ g_object_set (self,
+ "flags", (GXK_DIALOG_HIDE_ON_DELETE |
+ GXK_DIALOG_PRESERVE_STATE |
+ GXK_DIALOG_POPUP_POS |
+ GXK_DIALOG_MODAL),
+ NULL);
+ gxk_dialog_set_sizes (GXK_DIALOG (self), -1, -1, 500, 450);
+ g_object_set (main_box,
+ "homogeneous", FALSE,
+ "spacing", 0,
+ "border_width", 0,
+ NULL);
+
+ /* notebook */
+ self->notebook = (GtkWidget*) g_object_new (GXK_TYPE_NOTEBOOK,
+ "visible", TRUE,
+ "show_border", TRUE,
+ "show_tabs", TRUE,
+ "scrollable", FALSE,
+ "tab_border", 0,
+ "enable_popup", TRUE,
+ "tab_pos", GTK_POS_TOP,
+ "border_width", 5,
+ "parent", main_box,
+ "enable_popup", FALSE,
+ NULL);
+
+ /* setup file selection widgets and add to notebook */
+ self->fs = (GtkFileSelection*) gtk_file_selection_new ("");
+ self->fpage = gxk_file_selection_split (self->fs, &bbox);
+ g_object_ref (self->fpage);
+ gtk_container_remove (GTK_CONTAINER (self->fpage->parent), self->fpage);
+ gxk_notebook_append (GTK_NOTEBOOK (self->notebook), self->fpage, "File Selection", TRUE);
+ g_object_unref (self->fpage);
+
+ /* sample selection tree */
+ self->spage = (GtkWidget*) g_object_new (GTK_TYPE_SCROLLED_WINDOW,
+ "visible", TRUE,
+ "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar_policy", GTK_POLICY_ALWAYS,
+ "border_width", 5,
+ "shadow_type", GTK_SHADOW_IN,
+ NULL);
+ gxk_notebook_append (GTK_NOTEBOOK (self->notebook), self->spage, "Sample Selection", TRUE);
+ self->file_store = bst_file_store_create ();
+ smodel = gtk_tree_model_sort_new_with_model (self->file_store);
+ self->tview = (GtkTreeView*) g_object_new (GTK_TYPE_TREE_VIEW,
+ "visible", TRUE,
+ "can_focus", TRUE,
+ "model", smodel,
+ "rules_hint", TRUE,
+ "parent", self->spage,
+ "search_column", BST_FILE_STORE_COL_BASE_NAME,
+ NULL);
+ g_object_unref (smodel);
+ g_object_connect (self->tview,
+ "swapped_signal::viewable-changed", tree_viewable_changed, self,
+ NULL);
+ tsel = gtk_tree_view_get_selection (self->tview);
+ gtk_tree_selection_set_mode (tsel, GTK_SELECTION_BROWSE);
+ gxk_tree_selection_force_browse (tsel, smodel);
+ g_object_connect (self->tview, "swapped_object_signal::row_activated", gtk_button_clicked,
self->fs->ok_button, NULL);
+
+ /* sample selection tree columns */
+ gxk_tree_view_add_text_column (self->tview, BST_FILE_STORE_COL_WAVE_NAME, "S",
+ 0.0, _("Name"), _("Sample or instrument name"),
+ NULL, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (self->tview, BST_FILE_STORE_COL_SIZE, "S",
+ 1.0, _("Size"), _("File size in bytes"),
+ NULL, self, G_CONNECT_SWAPPED);
+ gchar *padstring = g_strdup (_("Format")), *tip = g_strdup (_("Detected file format"));
+ guint l = strlen (padstring), n = 14;
+ if (l < n)
+ {
+ GString *gstring = g_string_new (padstring);
+ g_free (padstring);
+ while (l++ < n)
+ g_string_append (gstring, " ");
+ padstring = g_string_free (gstring, FALSE);
+ }
+ gxk_tree_view_add_text_column (self->tview, BST_FILE_STORE_COL_LOADER, "OF",
+ 0.0, padstring, tip,
+ NULL, self, G_CONNECT_SWAPPED);
+ g_free (padstring);
+ g_free (tip);
+ gxk_tree_view_add_text_column (self->tview, BST_FILE_STORE_COL_TIME_STR, "S",
+ 0.0, _("Time"), _("File modification time"),
+ NULL, self, G_CONNECT_SWAPPED);
+ if (BST_DVL_HINTS)
+ gxk_tree_view_add_toggle_column (self->tview, BST_FILE_STORE_COL_LOADABLE, "",
+ 0.0, "L", "Indication of whether a file is expected to be loadable",
+ NULL, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (self->tview, BST_FILE_STORE_COL_FILE, "S",
+ 0.0, _("Filename"), NULL,
+ NULL, self, G_CONNECT_SWAPPED);
+
+ /* pack separator and buttons */
+ gtk_box_pack_end (GTK_BOX (main_box), bbox, FALSE, TRUE, 0);
+ gtk_box_pack_end (GTK_BOX (main_box),
+ (GtkWidget*) g_object_new (GTK_TYPE_HSEPARATOR,
+ "visible", TRUE,
+ NULL),
+ FALSE, TRUE, 0);
+
+ /* setup save options */
+ self->osave = (GtkWidget*) g_object_new (GTK_TYPE_FRAME,
+ "label", _("Contents"),
+ "parent", self->fs->action_area,
+ NULL);
+ vbox = (GtkWidget*) g_object_new (GTK_TYPE_VBOX,
+ "visible", TRUE,
+ "parent", self->osave,
+ NULL);
+ self->radio1 = (GtkWidget*) g_object_new (GTK_TYPE_RADIO_BUTTON,
+ "label", "radio-1",
+ "visible", TRUE,
+ "parent", vbox,
+ "can_focus", FALSE,
+ NULL);
+ gtk_misc_set_alignment (GTK_MISC (GTK_BIN (self->radio1)->child), 0, .5);
+ self->radio2 = (GtkWidget*) g_object_new (GTK_TYPE_RADIO_BUTTON,
+ "label", "radio-2",
+ "visible", TRUE,
+ "parent", vbox,
+ "group", self->radio1,
+ "can_focus", FALSE,
+ NULL);
+ gtk_misc_set_alignment (GTK_MISC (GTK_BIN (self->radio2)->child), 0, .5);
+
+ /* setup actions */
+ g_object_connect (self->fs->ok_button, "swapped_signal::clicked", bst_file_dialog_activate, self, NULL);
+ g_object_connect (self->fs->cancel_button, "swapped_signal::clicked", gxk_toplevel_delete, self, NULL);
+
+ /* fixup focus and default widgets */
+ gxk_dialog_set_default (GXK_DIALOG (self), self->fs->ok_button);
+ gxk_dialog_set_focus (GXK_DIALOG (self), self->fs->selection_entry);
+
+ /* setup remaining bits */
+ bst_file_dialog_set_mode (self, NULL, BstFileDialogMode (0), _("File Selection"), 0);
+ gtk_window_set_type_hint (GTK_WINDOW (self), GDK_WINDOW_TYPE_HINT_DIALOG);
+ }
+
+ static void
+ bst_file_dialog_finalize (GObject *object)
+ {
+ BstFileDialog *self = BST_FILE_DIALOG (object);
+
+ bst_file_dialog_set_mode (self, NULL, BstFileDialogMode (0), NULL, 0);
+ g_free (self->search_path);
+ self->search_filter = NULL;
+ bst_file_store_destroy (self->file_store);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (bst_file_dialog_parent_class)->finalize (object);
+ }
+
+ static BstFileDialog*
+ bst_file_dialog_global_project (void)
+ {
+ static BstFileDialog *singleton = NULL;
+ if (!singleton)
+ singleton = (BstFileDialog*) g_object_new (BST_TYPE_FILE_DIALOG, NULL);
+ return singleton;
+ }
+
+ static BstFileDialog*
+ bst_file_dialog_global_wave (void)
+ {
+ static BstFileDialog *singleton = NULL;
+ if (!singleton)
+ singleton = (BstFileDialog*) g_object_new (BST_TYPE_FILE_DIALOG, NULL);
+ return singleton;
+ }
+
+ static BstFileDialog*
++bst_file_dialog_global_sound_font (void)
++{
++ static BstFileDialog *singleton = NULL;
++ if (!singleton)
++ singleton = g_object_new (BST_TYPE_FILE_DIALOG, NULL);
++ return singleton;
++}
++
++
++static BstFileDialog*
+ bst_file_dialog_global_effect (void)
+ {
+ static BstFileDialog *singleton = NULL;
+ if (!singleton)
+ {
+ const gchar *dir = bse_server_get_custom_effect_dir (BSE_SERVER);
+ singleton = (BstFileDialog*) g_object_new (BST_TYPE_FILE_DIALOG, NULL);
+ if (dir)
+ {
+ sfi_make_dirpath (dir);
+ gtk_file_selection_complete (singleton->fs, dir);
+ }
+ }
+ return singleton;
+ }
+
+ static BstFileDialog*
+ bst_file_dialog_global_instrument (void)
+ {
+ static BstFileDialog *singleton = NULL;
+ if (!singleton)
+ {
+ const gchar *dir = bse_server_get_custom_instrument_dir (BSE_SERVER);
+ singleton = (BstFileDialog*) g_object_new (BST_TYPE_FILE_DIALOG, NULL);
+ if (dir)
+ {
+ sfi_make_dirpath (dir);
+ gtk_file_selection_complete (singleton->fs, dir);
+ }
+ }
+ return singleton;
+ }
+
+ static void
+ parent_window_destroyed (BstFileDialog *self)
+ {
+ gtk_widget_hide (GTK_WIDGET (self));
+ bst_file_dialog_set_mode (self, NULL, BstFileDialogMode (0), NULL, 0);
+ gxk_toplevel_delete (GTK_WIDGET (self));
+ }
+
+ void
+ bst_file_dialog_set_mode (BstFileDialog *self,
+ gpointer parent_widget,
+ BstFileDialogMode mode,
+ const gchar *fs_title,
+ SfiProxy proxy)
+ {
+ GtkWindow *window = GTK_WINDOW (self);
+
+ g_return_if_fail (BST_IS_FILE_DIALOG (self));
+
+ gtk_widget_hide (GTK_WIDGET (self));
+ gtk_widget_hide (self->osave);
+ self->mode = mode;
+ g_free (self->selected);
+ self->selected = NULL;
+
+ /* reset proxy handling */
+ bst_window_sync_title_to_proxy (self, proxy, fs_title);
+ self->proxy = proxy;
+ self->super = 0;
+
+ /* cleanup connections to old parent_window */
+ if (self->parent_window)
+ g_signal_handlers_disconnect_by_func (self->parent_window, (void*) parent_window_destroyed, self);
+ if (window->group)
+ gtk_window_group_remove_window (window->group, window);
+ gtk_window_set_transient_for (window, NULL);
+
+ self->parent_window = parent_widget ? (GtkWindow*) gtk_widget_get_ancestor ((GtkWidget*) parent_widget,
GTK_TYPE_WINDOW) : NULL;
+
+ /* setup connections to new parent_window */
+ if (self->parent_window)
+ {
+ gtk_window_set_transient_for (window, self->parent_window);
+ if (self->parent_window->group)
+ gtk_window_group_add_window (self->parent_window->group, window);
+ g_signal_connect_object (self->parent_window, "destroy",
+ G_CALLBACK (parent_window_destroyed),
+ self, G_CONNECT_SWAPPED);
+ }
+
+ /* allow activation */
+ self->ignore_activate = FALSE;
+
+ /* 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_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_filter = NULL;
+ gtk_widget_show (self->spage);
+ gxk_notebook_set_current_page_widget (GTK_NOTEBOOK (self->notebook), self->spage);
+ g_object_set (self->notebook, "show_border", TRUE, "show_tabs", TRUE, NULL);
+ break;
+ case BST_FILE_DIALOG_MERGE_EFFECT:
+ g_free (self->search_path);
+ self->search_path = g_strdup (bse_server_get_effect_path (BSE_SERVER));
+ self->search_filter = "*";
+ gtk_widget_show (self->spage);
+ gxk_notebook_set_current_page_widget (GTK_NOTEBOOK (self->notebook), self->spage);
+ g_object_set (self->notebook, "show_border", TRUE, "show_tabs", TRUE, NULL);
+ break;
+ case BST_FILE_DIALOG_MERGE_INSTRUMENT:
+ g_free (self->search_path);
+ self->search_path = g_strdup (bse_server_get_instrument_path (BSE_SERVER));
+ self->search_filter = "*";
+ gtk_widget_show (self->spage);
+ gxk_notebook_set_current_page_widget (GTK_NOTEBOOK (self->notebook), self->spage);
+ g_object_set (self->notebook, "show_border", TRUE, "show_tabs", TRUE, NULL);
+ break;
+ default:
+ g_free (self->search_path);
+ self->search_path = NULL;
+ self->search_filter = NULL;
+ if (self->using_file_store)
+ {
+ self->using_file_store = FALSE;
+ bst_file_store_forget_list (self->file_store);
+ }
+ gtk_widget_hide (self->spage);
+ g_object_set (self->notebook, "show_border", FALSE, "show_tabs", FALSE, NULL);
+ break;
+ }
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_open_project (gpointer parent_widget)
+ {
+ BstFileDialog *self = bst_file_dialog_global_project ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_OPEN_PROJECT,
+ _("Open Project"), 0);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_select_file (gpointer parent_widget)
+ {
+ BstFileDialog *self = bst_file_dialog_global_project ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_SELECT_FILE,
+ _("Select File"), 0);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_select_dir (gpointer parent_widget)
+ {
+ BstFileDialog *self = bst_file_dialog_global_project ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_SELECT_DIR | BST_FILE_DIALOG_ALLOW_DIRS,
+ _("Select Directory"), 0);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_open_project (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ SfiProxy project = bse_server_use_new_project (BSE_SERVER, file_name);
+ BseErrorType error = bst_project_restore_from_file (project, file_name, TRUE, TRUE);
+
+ if (error)
+ bst_status_eprintf (error, _("Opening project `%s'"), file_name);
+ else
+ {
+ bse_project_get_wave_repo (project);
+ BstApp *app = bst_app_new (project);
+ gxk_status_window_push (app);
+ bst_status_eprintf (error, _("Opening project `%s'"), file_name);
+ gxk_status_window_pop ();
+ gxk_idle_show_widget (GTK_WIDGET (app));
+ }
+ bse_item_unuse (project);
+
+ return TRUE;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_merge_project (gpointer parent_widget,
+ SfiProxy project)
+ {
+ BstFileDialog *self = bst_file_dialog_global_project ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_MERGE_PROJECT,
+ _("Merge: %s"), project);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_merge_project (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ SfiProxy project = bse_item_use (self->proxy);
+ BseErrorType error = bst_project_restore_from_file (project, file_name, FALSE, FALSE);
+
+ bst_status_eprintf (error, _("Merging project `%s'"), file_name);
+
+ bse_item_unuse (project);
+
+ return TRUE;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_import_midi (gpointer parent_widget,
+ SfiProxy project)
+ {
+ BstFileDialog *self = bst_file_dialog_global_project ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_IMPORT_MIDI,
+ _("Import MIDI: %s"), project);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_import_midi (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ BseErrorType error = bst_project_import_midi_file (self->proxy, file_name);
+ bst_status_eprintf (error, _("Importing MIDI file `%s'"), file_name);
+ return TRUE;
+ }
+
+ static gboolean
+ store_bse_file (SfiProxy project,
+ SfiProxy super,
+ const gchar *file_name,
+ const gchar *saving_message_format,
+ gboolean self_contained,
+ gboolean want_overwrite)
+ {
+ BseErrorType error = bse_project_store_bse (project, super, file_name, self_contained);
+ gchar *title = g_strdup_format (saving_message_format, bse_item_get_name (super ? super : project));
+ gboolean handled = TRUE;
+ gchar *msg = NULL;
+ /* handle file exists cases */
+ if (error == BSE_ERROR_FILE_EXISTS)
+ {
+ if (!want_overwrite)
+ {
+ gchar *text = g_strdup_format (_("Failed to save\n`%s'\nto\n`%s':\n%s"), bse_item_get_name
(project), file_name, bse_error_blurb (error));
+ GtkWidget *choice = bst_choice_dialog_createv (BST_CHOICE_TITLE (title),
+ BST_CHOICE_TEXT (text),
+ BST_CHOICE_D (1, BST_STOCK_OVERWRITE, NONE),
+ BST_CHOICE (0, BST_STOCK_CANCEL, NONE),
+ BST_CHOICE_END);
+ g_free (text);
+ want_overwrite = bst_choice_modal (choice, 0, 0) == 1;
+ bst_choice_destroy (choice);
+ }
+ if (want_overwrite)
+ {
+ /* save to temporary file */
+ gchar *temp_file = NULL;
+ while (error == BSE_ERROR_FILE_EXISTS)
+ {
+ g_free (temp_file);
+ temp_file = g_strdup_format ("%s.tmp%06xyXXXXXX", file_name, rand() & 0xfffffd);
+ char *result = mktemp (temp_file); /* this is save, due to use of: O_CREAT | O_EXCL */
+ (void) result;
+ error = bse_project_store_bse (project, super, temp_file, self_contained);
+ }
+ /* replace file by temporary file */
+ if (error != BSE_ERROR_NONE)
+ {
+ unlink (temp_file); /* error != BSE_ERROR_FILE_EXISTS */
+ msg = g_strdup_format (_("Failed to save to file\n`%s'\ndue to:\n%s"), file_name,
bse_error_blurb (error));
+ }
+ else if (rename (temp_file, file_name) < 0)
+ {
+ unlink (temp_file);
+ msg = g_strdup_format (_("Failed to replace file\n`%s'\ndue to:\n%s"), file_name, g_strerror
(errno));
+ }
+ else /* success */
+ ;
+ }
+ else
+ handled = FALSE; /* exists && !overwrite */
+ }
+ else if (error != BSE_ERROR_NONE)
+ msg = g_strdup_format (_("Failed to save to file\n`%s'\ndue to:\n%s"), file_name, bse_error_blurb
(error));
+ /* report errors */
+ if (msg)
+ {
+ GtkWidget *choice = bst_choice_dialog_createv (BST_CHOICE_TITLE (title),
+ BST_CHOICE_TEXT (msg),
+ BST_CHOICE_D (0, BST_STOCK_CLOSE, NONE),
+ BST_CHOICE_END);
+ g_free (msg);
+ bst_choice_modal (choice, 0, 0);
+ bst_choice_destroy (choice);
+ handled = FALSE;
+ }
+ else if (handled) /* no error */
+ bst_status_eprintf (BSE_ERROR_NONE, "%s", title);
+ g_free (title);
+ return handled;
+ }
+
+ static gboolean
+ bst_file_dialog_save_project (SfiProxy proxy,
+ gboolean self_contained,
+ const gchar *file_name,
+ gboolean apply_project_name,
+ gboolean want_overwrite)
+ {
+ SfiProxy project = bse_item_use (proxy);
+ gboolean handled = store_bse_file (project, 0, file_name, _("Saving project `%s'"), self_contained,
want_overwrite);
+ if (apply_project_name)
+ {
+ bse_proxy_set_data_full (project, "beast-project-file-name", g_strdup (file_name), g_free);
+ bse_proxy_set_data (project, "beast-project-store-references", (void*) !self_contained);
+ gchar *bname = g_path_get_basename (file_name);
+ bse_project_change_name (project, bname);
+ g_free (bname);
+ }
+ if (handled)
+ bse_project_clean_dirty (project);
+ bse_item_unuse (project);
+
+ return handled;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_save_project (gpointer parent_widget,
+ SfiProxy project,
+ gboolean query_project_name,
+ gboolean apply_project_name)
+ {
+ /* handle non-popup case */
+ const char *filename = (const char*) bse_proxy_get_data (project, "beast-project-file-name");
+ bool store_references = size_t (bse_proxy_get_data (project, "beast-project-store-references"));
+ if (filename && !query_project_name)
+ {
+ gboolean handled = bst_file_dialog_save_project (project, !store_references, filename, FALSE, TRUE);
+ if (handled)
+ return NULL;
+ }
+ /* the usual Save As scenario */
+ BstFileDialog *self = bst_file_dialog_global_project ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_SAVE_PROJECT,
+ _("Save: %s"), project);
+ self->apply_project_name = apply_project_name != FALSE;
+ gtk_file_selection_set_filename (self->fs, filename ? filename : "");
+ /* setup radio buttons */
+ g_object_set (GTK_BIN (self->radio1)->child, "label", _("Fully include wave files"), NULL);
+ g_object_set (GTK_BIN (self->radio2)->child, "label", _("Store references to wave files"), NULL);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->radio2), store_references);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->radio1), !store_references);
+ gtk_widget_show (self->osave);
+ /* show dialog */
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_merge_effect (gpointer parent_widget,
+ SfiProxy project)
+ {
+ BstFileDialog *self = bst_file_dialog_global_effect ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_MERGE_EFFECT,
+ _("Load Effect"), project);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_merge_effect (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ SfiProxy project = bse_item_use (self->proxy);
+ BseErrorType error = bst_project_restore_from_file (project, file_name, FALSE, FALSE);
+
+ bst_status_eprintf (error, _("Merging effect `%s'"), file_name);
+
+ bse_item_unuse (project);
+
+ return TRUE;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_save_effect (gpointer parent_widget,
+ SfiProxy project,
+ SfiProxy super)
+ {
+ BstFileDialog *self = bst_file_dialog_global_effect ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_SAVE_EFFECT,
+ _("Save Effect"), project);
+ self->super = super;
+ /* show dialog */
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_save_effect (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ SfiProxy project = bse_item_use (self->proxy);
+ gboolean self_contained = TRUE;
+ gboolean handled = store_bse_file (project, self->super, file_name, _("Saving effect `%s'"),
self_contained, FALSE);
+ bse_item_unuse (project);
+
+ return handled;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_merge_instrument (gpointer parent_widget,
+ SfiProxy project)
+ {
+ BstFileDialog *self = bst_file_dialog_global_instrument ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_MERGE_INSTRUMENT,
+ _("Load Instrument"), project);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_merge_instrument (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ SfiProxy project = bse_item_use (self->proxy);
+ BseErrorType error = bst_project_restore_from_file (project, file_name, FALSE, FALSE);
+
+ bst_status_eprintf (error, _("Merging instrument `%s'"), file_name);
+
+ bse_item_unuse (project);
+
+ return TRUE;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_save_instrument (gpointer parent_widget,
+ SfiProxy project,
+ SfiProxy super)
+ {
+ BstFileDialog *self = bst_file_dialog_global_instrument ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_SAVE_INSTRUMENT,
+ _("Save Instrument"), project);
+ self->super = super;
+ /* show dialog */
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_save_instrument (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ SfiProxy project = bse_item_use (self->proxy);
+ gboolean self_contained = TRUE;
+ gboolean handled = store_bse_file (project, self->super, file_name, _("Saving instrument `%s'"),
self_contained, FALSE);
+ bse_item_unuse (project);
+
+ return handled;
+ }
+
+ GtkWidget*
+ bst_file_dialog_popup_load_wave (gpointer parent_widget,
+ SfiProxy wave_repo,
+ gboolean show_lib)
+ {
+ BstFileDialog *self = bst_file_dialog_global_wave ();
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ bst_file_dialog_set_mode (self, parent_widget,
+ show_lib ? BST_FILE_DIALOG_LOAD_WAVE_LIB : BST_FILE_DIALOG_LOAD_WAVE,
+ _("Load Wave"), wave_repo);
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ static gboolean
+ bst_file_dialog_load_wave (BstFileDialog *self,
+ const gchar *file_name)
+ {
+ BseErrorType error;
+
+ gxk_status_printf (0, NULL, _("Loading wave `%s'"), file_name);
+ error = bse_wave_repo_load_file (self->proxy, file_name);
+ bst_status_eprintf (error, _("Loading wave `%s'"), file_name);
+ if (error)
+ sfi_error (_("Failed to load wave file \"%s\": %s"), file_name, bse_error_blurb (error));
+
+ return TRUE;
+ }
+
+ 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);
++ gxk_widget_showraise (widget);
++
++ return widget;
++}
++
++static gboolean
++bst_file_dialog_load_sound_font (BstFileDialog *self,
++ const gchar *file_name)
++{
++ BseErrorType error;
++
++ gxk_status_printf (0, NULL, _("Loading sound font `%s'"), file_name);
++ error = bse_sound_font_repo_load_file (self->proxy, 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));
++
++ return TRUE;
++}
++
++GtkWidget*
+ bst_file_dialog_create (void)
+ {
+ BstFileDialog *self = (BstFileDialog*) g_object_new (BST_TYPE_FILE_DIALOG, NULL);
+ bst_file_dialog_set_mode (self, NULL,
+ BST_FILE_DIALOG_SELECT_FILE,
+ "File Selector", 0);
+ return GTK_WIDGET (self);
+ }
+
+ void
+ bst_file_dialog_setup (GtkWidget *widget,
+ gpointer parent_widget,
+ const gchar *title,
+ const gchar *search_path)
+ {
+ BstFileDialog *self = BST_FILE_DIALOG (widget);
+ gchar *path;
+ bst_file_dialog_set_mode (self, parent_widget,
+ BST_FILE_DIALOG_SELECT_FILE,
+ title, 0);
+ g_free (self->search_path);
+ self->search_path = g_strdup (search_path);
+ self->search_filter = "*";
+ path = g_strconcat (self->search_path, G_DIR_SEPARATOR_S, self->search_filter, NULL);
+ gtk_file_selection_complete (self->fs, path);
+ g_free (path);
+ tree_viewable_changed (self);
+ }
+
+ typedef struct {
+ BstFileDialogHandler handler;
+ gpointer data;
+ GDestroyNotify destroy;
+ } BstFileDialogData;
+
+ static void
+ bst_file_dialog_handler (BstFileDialog *self,
+ BstFileDialogData *data)
+ {
+ if (data->handler && self->selected)
+ data->handler (GTK_WIDGET (self), self->selected, data->data);
+ if (data->destroy)
+ data->destroy (data->data);
+ g_object_disconnect (self, "any_signal", bst_file_dialog_handler, data, NULL);
+ g_free (data);
+ }
+
+ void
+ bst_file_dialog_set_handler (BstFileDialog *self,
+ BstFileDialogHandler handler,
+ gpointer handler_data,
+ GDestroyNotify destroy)
+ {
+ BstFileDialogData *data = g_new0 (BstFileDialogData, 1);
+
+ g_return_if_fail (GTK_WIDGET_VISIBLE (self));
+
+ data->handler = handler;
+ data->data = handler_data;
+ data->destroy = destroy;
+ g_object_connect (self, "signal_after::hide", bst_file_dialog_handler, data, NULL);
+ }
+
+ static void
+ bst_file_dialog_activate (BstFileDialog *self)
+ {
+ GtkWindow *swin = self->parent_window;
+ gboolean popdown = TRUE;
+ gchar *file_name;
+
+ if (self->ignore_activate)
+ return;
+
+ if (self->tview && gxk_widget_viewable (GTK_WIDGET (self->tview)))
+ {
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (self->tview), &model, &iter))
+ {
+ GValue value = { 0, };
+ gtk_tree_model_get_value (model, &iter, BST_FILE_STORE_COL_FILE, &value);
+ file_name = g_value_dup_string (&value);
+ g_value_unset (&value);
+ }
+ else
+ return;
+ }
+ else
+ file_name = g_strdup (gtk_file_selection_get_filename (self->fs));
+
+ if (!(self->mode & BST_FILE_DIALOG_ALLOW_DIRS) &&
+ g_file_test (file_name, G_FILE_TEST_IS_DIR))
+ {
+ gchar *tmp = g_strconcat (file_name, G_DIR_SEPARATOR_S, NULL); /* don't complete on "." but "./" */
+ gxk_notebook_set_current_page_widget (GTK_NOTEBOOK (self->notebook), self->fpage);
+ gtk_file_selection_complete (self->fs, tmp);
+ g_free (tmp);
+ g_free (file_name);
+ return;
+ }
+
+ if (swin)
+ gxk_status_window_push (swin);
+ switch (self->mode & BST_FILE_DIALOG_MODE_MASK)
+ {
+ case BST_FILE_DIALOG_OPEN_PROJECT:
+ popdown = bst_file_dialog_open_project (self, file_name);
+ break;
+ case BST_FILE_DIALOG_MERGE_PROJECT:
+ popdown = bst_file_dialog_merge_project (self, file_name);
+ break;
+ case BST_FILE_DIALOG_IMPORT_MIDI:
+ popdown = bst_file_dialog_import_midi (self, file_name);
+ break;
+ case BST_FILE_DIALOG_MERGE_EFFECT:
+ popdown = bst_file_dialog_merge_effect (self, file_name);
+ break;
+ case BST_FILE_DIALOG_MERGE_INSTRUMENT:
+ popdown = bst_file_dialog_merge_instrument (self, file_name);
+ break;
+ case BST_FILE_DIALOG_SAVE_PROJECT:
+ popdown = bst_file_dialog_save_project (self->proxy, GTK_TOGGLE_BUTTON (self->radio1)->active,
file_name, self->apply_project_name, FALSE);
+ break;
+ case BST_FILE_DIALOG_SAVE_EFFECT:
+ popdown = bst_file_dialog_save_effect (self, file_name);
+ break;
+ case BST_FILE_DIALOG_SAVE_INSTRUMENT:
+ popdown = bst_file_dialog_save_instrument (self, file_name);
+ break;
+ case BST_FILE_DIALOG_SELECT_FILE:
+ case BST_FILE_DIALOG_SELECT_DIR:
+ popdown = TRUE; /* handled via BstFileDialogHandler and ->selected */
+ break;
+ case BST_FILE_DIALOG_LOAD_WAVE:
+ case BST_FILE_DIALOG_LOAD_WAVE_LIB:
+ popdown = bst_file_dialog_load_wave (self, file_name);
+ break;
++ case BST_FILE_DIALOG_LOAD_SOUND_FONT:
++ case BST_FILE_DIALOG_LOAD_SOUND_FONT_LIB:
++ popdown = bst_file_dialog_load_sound_font (self, file_name);
++ break;
+ default: ;
+ }
+ if (swin)
+ gxk_status_window_pop ();
+ if (popdown)
+ {
+ /* ignore_activate guards against multiple clicks from long loads */
+ self->ignore_activate = TRUE;
+ g_free (self->selected);
+ self->selected = file_name;
+ gxk_toplevel_delete (GTK_WIDGET (self));
+ }
+ else
+ g_free (file_name);
+ }
diff --cc beast-gtk/bstfiledialog.hh
index 0000000,93fc348..9290588
mode 000000,100644..100644
--- a/beast-gtk/bstfiledialog.hh
+++ b/beast-gtk/bstfiledialog.hh
@@@ -1,0 -1,126 +1,131 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BST_FILE_DIALOG_H__
+ #define __BST_FILE_DIALOG_H__
+
+ #include "bstutils.hh"
+ #include "bstapp.hh"
+
+ G_BEGIN_DECLS
+
+
+ /* --- type macros --- */
+ #define BST_TYPE_FILE_DIALOG (bst_file_dialog_get_type ())
+ #define BST_FILE_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), BST_TYPE_FILE_DIALOG,
BstFileDialog))
+ #define BST_FILE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BST_TYPE_FILE_DIALOG,
BstFileDialogClass))
+ #define BST_IS_FILE_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), BST_TYPE_FILE_DIALOG))
+ #define BST_IS_FILE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BST_TYPE_FILE_DIALOG))
+ #define BST_FILE_DIALOG_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), BST_TYPE_FILE_DIALOG,
BstFileDialogClass))
+
+
+ /* --- typedefs --- */
+ typedef struct _BstFileDialog BstFileDialog;
+ typedef struct _BstFileDialogClass BstFileDialogClass;
+
+
+ /* --- structures --- */
+ typedef enum {
- BST_FILE_DIALOG_OPEN_PROJECT = 0x0001,
- BST_FILE_DIALOG_MERGE_PROJECT = 0x0002,
- BST_FILE_DIALOG_SAVE_PROJECT = 0x0003,
- BST_FILE_DIALOG_IMPORT_MIDI = 0x0004,
- BST_FILE_DIALOG_SELECT_FILE = 0x0008,
- BST_FILE_DIALOG_SELECT_DIR = 0x0009,
- BST_FILE_DIALOG_LOAD_WAVE = 0x0011,
- BST_FILE_DIALOG_LOAD_WAVE_LIB = 0x0012,
- BST_FILE_DIALOG_MERGE_EFFECT = 0x0021,
- BST_FILE_DIALOG_MERGE_INSTRUMENT = 0x0022,
- BST_FILE_DIALOG_SAVE_EFFECT = 0x0023,
- BST_FILE_DIALOG_SAVE_INSTRUMENT = 0x0024,
- BST_FILE_DIALOG_MODE_MASK = 0x00ff,
- BST_FILE_DIALOG_ALLOW_DIRS = 0x1000,
- BST_FILE_DIALOG_FLAG_MASK = 0xff00
++ BST_FILE_DIALOG_OPEN_PROJECT = 0x0001,
++ BST_FILE_DIALOG_MERGE_PROJECT = 0x0002,
++ BST_FILE_DIALOG_SAVE_PROJECT = 0x0003,
++ BST_FILE_DIALOG_IMPORT_MIDI = 0x0004,
++ BST_FILE_DIALOG_SELECT_FILE = 0x0008,
++ BST_FILE_DIALOG_SELECT_DIR = 0x0009,
++ BST_FILE_DIALOG_LOAD_WAVE = 0x0011,
++ BST_FILE_DIALOG_LOAD_WAVE_LIB = 0x0012,
++ BST_FILE_DIALOG_LOAD_SOUND_FONT = 0x0013,
++ BST_FILE_DIALOG_LOAD_SOUND_FONT_LIB = 0x0014,
++ BST_FILE_DIALOG_MERGE_EFFECT = 0x0021,
++ BST_FILE_DIALOG_MERGE_INSTRUMENT = 0x0022,
++ BST_FILE_DIALOG_SAVE_EFFECT = 0x0023,
++ BST_FILE_DIALOG_SAVE_INSTRUMENT = 0x0024,
++ BST_FILE_DIALOG_MODE_MASK = 0x00ff,
++ BST_FILE_DIALOG_ALLOW_DIRS = 0x1000,
++ BST_FILE_DIALOG_FLAG_MASK = 0xff00
+ } BstFileDialogMode;
+ struct _BstFileDialog
+ {
+ GxkDialog parent_instance;
+ GtkFileSelection *fs;
+ GtkWidget *notebook;
+ GtkWidget *fpage; /* file selection */
+ GtkWidget *spage; /* sample selection */
+ GtkTreeView *tview; /* sample selection tree view */
+ GtkWidget *osave; /* save options */
+ GtkWidget *radio1, *radio2;
+ gchar *selected;
+ /* mode state */
+ BstFileDialogMode mode : 16;
+ guint ignore_activate : 1;
+ guint using_file_store : 1;
+ guint apply_project_name : 1;
+ GtkTreeModel *file_store;
+ gchar *search_path;
+ const gchar *search_filter;
+ GtkWindow *parent_window;
+ SfiProxy proxy, super;
+ };
+ struct _BstFileDialogClass
+ {
+ GxkDialogClass parent_class;
+ };
+
+
+ /* --- prototypes --- */
+ GType bst_file_dialog_get_type (void);
+ GtkWidget* bst_file_dialog_popup_open_project (gpointer parent_widget);
+ GtkWidget* bst_file_dialog_popup_merge_project (gpointer parent_widget,
+ SfiProxy project);
+ GtkWidget* bst_file_dialog_popup_import_midi (gpointer parent_widget,
+ SfiProxy project);
+ GtkWidget* bst_file_dialog_popup_save_project (gpointer parent_widget,
+ SfiProxy project,
+ gboolean query_project_name,
+ gboolean apply_project_name);
+ GtkWidget* bst_file_dialog_popup_merge_effect (gpointer parent_widget,
+ SfiProxy project);
+ GtkWidget* bst_file_dialog_popup_save_effect (gpointer parent_widget,
+ SfiProxy project,
+ SfiProxy super);
+ GtkWidget* bst_file_dialog_popup_save_instrument (gpointer parent_widget,
+ SfiProxy project,
+ SfiProxy super);
+ GtkWidget* bst_file_dialog_popup_merge_instrument (gpointer parent_widget,
+ SfiProxy project);
+ GtkWidget* bst_file_dialog_popup_select_file (gpointer parent_widget);
+ GtkWidget* bst_file_dialog_popup_select_dir (gpointer parent_widget);
+ 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);
+ GtkWidget* bst_file_dialog_create (void);
+ void bst_file_dialog_setup (GtkWidget *widget,
+ gpointer parent_widget,
+ const gchar *title,
+ const gchar *search_path);
+ typedef void (*BstFileDialogHandler) (GtkWidget *dialog,
+ const gchar *file,
+ gpointer user_data);
+ void bst_file_dialog_set_handler (BstFileDialog *self,
+ BstFileDialogHandler handler,
+ gpointer handler_data,
+ GDestroyNotify destroy);
+
+ G_END_DECLS
+
+ // == Flags Enumeration Operators in C++ ==
+ #ifdef __cplusplus
+ constexpr BstFileDialogMode operator& (BstFileDialogMode s1, BstFileDialogMode s2) { return
BstFileDialogMode (s1 & (long long unsigned) s2); }
+ inline BstFileDialogMode& operator&= (BstFileDialogMode &s1, BstFileDialogMode s2) { s1 = s1 & s2;
return s1; }
+ constexpr BstFileDialogMode operator| (BstFileDialogMode s1, BstFileDialogMode s2) { return
BstFileDialogMode (s1 | (long long unsigned) s2); }
+ inline BstFileDialogMode& operator|= (BstFileDialogMode &s1, BstFileDialogMode s2) { s1 = s1 | s2;
return s1; }
+ constexpr BstFileDialogMode operator~ (BstFileDialogMode s1) { return
BstFileDialogMode (~(long long unsigned) s1); }
+ #endif // __cplusplus
+
+ #endif /* __BST_FILE_DIALOG_H__ */
diff --cc beast-gtk/bstsupershell.cc
index 0000000,5f06742..224c4df
mode 000000,100644..100644
--- a/beast-gtk/bstsupershell.cc
+++ b/beast-gtk/bstsupershell.cc
@@@ -1,0 -1,249 +1,266 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bstsupershell.hh"
+ #include "bstparamview.hh"
+ #include "bsttrackview.hh"
+ #include "bstpartview.hh"
+ #include "bstbusmixer.hh"
+ #include "bstbusview.hh"
+ #include "bstwaveview.hh"
+ #include "bstrackview.hh"
++#include "bstsoundfontview.h"
+ #include "bstsnetrouter.hh"
+ #include "bstgconfig.hh"
+ #include <string.h>
+
+ enum {
+ PROP_0,
+ PROP_SUPER
+ };
+
+
+ /* --- prototypes --- */
+ static void bst_super_shell_destroy (GtkObject *object);
+ static void bst_super_shell_finalize (GObject *object);
+ static void bst_super_shell_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+ static void bst_super_shell_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+ static void super_shell_add_views (BstSuperShell *self);
+
+
+ /* --- static variables --- */
+ static BstSuperShellClass *bst_super_shell_class = NULL;
+
+
+ /* --- functions --- */
+ G_DEFINE_TYPE (BstSuperShell, bst_super_shell, GTK_TYPE_VBOX);
+
+ static void
+ bst_super_shell_class_init (BstSuperShellClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
+
+ bst_super_shell_class = klass;
+
+ gobject_class->set_property = bst_super_shell_set_property;
+ gobject_class->get_property = bst_super_shell_get_property;
+ gobject_class->finalize = bst_super_shell_finalize;
+
+ object_class->destroy = bst_super_shell_destroy;
+
+ g_object_class_install_property (gobject_class,
+ PROP_SUPER,
+ sfi_pspec_proxy ("super", NULL, NULL, SFI_PARAM_STANDARD));
+ }
+
+ static void
+ bst_super_shell_init (BstSuperShell *self)
+ {
+ self->super = 0;
+ gtk_widget_set (GTK_WIDGET (self),
+ "visible", TRUE,
+ "homogeneous", FALSE,
+ "spacing", 0,
+ "border_width", 0,
+ NULL);
+ }
+
+ static void
+ bst_super_shell_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+ {
+ BstSuperShell *self = BST_SUPER_SHELL (object);
+
+ switch (prop_id)
+ {
+ case PROP_SUPER:
+ bst_super_shell_set_super (self, sfi_value_get_proxy (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+
+ static void
+ bst_super_shell_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+ {
+ BstSuperShell *self = BST_SUPER_SHELL (object);
+
+ switch (prop_id)
+ {
+ case PROP_SUPER:
+ sfi_value_set_proxy (value, self->super);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ }
+
+ static void
+ bst_super_shell_destroy (GtkObject *object)
+ {
+ BstSuperShell *self = BST_SUPER_SHELL (object);
+
+ if (self->super)
+ bst_super_shell_set_super (self, 0);
+
+ GTK_OBJECT_CLASS (bst_super_shell_parent_class)->destroy (object);
+ }
+
+ static void
+ bst_super_shell_finalize (GObject *object)
+ {
+ // BstSuperShell *self = BST_SUPER_SHELL (object);
+
+ G_OBJECT_CLASS (bst_super_shell_parent_class)->finalize (object);
+ }
+
+ void
+ bst_super_shell_set_super (BstSuperShell *self,
+ SfiProxy super)
+ {
+ g_return_if_fail (BST_IS_SUPER_SHELL (self));
+ if (super)
+ g_return_if_fail (BSE_IS_SUPER (super));
+
+ if (super != self->super)
+ {
+ if (self->super)
+ {
+ gtk_container_foreach (GTK_CONTAINER (self), (GtkCallback) gtk_widget_destroy, NULL);
+ bse_item_unuse (self->super);
+ }
+ self->super = super;
+ if (self->super)
+ {
+ bse_item_use (self->super);
+ super_shell_add_views (self);
+ }
+ }
+ }
+
+ GtkWidget*
+ bst_super_shell_create_label (BstSuperShell *super_shell)
+ {
+ return gxk_notebook_create_tabulator ("SuperShell", NULL, NULL);
+ }
+
+ static void
+ super_shell_build_song (BstSuperShell *self,
+ GtkNotebook *notebook)
+ {
+ SfiProxy song = self->super;
+
+ gtk_notebook_append_page (notebook,
+ bst_track_view_new (song),
+ gxk_notebook_create_tabulator (_("Tracks"), BST_STOCK_TRACKS, _("Tracks contain
instrument definitions and parts with notes")));
+ gtk_notebook_append_page (notebook,
+ bst_bus_mixer_new (song),
+ gxk_notebook_create_tabulator (_("Mixer"), BST_STOCK_MIXER, _("Mix track
outputs, adjust volume and add effects")));
+ gtk_notebook_append_page (notebook,
+ bst_param_view_new (song),
+ gxk_notebook_create_tabulator (_("Properties"), BST_STOCK_PROPERTIES, _("Adjust
overall song behaviour")));
+ if (BST_DBG_EXT)
+ gtk_notebook_append_page (notebook,
+ bst_part_view_new (song),
+ gxk_notebook_create_tabulator (_("Parts"), BST_STOCK_PART, NULL));
+ if (BST_DBG_EXT)
+ gtk_notebook_append_page (notebook,
+ bst_bus_view_new (song),
+ gxk_notebook_create_tabulator (_("Busses"), BST_STOCK_BUS, NULL));
+ if (BST_DBG_EXT)
+ gtk_notebook_append_page (notebook,
+ gtk_widget_get_toplevel (GTK_WIDGET (bst_snet_router_build_page (song))),
+ gxk_notebook_create_tabulator (_("Routing"), BST_STOCK_MESH, NULL));
+ }
+
+ static void
+ super_shell_build_snet (BstSuperShell *self,
+ GtkNotebook *notebook)
+ {
+ SfiProxy snet = self->super;
+ GtkWidget *param_view;
+
+ if (BST_DBG_EXT && bse_snet_supports_user_synths (snet))
+ gtk_notebook_append_page (notebook,
+ gtk_widget_get_toplevel (bst_rack_view_new (snet)),
+ gxk_notebook_create_tabulator (_("Rack"), NULL, NULL));
+ if (bse_snet_supports_user_synths (snet) || BST_DBG_EXT)
+ gtk_notebook_append_page (notebook,
+ gtk_widget_get_toplevel (GTK_WIDGET (bst_snet_router_build_page (snet))),
+ gxk_notebook_create_tabulator (_("Routing"), BST_STOCK_MESH, _("Add, edit and
connect synthesizer mesh components")));
+ param_view = bst_param_view_new (snet);
+ gtk_notebook_append_page (notebook,
+ bst_param_view_new (snet),
+ gxk_notebook_create_tabulator (_("Properties"), BST_STOCK_PROPERTIES, _("Adjust
overall synthesizer behaviour")));
+ }
+
+ static void
+ super_shell_build_wave_repo (BstSuperShell *self,
+ GtkNotebook *notebook)
+ {
+ SfiProxy wrepo = self->super;
+
+ gtk_notebook_append_page (notebook,
+ bst_wave_view_new (wrepo),
+ gxk_notebook_create_tabulator (_("Waves"), BST_STOCK_MINI_WAVE_REPO, NULL));
+ gtk_notebook_append_page (notebook,
+ bst_param_view_new (wrepo),
+ 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;
++
++ 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)
+ {
+ GtkNotebook *notebook = (GtkNotebook*) g_object_new (GXK_TYPE_NOTEBOOK,
+ "scrollable", FALSE,
+ "tab_border", 0,
+ "show_border", TRUE,
+ "enable_popup", FALSE,
+ "show_tabs", TRUE,
+ "tab_pos", GTK_POS_TOP,
+ "border_width", 3,
+ "parent", self,
+ "visible", TRUE,
+ NULL);
+ return notebook;
+ }
+
+ static void
+ super_shell_add_views (BstSuperShell *self)
+ {
+ if (BSE_IS_SONG (self->super))
+ super_shell_build_song (self, create_notebook (self));
+ else if (BSE_IS_WAVE_REPO (self->super))
+ super_shell_build_wave_repo (self, create_notebook (self));
++ else if (BSE_IS_SOUND_FONT_REPO (self->super))
++ 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 0000000,dcad9d9..16ec978
mode 000000,100644..100644
--- a/beast-gtk/bsttracksynthdialog.cc
+++ b/beast-gtk/bsttracksynthdialog.cc
@@@ -1,0 -1,307 +1,326 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bsttracksynthdialog.hh"
+ #include "bsttreestores.hh"
+
+
+ /* --- prototypes --- */
+ static void bst_track_synth_dialog_finalize (GObject *object);
+ static void bst_track_synth_dialog_activate (BstTrackSynthDialog *self);
+ static gboolean bst_track_synth_dialog_delete_event (GtkWidget *widget,
+ GdkEventAny *event);
+ static void bst_track_synth_dialog_setup (BstTrackSynthDialog *self,
+ gpointer parent_widget,
+ const gchar *title,
+ SfiProxy proxy);
+
+
+ /* --- functions --- */
+ G_DEFINE_TYPE (BstTrackSynthDialog, bst_track_synth_dialog, GXK_TYPE_DIALOG);
+
+ static void
+ bst_track_synth_dialog_class_init (BstTrackSynthDialogClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gobject_class->finalize = bst_track_synth_dialog_finalize;
+
+ widget_class->delete_event = bst_track_synth_dialog_delete_event;
+ }
+
+ static void
+ bst_track_synth_dialog_init (BstTrackSynthDialog *self)
+ {
+ GtkTreeSelection *tsel;
+ GtkTreeModel *smodel;
+ GtkWidget *main_box = GXK_DIALOG (self)->vbox;
+
+ /* configure self */
+ g_object_set (self,
+ "flags", (GXK_DIALOG_HIDE_ON_DELETE |
+ GXK_DIALOG_PRESERVE_STATE |
+ GXK_DIALOG_POPUP_POS |
+ GXK_DIALOG_MODAL),
+ NULL);
- gxk_dialog_set_sizes (GXK_DIALOG (self), 550, 300, 600, 320);
++ gxk_dialog_set_sizes (GXK_DIALOG (self), 550, 300, 600, 450);
+
+ /* notebook */
+ self->notebook = (GtkNotebook*) g_object_new (GXK_TYPE_NOTEBOOK,
+ "visible", TRUE,
+ "homogeneous", TRUE,
+ "show_border", TRUE,
+ "show_tabs", TRUE,
+ "scrollable", FALSE,
+ "tab_border", 0,
+ "enable_popup", TRUE,
+ "tab_pos", GTK_POS_TOP,
+ "border_width", 5,
+ "parent", main_box,
+ "enable_popup", FALSE,
+ NULL);
+
+ /* synth list */
+ self->spage = (GtkWidget*) g_object_new (GTK_TYPE_SCROLLED_WINDOW,
+ "visible", TRUE,
+ "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar_policy", GTK_POLICY_ALWAYS,
+ "border_width", 5,
+ "shadow_type", GTK_SHADOW_IN,
+ NULL);
+ gxk_notebook_append (self->notebook, self->spage, "synth", TRUE);
+
+ /* synth selection store and tree */
+ self->pstore = bst_item_seq_store_new (TRUE);
+ smodel = gtk_tree_model_sort_new_with_model (self->pstore);
+ self->tview = (GtkTreeView*) g_object_new (GTK_TYPE_TREE_VIEW,
+ "visible", TRUE,
+ "can_focus", TRUE,
+ "model", smodel,
+ "rules_hint", TRUE,
+ "parent", self->spage,
+ "search_column", BST_PROXY_STORE_NAME,
+ NULL);
+ g_object_unref (smodel);
+ tsel = gtk_tree_view_get_selection (self->tview);
+ gtk_tree_selection_set_mode (tsel, GTK_SELECTION_BROWSE);
+ gxk_tree_selection_force_browse (tsel, smodel);
+
+ /* synth selection tree columns */
+ if (BST_DVL_HINTS)
+ gxk_tree_view_add_text_column (self->tview, BST_PROXY_STORE_SEQID, "S",
+ 0.0, "ID", NULL,
+ NULL, NULL, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (self->tview, BST_PROXY_STORE_NAME, "S",
+ 0.0, "Name", NULL,
+ NULL, NULL, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (self->tview, BST_PROXY_STORE_BLURB, "",
+ 0.0, "Comment", NULL,
+ NULL, NULL, G_CONNECT_SWAPPED);
+ if (BST_DVL_HINTS)
+ gxk_tree_view_add_text_column (self->tview, BST_PROXY_STORE_TYPE, "",
+ 0.0, "Type", NULL,
+ NULL, NULL, G_CONNECT_SWAPPED);
+
+ /* wave repo view */
+ self->wpage = (GtkWidget*) g_object_new (BST_TYPE_WAVE_VIEW, "visible", TRUE, NULL);
+ gxk_notebook_append (self->notebook, self->wpage, "wave", TRUE);
+ bst_wave_view_set_editable (BST_WAVE_VIEW (self->wpage), FALSE);
++ /* sound font view */
++ self->sfont_page = g_object_new (BST_TYPE_SOUND_FONT_VIEW, "visible", TRUE, NULL);
++ gxk_notebook_append (self->notebook, self->sfont_page, "sound_font", TRUE);
+
+ /* provide buttons */
+ self->ok = gxk_dialog_default_action_swapped (GXK_DIALOG (self), BST_STOCK_OK, (void*)
bst_track_synth_dialog_activate, self);
+ gxk_dialog_action (GXK_DIALOG (self), BST_STOCK_CANCEL, (void*) gxk_toplevel_delete, (GtkWidget*) self);
+
+ /* make row connections */
+ g_signal_connect_object (self->tview, "row_activated", G_CALLBACK (gtk_button_clicked), self->ok,
G_CONNECT_SWAPPED);
+ g_signal_connect_object (BST_ITEM_VIEW (self->wpage)->tree, "row_activated",
+ G_CALLBACK (gtk_button_clicked), self->ok, G_CONNECT_SWAPPED);
+ }
+
+ static void
+ bst_track_synth_dialog_finalize (GObject *object)
+ {
+ BstTrackSynthDialog *self = BST_TRACK_SYNTH_DIALOG (object);
+
+ bst_track_synth_dialog_setup (self, NULL, NULL, 0);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (bst_track_synth_dialog_parent_class)->finalize (object);
+ }
+
+ static gboolean
+ bst_track_synth_dialog_delete_event (GtkWidget *widget,
+ GdkEventAny *event)
+ {
+ BstTrackSynthDialog *self = BST_TRACK_SYNTH_DIALOG (widget);
+ GxkFreeFunc selected_cleanup = self->selected_cleanup;
+ self->selected_callback = NULL;
+ self->selected_cleanup = NULL;
+ if (selected_cleanup)
+ selected_cleanup (self->selected_data);
+ if (self->pstore)
+ bst_item_seq_store_set (self->pstore, NULL);
+ /* chain parent class' handler */
+ return GTK_WIDGET_CLASS (bst_track_synth_dialog_parent_class)->delete_event (widget, event);
+ }
+
+ static void
+ parent_window_destroyed (BstTrackSynthDialog *self)
+ {
+ GxkFreeFunc selected_cleanup = self->selected_cleanup;
+ self->selected_callback = NULL;
+ self->selected_cleanup = NULL;
+ if (selected_cleanup)
+ selected_cleanup (self->selected_data);
+ gtk_widget_hide (GTK_WIDGET (self));
+ bst_track_synth_dialog_setup (self, NULL, NULL, 0);
+ gxk_toplevel_delete (GTK_WIDGET (self));
+ }
+
+ static void
+ bst_track_synth_dialog_setup (BstTrackSynthDialog *self,
+ gpointer parent_widget,
+ const gchar *title,
+ SfiProxy proxy)
+ {
+ GtkWindow *window = GTK_WINDOW (self);
+
+ g_return_if_fail (BST_IS_TRACK_SYNTH_DIALOG (self));
+
+ self->selected_callback = NULL;
+ GxkFreeFunc selected_cleanup = self->selected_cleanup;
+ self->selected_callback = NULL;
+ self->selected_cleanup = NULL;
+ if (selected_cleanup)
+ selected_cleanup (self->selected_data);
+
+ gtk_widget_hide (GTK_WIDGET (self));
+
+ /* reset proxy handling */
+ bst_window_sync_title_to_proxy (self, proxy, title);
+
+ /* cleanup connections to old parent_window */
+ if (self->parent_window)
+ g_signal_handlers_disconnect_by_func (self->parent_window, (void*) parent_window_destroyed, self);
+ if (window->group)
+ gtk_window_group_remove_window (window->group, window);
+ gtk_window_set_transient_for (window, NULL);
+
+ self->parent_window = parent_widget ? (GtkWindow*) gtk_widget_get_ancestor ((GtkWidget*) parent_widget,
GTK_TYPE_WINDOW) : NULL;
+
+ /* setup connections to new parent_window */
+ if (self->parent_window)
+ {
+ gtk_window_set_transient_for (window, self->parent_window);
+ if (self->parent_window->group)
+ gtk_window_group_add_window (self->parent_window->group, window);
+ g_signal_connect_object (self->parent_window, "destroy",
+ G_CALLBACK (parent_window_destroyed),
+ self, G_CONNECT_SWAPPED);
+ }
+
+ /* allow activation */
+ self->ignore_activate = FALSE;
+ gxk_notebook_set_current_page_widget (self->notebook, self->spage);
+ }
+
+ static BstTrackSynthDialog*
+ bst_track_synth_dialog_singleton (void)
+ {
+ static BstTrackSynthDialog *ts_singleton = NULL;
+ if (!ts_singleton)
+ ts_singleton = (BstTrackSynthDialog*) g_object_new (BST_TYPE_TRACK_SYNTH_DIALOG, NULL);
+ return ts_singleton;
+ }
+
+ GtkWidget*
+ bst_track_synth_dialog_popup (gpointer parent_widget,
+ SfiProxy track,
+ const gchar *candidate_label,
+ const gchar *candidate_tooltip,
+ BseItemSeq *candidates,
+ const gchar *wrepo_label,
+ const gchar *wrepo_tooltip,
+ SfiProxy wrepo,
++ const gchar *sfrepo_label,
++ const gchar *sfrepo_tooltip,
++ SfiProxy sfrepo,
+ BstTrackSynthDialogSelected selected_callback,
+ gpointer selected_data,
+ GxkFreeFunc selected_cleanup)
+ {
+ BstTrackSynthDialog *self = bst_track_synth_dialog_singleton ();
+ GtkWidget *widget = GTK_WIDGET (self);
+ if (!candidate_label)
+ candidate_label = "";
+ if (!wrepo_label)
+ wrepo_label = "";
++ if (!sfrepo_label)
++ sfrepo_label = "";
+
+ bst_track_synth_dialog_setup (self, NULL, NULL, 0);
+
+ g_object_set (gtk_notebook_get_tab_label (self->notebook, self->spage), "label", candidate_label, NULL);
+ gxk_widget_set_tooltip (self->tview, candidate_tooltip);
+ g_object_set (gtk_notebook_get_tab_label (self->notebook, self->wpage), "label", wrepo_label, NULL);
+ gxk_widget_set_tooltip (BST_ITEM_VIEW (self->wpage)->tree, wrepo_tooltip);
++ g_object_set (gtk_notebook_get_tab_label (self->notebook, self->sfont_page), "label", sfrepo_label, NULL);
++ gxk_widget_set_tooltip (BST_ITEM_VIEW (self->sfont_page)->tree, sfrepo_tooltip);
+
- bst_track_synth_dialog_set (self, candidates, wrepo);
++ bst_track_synth_dialog_set (self, candidates, wrepo, sfrepo);
+ bst_track_synth_dialog_setup (self, parent_widget,
+ /* TRANSLATORS: this is a dialog title and %s is replaced by an object name
*/
+ _("Synthesizer Selection: %s"),
+ track);
+
+ self->selected_callback = selected_callback;
+ self->selected_data = selected_data;
+ self->selected_cleanup = selected_cleanup;
+ gxk_widget_showraise (widget);
+
+ return widget;
+ }
+
+ void
+ bst_track_synth_dialog_set (BstTrackSynthDialog *self,
+ BseItemSeq *iseq,
- SfiProxy wrepo)
++ SfiProxy wrepo,
++ SfiProxy sfrepo)
+ {
+ g_return_if_fail (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
+ bst_track_synth_dialog_activate (BstTrackSynthDialog *self)
+ {
+ SfiProxy proxy = 0;
+
+ if (self->ignore_activate)
+ return;
+
+ if (self->tview && gxk_widget_viewable (GTK_WIDGET (self->tview)))
+ {
+ GtkTreeIter siter;
+ GtkTreeModel *smodel;
+ if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (self->tview), &smodel, &siter))
+ {
+ GtkTreeIter piter;
+ if (GTK_IS_TREE_MODEL_SORT (smodel))
+ gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (smodel), &piter, &siter);
+ else
+ piter = siter;
+ proxy = bst_item_seq_store_get_from_iter (self->pstore, &piter);
+ }
+ }
- else if (self->wpage)
- proxy = bst_item_view_get_current (BST_ITEM_VIEW (self->wpage));
++ else if (self->wpage && gxk_widget_viewable (GTK_WIDGET (self->wpage)))
++ {
++ proxy = bst_item_view_get_current (BST_ITEM_VIEW (self->wpage));
++ }
++ else if (self->sfont_page && gxk_widget_viewable (GTK_WIDGET (self->sfont_page)))
++ {
++ proxy = bst_sound_font_view_get_preset (BST_SOUND_FONT_VIEW (self->sfont_page));
++ }
+
+ /* ignore_activate guards against multiple clicks */
+ self->ignore_activate = TRUE;
+ /* notify and done */
+ BstTrackSynthDialogSelected selected_callback = self->selected_callback;
+ GxkFreeFunc selected_cleanup = self->selected_cleanup;
+ gpointer selected_data = self->selected_data;
+ self->selected_callback = NULL;
+ self->selected_cleanup = NULL;
+ if (selected_callback)
+ selected_callback (selected_data, proxy, self);
+ if (selected_cleanup)
+ selected_cleanup (selected_data);
+ gxk_toplevel_delete (GTK_WIDGET (self));
+ }
diff --cc beast-gtk/bsttracksynthdialog.hh
index 0000000,df50a4f..90cbe68
mode 000000,100644..100644
--- a/beast-gtk/bsttracksynthdialog.hh
+++ b/beast-gtk/bsttracksynthdialog.hh
@@@ -1,0 -1,68 +1,73 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BST_TRACK_SYNTH_DIALOG_H__
+ #define __BST_TRACK_SYNTH_DIALOG_H__
+
+ #include "bstutils.hh"
+ #include "bstwaveview.hh"
++#include "bstsoundfontview.h"
+
+ G_BEGIN_DECLS
+
+
+ /* --- Gtk+ type macros --- */
+ #define BST_TYPE_TRACK_SYNTH_DIALOG (bst_track_synth_dialog_get_type ())
+ #define BST_TRACK_SYNTH_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object),
BST_TYPE_TRACK_SYNTH_DIALOG, BstTrackSynthDialog))
+ #define BST_TRACK_SYNTH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
BST_TYPE_TRACK_SYNTH_DIALOG, BstTrackSynthDialogClass))
+ #define BST_IS_TRACK_SYNTH_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object),
BST_TYPE_TRACK_SYNTH_DIALOG))
+ #define BST_IS_TRACK_SYNTH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
BST_TYPE_TRACK_SYNTH_DIALOG))
+ #define BST_TRACK_SYNTH_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
BST_TYPE_TRACK_SYNTH_DIALOG, BstTrackSynthDialogClass))
+
+
+ /* --- structures & typedefs --- */
+ typedef struct _BstTrackSynthDialog BstTrackSynthDialog;
+ typedef struct _BstTrackSynthDialogClass BstTrackSynthDialogClass;
+ typedef void (*BstTrackSynthDialogSelected) (gpointer data,
+ SfiProxy proxy,
+ BstTrackSynthDialog *tsdialog);
+ struct _BstTrackSynthDialog
+ {
+ GxkDialog parent_instance;
+ GtkNotebook *notebook;
+ GtkWidget *wpage; /* wave repo item view */
+ GtkWidget *spage; /* synth list */
++ GtkWidget *sfont_page; /* sound font patch selection */
+ GtkWidget *ok; /* ok button */
+ GtkWindow *parent_window;
+ guint ignore_activate : 1;
+ GtkTreeModel *pstore; /* proxy store */
+ GtkTreeView *tview; /* synth selection tree view */
+ BstTrackSynthDialogSelected selected_callback;
+ gpointer selected_data;
+ GxkFreeFunc selected_cleanup;
+ };
+ struct _BstTrackSynthDialogClass
+ {
+ GxkDialogClass parent_class;
+ };
+
+
+ /* --- prototypes --- */
+ GType bst_track_synth_dialog_get_type (void);
+ GtkWidget* bst_track_synth_dialog_popup (gpointer parent_widget,
+ SfiProxy track,
+ const gchar *candidate_label,
+ const gchar *candidate_tooltip,
+ BseItemSeq *candidates,
+ const gchar *wrepo_label,
+ const gchar *wrepo_tooltip,
+ SfiProxy wrepo,
++ const gchar *sfrepo_label,
++ const gchar *sfrepo_tooltip,
++ SfiProxy sfrepo,
+ BstTrackSynthDialogSelected selected_callback,
+ gpointer selected_data,
+ GxkFreeFunc selected_cleanup);
+ void bst_track_synth_dialog_set (BstTrackSynthDialog *self,
+ BseItemSeq *iseq,
- SfiProxy wrepo);
-
++ SfiProxy wrepo,
++ SfiProxy sfrepo);
+
+
+ G_END_DECLS
+
+ #endif /* __BST_TRACK_SYNTH_DIALOG_H__ */
diff --cc beast-gtk/bsttrackview.cc
index 0000000,60bcc5a..fa94ea0
mode 000000,100644..100644
--- a/beast-gtk/bsttrackview.cc
+++ b/beast-gtk/bsttrackview.cc
@@@ -1,0 -1,759 +1,777 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bsttrackview.hh"
+ #include "bstparam.hh"
+ #include "bstgrowbar.hh"
+ #include "bsttracksynthdialog.hh"
+ #include "bstitemseqdialog.hh"
+ #include <stdlib.h> /* strtol */
+ #include <string.h>
+
+ #define SCROLLBAR_SPACING (3) /* from gtkscrolledwindow.c:DEFAULT_SCROLLBAR_SPACING */
+
+ /* --- prototypes --- */
+ static void bst_track_view_finalize (GObject *object);
+ static gboolean track_view_action_check (gpointer data,
+ size_t action,
+ guint64 action_stamp);
+ static void track_view_action_exec (gpointer data,
+ size_t action);
+ static void track_view_set_container (BstItemView *self,
+ SfiProxy new_container);
+ static void track_view_listen_on (BstItemView *iview,
+ SfiProxy item);
+ static void track_view_unlisten_on (BstItemView *iview,
+ SfiProxy item);
+
+
+ /* --- columns --- */
+ enum {
+ COL_SEQID,
+ COL_NAME,
+ COL_MUTE,
+ COL_VOICES,
+ COL_SYNTH,
+ COL_MIDI_CHANNEL,
+ COL_OUTPUTS,
+ COL_POST_SYNTH,
+ COL_BLURB,
+ N_COLS
+ };
+
+
+ /* --- track actions --- */
+ enum {
+ ACTION_ADD_TRACK,
+ ACTION_DELETE_TRACK
+ };
+ static const GxkStockAction track_view_actions[] = {
+ { N_("Add"), NULL, N_("Add a new track to this song"),
+ ACTION_ADD_TRACK, BST_STOCK_TRACKS_ADD,
+ },
+ { N_("Delete"), NULL, N_("Delete the currently selected track"),
+ ACTION_DELETE_TRACK, BST_STOCK_TRASHCAN,
+ },
+ };
+
+
+ /* --- functions --- */
+ G_DEFINE_TYPE (BstTrackView, bst_track_view, BST_TYPE_ITEM_VIEW);
+
+ static void
+ bst_track_view_class_init (BstTrackViewClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ BstItemViewClass *item_view_class = BST_ITEM_VIEW_CLASS (klass);
+
+ gobject_class->finalize = bst_track_view_finalize;
+
+ item_view_class->set_container = track_view_set_container;
+ item_view_class->listen_on = track_view_listen_on;
+ item_view_class->unlisten_on = track_view_unlisten_on;
+
+ item_view_class->item_type = "BseTrack";
+ }
+
+ static void
+ bst_track_view_finalize (GObject *object)
+ {
+ BstTrackView *self = BST_TRACK_VIEW (object);
+
+ if (self->tctrl)
+ bst_track_roll_controller_unref (self->tctrl);
+
+ G_OBJECT_CLASS (bst_track_view_parent_class)->finalize (object);
+ }
+
+ GtkWidget*
+ bst_track_view_new (SfiProxy song)
+ {
+ GtkWidget *track_view;
+
+ g_return_val_if_fail (BSE_IS_SONG (song), NULL);
+
+ track_view = gtk_widget_new (BST_TYPE_TRACK_VIEW, NULL);
+ bst_item_view_set_container (BST_ITEM_VIEW (track_view), song);
+
+ return track_view;
+ }
+
+ static void
+ track_view_hzoom_changed (BstTrackView *self,
+ GtkAdjustment *adjustment)
+ {
+ if (self->troll)
+ bst_track_roll_set_hzoom (self->troll, adjustment->value);
+ }
+
+ static void
+ track_view_fill_value (BstItemView *iview,
+ guint column,
+ guint row,
+ GValue *value)
+ {
+ BstTrackView *self = BST_TRACK_VIEW (iview);
+ guint seqid = row + 1;
+ SfiProxy item = bse_container_get_item (iview->container, BST_ITEM_VIEW_GET_CLASS (self)->item_type,
seqid);
+ if (!item)
+ return; // item is probably already destructed
+ switch (column)
+ {
+ const gchar *string;
+ gboolean vbool;
+ SfiInt vint;
- SfiProxy snet, wave;
++ SfiProxy snet, wave, sound_font_preset;
+ BseItemSeq *iseq;
+ SfiSeq *seq;
+ case COL_SEQID:
+ sfi_value_take_string (value, g_strdup_format ("%03d", seqid));
+ break;
+ case COL_NAME:
+ g_value_set_string (value, bse_item_get_name (item));
+ break;
+ case COL_MUTE:
+ bse_proxy_get (item, "muted", &vbool, NULL);
+ g_value_set_boolean (value, !vbool);
+ break;
+ case COL_VOICES:
+ bse_proxy_get (item, "n_voices", &vint, NULL);
+ sfi_value_take_string (value, g_strdup_format ("%2d", vint));
+ break;
+ case COL_SYNTH:
+ snet = 0;
- bse_proxy_get (item, "snet", &snet, "wave", &wave, NULL);
- g_value_set_string (value, snet || wave ? bse_item_get_name (snet ? snet : wave) : "");
++ wave = 0;
++ sound_font_preset = 0;
++ bse_proxy_get (item, "snet", &snet, "wave", &wave, "sound_font_preset", &sound_font_preset, NULL);
++ if (snet)
++ string = bse_item_get_name (snet);
++ else if (wave)
++ string = bse_item_get_name (wave);
++ else if (sound_font_preset)
++ string = bse_item_get_name (sound_font_preset);
++ else
++ string = "";
++ g_value_set_string (value, string);
+ break;
+ case COL_MIDI_CHANNEL:
+ bse_proxy_get (item, "midi-channel", &vint, NULL);
+ sfi_value_take_string (value, g_strdup_format ("%2d", vint));
+ break;
+ case COL_OUTPUTS:
+ bse_proxy_get (item, "outputs", &seq, NULL);
+ iseq = bse_item_seq_from_seq (seq);
+ if (iseq && iseq->n_items == 1)
+ g_value_take_string (value, g_strdup_format ("%s", bse_item_get_name_or_type (iseq->items[0])));
+ else if (iseq && iseq->n_items > 1)
+ g_value_take_string (value, g_strdup_format ("#%u", iseq ? iseq->n_items : 0));
+ else
+ g_value_set_string (value, "");
+ bse_item_seq_free (iseq);
+ break;
+ case COL_POST_SYNTH:
+ snet = 0;
+ bse_proxy_get (item, "pnet", &snet, NULL);
+ g_value_set_string (value, snet ? bse_item_get_name (snet) : "");
+ break;
+ case COL_BLURB:
+ bse_proxy_get (item, "blurb", &string, NULL);
+ g_value_set_string (value, string ? string : "");
+ break;
+ }
+ }
+
+ static void
+ track_view_synth_edited (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (text)
+ {
+ SfiProxy proxy = 0;
+ GSList *slist = NULL;
- /* list possible snet/wave candidates */
++ /* list possible snet/wave/sound_font_preset candidates */
+ BsePropertyCandidates *pc = bse_item_get_property_candidates (item, "snet");
+ slist = g_slist_append (slist, pc->items);
+ pc = bse_item_get_property_candidates (item, "wave");
+ slist = g_slist_append (slist, pc->items);
++ pc = bse_item_get_property_candidates (item, "sound_font_preset");
++ slist = g_slist_append (slist, pc->items);
+ /* find best match */
+ proxy = bst_item_seq_list_match (slist, text);
+ g_slist_free (slist);
+ if (proxy && BSE_IS_SNET (proxy))
+ bse_proxy_set (item, "snet", proxy, NULL);
+ else if (proxy && BSE_IS_WAVE (proxy))
+ bse_proxy_set (item, "wave", proxy, NULL);
++ else if (proxy && BSE_IS_SOUND_FONT_PRESET (proxy))
++ bse_proxy_set (item, "sound_font_preset", proxy, NULL);
+ else
- bse_proxy_set (item, "snet", 0, "wave", 0, NULL);
++ bse_proxy_set (item, "snet", 0, "wave", 0, "sound_font_preset", 0, NULL);
+ }
+ else
- bse_proxy_set (item, "snet", 0, "wave", 0, NULL);
++ bse_proxy_set (item, "snet", 0, "wave", 0, "sound_font_preset", 0, NULL);
+ }
+ }
+
+ static void
+ track_view_post_synth_edited (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (text)
+ {
+ SfiProxy proxy = 0;
+ GSList *slist = NULL;
+ /* list possible snet candidates */
+ BsePropertyCandidates *pc = bse_item_get_property_candidates (item, "pnet");
+ slist = g_slist_append (slist, pc->items);
+ /* find best match */
+ proxy = bst_item_seq_list_match (slist, text);
+ g_slist_free (slist);
+ if (proxy && BSE_IS_SNET (proxy))
+ bse_proxy_set (item, "pnet", proxy, NULL);
+ else
+ bse_proxy_set (item, "pnet", 0, NULL);
+ }
+ else
+ bse_proxy_set (item, "pnet", 0, NULL);
+ }
+ }
+
+ typedef struct {
+ BstTrackView *self;
+ GxkCellRendererPopup *pcell;
+ } SynthPopup;
+
+ static void
+ track_view_synth_popup_cleanup (gpointer data)
+ {
+ SynthPopup *sdata = (SynthPopup*) data;
+ gxk_cell_renderer_popup_change (sdata->pcell, NULL, FALSE, TRUE);
+ g_free (sdata);
+ }
+
+ static void
+ track_view_synth_popup_cb (gpointer data,
+ SfiProxy proxy,
+ BstTrackSynthDialog *tsdialog)
+ {
+ SynthPopup *sdata = (SynthPopup*) data;
+ gxk_cell_renderer_popup_change (sdata->pcell,
+ proxy ? bse_item_get_uname_path (proxy) : "",
+ FALSE,
+ proxy == 0);
+ }
+
+ static void
+ track_view_synth_popup (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text,
+ GxkCellRendererPopup *pcell)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (bse_item_editable_property (item, "snet"))
+ {
+ BsePropertyCandidates *pc = bse_item_get_property_candidates (item, "snet");
+ SynthPopup sdata = { self, pcell, };
+ GtkWidget *dialog = bst_track_synth_dialog_popup (self, item,
+ pc->label, pc->tooltip, pc->items,
+ _("Available Waves"),
+ _("List of available waves to choose a track
instrument from"),
+ bse_project_get_wave_repo (bse_item_get_project
(item)),
++ _("Available Sound Fonts"),
++ _("List of available sound fonts to choose track
instrument from"),
++ bse_project_get_sound_font_repo
(bse_item_get_project (item)),
+ track_view_synth_popup_cb, g_memdup (&sdata,
sizeof (sdata)), track_view_synth_popup_cleanup);
+ gxk_cell_renderer_popup_dialog (pcell, dialog);
+ }
+ else
+ bst_gui_error_bell (self);
+ }
+ }
+
+ static void
+ track_view_post_synth_popup (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text,
+ GxkCellRendererPopup *pcell)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (bse_item_editable_property (item, "pnet"))
+ {
+ BsePropertyCandidates *pc = bse_item_get_property_candidates (item, "pnet");
+ SynthPopup sdata = { self, pcell, };
+ GtkWidget *dialog = bst_track_synth_dialog_popup (self, item,
+ pc->label, pc->tooltip, pc->items,
+ NULL, NULL, 0,
++ NULL, NULL, 0,
+ track_view_synth_popup_cb, g_memdup (&sdata,
sizeof (sdata)), track_view_synth_popup_cleanup);
+ gxk_cell_renderer_popup_dialog (pcell, dialog);
+ }
+ else
+ bst_gui_error_bell (self);
+ }
+ }
+
+ typedef struct {
+ BstTrackView *self;
+ GxkCellRendererPopup *pcell;
+ SfiProxy item;
+ } OutputsPopup;
+
+ static void
+ track_view_outputs_cleanup (gpointer data)
+ {
+ OutputsPopup *odata = (OutputsPopup*) data;
+ gxk_cell_renderer_popup_change (odata->pcell, NULL, FALSE, FALSE);
+ g_free (odata);
+ }
+
+ static void
+ track_view_outputs_changed (gpointer data,
+ BseItemSeq *iseq,
+ BstItemSeqDialog *isdialog)
+ {
+ OutputsPopup *odata = (OutputsPopup*) data;
+ gxk_cell_renderer_popup_change (odata->pcell, NULL, FALSE, FALSE);
+ SfiSeq *seq = bse_item_seq_to_seq (iseq);
+ GValue *value = sfi_value_seq (seq);
+ sfi_seq_unref (seq);
+ bse_proxy_set_property (odata->item, "outputs", value);
+ sfi_value_free (value);
+ }
+
+ static void
+ track_view_outputs_popup (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text,
+ GxkCellRendererPopup *pcell)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ BsePropertyCandidates *pc = bse_item_get_property_candidates (item, "outputs");
+ GParamSpec *pspec = bse_proxy_get_pspec (item, "outputs");
+ const GValue *value = bse_proxy_get_property (item, "outputs");
+ SfiSeq *seq = (SfiSeq*) g_value_get_boxed (value);
+ BseItemSeq *iseq = bse_item_seq_from_seq (seq);
+ OutputsPopup odata = { self, pcell, item };
+ GtkWidget *dialog = bst_item_seq_dialog_popup (self, item,
+ pc->label, pc->tooltip, pc->items,
+ g_param_spec_get_nick (pspec), g_param_spec_get_blurb
(pspec), iseq,
+ track_view_outputs_changed, g_memdup (&odata, sizeof
(odata)), track_view_outputs_cleanup);
+ bse_item_seq_free (iseq);
+ gxk_cell_renderer_popup_dialog (pcell, dialog);
+ }
+ }
+
+ static void
+ track_view_mute_toggled (BstTrackView *self,
+ const gchar *strpath,
+ GtkCellRendererToggle *tcell)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (item)
+ {
+ gboolean muted;
+ bse_proxy_get (item, "muted", &muted, NULL);
+ bse_proxy_set (item, "muted", !muted, NULL);
+ bse_proxy_get (item, "muted", &muted, NULL);
+ gtk_cell_renderer_toggle_set_active (tcell, !muted);
+ }
+ }
+ }
+
+ static void
+ track_view_voice_edited (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (item)
+ {
+ int i = strtol (text, NULL, 10);
+ if (i > 0)
+ bse_proxy_set (item, "n_voices", i, NULL);
+ }
+ }
+ }
+
+ static void
+ track_view_midi_channel_edited (BstTrackView *self,
+ const gchar *strpath,
+ const gchar *text)
+ {
+ g_return_if_fail (BST_IS_TRACK_VIEW (self));
+
+ if (strpath)
+ {
+ gint row = gxk_tree_spath_index0 (strpath);
+ SfiProxy item = bst_item_view_get_proxy (BST_ITEM_VIEW (self), row);
+ if (item)
+ {
+ int i = strtol (text, NULL, 10);
+ if (i >= 0)
+ bse_proxy_set (item, "midi-channel", i, NULL);
+ }
+ }
+ }
+
+ static SfiProxy
+ get_track (gpointer data,
+ gint row)
+ {
+ return bst_item_view_get_proxy (BST_ITEM_VIEW (data), row);
+ }
+
+ static void
+ track_view_marks_changed (BstTrackView *self)
+ {
+ SfiProxy song = BST_ITEM_VIEW (self)->container;
+ if (self->troll && song)
+ {
+ SfiInt lleft, lright, pointer;
+ bse_proxy_get (song, "loop_left", &lleft, "loop_right", &lright, "tick_pointer", &pointer, NULL);
+ bst_track_roll_set_marker (self->troll, 1, lleft, lleft >= 0 ? BST_TRACK_ROLL_MARKER_LOOP :
BST_TRACK_ROLL_MARKER_NONE);
+ bst_track_roll_set_marker (self->troll, 2, lright, lright >= 0 ? BST_TRACK_ROLL_MARKER_LOOP :
BST_TRACK_ROLL_MARKER_NONE);
+ bst_track_roll_set_marker (self->troll, 3, pointer, pointer >= 0 ? BST_TRACK_ROLL_MARKER_POS :
BST_TRACK_ROLL_MARKER_NONE);
+ }
+ }
+
+ static void
+ track_view_repeat_toggled (BstTrackView *self)
+ {
+ SfiProxy song = BST_ITEM_VIEW (self)->container;
+ if (song && self->repeat_toggle)
+ bse_proxy_set (song, "loop_enabled", GTK_TOGGLE_BUTTON (self->repeat_toggle)->active, NULL);
+ }
+
+ static void
+ track_view_repeat_changed (BstTrackView *self)
+ {
+ SfiProxy song = BST_ITEM_VIEW (self)->container;
+ if (song && self->repeat_toggle)
+ {
+ GtkToggleButton *toggle = GTK_TOGGLE_BUTTON (self->repeat_toggle);
+ gboolean enabled;
+ bse_proxy_get (song, "loop_enabled", &enabled, NULL);
+ if (toggle->active != enabled)
+ gtk_toggle_button_set_active (toggle, enabled);
+ }
+ }
+
+ static void
+ bst_track_view_init (BstTrackView *self)
+ {
+ BstItemView *iview = BST_ITEM_VIEW (self);
+ GtkWidget *treehs, *trackgb, *vscroll;
+ GtkObject *adjustment;
+ GtkTreeView *tview;
+ GtkTreeSelection *tsel;
+ GtkTreeModel *smodel;
+ GxkListWrapper *lwrapper;
+ GxkRadget *radget;
+
+ /* create GUI */
+ gxk_widget_publish_actions (self, "track-view-actions",
+ G_N_ELEMENTS (track_view_actions), track_view_actions,
+ NULL, track_view_action_check, track_view_action_exec);
+ radget = gxk_radget_complete (GTK_WIDGET (self), "beast", "track-view", NULL);
+
+ /* item list model */
+ lwrapper = gxk_list_wrapper_new (N_COLS,
+ G_TYPE_STRING, /* COL_SEQID */
+ G_TYPE_STRING, /* COL_NAME */
+ G_TYPE_BOOLEAN, /* COL_MUTE */
+ G_TYPE_STRING, /* COL_VOICES */
+ G_TYPE_STRING, /* COL_SYNTH */
+ G_TYPE_STRING, /* COL_MIDI_CHANNEL */
+ G_TYPE_STRING, /* COL_OUTPUTS */
+ G_TYPE_STRING, /* COL_POST_SYNTH */
+ G_TYPE_STRING /* COL_BLURB */
+ );
+ smodel = bst_item_view_adapt_list_wrapper (iview, lwrapper);
+ g_signal_connect_object (lwrapper, "fill-value",
+ G_CALLBACK (track_view_fill_value),
+ iview, G_CONNECT_SWAPPED);
+ g_object_unref (lwrapper);
+
+ /* scrollbars */
+ treehs = (GtkWidget*) gxk_radget_find (radget, "tree-hscrollbar");
+ trackgb = (GtkWidget*) gxk_radget_find (radget, "track-hgrow-bar");
+ vscroll = (GtkWidget*) gxk_radget_find (radget, "tree-vscrollbar");
+
+ /* tree view (track list) */
+ tview = (GtkTreeView*) gxk_radget_find (radget, "tree-view");
+ gtk_tree_view_set_model (tview, smodel);
+ bst_item_view_set_tree (iview, tview);
+ gtk_tree_view_set_hadjustment (iview->tree, gtk_range_get_adjustment (GTK_RANGE (treehs)));
+ gtk_tree_view_set_vadjustment (iview->tree, gtk_range_get_adjustment (GTK_RANGE (vscroll)));
+ tsel = gtk_tree_view_get_selection (iview->tree);
+ gtk_tree_selection_set_mode (tsel, GTK_SELECTION_BROWSE);
+ gxk_tree_selection_force_browse (tsel, smodel);
+ g_object_unref (smodel);
+
+ /* track roll */
+ self->troll = (BstTrackRoll*) g_object_new (BST_TYPE_TRACK_ROLL,
+ "visible", TRUE,
+ "parent", gxk_radget_find (radget, "track-area"),
+ NULL);
+ gxk_nullify_in_object (self, &self->troll);
+ gxk_scroll_canvas_set_hadjustment (GXK_SCROLL_CANVAS (self->troll), bst_grow_bar_get_adjustment
(BST_GROW_BAR (trackgb)));
+ gxk_scroll_canvas_set_vadjustment (GXK_SCROLL_CANVAS (self->troll), gtk_range_get_adjustment (GTK_RANGE
(vscroll)));
+ bst_track_roll_set_track_callback (self->troll, self, get_track);
+ track_view_marks_changed (self);
+
+ /* link track roll to tree view and list model */
+ g_signal_connect_object (tsel, "changed",
+ G_CALLBACK (bst_track_roll_reselect),
+ self->troll, G_CONNECT_SWAPPED | G_CONNECT_AFTER);
+ g_signal_connect_object (self->troll, "select-row",
+ G_CALLBACK (gxk_tree_view_focus_row),
+ iview->tree, G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->troll, "select-row",
+ G_CALLBACK (gtk_widget_grab_focus),
+ iview->tree, G_CONNECT_SWAPPED);
+ g_signal_connect_object (iview->wlist, "row-change",
+ G_CALLBACK (bst_track_roll_abort_edit),
+ self->troll, G_CONNECT_SWAPPED);
+
+ /* track roll controller */
+ self->tctrl = bst_track_roll_controller_new (self->troll);
+ bst_track_roll_controller_set_song (self->tctrl, iview->container);
+ gxk_widget_publish_action_list (self, "tctrl-canvas-tools", bst_track_roll_controller_canvas_actions
(self->tctrl));
+ gxk_widget_publish_action_list (self, "tctrl-hpanel-tools", bst_track_roll_controller_hpanel_actions
(self->tctrl));
+ gxk_widget_publish_action_list (self, "tctrl-quant-tools", bst_track_roll_controller_quant_actions
(self->tctrl));
+
+ /* add repeat toggle */
+ self->repeat_toggle = (GtkWidget*) gxk_radget_find (radget, "repeat-toggle");
+ gxk_nullify_in_object (self, &self->repeat_toggle);
+ g_object_connect (self->repeat_toggle, "swapped_signal::toggled", track_view_repeat_toggled, self, NULL);
+ track_view_repeat_changed (self);
+
+ /* add zoom spinner */
+ adjustment = gtk_adjustment_new (50, 1, 100, 1, 5, 0);
+ g_object_connect (adjustment,
+ "swapped_signal_after::value_changed", track_view_hzoom_changed, self,
+ NULL);
+ gxk_radget_add (self, "hzoom-area",
+ g_object_new (GTK_TYPE_SPIN_BUTTON,
+ "visible", TRUE,
+ "adjustment", adjustment,
+ "digits", 0,
+ "width_request", 2 * gxk_size_width (GXK_ICON_SIZE_TOOLBAR),
+ NULL));
+
+ /* add list view columns */
+ if (BST_DVL_HINTS)
+ gxk_tree_view_add_text_column (iview->tree, COL_SEQID, "S",
+ 0.0, "ID", NULL,
+ NULL, NULL, GConnectFlags (0));
+ gxk_tree_view_add_text_column (iview->tree, COL_NAME, "S",
+ 0.0, _("Name"), NULL,
+ (void*) bst_item_view_name_edited, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_toggle_column (iview->tree, COL_MUTE, "",
+ 0.5, "M", _("Notes from unchecked tracks are ignored by the sequencer
during playback"),
+ (void*) track_view_mute_toggled, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (iview->tree, COL_VOICES, "",
+ 0.5, "V", _("Maximum number of voices for simultaneous playback"),
+ (void*) track_view_voice_edited, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_popup_column (iview->tree, COL_SYNTH, "#",
+ 0.5, "Synth", _("Synthesis network or wave to be used as instrument by this
track"),
+ (void*) track_view_synth_edited, (void*) track_view_synth_popup, self,
G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (iview->tree, COL_MIDI_CHANNEL, "",
+ 0.5, "Ch", _("Midi channel assigned to this track, 0 uses private
per-track channel"),
+ (void*) track_view_midi_channel_edited, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_popup_column (iview->tree, COL_OUTPUTS, "#",
+ 0.5, "Outputs", _("Mixer busses connected to track output"),
+ NULL, (void*) track_view_outputs_popup, self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_popup_column (iview->tree, COL_POST_SYNTH, "",
+ 0.5, "Post", _("Synthesis network to be used as postprocessor"),
+ (void*) track_view_post_synth_edited, (void*) track_view_post_synth_popup,
self, G_CONNECT_SWAPPED);
+ gxk_tree_view_add_text_column (iview->tree, COL_BLURB, "",
+ 0.0, _("Comment"), NULL,
+ (void*) bst_item_view_blurb_edited, self, G_CONNECT_SWAPPED);
+ }
+
+ static void
+ track_changed (SfiProxy track,
+ BstTrackView *self)
+ {
+ if (self->troll)
+ {
+ gint row = bst_item_view_get_proxy_row (BST_ITEM_VIEW (self), track);
+ bst_track_roll_queue_row_change (self->troll, row);
+ }
+ }
+
+ static void
+ track_view_pointer_changed (BstTrackView *self,
+ SfiInt position)
+ {
+ if (self->troll)
+ bst_track_roll_set_marker (self->troll, 3, position, position >= 0 ? BST_TRACK_ROLL_MARKER_POS :
BST_TRACK_ROLL_MARKER_NONE);
+ }
+
+ static void
+ track_view_set_container (BstItemView *iview,
+ SfiProxy new_container)
+ {
+ BstTrackView *self = BST_TRACK_VIEW (iview);
+ if (BSE_IS_SONG (iview->container))
+ bse_proxy_disconnect (iview->container,
+ "any_signal", track_view_pointer_changed, self,
+ "any_signal", track_view_marks_changed, self,
+ "any_signal", track_view_repeat_changed, self,
+ NULL);
+ BST_ITEM_VIEW_CLASS (bst_track_view_parent_class)->set_container (iview, new_container);
+ if (self->troll)
+ bst_track_roll_setup (self->troll, iview->container ? iview->tree : NULL, iview->container);
+ if (BSE_IS_SONG (iview->container))
+ {
+ bst_track_roll_controller_set_song (self->tctrl, iview->container);
+ bse_proxy_connect (iview->container,
+ "swapped_signal::pointer-changed", track_view_pointer_changed, self,
+ "swapped_signal::property-notify::loop-left", track_view_marks_changed, self,
+ "swapped_signal::property-notify::loop-right", track_view_marks_changed, self,
+ "swapped_signal::property-notify::tick-pointer", track_view_marks_changed, self,
+ "swapped_signal::property-notify::loop-enabled", track_view_repeat_changed, self,
+ NULL);
+ track_view_marks_changed (self);
+ track_view_repeat_changed (self);
+ }
+ }
+
+ static void
+ track_property_changed (SfiProxy item,
+ const gchar *property_name,
+ BstItemView *iview)
+ {
+ bst_item_view_refresh (iview, item);
+ }
+
+ static void
+ track_view_listen_on (BstItemView *iview,
+ SfiProxy item)
+ {
+ BST_ITEM_VIEW_CLASS (bst_track_view_parent_class)->listen_on (iview, item);
+ bse_proxy_connect (item,
+ "signal::changed", track_changed, iview,
+ NULL);
+ bse_proxy_connect (item,
+ /* COL_SEQID handled by GxkListWrapper */
+ /* COL_NAME handled by GxkListWrapper */
+ "signal::property-notify::muted", track_property_changed, iview, /* COL_MUTE */
+ "signal::property-notify::n-voices", track_property_changed, iview, /* COL_VOICES */
+ "signal::property-notify::snet", track_property_changed, iview, /* COL_SYNTH */
+ "signal::property-notify::midi-channel", track_property_changed, iview, /*
COL_MIDI_CHANNEL */
+ "signal::property-notify::outputs", track_property_changed, iview, /* COL_OUTPUTS */
+ "signal::property-notify::pnet", track_property_changed, iview, /* COL_POST_SYNTH */
+ /* COL_BLURB handled by GxkListWrapper */
+ NULL);
+ }
+
+ static void
+ track_view_unlisten_on (BstItemView *iview,
+ SfiProxy item)
+ {
+ bse_proxy_disconnect (item,
+ "any_signal", track_changed, iview,
+ "any_signal", track_property_changed, iview,
+ NULL);
+ BST_ITEM_VIEW_CLASS (bst_track_view_parent_class)->unlisten_on (iview, item);
+ }
+
+ static void
+ track_view_action_exec (gpointer data,
+ size_t action)
+ {
+ BstTrackView *self = BST_TRACK_VIEW (data);
+ BstItemView *item_view = BST_ITEM_VIEW (self);
+ SfiProxy song = item_view->container;
+
+ switch (action)
+ {
+ SfiProxy item;
+ guint i;
+ case ACTION_ADD_TRACK:
+ bse_item_group_undo (song, "Add Track");
+ item = bse_song_create_track (song);
+ if (item)
+ {
+ gchar *string = g_strdup_format ("Track-%02X", bse_item_get_seqid (item));
+ bse_item_set_name (item, string);
+ g_free (string);
+ bst_item_view_select (item_view, item);
+ bse_track_ensure_output (item);
+ }
+ bse_item_ungroup_undo (song);
+ break;
+ case ACTION_DELETE_TRACK:
+ item = bst_item_view_get_current (item_view);
+ bse_item_group_undo (song, "Delete Track");
+ BseItemSeq *iseq = bse_track_list_parts_uniq (item);
+ bse_song_remove_track (song, item);
+ for (i = 0; i < iseq->n_items; i++)
+ if (!bse_song_find_any_track_for_part (song, iseq->items[i]))
+ bse_song_remove_part (song, iseq->items[i]);
+ bse_item_ungroup_undo (song);
+ break;
+ }
+ gxk_widget_update_actions_downwards (self);
+ }
+
+ static gboolean
+ track_view_action_check (gpointer data,
+ size_t action,
+ guint64 action_stamp)
+ {
+ BstTrackView *self = BST_TRACK_VIEW (data);
+ BstItemView *item_view = BST_ITEM_VIEW (self);
+
+ switch (action)
+ {
+ SfiProxy item;
+ case ACTION_ADD_TRACK:
+ return TRUE;
+ case ACTION_DELETE_TRACK:
+ item = bst_item_view_get_current (item_view);
+ return item != 0;
+ default:
+ return FALSE;
+ }
+ }
diff --cc beast-gtk/bstutils.cc
index 0000000,af7ad9d..90a1afa
mode 000000,100644..100644
--- a/beast-gtk/bstutils.cc
+++ b/beast-gtk/bstutils.cc
@@@ -1,0 -1,1512 +1,1515 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bstutils.hh"
+
+ #include "bstgconfig.hh"
+ #include "bstmenus.hh"
+ #include "bsttrackview.hh"
+ #include "bstwaveview.hh"
++#include "bstsoundfontview.h"
+ #include "bstpartview.hh"
+ #include "bstbusmixer.hh"
+ #include "bstbuseditor.hh"
+ #include "bstbusview.hh"
+ #include "bstpianoroll.hh"
+ #include "bstpatternview.hh"
+ #include "bsteventroll.hh"
+ #include "bstgrowbar.hh"
+ #include "bstdbmeter.hh"
+ #include "bstscrollgraph.hh"
++
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <string.h>
+ /* --- generated enums --- */
+ #include "bstenum_arrays.cc" /* enum string value arrays plus include directives */
+
+ /* --- prototypes --- */
+ static void _bst_init_idl (void);
+ /* --- variables --- */
+ static GtkIconFactory *stock_icon_factory = NULL;
+ Bse::ServerH bse_server;
+
+ /* --- functions --- */
+ void
+ _bst_init_utils (void)
+ {
+ g_assert (stock_icon_factory == NULL);
+ stock_icon_factory = gtk_icon_factory_new ();
+ gtk_icon_factory_add_default (stock_icon_factory);
+ /* initialize generated type ids */
+ {
+ static struct {
+ const char *type_name;
+ GType parent;
+ GType *type_id;
+ gconstpointer pointer1;
+ } builtin_info[] = {
+ #include "bstenum_list.cc" /* type entries */
+ };
+ guint i;
+ for (i = 0; i < sizeof (builtin_info) / sizeof (builtin_info[0]); i++)
+ {
+ GType type_id = 0;
+
+ if (builtin_info[i].parent == G_TYPE_ENUM)
+ type_id = g_enum_register_static (builtin_info[i].type_name, (const GEnumValue*)
builtin_info[i].pointer1);
+ else if (builtin_info[i].parent == G_TYPE_FLAGS)
+ type_id = g_flags_register_static (builtin_info[i].type_name, (const GFlagsValue*)
builtin_info[i].pointer1);
+ else
+ g_assert_not_reached ();
+ g_assert (g_type_name (type_id) != NULL);
+ *builtin_info[i].type_id = type_id;
+ }
+ }
+
+ /* initialize IDL types */
+ _bst_init_idl ();
+
+ /* initialize stock icons (included above) */
+ {
+ /* generated stock icons */
+ #include "beast-gtk/icons/bst-stock-gen.cc"
+
+ gxk_stock_register_icons (G_N_ELEMENTS (stock_icons), stock_icons);
+ }
+
+ /* initialize stock actions */
+ {
+ static const GxkStockItem stock_items[] = {
+ { BST_STOCK_CLONE, "_Clone", GTK_STOCK_COPY, },
+ { BST_STOCK_DISMISS, "_Dismiss", GTK_STOCK_CLOSE, },
+ { BST_STOCK_DEFAULT_REVERT, "_Defaults", GTK_STOCK_UNDO, },
+ { BST_STOCK_LOAD, "_Load", NULL, },
+ { BST_STOCK_OVERWRITE, "_Overwrite", GTK_STOCK_SAVE, },
+ { BST_STOCK_REVERT, "_Revert", GTK_STOCK_UNDO, },
+ };
+ gxk_stock_register_items (G_N_ELEMENTS (stock_items), stock_items);
+ }
+ }
+
+ #include "beast-gtk/dialogs/beast-xml-zfiles.cc"
+ void
+ _bst_init_radgets (void)
+ {
+ gchar *text;
+ gxk_radget_define_widget_type (BST_TYPE_TRACK_VIEW);
+ gxk_radget_define_widget_type (BST_TYPE_HGROW_BAR);
+ gxk_radget_define_widget_type (BST_TYPE_VGROW_BAR);
+ gxk_radget_define_widget_type (BST_TYPE_WAVE_VIEW);
++ gxk_radget_define_widget_type (BST_TYPE_SOUND_FONT_VIEW);
+ gxk_radget_define_widget_type (BST_TYPE_PART_VIEW);
+ gxk_radget_define_widget_type (BST_TYPE_BUS_EDITOR);
+ gxk_radget_define_widget_type (BST_TYPE_BUS_MIXER);
+ gxk_radget_define_widget_type (BST_TYPE_BUS_VIEW);
+ gxk_radget_define_widget_type (BST_TYPE_PIANO_ROLL);
+ gxk_radget_define_widget_type (BST_TYPE_EVENT_ROLL);
+ gxk_radget_define_widget_type (BST_TYPE_DB_BEAM);
+ gxk_radget_define_widget_type (BST_TYPE_DB_LABELING);
+ gxk_radget_define_widget_type (BST_TYPE_DB_METER);
+ gxk_radget_define_widget_type (BST_TYPE_SCROLLGRAPH);
+ gxk_radget_define_widget_type (BST_TYPE_PATTERN_VIEW);
+ gxk_radget_define_widget_type (BST_TYPE_ZOOMED_WINDOW);
+ text = gxk_zfile_uncompress (BST_RADGETS_STANDARD_SIZE, BST_RADGETS_STANDARD_DATA, G_N_ELEMENTS
(BST_RADGETS_STANDARD_DATA));
+ gxk_radget_parse_text ("beast", text, -1, NULL, NULL);
+ g_free (text);
+ text = gxk_zfile_uncompress (BST_RADGETS_BEAST_SIZE, BST_RADGETS_BEAST_DATA, G_N_ELEMENTS
(BST_RADGETS_BEAST_DATA));
+ gxk_radget_parse_text ("beast", text, -1, NULL, NULL);
+ g_free (text);
+ }
+
+ GtkWidget*
+ bst_stock_button (const gchar *stock_id)
+ {
+ GtkWidget *w = gtk_button_new_from_stock (stock_id);
+ gtk_widget_show_all (w);
+ return w;
+ }
+
+ GtkWidget*
+ bst_stock_dbutton (const gchar *stock_id)
+ {
+ GtkWidget *w = bst_stock_button (stock_id);
+ g_object_set (w, "can-default", TRUE, NULL);
+ return w;
+ }
+
+ GtkWidget*
+ bst_stock_icon_button (const gchar *stock_id)
+ {
+ GtkWidget *w = (GtkWidget*) g_object_new (GTK_TYPE_BUTTON,
+ "visible", TRUE,
+ "child", gtk_image_new_from_stock (stock_id, GXK_ICON_SIZE_BUTTON),
+ "can-focus", FALSE,
+ NULL);
+ gtk_widget_show_all (w);
+ return w;
+ }
+
+ void
+ bst_stock_register_icon (const gchar *stock_id,
+ guint bytes_per_pixel,
+ guint width,
+ guint height,
+ guint rowstride,
+ const guint8 *pixels)
+ {
+ g_return_if_fail (bytes_per_pixel == 3 || bytes_per_pixel == 4);
+ g_return_if_fail (width > 0 && height > 0 && rowstride >= width * bytes_per_pixel);
+
+ if (!gtk_icon_factory_lookup (stock_icon_factory, stock_id))
+ {
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data ((guchar*) g_memdup (pixels, rowstride * height),
+ GDK_COLORSPACE_RGB, bytes_per_pixel == 4,
+ 8, width, height,
+ width * bytes_per_pixel,
+ (GdkPixbufDestroyNotify) g_free, NULL);
+ GtkIconSet *iset = gtk_icon_set_new_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
+ gtk_icon_factory_add (stock_icon_factory, stock_id, iset);
+ gtk_icon_set_unref (iset);
+ }
+ }
+
+ /* --- beast/bse specific extensions --- */
+ void
+ bst_status_set_error (BseErrorType error, const std::string &message)
+ {
+ if (error)
+ gxk_status_set (GXK_STATUS_ERROR, message.c_str(), bse_error_blurb (error));
+ else
+ gxk_status_set (GXK_STATUS_DONE, message.c_str(), NULL);
+ }
+
+ void
+ bst_gui_error_bell (gpointer widget)
+ {
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (GTK_WIDGET_DRAWABLE (widget) && BST_GUI_ENABLE_ERROR_BELL)
+ {
+ #if GTK_CHECK_VERSION (2, 12, 0)
+ gdk_window_beep (GTK_WIDGET (widget)->window);
+ #else
+ gdk_beep();
+ #endif
+ }
+ }
+
+ typedef struct {
+ GtkWindow *window;
+ SfiProxy proxy;
+ gchar *title1;
+ gchar *title2;
+ } TitleSync;
+
+ static void
+ sync_title (TitleSync *tsync)
+ {
+ const gchar *name = bse_item_get_name (tsync->proxy);
+ gchar *s;
+
+ s = g_strconcat (tsync->title1, name ? name : "<NULL>", tsync->title2, NULL);
+ g_object_set (tsync->window, "title", s, NULL);
+ g_free (s);
+ }
+
+ static void
+ free_title_sync (gpointer data)
+ {
+ TitleSync *tsync = (TitleSync*) data;
+
+ bse_proxy_disconnect (tsync->proxy,
+ "any_signal", sync_title, tsync,
+ NULL);
+ g_free (tsync->title1);
+ g_free (tsync->title2);
+ g_free (tsync);
+ }
+
+ void
+ bst_window_sync_title_to_proxy (gpointer window,
+ SfiProxy proxy,
+ const gchar *title_format)
+ {
+ const char *p;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ if (proxy)
+ {
+ g_return_if_fail (BSE_IS_ITEM (proxy));
+ g_return_if_fail (title_format != NULL);
+ /* g_return_if_fail (strstr (title_format, "%s") != NULL); */
+ }
+ p = title_format ? strstr (title_format, "%s") : NULL;
+ if (proxy && p)
+ {
+ TitleSync *tsync = g_new0 (TitleSync, 1);
+ tsync->window = (GtkWindow*) window;
+ tsync->proxy = proxy;
+ tsync->title1 = g_strndup (title_format, p - title_format);
+ tsync->title2 = g_strdup (p + 2);
+ bse_proxy_connect (tsync->proxy,
+ "swapped_signal::property-notify::uname", sync_title, tsync,
+ NULL);
+ g_object_set_data_full ((GObject*) window, "bst-title-sync", tsync, free_title_sync);
+ sync_title (tsync);
+ }
+ else
+ {
+ g_object_set_data ((GObject*) window, "bst-title-sync", NULL);
+ g_object_set (window, "title", title_format, NULL);
+ }
+ }
+
+ typedef struct {
+ gboolean (*handler) (gpointer data);
+ gpointer data;
+ void (*free_func) (gpointer data);
+ } BackgroundHandler;
+
+ static SfiRing *background_handlers1 = NULL;
+ static SfiRing *background_handlers2 = NULL;
+
+ static gboolean
+ bst_background_handlers_timeout (gpointer timeout_data)
+ {
+ GDK_THREADS_ENTER();
+ if (background_handlers1 || background_handlers2)
+ {
+ gxk_status_set (GXK_STATUS_PROGRESS, _("Updating View"), NULL);
+ BackgroundHandler *bgh = (BackgroundHandler*) sfi_ring_pop_head (&background_handlers1);
+ gint prio = 1;
+ if (!bgh)
+ {
+ prio = 2;
+ bgh = (BackgroundHandler*) sfi_ring_pop_head (&background_handlers2);
+ }
+ if (bgh->handler (bgh->data))
+ {
+ if (prio == 1)
+ background_handlers1 = sfi_ring_append (background_handlers1, bgh);
+ else
+ background_handlers2 = sfi_ring_append (background_handlers2, bgh);
+ }
+ else
+ {
+ if (bgh->free_func)
+ bgh->free_func (bgh->data);
+ g_free (bgh);
+ }
+ if (background_handlers1 || background_handlers2)
+ gxk_status_set (GXK_STATUS_PROGRESS, _("Updating View"), NULL);
+ }
+ if (!background_handlers1 && !background_handlers2)
+ gxk_status_set (100, _("Updating View"), NULL); /* done */
+ GDK_THREADS_LEAVE();
+ /* re-queue instead of returning TRUE to start a new delay cycle */
+ if (background_handlers1 || background_handlers2)
+ g_timeout_add_full (G_PRIORITY_LOW - 100,
+ 30, /* milliseconds */
+ bst_background_handlers_timeout, NULL, NULL);
+ return FALSE;
+ }
+
+ static void
+ bst_background_handler_add (gboolean (*handler) (gpointer data),
+ gpointer data,
+ void (*free_func) (gpointer data),
+ gint prio)
+ {
+ g_return_if_fail (handler != NULL);
+ BackgroundHandler *bgh = g_new0 (BackgroundHandler, 1);
+ bgh->handler = handler;
+ bgh->data = data;
+ bgh->free_func = free_func;
+ if (!background_handlers1 && !background_handlers2)
+ g_timeout_add_full (G_PRIORITY_LOW - 100,
+ 20, /* milliseconds */
+ bst_background_handlers_timeout, NULL, NULL);
+ if (prio == 1)
+ background_handlers1 = sfi_ring_append (background_handlers1, bgh);
+ else
+ background_handlers2 = sfi_ring_append (background_handlers2, bgh);
+ }
+
+ void
+ bst_background_handler1_add (gboolean (*handler) (gpointer data),
+ gpointer data,
+ void (*free_func) (gpointer data))
+ {
+ bst_background_handler_add (handler, data, free_func, 1);
+ }
+
+ void
+ bst_background_handler2_add (gboolean (*handler) (gpointer data),
+ gpointer data,
+ void (*free_func) (gpointer data))
+ {
+ bst_background_handler_add (handler, data, free_func, 2);
+ }
+
+ /* --- packing utilities --- */
+ #define SPACING 3
+ static void
+ bst_util_pack (GtkWidget *widget,
+ const gchar *location,
+ guint spacing,
+ va_list args)
+ {
+ GtkBox *box = GTK_BOX (widget);
+ while (location)
+ {
+ gchar *t, **toks = g_strsplit (location, ":", -1);
+ guint border = 0, padding = 0, i = 0;
+ gboolean fill = FALSE, expand = FALSE, start = TRUE;
+ GtkWidget *child;
+ t = toks[i++];
+ if (t && t[0] >= '0' && t[0] <= '9')
+ {
+ border = g_ascii_strtoull (t, NULL, 10);
+ t = toks[i++];
+ }
+ if (t && t[0] == '+')
+ {
+ expand = TRUE;
+ t = toks[i++];
+ }
+ if (t && t[0] == '*')
+ {
+ expand = fill = TRUE;
+ t = toks[i++];
+ }
+ if (t && t[0] == 'H')
+ {
+ gtk_box_set_homogeneous (box, TRUE);
+ expand = fill = TRUE;
+ t = toks[i++];
+ }
+ if (t && t[0] == 's')
+ {
+ start = TRUE;
+ t = toks[i++];
+ }
+ if (t && t[0] == 'e')
+ {
+ start = FALSE;
+ t = toks[i++];
+ }
+ if (t && t[0] == 'p')
+ {
+ padding = g_ascii_strtoull (t + 1, NULL, 10);
+ t = toks[i++];
+ }
+ g_strfreev (toks);
+ child = va_arg (args, GtkWidget*);
+ if (child)
+ {
+ if (border)
+ child = (GtkWidget*) g_object_new (GTK_TYPE_ALIGNMENT,
+ "child", child,
+ "border_width", border * spacing,
+ NULL);
+ if (start)
+ gtk_box_pack_start (box, child, expand, fill, padding);
+ else
+ gtk_box_pack_end (box, child, expand, fill, padding);
+ }
+ location = va_arg (args, gchar*);
+ }
+ }
+
+ GtkWidget*
+ bst_vpack (const gchar *first_location,
+ ...)
+ {
+ va_list args;
+ GtkWidget *box = (GtkWidget*) g_object_new (GTK_TYPE_VBOX,
+ "spacing", SPACING,
+ NULL);
+ va_start (args, first_location);
+ bst_util_pack (box, first_location, SPACING, args);
+ va_end (args);
+ gtk_widget_show_all (box);
+ return box;
+ }
+
+ GtkWidget*
+ bst_hpack (const gchar *first_location,
+ ...)
+ {
+ va_list args;
+ GtkWidget *box = (GtkWidget*) g_object_new (GTK_TYPE_HBOX,
+ "spacing", SPACING,
+ NULL);
+ va_start (args, first_location);
+ bst_util_pack (box, first_location, SPACING, args);
+ va_end (args);
+ gtk_widget_show_all (box);
+ return box;
+ }
+
+ GtkWidget*
+ bst_vpack0 (const gchar *first_location,
+ ...)
+ {
+ va_list args;
+ GtkWidget *box = (GtkWidget*) g_object_new (GTK_TYPE_VBOX,
+ "spacing", 0,
+ NULL);
+ va_start (args, first_location);
+ bst_util_pack (box, first_location, SPACING, args);
+ va_end (args);
+ gtk_widget_show_all (box);
+ return box;
+ }
+
+ GtkWidget*
+ bst_hpack0 (const gchar *first_location,
+ ...)
+ {
+ va_list args;
+ GtkWidget *box = (GtkWidget*) g_object_new (GTK_TYPE_HBOX,
+ "spacing", 0,
+ NULL);
+ va_start (args, first_location);
+ bst_util_pack (box, first_location, SPACING, args);
+ va_end (args);
+ gtk_widget_show_all (box);
+ return box;
+ }
+
+ void
+ bst_action_list_add_cat (GxkActionList *alist,
+ BseCategory *cat,
+ guint skip_levels,
+ const gchar *stock_fallback,
+ GxkActionCheck acheck,
+ GxkActionExec aexec,
+ gpointer user_data)
+ {
+ const gchar *p, *stock_id;
+
+ if (cat->icon)
+ {
+ BseIcon *icon = cat->icon;
+ g_assert (icon->width * icon->height == int (icon->pixel_seq->n_pixels));
+ bst_stock_register_icon (cat->category, 4,
+ icon->width, icon->height,
+ icon->width * 4,
+ (guchar*) icon->pixel_seq->pixels);
+ stock_id = cat->category;
+ }
+ else
+ stock_id = stock_fallback;
+
+ p = cat->category[0] == '/' ? cat->category + 1 : cat->category;
+ while (skip_levels--)
+ {
+ const gchar *d = strchr (p, '/');
+ p = d ? d + 1 : p;
+ }
+
+ gxk_action_list_add_translated (alist, NULL, p, NULL,
+ gxk_factory_path_get_leaf (cat->category),
+ cat->category_id, stock_id,
+ acheck, aexec, user_data);
+ }
+
+ GxkActionList*
+ bst_action_list_from_cats_pred (BseCategorySeq *cseq,
+ guint skip_levels,
+ const gchar *stock_fallback,
+ GxkActionCheck acheck,
+ GxkActionExec aexec,
+ gpointer user_data,
+ BstActionListCategoryP predicate,
+ gpointer predicate_data)
+ {
+ GxkActionList *alist = gxk_action_list_create ();
+ guint i;
+
+ g_return_val_if_fail (cseq != NULL, alist);
+
+ for (i = 0; i < cseq->n_cats; i++)
+ if (!predicate || predicate (predicate_data, cseq->cats[i]))
+ bst_action_list_add_cat (alist, cseq->cats[i], skip_levels, stock_fallback, acheck, aexec, user_data);
+ return alist;
+ }
+
+ GxkActionList*
+ bst_action_list_from_cats (BseCategorySeq *cseq,
+ guint skip_levels,
+ const gchar *stock_fallback,
+ GxkActionCheck acheck,
+ GxkActionExec aexec,
+ gpointer user_data)
+ {
+ return bst_action_list_from_cats_pred (cseq, skip_levels, stock_fallback, acheck, aexec, user_data, NULL,
NULL);
+ }
+
+
+ /* --- field mask --- */
+ static GQuark gmask_quark = 0;
+ typedef struct {
+ GtkWidget *parent;
+ GtkWidget *prompt;
+ GtkWidget *aux1;
+ GtkWidget *aux2; /* auto-expand */
+ GtkWidget *aux3;
+ GtkWidget *action;
+ gchar *tip;
+ guint column : 16;
+ guint gpack : 8;
+ } GMask;
+ #define GMASK_GET(o) ((GMask*) g_object_get_qdata (G_OBJECT (o), gmask_quark))
+
+ static void
+ gmask_destroy (gpointer data)
+ {
+ GMask *gmask = (GMask*) data;
+
+ if (gmask->parent)
+ g_object_unref (gmask->parent);
+ if (gmask->prompt)
+ g_object_unref (gmask->prompt);
+ if (gmask->aux1)
+ g_object_unref (gmask->aux1);
+ if (gmask->aux2)
+ g_object_unref (gmask->aux2);
+ if (gmask->aux3)
+ g_object_unref (gmask->aux3);
+ g_free (gmask->tip);
+ g_free (gmask);
+ }
+
+ static gpointer
+ gmask_form (GtkWidget *parent,
+ GtkWidget *action,
+ BstGMaskPack gpack)
+ {
+ GMask *gmask;
+
+ g_return_val_if_fail (GTK_IS_TABLE (parent), NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (action), NULL);
+
+ if (!gmask_quark)
+ gmask_quark = g_quark_from_static_string ("GMask");
+
+ gmask = GMASK_GET (action);
+ g_return_val_if_fail (gmask == NULL, NULL);
+
+ gmask = g_new0 (GMask, 1);
+ g_object_set_qdata_full (G_OBJECT (action), gmask_quark, gmask, gmask_destroy);
+ gmask->parent = (GtkWidget*) g_object_ref (parent);
+ gtk_object_sink (GTK_OBJECT (parent));
+ gmask->action = action;
+ gmask->gpack = gpack;
+
+ return action;
+ }
+
+ /**
+ * @param border_width Border width of this GUI mask
+ * @param dislodge_columns Provide expandable space between columns
+ * @return GUI field mask container
+ *
+ * Create a container capable to hold GUI field masks.
+ * This is the container to be passed into bst_gmask_form().
+ * In case multiple field mask columns are packed into the
+ * container (by using bst_gmask_set_column() on the filed
+ * masks), @a dislodge_columns specifies whether the field
+ * mask columns are to be closely aligned.
+ */
+ GtkWidget*
+ bst_gmask_container_create (guint border_width,
+ gboolean dislodge_columns)
+ {
+ GtkWidget *container = gtk_widget_new (GTK_TYPE_TABLE,
+ "visible", TRUE,
+ "homogeneous", FALSE,
+ "n_columns", 2,
+ "border_width", border_width,
+ NULL);
+ if (dislodge_columns)
+ g_object_set_data (G_OBJECT (container), "GMask-dislodge", GUINT_TO_POINTER (TRUE));
+
+ return container;
+ }
+
+ /**
+ * @param gmask_container container created with bst_gmask_container_create()
+ * @param action valid GtkWidget
+ * @param gpack BstGMaskPack packing type
+ * @return a new GUI field mask
+ *
+ * Create a new GUI field mask with @a action as action widget.
+ * Each GUI field mask consists of an action widget which may
+ * be neighboured by pre and post action widgets, the action
+ * widget is usually something like a GtkEntry input widget.
+ * Also, most field masks have a prompt widget, usually a
+ * GtkLabel, labeling the field mask with a name.
+ * Optionally, up to three auxillary widgets are supported
+ * per field mask, layed out between the prompt and the
+ * action widgets.
+ * The second auxillary widget will expand if additional
+ * space is available. Other layout details are configured
+ * through the @a gpack packing type:
+ * @li @c BST_GMASK_FIT - the action widget is not expanded,
+ * @li @c BST_GMASK_INTERLEAVE - allow the action widget to expand across auxillary
+ * columns if it requests that much space,
+ * @li @c BST_GMASK_BIG - force expansion of the action widget across all possible
+ * columns up to the prompt,
+ * @li @c BST_GMASK_CENTER - center the action widget within space across all possible
+ * columns up to the prompt.
+ * @li @c BST_GMASK_MULTI_SPAN - span aux2 widget across multiple gmask columns.
+ */
+ BstGMask*
+ bst_gmask_form (GtkWidget *gmask_container,
+ GtkWidget *action,
+ BstGMaskPack gpack)
+ {
+ return (BstGMask*) gmask_form (gmask_container, action, gpack);
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param tip_text tooltip text
+ *
+ * Set the tooltip text of this GUI field @a mask.
+ */
+ void
+ bst_gmask_set_tip (BstGMask *mask,
+ const gchar *tip_text)
+ {
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+
+ g_free (gmask->tip);
+ gmask->tip = g_strdup (tip_text);
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param widget valid GtkWidget
+ *
+ * Set the prompt widget of this GUI field @a mask.
+ */
+ void
+ bst_gmask_set_prompt (BstGMask *mask,
+ gpointer widget)
+ {
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (gmask->prompt)
+ g_object_unref (gmask->prompt);
+ gmask->prompt = (GtkWidget*) g_object_ref (widget);
+ gtk_object_sink (GTK_OBJECT (widget));
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param widget valid GtkWidget
+ *
+ * Set the first auxillary widget of this GUI field @a mask.
+ */
+ void
+ bst_gmask_set_aux1 (BstGMask *mask,
+ gpointer widget)
+ {
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (gmask->aux1)
+ g_object_unref (gmask->aux1);
+ gmask->aux1 = (GtkWidget*) g_object_ref (widget);
+ gtk_object_sink (GTK_OBJECT (widget));
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param widget valid GtkWidget
+ *
+ * Set the second auxillary widget of this GUI field @a mask.
+ * In contrast to the first and third auxillary widget, this
+ * one is expanded if extra space is available.
+ */
+ void
+ bst_gmask_set_aux2 (BstGMask *mask,
+ gpointer widget)
+ {
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (gmask->aux2)
+ g_object_unref (gmask->aux2);
+ gmask->aux2 = (GtkWidget*) g_object_ref (widget);
+ gtk_object_sink (GTK_OBJECT (widget));
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param widget valid GtkWidget
+ *
+ * Set the third auxillary widget of this GUI field @a mask.
+ */
+ void
+ bst_gmask_set_aux3 (BstGMask *mask,
+ gpointer widget)
+ {
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if (gmask->aux3)
+ g_object_unref (gmask->aux3);
+ gmask->aux3 = (GtkWidget*) g_object_ref (widget);
+ gtk_object_sink (GTK_OBJECT (widget));
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param column column number
+ *
+ * Set the field mask column. By default all field masks are
+ * packed into column 0, so that only vertical packing occours.
+ */
+ void
+ bst_gmask_set_column (BstGMask *mask,
+ guint column)
+ {
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+
+ gmask->column = column;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @return the requested GtkWidget or NULL
+ *
+ * Retrieve the prompt widget of this GUI field @a mask.
+ */
+ GtkWidget*
+ bst_gmask_get_prompt (BstGMask *mask)
+ {
+ GMask *gmask;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (mask), NULL);
+ gmask = GMASK_GET (mask);
+ g_return_val_if_fail (gmask != NULL, NULL);
+
+ return gmask->prompt;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @return the requested GtkWidget or NULL
+ *
+ * Retrieve the first auxillary widget of this GUI field @a mask.
+ */
+ GtkWidget*
+ bst_gmask_get_aux1 (BstGMask *mask)
+ {
+ GMask *gmask;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (mask), NULL);
+ gmask = GMASK_GET (mask);
+ g_return_val_if_fail (gmask != NULL, NULL);
+
+ return gmask->aux1;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @return the requested GtkWidget or NULL
+ *
+ * Retrieve the second auxillary widget of this GUI field @a mask.
+ */
+ GtkWidget*
+ bst_gmask_get_aux2 (BstGMask *mask)
+ {
+ GMask *gmask;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (mask), NULL);
+ gmask = GMASK_GET (mask);
+ g_return_val_if_fail (gmask != NULL, NULL);
+
+ return gmask->aux2;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @return the requested GtkWidget or NULL
+ *
+ * Retrieve the third auxillary widget of this GUI field @a mask.
+ */
+ GtkWidget*
+ bst_gmask_get_aux3 (BstGMask *mask)
+ {
+ GMask *gmask;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (mask), NULL);
+ gmask = GMASK_GET (mask);
+ g_return_val_if_fail (gmask != NULL, NULL);
+
+ return gmask->aux3;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @return the requested GtkWidget or NULL
+ *
+ * Retrieve the action widget of this GUI field @a mask.
+ */
+ GtkWidget*
+ bst_gmask_get_action (BstGMask *mask)
+ {
+ GMask *gmask;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (mask), NULL);
+ gmask = GMASK_GET (mask);
+ g_return_val_if_fail (gmask != NULL, NULL);
+
+ return gmask->action;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ * @param func foreach function as: void func(GtkWidget*, gpointer data);
+ * @param data data passed in to @a func
+ *
+ * Invoke @a func() with each of the widgets set for this
+ * field mask.
+ */
+ void
+ bst_gmask_foreach (BstGMask *mask,
+ gpointer func,
+ gpointer data)
+ {
+ GMask *gmask;
+ GtkCallback callback = GtkCallback (func);
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+ g_return_if_fail (func != NULL);
+
+ if (gmask->prompt)
+ callback (gmask->prompt, data);
+ if (gmask->aux1)
+ callback (gmask->aux1, data);
+ if (gmask->aux2)
+ callback (gmask->aux2, data);
+ if (gmask->aux3)
+ callback (gmask->aux3, data);
+ if (gmask->action)
+ callback (gmask->action, data);
+ }
+
+ static GtkWidget*
+ get_toplevel_and_set_tip (GtkWidget *widget,
+ const gchar *tip)
+ {
+ GtkWidget *last;
+
+ if (!widget)
+ return NULL;
+ else if (!tip)
+ return gtk_widget_get_toplevel (widget);
+ do
+ {
+ if (!GTK_WIDGET_NO_WINDOW (widget))
+ {
+ gxk_widget_set_tooltip (widget, tip);
+ return gtk_widget_get_toplevel (widget);
+ }
+ last = widget;
+ widget = last->parent;
+ }
+ while (widget);
+ /* need to create a tooltips sensitive parent */
+ widget = gtk_widget_new (GTK_TYPE_EVENT_BOX,
+ "visible", TRUE,
+ "child", last,
+ NULL);
+ gxk_widget_set_tooltip (widget, tip);
+ return widget;
+ }
+
+ static guint
+ table_max_bottom_row (GtkTable *table,
+ guint left_col,
+ guint right_col)
+ {
+ guint max_bottom = 0;
+ GList *list;
+
+ for (list = table->children; list; list = list->next)
+ {
+ GtkTableChild *child = (GtkTableChild*) list->data;
+
+ if (child->left_attach < right_col && child->right_attach > left_col)
+ max_bottom = MAX (max_bottom, child->bottom_attach);
+ }
+ return max_bottom;
+ }
+
+ /**
+ * @param mask valid BstGMask
+ *
+ * After the GUI field mask is fully configured, by setting
+ * all associated widgets on it, column tooltip text, etc.,
+ * this function actually packs it into its container. The
+ * field mask setters shouldn't be used after this point.
+ */
+ void
+ bst_gmask_pack (BstGMask *mask)
+ {
+ GtkWidget *prompt, *aux1, *aux2, *aux3, *action;
+ GtkTable *table;
+ gboolean dummy_aux2 = FALSE;
+ guint row, n, c, dislodge_columns;
+ GMask *gmask;
+
+ g_return_if_fail (GTK_IS_WIDGET (mask));
+ gmask = GMASK_GET (mask);
+ g_return_if_fail (gmask != NULL);
+
+ /* GUI mask layout:
+ * row: |Prompt|Aux1| Aux2 |Aux3| PreAction#Action#PostAction|
+ * FILL: allocate all possible (Pre/Post)Action space to the action widget
+ * INTERLEAVE: allow the action widget to facilitate unused Aux2/Aux3 space
+ * BIG: allocate maximum (left extendeded) possible space to Action
+ * Aux2 expands automatically
+ */
+
+ /* retrieve children and set tips */
+ prompt = get_toplevel_and_set_tip (gmask->prompt, gmask->tip);
+ aux1 = get_toplevel_and_set_tip (gmask->aux1, gmask->tip);
+ aux2 = get_toplevel_and_set_tip (gmask->aux2, gmask->tip);
+ aux3 = get_toplevel_and_set_tip (gmask->aux3, gmask->tip);
+ action = get_toplevel_and_set_tip (gmask->action, gmask->tip);
+ dislodge_columns = g_object_get_data (G_OBJECT (gmask->parent), "GMask-dislodge") != NULL;
+ table = GTK_TABLE (gmask->parent);
+
+ /* ensure expansion happens outside of columns */
+ if (dislodge_columns)
+ {
+ gchar *dummy_name = g_strdup_format ("GMask-dummy-dislodge-%u", MAX (gmask->column, 1) - 1);
+ GtkWidget *dislodge = (GtkWidget*) g_object_get_data (G_OBJECT (table), dummy_name);
+
+ if (!dislodge)
+ {
+ dislodge = (GtkWidget*) g_object_new (GTK_TYPE_ALIGNMENT, "visible", TRUE, NULL);
+ g_object_set_data_full (G_OBJECT (table), dummy_name, g_object_ref (dislodge), g_object_unref);
+ c = MAX (gmask->column, 1) * 6;
+ gtk_table_attach (table, dislodge, c - 1, c, 0, 1, GTK_EXPAND, GtkAttachOptions (0), 0, 0);
+ }
+ g_free (dummy_name);
+ }
+
+ /* pack gmask children, options: GTK_EXPAND, GTK_SHRINK, GTK_FILL */
+ gboolean span_multi_columns = aux2 && gmask->gpack == BST_GMASK_MULTI_SPAN;
+ c = span_multi_columns ? 0 : 6 * gmask->column;
+ row = table_max_bottom_row (table, c, 6 * gmask->column + 6);
+ if (prompt)
+ {
+ gtk_table_attach (table, prompt, c, c + 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_set_col_spacing (table, c, 2); /* seperate prompt from rest */
+ }
+ c++;
+ if (aux1)
+ {
+ gtk_table_attach (table, aux1, c, c + 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_set_col_spacing (table, c, 3); /* aux1 spacing */
+ }
+ c++;
+ if (!aux2 && !dislodge_columns)
+ {
+ char *dummy_name = g_strdup_format ("GMask-dummy-aux2-%u", gmask->column);
+ aux2 = (GtkWidget*) g_object_get_data (G_OBJECT (table), dummy_name);
+
+ /* need to have at least 1 (dummy) aux2-child per table column to eat up
+ * expanding space in this column if !dislodge_columns
+ */
+ if (!aux2)
+ {
+ aux2 = gtk_widget_new (GTK_TYPE_ALIGNMENT, "visible", TRUE, NULL);
+ g_object_set_data_full (G_OBJECT (table), dummy_name, g_object_ref (aux2), g_object_unref);
+ }
+ else
+ aux2 = NULL;
+ g_free (dummy_name);
+ dummy_aux2 = TRUE;
+ }
+ if (aux2)
+ {
+ guint left_col = c;
+ if (span_multi_columns)
+ c += 6 * gmask->column;
+ gtk_table_attach (table, aux2,
+ left_col, c + 1,
+ row, row + 1, GTK_EXPAND | GTK_FILL, GtkAttachOptions (0), 0, 0);
+ if (dummy_aux2)
+ aux2 = NULL;
+ if (aux2)
+ gtk_table_set_col_spacing (table, c, 3); /* aux2 spacing */
+ }
+ c++;
+ if (aux3)
+ {
+ gtk_table_attach (table, aux3, c, c + 1, row, row + 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_set_col_spacing (table, c, 3); /* aux3 spacing */
+ }
+ c++;
+ n = c;
+ if (gmask->gpack == BST_GMASK_BIG || gmask->gpack == BST_GMASK_CENTER ||
+ gmask->gpack == BST_GMASK_INTERLEAVE) /* extend action to the left when possible */
+ {
+ if (!aux3)
+ {
+ n--;
+ if (!aux2)
+ {
+ n--;
+ if (!aux1 && (gmask->gpack == BST_GMASK_BIG ||
+ gmask->gpack == BST_GMASK_CENTER))
+ {
+ n--;
+ if (!prompt)
+ n--;
+ }
+ }
+ }
+ }
+ if (gmask->gpack == BST_GMASK_FIT ||
+ gmask->gpack == BST_GMASK_INTERLEAVE) /* align to right without expansion */
+ action = gtk_widget_new (GTK_TYPE_ALIGNMENT,
+ "visible", TRUE,
+ "child", action,
+ "xalign", 1.0,
+ "xscale", 0.0,
+ "yscale", 0.0,
+ NULL);
+ else if (gmask->gpack == BST_GMASK_CENTER)
+ action = gtk_widget_new (GTK_TYPE_ALIGNMENT,
+ "visible", TRUE,
+ "child", action,
+ "xalign", 0.5,
+ "yalign", 0.5,
+ "xscale", 0.0,
+ "yscale", 0.0,
+ NULL);
+ gtk_table_attach (table, action,
+ n, c + 1, row, row + 1,
+ GTK_SHRINK | GTK_FILL,
+ GTK_FILL,
+ 0, 0);
+ gtk_table_set_col_spacing (table, c - 1, 3); /* seperate action from rest */
+ c = 6 * gmask->column;
+ if (c)
+ gtk_table_set_col_spacing (table, c - 1, 5); /* spacing between gmask columns */
+ }
+
+ /**
+ * @param gmask_container container created with bst_gmask_container_create()
+ * @param column column number for bst_gmask_set_column()
+ * @param prompt valid GtkWidget for bst_gmask_set_prompt()
+ * @param action valid GtkWidget as with bst_gmask_form()
+ * @param tip_text text for bst_gmask_set_tip()
+ * @return an already packed GUI field mask
+ *
+ * Shorthand to form a GUI field mask in @a column of type BST_GMASK_INTERLEAVE,
+ * with @a prompt and @a tip_text. Note that this function already calls
+ * bst_gmask_pack(), so the returned field mask already can't be modified
+ * anymore.
+ */
+ BstGMask*
+ bst_gmask_quick (GtkWidget *gmask_container,
+ guint column,
+ const gchar *prompt,
+ gpointer action,
+ const gchar *tip_text)
+ {
+ BstGMask *mask = bst_gmask_form (gmask_container, (GtkWidget*) action, BST_GMASK_INTERLEAVE);
+
+ if (prompt)
+ bst_gmask_set_prompt (mask, g_object_new (GTK_TYPE_LABEL,
+ "visible", TRUE,
+ "label", prompt,
+ NULL));
+ if (tip_text)
+ bst_gmask_set_tip (mask, tip_text);
+ bst_gmask_set_column (mask, column);
+ bst_gmask_pack (mask);
+
+ return mask;
+ }
+
+
+ /* --- named children --- */
+ static GQuark quark_container_named_children = 0;
+ typedef struct {
+ GData *qdata;
+ } NChildren;
+ static void
+ nchildren_free (gpointer data)
+ {
+ NChildren *children = (NChildren*) data;
+
+ g_datalist_clear (&children->qdata);
+ g_free (children);
+ }
+ static void
+ destroy_nchildren (GtkWidget *container)
+ {
+ g_object_set_qdata (G_OBJECT (container), quark_container_named_children, NULL);
+ }
+ void
+ bst_container_set_named_child (GtkWidget *container,
+ GQuark qname,
+ GtkWidget *child)
+ {
+ NChildren *children;
+
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+ g_return_if_fail (qname > 0);
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ if (child)
+ g_return_if_fail (gtk_widget_is_ancestor (child, container));
+
+ if (!quark_container_named_children)
+ quark_container_named_children = g_quark_from_static_string ("BstContainer-named_children");
+
+ children = (NChildren*) g_object_get_qdata (G_OBJECT (container), quark_container_named_children);
+ if (!children)
+ {
+ children = g_new (NChildren, 1);
+ g_datalist_init (&children->qdata);
+ g_object_set_qdata_full (G_OBJECT (container), quark_container_named_children, children,
nchildren_free);
+ g_object_connect (container,
+ "signal::destroy", destroy_nchildren, NULL,
+ NULL);
+ }
+ g_object_ref (child);
+ g_datalist_id_set_data_full (&children->qdata, qname, child, g_object_unref);
+ }
+
+ GtkWidget*
+ bst_container_get_named_child (GtkWidget *container,
+ GQuark qname)
+ {
+ NChildren *children;
+
+ g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
+ g_return_val_if_fail (qname > 0, NULL);
+
+ children = quark_container_named_children ? (NChildren*) g_object_get_qdata (G_OBJECT (container),
quark_container_named_children) : NULL;
+ if (children)
+ {
+ GtkWidget *child = (GtkWidget*) g_datalist_id_get_data (&children->qdata, qname);
+
+ if (child && !gtk_widget_is_ancestor (child, container))
+ {
+ /* got removed meanwhile */
+ g_datalist_id_set_data (&children->qdata, qname, NULL);
+ child = NULL;
+ }
+ return child;
+ }
+ return NULL;
+ }
+
+ GtkWidget*
+ bst_xpm_view_create (const gchar **xpm,
+ GtkWidget *colormap_widget)
+ {
+ GtkWidget *pix;
+ GdkPixmap *pixmap;
+ GdkBitmap *mask;
+
+ g_return_val_if_fail (xpm != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (colormap_widget), NULL);
+
+ pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, gtk_widget_get_colormap (colormap_widget),
+ &mask, NULL, (gchar**) xpm);
+ pix = gtk_pixmap_new (pixmap, mask);
+ gdk_pixmap_unref (pixmap);
+ gdk_pixmap_unref (mask);
+ gtk_widget_set (pix,
+ "visible", TRUE,
+ NULL);
+ return pix;
+ }
+
+
+ /* --- misc utils --- */
+ gint
+ bst_fft_size_to_int (BstFFTSize fft_size)
+ {
+ switch (fft_size)
+ {
+ #if 0
+ case BST_FFT_SIZE_1: return 1;
+ #endif
+ case BST_FFT_SIZE_2: return 2;
+ case BST_FFT_SIZE_4: return 4;
+ case BST_FFT_SIZE_8: return 8;
+ case BST_FFT_SIZE_16: return 16;
+ case BST_FFT_SIZE_32: return 32;
+ case BST_FFT_SIZE_64: return 64;
+ case BST_FFT_SIZE_128: return 128;
+ case BST_FFT_SIZE_256: return 256;
+ case BST_FFT_SIZE_512: return 512;
+ case BST_FFT_SIZE_1024: return 1024;
+ case BST_FFT_SIZE_2048: return 2048;
+ case BST_FFT_SIZE_4096: return 4096;
+ case BST_FFT_SIZE_8192: return 8192;
+ case BST_FFT_SIZE_16384: return 16384;
+ case BST_FFT_SIZE_32768: return 32768;
+ case BST_FFT_SIZE_65536: return 65536;
+ #if 0
+ case BST_FFT_SIZE_131072: return 131072;
+ case BST_FFT_SIZE_262144: return 262144;
+ case BST_FFT_SIZE_524288: return 524288;
+ case BST_FFT_SIZE_1048576: return 1048576;
+ case BST_FFT_SIZE_2097152: return 2097152;
+ case BST_FFT_SIZE_4194304: return 4194304;
+ case BST_FFT_SIZE_8388608: return 8388608;
+ case BST_FFT_SIZE_16777216: return 16777216;
+ case BST_FFT_SIZE_33554432: return 33554432;
+ case BST_FFT_SIZE_67108864: return 67108864;
+ case BST_FFT_SIZE_134217728: return 134217728;
+ case BST_FFT_SIZE_268435456: return 268435456;
+ case BST_FFT_SIZE_536870912: return 536870912;
+ case BST_FFT_SIZE_1073741824: return 1073741824;
+ case BST_FFT_SIZE_2147483648: return 2147483648;
+ case BST_FFT_SIZE_4294967296: return 4294967296;
+ #endif
+ default: return 0;
+ }
+ }
+
+ BstFFTSize
+ bst_fft_size_from_int (guint sz)
+ {
+ const struct { BstFFTSize fft_size; guint sz; } sizes[] = {
+ #if 0
+ { BST_FFT_SIZE_1, 1 },
+ #endif
+ { BST_FFT_SIZE_2, 2 },
+ { BST_FFT_SIZE_4, 4 },
+ { BST_FFT_SIZE_8, 8 },
+ { BST_FFT_SIZE_16, 16 },
+ { BST_FFT_SIZE_32, 32 },
+ { BST_FFT_SIZE_64, 64 },
+ { BST_FFT_SIZE_128, 128 },
+ { BST_FFT_SIZE_256, 256 },
+ { BST_FFT_SIZE_512, 512 },
+ { BST_FFT_SIZE_1024, 1024 },
+ { BST_FFT_SIZE_2048, 2048 },
+ { BST_FFT_SIZE_4096, 4096 },
+ { BST_FFT_SIZE_8192, 8192 },
+ { BST_FFT_SIZE_16384, 16384 },
+ { BST_FFT_SIZE_32768, 32768 },
+ { BST_FFT_SIZE_65536, 65536 },
+ #if 0
+ { BST_FFT_SIZE_131072, 131072 },
+ { BST_FFT_SIZE_262144, 262144 },
+ { BST_FFT_SIZE_524288, 524288 },
+ { BST_FFT_SIZE_1048576, 1048576 },
+ { BST_FFT_SIZE_2097152, 2097152 },
+ { BST_FFT_SIZE_4194304, 4194304 },
+ { BST_FFT_SIZE_8388608, 8388608 },
+ { BST_FFT_SIZE_16777216, 16777216 },
+ { BST_FFT_SIZE_33554432, 33554432 },
+ { BST_FFT_SIZE_67108864, 67108864 },
+ { BST_FFT_SIZE_134217728, 134217728 },
+ { BST_FFT_SIZE_268435456, 268435456 },
+ { BST_FFT_SIZE_536870912, 536870912 },
+ { BST_FFT_SIZE_1073741824, 1073741824 },
+ { BST_FFT_SIZE_2147483648, 2147483648 },
+ { BST_FFT_SIZE_4294967296, 4294967296 },
+ #endif
+ };
+ /* find size via bisection */
+ guint offset = 0, n = G_N_ELEMENTS (sizes);
+ while (offset + 1 < n)
+ {
+ guint i = (offset + n) >> 1;
+ if (sz < sizes[i].sz)
+ n = i;
+ else
+ offset = i;
+ }
+ return sizes[offset].fft_size;
+ }
+
+ #include <sfi/sfistore.hh>
+
+ gchar*
+ bst_file_scan_find_key (const gchar *file,
+ const gchar *key,
+ const gchar *value_prefix)
+ {
+ SfiRStore *rstore;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ rstore = sfi_rstore_new_open (file);
+ if (rstore)
+ {
+ guint l = value_prefix ? strlen (value_prefix) : 0;
+ gchar *name = NULL;
+ while (!g_scanner_eof (rstore->scanner))
+ {
+ if (g_scanner_get_next_token (rstore->scanner) == '(' &&
+ g_scanner_peek_next_token (rstore->scanner) == G_TOKEN_IDENTIFIER)
+ {
+ g_scanner_get_next_token (rstore->scanner);
+ if (strcmp (rstore->scanner->value.v_identifier, key) == 0 &&
+ g_scanner_peek_next_token (rstore->scanner) == G_TOKEN_STRING)
+ {
+ g_scanner_get_next_token (rstore->scanner);
+ if (!l || strncmp (rstore->scanner->value.v_string, value_prefix, l) == 0)
+ {
+ name = g_strdup (rstore->scanner->value.v_string + l);
+ break;
+ }
+ }
+ }
+ }
+ sfi_rstore_destroy (rstore);
+ return name;
+ }
+ else
+ return NULL;
+ }
+
+
+ /* --- generated marshallers --- */
+ #include "bstmarshal.cc"
+
+
+ /* --- IDL pspecs --- */
+ #define sfidl_pspec_Bool(group, name, nick, blurb, dflt, hints) \
+ sfi_pspec_set_group (sfi_pspec_bool (name, nick, blurb, dflt, hints), group)
+ #define sfidl_pspec_Bool_default(group, name) \
+ sfi_pspec_set_group (sfi_pspec_bool (name, NULL, NULL, FALSE, SFI_PARAM_STANDARD), group)
+ #define sfidl_pspec_Int(group, name, nick, blurb, dflt, min, max, step, hints) \
+ sfi_pspec_set_group (sfi_pspec_int (name, nick, blurb, dflt, min, max, step, hints), group)
+ #define sfidl_pspec_Int_default(group, name) \
+ sfi_pspec_set_group (sfi_pspec_int (name, NULL, NULL, 0, G_MININT, G_MAXINT, 256, SFI_PARAM_STANDARD),
group)
+ #define sfidl_pspec_UInt(group, name, nick, blurb, dflt, hints) \
+ sfi_pspec_set_group (sfi_pspec_int (name, nick, blurb, dflt, 0, G_MAXINT, 1, hints), group)
+ #define sfidl_pspec_Real(group, name, nick, blurb, dflt, min, max, step, hints) \
+ sfi_pspec_set_group (sfi_pspec_real (name, nick, blurb, dflt, min, max, step, hints), group)
+ #define sfidl_pspec_Real_default(group, name) \
+ sfi_pspec_set_group (sfi_pspec_real (name, NULL, NULL, 0, -SFI_MAXREAL, SFI_MAXREAL, 10,
SFI_PARAM_STANDARD), group)
+ #define sfidl_pspec_Note(group, name, nick, blurb, dflt, hints) \
+ sfi_pspec_set_group (sfi_pspec_note (name, nick, blurb, dflt, hints), group)
+ #define sfidl_pspec_Choice(group, name, nick, blurb, dval, options, cvalues) \
+ sfi_pspec_set_group (sfi_pspec_choice (name, nick, blurb, dval, cvalues, SFI_PARAM_STANDARD), group)
+ #define sfidl_pspec_Choice_default(group, name, cvalues) \
+ sfidl_pspec_Choice (group, name, NULL, NULL, NULL, SFI_PARAM_STANDARD, cvalues)
+ #define sfidl_pspec_String(group, name, nick, blurb, dflt, options) \
+ sfi_pspec_set_group (sfi_pspec_string (name, nick, blurb, dflt, options), group)
+ #define sfidl_pspec_String_default(group, name) \
+ sfidl_pspec_String (group, name, NULL, NULL, NULL, SFI_PARAM_STANDARD)
+ #define sfidl_pspec_BBlock(group, name, nick, blurb, options) \
+ sfi_pspec_set_group (sfi_pspec_bblock (name, nick, blurb, options), group)
+ #define sfidl_pspec_BBlock_default(group, name) \
+ sfidl_pspec_BBlock (group, name, NULL, NULL, SFI_PARAM_STANDARD)
+ #define sfidl_pspec_FBlock(group, name, nick, blurb, options) \
+ sfi_pspec_set_group (sfi_pspec_fblock (name, nick, blurb, options), group)
+ #define sfidl_pspec_FBlock_default(group, name) \
+ sfidl_pspec_FBlock (group, name, NULL, NULL, SFI_PARAM_STANDARD)
+ #define sfidl_pspec_Rec(group, name, nick, blurb, options) \
+ sfi_pspec_set_group (sfi_pspec_rec_generic (name, nick, blurb, options), group)
+ #define sfidl_pspec_Rec_default(group, name, fields) \
+ sfidl_pspec_Rec (group, name, NULL, NULL, SFI_PARAM_STANDARD)
+ #define sfidl_pspec_Record(group, name, nick, blurb, options, fields) \
+ sfi_pspec_set_group (sfi_pspec_rec (name, nick, blurb, fields, options), group)
+ #define sfidl_pspec_Record_default(group, name, fields) \
+ sfidl_pspec_Record (group, name, NULL, NULL, SFI_PARAM_STANDARD, fields)
+ #define sfidl_pspec_Sequence(group, name, nick, blurb, options, element) \
+ sfi_pspec_set_group (sfi_pspec_seq (name, nick, blurb, element, options), group)
+ #define sfidl_pspec_Sequence_default(group, name, element) \
+ sfidl_pspec_Sequence (group, name, NULL, NULL, SFI_PARAM_STANDARD, element)
+ #define sfidl_pspec_Proxy_default(group, name) \
+ sfi_pspec_set_group (sfi_pspec_proxy (name, NULL, NULL, SFI_PARAM_STANDARD), group)
+ /* --- generated type IDs and SFIDL types --- */
+ #include "bstgentypes.cc" /* type id defs */
+
+ // == mouse button checks ==
+ static bool
+ shift_event (GdkEvent *event)
+ {
+ return (event->button.state & GDK_SHIFT_MASK) != 0;
+ }
+
+ static bool
+ alt_event (GdkEvent *event)
+ {
+ return (event->button.state & GDK_MOD1_MASK) != 0;
+ }
+
+ static bool
+ button_event (GdkEvent *event)
+ {
+ return event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE;
+ }
+
+ bool
+ bst_mouse_button_activate (GdkEvent *event)
+ {
+ return button_event (event) && event->button.button == 1;
+ }
+
+ bool
+ bst_mouse_button_activate1 (GdkEvent *event)
+ {
+ return !shift_event (event) && button_event (event) && event->button.button == 1;
+ }
+
+ bool
+ bst_mouse_button_activate2 (GdkEvent *event)
+ {
+ return shift_event (event) && button_event (event) && event->button.button == 1;
+ }
+
+ bool
+ bst_mouse_button_move (GdkEvent *event)
+ {
+ return button_event (event) && (event->button.button == 2 ||
+ (alt_event (event) && event->button.button == 1));
+ }
+
+ bool
+ bst_mouse_button_context (GdkEvent *event)
+ {
+ return button_event (event) && event->button.button == 3;
+ }
diff --cc bse/Makefile.am
index f562cf9,cda233c..0d16dbb
--- a/bse/Makefile.am
+++ b/bse/Makefile.am
@@@ -30,73 -26,74 +26,77 @@@ bse_public_headers = $(strip
\
bsegentypes.h \
\
- bse.h bsedefs.h bseexports.h bseconfig.h bsegenclosures.h \
- bseincluder.h ladspa.h bseenginenode.h bseieee754.h \
- \
- bseengine.h bseenginemaster.h bseengineschedule.h bseengineutils.h \
- bsebus.h bsecategories.h \
- bsefilter.h bsebiquadfilter.h \
- bseconstant.h bseconstvalues.h bsecontainer.h bsecontextmerger.h \
- bsedatapocket.h bseeditablesample.h bseenums.h bsegconfig.h \
- bseglobals.h bseglue.h bseitem.h bsejanitor.h \
- bsemain.h bsemath.h bsemathsignal.h bseladspa.h \
- bsemidicontroller.h bsemididevice.h bsedevice.h \
- bsemididevice-null.h bsemididevice-oss.h bsemidievent.h bsemidinotifier.h \
- bsemidireceiver.h bsemidisynth.h bseobject.h bsepart.h \
- bsepcminput.h bsepcmoutput.h bseparam.h bseparasite.h \
- bsepcmdevice.h bsepcmdevice-oss.h bsepcmdevice-null.h bseplugin.h \
- bseprocedure.h bseproject.h bsescripthelper.h bseserver.h \
- bsesnet.h bsesnooper.h bsesong.h bsesequencer.h \
- bsesource.h bsestandardosc.h bsestandardsynths.h bsestorage.h \
- bseinstrumentoutput.h bsesubiport.h bseinstrumentinput.h bsesuboport.h \
- bsesubsynth.h bsesuper.h bsetrack.h bsetype.h \
- bseutils.h bsemidivoice.h bsewave.h bsewaveosc.h \
- bsecsynth.h bsewaverepo.h bseladspamodule.h bsepcmwriter.h \
- bsecompat.h bseundostack.h bsemidiinput.h bsemididecoder.h \
- bsenote.h bsemidifile.h bseblockutils.hh \
+ bse.hh bsedefs.hh bseexports.hh bseconfig.h bsegenclosures.hh \
+ bseincluder.hh ladspa.hh bseenginenode.hh bseieee754.hh \
+ bsecore.hh \
+ bseengine.hh bseenginemaster.hh bseengineschedule.hh bseengineutils.hh \
+ bsebus.hh bsecategories.hh \
+ bsefilter.hh bsebiquadfilter.hh \
+ bseconstant.hh bseconstvalues.hh bsecontainer.hh bsecontextmerger.hh \
+ bseclientapi.hh \
+ bsedatapocket.hh bseeditablesample.hh bseenums.hh bsegconfig.hh
\
+ bseglobals.hh bseglue.hh bseitem.hh bsejanitor.hh \
+ bsemain.hh bsemath.hh bsemathsignal.hh bseladspa.hh \
+ bsemidicontroller.hh bsemididevice.hh bsedevice.hh \
+ bsemididevice-null.hh bsemididevice-oss.hh bsemidievent.hh bsemidinotifier.hh \
+ bsemidireceiver.hh bsemidisynth.hh bseobject.hh bsepart.hh \
+ bsepcminput.hh bsepcmoutput.hh bseparam.hh bseparasite.hh \
+ bsepcmdevice.hh bsepcmdevice-oss.hh bsepcmdevice-null.hh bseplugin.hh \
+ bseprocedure.hh bseproject.hh bsescripthelper.hh bseserver.hh \
+ bsesnet.hh bsesnooper.hh bsesong.hh bsesequencer.hh \
+ bsesource.hh bsestandardosc.hh bsestandardsynths.hh bsestorage.hh \
+ bseinstrumentoutput.hh bsesubiport.hh bseinstrumentinput.hh bsesuboport.hh \
++ bsesoundfont.h bsesoundfontpreset.h bsesoundfontosc.h \
+ bsesubsynth.hh bsesuper.hh bsetrack.hh bsetype.hh \
+ bseutils.hh bsemidivoice.hh bsewave.hh bsewaveosc.hh \
+ bsecsynth.hh bsewaverepo.hh bseladspamodule.hh bsepcmwriter.hh \
+ bsecompat.hh bseundostack.hh bsemidiinput.hh bsemididecoder.hh \
+ bsenote.hh bsemidifile.hh bseblockutils.hh \
bsecxxvalue.hh bsecxxutils.hh bsecxxbase.hh bsecxxclosure.hh \
- bsecxxarg.hh bsecxxmodule.hh bsecxxplugin.hh bseloader.h \
- bseresampler.hh bseresamplerimpl.hh bsesoundfontrepo.h bsesoundfont.h \
- bsesoundfontpreset.h bsesoundfontosc.h \
+ bsecxxarg.hh bsecxxmodule.hh bsecxxplugin.hh bseloader.hh \
+ bseresampler.hh bseresamplerimpl.hh bsedatahandle-flac.hh \
+ testobject.hh \
)
# BSE C & C++ sources
bse_sources = $(strip \
- gslfft.c gsloscillator.c gsldatahandle.c gslwavechunk.c \
- gslfilter.c gslcommon.c \
- gsldatahandle-vorbis.c gslvorbis-enc.c gsldatacache.c gslvorbis-cutter.c \
- gsldatahandle-mad.c gslfilehash.c gsldatautils.c \
- gslwaveosc.c gslosctable.c gslmagic.c \
- \
- bseengine.c bseenginemaster.c bseengineschedule.c bseengineutils.c \
- bsebus.c bsecategories.c \
- bsefilter.cc bsebiquadfilter.c bsefilter-ellf.c \
- bseconstant.c bseconstvalues.c bsecontainer.c bsecontextmerger.c \
- bsedatapocket.c bseeditablesample.c bseenums.c bsegconfig.c \
- bseglobals.c bseglue.c bseitem.c bsejanitor.c \
- bsemain.cc bsemath.c bsemathsignal.c bseladspa.cc \
- bsemidicontroller.c bsemididevice.c bsedevice.c \
- bsemididevice-null.c bsemididevice-oss.c bsemidievent.c bsemidinotifier.c \
- bsemidireceiver.cc bsemidisynth.c bseobject.c bsepart.c \
- bsepcminput.c bsepcmoutput.c bseparam.c bseparasite.c \
- bsepcmdevice.c bsepcmdevice-oss.c bsepcmdevice-null.c bseplugin.c \
- bseprocedure.c bseproject.c bsescripthelper.c bseserver.c \
- bsesnet.c bsesnooper.c bsesong.c bsesequencer.cc \
- bsesource.c bsestandardosc.c bsestandardsynths.c bsestorage.c \
- bseinstrumentoutput.c bsesubiport.c bseinstrumentinput.c bsesuboport.c \
- bsesubsynth.c bsesuper.c bsetrack.c bsetype.c \
- bseutils.c bsemidivoice.c bsewave.c bsewaveosc.c \
- bsecsynth.c bsewaverepo.c bseladspamodule.c bsepcmwriter.c \
- bsecompat.c bseundostack.c bsemidiinput.c bsemididecoder.c \
- bsenote.cc bsemidifile.c bseblockutils.cc \
+ gslfft.cc gsloscillator.cc gsldatahandle.cc gslwavechunk.cc \
+ gslfilter.cc gslcommon.cc \
+ gsldatahandle-vorbis.cc gslvorbis-enc.cc gsldatacache.cc gslvorbis-cutter.cc \
+ gsldatahandle-mad.cc gslfilehash.cc gsldatautils.cc \
+ gslwaveosc.cc gslosctable.cc gslmagic.cc \
+ bsecore.cc \
+ bseengine.cc bseenginemaster.cc bseengineschedule.cc bseengineutils.cc \
+ bsebus.cc bsecategories.cc \
+ bsefilter.cc bsebiquadfilter.cc bsefilter-ellf.cc \
+ bseconstant.cc bseconstvalues.cc bsecontainer.cc bsecontextmerger.cc \
+ bsedatapocket.cc bseeditablesample.cc bseenums.cc bsegconfig.cc \
+ bseglobals.cc bseglue.cc bseitem.cc bsejanitor.cc \
+ bsemain.cc bsemath.cc bsemathsignal.cc bseladspa.cc \
+ bsemidicontroller.cc bsemididevice.cc bsedevice.cc \
+ bsemididevice-null.cc bsemididevice-oss.cc bsemidievent.cc bsemidinotifier.cc \
+ bsemidireceiver.cc bsemidisynth.cc bseobject.cc bsepart.cc \
+ bsepcminput.cc bsepcmoutput.cc bseparam.cc bseparasite.cc \
+ bsepcmdevice.cc bsepcmdevice-oss.cc bsepcmdevice-null.cc bseplugin.cc \
+ bseprocedure.cc bseproject.cc bsescripthelper.cc bseserver.cc \
+ bsesnet.cc bsesnooper.cc bsesong.cc bsesequencer.cc \
++ bsesoundfont.c bsesoundfontrepo.c bsesoundfontpreset.c bsesoundfontosc.c \
++ bsesoundfontrepo.c bsesoundfont.c bsesoundfontpreset.c bsesoundfontosc.c \
+ bsesource.cc bsestandardosc.cc bsestandardsynths.cc bsestorage.cc \
+ bseinstrumentoutput.cc bsesubiport.cc bseinstrumentinput.cc bsesuboport.cc \
+ bsesubsynth.cc bsesuper.cc bsetrack.cc bsetype.cc \
+ bseutils.cc bsemidivoice.cc bsewave.cc bsewaveosc.cc \
+ bsecsynth.cc bsewaverepo.cc bseladspamodule.cc bsepcmwriter.cc \
+ bsecompat.cc bseundostack.cc bsemidiinput.cc bsemididecoder.cc \
+ bsenote.cc bsemidifile.cc bseblockutils.cc \
bsecxxvalue.cc bsecxxutils.cc bsecxxbase.cc bsecxxclosure.cc \
- bsecxxarg.cc bsecxxmodule.cc bsecxxplugin.cc bseloader.c \
+ bsecxxarg.cc bsecxxmodule.cc bsecxxplugin.cc bseloader.cc \
bseresampler.cc bsedatahandle-resample.cc bsedatahandle-fir.cc \
- bseloader-aiff.c bseloader-guspatch.cc bseloader-oggvorbis.c bseloader-bsewave.c \
- bseloader-mad.c bseloader-wav.c \
+ bseloader-aiff.cc bseloader-guspatch.cc bseloader-oggvorbis.cc bseloader-bsewave.cc \
+ bseloader-mad.cc bseloader-wav.cc bseloader-flac.cc bsedatahandle-flac.cc
\
bsebusmodule.cc \
- bsecore.cc \
+ bsebasics.cc \
bseprobe.cc \
- bsesoundfontrepo.c bsesoundfont.c bsesoundfontpreset.c bsesoundfontosc.c \
+ testobject.cc \
)
# BSE Synthesis Modules
bse_idl_sources =
@@@ -118,22 -117,19 +120,20 @@@ bse_proc_sources = $(strip
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 \
+ bsesoundfontrepo.proc \
)
- bse_proc_gen_sources = $(bse_proc_sources:.proc=.genprc.c)
+ bse_proc_gen_sources = $(bse_proc_sources:.proc=.genprc.cc)
# non-compile and non-install sources required
EXTRA_DIST += $(strip \
- bsecore.idl bse.idl \
+ bsebasics.idl bse.idl \
mktypes.pl mkcalls.pl mkcproc.pl \
- bseconfig.h.in bsepcmmodule.c \
+ bseconfig.h.in bsepcmmodule.cc \
bsewave.header \
- gsl-fftgen.pl gsl-fftconf.sh gsloscillator-aux.c \
- gslincluder.c gslwaveosc-aux.c \
+ gsl-fftgen.pl gsl-fftconf.sh gsloscillator-aux.cc \
+ gslincluder.hh gslwaveosc-aux.cc \
+ bse-internals.hh \
)
- # -pthread -> -lpthread hack (required for libtool library linkage)
- pthread_2_lpthread = $(if $(findstring -pthread, $1), -lpthread)
-
#
# BSE library
#
diff --cc bse/bsedefs.hh
index 0000000,634e5df..f1f962e
mode 000000,100644..100644
--- a/bse/bsedefs.hh
+++ b/bse/bsedefs.hh
@@@ -1,0 -1,140 +1,146 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BSE_DEFS_H__
+ #define __BSE_DEFS_H__
+
+ #undef G_DISABLE_ASSERT
+ #undef G_DISABLE_CHECKS
+ #include <libintl.h>
+ #include <sfi/sfi.hh>
+ #include <sfi/sfistore.hh> // FIXME
+ #include <sfi/sficomwire.hh> // FIXME
+ #include <bse/bseconfig.h>
+
+ G_BEGIN_DECLS
+
+
+ /* --- some globally used macros --- */
+ #define BSE_VERSION_CMP(v1_major, v1_minor, v1_micro, v2_major, v2_minor, v2_micro) ( \
+ (v1_major != v2_major) ? (v1_major > v2_major ? +1 : -1) : \
+ (v1_minor != v2_minor) ? (v1_minor > v2_minor ? +1 : -1) : \
+ (v1_micro < v2_micro ? -1 : v1_micro > v2_micro))
+
+
+ /* --- BSE objects, classes & interfaces --- */
+ typedef struct _BseBinData BseBinData;
+ typedef struct _BseBinDataClass BseBinDataClass;
+ struct BseBus;
+ struct BseBusClass;
+ typedef struct _BseCapture BseCapture;
+ typedef struct _BseCaptureClass BseCaptureClass;
+ struct BseContainer;
+ struct BseContainerClass;
+ struct BseContextMerger;
+ struct BseContextMergerClass;
+ struct BseCSynth;
+ struct BseCSynthClass;
+ struct BseEditableSample;
+ struct BseEditableSampleClass;
+ struct BseItem;
+ struct BseItemClass;
+ struct BseJanitor;
+ struct BseJanitorClass;
+ struct BseMidiDecoder;
+ struct BseMidiNotifier;
+ struct BseMidiNotifierClass;
+ struct BseMidiReceiver;
+ struct BseMidiSynth;
+ struct BseMidiSynthClass;
+ struct BseMidiContext;
+ struct BseObject;
+ struct BseObjectClass;
+ struct BseParasite;
+ struct BsePart;
+ struct BsePartClass;
+ struct BsePcmWriter;
+ struct BsePcmWriterClass;
+ typedef struct _BseProcedureClass BseProcedureClass;
+ struct BseProject;
+ struct BseProjectClass;
+ typedef struct _BseScriptControl BseScriptControl;
+ typedef struct _BseScriptControlClass BseScriptControlClass;
+ struct BseServer;
+ struct BseServerClass;
+ struct BseSNet;
+ struct BseSNetClass;
+ struct BseSong;
+ struct BseSongClass;
+ typedef struct _BseSongSequencer BseSongSequencer;
++typedef struct _BseSoundFont BseSoundFont;
++typedef struct _BseSoundFontClass BseSoundFontClass;
++typedef struct _BseSoundFontPreset BseSoundFontPreset;
++typedef struct _BseSoundFontPresetClass BseSoundFontPresetClass;
++typedef struct _BseSoundFontRepo BseSoundFontRepo;
++typedef struct _BseSoundFontRepoClass BseSoundFontRepoClass;
+ struct BseSource;
+ struct BseSourceClass;
+ struct BseStorage;
+ struct BseStorageClass;
+ struct BseSubSynth;
+ struct BseSubSynthClass;
+ struct BseSuper;
+ struct BseSuperClass;
+ struct BseTrack;
+ struct BseTrackClass;
+ typedef struct _BseTrans BseTrans;
+ typedef struct _BseUndoStack BseUndoStack;
+ typedef struct _BseUndoStep BseUndoStep;
+ typedef struct _BseVirtualThroughput BseVirtualThroughput;
+ typedef struct _BseVirtualThroughputClass BseVirtualThroughputClass;
+ typedef struct _BseVoice BseVoice;
+ struct BseWave;
+ struct BseWaveRepo;
+ struct BseWaveRepoClass;
+ /* --- BseModule special handling --- */
+ typedef struct _BseModule BseModule;
+ typedef struct _BseModuleClass BseModuleClass;
+ typedef struct _BseIStream BseIStream;
+ typedef struct _BseJStream BseJStream;
+ typedef struct _BseOStream BseOStream;
+ /* dereference some BseModule members without including bseengine.hh */
+ #define BSE_MODULE_GET_USER_DATA(bsemodule) (((gpointer*) bsemodule)[1])
+ #define BSE_MODULE_GET_ISTREAMSP(bsemodule) (((gpointer*) bsemodule)[2])
+ #define BSE_MODULE_GET_JSTREAMSP(bsemodule) (((gpointer*) bsemodule)[3])
+ #define BSE_MODULE_GET_OSTREAMSP(bsemodule) (((gpointer*) bsemodule)[4])
+ /* --- Bse Loader --- */
+ struct BseLoader;
+ typedef struct _BseWaveDsc BseWaveDsc;
+ typedef struct _BseWaveChunkDsc BseWaveChunkDsc;
+ /* --- BSE aux structures --- */
+ typedef struct _BseExportNode BseExportNode;
+ typedef struct _BseExportNodeBoxed BseExportNodeBoxed;
+ typedef struct _BseGlobals BseGlobals;
+ struct BsePlugin;
+ struct BsePluginClass;
+ /* --- BSE function types --- */
+ typedef void (*BseFunc) (void);
+ typedef void (*BseFreeFunc) (gpointer data);
+ typedef gboolean (*BseIOWatch) (gpointer data,
+ guint n_pfds,
+ GPollFD *pfd);
+ typedef GTokenType (*BseTryStatement) (gpointer context_data,
+ BseStorage *storage,
+ GScanner *scanner,
+ gpointer user_data);
+ typedef BseObject* (*BseUPathResolver) (gpointer func_data,
+ GType required_type,
+ const gchar *path,
+ gchar **error);
+ typedef gboolean (*BseProcedureShare) (gpointer func_data,
+ const gchar *proc_name,
+ gfloat progress);
+ typedef gboolean (*BseCategoryForeach) (const gchar *category_path,
+ GType type,
+ gpointer user_data);
+ typedef void (*BseEngineAccessFunc) (BseModule *module,
+ gpointer data);
+
+
+
+ /* --- i18n and gettext helpers --- */
+ const gchar* bse_gettext (const gchar *text);
+ #define _(str) bse_gettext (str)
+ #define N_(str) (str)
+
+ G_END_DECLS
+
+ #endif /* __BSE_DEFS_H__ */
diff --cc bse/bsemidireceiver.cc
index e831b2e,b72aa52..5ce7e47
--- a/bse/bsemidireceiver.cc
+++ b/bse/bsemidireceiver.cc
@@@ -1,48 -1,27 +1,29 @@@
- /* BSE - Bedevilled Sound Engine
- * Copyright (C) 1996-1999, 2000-2004 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 "bsemidireceiver.h"
-
- #include "bsemain.h"
- #include "gslcommon.h"
- #include "bseengine.h"
- #include "bsemathsignal.h"
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bsemidireceiver.hh"
+
+ #include "bsemain.hh"
+ #include "gslcommon.hh"
+ #include "bseengine.hh"
+ #include "bsemathsignal.hh"
#include "bsecxxutils.hh"
- #include "bsemidinotifier.h"
+ #include "bsemidinotifier.hh"
#include <string.h>
- #include <sfi/gbsearcharray.h>
+ #include <sfi/gbsearcharray.hh>
#include <map>
#include <set>
+#include <list>
+
namespace {
using namespace Bse;
- using namespace Birnet;
using namespace std;
- static SFI_MSG_TYPE_DEFINE (debug_midi_receiver, "midi-receiver", SFI_MSG_DEBUG, NULL);
- #define DEBUG(...) sfi_debug (debug_midi_receiver, __VA_ARGS__)
- static SFI_MSG_TYPE_DEFINE (debug_midi_events, "midi-events", SFI_MSG_DEBUG, NULL);
- #define DEBUG_EVENTS(...) sfi_debug (debug_midi_events, __VA_ARGS__)
+ #define MDEBUG(...) BSE_KEY_DEBUG ("midi-receiver", __VA_ARGS__)
+ #define EDEBUG(...) BSE_KEY_DEBUG ("midi-events", __VA_ARGS__)
/* --- variables --- */
- static BirnetMutex global_midi_mutex = { 0, };
- #define BSE_MIDI_RECEIVER_LOCK() GSL_SPIN_LOCK (&global_midi_mutex)
- #define BSE_MIDI_RECEIVER_UNLOCK() GSL_SPIN_UNLOCK (&global_midi_mutex)
-
+ static Bse::Mutex global_midi_mutex;
+ #define BSE_MIDI_RECEIVER_LOCK() global_midi_mutex.lock()
+ #define BSE_MIDI_RECEIVER_UNLOCK() global_midi_mutex.unlock()
/********************************************************************************
*
@@@ -2103,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_MIDI_SIGNAL_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,
- 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,
- 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,
- 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:
- DEBUG_EVENTS ("MidiChannel[%u]: NoteOn %fHz Velo=%f (stamp:%llu)", event->channel,
- event->data.note.frequency, event->data.note.velocity, event->delta_time);
++ 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:
- DEBUG_EVENTS ("MidiChannel[%u]: %s %fHz (stamp:%llu)", event->channel,
- event->status == BSE_MIDI_NOTE_OFF ? "NoteOff" : "NotePressure",
- event->data.note.frequency, event->delta_time);
++ 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));
+ 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:
- DEBUG_EVENTS ("MidiChannel[%u]: Control %2u Value=%f (stamp:%llu)", event->channel,
- event->data.control.control, event->data.control.value, event->delta_time);
++ 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:
- DEBUG_EVENTS ("MidiChannel[%u]: X Continuous Control %2u Value=%f (stamp:%llu)", event->channel,
- event->data.control.control, event->data.control.value, event->delta_time);
++ 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:
- DEBUG_EVENTS ("MidiChannel[%u]: Program %u (Value=%f) (stamp:%llu)", event->channel,
- event->data.program, event->data.program / (gfloat) 0x7f, event->delta_time);
++ 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,
+ trans);
+ break;
+ case BSE_MIDI_CHANNEL_PRESSURE:
- DEBUG_EVENTS ("MidiChannel[%u]: Channel Pressure Value=%f (stamp:%llu)", event->channel,
- event->data.intensity, event->delta_time);
++ 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,
+ trans);
+ break;
+ case BSE_MIDI_PITCH_BEND:
- DEBUG_EVENTS ("MidiChannel[%u]: Pitch Bend Value=%f (stamp:%llu)", event->channel,
- event->data.pitch_bend, event->delta_time);
++ 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,
+ trans);
+ break;
+ default:
- DEBUG_EVENTS ("MidiChannel[%u]: Ignoring Event %u (stamp:%llu)", event->channel,
- event->status, event->delta_time);
++ EDEBUG ("MidiChannel[%u]: Ignoring Event %u (stamp:%llu)", event->channel,
++ event->status, event->delta_time);
+ break;
+ }
}
if (self->notifier)
{
diff --cc bse/bsemidireceiver.hh
index 0000000,915de2c..d7a1de6
mode 000000,100644..100644
--- a/bse/bsemidireceiver.hh
+++ b/bse/bsemidireceiver.hh
@@@ -1,0 -1,102 +1,116 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BSE_MIDI_RECEIVER_H__
+ #define __BSE_MIDI_RECEIVER_H__
+
+ #include <bse/bseobject.hh>
+ #include <bse/bsemidievent.hh>
+
+ G_BEGIN_DECLS
+
+
+ /* --- API --- */
+ #define BSE_MIDI_CONTROL_MODULE_N_CHANNELS (4)
+ #define BSE_MIDI_VOICE_MODULE_N_CHANNELS (4)
+ #define BSE_MIDI_VOICE_N_CHANNELS (3)
+ typedef void (*BseMidiControlHandler) (gpointer handler_data,
+ guint64 tick_stamp,
+ BseMidiSignalType signal_type,
+ gfloat control_value,
+ guint n_modules,
+ BseModule *const *modules,
+ gpointer user_data,
+ BseTrans *trans);
++typedef void (*BseMidiEventHandler) (gpointer handler_data,
++ BseModule *module,
++ const BseMidiEvent *event,
++ BseTrans *trans);
+ BseMidiReceiver* bse_midi_receiver_new (const gchar *receiver_name);
+ BseMidiReceiver* bse_midi_receiver_ref (BseMidiReceiver *self);
+ void bse_midi_receiver_unref (BseMidiReceiver *self);
+ void bse_midi_receiver_push_event (BseMidiReceiver *self,
+ BseMidiEvent *event);
+ void bse_midi_receiver_process_events (BseMidiReceiver *self,
+ guint64 max_tick_stamp);
+ BseModule* bse_midi_receiver_retrieve_control_module (BseMidiReceiver *self,
+ guint midi_channel,
+ BseMidiSignalType
signals[BSE_MIDI_CONTROL_MODULE_N_CHANNELS],
+ BseTrans *trans);
+ void bse_midi_receiver_discard_control_module (BseMidiReceiver *self,
+ BseModule *cmodule,
+ BseTrans *trans);
+ gboolean bse_midi_receiver_add_control_handler (BseMidiReceiver *self,
+ guint midi_channel,
+ BseMidiSignalType signal_type,
+ BseMidiControlHandler handler_func,
+ gpointer handler_data,
+ BseModule *module);
+ void bse_midi_receiver_set_control_handler_data(BseMidiReceiver *self,
+ guint midi_channel,
+ BseMidiSignalType signal_type,
+ BseMidiControlHandler handler_func,
+ gpointer handler_data,
+ gpointer extra_data,
+ BseFreeFunc extra_free); /* UserThread */
+ void bse_midi_receiver_remove_control_handler (BseMidiReceiver *self,
+ guint midi_channel,
+ BseMidiSignalType signal_type,
+ BseMidiControlHandler handler_func,
+ gpointer handler_data,
+ BseModule *module);
++void bse_midi_receiver_add_event_handler (BseMidiReceiver *self,
++ guint midi_channel,
++ BseMidiEventHandler handler_func,
++ gpointer handler_data,
++ BseModule *module);
++void bse_midi_receiver_remove_event_handler (BseMidiReceiver *self,
++ guint midi_channel,
++ BseMidiEventHandler handler_func,
++ gpointer handler_data,
++ BseModule *module);
+ BseModule* bse_midi_receiver_retrieve_mono_voice (BseMidiReceiver *self,
+ guint midi_channel,
+ BseTrans *trans);
+ void bse_midi_receiver_discard_mono_voice (BseMidiReceiver *self,
+ guint midi_channel,
+ BseModule *fmodule,
+ BseTrans *trans);
+ void bse_midi_receiver_channel_enable_poly (BseMidiReceiver *self,
+ guint midi_channel);
+ void bse_midi_receiver_channel_disable_poly (BseMidiReceiver *self,
+ guint midi_channel);
+ guint bse_midi_receiver_create_poly_voice (BseMidiReceiver *self,
+ guint midi_channel,
+ BseTrans *trans);
+ void bse_midi_receiver_discard_poly_voice (BseMidiReceiver *self,
+ guint midi_channel,
+ guint voice_id,
+ BseTrans *trans);
+ BseModule* bse_midi_receiver_get_poly_voice_input (BseMidiReceiver *self,
+ guint midi_channel,
+ guint voice_id);
+ BseModule* bse_midi_receiver_get_poly_voice_output (BseMidiReceiver *self,
+ guint midi_channel,
+ guint voice_id);
+ BseModule* bse_midi_receiver_create_sub_voice (BseMidiReceiver *self,
+ guint midi_channel,
+ guint voice_id,
+ BseTrans *trans);
+ void bse_midi_receiver_discard_sub_voice (BseMidiReceiver *self,
+ guint midi_channel,
+ guint voice_id,
+ BseModule *fmodule,
+ BseTrans *trans);
+ void bse_midi_receiver_set_notifier (BseMidiReceiver *self,
+ BseMidiNotifier *notifier);
+ gboolean bse_midi_receiver_has_notify_events (BseMidiReceiver *self);
+ SfiRing* bse_midi_receiver_fetch_notify_events (BseMidiReceiver *self);
+ gboolean bse_midi_receiver_voices_pending (BseMidiReceiver *self,
+ guint midi_channel);
+ void bse_midi_receiver_enter_farm (BseMidiReceiver *self);
+ void bse_midi_receiver_farm_distribute_event (BseMidiEvent *event);
+ void bse_midi_receiver_farm_process_events (guint64 max_tick_stamp);
+ void bse_midi_receiver_leave_farm (BseMidiReceiver *self);
+
+ G_END_DECLS
+
+ #endif /* __BSE_MIDI_RECEIVER_H__ */
diff --cc bse/bseproject.cc
index 0000000,e278a35..039c21b
mode 000000,100644..100644
--- a/bse/bseproject.cc
+++ b/bse/bseproject.cc
@@@ -1,0 -1,965 +1,990 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bseproject.hh"
+
+ #include "bsesuper.hh"
+ #include "bsestorage.hh"
+ #include "bsesong.hh"
+ #include "bsesnet.hh"
+ #include "bsecsynth.hh"
+ #include "bsewaverepo.hh"
+ #include "bsesequencer.hh"
+ #include "bseserver.hh"
+ #include "bseundostack.hh"
+ #include "bsemain.hh"
+ #include "bsestandardsynths.hh"
+ #include "bsemidireceiver.hh"
+ #include "bsemidinotifier.hh"
+ #include "gslcommon.hh"
+ #include "bseengine.hh"
++#include "bsesoundfontrepo.h"
+ #include <string.h>
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ #include <errno.h>
+
+
+ typedef struct {
+ GType base_type;
+ gboolean intern_children;
+ guint max_items;
+ GSList *items;
+ } StorageTrap;
+
+ /* --- macros --- */
+ #define parse_or_return bse_storage_scanner_parse_or_return
+ #define peek_or_return bse_storage_scanner_peek_or_return
+
+ enum {
+ PARAM_0,
+ PARAM_DIRTY
+ };
+
+
+ /* --- prototypes --- */
+ static void bse_project_class_init (BseProjectClass *klass);
+ static void bse_project_class_finalize (BseProjectClass *klass);
+ static void bse_project_init (BseProject *project,
+ gpointer rclass);
+ static void bse_project_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+ static void bse_project_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+ static void bse_project_finalize (GObject *object);
+ static void bse_project_release_children (BseContainer *container);
+ static void bse_project_dispose (GObject *object);
+ static void bse_project_add_item (BseContainer *container,
+ BseItem *item);
+ static void bse_project_remove_item (BseContainer *container,
+ BseItem *item);
+ static void bse_project_forall_items (BseContainer *container,
+ BseForallItemsFunc func,
+ gpointer data);
+ static BseItem* bse_project_retrieve_child (BseContainer *container,
+ GType child_type,
+ const gchar *uname);
+ static void bse_project_prepare (BseSource *source);
+ static gboolean project_check_restore (BseContainer *container,
+ const gchar *child_type);
+ static BseUndoStack* bse_project_get_undo (BseItem *item);
+
+
+ /* --- variables --- */
+ static GTypeClass *parent_class = NULL;
+ static guint signal_state_changed = 0;
+ static GQuark quark_storage_trap = 0;
+
+
+ /* --- functions --- */
+ BSE_BUILTIN_TYPE (BseProject)
+ {
+ static const GTypeInfo project_info = {
+ sizeof (BseProjectClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) bse_project_class_init,
+ (GClassFinalizeFunc) bse_project_class_finalize,
+ NULL /* class_data */,
+
+ sizeof (BseProject),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) bse_project_init,
+ };
+
+ return bse_type_register_static (BSE_TYPE_CONTAINER,
+ "BseProject",
+ "BSE Super container type",
+ __FILE__, __LINE__,
+ &project_info);
+ }
+
+ static void
+ bse_project_class_init (BseProjectClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ BseObjectClass *object_class = BSE_OBJECT_CLASS (klass);
+ BseItemClass *item_class = BSE_ITEM_CLASS (klass);
+ BseSourceClass *source_class = BSE_SOURCE_CLASS (klass);
+ BseContainerClass *container_class = BSE_CONTAINER_CLASS (klass);
+
+ parent_class = (GTypeClass*) g_type_class_peek_parent (klass);
+ quark_storage_trap = g_quark_from_static_string ("bse-project-storage-trap");
+
+ gobject_class->set_property = bse_project_set_property;
+ gobject_class->get_property = bse_project_get_property;
+ gobject_class->dispose = bse_project_dispose;
+ gobject_class->finalize = bse_project_finalize;
+
+ item_class->get_undo = bse_project_get_undo;
+
+ source_class->prepare = bse_project_prepare;
+
+ container_class->add_item = bse_project_add_item;
+ container_class->remove_item = bse_project_remove_item;
+ container_class->forall_items = bse_project_forall_items;
+ container_class->check_restore = project_check_restore;
+ container_class->retrieve_child = bse_project_retrieve_child;
+ container_class->release_children = bse_project_release_children;
+
+ bse_object_class_add_param (object_class, "State",
+ PARAM_DIRTY,
+ sfi_pspec_bool ("dirty", NULL, "Whether project needs saving",
+ FALSE, "r"));
+
+ signal_state_changed = bse_object_class_add_signal (object_class, "state-changed",
+ G_TYPE_NONE,
+ 1, BSE_TYPE_PROJECT_STATE);
+ }
+
+ static void
+ bse_project_class_finalize (BseProjectClass *klass)
+ {
+ }
+
+ static void
+ undo_notify (BseProject *project,
+ BseUndoStack *ustack,
+ gboolean step_added)
+ {
+ g_object_notify ((GObject*) project, "dirty");
+ if (step_added && !project->in_redo)
+ {
+ bse_undo_stack_force_dirty (project->undo_stack);
+ bse_undo_stack_clear (project->redo_stack);
+ }
+ }
+
+ static void
+ redo_notify (BseProject *project,
+ BseUndoStack *ustack,
+ gboolean step_added)
+ {
+ g_object_notify ((GObject*) project, "dirty");
+ }
+
+ static void
+ bse_project_init (BseProject *self,
+ gpointer rclass)
+ {
+ self->state = BSE_PROJECT_INACTIVE;
+ self->supers = NULL;
+ self->items = NULL;
+ self->in_undo = FALSE;
+ self->in_redo = FALSE;
+ self->undo_stack = bse_undo_stack_new (self, undo_notify);
+ self->redo_stack = bse_undo_stack_new (self, redo_notify);
+ self->deactivate_usecs = 3 * 1000000;
+ self->midi_receiver = bse_midi_receiver_new ("BseProjectReceiver");
+ bse_midi_receiver_enter_farm (self->midi_receiver);
+ /* we always have a wave-repo */
- BseWaveRepo *wrepo = (BseWaveRepo*) bse_container_new_child (BSE_CONTAINER (self), BSE_TYPE_WAVE_REPO,
"uname", "Wave-Repository", NULL);
++ BseWaveRepo *wrepo = bse_container_new_child (BSE_CONTAINER (self), BSE_TYPE_WAVE_REPO,
++ "uname", "Wave-Repository",
++ NULL);
++ BseSoundFontRepo *sfrepo = bse_container_new_child (BSE_CONTAINER (self), BSE_TYPE_SOUND_FONT_REPO,
++ "uname", "Sound-Font-Repository",
++ NULL);
+ /* with fixed uname */
+ BSE_OBJECT_SET_FLAGS (wrepo, BSE_OBJECT_FLAG_FIXED_UNAME);
++ BSE_OBJECT_SET_FLAGS (sfrepo, BSE_OBJECT_FLAG_FIXED_UNAME);
+ }
+
+ static void
+ bse_project_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+ {
+ BseProject *self = BSE_PROJECT (object);
+
+ switch (param_id)
+ {
+ case PARAM_DIRTY:
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
+ break;
+ }
+ }
+
+ static void
+ bse_project_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+ {
+ BseProject *self = BSE_PROJECT (object);
+
+ switch (param_id)
+ {
+ case PARAM_DIRTY:
+ sfi_value_set_bool (value, bse_undo_stack_dirty (self->undo_stack));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
+ break;
+ }
+ }
+
+ static void
+ bse_project_release_children (BseContainer *container)
+ {
+ BseProject *project = BSE_PROJECT (container);
+
+ while (project->items)
+ bse_container_remove_item (BSE_CONTAINER (project), (BseItem*) project->items->data);
+ while (project->supers)
+ bse_container_remove_item (BSE_CONTAINER (project), (BseItem*) project->supers->data);
+
+ /* chain parent class' handler */
+ BSE_CONTAINER_CLASS (parent_class)->release_children (container);
+ }
+
+ static void
+ bse_project_dispose (GObject *object)
+ {
+ BseProject *self = BSE_PROJECT (object);
+
+ bse_project_deactivate (self);
+
+ bse_undo_stack_limit (self->undo_stack, 0);
+ bse_undo_stack_limit (self->redo_stack, 0);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+ }
+
+ static void
+ bse_project_finalize (GObject *object)
+ {
+ BseProject *self = BSE_PROJECT (object);
+
+ bse_midi_receiver_unref (self->midi_receiver);
+ self->midi_receiver = NULL;
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+
+ bse_undo_stack_destroy (self->undo_stack);
+ bse_undo_stack_destroy (self->redo_stack);
+ }
+
+ static BseUndoStack*
+ bse_project_get_undo (BseItem *item)
+ {
+ BseProject *self = BSE_PROJECT (item);
+ return self->in_undo ? self->redo_stack : self->undo_stack;
+ }
+
+ void
+ bse_project_clear_undo (BseProject *self)
+ {
+ g_return_if_fail (BSE_IS_PROJECT (self));
+ if (!self->in_undo && !self->in_redo)
+ {
+ bse_undo_stack_clear (self->undo_stack);
+ bse_undo_stack_clear (self->redo_stack);
+ g_object_notify ((GObject*) self, "dirty");
+ }
+ }
+
+ void
+ bse_project_clean_dirty (BseProject *self)
+ {
+ g_return_if_fail (BSE_IS_PROJECT (self));
+ bse_undo_stack_clean_dirty (self->undo_stack);
+ bse_undo_stack_clean_dirty (self->redo_stack);
+ g_object_notify ((GObject*) self, "dirty");
+ }
+
+ static void
+ project_undo_do_deactivate (BseUndoStep *ustep,
+ BseUndoStack *ustack)
+ {
+ BseProject *self = (BseProject*) bse_undo_pointer_unpack ((const char*) ustep->data[0].v_pointer, ustack);
+ bse_project_deactivate (self);
+ }
+
+ static void
+ project_undo_do_deactivate_free (BseUndoStep *ustep)
+ {
+ g_free (ustep->data[0].v_pointer);
+ }
+
+ void
+ bse_project_push_undo_silent_deactivate (BseProject *self)
+ {
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ /* certain things work only (can only be undone/redone) in deactivated projects,
+ * so we need to push an undo step here. this step isn't required however
+ * if there're no undo steps pushed so far, and it shouldn't be visible
+ * as a seperate undo step to the user either. so what we do is to push
+ * an "add-on" step, which just prepares state for execution of further
+ * undo steps, if there are any pending.
+ */
+ if (self->state != BSE_PROJECT_INACTIVE)
+ {
+ BseUndoStack *ustack = bse_item_undo_open (self, "deactivate-project");
+ BseUndoStep *ustep = bse_undo_step_new (project_undo_do_deactivate, project_undo_do_deactivate_free,
1);
+ ustep->data[0].v_pointer = bse_undo_pointer_pack (self, ustack);
+ bse_undo_stack_push_add_on (ustack, ustep);
+ bse_item_undo_close (ustack);
+
+ gboolean in_undo = self->in_undo;
+ self->in_undo = !in_undo; /* swap undo<=>redo */
+ ustack = bse_item_undo_open (self, "deactivate-project");
+ ustep = bse_undo_step_new (project_undo_do_deactivate, project_undo_do_deactivate_free, 1);
+ ustep->data[0].v_pointer = bse_undo_pointer_pack (self, ustack);
+ bse_undo_stack_push_add_on (ustack, ustep);
+ bse_item_undo_close (ustack);
+ self->in_undo = in_undo; /* swap undo<=>redo */
+ }
+ }
+
+ static void
+ bse_project_add_item (BseContainer *container,
+ BseItem *item)
+ {
+ BseProject *self = BSE_PROJECT (container);
+
+ if (BSE_IS_SUPER (item))
+ self->supers = g_slist_append (self->supers, item);
+ else
+ self->items = g_slist_append (self->items, item);
+
+ /* chain parent class' add_item handler */
+ BSE_CONTAINER_CLASS (parent_class)->add_item (container, item);
+ }
+
+ static void
+ bse_project_remove_item (BseContainer *container,
+ BseItem *item)
+ {
+ BseProject *self = BSE_PROJECT (container);
+
+ /* chain parent class' remove_item handler */
+ BSE_CONTAINER_CLASS (parent_class)->remove_item (container, item);
+
+ if (BSE_IS_SUPER (item))
+ self->supers = g_slist_remove (self->supers, item);
+ else
+ self->items = g_slist_remove (self->items, item);
+ }
+
+ static void
+ bse_project_forall_items (BseContainer *container,
+ BseForallItemsFunc func,
+ gpointer data)
+ {
+ BseProject *self = BSE_PROJECT (container);
+ GSList *slist;
+
+ slist = self->supers;
+ while (slist)
+ {
+ BseItem *item = (BseItem*) slist->data;
+ slist = slist->next;
+ if (!func (item, data))
+ return;
+ }
+
+ slist = self->items;
+ while (slist)
+ {
+ BseItem *item = (BseItem*) slist->data;
+ slist = slist->next;
+ if (!func (item, data))
+ return;
+ }
+ }
+
+ static BseItem*
+ bse_project_retrieve_child (BseContainer *container,
+ GType child_type,
+ const gchar *uname)
+ {
+ BseProject *self = BSE_PROJECT (container);
+
+ /* always hand out the same wave repo */
+ if (g_type_is_a (child_type, BSE_TYPE_WAVE_REPO))
+ {
+ GSList *slist;
+
+ for (slist = self->supers; slist; slist = slist->next)
+ if (g_type_is_a (G_OBJECT_TYPE (slist->data), BSE_TYPE_WAVE_REPO))
+ return (BseItem*) slist->data;
+ g_warning ("%s: no wave-repo found in project\n", G_STRLOC);
+ return NULL; /* shouldn't happen */
+ }
++ else if (g_type_is_a (child_type, BSE_TYPE_SOUND_FONT_REPO)) /* and the same sound font repo */
++ {
++ BseSoundFontRepo *sfrepo = bse_project_get_sound_font_repo (self);
++ if (!sfrepo)
++ g_warning ("%s: no sound-font-repo found in project\n", G_STRLOC);
++ return BSE_ITEM (sfrepo);
++ }
+ else
+ {
+ BseItem *item = BSE_CONTAINER_CLASS (parent_class)->retrieve_child (container, child_type, uname);
+ StorageTrap *strap = (StorageTrap*) g_object_get_qdata ((GObject*) self, quark_storage_trap);
+ if (item && strap)
+ {
+ if (strap->intern_children)
+ bse_item_set_internal (item, TRUE);
+ strap->items = g_slist_prepend (strap->items, item);
+ strap->max_items--;
+ }
+ return item;
+ }
+ }
+
+ static gboolean
+ add_item_upaths (BseItem *item,
+ gpointer data_p)
+ {
+ gpointer *data = (void**) data_p;
+ BseStringSeq *sseq = (BseStringSeq*) data[0];
+ GType item_type = (GType) data[1];
+ BseContainer *container = (BseContainer*) data[2];
+
+ if (g_type_is_a (BSE_OBJECT_TYPE (item), item_type))
+ {
+ gchar *upath = bse_container_make_upath (container, item);
+ bse_string_seq_append (sseq, upath);
+ g_free (upath);
+ }
+ if (BSE_IS_CONTAINER (item))
+ bse_container_forall_items (BSE_CONTAINER (item), add_item_upaths, data);
+
+ return TRUE;
+ }
+
+ BseStringSeq*
+ bse_project_list_upaths (BseProject *self,
+ GType item_type)
+ {
+ gpointer data[3];
+ BseStringSeq *sseq;
+
+ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
+ g_return_val_if_fail (g_type_is_a (item_type, BSE_TYPE_ITEM), NULL);
+
+ sseq = bse_string_seq_new ();
+ data[0] = sseq;
+ data[1] = (gpointer) item_type;
+ data[2] = self;
+ bse_container_forall_items (BSE_CONTAINER (self), add_item_upaths, data);
+
+ return sseq;
+ }
+
+ static GSList*
+ compute_missing_supers (BseProject *self,
+ BseStorage *storage)
+ {
+ BseItem *project_item = BSE_ITEM (self);
+ GSList *targets = NULL, *missing = sfi_ppool_slist (storage->referenced_items);
+ while (missing)
+ {
+ BseItem *item = (BseItem*) g_slist_pop_head (&missing);
+ BseSuper *super = bse_item_get_super (item);
+ if (BSE_ITEM (super)->parent == project_item &&
+ !sfi_ppool_lookup (storage->stored_items, super))
+ targets = g_slist_prepend (targets, super);
+ }
+ return targets;
+ }
+
+ BseErrorType
+ bse_project_store_bse (BseProject *self,
+ BseSuper *super,
+ const gchar *bse_file,
+ gboolean self_contained)
+ {
+ BseStorage *storage;
+ GSList *slist = NULL;
+ gchar *string;
+ guint l, flags;
+ gint fd;
+
+ g_return_val_if_fail (BSE_IS_PROJECT (self), BSE_ERROR_INTERNAL);
+ if (super)
+ {
+ g_return_val_if_fail (BSE_IS_SUPER (super), BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (BSE_ITEM (super)->parent == BSE_ITEM (self), BSE_ERROR_INTERNAL);
+ }
+ g_return_val_if_fail (bse_file != NULL, BSE_ERROR_INTERNAL);
+
+ fd = open (bse_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ if (fd < 0)
+ return bse_error_from_errno (errno, BSE_ERROR_FILE_OPEN_FAILED);
+
+ storage = (BseStorage*) g_object_new (BSE_TYPE_STORAGE, NULL);
+ flags = 0;
+ if (self_contained)
+ flags |= BSE_STORAGE_SELF_CONTAINED;
+ bse_storage_prepare_write (storage, BseStorageMode (flags));
+
+ slist = g_slist_prepend (slist, super ? (void*) super : (void*) self);
+ while (slist)
+ {
+ BseItem *item = (BseItem*) g_slist_pop_head (&slist);
+ if (item == (BseItem*) self)
+ bse_storage_store_item (storage, item);
+ else
+ bse_storage_store_child (storage, item);
+ slist = g_slist_concat (compute_missing_supers (self, storage), slist);
+ }
+
+ string = g_strdup_format ("; BseProject\n\n"); /* %010o mflags */
+ do
+ l = write (fd, string, strlen (string));
+ while (l < 0 && errno == EINTR);
+ g_free (string);
+
+ BseErrorType error = bse_storage_flush_fd (storage, fd);
+ if (close (fd) < 0 && error == BSE_ERROR_NONE)
+ error = bse_error_from_errno (errno, BSE_ERROR_FILE_WRITE_FAILED);
+ bse_storage_reset (storage);
+ g_object_unref (storage);
+
+ return error;
+ }
+
+ BseErrorType
+ bse_project_restore (BseProject *self,
+ BseStorage *storage)
+ {
+ GScanner *scanner;
+ GTokenType expected_token = G_TOKEN_NONE;
+
+ g_return_val_if_fail (BSE_IS_PROJECT (self), BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (BSE_IS_STORAGE (storage), BSE_ERROR_INTERNAL);
+
+ scanner = bse_storage_get_scanner (storage);
+ g_return_val_if_fail (scanner != NULL, BSE_ERROR_INTERNAL);
+
+ g_object_ref (self);
+
+ expected_token = bse_storage_restore_item (storage, BSE_ITEM (self));
+ if (expected_token != G_TOKEN_NONE)
+ bse_storage_unexp_token (storage, expected_token);
+
+ bse_storage_finish_parsing (storage);
+
+ GSList *slist = self->supers;
+ while (slist)
+ {
+ BseSuper *super = (BseSuper*) slist->data;
+ slist = slist->next;
+ BseSuperClass *super_class = BSE_SUPER_GET_CLASS (super);
+ super_class->compat_finish (super, storage->major_version, storage->minor_version,
storage->micro_version);
+ }
+
+ bse_undo_stack_force_dirty (self->undo_stack);
+
+ g_object_unref (self);
+
+ return (scanner->parse_errors >= scanner->max_parse_errors ?
+ BSE_ERROR_PARSE_ERROR :
+ BSE_ERROR_NONE);
+ }
+
+ BseObject*
+ bse_project_upath_resolver (gpointer func_data,
+ GType required_type,
+ const gchar *upath,
+ gchar **error_p)
+ {
+ BseProject *self = (BseProject*) func_data;
+ gpointer item = NULL;
+
+ if (error_p)
+ *error_p = NULL;
+ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
+ g_return_val_if_fail (upath != NULL, NULL);
+
+ /* FIXME: need error handling, warnings.... */
+
+ if (g_type_is_a (required_type, BSE_TYPE_ITEM))
+ item = bse_container_resolve_upath (BSE_CONTAINER (self), upath);
+ else if (error_p)
+ *error_p = g_strdup_format ("unable to resolve object of type `%s' from upath: %s", g_type_name
(required_type), upath);
+
+ return (BseObject*) item;
+ }
+
+ BseItem*
+ bse_project_lookup_typed_item (BseProject *self,
+ GType item_type,
+ const gchar *uname)
+ {
+ BseItem *item;
+
+ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
+ g_return_val_if_fail (uname != NULL, NULL);
+
+ item = bse_container_lookup_item (BSE_CONTAINER (self), uname);
+ if (item && G_OBJECT_TYPE (item) == item_type)
+ return item;
+
+ return NULL;
+ }
+
+ BseWaveRepo*
+ bse_project_get_wave_repo (BseProject *self)
+ {
+ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
+ GSList *slist;
+ for (slist = self->supers; slist; slist = slist->next)
+ if (BSE_IS_WAVE_REPO (slist->data))
+ return (BseWaveRepo*) slist->data;
+ return NULL;
+ }
+
++BseSoundFontRepo*
++bse_project_get_sound_font_repo (BseProject *self)
++{
++ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
++ GSList *slist;
++ for (slist = self->supers; slist; slist = slist->next)
++ if (BSE_IS_SOUND_FONT_REPO (slist->data))
++ return slist->data;
++ return NULL;
++}
++
+ BseSong*
+ bse_project_get_song (BseProject *self)
+ {
+ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
+ GSList *slist;
+ for (slist = self->supers; slist; slist = slist->next)
+ if (BSE_IS_SONG (slist->data))
+ return (BseSong*) slist->data;
+ return NULL;
+ }
+
+ static gboolean
+ project_check_restore (BseContainer *container,
+ const gchar *child_type)
+ {
+ if (BSE_CONTAINER_CLASS (parent_class)->check_restore (container, child_type))
+ {
+ StorageTrap *strap = (StorageTrap*) g_object_get_qdata ((GObject*) container, quark_storage_trap);
+ if (!strap)
+ return TRUE;
+ if (!g_type_is_a (g_type_from_name (child_type), strap->base_type))
+ return FALSE;
+ if (strap->max_items < 1)
+ return FALSE;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ BseSNet*
+ bse_project_create_intern_synth (BseProject *self,
+ const gchar *synth_name,
+ GType check_type)
+ {
+ BseItem *synth = NULL;
+ gchar *bse_synth;
+
+ g_return_val_if_fail (BSE_IS_PROJECT (self), NULL);
+ g_return_val_if_fail (synth_name != NULL, NULL);
+
+ bse_synth = bse_standard_synth_inflate (synth_name, NULL);
+ if (bse_synth)
+ {
+ BseStorage *storage = (BseStorage*) g_object_new (BSE_TYPE_STORAGE, NULL);
+ BseErrorType error = BSE_ERROR_NONE;
+ StorageTrap strap = { 0, TRUE, }, *old_strap = (StorageTrap*) g_object_get_qdata ((GObject*) self,
quark_storage_trap);
+ bse_storage_input_text (storage, bse_synth, "<builtin-lib>");
+ g_object_set_qdata ((GObject*) self, quark_storage_trap, &strap);
+ strap.max_items = 1;
+ strap.base_type = check_type;
+ strap.items = NULL;
+ if (!error)
+ error = bse_project_restore (self, storage);
+ bse_storage_reset (storage);
+ g_object_unref (storage);
+ g_free (bse_synth);
+ if (error || !strap.items)
+ g_warning ("failed to create internal synth \"%s\": %s",
+ synth_name, bse_error_blurb (error ? error : BSE_ERROR_NO_ENTRY));
+ else
+ synth = (BseItem*) strap.items->data;
+ g_slist_free (strap.items);
+ g_object_set_qdata ((GObject*) self, quark_storage_trap, old_strap);
+ }
+ return BSE_SNET (synth);
+ }
+
+ BseCSynth*
+ bse_project_create_intern_csynth (BseProject *self,
+ const char *base_name)
+ {
+ BseCSynth *csynth = (BseCSynth*) bse_container_new_child_bname (BSE_CONTAINER (self), BSE_TYPE_CSYNTH,
base_name, NULL);
+ bse_item_set_internal (BSE_ITEM (csynth), TRUE);
+ return csynth;
+ }
+
+ BseMidiNotifier*
+ bse_project_get_midi_notifier (BseProject *self)
+ {
+ GSList *slist;
+ for (slist = self->items; slist; slist = slist->next)
+ if (BSE_IS_MIDI_NOTIFIER (slist->data))
+ return (BseMidiNotifier*) slist->data;
+
+ BseMidiNotifier *mnot = (BseMidiNotifier*) bse_container_new_child_bname (BSE_CONTAINER (self),
BSE_TYPE_MIDI_NOTIFIER,
+ "%bse-intern-midi-notifier",
NULL);
+ bse_midi_notifier_set_receiver (mnot, self->midi_receiver);
+ bse_item_set_internal (BSE_ITEM (mnot), TRUE);
+ return mnot;
+ }
+
+ static void
+ bse_project_prepare (BseSource *source)
+ {
+ BseProject *self = BSE_PROJECT (source);
+ GSList *slist;
+
+ /* make sure Wave repositories are prepared first */
+ for (slist = self->supers; slist; slist = slist->next)
+ if (BSE_IS_WAVE_REPO (slist->data))
+ bse_source_prepare ((BseSource*) slist->data);
+
+ /* chain parent class' handler to prepare the rest */
+ BSE_SOURCE_CLASS (parent_class)->prepare (source);
+ }
+
+ static gboolean
+ auto_deactivate (gpointer data)
+ {
+ BseProject *self = BSE_PROJECT (data);
+ self->deactivate_timer = 0;
+ if (self->state == BSE_PROJECT_ACTIVE)
+ bse_project_deactivate (self);
+ return FALSE;
+ }
+
+ void
+ bse_project_state_changed (BseProject *self,
+ BseProjectState state)
+ {
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ if (self->deactivate_timer)
+ {
+ bse_idle_remove (self->deactivate_timer);
+ self->deactivate_timer = 0;
+ }
+ self->state = state;
+ if (self->state == BSE_PROJECT_ACTIVE && self->deactivate_usecs >= 0)
+ {
+ SfiTime stamp = Bse::TickStamp::current();
+ SfiTime delay_usecs = 0;
+ if (SfiTime (self->deactivate_min_tick) > stamp)
+ delay_usecs = (self->deactivate_min_tick - stamp) * 1000000 / bse_engine_sample_freq ();
+ self->deactivate_timer = bse_idle_timed (self->deactivate_usecs + delay_usecs, auto_deactivate, self);
+ }
+ g_signal_emit (self, signal_state_changed, 0, state);
+ }
+
+ void
+ bse_project_keep_activated (BseProject *self,
+ guint64 min_tick)
+ {
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ if (min_tick > self->deactivate_min_tick)
+ {
+ self->deactivate_min_tick = min_tick;
+ if (self->deactivate_timer)
+ bse_project_state_changed (self, self->state);
+ }
+ }
+
+ BseErrorType
+ bse_project_activate (BseProject *self)
+ {
+ BseErrorType error;
+ BseTrans *trans;
+ GSList *slist;
+
+ g_return_val_if_fail (BSE_IS_PROJECT (self), BSE_ERROR_INTERNAL);
+
+ if (self->state != BSE_PROJECT_INACTIVE)
+ return BSE_ERROR_NONE;
+
+ g_return_val_if_fail (BSE_SOURCE_PREPARED (self) == FALSE, BSE_ERROR_INTERNAL);
+
+ error = bse_server_open_devices (bse_server_get ());
+ if (error)
+ return error;
+
+ bse_source_prepare (BSE_SOURCE (self));
+ self->deactivate_min_tick = 0;
+
+ trans = bse_trans_open ();
+ for (slist = self->supers; slist; slist = slist->next)
+ {
+ BseSuper *super = BSE_SUPER (slist->data);
+ if (BSE_SUPER_NEEDS_CONTEXT (super))
+ {
+ BseMidiContext mcontext = { 0, 0, 0 };
+ BseSNet *snet = BSE_SNET (super);
+ mcontext.midi_receiver = self->midi_receiver;
+ mcontext.midi_channel = 1; /* midi channel default */
+ super->context_handle = bse_snet_create_context (snet, mcontext, trans);
+ bse_source_connect_context (BSE_SOURCE (snet), super->context_handle, trans);
+ }
+ else
+ super->context_handle = ~0;
+ }
+ bse_trans_commit (trans);
+ bse_project_state_changed (self, BSE_PROJECT_ACTIVE);
+ return BSE_ERROR_NONE;
+ }
+
+ void
+ bse_project_start_playback (BseProject *self)
+ {
+ BseTrans *trans;
+ GSList *slist;
+ guint seen_synth = 0;
+
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ if (self->state != BSE_PROJECT_ACTIVE)
+ return;
+ g_return_if_fail (BSE_SOURCE_PREPARED (self) == TRUE);
+
+ SfiRing *songs = NULL;
+ trans = bse_trans_open ();
+ for (slist = self->supers; slist; slist = slist->next)
+ {
+ BseSuper *super = BSE_SUPER (slist->data);
+ if (BSE_SUPER_NEEDS_CONTEXT (super) &&
+ super->context_handle == ~uint (0))
+ {
+ BseMidiContext mcontext = { 0, 0, 0 };
+ BseSNet *snet = BSE_SNET (super);
+ mcontext.midi_receiver = self->midi_receiver;
+ mcontext.midi_channel = 1; /* midi channel default */
+ super->context_handle = bse_snet_create_context (snet, mcontext, trans);
+ bse_source_connect_context (BSE_SOURCE (snet), super->context_handle, trans);
+ }
+ if (BSE_SUPER_NEEDS_CONTEXT (super))
+ seen_synth++;
+ if (BSE_IS_SONG (super))
+ songs = sfi_ring_append (songs, super);
+ }
+ /* enfore MasterThread roundtrip */
+ bse_trans_add (trans, bse_job_nop());
+ bse_trans_commit (trans);
+ /* first, enforce integrated (and possibly scheduled) modules; */
+ bse_engine_wait_on_trans();
+ /* update state */
+ if (seen_synth || songs)
+ bse_project_state_changed (self, BSE_PROJECT_PLAYING);
+ /* then, start the sequencer */
+ while (songs)
+ Bse::Sequencer::instance().start_song ((BseSong*) sfi_ring_pop_head (&songs), 0);
+ }
+
+ void
+ bse_project_stop_playback (BseProject *self)
+ {
+ BseTrans *trans;
+ GSList *slist;
+
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ if (self->state != BSE_PROJECT_PLAYING)
+ return;
+ g_return_if_fail (BSE_SOURCE_PREPARED (self) == TRUE);
+
+ trans = bse_trans_open ();
+ for (slist = self->supers; slist; slist = slist->next)
+ {
+ BseSuper *super = BSE_SUPER (slist->data);
+ if (BSE_IS_SONG (super))
+ Bse::Sequencer::instance().remove_song (BSE_SONG (super));
+ if (super->context_handle != ~uint (0) && BSE_SUPER_NEEDS_CONTEXT (super))
+ {
+ BseSource *source = BSE_SOURCE (super);
+ bse_source_dismiss_context (source, super->context_handle, trans);
+ super->context_handle = ~0;
+ }
+ }
+ /* enfore MasterThread roundtrip */
+ bse_trans_add (trans, bse_job_nop());
+ bse_trans_commit (trans);
+ /* wait until after all modules have actually been dismissed */
+ bse_engine_wait_on_trans ();
+ /* update state */
+ bse_project_state_changed (self, BSE_PROJECT_ACTIVE);
+ }
+
+ void
+ bse_project_check_auto_stop (BseProject *self)
+ {
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ if (self->state == BSE_PROJECT_PLAYING)
+ {
+ GSList *slist;
+ for (slist = self->supers; slist; slist = slist->next)
+ {
+ BseSuper *super = BSE_SUPER (slist->data);
+ if (super->context_handle != ~uint (0))
+ {
+ if (!BSE_IS_SONG (super) || !BSE_SONG (super)->sequencer_done_SL)
+ return;
+ }
+ }
+ bse_project_stop_playback (self);
+ }
+ }
+
+ void
+ bse_project_deactivate (BseProject *self)
+ {
+ BseTrans *trans;
+ GSList *slist;
+
+ g_return_if_fail (BSE_IS_PROJECT (self));
+
+ if (self->state == BSE_PROJECT_INACTIVE)
+ return;
+ g_return_if_fail (BSE_SOURCE_PREPARED (self) == TRUE);
+
+ bse_project_stop_playback (self);
+
+ trans = bse_trans_open ();
+ for (slist = self->supers; slist; slist = slist->next)
+ {
+ BseSuper *super = BSE_SUPER (slist->data);
+ if (super->context_handle != ~uint (0))
+ {
+ BseSource *source = BSE_SOURCE (super);
+ bse_source_dismiss_context (source, super->context_handle, trans);
+ super->context_handle = ~0;
+ }
+ }
+ bse_trans_commit (trans);
+ /* wait until after all modules have actually been dismissed */
+ bse_engine_wait_on_trans ();
+ bse_source_reset (BSE_SOURCE (self));
+ bse_project_state_changed (self, BSE_PROJECT_INACTIVE);
+
+ bse_server_close_devices (bse_server_get ());
+ }
diff --cc bse/bseproject.hh
index 0000000,f4ebe16..48877b0
mode 000000,100644..100644
--- a/bse/bseproject.hh
+++ b/bse/bseproject.hh
@@@ -1,0 -1,83 +1,84 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BSE_PROJECT_H__
+ #define __BSE_PROJECT_H__
+
+ #include <bse/bsecontainer.hh>
+
+ G_BEGIN_DECLS
+
+
+ /* --- object type macros --- */
+ #define BSE_TYPE_PROJECT (BSE_TYPE_ID (BseProject))
+ #define BSE_PROJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), BSE_TYPE_PROJECT, BseProject))
+ #define BSE_PROJECT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_PROJECT, BseProjectClass))
+ #define BSE_IS_PROJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), BSE_TYPE_PROJECT))
+ #define BSE_IS_PROJECT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_PROJECT))
+ #define BSE_PROJECT_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), BSE_TYPE_PROJECT,
BseProjectClass))
+
+
+ /* --- BseProject object --- */
+ typedef enum {
+ BSE_PROJECT_INACTIVE,
+ BSE_PROJECT_ACTIVE,
+ BSE_PROJECT_PLAYING
+ } BseProjectState;
+
+ struct BseProject : BseContainer {
+ GSList *supers;
+ GSList *items;
+ guint in_undo : 1;
+ guint in_redo : 1;
+ BseUndoStack *undo_stack;
+ BseUndoStack *redo_stack;
+ BseProjectState state;
+ guint deactivate_timer;
+ gint64 deactivate_usecs;
+ guint64 deactivate_min_tick;
+ BseMidiReceiver *midi_receiver;
+ };
+ struct BseProjectClass : BseContainerClass
+ {};
+
+ BseErrorType bse_project_activate (BseProject *project);
+ void bse_project_start_playback (BseProject *project);
+ void bse_project_stop_playback (BseProject *project);
+ void bse_project_check_auto_stop (BseProject *project);
+ void bse_project_deactivate (BseProject *project);
+ void bse_project_set_auto_deactivate (BseProject *project,
+ gint64 usecs);
+ void bse_project_keep_activated (BseProject *project,
+ guint64 min_tick);
+ void bse_project_state_changed (BseProject *project,
+ BseProjectState state);
+ BseStringSeq* bse_project_list_upaths (BseProject *project,
+ GType item_type);
+ BseErrorType bse_project_restore (BseProject *project,
+ BseStorage *storage);
+ BseErrorType bse_project_store_bse (BseProject *project,
+ BseSuper *super,
+ const gchar *bse_file,
+ gboolean self_contained);
+ BseObject* bse_project_upath_resolver (gpointer project /* func_data */,
+ GType required_type,
+ const gchar *upath,
+ gchar **error_p);
+ BseItem* bse_project_lookup_typed_item (BseProject *project,
+ GType item_type,
+ const gchar *uname);
+ BseWaveRepo* bse_project_get_wave_repo (BseProject *project);
++BseSoundFontRepo* bse_project_get_sound_font_repo (BseProject *project);
+ BseSong* bse_project_get_song (BseProject *project);
+ BseSNet* bse_project_create_intern_synth (BseProject *project,
+ const gchar *synth_name,
+ GType check_type);
+ BseCSynth* bse_project_create_intern_csynth(BseProject *project,
+ const char *base_name);
+ BseMidiNotifier*bse_project_get_midi_notifier (BseProject *project);
+ void bse_project_clear_undo (BseProject *project);
+ void bse_project_clean_dirty (BseProject *project);
+ void bse_project_push_undo_silent_deactivate (BseProject *self);
+
+
+ G_END_DECLS
+
+ #endif /* __BSE_PROJECT_H__ */
diff --cc bse/bseproject.proc
index 1bd9d77,ff4a8d5..2dc1d52
--- a/bse/bseproject.proc
+++ b/bse/bseproject.proc
@@@ -1,36 -1,21 +1,21 @@@
- /* BSE - Bedevilled Sound Engine -*-mode: c;-*-
- * Copyright (C) 2000-2005 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.h>
- #include <bse/bseprocedure.h>
- #include <bse/bseproject.h>
- #include <bse/bsestorage.h>
- #include <bse/bsesong.h>
- #include <bse/bseundostack.h>
- #include <bse/bsewaverepo.h>
+ // 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.h>
- #include <bse/bsecsynth.h>
- #include <bse/bsemidisynth.h>
- #include <bse/bsedatapocket.h>
- #include <bse/bsemidifile.h>
- #include <bse/bsemidireceiver.h>
- #include <bse/bsemidinotifier.h>
- #include <bse/bseengine.h>
-
+ #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"
-
AUTHORS = "Tim Janik <timj gtk org>";
LICENSE = "GNU Lesser General Public License";
diff --cc bse/bsestorage.cc
index 0000000,22438e2..e62eb4e
mode 000000,100644..100644
--- a/bse/bsestorage.cc
+++ b/bse/bsestorage.cc
@@@ -1,0 -1,1685 +1,2035 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bsestorage.hh"
+ #include "bseitem.hh"
+ #include "gsldatahandle.hh"
+ #include "gsldatahandle-vorbis.hh"
+ #include "bsedatahandle-flac.hh"
+ #include "gsldatautils.hh"
+ #include "gslcommon.hh"
+ #include "bseproject.hh"
+ #include "bseparasite.hh"
+ #include "bsecxxplugin.hh"
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
++#include <sys/types.h>
++#include <signal.h>
+
+ using Bse::Flac1Handle;
+
+ /* --- macros --- */
+ #define parse_or_return sfi_scanner_parse_or_return
+ #define peek_or_return sfi_scanner_peek_or_return
+
+ /* --- typedefs --- */
+ struct _BseStorageDBlock
+ {
+ gulong id;
+ GslDataHandle *dhandle;
+ guint n_channels : 16;
+ guint needs_close : 1;
+ gfloat mix_freq;
+ gfloat osc_freq;
+ };
+ struct _BseStorageItemLink
+ {
+ BseItem *from_item;
+ BseStorageRestoreLink restore_link;
+ gpointer data;
+ guint pbackup;
+ gchar *upath;
+ BseItem *to_item;
+ gchar *error;
+ };
-
++struct _BseStorageBlob
++{
++ SfiMutex mutex;
++ char *file_name;
++ int ref_count;
++ gboolean is_temp_file;
++ gulong id;
++};
+
+ /* --- prototypes --- */
+ static void bse_storage_init (BseStorage *self);
+ static void bse_storage_class_init (BseStorageClass *klass);
+ static void bse_storage_finalize (GObject *object);
+ static void storage_path_table_insert (BseStorage *self,
+ BseContainer *container,
+ const gchar *uname,
+ BseItem *item);
+ static BseItem* storage_path_table_resolve_upath (BseStorage *self,
+ BseContainer *container,
+ gchar *upath);
+ static guint uname_child_hash (gconstpointer uc);
+ static gint uname_child_equals (gconstpointer uc1,
+ gconstpointer uc2);
+ static void uname_child_free (gpointer uc);
+ static GTokenType compat_parse_data_handle (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p);
+
+
+ /* --- variables --- */
+ static gpointer parent_class = NULL;
+ static GQuark quark_raw_data_handle = 0;
++static GQuark quark_blob = 0;
++static GQuark quark_blob_id = 0;
+ static GQuark quark_vorbis_data_handle = 0;
+ static GQuark quark_flac_data_handle = 0;
+ static GQuark quark_dblock_data_handle = 0;
+ static GQuark quark_bse_storage_binary_v0 = 0;
+
+
+ /* --- functions --- */
+ BSE_BUILTIN_TYPE (BseStorage)
+ {
+ static const GTypeInfo storage_info = {
+ sizeof (BseStorageClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) bse_storage_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL /* class_data */,
+ sizeof (BseStorage),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) bse_storage_init,
+ };
+
+ g_assert (BSE_STORAGE_FLAGS_USHIFT < BSE_OBJECT_FLAGS_MAX_SHIFT);
+
+ return bse_type_register_static (BSE_TYPE_OBJECT, "BseStorage",
+ "Storage object for item serialization",
+ __FILE__, __LINE__,
+ &storage_info);
+ }
+
+ static void
+ bse_storage_class_init (BseStorageClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ quark_raw_data_handle = g_quark_from_static_string ("raw-data-handle");
+ quark_vorbis_data_handle = g_quark_from_static_string ("vorbis-data-handle");
+ quark_flac_data_handle = g_quark_from_static_string ("flac-data-handle");
+ quark_dblock_data_handle = g_quark_from_static_string ("dblock-data-handle");
+ quark_bse_storage_binary_v0 = g_quark_from_static_string ("BseStorageBinaryV0");
++ quark_blob = g_quark_from_string ("blob");
++ quark_blob_id = g_quark_from_string ("blob-id");
++
++ bse_storage_blob_clean_files(); /* FIXME: maybe better placed in bsemain.c */
+
+ gobject_class->finalize = bse_storage_finalize;
+ }
+
+ static void
+ bse_storage_init (BseStorage *self)
+ {
+ /* writing */
+ self->wstore = NULL;
+ self->stored_items = NULL;
+ self->referenced_items = NULL;
+ /* reading */
+ self->rstore = NULL;
+ self->path_table = NULL;
+ self->item_links = NULL;
+ self->restorable_objects = NULL;
+ /* misc */
+ self->dblocks = NULL;
+ self->n_dblocks = 0;
+ self->free_me = NULL;
++ self->blobs = NULL;
++ self->n_blobs = 0;
+
+ bse_storage_reset (self);
+ }
+
+ static void
+ bse_storage_finalize (GObject *object)
+ {
+ BseStorage *self = BSE_STORAGE (object);
+
+ bse_storage_reset (self);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+
+ void
+ bse_storage_turn_readable (BseStorage *self,
+ 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);
+
+ bse_storage_break (self);
+
+ cmem = sfi_wstore_peek_text (self->wstore, &l);
+ text = (char*) g_memdup (cmem, l + 1);
+ dblocks = self->dblocks;
+ n_dblocks = self->n_dblocks;
++ blobs = self->blobs;
++ n_blobs = self->n_blobs;
+ self->dblocks = NULL;
+ self->n_dblocks = 0;
++ self->blobs = NULL;
++ self->n_blobs = 0;
+
+ bse_storage_input_text (self, text, storage_name);
+ self->free_me = text;
+ self->dblocks = dblocks;
+ self->n_dblocks = n_dblocks;
++ self->blobs = blobs;
++ self->n_blobs = n_blobs;
+ BSE_OBJECT_SET_FLAGS (self, BSE_STORAGE_DBLOCK_CONTAINED);
+ }
+
+ void
+ bse_storage_reset (BseStorage *self)
+ {
+ guint i;
+
+ g_return_if_fail (BSE_IS_STORAGE (self));
+
+ if (self->rstore)
+ {
+ bse_storage_finish_parsing (self);
+ g_hash_table_destroy (self->path_table);
+ self->path_table = NULL;
+ sfi_rstore_destroy (self->rstore);
+ self->rstore = NULL;
+ if (self->restorable_objects)
+ sfi_ppool_destroy (self->restorable_objects);
+ self->restorable_objects = NULL;
+ }
+
+ if (self->wstore)
+ sfi_wstore_destroy (self->wstore);
+ self->wstore = NULL;
+ if (self->stored_items)
+ sfi_ppool_destroy (self->stored_items);
+ self->stored_items = NULL;
+ if (self->referenced_items)
+ sfi_ppool_destroy (self->referenced_items);
+ self->referenced_items = NULL;
+
+ self->major_version = BST_MAJOR_VERSION;
+ self->minor_version = BST_MINOR_VERSION;
+ self->micro_version = BST_MICRO_VERSION;
+
+ for (i = 0; i < self->n_dblocks; i++)
+ {
+ bse_id_free (self->dblocks[i].id);
+ if (self->dblocks[i].needs_close)
+ gsl_data_handle_close (self->dblocks[i].dhandle);
+ gsl_data_handle_unref (self->dblocks[i].dhandle);
+ }
+ g_free (self->dblocks);
+ self->dblocks = NULL;
+ self->n_dblocks = 0;
+
++ for (i = 0; i < self->n_blobs; i++)
++ bse_storage_blob_unref (self->blobs[i]);
++ g_free (self->blobs);
++ self->blobs = NULL;
++ self->n_blobs = 0;
++
+ g_free (self->free_me);
+ self->free_me = NULL;
+
+ BSE_OBJECT_UNSET_FLAGS (self, BSE_STORAGE_MODE_MASK);
+ }
+
+ static gulong
+ bse_storage_add_dblock (BseStorage *self,
+ GslDataHandle *dhandle)
+ {
+ guint i = self->n_dblocks++;
+ self->dblocks = g_renew (BseStorageDBlock, self->dblocks, self->n_dblocks);
+ self->dblocks[i].id = bse_id_alloc ();
+ self->dblocks[i].dhandle = gsl_data_handle_ref (dhandle);
+ if (GSL_DATA_HANDLE_OPENED (dhandle))
+ {
+ /* keep data handles opened to protect against rewrites */
+ gsl_data_handle_open (dhandle);
+ self->dblocks[i].needs_close = TRUE;
+ }
+ else
+ self->dblocks[i].needs_close = FALSE;
+ self->dblocks[i].n_channels = gsl_data_handle_n_channels (dhandle);
+ self->dblocks[i].mix_freq = gsl_data_handle_mix_freq (dhandle);
+ self->dblocks[i].osc_freq = gsl_data_handle_osc_freq (dhandle);
+ return self->dblocks[i].id;
+ }
+
++static gulong
++bse_storage_add_blob (BseStorage *self,
++ BseStorageBlob *blob)
++{
++ guint i = self->n_blobs++;
++ self->blobs = g_renew (BseStorageBlob *, self->blobs, self->n_blobs);
++ self->blobs[i] = bse_storage_blob_ref (blob);
++ return self->blobs[i]->id;
++}
++
+ static BseStorageDBlock*
+ bse_storage_get_dblock (BseStorage *self,
+ gulong id)
+ {
+ guint i;
+ for (i = 0; i < self->n_dblocks; i++)
+ if (id == self->dblocks[i].id)
+ return self->dblocks + i;
+ return NULL;
+ }
+
+ void
+ bse_storage_prepare_write (BseStorage *self,
+ BseStorageMode mode)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+
+ bse_storage_reset (self);
+ self->wstore = sfi_wstore_new ();
+ self->stored_items = sfi_ppool_new ();
+ self->referenced_items = sfi_ppool_new ();
+ mode = BseStorageMode (mode & BSE_STORAGE_MODE_MASK);
+ if (mode & BSE_STORAGE_DBLOCK_CONTAINED)
+ mode = BseStorageMode (mode | BSE_STORAGE_SELF_CONTAINED);
+ BSE_OBJECT_SET_FLAGS (self, mode);
+ bse_storage_break (self);
+ bse_storage_printf (self, "(bse-version \"%u.%u.%u\")\n\n", BST_MAJOR_VERSION, BST_MINOR_VERSION,
BST_MICRO_VERSION);
+ }
+
+ void
+ bse_storage_input_text (BseStorage *self,
+ const gchar *text,
+ const gchar *text_name)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+
+ if (!text)
+ text = "";
+
+ bse_storage_reset (self);
+ self->rstore = sfi_rstore_new ();
+ self->rstore->parser_this = self;
+ sfi_rstore_input_text (self->rstore, text, text_name);
+ self->path_table = g_hash_table_new_full (uname_child_hash, uname_child_equals, NULL, uname_child_free);
+ self->restorable_objects = sfi_ppool_new ();
+ }
+
+ BseErrorType
+ bse_storage_input_file (BseStorage *self,
+ const gchar *file_name)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (file_name != NULL, BSE_ERROR_INTERNAL);
+
+ bse_storage_reset (self);
+ self->rstore = sfi_rstore_new_open (file_name);
+ if (!self->rstore)
+ return bse_error_from_errno (errno, BSE_ERROR_FILE_OPEN_FAILED);
+ self->rstore->parser_this = self;
+ self->path_table = g_hash_table_new_full (uname_child_hash, uname_child_equals, NULL, uname_child_free);
+ self->restorable_objects = sfi_ppool_new ();
+
+ return BSE_ERROR_NONE;
+ }
+
+ static GTokenType
+ storage_parse_bse_version (BseStorage *self)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ gchar *vstring, *pminor, *pmicro, *ep = NULL;
+ gboolean parsed_version = FALSE;
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER); /* eat bse-version */
+ parse_or_return (scanner, G_TOKEN_STRING); /* fetch "version" */
+ peek_or_return (scanner, ')'); /* check for closing paren */
+ vstring = g_strdup (scanner->value.v_string);
+ pminor = strchr (vstring, '.');
+ pmicro = !pminor ? NULL : strchr (pminor + 1, '.');
+ if (pmicro)
+ {
+ glong vmajor, vminor = -1, vmicro = -1;
+ *pminor++ = 0;
+ *pmicro++ = 0;
+ vmajor = strtol (vstring, &ep, 10);
+ if (!ep || *ep == 0)
+ vminor = strtol (pminor, &ep, 10);
+ if (!ep || *ep == 0)
+ vmicro = strtol (pmicro, &ep, 10);
+ if ((!ep || *ep == 0 || ep > pmicro) && vmajor >= 0 && vminor >= 0 && vmicro >= 0 &&
+ BSE_VERSION_CMP (vmajor, vminor, vmicro, 0, 0, 0) > 0)
+ {
+ parsed_version = TRUE;
+ if (BSE_VERSION_CMP (vmajor, vminor, vmicro, 0, 5, 0) >= 0)
+ {
+ self->major_version = vmajor;
+ self->minor_version = vminor;
+ self->micro_version = vmicro;
+ }
+ }
+ }
+ g_free (vstring);
+ if (!parsed_version)
+ bse_storage_warn (self, "ignoring invalid version string: %s", scanner->value.v_string);
+ parse_or_return (scanner, ')'); /* eat closing paren */
+ if (0)
+ g_printerr ("bse-version: code: %u.%u.%u file: %u.%u.%u feature(current):%d compat(current):%d
compat(-1):%d\n",
+ BST_MAJOR_VERSION, BST_MINOR_VERSION, BST_MICRO_VERSION,
+ self->major_version, self->minor_version, self->micro_version,
+ BSE_STORAGE_VERSION (self, BST_MAJOR_VERSION, BST_MINOR_VERSION, BST_MICRO_VERSION),
+ BSE_STORAGE_COMPAT (self, BST_MAJOR_VERSION, BST_MINOR_VERSION, BST_MICRO_VERSION),
+ BSE_STORAGE_COMPAT (self, BST_MAJOR_VERSION, BST_MINOR_VERSION, BST_MICRO_VERSION - 1));
+ return G_TOKEN_NONE;
+ }
+
+ static BseStorageItemLink*
+ storage_add_item_link (BseStorage *self,
+ BseItem *from_item,
+ BseStorageRestoreLink restore_link,
+ gpointer data,
+ gchar *error)
+ {
+ BseStorageItemLink *ilink = g_new0 (BseStorageItemLink, 1);
+ self->item_links = sfi_ring_append (self->item_links, ilink);
+ ilink->from_item = (BseItem*) g_object_ref (from_item);
+ ilink->restore_link = restore_link;
+ ilink->data = data;
+ ilink->error = error;
+
+ return ilink;
+ }
+
+ void
+ bse_storage_add_restorable (BseStorage *self,
+ BseObject *object)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->rstore);
+ g_return_if_fail (self->restorable_objects);
+ g_return_if_fail (BSE_IS_OBJECT (object));
+ g_return_if_fail (BSE_OBJECT_IN_RESTORE (object));
+
+ sfi_ppool_set (self->restorable_objects, object);
+ }
+
+ static gboolean
+ storage_restorable_objects_foreach (gpointer data,
+ gpointer pointer)
+ {
+ BseStorage *self = BSE_STORAGE (data);
+ BseObject *object = BSE_OBJECT (pointer);
+ bse_object_restore_finish (object, self->major_version, self->minor_version, self->micro_version);
+ return TRUE;
+ }
+
+ void
+ bse_storage_finish_parsing (BseStorage *self)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->rstore != NULL);
+
+ while (self->item_links)
+ {
+ BseStorageItemLink *ilink = (BseStorageItemLink*) sfi_ring_pop_head (&self->item_links);
+
+ if (ilink->error)
+ {
+ gchar *error = g_strdup_format ("unable to resolve link path for item `%s': %s",
+ BSE_OBJECT_UNAME (ilink->from_item),
+ ilink->error);
+ ilink->restore_link (ilink->data, self, ilink->from_item, NULL, error);
+ g_free (error);
+ if (ilink->to_item)
+ g_object_unref (ilink->to_item);
+ g_free (ilink->error);
+ }
+ else if (ilink->to_item)
+ {
+ ilink->restore_link (ilink->data, self, ilink->from_item, ilink->to_item, NULL);
+ g_object_unref (ilink->to_item);
+ }
+ else if (!ilink->upath)
+ {
+ ilink->restore_link (ilink->data, self, ilink->from_item, NULL, NULL);
+ }
+ else
+ {
+ BseItem *child = NULL, *parent = ilink->from_item;
+ guint pbackup = ilink->pbackup;
+ gchar *error = NULL;
+
+ while (pbackup && parent)
+ {
+ pbackup--;
+ parent = parent->parent;
+ }
+ if (!parent)
+ error = g_strdup_format ("failed to find ancestor of item `%s' (branch depth: -%u, "
+ "number of parents: %u) while resolving link path \"%s\"",
+ BSE_OBJECT_UNAME (ilink->from_item),
+ ilink->pbackup,
+ ilink->pbackup - pbackup + 1,
+ ilink->upath);
+ else
+ {
+ child = storage_path_table_resolve_upath (self, BSE_CONTAINER (parent), ilink->upath);
+ if (!child)
+ error = g_strdup_format ("failed to find object for item `%s' while resolving link path
\"%s\" from ancestor `%s'",
+ BSE_OBJECT_UNAME (ilink->from_item),
+ ilink->upath, BSE_OBJECT_UNAME (parent));
+ }
+ ilink->restore_link (ilink->data, self, ilink->from_item, child, error);
+ g_free (error);
+ }
+ g_object_unref (ilink->from_item);
+ g_free (ilink->upath);
+ g_free (ilink);
+ }
+
+ /* finish restorables */
+ sfi_ppool_foreach (self->restorable_objects, storage_restorable_objects_foreach, self);
+ /* clear pool */
+ sfi_ppool_destroy (self->restorable_objects);
+ self->restorable_objects = sfi_ppool_new();
+ }
+
+ const gchar*
+ bse_storage_item_get_compat_type (BseItem *item)
+ {
+ const gchar *type = (const char*) g_object_get_data ((GObject*) item, "BseStorage-compat-type");
+ if (!type)
+ type = G_OBJECT_TYPE_NAME (item);
+ return type;
+ }
+
+ typedef struct {
+ BseContainer *container;
+ gchar *uname;
+ BseItem *item;
+ } UNameChild;
+
+ static guint
+ uname_child_hash (gconstpointer uc)
+ {
+ const UNameChild *uchild = (const UNameChild*) uc;
+ guint h = g_str_hash (uchild->uname);
+ h ^= G_HASH_LONG ((long) uchild->container);
+ return h;
+ }
+
+ static gint
+ uname_child_equals (gconstpointer uc1,
+ gconstpointer uc2)
+ {
+ const UNameChild *uchild1 = (const UNameChild*) uc1;
+ const UNameChild *uchild2 = (const UNameChild*) uc2;
+ return (bse_string_equals (uchild1->uname, uchild2->uname) &&
+ uchild1->container == uchild2->container);
+ }
+
+ static void
+ uname_child_free (gpointer uc)
+ {
+ UNameChild *uchild = (UNameChild*) uc;
+ g_object_unref (uchild->container);
+ g_free (uchild->uname);
+ g_object_unref (uchild->item);
+ g_free (uchild);
+ }
+
+ static void
+ storage_path_table_insert (BseStorage *self,
+ BseContainer *container,
+ const gchar *uname,
+ BseItem *item)
+ {
+ UNameChild key;
+ key.container = container;
+ key.uname = (char*) uname;
+ UNameChild *uchild = (UNameChild*) g_hash_table_lookup (self->path_table, &key);
+ if (!uchild)
+ {
+ uchild = g_new (UNameChild, 1);
+ uchild->container = (BseContainer*) g_object_ref (container);
+ uchild->uname = g_strdup (uname);
+ uchild->item = NULL;
+ g_hash_table_insert (self->path_table, uchild, uchild);
+ }
+ if (uchild->item)
+ g_object_unref (uchild->item);
+ uchild->item = (BseItem*) g_object_ref (item);
+ // DEBUG ("INSERT: (%p,%s) => %p", container, uname, item);
+ }
+
+ static inline BseItem*
+ storage_path_table_lookup (BseStorage *self,
+ BseContainer *container,
+ const gchar *uname)
+ {
+ UNameChild key, *uchild;
+ key.container = container;
+ key.uname = (gchar*) uname;
+ uchild = (UNameChild*) g_hash_table_lookup (self->path_table, &key);
+ // DEBUG ("LOOKUP: (%p,%s) => %p", container, uname, uchild ? uchild->item : NULL);
+ if (uchild)
+ return uchild->item;
+ /* we resort to container lookups in case
+ * object links refer across external
+ * containers.
+ */
+ return bse_container_lookup_item (container, uname);
+ }
+
+ static BseItem*
+ storage_path_table_resolve_upath (BseStorage *self,
+ BseContainer *container,
+ gchar *upath)
+ {
- gchar *next_uname = strchr (upath, ':');
++ char *next_upath = strchr (upath, ':');
+ /* upaths consist of colon seperated unames from the item's ancestry */
- if (next_uname)
++ if (next_upath) /* A:B[:...] */
+ {
++ char *next_next_upath = strchr (next_upath + 1, ':');
+ BseItem *item;
- next_uname[0] = 0;
- item = storage_path_table_lookup (self, container, upath);
- next_uname[0] = ':';
++ next_upath[0] = 0;
++ if (next_next_upath)
++ next_next_upath[0] = 0;
++ /* lookup A */
++ item = storage_path_table_resolve_upath (self, container, upath);
++ next_upath[0] = ':';
++ if (next_next_upath)
++ next_next_upath[0] = ':';
++ /* lookup B[:...] in A */
+ if (BSE_IS_CONTAINER (item))
- return storage_path_table_lookup (self, BSE_CONTAINER (item), next_uname + 1);
++ return storage_path_table_resolve_upath (self, BSE_CONTAINER (item), next_upath + 1);
+ else
- return NULL;
++ return NULL;
+ }
- else
- return storage_path_table_lookup (self, container, upath);
++ return storage_path_table_lookup (self, container, upath);
+ }
+
+ static void
+ item_link_resolved (gpointer data,
+ BseStorage *self,
+ BseItem *item,
+ BseItem *dest_item,
+ const gchar *error)
+ {
+ if (error)
+ bse_storage_warn (self, "%s", error);
+ else
+ {
+ GParamSpec *pspec = (GParamSpec*) data;
+ GValue value = { 0, };
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_value_set_object (&value, dest_item);
+ g_object_set_property (G_OBJECT (item), /* no undo */
+ pspec->name, &value);
+ g_value_unset (&value);
+ }
+ }
+
+ static GTokenType item_restore_try_statement (gpointer item, BseStorage *self, GScanner *scanner, gpointer
user_data);
+ static GTokenType
+ restore_item_property (BseItem *item,
+ BseStorage *self)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ GTokenType expected_token;
+ GParamSpec *pspec;
+ GValue value = { 0, };
+ /* check identifier */
+ if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
+ return SFI_TOKEN_UNMATCHED;
+ /* in theory, we should only find SFI_PARAM_SERVE_STORAGE
+ * properties here, but due to version changes or even
+ * users editing their files, we will simply parse all
+ * kinds of properties (we might want to at least restrict
+ * them to SFI_PARAM_SERVE_STORAGE and SFI_PARAM_SERVE_GUI
+ * at some point...)
+ */
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (item), scanner->next_value.v_identifier);
+ if (!pspec)
+ return SFI_TOKEN_UNMATCHED;
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER); /* eat pspec name */
+ /* parse value, special casing object references */
+ if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspec), BSE_TYPE_ITEM))
+ {
+ expected_token = bse_storage_parse_item_link (self, item, item_link_resolved, pspec);
+ if (expected_token != G_TOKEN_NONE)
+ return expected_token;
+ parse_or_return (scanner, ')');
+ /* we cannot provide the object value at this time */
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_value_set_object (&value, NULL);
+ }
+ else if (g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspec), G_TYPE_OBJECT))
+ return bse_storage_warn_skip (self, "unable to restore object property \"%s\" of type `%s'",
+ pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+ else
+ {
+ /* parse the value for this pspec, including the closing ')' */
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ expected_token = bse_storage_parse_param_value (self, &value, pspec);
+ if (expected_token != G_TOKEN_NONE)
+ {
+ g_value_unset (&value);
+ return expected_token;
+ }
+ }
+ /* set property value while preserving the object uname */
+ if ((pspec->flags & G_PARAM_WRITABLE) && !(pspec->flags & G_PARAM_CONSTRUCT_ONLY))
+ g_object_set_property (G_OBJECT (item), /* no undo */
+ pspec->name, &value);
+ else
+ bse_storage_warn (self, "ignoring non-writable object property \"%s\" of type `%s'",
+ pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+ g_value_unset (&value);
+ return G_TOKEN_NONE;
+ }
+
+ static GTokenType
+ restore_source_automation (BseItem *item,
+ BseStorage *self)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ /* check identifier */
+ if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER ||
+ !bse_string_equals ("source-automate", scanner->next_value.v_identifier))
+ return SFI_TOKEN_UNMATCHED;
+ /* check object type */
+ if (!BSE_IS_SOURCE (item))
+ return SFI_TOKEN_UNMATCHED;
+ /* eat source-automate */
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ /* read pspec name */
+ parse_or_return (scanner, G_TOKEN_STRING);
+ /* find pspec */
+ GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (item), scanner->value.v_string);
+ if (!pspec || !sfi_pspec_check_option (pspec, "automate"))
+ return bse_storage_warn_skip (self, "not an automatable property: \"%s\"", pspec->name);
+ /* parse midi channel */
+ parse_or_return (scanner, G_TOKEN_INT);
+ gint midi_channel = scanner->value.v_int64;
+ /* parse control type */
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ BseMidiControlType control_type = (BseMidiControlType) sfi_choice2enum (scanner->value.v_identifier,
BSE_TYPE_MIDI_CONTROL_TYPE);
+ /* close statement */
+ parse_or_return (scanner, ')');
+ BseErrorType error = bse_source_set_automation_property (BSE_SOURCE (item), pspec->name, midi_channel,
BseMidiSignalType (control_type));
+ if (error)
+ bse_storage_warn (self, "failed to automate property \"%s\": %s", pspec->name, bse_error_blurb (error));
+ return G_TOKEN_NONE;
+ }
+
+ static GTokenType
+ restore_container_child (BseContainer *container,
+ BseStorage *self)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ GTokenType expected_token;
+ BseItem *item;
+ const gchar *uname;
+ gchar *type_name, *tmp, *compat_type = NULL;
+ /* check identifier */
+ if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER ||
+ !bse_string_equals ("container-child", scanner->next_value.v_identifier))
+ return SFI_TOKEN_UNMATCHED;
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER); /* eat identifier */
+ /* parse and validate type::uname argument */
+ parse_or_return (scanner, G_TOKEN_STRING);
+ uname = strchr (scanner->value.v_string, ':');
+ if (!uname || uname[1] != ':')
+ {
+ bse_storage_error (self, "invalid object handle: \"%s\"", scanner->value.v_string);
+ return G_TOKEN_ERROR;
+ }
+ type_name = g_strndup (scanner->value.v_string, uname - scanner->value.v_string);
+ uname += 2;
+ /* handle different versions */
+ tmp = bse_compat_rewrite_type_name (self, type_name);
+ if (tmp)
+ {
+ compat_type = type_name;
+ type_name = tmp;
+ }
+ /* check container's storage filter */
+ if (!bse_container_check_restore (container, type_name))
+ {
+ g_free (type_name);
+ g_free (compat_type);
+ return bse_storage_warn_skip (self, "ignoring child: \"%s\"", scanner->value.v_string);
+ }
+ /* create container child */
+ tmp = g_strconcat (type_name, "::", uname, NULL);
+ g_free (type_name);
+ item = bse_container_retrieve_child (container, tmp);
+ if (item)
+ g_object_set_data_full ((GObject*) item, "BseStorage-compat-type", compat_type, g_free);
+ else
+ g_free (compat_type);
+ g_free (tmp);
+ if (!item)
+ return bse_storage_warn_skip (self, "failed to create object from (invalid?) handle: \"%s\"",
+ scanner->value.v_string);
+ /* provide compatibility setup (e.g. property defaults) */
+ bse_item_compat_setup (item, self->major_version, self->minor_version, self->micro_version);
+ storage_path_table_insert (self, container, uname, item);
+ /* restore_item reads out closing parenthesis */
+ g_object_ref (item);
+ expected_token = bse_storage_parse_rest (self, item, item_restore_try_statement, NULL);
+ g_object_unref (item);
+ return expected_token;
+ }
+
+ static GTokenType
+ item_restore_try_statement (gpointer _item,
+ BseStorage *self,
+ GScanner *scanner,
+ gpointer user_data)
+ {
+ BseItem *item = BSE_ITEM (_item);
+ GTokenType expected_token = SFI_TOKEN_UNMATCHED;
+ /* ensure that the statement starts out with an identifier */
+ if (g_scanner_peek_next_token (scanner) != G_TOKEN_IDENTIFIER)
+ {
+ g_scanner_get_next_token (scanner);
+ return G_TOKEN_IDENTIFIER;
+ }
+ /* this is pretty much the *only* place where something else than
+ * G_TOKEN_NONE may be returned without erroring out. return values:
+ * G_TOKEN_NONE - statement got parsed, advance to next statement
+ * SFI_TOKEN_UNMATCHED - statement not recognized, try further
+ * anything else - encountered (syntax/semantic) error during parsing
+ */
+ bse_object_restore_start (BSE_OBJECT (item), self);
+ if (expected_token == SFI_TOKEN_UNMATCHED)
+ expected_token = restore_item_property (item, self);
+ if (expected_token == SFI_TOKEN_UNMATCHED)
+ expected_token = restore_source_automation (item, self);
+ if (expected_token == SFI_TOKEN_UNMATCHED)
+ expected_token = BSE_OBJECT_GET_CLASS (item)->restore_private ((BseObject*) item, self, scanner);
+ if (expected_token == SFI_TOKEN_UNMATCHED)
+ expected_token = bse_parasite_restore ((BseObject*) item, self);
+ if (expected_token == SFI_TOKEN_UNMATCHED && BSE_IS_CONTAINER (item))
+ expected_token = restore_container_child ((BseContainer*) item, self);
+ if (expected_token == SFI_TOKEN_UNMATCHED && strcmp (scanner->next_value.v_identifier, "bse-version") ==
0)
+ expected_token = storage_parse_bse_version (self);
+ return expected_token;
+ }
+
+ GTokenType
+ bse_storage_restore_item (BseStorage *self,
+ gpointer item)
+ {
+ GTokenType expected_token;
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (BSE_IS_ITEM (item), G_TOKEN_ERROR);
+ g_object_ref (self);
+ g_object_ref (item);
+ expected_token = sfi_rstore_parse_until (self->rstore, G_TOKEN_EOF, item,
+ (SfiStoreParser) item_restore_try_statement, NULL);
+ g_object_unref (item);
+ g_object_unref (self);
+ return expected_token;
+ }
+
+ GTokenType
+ bse_storage_parse_rest (BseStorage *self,
+ gpointer context_data,
+ BseTryStatement try_statement,
+ gpointer user_data)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (self->rstore != NULL, G_TOKEN_ERROR);
+ return sfi_rstore_parse_until (self->rstore, GTokenType (')'), context_data, (SfiStoreParser)
try_statement, user_data);
+ }
+
+ gboolean
+ bse_storage_check_parse_negate (BseStorage *self)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), FALSE);
+ if (g_scanner_peek_next_token (bse_storage_get_scanner (self)) == '-')
+ {
+ g_scanner_get_next_token (bse_storage_get_scanner (self));
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ void
+ bse_storage_put_param (BseStorage *self,
+ const GValue *value,
+ GParamSpec *pspec)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ g_return_if_fail (G_IS_VALUE (value));
+ g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ sfi_wstore_put_param (self->wstore, value, pspec);
+ }
+
+ GTokenType
+ bse_storage_parse_param_value (BseStorage *self,
+ GValue *value,
+ GParamSpec *pspec)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (self->rstore, G_TOKEN_ERROR);
+ return sfi_rstore_parse_param (self->rstore, value, pspec);
+ }
+
+ void
+ bse_storage_put_item_link (BseStorage *self,
+ BseItem *from_item,
+ BseItem *to_item)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ g_return_if_fail (BSE_IS_ITEM (from_item));
+ g_return_if_fail (BSE_IS_ITEM (to_item));
+ if (!to_item) /* special case (1) */
+ {
+ bse_storage_puts (self, SFI_SERIAL_NULL_TOKEN);
+ }
+ else /* ordinary object link within a project or other container */
+ {
+ BseItem *tmp, *common_ancestor;
+ guint pbackup = 0;
+ gchar *upath, *epath;
+ g_return_if_fail (BSE_IS_ITEM (to_item));
+ common_ancestor = bse_item_common_ancestor (from_item, to_item);
+ g_return_if_fail (BSE_IS_CONTAINER (common_ancestor));
+ sfi_ppool_set (self->referenced_items, to_item);
+ /* figure number of parent backup levels to reach common ancestor */
+ for (tmp = from_item; tmp != common_ancestor; tmp = tmp->parent)
+ pbackup++;
+ /* path to reach to_item */
+ upath = bse_container_make_upath (BSE_CONTAINER (common_ancestor), to_item);
+ /* store path reference */
+ epath = g_strescape (upath, NULL);
+ bse_storage_printf (self, "(link %u \"%s\")", pbackup, epath);
+ g_free (epath);
+ g_free (upath);
+ }
+ }
+
+ #ifdef DOXER
+ /**
+ * @param data user data
+ * @param storage BseStorage instance
+ * @param from_item link owner
+ * @param to_item link target or NULL
+ * @param error error string describing failing link lookups
+ *
+ * BseStorageRestoreLink() is a user supplied handler to be called
+ * at the end of a parsing stage, once object references could be
+ * resolved. Failing resolutions are indicated by non NULL @a error
+ * strings.
+ */
+ typedef void (*BseStorageRestoreLink) (gpointer data,
+ BseStorage *storage,
+ BseItem *from_item,
+ BseItem *to_item,
+ const gchar *error);
+ #endif
+
+ /**
+ * @param self valid BseStorage
+ * @param from_item link owner
+ * @param restore_link BseStorageRestoreLink handler to be called once the link was resolved
+ * @param data user data passed into @a restore_link()
+ * @return expected token in case of a parsing error (G_TOKEN_NONE on success)
+ *
+ * Parse an item link statement and return the expected token if a parsing
+ * error occours. Item links are resolved at the end of the parsing stage
+ * by calling the user supplied handler @a restore_link() with the link target
+ * amongst its arguments (see BseStorageRestoreLink()).
+ */
+ GTokenType
+ bse_storage_parse_item_link (BseStorage *self,
+ BseItem *from_item,
+ BseStorageRestoreLink restore_link,
+ gpointer data)
+ {
+ GScanner *scanner;
+ BseStorageItemLink *ilink;
+ GTokenType expected_token;
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (self->rstore, G_TOKEN_ERROR);
+ g_return_val_if_fail (BSE_IS_ITEM (from_item), G_TOKEN_ERROR);
+ g_return_val_if_fail (restore_link != NULL, G_TOKEN_ERROR);
+ scanner = bse_storage_get_scanner (self);
+ #define parse_or_goto(etoken,label) \
+ { expected_token = (etoken); if (g_scanner_get_next_token (scanner) != expected_token) goto label; }
+ #define peek_or_goto(etoken,label) \
+ { expected_token = (etoken); if (g_scanner_peek_next_token (scanner) != expected_token) \
+ { g_scanner_get_next_token (scanner); goto label; } }
+ g_scanner_get_next_token (scanner);
+ bse_object_restore_start (BSE_OBJECT (from_item), self);
+ if (sfi_serial_check_parse_null_token (scanner))
+ {
+ ilink = storage_add_item_link (self, from_item, restore_link, data, NULL);
+ }
+ else if (scanner->token == '(')
+ {
+ parse_or_goto (G_TOKEN_IDENTIFIER, error_parse_link);
+ if (strcmp (scanner->value.v_identifier, "link") == 0)
+ {
+ guint pbackup = 0;
+ if (g_scanner_peek_next_token (scanner) == G_TOKEN_INT)
+ {
+ g_scanner_get_next_token (scanner); /* eat int */
+ pbackup = scanner->value.v_int64;
+ }
+ parse_or_goto (G_TOKEN_STRING, error_parse_link);
+ peek_or_goto (GTokenType (')'), error_parse_link);
+ ilink = storage_add_item_link (self, from_item, restore_link, data, NULL);
+ ilink->upath = g_strdup (scanner->value.v_string);
+ ilink->pbackup = pbackup;
+ }
+ else
+ {
+ expected_token = G_TOKEN_IDENTIFIER;
+ goto error_parse_link;
+ }
+ parse_or_goto (GTokenType (')'), error_parse_link);
+ }
+ else
+ {
+ expected_token = GTokenType ('(');
+ goto error_parse_link;
+ }
+ return G_TOKEN_NONE;
+ #undef parse_or_goto
+ #undef peek_or_goto
+ error_parse_link:
+ ilink = storage_add_item_link (self, from_item, restore_link, data, g_strdup ("failed to parse link
path"));
+ return expected_token;
+ }
+
+ void
+ bse_storage_warn_str (BseStorage *self, const std::string &string)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ if (self->rstore)
+ sfi_rstore_warn (self->rstore, string);
+ else
+ g_printerr ("BseStorage: while storing: %s", string.c_str());
+ }
+
+ GTokenType
+ bse_storage_skip (BseStorage *self, const std::string &string)
+ {
+ GTokenType token;
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (self->rstore != NULL, G_TOKEN_ERROR);
+ token = sfi_rstore_warn_skip (self->rstore, string);
+ return token;
+ }
+
+ void
+ bse_storage_error_str (BseStorage *self, const std::string &string)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ if (self->rstore)
+ sfi_rstore_error (self->rstore, string);
+ else
+ g_printerr ("BseStorage: ERROR: while storing: %s\n", string.c_str());
+ }
+
+ static void
+ bse_item_store_property (BseItem *item,
+ BseStorage *storage,
+ GValue *value,
+ GParamSpec *pspec)
+ {
+ if (g_type_is_a (G_VALUE_TYPE (value), BSE_TYPE_ITEM))
+ {
+ bse_storage_break (storage);
+ bse_storage_putc (storage, '(');
+ bse_storage_puts (storage, pspec->name);
+ bse_storage_putc (storage, ' ');
+ bse_storage_put_item_link (storage, item, (BseItem*) g_value_get_object (value));
+ bse_storage_putc (storage, ')');
+ }
+ else if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT))
+ g_warning ("%s: unable to store object property \"%s\" of type `%s'",
+ G_STRLOC, pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
+ else
+ bse_storage_put_param (storage, value, pspec);
+ }
+
+ static void
+ bse_source_store_automation (BseSource *source,
+ BseStorage *storage,
+ GParamSpec *pspec)
+ {
+ guint midi_channel = 0;
+ BseMidiSignalType signal_type = BseMidiSignalType (0);
+ bse_source_get_automation_property (source, pspec->name, &midi_channel, &signal_type);
+ BseMidiControlType control_type = BseMidiControlType (signal_type);
+ if (control_type)
+ {
+ bse_storage_break (storage);
+ bse_storage_printf (storage, "(source-automate \"%s\" %u %s)", pspec->name,
+ midi_channel, sfi_enum2choice (control_type, BSE_TYPE_MIDI_CONTROL_TYPE));
+ }
+ }
+
+ static void
+ store_item_properties (BseItem *item,
+ BseStorage *storage)
+ {
+ GParamSpec **pspecs;
+ guint n;
+ /* dump the object properties, starting out at the base class */
+ pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (item), &n);
+ while (n--)
+ {
+ GParamSpec *pspec = pspecs[n];
+ if (sfi_pspec_check_option (pspec, "S")) /* check serializable */
+ {
+ GValue value = { 0, };
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_object_get_property (G_OBJECT (item), pspec->name, &value);
+ if (!g_param_value_defaults (pspec, &value) ||
+ !sfi_pspec_check_option (pspec, "skip-default"))
+ bse_item_store_property (item, storage, &value, pspec);
+ g_value_unset (&value);
+ if (sfi_pspec_check_option (pspec, "automate") && BSE_IS_SOURCE (item))
+ bse_source_store_automation (BSE_SOURCE (item), storage, pspec);
+ }
+ }
+ g_free (pspecs);
+ }
+
+ void
+ bse_storage_store_item (BseStorage *self, BseItem *item)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ g_return_if_fail (BSE_IS_ITEM (item));
+ g_object_ref (self);
+ g_object_ref (item);
+ sfi_ppool_set (self->stored_items, item);
+ store_item_properties (item, self);
+ BSE_OBJECT_GET_CLASS (item)->store_private (BSE_OBJECT (item), self);
+ bse_parasite_store (BSE_OBJECT (item), self);
+ if (BSE_IS_CONTAINER (item))
+ bse_container_store_children ((BseContainer*) item, self);
+ g_object_unref (item);
+ g_object_unref (self);
+ }
+
+ void
+ bse_storage_store_child (BseStorage *self, BseItem *item)
+ {
+ gchar *uname;
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ g_return_if_fail (BSE_IS_ITEM (item));
+ uname = g_strescape (BSE_OBJECT_UNAME (item), NULL);
+ bse_storage_break (self);
+ bse_storage_printf (self, "(%s \"%s::%s\"", "container-child", G_OBJECT_TYPE_NAME (item), uname);
+ g_free (uname);
+ bse_storage_push_level (self);
+ bse_storage_store_item (self, item);
+ bse_storage_pop_level (self);
+ bse_storage_putc (self, ')');
+ }
+
+ void
+ bse_storage_putf (BseStorage *self,
+ gfloat vfloat)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ sfi_wstore_putf (self->wstore, vfloat);
+ }
+
+ void
+ bse_storage_putd (BseStorage *self,
+ gdouble vdouble)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ sfi_wstore_putd (self->wstore, vdouble);
+ }
+
+ void
+ bse_storage_putr (BseStorage *self,
+ SfiReal vreal,
+ const gchar *hints)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ if (hints && g_option_check (hints, "f")) /* check float option */
+ bse_storage_putf (self, vreal);
+ else
+ bse_storage_putd (self, vreal);
+ }
+
+ void
+ bse_storage_put_xinfos (BseStorage *self,
+ gchar **xinfos)
+ {
+ xinfos = bse_xinfos_dup_consolidated (xinfos, FALSE);
+ if (xinfos && xinfos[0])
+ {
+ bse_storage_break (self);
+ gchar *str = g_strescape (xinfos[0], NULL);
+ bse_storage_printf (self, " (\"%s\"", str);
+ g_free (str);
+ guint i;
+ bse_storage_push_level (self);
+ for (i = 1; xinfos[i]; i++)
+ {
+ bse_storage_break (self);
+ str = g_strescape (xinfos[i], NULL);
+ bse_storage_printf (self, "\"%s\"", str);
+ g_free (str);
+ }
+ bse_storage_pop_level (self);
+ bse_storage_puts (self, ")");
+ }
+ else
+ bse_storage_printf (self, "#f");
+ g_strfreev (xinfos);
+ }
+
+ GTokenType
+ bse_storage_parse_xinfos (BseStorage *self,
+ gchar ***xinfosp)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ g_scanner_get_next_token (scanner);
+ if (scanner->token == '#') /* parse "#f" => NULL */
+ {
+ g_scanner_get_next_token (scanner);
+ if (scanner->token == 'f' || scanner->token == 'F')
+ {
+ *xinfosp = NULL;
+ return G_TOKEN_NONE;
+ }
+ /* everything else, even #t is bogus */
+ return GTokenType ('f');
+ }
+ else if (scanner->token == '(')
+ {
+ gchar **xinfos = NULL;
+ while (g_scanner_get_next_token (scanner) != ')')
+ {
+ if (scanner->token == G_TOKEN_STRING)
+ xinfos = bse_xinfos_parse_assignment (xinfos, scanner->value.v_string);
+ else
+ return G_TOKEN_STRING;
+ }
+ *xinfosp = bse_xinfos_dup_consolidated (xinfos, FALSE);
+ g_strfreev (xinfos);
+ return G_TOKEN_NONE;
+ }
+ else
+ return GTokenType ('(');
+ }
+
+ static GTokenType
+ parse_dblock_data_handle (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ BseStorageDBlock *dblock;
+ gulong id;
+ parse_or_return (scanner, G_TOKEN_INT);
+ id = scanner->value.v_int64;
+ parse_or_return (scanner, ')');
+ dblock = bse_storage_get_dblock (self, id);
+ if (!dblock)
+ {
+ bse_storage_error (self, "failed to lookup internal data handle with id: %lu", id);
+ return G_TOKEN_ERROR;
+ }
+ *data_handle_p = gsl_data_handle_ref (dblock->dhandle); /* fake "creating" a data handle */
+ if (n_channels_p)
+ *n_channels_p = dblock->n_channels;
+ if (mix_freq_p)
+ *mix_freq_p = dblock->mix_freq;
+ if (osc_freq_p)
+ *osc_freq_p = dblock->osc_freq;
+ return G_TOKEN_NONE;
+ }
+
+ typedef struct {
+ GslDataHandle *dhandle;
+ guint opened : 1;
+ guint bpv, format, byte_order;
+ BseStorage *storage;
+ guint length;
+ } WStoreDHandle;
+
+ static void
+ wstore_data_handle_destroy (gpointer data)
+ {
+ WStoreDHandle *wh = (WStoreDHandle*) data;
+ if (wh->opened)
+ gsl_data_handle_close (wh->dhandle);
+ gsl_data_handle_unref (wh->dhandle);
+ g_free (wh);
+ }
+
+ static gint /* -errno || length */
+ wstore_data_handle_reader (gpointer data,
+ void *buffer,
+ guint blength)
+ {
+ WStoreDHandle *wh = (WStoreDHandle*) data;
+ GslLong n;
+ if (!wh->opened)
+ {
+ BseErrorType error = gsl_data_handle_open (wh->dhandle);
+ if (error)
+ {
+ bse_storage_error (wh->storage, "failed to open data handle: %s", bse_error_blurb (error));
+ return -ENOENT;
+ }
+ wh->opened = TRUE;
+ }
+ /* catch end */
+ if (wh->length >= gsl_data_handle_length (wh->dhandle))
+ return 0;
+ do
+ n = gsl_data_handle_read (wh->dhandle, wh->length, blength / sizeof (gfloat), (float*) buffer);
+ while (n < 0 && errno == EINTR);
+ if (n < 0) /* bail out */
+ {
+ bse_storage_error (wh->storage, "failed to read from data handle");
+ return -EIO;
+ }
+ wh->length += n;
+ return gsl_conv_from_float_clip (GslWaveFormatType (wh->format), wh->byte_order, (const float*) buffer,
buffer, n);
+ }
+
+ void
+ bse_storage_put_data_handle (BseStorage *self,
+ guint significant_bits,
+ GslDataHandle *dhandle)
+ {
+ g_return_if_fail (BSE_IS_STORAGE (self));
+ g_return_if_fail (self->wstore);
+ g_return_if_fail (dhandle != NULL);
+ g_return_if_fail (GSL_DATA_HANDLE_OPENED (dhandle));
+ if (BSE_STORAGE_DBLOCK_CONTAINED (self))
+ {
+ /* stored as binary data block in memory for undo storage */
+ gulong id = bse_storage_add_dblock (self, dhandle);
+ bse_storage_break (self);
+ bse_storage_printf (self, "(%s %lu)", g_quark_to_string (quark_dblock_data_handle), id);
+ return;
+ }
+ GslDataHandle *test_handle, *tmp_handle = dhandle;
+ do /* skip comment or cache handles */
+ {
+ test_handle = tmp_handle;
+ tmp_handle = gsl_data_handle_get_source (test_handle);
+ }
+ while (tmp_handle); /* skip comment or cache handles */
+ GslVorbis1Handle *vhandle = gsl_vorbis1_handle_new (test_handle, gsl_vorbis_make_serialno());
+ Flac1Handle *flac_handle = Flac1Handle::create (test_handle);
+ if (vhandle) /* save already compressed Ogg/Vorbis data */
+ {
+ bse_storage_break (self);
+ bse_storage_printf (self, "(%s ", g_quark_to_string (quark_vorbis_data_handle));
+ bse_storage_putf (self, gsl_data_handle_osc_freq (dhandle));
+ bse_storage_push_level (self);
+ bse_storage_break (self);
+ gsl_vorbis1_handle_put_wstore (vhandle, self->wstore);
+ bse_storage_pop_level (self);
+ bse_storage_putc (self, ')');
+ }
+ else if (flac_handle) /* save flac compressed handle */
+ {
+ bse_storage_break (self);
+ bse_storage_printf (self, "(%s ", g_quark_to_string (quark_flac_data_handle));
+ bse_storage_putf (self, gsl_data_handle_osc_freq (dhandle));
+ bse_storage_push_level (self);
+ bse_storage_break (self);
+ flac_handle->put_wstore (self->wstore);
+ bse_storage_pop_level (self);
+ bse_storage_putc (self, ')');
+ }
+ else /* save raw data handle */
+ {
+ if (significant_bits < 1)
+ significant_bits = 32;
+ const uint bitdepth = gsl_data_handle_bit_depth (dhandle);
+ significant_bits = MIN (bitdepth, significant_bits);
+ GslWaveFormatType format;
+ if (significant_bits > 16)
+ format = GSL_WAVE_FORMAT_FLOAT;
+ else if (significant_bits <= 8)
+ format = GSL_WAVE_FORMAT_SIGNED_8;
+ else
+ format = GSL_WAVE_FORMAT_SIGNED_16;
+ bse_storage_break (self);
+ bse_storage_printf (self,
+ "(%s %u %s %s",
+ g_quark_to_string (quark_raw_data_handle),
+ gsl_data_handle_n_channels (dhandle),
+ gsl_wave_format_to_string (format),
+ gsl_byte_order_to_string (G_LITTLE_ENDIAN));
+ bse_storage_puts (self, " ");
+ bse_storage_putf (self, gsl_data_handle_mix_freq (dhandle));
+ bse_storage_puts (self, " ");
+ bse_storage_putf (self, gsl_data_handle_osc_freq (dhandle));
+ bse_storage_push_level (self);
+ bse_storage_break (self);
+ WStoreDHandle *wh = g_new0 (WStoreDHandle, 1);
+ wh->dhandle = gsl_data_handle_ref (dhandle);
+ wh->format = format;
+ wh->byte_order = G_LITTLE_ENDIAN;
+ wh->bpv = gsl_wave_format_byte_width (format);
+ wh->storage = self;
+ sfi_wstore_put_binary (self->wstore, wstore_data_handle_reader, wh, wstore_data_handle_destroy);
+ bse_storage_pop_level (self);
+ bse_storage_putc (self, ')');
+ }
+ }
+
+ static GTokenType
+ parse_raw_data_handle (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ guint n_channels, byte_order;
+ gfloat mix_freq, osc_freq;
+ SfiNum offset, length;
+ GTokenType token;
+ parse_or_return (scanner, G_TOKEN_INT);
+ n_channels = scanner->value.v_int64;
+ if (n_channels <= 0 || n_channels > 256)
+ return bse_storage_warn_skip (self, "invalid number of channels: %u", n_channels);
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ GslWaveFormatType format = gsl_wave_format_from_string (scanner->value.v_identifier);
+ if (format == GSL_WAVE_FORMAT_NONE)
+ return bse_storage_warn_skip (self, "unknown format for data handle: %s", scanner->value.v_identifier);
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ byte_order = gsl_byte_order_from_string (scanner->value.v_identifier);
+ if (!byte_order)
+ return bse_storage_warn_skip (self, "unknown byte-order for data handle: %s",
scanner->value.v_identifier);
+ g_scanner_get_next_token (scanner);
+ if (scanner->token == G_TOKEN_INT)
+ mix_freq = scanner->value.v_int64;
+ else if (scanner->token == G_TOKEN_FLOAT)
+ mix_freq = scanner->value.v_float;
+ else
+ return G_TOKEN_FLOAT;
+ g_scanner_get_next_token (scanner);
+ if (scanner->token == G_TOKEN_INT)
+ osc_freq = scanner->value.v_int64;
+ else if (scanner->token == G_TOKEN_FLOAT)
+ osc_freq = scanner->value.v_float;
+ else
+ return G_TOKEN_FLOAT;
+ if (osc_freq <= 0 || mix_freq < 4000 || osc_freq >= mix_freq / 2)
+ return bse_storage_warn_skip (self, "invalid oscillating/mixing frequencies: %.7g/%.7g", osc_freq,
mix_freq);
+ token = sfi_rstore_parse_binary (self->rstore, &offset, &length);
+ if (token != G_TOKEN_NONE)
+ return token;
+ length /= gsl_wave_format_byte_width (format);
+ parse_or_return (scanner, ')');
+ if (length < 1)
+ {
+ bse_storage_warn (self, "encountered empty data handle");
+ *data_handle_p = NULL;
+ }
+ else
+ *data_handle_p = gsl_wave_handle_new (self->rstore->fname,
+ n_channels, format, byte_order,
+ mix_freq, osc_freq,
+ offset, length, NULL);
+ if (n_channels_p)
+ *n_channels_p = n_channels;
+ if (mix_freq_p)
+ *mix_freq_p = mix_freq;
+ if (osc_freq_p)
+ *osc_freq_p = osc_freq;
+ return G_TOKEN_NONE;
+ }
+
+ static GTokenType
+ parse_vorbis_or_flac_data_handle (BseStorage *self,
+ GQuark quark,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ GTokenType token;
+ gfloat osc_freq;
+ g_scanner_get_next_token (scanner);
+ if (scanner->token == G_TOKEN_INT)
+ osc_freq = scanner->value.v_int64;
+ else if (scanner->token == G_TOKEN_FLOAT)
+ osc_freq = scanner->value.v_float;
+ else
+ return G_TOKEN_FLOAT;
+ if (osc_freq <= 0)
+ return bse_storage_warn_skip (self, "invalid oscillating frequency: %.7g", osc_freq);
+ if (osc_freq_p)
+ *osc_freq_p = osc_freq;
+ SfiNum offset, length;
+ token = sfi_rstore_parse_zbinary (self->rstore, &offset, &length);
+ if (token != G_TOKEN_NONE)
+ return token;
+ parse_or_return (scanner, ')');
+ if (length < 1)
+ {
+ bse_storage_warn (self, "encountered empty data handle");
+ *data_handle_p = NULL;
+ }
+ else
+ {
+ gfloat mix_freq;
+ if (quark == quark_vorbis_data_handle)
+ {
+ *data_handle_p = gsl_data_handle_new_ogg_vorbis_zoffset (self->rstore->fname, osc_freq,
+ offset, length, n_channels_p, &mix_freq);
+ }
+ else if (quark == quark_flac_data_handle)
+ {
+ *data_handle_p = bse_data_handle_new_flac_zoffset (self->rstore->fname, osc_freq,
+ offset, length, n_channels_p, &mix_freq);
+ }
+ else
+ {
+ return bse_storage_warn_skip (self, "unknown compressed data handle type in
parse_vorbis_or_flac_data_handle");
+ }
+ if (osc_freq <= 0 || mix_freq < 4000 || osc_freq >= mix_freq / 2)
+ return bse_storage_warn_skip (self, "invalid oscillating/mixing frequencies: %.7g/%.7g", osc_freq,
mix_freq);
+ if (mix_freq_p)
+ *mix_freq_p = mix_freq;
+ }
+ return G_TOKEN_NONE;
+ }
+
+ gboolean
+ bse_storage_match_data_handle (BseStorage *self,
+ GQuark quark)
+ {
+ if (BSE_STORAGE_DBLOCK_CONTAINED (self) &&
+ quark == quark_dblock_data_handle)
+ return TRUE;
+ if (quark == quark_raw_data_handle ||
+ quark == quark_vorbis_data_handle ||
+ quark == quark_flac_data_handle)
+ return TRUE;
+ return FALSE;
+ }
+
+ static GTokenType
+ parse_data_handle_trampoline (BseStorage *self,
+ gboolean statement_opened,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ GScanner *scanner = bse_storage_get_scanner (self);
+ GQuark quark;
+ *data_handle_p = NULL;
+ if (n_channels_p)
+ *n_channels_p = 0;
+ if (mix_freq_p)
+ *mix_freq_p = 0;
+ if (osc_freq_p)
+ *osc_freq_p = 0;
+ if (!statement_opened)
+ parse_or_return (scanner, '(');
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ quark = g_quark_try_string (scanner->value.v_identifier);
+ if (BSE_STORAGE_DBLOCK_CONTAINED (self) && quark == quark_dblock_data_handle)
+ return parse_dblock_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
+ if (quark == quark_raw_data_handle)
+ return parse_raw_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
+ else if (quark == quark_vorbis_data_handle || quark == quark_flac_data_handle)
+ return parse_vorbis_or_flac_data_handle (self, quark, data_handle_p, n_channels_p, mix_freq_p,
osc_freq_p);
+ if (BSE_STORAGE_COMPAT (self, 0, 5, 1) && quark == quark_bse_storage_binary_v0)
+ return compat_parse_data_handle (self, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
+ bse_storage_error (self, "unknown data handle keyword: %s", scanner->value.v_identifier);
+ return G_TOKEN_ERROR;
+ }
+
+ GTokenType
+ bse_storage_parse_data_handle (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (self->rstore, G_TOKEN_ERROR);
+ g_return_val_if_fail (data_handle_p != NULL, G_TOKEN_ERROR);
+ return parse_data_handle_trampoline (self, FALSE, data_handle_p, n_channels_p, mix_freq_p, osc_freq_p);
+ }
+
+ GTokenType
+ bse_storage_parse_data_handle_rest (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), G_TOKEN_ERROR);
+ g_return_val_if_fail (self->rstore, G_TOKEN_ERROR);
+ g_return_val_if_fail (data_handle_p != NULL, G_TOKEN_ERROR);
+ 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);
++
++ GSL_SPIN_LOCK (&blob->mutex);
++ blob->ref_count++;
++ GSL_SPIN_UNLOCK (&blob->mutex);
++
++ 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);
++
++ GSL_SPIN_LOCK (&blob->mutex);
++ const gchar *file_name = blob->file_name;
++ GSL_SPIN_UNLOCK (&blob->mutex);
++
++ return file_name;
++}
++
++void
++bse_storage_blob_unref (BseStorageBlob *blob)
++{
++ g_return_if_fail (blob != NULL);
++ g_return_if_fail (blob->ref_count > 0);
++
++ GSL_SPIN_LOCK (&blob->mutex);
++ blob->ref_count--;
++ gboolean destroy = blob->ref_count == 0;
++ GSL_SPIN_UNLOCK (&blob->mutex);
++ if (destroy)
++ {
++ if (blob->is_temp_file)
++ {
++ unlink (blob->file_name);
++ /* FIXME: check error code and do what? */
++ }
++ sfi_mutex_destroy (&blob->mutex);
++ g_free (blob->file_name);
++ blob->file_name = NULL;
++ bse_id_free (blob->id);
++ 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_printf ("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_printf ("%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);
++ blob->file_name = g_strdup (file_name);
++ blob->ref_count = 1;
++ blob->is_temp_file = is_temp_file;
++ blob->id = bse_id_alloc();
++ sfi_mutex_init (&blob->mutex);
++ 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);
++
++ GSL_SPIN_LOCK (&blob->mutex);
++ gboolean is_temp_file = blob->is_temp_file;
++ GSL_SPIN_UNLOCK (&blob->mutex);
++
++ 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 = 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 = 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_printf ("%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)
++ {
++ int i;
++ gulong id;
++ parse_or_return (scanner, G_TOKEN_INT);
++ id = scanner->value.v_int64;
++ *blob = NULL;
++ for (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_storage_flush_fd (BseStorage *self,
+ gint fd)
+ {
+ g_return_val_if_fail (BSE_IS_STORAGE (self), BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (self->wstore, BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (fd >= 0, BSE_ERROR_INTERNAL);
+ bse_storage_break (self);
+ gint nerrno = sfi_wstore_flush_fd (self->wstore, fd);
+ return bse_error_from_errno (-nerrno, BSE_ERROR_FILE_WRITE_FAILED);
+ }
+
+ void
+ bse_storage_compat_dhreset (BseStorage *self)
+ {
+ self->n_channels = 1;
+ self->mix_freq = 44100;
+ self->osc_freq = 440;
+ }
+
+ void
+ bse_storage_compat_dhmixf (BseStorage *self,
+ gfloat mix_freq)
+ {
+ self->mix_freq = mix_freq;
+ }
+
+ void
+ bse_storage_compat_dhoscf (BseStorage *self,
+ gfloat osc_freq)
+ {
+ self->osc_freq = osc_freq;
+ }
+
+ void
+ bse_storage_compat_dhchannels (BseStorage *self,
+ guint n_channels)
+ {
+ self->n_channels = n_channels;
+ }
+
+ static GTokenType
+ compat_parse_data_handle (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p)
+ {
+ guint offset, bytes_per_value, length, vlength, byte_order = G_LITTLE_ENDIAN;
+ GScanner *scanner = bse_storage_get_scanner (self);
+ GTokenType token;
+ gchar *string;
+
+ parse_or_return (scanner, G_TOKEN_INT);
+ offset = scanner->value.v_int64;
+
+ parse_or_return (scanner, G_TOKEN_IDENTIFIER);
+ string = scanner->value.v_identifier;
+ if (string[0] == 'L' || string[0] == 'l')
+ byte_order = G_LITTLE_ENDIAN;
+ else if (string[0] == 'B' || string[0] == 'b')
+ byte_order = G_BIG_ENDIAN;
+ else
+ string = NULL;
+ if (string && string[1] != ':')
+ string = NULL;
+ if (string)
+ {
+ gchar *f = NULL;
+
+ bytes_per_value = strtol (string + 2, &f, 10);
+ if ((bytes_per_value != 1 && bytes_per_value != 2 && bytes_per_value != 4) ||
+ (f && *f != 0))
+ string = NULL;
+ }
+ if (!string)
+ return bse_storage_warn_skip (self,
+ "unknown value type `%s' in binary data definition",
+ scanner->value.v_identifier);
+
+ parse_or_return (scanner, G_TOKEN_INT);
+ length = scanner->value.v_int64;
+ if (length < bytes_per_value)
+ return G_TOKEN_INT;
+
+ if (g_scanner_peek_next_token (scanner) == G_TOKEN_INT)
+ {
+ g_scanner_get_next_token (scanner);
+ vlength = scanner->value.v_int64;
+ if (vlength < 1 || vlength * bytes_per_value > length)
+ return G_TOKEN_INT;
+ }
+ else
+ vlength = length / bytes_per_value;
+
+ parse_or_return (scanner, ')');
+
+ token = sfi_rstore_ensure_bin_offset (self->rstore);
+ if (token != G_TOKEN_NONE)
+ return token;
+
+ if (n_channels_p)
+ *n_channels_p = self->n_channels;
+ if (mix_freq_p)
+ *mix_freq_p = self->mix_freq;
+ if (osc_freq_p)
+ *osc_freq_p = self->osc_freq;
+ *data_handle_p = gsl_wave_handle_new (self->rstore->fname, self->n_channels,
+ bytes_per_value == 1 ? GSL_WAVE_FORMAT_SIGNED_8 :
+ bytes_per_value == 2 ? GSL_WAVE_FORMAT_SIGNED_16 :
+ GSL_WAVE_FORMAT_FLOAT,
+ byte_order,
+ self->mix_freq, self->osc_freq,
+ sfi_rstore_get_bin_offset (self->rstore) + offset,
+ vlength, NULL);
+ return G_TOKEN_NONE;
+ }
diff --cc bse/bsestorage.hh
index 0000000,676fae0..c7f8645
mode 000000,100644..100644
--- a/bse/bsestorage.hh
+++ b/bse/bsestorage.hh
@@@ -1,0 -1,177 +1,193 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BSE_STORAGE_H__
+ #define __BSE_STORAGE_H__
+
+ #include <bse/bseobject.hh>
+ #include <bse/gsldefs.hh>
+
+ G_BEGIN_DECLS
+
+ /* --- object type macros --- */
+ #define BSE_TYPE_STORAGE (BSE_TYPE_ID (BseStorage))
+ #define BSE_STORAGE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), BSE_TYPE_STORAGE,
BseStorage))
+ #define BSE_STORAGE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_STORAGE,
BseStorageClass))
+ #define BSE_IS_STORAGE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), BSE_TYPE_STORAGE))
+ #define BSE_IS_STORAGE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_STORAGE))
+ #define BSE_STORAGE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), BSE_TYPE_STORAGE,
BseStorageClass))
+
+
+ /* --- macros --- */
+ #define BSE_STORAGE_VERSION(self, vmaj, min, vmic) ( /* whether file uses >=vARGS features */ \
+ BSE_VERSION_CMP (self->major_version, self->minor_version, self->micro_version, vmaj, min, vmic) >= 0)
+ #define BSE_STORAGE_COMPAT(self, vmaj, min, vmic) ( /* whether file needs <=vARGS compat code */ \
+ BSE_VERSION_CMP (self->major_version, self->minor_version, self->micro_version, vmaj, min, vmic) <= 0)
+ #define BSE_STORAGE_SELF_CONTAINED(st) ((BSE_OBJECT_FLAGS (st) & BSE_STORAGE_SELF_CONTAINED) != 0)
+ #define BSE_STORAGE_DBLOCK_CONTAINED(st) ((BSE_OBJECT_FLAGS (st) & BSE_STORAGE_DBLOCK_CONTAINED) != 0)
+ #define BSE_STORAGE_IS_UNDO(st) BSE_STORAGE_DBLOCK_CONTAINED (st)
+ typedef enum /*< skip >*/
+ {
+ BSE_STORAGE_SELF_CONTAINED = 1 << (BSE_OBJECT_FLAGS_USHIFT + 0),
+ BSE_STORAGE_DBLOCK_CONTAINED = 1 << (BSE_OBJECT_FLAGS_USHIFT + 1)
+ } BseStorageMode;
+ #define BSE_STORAGE_FLAGS_USHIFT (BSE_OBJECT_FLAGS_USHIFT + 2)
+ #define BSE_STORAGE_MODE_MASK (BSE_STORAGE_SELF_CONTAINED | BSE_STORAGE_DBLOCK_CONTAINED)
+
+
+ /* --- compatibility --- */
+ #define bse_storage_scanner_parse_or_return sfi_scanner_parse_or_return
+ #define bse_storage_scanner_peek_or_return sfi_scanner_peek_or_return
+
+
+ /* --- BseStorage --- */
+ typedef struct _BseStorageDBlock BseStorageDBlock;
+ typedef struct _BseStorageItemLink BseStorageItemLink;
++typedef struct _BseStorageBlob BseStorageBlob;
+ typedef void (*BseStorageRestoreLink) (gpointer data,
+ BseStorage *storage,
+ BseItem *from_item,
+ BseItem *to_item,
+ const gchar *error);
+ struct BseStorage : BseObject {
+ /* writing */
+ SfiWStore *wstore;
+ SfiPPool *stored_items;
+ SfiPPool *referenced_items;
+ /* parsing */
+ SfiRStore *rstore;
+ guint major_version;
+ guint minor_version;
+ guint micro_version;
+ GHashTable *path_table;
+ SfiRing *item_links;
+ SfiPPool *restorable_objects;
+ /* internal data */
+ guint n_dblocks;
+ BseStorageDBlock *dblocks;
++ guint n_blobs;
++ BseStorageBlob **blobs;
+ gchar *free_me;
+ /* compat */ // VERSION-FIXME: needed only for <= 0.5.1
+ gfloat mix_freq;
+ gfloat osc_freq;
+ guint n_channels;
+ };
+ struct BseStorageClass : BseObjectClass
+ {};
+
+ /* --- compatibility file parsing --- */
+ void bse_storage_compat_dhreset (BseStorage *self);
+ void bse_storage_compat_dhmixf (BseStorage *self,
+ gfloat mix_freq);
+ void bse_storage_compat_dhoscf (BseStorage *self,
+ gfloat osc_freq);
+ void bse_storage_compat_dhchannels (BseStorage *self,
+ guint n_channels);
+
+
+ /* --- prototypes -- */
+ void bse_storage_reset (BseStorage *self);
+ void bse_storage_prepare_write (BseStorage *self,
+ BseStorageMode mode);
+ void bse_storage_turn_readable (BseStorage *self,
+ const gchar *storage_name);
+ BseErrorType bse_storage_input_file (BseStorage *self,
+ const gchar *file_name);
+ void bse_storage_input_text (BseStorage *self,
+ const gchar *text,
+ const gchar *text_name);
+ GTokenType bse_storage_restore_item (BseStorage *self,
+ gpointer item);
+ void bse_storage_store_item (BseStorage *self,
+ BseItem *item);
+ void bse_storage_store_child (BseStorage *self,
+ BseItem *item);
+ const gchar* bse_storage_item_get_compat_type (BseItem *item);
+
+
+ /* --- writing --- */
+ void bse_storage_putf (BseStorage *self,
+ gfloat vfloat);
+ void bse_storage_putd (BseStorage *self,
+ gdouble vdouble);
+ void bse_storage_putr (BseStorage *self,
+ SfiReal vreal,
+ const gchar *hints);
+ void bse_storage_put_param (BseStorage *self,
+ const GValue *value,
+ GParamSpec *pspec);
+ void bse_storage_put_item_link (BseStorage *self,
+ BseItem *from_item,
+ BseItem *to_item);
+ 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,
+ gint fd);
+
+
+ /* --- reading --- */
+ #define bse_storage_error(s, ...) bse_storage_error_str (s, Rapicorn::string_format
(__VA_ARGS__).c_str())
+ void bse_storage_error_str (BseStorage *self, const std::string &string);
+ #define bse_storage_warn(s, ...) bse_storage_warn_str (s, Rapicorn::string_format
(__VA_ARGS__).c_str())
+ void bse_storage_warn_str (BseStorage *self, const std::string &string);
+ #define bse_storage_warn_skip(s, ...) bse_storage_skip (s, Rapicorn::string_format
(__VA_ARGS__).c_str())
+ GTokenType bse_storage_skip (BseStorage *self, const std::string &string);
+ GTokenType bse_storage_parse_param_value (BseStorage *self,
+ GValue *value,
+ GParamSpec *pspec);
+ GTokenType bse_storage_parse_item_link (BseStorage *self,
+ BseItem *from_item,
+ BseStorageRestoreLink restore_link,
+ gpointer data);
+ void bse_storage_add_restorable (BseStorage *self,
+ BseObject *object);
+ void bse_storage_finish_parsing (BseStorage *self);
+ GTokenType bse_storage_parse_data_handle (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p);
+ gboolean bse_storage_match_data_handle (BseStorage *self,
+ GQuark quark);
+ GTokenType bse_storage_parse_data_handle_rest (BseStorage *self,
+ GslDataHandle **data_handle_p,
+ guint *n_channels_p,
+ gfloat *mix_freq_p,
+ gfloat *osc_freq_p);
+ GTokenType bse_storage_parse_xinfos (BseStorage *self,
+ gchar ***xinfosp);
+ GTokenType bse_storage_parse_rest (BseStorage *self,
+ gpointer context_data,
+ BseTryStatement try_statement,
+ gpointer user_data);
++GTokenType bse_storage_parse_blob (BseStorage *self,
++ BseStorageBlob **blob);
+ gboolean bse_storage_check_parse_negate (BseStorage *self);
+
++/* --- bse storage blob --- */
++
++BseStorageBlob *bse_storage_blob_ref (BseStorageBlob *self);
++const gchar *bse_storage_blob_file_name (BseStorageBlob *self);
++gboolean bse_storage_blob_is_temp_file (BseStorageBlob *self);
++void bse_storage_blob_unref (BseStorageBlob *self);
++BseStorageBlob *bse_storage_blob_new_from_file (const gchar *file_name,
++ gboolean is_temp_file);
++void bse_storage_blob_clean_files (void);
+
+ /* --- short-hands --- */
+ #define bse_storage_get_scanner(s) ((s)->rstore->scanner)
+ #define bse_storage_unexp_token(s,et) sfi_rstore_unexp_token ((s)->rstore, et)
+ #define bse_storage_push_level(s) sfi_wstore_push_level ((s)->wstore)
+ #define bse_storage_pop_level(s) sfi_wstore_pop_level ((s)->wstore)
+ #define bse_storage_break(s) sfi_wstore_break ((s)->wstore)
+ #define bse_storage_putc(s,c) sfi_wstore_putc ((s)->wstore, c)
+ #define bse_storage_puts(s,b) sfi_wstore_puts ((s)->wstore, b)
+ #define bse_storage_printf(s, ...) bse_storage_puts (s, Rapicorn::string_format (__VA_ARGS__).c_str())
+
+ G_END_DECLS
+
+ #endif /* __BSE_STORAGE_H__ */
diff --cc bse/bsetrack.cc
index 0000000,84677c6..b1fbba9
mode 000000,100644..100644
--- a/bse/bsetrack.cc
+++ b/bse/bsetrack.cc
@@@ -1,0 -1,1058 +1,1148 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #include "bsetrack.hh"
+
+ #include "bseglobals.hh"
+ #include "bsestorage.hh"
+ #include "bsecsynth.hh"
+ #include "bsewave.hh"
+ #include "bsepart.hh"
+ #include "bsebus.hh"
+ #include "bsesequencer.hh"
+ #include "gslcommon.hh"
+ #include "bsesubsynth.hh"
+ #include "bseproject.hh"
+ #include "bsesong.hh"
+ #include "bsemidivoice.hh"
+ #include "bsemidireceiver.hh"
+ #include "bsewaverepo.hh"
++#include "bsesoundfontrepo.h"
++#include "bsesoundfontpreset.h"
++#include "bsesoundfont.h"
+ #include "bsecxxplugin.hh"
++
+ #include <string.h>
+
+ #define XREF_DEBUG(...) BSE_KEY_DEBUG ("xref", __VA_ARGS__)
+
+ #define upper_power2(uint_n) sfi_alloc_upper_power2 (MAX ((uint_n), 4))
+ #define parse_or_return bse_storage_scanner_parse_or_return
+ #define peek_or_return bse_storage_scanner_peek_or_return
+
+ enum {
+ PROP_0,
+ PROP_MUTED,
+ PROP_SNET,
+ PROP_WAVE,
++ PROP_SOUND_FONT_PRESET,
+ PROP_MIDI_CHANNEL,
+ PROP_N_VOICES,
+ PROP_PNET,
+ PROP_OUTPUTS
+ };
+
+ /* --- prototypes --- */
+ static void bse_track_class_init (BseTrackClass *klass);
+ static void bse_track_init (BseTrack *self);
+ static void bse_track_dispose (GObject *object);
+ static void bse_track_finalize (GObject *object);
+ static void bse_track_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+ static void bse_track_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+ static void bse_track_store_private (BseObject *object,
+ BseStorage *storage);
+ static GTokenType bse_track_restore_private (BseObject *object,
+ BseStorage *storage,
+ GScanner *scanner);
+ static void bse_track_update_midi_channel (BseTrack *self);
+
+
+ /* --- variables --- */
+ static GTypeClass *parent_class = NULL;
+ static guint signal_changed = 0;
+
+
+ /* --- functions --- */
+ BSE_BUILTIN_TYPE (BseTrack)
+ {
+ static const GTypeInfo track_info = {
+ sizeof (BseTrackClass),
+
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) bse_track_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL /* class_data */,
+
+ sizeof (BseTrack),
+ 0 /* n_preallocs */,
+ (GInstanceInitFunc) bse_track_init,
+ };
+
+ return bse_type_register_static (BSE_TYPE_CONTEXT_MERGER,
+ "BseTrack",
+ "BSE track type",
+ __FILE__, __LINE__,
+ &track_info);
+ }
+
+ static gulong
+ alloc_id_above (guint n)
+ {
+ gulong tmp, id = bse_id_alloc ();
+ if (id > n)
+ return id;
+ tmp = id;
+ id = alloc_id_above (n);
+ bse_id_free (tmp);
+ return id;
+ }
+
+ static void
+ bse_track_init (BseTrack *self)
+ {
+ BSE_OBJECT_SET_FLAGS (self, BSE_SOURCE_FLAG_PRIVATE_INPUTS);
+ self->snet = NULL;
+ self->pnet = NULL;
++ self->sound_font_preset = NULL;
++ self->wave = NULL;
++ self->wnet = NULL;
+ self->max_voices = 16;
+ self->muted_SL = FALSE;
+ self->n_entries_SL = 0;
+ self->entries_SL = g_renew (BseTrackEntry, NULL, upper_power2 (self->n_entries_SL));
+ self->channel_id = alloc_id_above (BSE_MIDI_MAX_CHANNELS);
+ self->midi_channel_SL = self->channel_id;
+ self->track_done_SL = FALSE;
+ }
+
+ static void
+ bse_track_dispose (GObject *object)
+ {
+ BseTrack *self = BSE_TRACK (object);
+
+ /* we may assert removal here, since if these assertions fail,
+ * our parent (BseSong) doesn't properly implement track support
+ */
+ g_assert (self->sub_synth == NULL);
+
+ /* check uncrossed references */
+ g_assert (self->snet == NULL);
+ g_assert (self->pnet == NULL);
+ g_assert (self->n_entries_SL == 0);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+
+ g_assert (self->bus_outputs == NULL);
+ }
+
+ static void
+ bse_track_finalize (GObject *object)
+ {
+ BseTrack *self = BSE_TRACK (object);
+
+ g_assert (self->bus_outputs == NULL);
+
+ g_assert (self->n_entries_SL == 0);
+ g_free (self->entries_SL);
+ bse_id_free (self->channel_id);
+
+ /* chain parent class' handler */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+ }
+
+ static void track_uncross_part (BseItem *owner,
+ BseItem *ref_item);
+
+ static BseTrackEntry*
+ track_add_entry (BseTrack *self,
+ guint index,
+ guint tick,
+ BsePart *part)
+ {
+ guint n, size;
+
+ g_return_val_if_fail (index <= self->n_entries_SL, NULL);
+ if (index > 0)
+ g_return_val_if_fail (self->entries_SL[index - 1].tick < tick, NULL);
+ if (index < self->n_entries_SL)
+ g_return_val_if_fail (self->entries_SL[index].tick > tick, NULL);
+
+ BSE_SEQUENCER_LOCK ();
+ n = self->n_entries_SL++;
+ size = upper_power2 (self->n_entries_SL);
+ if (size > upper_power2 (n))
+ self->entries_SL = g_renew (BseTrackEntry, self->entries_SL, size);
+ memmove (self->entries_SL + index + 1, self->entries_SL + index, (n - index) * sizeof
(self->entries_SL[0]));
+ self->entries_SL[index].tick = tick;
+ self->entries_SL[index].id = bse_id_alloc ();
+ self->entries_SL[index].part = part;
+ self->track_done_SL = FALSE; /* let sequencer recheck if playing */
+ BSE_SEQUENCER_UNLOCK ();
+ bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (part), track_uncross_part);
+ XREF_DEBUG ("cross-link: %p %p", self, part);
+ bse_object_proxy_notifies (part, self, "changed");
+ bse_object_reemit_signal (part, "notify::last-tick", self, "changed");
+ return self->entries_SL + index;
+ }
+
+ static void
+ track_delete_entry (BseTrack *self,
+ guint index)
+ {
+ g_return_if_fail (index < self->n_entries_SL);
+
+ BsePart *part = self->entries_SL[index].part;
+ bse_object_remove_reemit (part, "notify::last-tick", self, "changed");
+ bse_object_unproxy_notifies (part, self, "changed");
+ XREF_DEBUG ("cross-unlink: %p %p", self, part);
+ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (part), track_uncross_part);
+ BSE_SEQUENCER_LOCK ();
+ self->n_entries_SL -= 1;
+ bse_id_free (self->entries_SL[index].id);
+ memmove (self->entries_SL + index, self->entries_SL + index + 1, (self->n_entries_SL - index) * sizeof
(self->entries_SL[0]));
+ BSE_SEQUENCER_UNLOCK ();
+ }
+
+ static BseTrackEntry*
+ track_lookup_entry (BseTrack *self,
+ guint tick)
+ {
+ BseTrackEntry *nodes = self->entries_SL;
+ guint n = self->n_entries_SL, offs = 0, i = 0;
+
+ while (offs < n)
+ {
+ gint cmp;
+ i = (offs + n) >> 1;
+ cmp = tick > nodes[i].tick ? +1 : tick < nodes[i].tick ? -1 : 0;
+ if (!cmp)
+ return nodes + i;
+ else if (cmp < 0)
+ n = i;
+ else /* (cmp > 0) */
+ offs = i + 1;
+ }
+
+ /* return the closest entry with tick <= requested tick if possible */
+ if (!self->n_entries_SL)
+ return NULL;
+ if (nodes[i].tick > tick)
+ return i > 0 ? nodes + i - 1 : NULL; /* previous entry */
+ else
+ return nodes + i; /* closest match */
+ }
+
+ static void
+ track_uncross_part (BseItem *owner,
+ BseItem *item)
+ {
+ BseTrack *self = BSE_TRACK (owner);
+ BsePart *part = BSE_PART (item);
+ guint i;
+ for (i = 0; i < self->n_entries_SL; i++)
+ if (self->entries_SL[i].part == part)
+ {
+ guint tick = self->entries_SL[i].tick;
+ XREF_DEBUG ("uncrossing[start]: %p %p (%d)", self, part, tick);
+ /* delete track via procedure so deletion is recorded to undo */
+ bse_item_exec_void (owner, "remove-tick", tick);
+ XREF_DEBUG ("uncrossing[done]: %p %p (%d)", self, part, tick);
+ return;
+ }
+ }
+
+ static void
+ bse_track_get_candidates (BseItem *item,
+ guint param_id,
+ BsePropertyCandidates *pc,
+ GParamSpec *pspec)
+ {
+ BseTrack *self = BSE_TRACK (item);
+ switch (param_id)
+ {
+ BseProject *project;
+ SfiRing *ring;
+ case PROP_WAVE:
+ bse_property_candidate_relabel (pc, _("Available Waves"), _("List of available waves to choose as
track instrument"));
+ project = bse_item_get_project (item);
+ if (project)
+ {
+ BseWaveRepo *wrepo = bse_project_get_wave_repo (project);
+ bse_item_gather_items_typed (BSE_ITEM (wrepo), pc->items, BSE_TYPE_WAVE, BSE_TYPE_WAVE_REPO, FALSE);
+ }
+ break;
++ case PROP_SOUND_FONT_PRESET:
++ bse_property_candidate_relabel (pc, _("Sound Fonts"), _("List of available sound font presets to
choose as track instrument"));
++ project = bse_item_get_project (item);
++ if (project)
++ bse_sound_font_repo_list_all_presets (bse_project_get_sound_font_repo (project), pc->items);
++ break;
+ case PROP_SNET:
+ bse_property_candidate_relabel (pc, _("Available Synthesizers"), _("List of available synthesis
networks to choose a track instrument from"));
+ bse_item_gather_items_typed (item, pc->items, BSE_TYPE_CSYNTH, BSE_TYPE_PROJECT, FALSE);
+ break;
+ case PROP_PNET:
+ bse_property_candidate_relabel (pc, _("Available Postprocessors"), _("List of available synthesis
networks to choose a postprocessor from"));
+ bse_item_gather_items_typed (item, pc->items, BSE_TYPE_CSYNTH, BSE_TYPE_PROJECT, FALSE);
+ break;
+ case PROP_OUTPUTS:
+ bse_property_candidate_relabel (pc, _("Available Outputs"), _("List of available mixer busses to be
used as track output"));
+ bse_bus_or_track_list_output_candidates (BSE_ITEM (self), pc->items);
+ /* remove existing outputs */
+ for (ring = self->bus_outputs; ring; ring = sfi_ring_walk (ring, self->bus_outputs))
+ bse_item_seq_remove (pc->items, (BseItem*) ring->data);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
+ break;
+ }
+ }
+
+ static void
+ track_uncross_snet (BseItem *owner,
+ BseItem *ref_item)
+ {
+ BseTrack *self = BSE_TRACK (owner);
+ bse_item_set (self, "snet", NULL, NULL);
+ }
+
+ static void
+ track_uncross_pnet (BseItem *owner,
+ BseItem *ref_item)
+ {
+ BseTrack *self = BSE_TRACK (owner);
+ bse_item_set (self, "pnet", NULL, NULL);
+ }
+
+ static void
+ track_uncross_wave (BseItem *owner,
+ BseItem *ref_item)
+ {
+ BseTrack *self = BSE_TRACK (owner);
+ bse_item_set (self, "wave", NULL, NULL);
+ }
+
+ static void
+ set_amp_master_volume (BseSNet *snet, const char *amp_name, gchar **xinfos)
+ {
+ const gchar *master_volume_db = bse_xinfos_get_value (xinfos, "master-volume-db");
+ if (master_volume_db)
+ {
+ BseItem *amp = bse_container_resolve_upath (BSE_CONTAINER (snet), amp_name);
+ double volume = 0;
+ g_object_get (amp, "master-volume", &volume, NULL);
+ volume *= bse_db_to_factor (g_ascii_strtod (master_volume_db, NULL));
+ g_object_set (amp, "master-volume", volume, NULL);
+ }
+ }
++
+ static void
+ set_adsr_params (BseSNet *snet, const char *adsr_name, gchar **xinfos)
+ {
+ const gchar *adsr_release_time = bse_xinfos_get_value (xinfos, "adsr-release-time");
+ if (adsr_release_time)
+ {
+ BseItem *adsr = bse_container_resolve_upath (BSE_CONTAINER (snet), adsr_name);
+ g_object_set (adsr, "release_time", g_ascii_strtod (adsr_release_time, NULL), NULL);
+ }
+ const gchar *adsr_attack_time = bse_xinfos_get_value (xinfos, "adsr-attack-time");
+ if (adsr_attack_time)
+ {
+ BseItem *adsr = bse_container_resolve_upath (BSE_CONTAINER (snet), adsr_name);
+ g_object_set (adsr, "attack_time", g_ascii_strtod (adsr_attack_time, NULL), NULL);
+ }
+ }
++
++static void
++track_uncross_sound_font_preset (BseItem *owner,
++ BseItem *ref_item)
++{
++ BseTrack *self = BSE_TRACK (owner);
++ bse_item_set (self, "sound-font-preset", NULL, NULL);
++}
++
+ static void
+ create_wnet (BseTrack *self,
+ BseWave *wave)
+ {
+ g_return_if_fail (self->wnet == NULL);
+
+ const gchar *play_type = bse_xinfos_get_value (wave->xinfos, "play-type");
+ const gchar *synthesis_network = play_type ? play_type : "adsr-wave-1";
+
+ self->wnet = bse_project_create_intern_synth (bse_item_get_project (BSE_ITEM (self)),
+ synthesis_network,
+ BSE_TYPE_SNET);
+
+ bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->wnet), track_uncross_wave);
+
+ if (self->sub_synth)
+ g_object_set (self->sub_synth, /* no undo */
+ "snet", self->wnet,
+ NULL);
+
+ if (strcmp (synthesis_network, "adsr-wave-1") == 0 ||
+ strcmp (synthesis_network, "plain-wave-1") == 0)
+ {
+ g_object_set (bse_container_resolve_upath (BSE_CONTAINER (self->wnet), "wave-osc"), /* no undo */
+ "wave", wave,
+ NULL);
+ set_amp_master_volume (self->wnet, "amplifier", wave->xinfos);
+ set_adsr_params (self->wnet, "adsr", wave->xinfos);
+ }
+ else if (strcmp (synthesis_network, "adsr-wave-2") == 0 ||
+ strcmp (synthesis_network, "plain-wave-2") == 0)
+ {
+ g_object_set (bse_container_resolve_upath (BSE_CONTAINER (self->wnet), "wave-osc-left"), /* no undo */
+ "wave", wave,
+ NULL);
+ g_object_set (bse_container_resolve_upath (BSE_CONTAINER (self->wnet), "wave-osc-right"), /* no undo
*/
+ "wave", wave,
+ NULL);
+ set_amp_master_volume (self->wnet, "amplifier-left", wave->xinfos);
+ set_amp_master_volume (self->wnet, "amplifier-right", wave->xinfos);
+ set_adsr_params (self->wnet, "adsr", wave->xinfos);
+ }
+ else if (strcmp (synthesis_network, "gus-patch") == 0)
+ {
+ g_object_set (bse_container_resolve_upath (BSE_CONTAINER (self->wnet), "wave-osc"), /* no undo */
+ "wave", wave,
+ NULL);
+ g_object_set (bse_container_resolve_upath (BSE_CONTAINER (self->wnet), "gus-patch-envelope"), /* no
undo */
+ "wave", wave,
+ NULL);
+ }
+ else
+ {
+ g_warning ("track: waves with the play-type \"%s\" are not supported by this version of beast\n",
+ synthesis_network);
+ }
+
+ }
+
+ 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));
+
+ if (self->sub_synth)
+ g_object_set (self->sub_synth, /* no undo */
+ "snet", NULL,
+ NULL);
+ if (self->snet)
+ {
+ bse_object_unproxy_notifies (self->snet, self, "changed");
+ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (self->snet), track_uncross_snet);
+ self->snet = NULL;
+ g_object_notify ((GObject*) self, "snet");
+ }
+ if (self->wave)
+ {
+ bse_object_unproxy_notifies (self->wave, self, "changed");
+ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (self->wave), track_uncross_wave);
+ self->wave = NULL;
+ g_object_notify ((GObject*) self, "wave");
+ }
+ if (self->wnet)
+ {
+ BseSNet *wnet = self->wnet;
+ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (self->wnet), track_uncross_wave);
+ self->wnet = NULL;
+ bse_container_remove_item (BSE_CONTAINER (bse_item_get_project (BSE_ITEM (self))), BSE_ITEM (wnet));
+ }
++ if (self->sound_font_preset)
++ {
++ bse_object_unproxy_notifies (self->sound_font_preset, self, "changed");
++ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (self->sound_font_preset),
track_uncross_sound_font_preset);
++ self->sound_font_preset = NULL;
++ g_object_notify (self, "sound_font_preset");
++ }
++ if (self->sound_font_net)
++ {
++ BseSNet *sound_font_net = self->sound_font_net;
++ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (self->sound_font_net),
track_uncross_sound_font_preset);
++ self->sound_font_net = NULL;
++ bse_container_remove_item (BSE_CONTAINER (bse_item_get_project (BSE_ITEM (self))), BSE_ITEM
(sound_font_net));
++ }
+ }
+
+ static void
+ bse_track_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+ {
+ BseTrack *self = BSE_TRACK (object);
+
+ switch (param_id)
+ {
+ guint i;
+ case PROP_MUTED:
+ BSE_SEQUENCER_LOCK ();
+ self->muted_SL = sfi_value_get_bool (value);
+ BSE_SEQUENCER_UNLOCK ();
+ break;
+ case PROP_SNET:
+ if (!self->sub_synth || !BSE_SOURCE_PREPARED (self))
+ {
+ BseSNet *snet = (BseSNet*) bse_value_get_object (value);
+ if (snet || self->snet)
+ {
- clear_snet_and_wave (self);
++ clear_snet_and_wave_and_sfpreset (self);
+ self->snet = snet;
+ if (self->snet)
+ {
+ bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->snet), track_uncross_snet);
+ bse_object_proxy_notifies (self->snet, self, "changed");
+ }
+ if (self->sub_synth)
+ g_object_set (self->sub_synth, /* no undo */
+ "snet", self->snet,
+ NULL);
+ }
+ }
+ break;
+ case PROP_WAVE:
+ if (!self->sub_synth || !BSE_SOURCE_PREPARED (self->sub_synth))
+ {
+ BseWave *wave = (BseWave*) bse_value_get_object (value);
+ if (wave || self->wave)
+ {
- clear_snet_and_wave (self);
++ clear_snet_and_wave_and_sfpreset (self);
+
+ self->wave = wave;
+ if (self->wave)
+ {
+ create_wnet (self, wave);
+ bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->wave), track_uncross_wave);
+ bse_object_proxy_notifies (self->wave, self, "changed");
+ }
+ }
+ }
+ break;
++ case PROP_SOUND_FONT_PRESET:
++ if (!self->sub_synth || !BSE_SOURCE_PREPARED (self->sub_synth))
++ {
++ BseSoundFontPreset *sound_font_preset = bse_value_get_object (value);
++ if (sound_font_preset || self->sound_font_preset)
++ {
++ clear_snet_and_wave_and_sfpreset (self);
++
++ self->sound_font_preset = sound_font_preset;
++ if (self->sound_font_preset)
++ {
++ create_sound_font_net (self, sound_font_preset);
++ bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->sound_font_preset),
track_uncross_sound_font_preset);
++ bse_object_proxy_notifies (self->sound_font_preset, self, "changed");
++ }
++ }
++ }
++ break;
+ case PROP_N_VOICES:
+ if (!self->postprocess || !BSE_SOURCE_PREPARED (self->postprocess))
+ self->max_voices = sfi_value_get_int (value);
+ break;
+ case PROP_MIDI_CHANNEL:
+ i = sfi_value_get_int (value);
+ if (i != self->midi_channel_SL && !BSE_SOURCE_PREPARED (self))
+ {
+ self->midi_channel_SL = i > 0 ? i : self->channel_id;
+ bse_track_update_midi_channel (self);
+ }
+ break;
+ case PROP_PNET:
+ if (!self->postprocess || !BSE_SOURCE_PREPARED (self))
+ {
+ if (self->pnet)
+ {
+ bse_object_unproxy_notifies (self->pnet, self, "notify::pnet");
+ bse_item_cross_unlink (BSE_ITEM (self), BSE_ITEM (self->pnet), track_uncross_pnet);
+ self->pnet = NULL;
+ }
+ self->pnet = (BseSNet*) bse_value_get_object (value);
+ if (self->pnet)
+ {
+ bse_item_cross_link (BSE_ITEM (self), BSE_ITEM (self->pnet), track_uncross_pnet);
+ bse_object_proxy_notifies (self->pnet, self, "notify::pnet");
+ }
+ if (self->postprocess)
+ g_object_set (self->postprocess, /* no undo */
+ "snet", self->pnet,
+ NULL);
+ }
+ break;
+ case PROP_OUTPUTS:
+ bse_bus_or_track_set_outputs (BSE_ITEM (self), (BseItemSeq*) g_value_get_boxed (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
+ break;
+ }
+ }
+
+ static void
+ bse_track_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+ {
+ BseTrack *self = BSE_TRACK (object);
+
+ switch (param_id)
+ {
+ BseItemSeq *iseq;
+ SfiRing *ring;
+ case PROP_MUTED:
+ sfi_value_set_bool (value, self->muted_SL);
+ break;
+ case PROP_SNET:
+ bse_value_set_object (value, self->snet);
+ break;
+ case PROP_PNET:
+ bse_value_set_object (value, self->pnet);
+ break;
+ case PROP_OUTPUTS:
+ iseq = bse_item_seq_new();
+ for (ring = self->bus_outputs; ring; ring = sfi_ring_walk (ring, self->bus_outputs))
+ bse_item_seq_append (iseq, (BseItem*) ring->data);
+ g_value_take_boxed (value, iseq);
+ break;
+ case PROP_WAVE:
+ bse_value_set_object (value, self->wave);
+ break;
++ case PROP_SOUND_FONT_PRESET:
++ bse_value_set_object (value, self->sound_font_preset);
++ break;
+ case PROP_N_VOICES:
+ sfi_value_set_int (value, self->max_voices);
+ break;
+ case PROP_MIDI_CHANNEL:
+ sfi_value_set_int (value, self->midi_channel_SL <= BSE_MIDI_MAX_CHANNELS ? self->midi_channel_SL : 0);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (self, param_id, pspec);
+ break;
+ }
+ }
+
+ guint
+ bse_track_insert_part (BseTrack *self,
+ guint tick,
+ BsePart *part)
+ {
+ BseTrackEntry *entry;
+
+ g_return_val_if_fail (BSE_IS_TRACK (self), BSE_ERROR_INTERNAL);
+ g_return_val_if_fail (BSE_IS_PART (part), BSE_ERROR_INTERNAL);
+
+ entry = track_lookup_entry (self, tick);
+ if (entry && entry->tick == tick)
+ return 0;
+ else
+ {
+ gint i = entry ? entry - self->entries_SL : 0;
+ entry = track_add_entry (self, entry ? i + 1 : 0, tick, part);
+ }
+ bse_part_links_changed (part);
+ g_signal_emit (self, signal_changed, 0);
+ return entry ? entry->id : 0;
+ }
+
+ void
+ bse_track_remove_tick (BseTrack *self,
+ guint tick)
+ {
+ BseTrackEntry *entry;
+
+ g_return_if_fail (BSE_IS_TRACK (self));
+
+ entry = track_lookup_entry (self, tick);
+ if (entry && entry->tick == tick)
+ {
+ BsePart *part = entry->part;
+ track_delete_entry (self, entry - self->entries_SL);
+ bse_part_links_changed (part);
+ g_signal_emit (self, signal_changed, 0);
+ }
+ }
+
+ static BseTrackPartSeq*
+ bse_track_list_parts_intern (BseTrack *self,
+ BsePart *part)
+ {
+ BseItem *item = BSE_ITEM (self);
+ BseSong *song = NULL;
+ if (BSE_IS_SONG (item->parent))
+ song = BSE_SONG (item->parent);
+ BseSongTiming timing;
+ bse_song_timing_get_default (&timing);
+ BseTrackPartSeq *tps = bse_track_part_seq_new ();
+ gint i;
+ for (i = 0; i < self->n_entries_SL; i++)
+ {
+ BseTrackEntry *entry = self->entries_SL + i;
+ if (entry->part && (entry->part == part || !part))
+ {
+ BseTrackPart tp = { 0, };
+ tp.tick = entry->tick;
+ tp.part = entry->part;
+ if (song)
+ bse_song_get_timing (song, tp.tick, &timing);
+ tp.duration = MAX (timing.tpt, entry->part->last_tick_SL);
+ if (i + 1 < self->n_entries_SL)
+ tp.duration = MIN (tp.duration, entry[1].tick - entry->tick);
+ bse_track_part_seq_append (tps, &tp);
+ }
+ }
+ return tps;
+ }
+
+ BseTrackPartSeq*
+ bse_track_list_parts (BseTrack *self)
+ {
+ g_return_val_if_fail (BSE_IS_TRACK (self), NULL);
+ return bse_track_list_parts_intern (self, NULL);
+ }
+
+ BseTrackPartSeq*
+ bse_track_list_part (BseTrack *self,
+ BsePart *part)
+ {
+ g_return_val_if_fail (BSE_IS_TRACK (self), NULL);
+ g_return_val_if_fail (BSE_IS_PART (part), NULL);
+ return bse_track_list_parts_intern (self, part);
+ }
+
+ gboolean
+ bse_track_find_part (BseTrack *self,
+ BsePart *part,
+ guint *start_p)
+ {
+ guint i;
+
+ g_return_val_if_fail (BSE_IS_TRACK (self), FALSE);
+ g_return_val_if_fail (BSE_IS_PART (part), FALSE);
+
+ for (i = 0; i < self->n_entries_SL; i++)
+ if (self->entries_SL[i].part == part)
+ {
+ if (start_p)
+ *start_p = self->entries_SL[i].tick;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ BseTrackEntry*
+ bse_track_lookup_tick (BseTrack *self,
+ guint tick)
+ {
+ BseTrackEntry *entry;
+
+ g_return_val_if_fail (BSE_IS_TRACK (self), NULL);
+
+ entry = track_lookup_entry (self, tick);
+ if (entry && entry->tick == tick)
+ return entry;
+ return NULL;
+ }
+
+ BseTrackEntry*
+ bse_track_find_link (BseTrack *self,
+ guint id)
+ {
+ guint i;
+
+ g_return_val_if_fail (BSE_IS_TRACK (self), NULL);
+
+ for (i = 0; i < self->n_entries_SL; i++)
+ if (self->entries_SL[i].id == id)
+ return self->entries_SL + i;
+ return NULL;
+ }
+
+ BsePart*
+ bse_track_get_part_SL (BseTrack *self,
+ guint tick,
+ guint *start,
+ guint *next)
+ {
+ BseTrackEntry *entry;
+
+ g_return_val_if_fail (BSE_IS_TRACK (self), NULL);
+
+ /* we return the nearest part with start <= tick and
+ * set *next to the start of the following part if any
+ */
+
+ entry = track_lookup_entry (self, tick);
+ if (entry)
+ {
+ guint i = entry - self->entries_SL;
+ if (i + 1 < self->n_entries_SL)
+ *next = self->entries_SL[i + 1].tick;
+ else
+ *next = 0; /* no next part */
+ *start = entry->tick;
+ return entry->part;
+ }
+ *start = 0;
+ *next = self->n_entries_SL ? self->entries_SL[0].tick : 0;
+ return NULL;
+ }
+
+ void
+ bse_track_add_modules (BseTrack *self,
+ BseContainer *container,
+ BseMidiReceiver *midi_receiver)
+ {
+ g_return_if_fail (BSE_IS_TRACK (self));
+ g_return_if_fail (BSE_IS_CONTAINER (container));
+ g_return_if_fail (self->sub_synth == NULL);
+ g_return_if_fail (midi_receiver != NULL);
+
+ /* midi voice input */
+ self->voice_input = (BseSource*) bse_container_new_child (container, BSE_TYPE_MIDI_VOICE_INPUT, NULL);
+ bse_item_set_internal (self->voice_input, TRUE);
+
+ /* sub synth */
+ self->sub_synth = (BseSource*) bse_container_new_child_bname (container, BSE_TYPE_SUB_SYNTH,
"Track-Instrument",
+ "in_port_1", "frequency",
+ "in_port_2", "gate",
+ "in_port_3", "velocity",
+ "in_port_4", "aftertouch",
+ "out_port_1", "left-audio",
+ "out_port_2", "right-audio",
+ "out_port_3", "unused",
+ "out_port_4", "synth-done",
+ "snet", self->snet,
+ NULL);
+ bse_item_set_internal (self->sub_synth, TRUE);
+
+ /* voice input <-> sub-synth */
+ bse_source_must_set_input (self->sub_synth, 0,
+ self->voice_input, BSE_MIDI_VOICE_INPUT_OCHANNEL_FREQUENCY);
+ bse_source_must_set_input (self->sub_synth, 1,
+ self->voice_input, BSE_MIDI_VOICE_INPUT_OCHANNEL_GATE);
+ bse_source_must_set_input (self->sub_synth, 2,
+ self->voice_input, BSE_MIDI_VOICE_INPUT_OCHANNEL_VELOCITY);
+ bse_source_must_set_input (self->sub_synth, 3,
+ self->voice_input, BSE_MIDI_VOICE_INPUT_OCHANNEL_AFTERTOUCH);
+
+ /* midi voice switch */
+ self->voice_switch = (BseSource*) bse_container_new_child (container, BSE_TYPE_MIDI_VOICE_SWITCH, NULL);
+ bse_item_set_internal (self->voice_switch, TRUE);
+ bse_midi_voice_input_set_voice_switch (BSE_MIDI_VOICE_INPUT (self->voice_input), BSE_MIDI_VOICE_SWITCH
(self->voice_switch));
+
+ /* sub-synth <-> voice switch */
+ bse_source_must_set_input (self->voice_switch, BSE_MIDI_VOICE_SWITCH_ICHANNEL_LEFT,
+ self->sub_synth, 0);
+ bse_source_must_set_input (self->voice_switch, BSE_MIDI_VOICE_SWITCH_ICHANNEL_RIGHT,
+ self->sub_synth, 1);
+ bse_source_must_set_input (self->voice_switch, BSE_MIDI_VOICE_SWITCH_ICHANNEL_DISCONNECT,
+ self->sub_synth, 3);
+
+ /* midi voice switch <-> context merger */
+ bse_source_must_set_input (BSE_SOURCE (self), 0,
+ self->voice_switch, BSE_MIDI_VOICE_SWITCH_OCHANNEL_LEFT);
+ bse_source_must_set_input (BSE_SOURCE (self), 1,
+ self->voice_switch, BSE_MIDI_VOICE_SWITCH_OCHANNEL_RIGHT);
+
+ /* postprocess */
+ self->postprocess = (BseSource*) bse_container_new_child_bname (container, BSE_TYPE_SUB_SYNTH,
"Track-Postprocess", NULL);
+ bse_item_set_internal (self->postprocess, TRUE);
+ bse_sub_synth_set_null_shortcut (BSE_SUB_SYNTH (self->postprocess), TRUE);
+
+ /* context merger <-> postprocess */
+ bse_source_must_set_input (self->postprocess, 0, BSE_SOURCE (self), 0);
+ bse_source_must_set_input (self->postprocess, 1, BSE_SOURCE (self), 1);
+
+ /* propagate midi channel to modules */
+ bse_track_update_midi_channel (self);
+ }
+
+ BseSource*
+ bse_track_get_output (BseTrack *self)
+ {
+ return self->postprocess;
+ }
+
+ guint
+ bse_track_get_last_tick (BseTrack *self)
+ {
+ int last_tick = 0;
+
+ /* find last part */
+ BsePart *part = NULL;
+ guint i, offset = 0;
+ for (i = 0; i < self->n_entries_SL; i++)
+ if (self->entries_SL[i].part)
+ {
+ part = self->entries_SL[i].part;
+ offset = self->entries_SL[i].tick;
+ }
+ if (part)
+ {
+ BseItem *item = BSE_ITEM (self);
+ BseSongTiming timing;
+ g_object_get (part, "last-tick", &last_tick, NULL);
+ if (BSE_IS_SONG (item->parent))
+ bse_song_get_timing (BSE_SONG (item->parent), offset, &timing);
+ else
+ bse_song_timing_get_default (&timing);
+ last_tick = MAX (last_tick, timing.tpt); /* MAX duration with tact size, see bse_track_list_parts()
*/
+ last_tick += offset;
+ }
+ else
+ last_tick += 1; /* always return one after */
+
+ return last_tick;
+ }
+
+ static void
+ bse_track_update_midi_channel (BseTrack *self)
+ {
+ if (self->voice_switch)
- {
- bse_sub_synth_set_midi_channel (BSE_SUB_SYNTH (self->sub_synth), self->midi_channel_SL);
- bse_sub_synth_set_midi_channel (BSE_SUB_SYNTH (self->postprocess), self->midi_channel_SL);
- bse_midi_voice_switch_set_midi_channel (BSE_MIDI_VOICE_SWITCH (self->voice_switch),
self->midi_channel_SL);
- }
++ {
++ bse_sub_synth_set_midi_channel (BSE_SUB_SYNTH (self->sub_synth), self->midi_channel_SL);
++ bse_sub_synth_set_midi_channel (BSE_SUB_SYNTH (self->postprocess), self->midi_channel_SL);
++ bse_midi_voice_switch_set_midi_channel (BSE_MIDI_VOICE_SWITCH (self->voice_switch),
self->midi_channel_SL);
++ }
+ }
+
+ static void
+ bse_track_context_create (BseSource *source,
+ guint context_handle,
+ BseTrans *trans)
+ {
+ BseTrack *self = BSE_TRACK (source);
+ BseMidiContext mcontext = bse_snet_get_midi_context (bse_item_get_snet (BSE_ITEM (self)), context_handle);
+ if (self->snet || self->wave)
+ bse_midi_receiver_channel_enable_poly (mcontext.midi_receiver, self->midi_channel_SL);
+ /* chain parent class' handler */
+ BSE_SOURCE_CLASS (parent_class)->context_create (source, context_handle, trans);
+ }
+
+ static void
+ bse_track_context_dismiss (BseSource *source,
+ guint context_handle,
+ BseTrans *trans)
+ {
+ BseTrack *self = BSE_TRACK (source);
+ BseMidiContext mcontext = bse_snet_get_midi_context (bse_item_get_snet (BSE_ITEM (self)), context_handle);
+ if (self->snet || self->wave)
+ bse_midi_receiver_channel_disable_poly (mcontext.midi_receiver, self->midi_channel_SL);
+ /* chain parent class' handler */
+ BSE_SOURCE_CLASS (parent_class)->context_dismiss (source, context_handle, trans);
+ }
+
+ 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);
+
+ bse_container_remove_item (container, BSE_ITEM (self->sub_synth));
+ self->sub_synth = NULL;
+ bse_container_remove_item (container, BSE_ITEM (self->voice_input));
+ self->voice_input = NULL;
+ bse_container_remove_item (container, BSE_ITEM (self->voice_switch));
+ self->voice_switch = NULL;
+ bse_container_remove_item (container, BSE_ITEM (self->postprocess));
+ self->postprocess = NULL;
+ }
+
+ void
+ bse_track_clone_voices (BseTrack *self,
- BseSNet *snet,
- guint context,
++ BseSNet *snet,
++ guint context,
+ BseMidiContext mcontext,
- BseTrans *trans)
++ BseTrans *trans)
+ {
+ guint i;
+
+ g_return_if_fail (BSE_IS_TRACK (self));
+ g_return_if_fail (BSE_IS_SNET (snet));
+ g_return_if_fail (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
+ bse_track_store_private (BseObject *object,
+ BseStorage *storage)
+ {
+ BseTrack *self = BSE_TRACK (object);
+ BseItem *item = BSE_ITEM (self);
+ guint i;
+
+ /* chain parent class' handler */
+ if (BSE_OBJECT_CLASS (parent_class)->store_private)
+ BSE_OBJECT_CLASS (parent_class)->store_private (object, storage);
+
+ for (i = 0; i < self->n_entries_SL; i++)
+ {
+ BseTrackEntry *e = self->entries_SL + i;
+ if (e->part)
+ {
+ bse_storage_break (storage);
+ bse_storage_printf (storage, "(insert-part %u ",
+ e->tick);
+ bse_storage_put_item_link (storage, item, BSE_ITEM (e->part));
+ bse_storage_putc (storage, ')');
+ }
+ }
+ }
+
+ static void
+ part_link_resolved (gpointer data,
+ BseStorage *storage,
+ BseItem *from_item,
+ BseItem *to_item,
+ const gchar *error)
+ {
+ BseTrack *self = BSE_TRACK (from_item);
+
+ if (error)
+ bse_storage_warn (storage, "%s", error);
+ else if (!BSE_IS_PART (to_item))
+ bse_storage_warn (storage, "skipping invalid part reference: %s", bse_object_debug_name (to_item));
+ else if (to_item->parent != from_item->parent)
+ bse_storage_warn (storage, "skipping out-of-branch part reference: %s", bse_object_debug_name
(to_item));
+ else
+ {
+ guint tick = GPOINTER_TO_UINT (data);
+ if (bse_track_insert_part (self, tick, BSE_PART (to_item)) < 1)
+ bse_storage_warn (storage, "failed to insert part reference to %s",
+ bse_object_debug_name (to_item));
+ }
+ }
+
+ static GTokenType
+ bse_track_restore_private (BseObject *object,
+ BseStorage *storage,
+ GScanner *scanner)
+ {
+ BseTrack *self = BSE_TRACK (object);
+
+ if (g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER &&
+ bse_string_equals ("insert-part", scanner->next_value.v_identifier))
+ {
+ GTokenType token;
+ guint tick;
+
+ g_scanner_get_next_token (scanner); /* eat quark */
+
+ parse_or_return (scanner, G_TOKEN_INT);
+ tick = scanner->value.v_int64;
+ token = bse_storage_parse_item_link (storage, BSE_ITEM (self), part_link_resolved, GUINT_TO_POINTER
(tick));
+ if (token != G_TOKEN_NONE)
+ return token;
+ parse_or_return (scanner, ')');
+ return G_TOKEN_NONE;
+ }
+ else /* chain parent class' handler */
+ return BSE_OBJECT_CLASS (parent_class)->restore_private (object, storage, scanner);
+ }
+
+ static void
+ bse_track_class_init (BseTrackClass *klass)
+ {
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ BseObjectClass *object_class = BSE_OBJECT_CLASS (klass);
+ BseItemClass *item_class = BSE_ITEM_CLASS (klass);
+ BseSourceClass *source_class = BSE_SOURCE_CLASS (klass);
+
+ parent_class = (GTypeClass*) g_type_class_peek_parent (klass);
+
+ gobject_class->set_property = bse_track_set_property;
+ gobject_class->get_property = bse_track_get_property;
+ gobject_class->dispose = bse_track_dispose;
+ gobject_class->finalize = bse_track_finalize;
+
+ object_class->store_private = bse_track_store_private;
+ object_class->restore_private = bse_track_restore_private;
+
+ item_class->get_candidates = bse_track_get_candidates;
+
+ source_class->context_create = bse_track_context_create;
+ source_class->context_dismiss = bse_track_context_dismiss;
+
+ bse_source_class_inherit_channels (BSE_SOURCE_CLASS (klass));
+
+ bse_object_class_add_param (object_class, _("Adjustments"),
+ PROP_MUTED,
+ sfi_pspec_bool ("muted", _("Muted"), NULL,
+ FALSE, SFI_PARAM_STANDARD ":skip-default"));
+ bse_object_class_add_param (object_class, _("Synth Input"),
+ PROP_SNET,
+ bse_param_spec_object ("snet", _("Synthesizer"), _("Synthesis network to be
used as instrument"),
+ BSE_TYPE_CSYNTH,
+ SFI_PARAM_STANDARD ":unprepared"));
+ bse_object_class_add_param (object_class, _("Synth Input"),
+ PROP_WAVE,
+ bse_param_spec_object ("wave", _("Wave"), _("Wave to be used as instrument"),
+ BSE_TYPE_WAVE,
+ SFI_PARAM_STANDARD ":unprepared"));
+ bse_object_class_add_param (object_class, _("Synth Input"),
++ PROP_SOUND_FONT_PRESET,
++ bse_param_spec_object (("sound_font_preset"), _("Sound Font Preset"),
++ _("Sound font preset to be used as instrument"),
++ BSE_TYPE_SOUND_FONT_PRESET,
++ SFI_PARAM_STANDARD ":unprepared"));
++ bse_object_class_add_param (object_class, _("Synth Input"),
+ PROP_N_VOICES,
+ sfi_pspec_int ("n_voices", _("Max Voices"), _("Maximum number of voices for
simultaneous playback"),
+ 16, 1, 256, 1,
+ SFI_PARAM_GUI SFI_PARAM_STORAGE ":scale:unprepared"));
+ bse_object_class_add_param (object_class, _("MIDI Instrument"),
+ PROP_MIDI_CHANNEL,
+ sfi_pspec_int ("midi_channel", _("MIDI Channel"),
+ _("Midi channel assigned to this track, 0 uses internal
per-track channel"),
+ 0, 0, BSE_MIDI_MAX_CHANNELS, 1,
+ SFI_PARAM_GUI SFI_PARAM_STORAGE
":scale:skip-default:unprepared"));
+ bse_object_class_add_param (object_class, _("MIDI Instrument"),
+ PROP_PNET,
+ bse_param_spec_object ("pnet", _("Postprocessor"), _("Synthesis network to be
used as postprocessor"),
+ BSE_TYPE_CSYNTH, SFI_PARAM_STANDARD ":unprepared"));
+ bse_object_class_add_param (object_class, _("Signal Outputs"),
+ PROP_OUTPUTS,
+ bse_param_spec_boxed ("outputs", _("Output Signals"),
+ _("Mixer busses used as output for this track"),
+ BSE_TYPE_ITEM_SEQ, SFI_PARAM_GUI ":item-sequence"));
+ signal_changed = bse_object_class_add_asignal (object_class, "changed", G_TYPE_NONE, 0);
+ }
diff --cc bse/bsetrack.hh
index 0000000,83a06a7..deb50df
mode 000000,100644..100644
--- a/bse/bsetrack.hh
+++ b/bse/bsetrack.hh
@@@ -1,0 -1,83 +1,88 @@@
+ // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
+ #ifndef __BSE_TRACK_H__
+ #define __BSE_TRACK_H__
+
+ #include <bse/bseitem.hh>
+ #include <bse/bsesnet.hh>
+ #include <bse/bsecontextmerger.hh>
+
+ G_BEGIN_DECLS
+
+ /* --- BSE type macros --- */
+ #define BSE_TYPE_TRACK (BSE_TYPE_ID (BseTrack))
+ #define BSE_TRACK(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), BSE_TYPE_TRACK, BseTrack))
+ #define BSE_TRACK_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), BSE_TYPE_TRACK, BseTrackClass))
+ #define BSE_IS_TRACK(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), BSE_TYPE_TRACK))
+ #define BSE_IS_TRACK_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), BSE_TYPE_TRACK))
+ #define BSE_TRACK_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), BSE_TYPE_TRACK, BseTrackClass))
+
+ struct BseTrackEntry {
+ guint tick;
+ guint id;
+ BsePart *part;
+ };
+ struct BseTrack : BseContextMerger {
+ guint channel_id;
+ guint max_voices;
+ BseSNet *snet;
+ BseSNet *pnet;
+ /* wave synthesis */
+ BseWave *wave;
+ BseSNet *wnet;
++
++ /* sound font synthesis */
++ BseSoundFontPreset *sound_font_preset;
++ BseSNet *sound_font_net;
++
+ /* playback intergration */
+ BseSource *sub_synth;
+ BseSource *voice_input;
+ BseSource *voice_switch;
+ BseSource *postprocess;
+ SfiRing *bus_outputs; /* maintained by bsebus.[hc] */
+ /* fields protected by sequencer mutex */
+ guint n_entries_SL : 30;
+ guint muted_SL : 1;
+ BseTrackEntry *entries_SL;
+ guint midi_channel_SL;
+ gboolean track_done_SL;
+ };
+ struct BseTrackClass : BseContextMergerClass
+ {};
+
+ /* --- prototypes -- */
+ void bse_track_add_modules (BseTrack *self,
+ BseContainer *container,
+ BseMidiReceiver *midi_receiver);
+ void bse_track_remove_modules (BseTrack *self,
+ BseContainer *container);
+ void bse_track_clone_voices (BseTrack *self,
+ BseSNet *snet,
+ guint context,
+ BseMidiContext mcontext,
+ BseTrans *trans);
+ BseSource* bse_track_get_output (BseTrack *self);
+ guint bse_track_get_last_tick(BseTrack *self);
+ guint bse_track_insert_part (BseTrack *self,
+ guint tick,
+ BsePart *part);
+ void bse_track_remove_tick (BseTrack *self,
+ guint tick);
+ BseTrackPartSeq* bse_track_list_parts (BseTrack *self);
+ BseTrackPartSeq* bse_track_list_part (BseTrack *self,
+ BsePart *part);
+ gboolean bse_track_find_part (BseTrack *self,
+ BsePart *part,
+ guint *start_p);
+ BseTrackEntry* bse_track_lookup_tick (BseTrack *self,
+ guint tick);
+ BseTrackEntry* bse_track_find_link (BseTrack *self,
+ guint id);
+ BsePart* bse_track_get_part_SL (BseTrack *self,
+ guint tick,
+ guint *start,
+ guint *next);
+
+ G_END_DECLS
+
+ #endif /* __BSE_TRACK_H__ */
diff --cc configure.ac
index 0000000,a7d9f28..1ae3882
mode 000000,100644..100644
--- a/configure.ac
+++ b/configure.ac
@@@ -1,0 -1,764 +1,769 @@@
+ # Licensed GNU LGPL v2 or later: http://www.gnu.org/licenses/lgpl.html
+
+ # include various m4 macros
+ m4_include(acbeast.m4)dnl # include special macros
+ m4_include(ld-symbolic.m4)dnl # include special macros
+ m4_include(autotools/glib-gettext.m4)
+
+
+ #
+ # Configure script for BEAST/BSE
+ #
+ AC_PREREQ(2.57)
+ # VERSION: MAJOR.MINOR.MICRO-RC:
+ # * MAJOR, MINOR: increment on ABI/API changes
+ # * MICRO: increment when ABI compatible, development versions are odd
+ # * RC: release candidate, may be rc[0-9]+ or empty
+ AC_INIT([beast], [0.9.1]) # defines PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_STRING
+ AC_CONFIG_SRCDIR([bse/bseconfig.h.in])
+ AC_CONFIG_AUX_DIR([autotools])
+ AC_CONFIG_MACRO_DIR([autotools])
+ AC_CANONICAL_TARGET # architecture information
+ AM_INIT_AUTOMAKE(tar-pax no-define -Wno-portability) # don't define PACKAGE and VERSION
+ AM_CONFIG_HEADER(configure.h)
+ # version handling
+ BST_VERSION="$PACKAGE_VERSION"
+ [BST_MAJOR_VERSION=`echo $PACKAGE_VERSION | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\(.*\)/\1/'`]
+ [BST_MINOR_VERSION=`echo $PACKAGE_VERSION | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\(.*\)/\2/'`]
+ [BST_MICRO_VERSION=`echo $PACKAGE_VERSION | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\(.*\)/\3/'`]
+ [BIN_VERSION=`echo $PACKAGE_VERSION | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\(.*\)/\1.\2.\3/'`]
+ case "$BST_VERSION" in
+ 0.99.*) BST_VERSION_HINT=BETA ;;
+ 0.*) BST_VERSION_HINT="ALPHA" ;;
+ *) BST_VERSION_HINT="Stable Release"
+ test `expr $BST_MICRO_VERSION \% 2` = 1 && BST_VERSION_HINT="Development Build" ;;
+ esac
+ AC_DEFINE_UNQUOTED(BST_VERSION, "$BST_VERSION", [BEAST Version])
+ AC_DEFINE_UNQUOTED(BIN_VERSION, "$BIN_VERSION", [Binary Version])
+ AC_DEFINE_UNQUOTED(BST_VERSION_HINT, "$BST_VERSION_HINT", [Version classification])
+ AC_SUBST(BST_VERSION)
+ AC_SUBST(BST_MAJOR_VERSION)
+ AC_SUBST(BST_MINOR_VERSION)
+ AC_SUBST(BST_MICRO_VERSION)
+ AC_SUBST(BIN_VERSION)
+
+ # compute libtool versions
+ LT_RELEASE=$BST_MAJOR_VERSION.$BST_MINOR_VERSION
+ LT_CURRENT=$BST_MICRO_VERSION
+ LT_REVISION=0
+ LT_AGE=$BST_MICRO_VERSION
+ AC_SUBST(LT_RELEASE)
+ AC_SUBST(LT_CURRENT)
+ AC_SUBST(LT_REVISION)
+ AC_SUBST(LT_AGE)
+ if test 1 = $(($BST_MICRO_VERSION & 1)) ; then
+ DEFINE__FILE_DIR__='-D__FILE_DIR__=\"${abs_srcdir}\"'
+ else
+ DEFINE__FILE_DIR__='-D__FILE_DIR__=\"beast/${subdir}\"'
+ fi
+ AC_SUBST(DEFINE__FILE_DIR__)
+
+ # Build tree checks
+ AC_MSG_CHECKING([for git repository])
+ test -f "${srcdir}/.git/index" && INGIT= || INGIT='#'
+ AC_SUBST(INGIT)
+ result=$(test -z "$INGIT" && echo yes || echo no)
+ AC_MSG_RESULT($result)
+
+ dnl # AC_CANONICAL_HOST is provided by AC_CANONICAL_TARGET
+ AC_DEFINE_UNQUOTED(BST_ARCH_NAME, "$target", [Architecture Description])
+
+ # We have subdirectories.
+ AC_PROG_MAKE_SET
+ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+ # declare --enable-* args and collect ac_help strings
+ AC_ARG_ENABLE(debug, [ --enable-debug=no/minimum/yes turn on debugging,
default=yes],,enable_debug=yes)
+ AC_ARG_ENABLE(devel-mode, [ --enable-devel-mode=[no/yes] turn on development mode,
default=no],,enable_devel_mode=no)
+ AC_ARG_ENABLE(distcheck-tests, [ --enable-distcheck-tests turn on resource and time consuming
distcheck tests],,enable_distcheck_tests=no)
+
+ # set BEAST_BUILD_DEFAULTS from configure's BEAST_BUILD env
+ BEAST_BUILD_DEFAULTS="$BEAST_BUILD_DEFAULTS"
+ test "$enable_distcheck_tests" = yes && BEAST_BUILD_DEFAULTS="$BEAST_BUILD_DEFAULTS:distcheck-tests:"
+ AC_SUBST(BEAST_BUILD_DEFAULTS)
+
+ dnl # setup DEBUG defaults
+ if test "x$enable_debug" = "xyes"; then
+ DEBUG_FLAGS="-g -DG_ENABLE_DEBUG"
+ else if test "x$enable_debug" = "xno"; then
+ DEBUG_FLAGS="-DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS" # -DG_DISABLE_ASSERT
+ else
+ DEBUG_FLAGS="-DG_DISABLE_CAST_CHECKS"
+ fi fi
+ if test -z "$CFLAGS"; then
+ CFLAGS="$DEBUG_FLAGS"
+ else
+ CFLAGS="$CFLAGS $DEBUG_FLAGS"
+ fi
+ if test -z "$CXXFLAGS"; then
+ CXXFLAGS="$DEBUG_FLAGS"
+ else
+ CXXFLAGS="$CXXFLAGS $DEBUG_FLAGS"
+ fi
+
+ dnl # Foreign defaults:
+ MC_IF_VAR_EQ(enable_static, yes, , enable_static=no)
+ MC_IF_VAR_EQ(enable_shared, no, , enable_shared=yes)
+
+ # compiler, linker & libtool
+ saved_CFLAGS="$CFLAGS"
+ AC_PROG_CC
+ CFLAGS="$saved_CFLAGS" # AC_PROG_CC_G called internally consistently breaks $CFLAGS
+ saved_CXXFLAGS="$CFLAGS"
+ AC_PROG_CPP
+ CXXFLAGS="$saved_CXXFLAGS" # AC_PROG_CXX_G called internally consistently breaks $CXXFLAGS
+ AC_PROG_CXX
+ AC_PROG_CXXCPP
+ AC_PROG_LD
+ AC_LANG_CPLUSPLUS # use CXX for compilation tests
+ AC_LIB_PROG_LD
+ AC_LIB_PROG_LD_GNU
+ ACX_PROG_LD_GNU_SYMBOLIC
+ AC_SUBST([SYMBOLIC_LDFLAGS])
+ ACX_PROG_LD_GNU_DYNAMIC_LIST_CPP_NEW
+ AC_SUBST([DYNAMIC_LIST_CPP_NEW_LDFLAGS])
+ AM_PROG_LIBTOOL
+ AC_LIBTOOL_DLOPEN
+
+ # AM_LDFLAGS, optimize linker to use faster ELF symbol hashing if we have compiler and linker support
+ AC_MSG_CHECKING([whether CC and LD support gnu.hash sections])
+ if ${CC-cc} -dumpspecs | grep -q -- '--hash-style=\(both\|gnu\).*--as-needed' && \
+ ${LD-ld} --help | grep -q -- '--hash-style=.*\(both\|gnu\)' ; then
+ MC_EVAR_ADD(AM_LDFLAGS, [-Wl,--hash-style=both -Wl,--as-needed -Wl,-O1])
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ MC_EVAR_ADD(AM_LDFLAGS, -pthread)
+ MC_EVAR_ADD(AM_LDFLAGS, -lrt)
+ MC_EVAR_ADD(AM_LDFLAGS, -Wl,--no-undefined)
+ AC_SUBST(AM_LDFLAGS)
+
+ # Pick C++ dialect, needed in CXXFLAGS for compile tests
+ MC_CXX_TRY_OPTION(CXXFLAGS, -std=gnu++0x)
+
+ # AM_CFLAGS & AM_CXXFLAGS
+ MC_CXX_TRY_OPTION(AM_CXXFLAGS, -std=gnu++0x)
+ BOTHCCXXFLAGS=
+ if test "x$enable_debug" = "xyes"; then
+ MC_EVAR_ADD(BOTHCCXXFLAGS, -DG_ENABLE_DEBUG)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -g)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -ggdb3)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -fno-omit-frame-pointer)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -fverbose-asm)
+ dnl # MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Q -ftime-report -fmem-report)
+ elif test "x$enable_debug" = "xno"; then
+ MC_EVAR_ADD(BOTHCCXXFLAGS, [-DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS]) # -DG_DISABLE_ASSERT
+ else
+ : # minimum debugging
+ fi
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -fmessage-length=0)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -fdiagnostics-color=auto)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Wall)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Wdeprecated)
+ MC_CC_TRY_OPTION(AM_CFLAGS, -Wmissing-prototypes)
+ MC_CC_TRY_OPTION(AM_CFLAGS, -Wno-pointer-sign)
+ MC_CC_TRY_OPTION(AM_CFLAGS, -Wnested-externs)
+ MC_CC_TRY_OPTION(AM_CFLAGS, -fno-cond-mismatch)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Wmissing-declarations)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Wpointer-arith)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Wredundant-decls)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -Werror=format-security)
+ MC_CXX_TRY_OPTION(AM_CXXFLAGS, -Wsign-promo)
+ MC_CXX_TRY_OPTION(AM_CXXFLAGS, -Woverloaded-virtual)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -rdynamic)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -pipe)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -O2)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -ftracer)
+ MC_CC_TRY_OPTION(BOTHCCXXFLAGS, -mcx16)
+ dnl # MC_CXX_TRY_OPTION(AM_CXXFLAGS, -Wno-invalid-offsetof)
+ MC_EVAR_ADD(AM_CFLAGS, "$BOTHCCXXFLAGS")
+ MC_EVAR_ADD(AM_CXXFLAGS, "$BOTHCCXXFLAGS")
+ AC_SUBST(AM_CFLAGS)
+ AC_SUBST(AM_CXXFLAGS)
+ AC_SUBST(AM_CPPFLAGS)
+
+ # == CPU Optimizations ==
+ # MMX and SSE instruction sets have been introduced way more than a decade ago:
+ # Intel Pentium 3: CMOV MMX SSE (1999)
+ # VIA C3 Nehemiah: CMOV MMX SSE (2003)
+ # Athlon Palomino: CMOV MMX SSE 3DNow (2001)
+ MMX_SSE_FLAGS=
+ MC_CC_TRY_OPTION(MMX_SSE_FLAGS, -mmmx)
+ MC_CC_TRY_OPTION(MMX_SSE_FLAGS, -msse)
+ # Note, -mfpmath=sse can harm FPU-algorithm performance
+ # Note, -funroll-loops can harm SSE loop performance
+ #MC_CC_TRY_OPTION(MMX_SSE_FLAGS, -funroll-loops)
+ #AC_SUBST(MMX_SSE_FLAGS)
+ # Expect the target architecture to support MMX/SSE if the compiler does it.
+ MC_EVAR_ADD(AM_CFLAGS, "$MMX_SSE_FLAGS")
+ MC_EVAR_ADD(AM_CXXFLAGS, "$MMX_SSE_FLAGS")
+ # Newer vectorization instruction sets, should be optionally supported
+ # SSE >= 2, AVX
+ SSEAVX_FLAGS=
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -msse2)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -msse3)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -mssse3)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -msse4)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -msse4.1)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -msse4.2)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -msse4a)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -mavx)
+ MC_CC_TRY_OPTION(SSEAVX_FLAGS, -mavx2)
+ AC_SUBST(SSEAVX_FLAGS)
+
+ # == OPTIMIZE_FAST ==
+ # Some critical code paths should be optimized to run as fast as possible
+ OPTIMIZE_FAST=
+ MC_CC_TRY_OPTION(OPTIMIZE_FAST, -O3)
+ MC_CC_TRY_OPTION(OPTIMIZE_FAST, -ftree-vectorize)
+ MC_CC_TRY_OPTION(OPTIMIZE_FAST, -finline-functions)
+ MC_CC_TRY_OPTION(OPTIMIZE_FAST, -minline-all-stringops)
+ AC_SUBST(OPTIMIZE_FAST)
+
+ # == Bse Plugin FLAGS ==
+ # * -funroll-loops significantly boosts FPU performance
+ # * -mfpmath=sse harms FPU-algorithm performance
+ # * -funroll-loops harms SSE loop performance
+ MC_CXX_TRY_OPTION(FAST_MATH_FLAGS, -ftree-loop-ivcanon)
+ MC_CXX_TRY_OPTION(FAST_MATH_FLAGS, -ftree-loop-linear)
+ MC_CXX_TRY_OPTION(FAST_MATH_FLAGS, -ftree-loop-im)
+ MC_CXX_TRY_OPTION(FAST_MATH_FLAGS, -ffast-math)
+ MC_CXX_TRY_OPTION(FAST_MATH_FLAGS, -fivopts)
+ AC_SUBST(FAST_MATH_FLAGS)
+ MC_CXX_TRY_OPTION(FPU_FLAGS, -funroll-loops)
+ AC_SUBST(FPU_FLAGS)
+ MMX_SSE_FLAGS="$MMX_SSE_FLAGS"
+ AC_SUBST(MMX_SSE_FLAGS)
+
+ # == SSE Build Conditionals ==
+ lacking_mmx_sse=`echo "$MMX_SSE_FLAGS" | grep 'mmx.*sse' -q ; echo $?` # sh truth values: 1 (without sse)
or 0 (with sse)
+ AM_CONDITIONAL(WITH_MMX_SSE, test 0 == $lacking_mmx_sse)
+ AC_DEFINE_UNQUOTED(BSE_WITH_MMX_SSE, [(0 == $lacking_mmx_sse)], [wether MMX and SSE are supported])
+
+ # C & C++ idioms
+ AC_C_CONST
+ AC_C_INLINE
+ AC_HEADER_STDC
+
+ # Checks for programs
+ AC_PROG_INSTALL
+ AC_PROG_LN_S
+
+ # require pkg-config
+ MC_ASSERT_PROG(PKG_CONFIG, pkg-config, [pkg-config can be found at
http://www.freedesktop.org/software/pkgconfig/])
+
+ dnl #
+ dnl # Define package requirements.
+ dnl #
+ AC_DEFUN([AC_I18N_REQUIREMENTS],
+ [
+ # LINGUAS
+ ALL_LINGUAS=`cat "$srcdir/po/LINGUAS" | grep -v '^#' | xargs echo -n `
+ AC_SUBST(ALL_LINGUAS)
+ AC_SUBST([CONFIG_STATUS_DEPENDENCIES], ['$(top_srcdir)/po/LINGUAS'])
+
+ # versioned BEAST gettext domain (po/)
+ BST_GETTEXT_DOMAIN=beast-v$BIN_VERSION # version without -rcZ
+ AC_SUBST(BST_GETTEXT_DOMAIN)
+ AC_DEFINE_UNQUOTED(BST_GETTEXT_DOMAIN, "$BST_GETTEXT_DOMAIN", [Versioned BEAST gettext domain])
+ GETTEXT_PACKAGE=$BST_GETTEXT_DOMAIN
+ AC_SUBST(GETTEXT_PACKAGE)
+
+ # locale directory for all domains
+ # (AM_GLIB_DEFINE_LOCALEDIR() could do this if it would do AC_SUBST())
+ saved_prefix="$prefix" ; saved_exec_prefix="$exec_prefix"
+ test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+ test "x$exec_prefix" = xNONE && exec_prefix="$prefix"
+ if test "x$CATOBJEXT" = "x.mo" ; then
+ beastlocaledir=`eval echo "${libdir}/locale"`
+ else
+ beastlocaledir=`eval echo "${datadir}/locale"`
+ fi
+ exec_prefix="$saved_exec_prefix" ; prefix="$saved_prefix"
+ AC_SUBST(beastlocaledir)
+
+ # check for proper gettext support
+ AM_GLIB_GNU_GETTEXT([external])
+ test -z "$ac_cv_path_XGETTEXT" && {
+ AC_MSG_ERROR(["Failed to detect gettext, required for internationalization." \
+ "GNU gettext is available from: http://www.gnu.org/software/gettext/"])
+ }
+
+ # check for gettext utilities
+ AC_PATH_PROG(ICONV, iconv, iconv)
+ AC_PATH_PROG(MSGFMT, msgfmt, msgfmt)
+ AC_PATH_PROG(MSGMERGE, msgmerge, msgmerge)
+ AC_PATH_PROG(XGETTEXT, xgettext, xgettext)
+ AC_SUBST(ac_aux_dir) dnl # needed to ship various intlfix scripts
+ INTLMERGE='$(top_builddir)/$(ac_aux_dir)/intltool-merge'
+ AC_SUBST(INTLMERGE) dnl # AC_PATH_PROG(INTLMERGE, intltool-merge, intltool-merge)
+ ])
+ AC_DEFUN([AC_SFI_REQUIREMENTS],
+ [
+ dnl # check for GLib libs
+ PKG_CHECK_MODULES(GLIB_GOMT, glib-2.0 >= 2.32.3 gobject-2.0 gmodule-no-export-2.0 gthread-2.0)
+ AC_SUBST(GLIB_GOMT_CFLAGS)
+ AC_SUBST(GLIB_GOMT_LIBS)
+ SFI_CPPFLAGS="$GLIB_GOMT_CFLAGS"
+ SFI_LIBS="$GLIB_GOMT_LIBS"
+ AC_SUBST(SFI_CPPFLAGS)
+ AC_SUBST(SFI_LIBS)
+
+ AC_CHECK_FUNCS(getpwnam_r getpwnam)
+ AC_CHECK_FUNCS(timegm)
+
+ dnl # --- SFI directories ---
+ sfidlstdincdir=${includedir}
+ AC_SUBST(sfidlstdincdir)
+ ])
+ AC_DEFUN([AC_BSE_REQUIREMENTS],
+ [
+ dnl # require Rapicorn
+ PKG_CHECK_MODULES(RAPICORN, rapicorn1410 >= 14.10.0)
+ MC_ASSERT_PROG(AIDACC, aidacc-1410, [aidacc gets shipped with Rapicorn])
+
+ dnl # --- Ogg/Vorbis check ---
+ PKG_CHECK_MODULES(OV, ogg >= 1.2.2 vorbis >= 1.3.2 vorbisfile >= 1.3.2 vorbisenc >= 1.3.2)
+
+ dnl # --- FLAC check ---
+ PKG_CHECK_MODULES(FLAC, flac)
+
+ dnl # old FLAC versions use "-I/usr/.../include/FLAC" as pkg-config --cflags
+ dnl # new FLAC versions use "-I/usr/.../include" as pkg-config --cflags
+ dnl #
+ dnl # to support both, we strip /FLAC from FLAC_CFLAGS and use #include <FLAC/foo.h>
+ FLAC_CFLAGS=`echo $FLAC_CLFAGS | $SED "s/FLAC$//"`
+
+ dnl # --- libmad MPEG decoder check ---
+ dnl # libmad doesn't come with a mad.pc file (just its debian package)
+ dnl # PKG_CHECK_MODULES(MAD, mad >= 0.14.2,
+ dnl # BSE_HAVE_LIBMAD=1
+ dnl # ,
+ dnl # BSE_HAVE_LIBMAD=0
+ dnl # AC_MSG_WARN([failed to detect libmad (MPEG I-III audio decoder) or headers])
+ dnl # )
+ MAD_LIBS=
+ mad_tests=0
+ AC_CHECK_LIB(mad, mad_stream_errorstr,
+ [AC_CHECK_HEADER(mad.h, mad_tests=`expr $mad_tests + 1`)]
+ ,
+ mad_tests=0, -lm)
+ if test $mad_tests = 1 ; then
+ BSE_HAVE_LIBMAD=1
+ MAD_LIBS="-lmad -lm"
+ else
+ AC_MSG_WARN([failed to detect libmad (MPEG I-III audio decoder) or headers])
+ BSE_HAVE_LIBMAD=0
+ fi
+ AC_DEFINE_UNQUOTED(BSE_HAVE_LIBMAD, $BSE_HAVE_LIBMAD, [Whether bse links against libmad])
+
+ dnl # --- check codec requirements ---
+ AC_MSG_CHECKING([the required GSL-Loader library set])
+ if echo " $OV_LIBS" | grep ".*-lvorbis.*" >/dev/null ; then
+ AC_MSG_RESULT([complete])
+ else
+ AC_MSG_RESULT([])
+ 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_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 ---
+ BSE_PC_REQUIRE=
+ dnl # except for debian, libmad doesn't ship a mad.pc file
+ dnl #if test $BSE_HAVE_LIBMAD = 1 ; then
+ dnl # BSE_PC_REQUIRE=mad
+ dnl #fi
+ BSE_PC_CFLAGS=
+ BSE_PC_LIBS="$OV_LIBS"
+ AC_SUBST(BSE_PC_REQUIRE)
+ AC_SUBST(BSE_PC_CFLAGS)
+ AC_SUBST(BSE_PC_LIBS)
+
+ dnl # --- sizeof types ---
+ GLIB_SIZEOF([#include <pthread.h>], pthread_mutex_t, pth_mutex_t)
+ SFI_SIZEOF_PTH_MUTEX_T="$glib_cv_sizeof_pth_mutex_t"
+ AC_SUBST(SFI_SIZEOF_PTH_MUTEX_T)
+ GLIB_SIZEOF([#include <pthread.h>], pthread_cond_t, pth_cond_t)
+ SFI_SIZEOF_PTH_COND_T="$glib_cv_sizeof_pth_cond_t"
+ AC_SUBST(SFI_SIZEOF_PTH_COND_T)
+
+ dnl # --- pthread_mutexattr_settype ---
+ AC_MSG_CHECKING([for pthread_mutexattr_settype()])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #define _XOPEN_SOURCE 600
+ #include <pthread.h>
+ ]], [[
+ int (*attr_settype) (pthread_mutexattr_t *__attr, int __kind) = pthread_mutexattr_settype;
+ int val = PTHREAD_MUTEX_RECURSIVE;
+ attr_settype = 0; val = 0;
+ ]])],[
+ SFI_HAVE_MUTEXATTR_SETTYPE=1
+ AC_MSG_RESULT(yes)
+ ],[
+ SFI_HAVE_MUTEXATTR_SETTYPE=0
+ AC_MSG_RESULT(no)
+ ])
+ AC_SUBST(SFI_HAVE_MUTEXATTR_SETTYPE)
+
+ dnl # --- math.h glibc extensions
+ AC_CHECK_LIB(m, sincos,
+ AC_DEFINE(HAVE_SINCOS, 1, [Define if you have the sincos function in <math.h>]))
+
+ # --- setup BSE search/install paths ---
+ bseplugindir=\${libdir}/bse/v$BIN_VERSION/plugins
+ AC_SUBST(bseplugindir)
+ bsedriverdir=\${libdir}/bse/v$BIN_VERSION/drivers
+ AC_SUBST(bsedriverdir)
+ bseladspapath=${libdir}/ladspa
+ AC_SUBST(bseladspapath)
+ bseunversionedsampledir=\${datadir}/bse/samples
+ AC_SUBST(bseunversionedsampledir)
+ bsedatadir=\${datadir}/bse/v$BIN_VERSION
+ bseeffectdir=$bsedatadir/effects
+ AC_SUBST(bseeffectdir)
+ bseinstrumentdir=$bsedatadir/instruments
+ AC_SUBST(bseinstrumentdir)
+ bsesampledir=$bsedatadir/samples
+ AC_SUBST(bsesampledir)
+ bsescriptdir=$bsedatadir/scripts
+ AC_SUBST(bsescriptdir)
+ bsedemodir=$bsedatadir/demo
+ AC_SUBST(bsedemodir)
+ bseuserdatadir='~/beast'
+ AC_SUBST(bseuserdatadir)
+ ])
+ AC_DEFUN([AC_ASOUND_CHECK],
+ [
+ saved_cflags="$CFLAGS"
+ saved_cxxflags="$CXXFLAGS"
+ saved_ldflags="$LDFLAGS"
+ dnl # automatically search for libasound under the BSE prefix
+ CFLAGS="$CFLAGS $BSE_CFLAGS"
+ CXXFLAGS="$CFLAGS $BSE_CFLAGS"
+ LDFLAGS="$LDFLAGS $BSE_LIBS"
+ AC_LANG_SAVE
+
+ dnl --- find asoundlib.h ---
+ found_asoundlibh=0
+ AC_CHECK_HEADERS(alsa/asoundlib.h, found_asoundlibh=1)
+ if test $found_asoundlibh = 0 ; then
+ AC_MSG_ERROR([failed to detect asoundlib.h, ALSA not present?])
+ fi
+
+ dnl --- check for ALSA >= 1.0.5 ---
+ AC_MSG_CHECKING([for ALSA with version >= 1.0])
+ found_alsa1=0
+ AC_TRY_COMPILE([#include <alsa/asoundlib.h>],[
+ #if SND_LIB_MAJOR >= 1
+ /* ALSA >= 1.0 present */
+ #else
+ #error ALSA version <= 1.0
+ #endif
+ ], [ found_alsa1=1; AC_MSG_RESULT(present); ], [ AC_MSG_RESULT(not present); ])
+ if test $found_alsa1 = 0; then
+ AC_MSG_ERROR([ALSA version 1.0.5 is required to build this package])
+ fi
+
+ dnl --- check for -lasound ---
+ found_libasound=0
+ dnl snd_asoundlib_version() was introduced in ALSA 1.0.5
+ cflags=$CFLAGS
+ ldflags=$LDFLAGS
+ CFLAGS=""
+ LDFLAGS=""
+ AC_CHECK_LIB(asound, snd_asoundlib_version, ALSA_LIBS="-lasound"; found_libasound=1)
+ CFLAGS="$cflags"
+ LDFLAGS="$ldflags"
+ if test $found_libasound = 0; then
+ AC_MSG_ERROR([ALSA version 1.0.5 is required to build this package])
+ fi
+ AC_SUBST(ALSA_LIBS)
+
+ AC_LANG_RESTORE
+ CFLAGS="$saved_cflags"
+ CXXFLAGS="$saved_cxxflags"
+ LDFLAGS="$saved_ldflags"
+ ])
+ AC_DEFUN([AC_BSESCM_REQUIREMENTS],
+ [
+ BSESCM_CFLAGS="$BSE_CFLAGS"
+ BSESCM_LIBS="$BSE_LIBS"
+
+ dnl # --- libguile check ---
+ guile_tests=0
+ GUILE_VERSION=none
+ REQUIRED_VERSION=1.6
+ AC_PATH_PROG(GUILE_CONFIG, guile-config)
+ if test -n "$GUILE_CONFIG"; then
+ guile_tests=`expr $guile_tests + 1`
+ GUILE_VERSION=`$GUILE_CONFIG info guileversion`
+ GUILE_CFLAGS=`$GUILE_CONFIG compile`
+ GUILE_LDFLAGS=`$GUILE_CONFIG link`
+ MC_CHECK_VERSION($GUILE_VERSION, $REQUIRED_VERSION, [guile_tests=`expr $guile_tests + 1`])
+ dnl # check headers seperately, since some distributions ship on-devel guile packages with
guile-config
+ AC_CHECK_HEADER(guile/gh.h, guile_tests=`expr $guile_tests + 1`)
+ AC_CHECK_HEADER(libguile/properties.h, guile_tests=`expr $guile_tests + 1`) dnl # guile-1.6 headerfile
+ fi
+ if test $guile_tests = 4 ; then
+ BSESCM_CFLAGS="$GUILE_CFLAGS $BSESCM_CFLAGS"
+ BSESCM_LIBS="$GUILE_LDFLAGS $BSESCM_LIBS"
+ else
+ EMSG="failed to detect guile headers and library v$REQUIRED_VERSION"
+ EMSG="$EMSG (available from http://www.gnu.org/software/guile/guile.html)"
+ EMSG="$EMSG - detected library version: $GUILE_VERSION"
+ AC_MSG_ERROR([$EMSG])
+ fi
+
+ AC_SUBST(BSESCM_CFLAGS)
+ AC_SUBST(BSESCM_LIBS)
+ ])
+ AC_DEFUN([AC_GXK_REQUIREMENTS],
+ [
+ dnl # required libraries, defines LIB*_CFLAGS and LIB*_LIBS:
+ PKG_CHECK_MODULES(LIBPANGO, pangoft2 >= 1.4.0)
+ PKG_CHECK_MODULES(LIBGTK, gtk+-2.0 >= 2.12.12)
+ PKG_CHECK_MODULES(LIBART, libart-2.0 >= 2.3.8)
+ PKG_CHECK_MODULES(LIBGNOMECANVAS, libgnomecanvas-2.0 >= 2.4.0)
+ GXK_CFLAGS="$LIBPANGO_CFLAGS $LIBGTK_CFLAGS $LIBART_CFLAGS $LIBGNOMECANVAS_CFLAGS"
+ GXK_LIBS="$LIBPANGO_LIBS $LIBGTK_LIBS $LIBART_LIBS $LIBGNOMECANVAS_LIBS"
+ AC_SUBST(GXK_CFLAGS)
+ AC_SUBST(GXK_LIBS)
+ ])
+ AC_DEFUN([AC_BEAST_REQUIREMENTS],
+ [
+ dnl # start where GXK left off
+ BEAST_CFLAGS="$GXK_CFLAGS"
+ BEAST_LIBS="$GXK_LIBS"
+ AC_SUBST(BEAST_CFLAGS)
+ AC_SUBST(BEAST_LIBS)
+
+ dnl # Feature XKB extension if present
+ cflags=$CFLAGS
+ ldflags=$LDFLAGS
+ CFLAGS=$BEAST_CFLAGS
+ LDFLAGS=$BEAST_LIBS
+ have_xkb=
+ AC_CHECK_LIB(X11, XkbOpenDisplay, have_xkb=1$have_xkb)
+ AC_CHECK_LIB(X11, XkbGetKeyboard, have_xkb=2$have_xkb)
+ AC_CHECK_HEADER(X11/XKBlib.h, have_xkb=3$have_xkb)
+ AC_CHECK_HEADER(X11/extensions/XKBgeom.h, have_xkb=4$have_xkb, , X11/Xlib.h)
+ MC_IF_VAR_EQ(have_xkb, 4321,
+ AC_DEFINE_UNQUOTED(BST_WITH_XKB, 1, [XKB present]),
+ )
+ CFLAGS=$cflags
+ LDFLAGS=$ldflags
+
+ # --- BEAST paths ---
+ beastbasedir=\${datadir}/beast
+ beastimagesdir=$beastbasedir/v$BIN_VERSION/images
+ AC_SUBST(beastimagesdir)
+ beastkeysdir=$beastbasedir/v$BIN_VERSION/keys
+ AC_SUBST(beastkeysdir)
+ beastskinsdir=$beastbasedir/v$BIN_VERSION/skins
+ AC_SUBST(beastskinsdir)
+ ])
+ AC_DEFUN([AC_SUIDMAIN_REQUIREMENTS],
+ [
+ dnl # figure everything required by the suid wrapper
+ AC_CHECK_FUNCS(seteuid)
+ AC_CHECK_FUNCS(setreuid)
+ ])
+ AC_DEFUN([AC_BSE_SNDDEV_CHECK],
+ [
+ dnl # OSS-Lite driver check
+ AC_CHECK_HEADERS(sys/soundcard.h soundcard.h, have_oss_header=yes, have_oss_header=no)
+ AC_ARG_ENABLE(osspcm,
+ [ --enable-osspcm=DEVICE force DEVICE as OSS PCM device name],
+ [AC_MSG_WARN([Ignoring detection of PCM device])],
+ [enable_osspcm=""])
+ AC_ARG_ENABLE([ossmidi],
+ [ --enable-ossmidi=DEVICE force DEVICE as OSS MIDI device name],
+ [AC_MSG_WARN([Ignoring detection of MIDI device])],
+ [enable_ossmidi=""])
+
+ dnl # === OSS PCM device ===
+ AC_MSG_CHECKING([for available OSS audio devices])
+ result=
+ if test -n "$enable_osspcm" ; then
+ dev="$enable_osspcm"
+ else
+ for dev in /dev/dsp /dev/sound \
+ /dev/dsp0 /dev/dsp1 /dev/dsp2 /dev/dsp3 ; do
+ if test -c $dev ; then
+ break;
+ else
+ dev=""
+ fi
+ done
+ fi
+ if test -n "$dev" ; then
+ bse_found_pcmdev=yes
+ AC_DEFINE_UNQUOTED(BSE_PCM_DEVICE_CONF_OSS, "$dev", [Device used for PCM I/O])
+ result="PCM:$dev "
+ else
+ bse_found_pcmdev=no
+ AC_DEFINE_UNQUOTED(BSE_PCM_DEVICE_CONF_OSS, "/dev/dsp", [Device used for PCM I/O])
+ result="PCM:none (assuming PCM:/dev/dsp)"
+ fi
+ AC_MSG_RESULT($result)
+
+ dnl # === OSS MIDI device ===
+ AC_MSG_CHECKING([for available OSS midi devices])
+ if test -n "$enable_ossmidi" ; then
+ dev="$enable_ossmidi"
+ else
+ for dev in /dev/midi \
+ /dev/midi0 /dev/midi1 /dev/midi2 /dev/midi3 \
+ /dev/rmidi0 /dev/rmidi1 /dev/rmidi2 /dev/rmidi3 ; do
+ if test -c $dev ; then
+ break;
+ else
+ dev=""
+ fi
+ done
+ fi
+ if test -n "$dev" ; then
+ bse_found_mididev=yes
+ AC_DEFINE_UNQUOTED(BSE_MIDI_DEVICE_CONF_OSS, "$dev", [Device used for MID I/O])
+ result="MIDI:$dev "
+ else
+ bse_found_mididev=no
+ AC_DEFINE_UNQUOTED(BSE_MIDI_DEVICE_CONF_OSS, "/dev/midi", [Device used for MID I/O])
+ result="MIDI:none (assuming MIDI:/dev/midi)"
+ fi
+ AC_MSG_RESULT($result)
+
+ dnl # == Complain about mising devices ===
+ if test "$bse_found_pcmdev $bse_found_mididev" \!= "yes yes"; then
+ AC_MSG_WARN([failed to detect proper sound device files])
+ fi
+ ])
+ AC_DEFUN([AC_DOC_REQUIREMENTS],
+ [
+ ])
+
+ # find installation utilities
+ AC_PATH_PROG(UPDATE_MIME_DATABASE, update-mime-database)
+
+ # --enable-devel-mode: check for development build rules, i.e. autogen.sh
+ # based builds with .git repository; these enable additional build rules
+ # for files that are pre-packaged in tarballs.
+ if test x"$enable_devel_mode" = xyes ; then
+ TEST_SRCDIR=$(cd $srcdir ; /bin/pwd)
+ TEST_BUILDDIR=$(cd . ; /bin/pwd)
+ test "$TEST_SRCDIR" == "$TEST_BUILDDIR" || {
+ AC_MSG_ERROR([development build rules require srcdir == builddir])
+ }
+ git cat-file commit af82337c966c1182e 2>&1 | fgrep -q bb4f6e48724a6731 || { # 0.8.0
+ AC_MSG_ERROR([development build rules require a beast.git repository])
+ }
+ DEVELMODE="" ; NOTDEVELMODE="#"
+ # devel mode build tools
+ MC_ASSERT_PROG(XMLLINT, xmllint, [See: http://xmlsoft.org/xmllint.html])
+ MC_ASSERT_PROG(PYTHON, python2.7)
+ if test -z "$PYTHON" || $PYTHON -c "import sys; sys.exit (sys.hexversion >= 0x2070500)" 2>/dev/null ; then
+ AC_MSG_ERROR([failed to detect python (version >= 2.7.5) required for development mode])
+ fi
+ else
+ DEVELMODE="#"; NOTDEVELMODE=""
+ fi
+ AC_SUBST(DEVELMODE)
+ AC_SUBST(NOTDEVELMODE)
+
+ AC_MSG_CHECKING(whether source dir equals build dir)
+ TEST_SRCDIR=`cd $srcdir ; /bin/pwd`
+ TEST_BUILDDIR=`cd . ; /bin/pwd`
+ if test "$TEST_SRCDIR" = "$TEST_BUILDDIR" ; then
+ AC_MSG_RESULT(yes)
+ SRCEQBUILDRULE=''
+ else
+ AC_MSG_RESULT(no)
+ AC_MSG_WARN([disabling some build rules because srcdir != builddir])
+ SRCEQBUILDRULE='#'
+ fi
+ AC_CHECK_PROGS(PERL, perl5 perl)
+ if test -z "$PERL" || $PERL -e 'exit ($] >= 5.002)' >/dev/null ; then
+ AC_MSG_WARN([failed to detect perl (version >= 5.002), disabling dependent build rules])
+ PERLRULE='#'
+ else
+ PERLRULE="$SRCEQBUILDRULE"
+ fi
+ AC_SUBST(PERLRULE)
+ AM_CONDITIONAL(WITH_PERLRULE, [test "$PERLRULE" != "#"])
+
+ # Check requirement sets
+ AC_I18N_REQUIREMENTS
+ AC_SFI_REQUIREMENTS
+ AC_BSE_REQUIREMENTS
+ AC_ASOUND_CHECK
+ AC_BSESCM_REQUIREMENTS
+ AC_BSE_SNDDEV_CHECK
+ AC_GXK_REQUIREMENTS
+ AC_BEAST_REQUIREMENTS
+ AC_SUIDMAIN_REQUIREMENTS
+ AC_DOC_REQUIREMENTS
+
+ # Automake @VARIABLE@ exports.
+ AC_SUBST(CFLAGS)
+ AC_SUBST(CXXFLAGS)
+ AC_SUBST(CPPFLAGS)
+ AC_SUBST(LDFLAGS)
+
+
+ # create output files
+ AC_CONFIG_FILES([
+ Makefile
+ data/Makefile
+ data/bse.pc
+ data/beast.applications
+ sfi/Makefile
+ sfi/tests/Makefile
+ bse/bseconfig.h
+ bse/Makefile
+ bse/icons/Makefile
+ bse/zintern/Makefile
+ bse/tests/Makefile
+ plugins/Makefile
+ plugins/icons/Makefile
+ plugins/freeverb/Makefile
+ drivers/Makefile
+ shell/Makefile
+ beast-gtk/Makefile
+ beast-gtk/gxk/Makefile
+ beast-gtk/dialogs/Makefile
+ beast-gtk/icons/Makefile
+ launchers/Makefile
+ library/Makefile
+ library/effects/Makefile
+ library/instruments/Makefile
+ library/samples/Makefile
+ library/scripts/Makefile
+ library/demo/Makefile
+ library/keys/Makefile
+ library/skins/Makefile
+ library/skins/images/Makefile
+ tools/Makefile
+ tools/scripts/Makefile
+ po/Makefile
+ tests/Makefile
+ tests/latency/Makefile
+ tests/scripts/Makefile
+ tests/bse/Makefile
+ tests/audio/Makefile
+ tests/filecheck/Makefile
+ docs/Makefile
+ docs/images/Makefile
+ docs/imports/Makefile
+ ])
+
+ AC_OUTPUT
diff --cc po/POTSCAN
index a921515,aadb347..8a75ee0
--- a/po/POTSCAN
+++ b/po/POTSCAN
@@@ -1,108 -1,106 +1,108 @@@
#0 List of source files to scan for translatable strings
#0 Please keep alphabetically sorted
- beast-gtk/bstapp.c
- beast-gtk/bstauxdialogs.c
- beast-gtk/bstbuseditor.c
- beast-gtk/bstbusmixer.c
- beast-gtk/bstbusview.c
- beast-gtk/bstcanvaslink.c
- beast-gtk/bstcanvassource.c
- beast-gtk/bstdbmeter.c
- beast-gtk/bsteventrollctrl.c
- beast-gtk/bstfiledialog.c
- beast-gtk/bstgrowbar.c
- beast-gtk/bstitemseqdialog.c
- beast-gtk/bstitemview.c
- beast-gtk/bstkeybindings.c
- beast-gtk/bstmain.c
- beast-gtk/bstmsgabsorb.c
- beast-gtk/bstparam-automation.c
- beast-gtk/bstparam-choice.c
- beast-gtk/bstparam-color-spinner.c
- beast-gtk/bstparam-item-seq.c
- beast-gtk/bstparam-note-sequence.c
- beast-gtk/bstparam-note-spinner.c
- beast-gtk/bstparam-proxy.c
- beast-gtk/bstparam-scale.c
- beast-gtk/bstparam-searchpath.c
- beast-gtk/bstparam-time.c
- beast-gtk/bstpartdialog.c
- beast-gtk/bstpartview.c
- beast-gtk/bstpatterncolumns.c
- beast-gtk/bstpatternctrl.c
- beast-gtk/bstpianorollctrl.c
- beast-gtk/bstplayback.c
- beast-gtk/bstpreferences.c
- beast-gtk/bstprocedure.c
- beast-gtk/bstprofiler.c
- beast-gtk/bstprojectctrl.c
- beast-gtk/bstrackeditor.c
- beast-gtk/bstrackitem.c
- beast-gtk/bstrackview.c
+ beast-gtk/bstapp.cc
+ beast-gtk/bstauxdialogs.cc
+ beast-gtk/bstbuseditor.cc
+ beast-gtk/bstbusmixer.cc
+ beast-gtk/bstbusview.cc
+ beast-gtk/bstcanvaslink.cc
+ beast-gtk/bstcanvassource.cc
+ beast-gtk/bstdbmeter.cc
+ beast-gtk/bsteventrollctrl.cc
+ beast-gtk/bstfiledialog.cc
+ beast-gtk/bstgrowbar.cc
+ beast-gtk/bstitemseqdialog.cc
+ beast-gtk/bstitemview.cc
+ beast-gtk/bstkeybindings.cc
+ beast-gtk/bstmain.cc
+ beast-gtk/bstmsgabsorb.cc
+ beast-gtk/bstparam-automation.cc
+ beast-gtk/bstparam-choice.cc
+ beast-gtk/bstparam-color-spinner.cc
+ beast-gtk/bstparam-item-seq.cc
+ beast-gtk/bstparam-note-sequence.cc
+ beast-gtk/bstparam-note-spinner.cc
+ beast-gtk/bstparam-proxy.cc
+ beast-gtk/bstparam-scale.cc
+ beast-gtk/bstparam-searchpath.cc
+ beast-gtk/bstparam-time.cc
+ beast-gtk/bstpartdialog.cc
+ beast-gtk/bstpartview.cc
+ beast-gtk/bstpatterncolumns.cc
+ beast-gtk/bstpatternctrl.cc
+ beast-gtk/bstpianorollctrl.cc
+ beast-gtk/bstplayback.cc
+ beast-gtk/bstpreferences.cc
+ beast-gtk/bstprocedure.cc
+ beast-gtk/bstprofiler.cc
+ beast-gtk/bstprojectctrl.cc
+ beast-gtk/bstrackeditor.cc
+ beast-gtk/bstrackitem.cc
+ beast-gtk/bstrackview.cc
beast-gtk/bstrecords.idl
- beast-gtk/bstsampleeditor.c
- beast-gtk/bstscrollgraph.c
- beast-gtk/bstsnetrouter.c
- beast-gtk/bstsupershell.c
- beast-gtk/bsttrackrollctrl.c
- beast-gtk/bsttracksynthdialog.c
- beast-gtk/bsttrackview.c
- beast-gtk/bstusermessage.c
- beast-gtk/bstutils.c
- beast-gtk/bstwaveeditor.c
- beast-gtk/bstwaveview.c
+ beast-gtk/bstsampleeditor.cc
+ beast-gtk/bstscrollgraph.cc
+ beast-gtk/bstsnetrouter.cc
++beast-gtk/bstsoundfontview.c
+ beast-gtk/bstsupershell.cc
+ beast-gtk/bsttrackrollctrl.cc
+ beast-gtk/bsttracksynthdialog.cc
+ beast-gtk/bsttrackview.cc
+ beast-gtk/bstusermessage.cc
+ beast-gtk/bstutils.cc
+ beast-gtk/bstwaveeditor.cc
+ beast-gtk/bstwaveview.cc
beast-gtk/dialogs/radgets-beast.xml
beast-gtk/dialogs/radgets-standard.xml
- beast-gtk/gxk/gxklistwrapper.c
- beast-gtk/gxk/gxkparam-entry.c
- beast-gtk/gxk/gxkparam-label.c
- beast-gtk/gxk/gxkparam-scale.c
- beast-gtk/gxk/gxkparam-spinner.c
- beast-gtk/gxk/gxkparam-toggle.c
- beast-gtk/gxk/gxksimplelabel.c
- birnet/birnetmsg.cc
- birnet/birnetutils.cc
- bse/bseautodoc.c
- bse/bsebiquadfilter.c
- bse/bsebus.c
+ beast-gtk/gxk/gxklistwrapper.cc
+ beast-gtk/gxk/gxkparam-entry.cc
+ beast-gtk/gxk/gxkparam-label.cc
+ beast-gtk/gxk/gxkparam-scale.cc
+ beast-gtk/gxk/gxkparam-spinner.cc
+ beast-gtk/gxk/gxkparam-toggle.cc
+ beast-gtk/gxk/gxksimplelabel.cc
+ bse/bseautodoc.cc
+ bse/bsebasics.idl
+ bse/bsebiquadfilter.cc
+ bse/bsebus.cc
bse/bsebusmodule.idl
bse/bsebus.proc
- bse/bseconstant.c
+ bse/bseconstant.cc
bse/bsecontainer.proc
- bse/bsecore.idl
- bse/bsedevice.c
- bse/bseenums.c
- bse/bseinstrumentinput.c
- bse/bseinstrumentoutput.c
- bse/bsejanitor.c
- bse/bseladspamodule.c
+ bse/bsedevice.cc
+ bse/bseenums.cc
+ bse/bseinstrumentinput.cc
+ bse/bseinstrumentoutput.cc
+ bse/bsejanitor.cc
+ bse/bseladspamodule.cc
bse/bsemain.cc
- bse/bsemidicontroller.c
- bse/bsemididevice-null.c
- bse/bsemididevice-oss.c
- bse/bsemidiinput.c
- bse/bsemidisynth.c
- bse/bsemidivoice.c
- bse/bseobject.c
+ bse/bsemidicontroller.cc
+ bse/bsemididevice-null.cc
+ bse/bsemididevice-oss.cc
+ bse/bsemidiinput.cc
+ bse/bsemidisynth.cc
+ bse/bsemidivoice.cc
+ bse/bseobject.cc
bse/bseparasite.proc
- bse/bsepcmdevice-null.c
- bse/bsepcmdevice-oss.c
- bse/bsepcminput.c
- bse/bsepcmoutput.c
- bse/bseserver.c
- bse/bsesnooper.c
- bse/bsesong.c
+ bse/bsepcmdevice-null.cc
+ bse/bsepcmdevice-oss.cc
+ bse/bsepcminput.cc
+ bse/bsepcmoutput.cc
+ bse/bseserver.cc
+ bse/bsesnooper.cc
+ bse/bsesong.cc
bse/bsesong.proc
++bse/bsesoundfontosc.c
bse/bsesource.proc
- bse/bsestandardosc.c
- bse/bsesubiport.c
- bse/bsesuboport.c
- bse/bsesubsynth.c
- bse/bsesuper.c
- bse/bsetrack.c
+ bse/bsestandardosc.cc
+ bse/bsesubiport.cc
+ bse/bsesuboport.cc
+ bse/bsesubsynth.cc
+ bse/bsesuper.cc
+ bse/bsetrack.cc
bse/bsetrack.proc
- bse/bsewave.c
- bse/bsewaveosc.c
+ bse/bsewave.cc
+ bse/bsewaveosc.cc
data/beast.desktop.in
data/beast.xml.in
data/bse.keys.in
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]