summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
commit42995d7bf396933ee60c5f89c354ea89cf13df0d (patch)
treecfdcea0ac57420e7baf570bfe435e107bb842541
downloadarts-42995d7b.tar.gz
arts-42995d7b.zip
Copy of aRts for Trinity modifications
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/dependencies/arts@1070145 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
-rw-r--r--COPYING347
-rw-r--r--COPYING.LIB486
-rw-r--r--INSTALL176
-rw-r--r--Makefile.am.in32
-rw-r--r--Makefile.cvs22
-rw-r--r--arts.lsm11
-rw-r--r--artsc/Makefile.am32
-rwxr-xr-xartsc/artsc-config.in56
-rw-r--r--artsc/artsc.c226
-rw-r--r--artsc/artsc.h246
-rw-r--r--artsc/artsc_export.h.in52
-rw-r--r--artsc/artscbackend.cc805
-rw-r--r--artsc/artsdsp.c675
-rwxr-xr-xartsc/artsdsp.in106
-rw-r--r--artsc/stdioemu.c96
-rw-r--r--configure.in.bot11
-rw-r--r--configure.in.in851
-rw-r--r--doc/Makefile.am1
-rw-r--r--doc/NEWS58
-rw-r--r--doc/README5
-rw-r--r--doc/TODO215
-rw-r--r--examples/Makefile.am97
-rw-r--r--examples/aggregation.idl27
-rw-r--r--examples/artsccat.c115
-rw-r--r--examples/artscmt.c143
-rw-r--r--examples/artscrec.c115
-rw-r--r--examples/artsctest.c72
-rw-r--r--examples/catfile.cc55
-rw-r--r--examples/dcasttest.cc72
-rw-r--r--examples/flow.cc56
-rw-r--r--examples/hello.idl41
-rw-r--r--examples/hello_impl.cc76
-rw-r--r--examples/hello_impl.h51
-rw-r--r--examples/helloclient.cc76
-rw-r--r--examples/hellodynamic.cc94
-rw-r--r--examples/hellodynamic2.cc124
-rw-r--r--examples/hellomain.cc77
-rw-r--r--examples/helloserver.cc52
-rw-r--r--examples/irdemo.cc155
-rw-r--r--examples/playtofile.idl41
-rw-r--r--examples/playtofile_impl.cc99
-rw-r--r--examples/playtofile_main.cc147
-rw-r--r--examples/referenceinfo.cc57
-rw-r--r--examples/streamsound.cc106
-rw-r--r--examples/testaggregation.cc73
-rw-r--r--examples/testasubsys.cc142
-rw-r--r--examples/testdhandle.cc115
-rw-r--r--examples/testthreads.cc64
-rw-r--r--examples/x11commtest.cc76
-rw-r--r--flow/Makefile.am49
-rw-r--r--flow/artsflow.idl566
-rw-r--r--flow/asyncschedule.cc553
-rw-r--r--flow/asyncschedule.h134
-rw-r--r--flow/audioio.cc165
-rw-r--r--flow/audioio.h145
-rw-r--r--flow/audioioaix.cc390
-rw-r--r--flow/audioioalsa.cc561
-rw-r--r--flow/audioioalsa9.cc590
-rw-r--r--flow/audioiocsl.cc640
-rw-r--r--flow/audioioesd.cc231
-rw-r--r--flow/audioiojack.cc346
-rw-r--r--flow/audioiolibaudioio.cc236
-rw-r--r--flow/audioiomas.cc619
-rw-r--r--flow/audioionas.cc260
-rw-r--r--flow/audioionull.cc184
-rw-r--r--flow/audioiooss.cc485
-rw-r--r--flow/audioioossthreaded.cc681
-rw-r--r--flow/audioiosgi.cc274
-rw-r--r--flow/audioiosun.cc442
-rw-r--r--flow/audiomanager_impl.cc325
-rw-r--r--flow/audiosubsys.cc645
-rw-r--r--flow/audiosubsys.h236
-rw-r--r--flow/audiotobytestream_impl.cc223
-rw-r--r--flow/bufferqueue.h148
-rw-r--r--flow/bus.cc367
-rw-r--r--flow/bus.h76
-rw-r--r--flow/bytestreamtoaudio_impl.cc119
-rw-r--r--flow/cache.cc274
-rw-r--r--flow/cache.h92
-rw-r--r--flow/cachedwav.h81
-rw-r--r--flow/convert.cc418
-rw-r--r--flow/convert.h164
-rw-r--r--flow/cpuinfo.cc232
-rw-r--r--flow/cpuinfo.h72
-rw-r--r--flow/datahandle_impl.cc499
-rw-r--r--flow/fft.c32
-rw-r--r--flow/fft.h32
-rw-r--r--flow/gsl/Makefile.am24
-rw-r--r--flow/gsl/arts-patches73
-rw-r--r--flow/gsl/configure.in.in224
-rw-r--r--flow/gsl/dummy.cc3
-rw-r--r--flow/gsl/gbsearcharray.h292
-rwxr-xr-xflow/gsl/gsl-fftconf.sh468
-rwxr-xr-xflow/gsl/gsl-fftgen.pl810
-rw-r--r--flow/gsl/gsl-iplan.txt57
-rw-r--r--flow/gsl/gsl-mplan.txt226
-rw-r--r--flow/gsl/gsl.3822
-rw-r--r--flow/gsl/gsl.gnuplot5
-rw-r--r--flow/gsl/gslarrows30
-rw-r--r--flow/gsl/gslartsthreads.cc205
-rw-r--r--flow/gsl/gslartsthreads.h102
-rw-r--r--flow/gsl/gslcommon.c1651
-rw-r--r--flow/gsl/gslcommon.h293
-rw-r--r--flow/gsl/gslconfig.h.in11
-rw-r--r--flow/gsl/gslconvert.c57
-rw-r--r--flow/gsl/gslconvert.h43
-rw-r--r--flow/gsl/gsldatacache.c633
-rw-r--r--flow/gsl/gsldatacache.h87
-rw-r--r--flow/gsl/gsldatahandle-lbuffer.c11
-rw-r--r--flow/gsl/gsldatahandle-mad.c711
-rw-r--r--flow/gsl/gsldatahandle-mad.h42
-rw-r--r--flow/gsl/gsldatahandle-vorbis.c376
-rw-r--r--flow/gsl/gsldatahandle-vorbis.h41
-rw-r--r--flow/gsl/gsldatahandle.c1241
-rw-r--r--flow/gsl/gsldatahandle.h143
-rw-r--r--flow/gsl/gsldatautils.c462
-rw-r--r--flow/gsl/gsldatautils.h909
-rw-r--r--flow/gsl/gsldefs.h136
-rw-r--r--flow/gsl/gslengine.c753
-rw-r--r--flow/gsl/gslengine.h206
-rw-r--r--flow/gsl/gslfft.c9052
-rw-r--r--flow/gsl/gslfft.h126
-rw-r--r--flow/gsl/gslffttest.c435
-rw-r--r--flow/gsl/gslfilehash.c464
-rw-r--r--flow/gsl/gslfilehash.h77
-rw-r--r--flow/gsl/gslfilter.c1379
-rw-r--r--flow/gsl/gslfilter.h281
-rw-r--r--flow/gsl/gslglib.c2400
-rw-r--r--flow/gsl/gslglib.h858
-rw-r--r--flow/gsl/gslglibhash.cc151
-rw-r--r--flow/gsl/gslglibhashtest.cc123
-rw-r--r--flow/gsl/gslieee754.h246
-rw-r--r--flow/gsl/gslincluder.c13420
-rw-r--r--flow/gsl/gslloader-gslwave.c701
-rw-r--r--flow/gsl/gslloader-mad.c210
-rw-r--r--flow/gsl/gslloader-oggvorbis.c178
-rw-r--r--flow/gsl/gslloader-wav.c442
-rw-r--r--flow/gsl/gslloader.c335
-rw-r--r--flow/gsl/gslloader.h136
-rw-r--r--flow/gsl/gslmagic.c711
-rw-r--r--flow/gsl/gslmagic.h72
-rw-r--r--flow/gsl/gslmakefile.inc87
-rw-r--r--flow/gsl/gslmath.c1085
-rw-r--r--flow/gsl/gslmath.h518
-rw-r--r--flow/gsl/gslmathtest.c334
-rw-r--r--flow/gsl/gslopmaster.c783
-rw-r--r--flow/gsl/gslopmaster.h42
-rw-r--r--flow/gsl/gslopnode.h247
-rw-r--r--flow/gsl/gslopschedule.c582
-rw-r--r--flow/gsl/gslopschedule.h79
-rw-r--r--flow/gsl/gsloputil.c721
-rw-r--r--flow/gsl/gsloputil.h86
-rw-r--r--flow/gsl/gsloscillator-aux.c214
-rw-r--r--flow/gsl/gsloscillator.c219
-rw-r--r--flow/gsl/gsloscillator.h84
-rw-r--r--flow/gsl/gslosctable.c626
-rw-r--r--flow/gsl/gslosctable.h104
-rw-r--r--flow/gsl/gslsignal.c258
-rw-r--r--flow/gsl/gslsignal.h343
-rw-r--r--flow/gsl/gsltests.c650
-rw-r--r--flow/gsl/gslwave.headerbin0 -> 3342 bytes
-rw-r--r--flow/gsl/gslwavechunk.c812
-rw-r--r--flow/gsl/gslwavechunk.h129
-rw-r--r--flow/gsl/gslwaveloader.c2
-rw-r--r--flow/gsl/gslwaveloader.h6
-rw-r--r--flow/gsl/gslwaveosc-aux.c249
-rw-r--r--flow/gsl/gslwaveosc.c376
-rw-r--r--flow/gsl/gslwaveosc.h96
-rw-r--r--flow/gsl/gslwchunk.c279
-rw-r--r--flow/gslpp/Makefile.am7
-rw-r--r--flow/gslpp/datahandle.cpp412
-rw-r--r--flow/gslpp/datahandle.h220
-rw-r--r--flow/gslschedule.cc1195
-rw-r--r--flow/gslschedule.h262
-rw-r--r--flow/mcopclass/DataHandlePlay.mcopclass2
-rw-r--r--flow/mcopclass/Makefile.am15
-rw-r--r--flow/mcopclass/Synth_ADD.mcopclass3
-rw-r--r--flow/mcopclass/Synth_AMAN_PLAY.mcopclass3
-rw-r--r--flow/mcopclass/Synth_AMAN_RECORD.mcopclass3
-rw-r--r--flow/mcopclass/Synth_BUS_DOWNLINK.mcopclass3
-rw-r--r--flow/mcopclass/Synth_BUS_UPLINK.mcopclass3
-rw-r--r--flow/mcopclass/Synth_FREQUENCY.mcopclass3
-rw-r--r--flow/mcopclass/Synth_MUL.mcopclass3
-rw-r--r--flow/mcopclass/Synth_MULTI_ADD.mcopclass3
-rw-r--r--flow/mcopclass/Synth_PLAY.mcopclass3
-rw-r--r--flow/mcopclass/Synth_PLAY_WAV.mcopclass3
-rw-r--r--flow/mcopclass/Synth_RECORD.mcopclass3
-rw-r--r--flow/mcopclass/Synth_WAVE_SIN.mcopclass3
-rw-r--r--flow/mcopclass/WaveDataHandle.mcopclass2
-rw-r--r--flow/pipebuffer.cc166
-rw-r--r--flow/pipebuffer.h75
-rw-r--r--flow/resample.cc305
-rw-r--r--flow/resample.h167
-rw-r--r--flow/stdsynthmodule.cc92
-rw-r--r--flow/stdsynthmodule.h65
-rw-r--r--flow/stereoeffectstack_impl.cc179
-rw-r--r--flow/stereofftscope_impl.cc131
-rw-r--r--flow/stereovolumecontrol_impl.cc197
-rw-r--r--flow/synth_add_impl.cc44
-rw-r--r--flow/synth_frequency_impl.cc70
-rw-r--r--flow/synth_mul_impl.cc44
-rw-r--r--flow/synth_multi_add_impl.cc64
-rw-r--r--flow/synth_play_impl.cc285
-rw-r--r--flow/synth_play_wav_impl.cc579
-rw-r--r--flow/synth_record_impl.cc184
-rw-r--r--flow/synth_wave_sin_impl.cc44
-rw-r--r--flow/synthschedule.h36
-rw-r--r--flow/virtualports.cc491
-rw-r--r--flow/virtualports.h87
-rw-r--r--gmcop/Makefile.am10
-rw-r--r--gmcop/giomanager.cc506
-rw-r--r--gmcop/giomanager.h128
-rw-r--r--mcop/Makefile.am33
-rw-r--r--mcop/anyref.cc310
-rw-r--r--mcop/anyref.h146
-rw-r--r--mcop/arts_export.h.in53
-rw-r--r--mcop/asyncstream.cc46
-rw-r--r--mcop/asyncstream.h103
-rw-r--r--mcop/buffer.cc386
-rw-r--r--mcop/buffer.h104
-rw-r--r--mcop/common.h141
-rw-r--r--mcop/connect.cc149
-rw-r--r--mcop/connect.h55
-rw-r--r--mcop/connection.cc196
-rw-r--r--mcop/connection.h100
-rw-r--r--mcop/core.cc3191
-rw-r--r--mcop/core.h1561
-rw-r--r--mcop/core.idl715
-rw-r--r--mcop/datapacket.cc65
-rw-r--r--mcop/datapacket.h230
-rw-r--r--mcop/debug.cc821
-rw-r--r--mcop/debug.h138
-rw-r--r--mcop/delayedreturn.cc71
-rw-r--r--mcop/delayedreturn.h102
-rw-r--r--mcop/dispatcher.cc1090
-rw-r--r--mcop/dispatcher.h265
-rw-r--r--mcop/dynamicrequest.cc152
-rw-r--r--mcop/dynamicrequest.h133
-rw-r--r--mcop/dynamicskeleton.cc204
-rw-r--r--mcop/dynamicskeleton.h163
-rw-r--r--mcop/extensionloader.cc116
-rw-r--r--mcop/extensionloader.h59
-rw-r--r--mcop/factory.cc36
-rw-r--r--mcop/factory.h69
-rw-r--r--mcop/flowsystem.cc180
-rw-r--r--mcop/flowsystem.h147
-rw-r--r--mcop/idlfilereg.cc44
-rw-r--r--mcop/idlfilereg.h51
-rw-r--r--mcop/ifacerepo_impl.cc305
-rw-r--r--mcop/ifacerepo_impl.h98
-rw-r--r--mcop/iomanager.cc494
-rw-r--r--mcop/iomanager.h214
-rw-r--r--mcop/loopback.cc57
-rw-r--r--mcop/loopback.h51
-rw-r--r--mcop/mcopconfig.cc67
-rw-r--r--mcop/mcopconfig.h55
-rw-r--r--mcop/mcoputils.cc574
-rw-r--r--mcop/mcoputils.h97
-rw-r--r--mcop/md5.c197
-rw-r--r--mcop/md5.h45
-rw-r--r--mcop/md5auth.cc213
-rw-r--r--mcop/md5auth.h105
-rw-r--r--mcop/namedstore.h125
-rw-r--r--mcop/notification.cc101
-rw-r--r--mcop/notification.h87
-rw-r--r--mcop/object.cc1528
-rw-r--r--mcop/object.h390
-rw-r--r--mcop/objectmanager.cc289
-rw-r--r--mcop/objectmanager.h75
-rw-r--r--mcop/pool.h89
-rw-r--r--mcop/reference.cc32
-rw-r--r--mcop/reference.h349
-rw-r--r--mcop/referenceclean.cc87
-rw-r--r--mcop/referenceclean.h60
-rw-r--r--mcop/socketconnection.cc205
-rw-r--r--mcop/socketconnection.h64
-rw-r--r--mcop/startupmanager.cc150
-rw-r--r--mcop/startupmanager.h75
-rw-r--r--mcop/tcpconnection.cc152
-rw-r--r--mcop/tcpconnection.h43
-rw-r--r--mcop/tcpserver.cc193
-rw-r--r--mcop/tcpserver.h61
-rw-r--r--mcop/thread.cc169
-rw-r--r--mcop/thread.h375
-rw-r--r--mcop/tmpglobalcomm.cc82
-rw-r--r--mcop/trader_impl.cc345
-rw-r--r--mcop/type.cc31
-rw-r--r--mcop/type.h85
-rw-r--r--mcop/unixconnection.cc114
-rw-r--r--mcop/unixconnection.h43
-rw-r--r--mcop/unixserver.cc151
-rw-r--r--mcop/unixserver.h59
-rw-r--r--mcop/weakreference.h131
-rw-r--r--mcop_mt/Makefile.am9
-rw-r--r--mcop_mt/threads_posix.cc399
-rw-r--r--mcopidl/Makefile.am19
-rw-r--r--mcopidl/mcopidl.cc2645
-rw-r--r--mcopidl/namespace.cc208
-rw-r--r--mcopidl/namespace.h91
-rw-r--r--mcopidl/scanner.cc2090
-rw-r--r--mcopidl/scanner.ll183
-rw-r--r--mcopidl/yacc.cc1507
-rw-r--r--mcopidl/yacc.cc.h75
-rw-r--r--mcopidl/yacc.yy451
-rw-r--r--qtmcop/Makefile.am14
-rw-r--r--qtmcop/qiomanager.cc299
-rw-r--r--qtmcop/qiomanager.h106
-rw-r--r--qtmcop/qiomanager_p.h77
-rw-r--r--soundserver/FileInputStream.mcopclass5
-rw-r--r--soundserver/GSLPlayObject.mcopclass7
-rw-r--r--soundserver/Makefile.am122
-rw-r--r--soundserver/WavPlayObject.mcopclass7
-rw-r--r--soundserver/artscat.cc244
-rw-r--r--soundserver/artsd.cc376
-rw-r--r--soundserver/artsplay.cc77
-rw-r--r--soundserver/artsrec.cc194
-rw-r--r--soundserver/artsshell.cc671
-rw-r--r--soundserver/artsversion-new.h.in31
-rw-r--r--soundserver/artswrapper.c120
-rw-r--r--soundserver/cpuusage.cc137
-rw-r--r--soundserver/cpuusage.h53
-rw-r--r--soundserver/crashhandler.cc236
-rw-r--r--soundserver/crashhandler.h131
-rw-r--r--soundserver/fileinputstream_impl.cc193
-rw-r--r--soundserver/gslplayobject_impl.cc235
-rw-r--r--soundserver/kmedia2.idl242
-rw-r--r--soundserver/samplestorage_impl.cc202
-rw-r--r--soundserver/simplesoundserver_impl.cc453
-rw-r--r--soundserver/simplesoundserver_impl.h148
-rw-r--r--soundserver/soundserver.idl294
-rw-r--r--soundserver/soundserver_impl.cc90
-rw-r--r--soundserver/soundserver_impl.h46
-rw-r--r--soundserver/soundserverstartup_impl.cc99
-rw-r--r--soundserver/soundserverstartup_impl.h49
-rw-r--r--soundserver/soundserverv2_impl.cc386
-rw-r--r--soundserver/soundserverv2_impl.h71
-rw-r--r--soundserver/stdoutwriter_impl.cc52
-rw-r--r--soundserver/tradercheck.cc213
-rw-r--r--soundserver/tradercheck.h50
-rw-r--r--soundserver/wavplayobject_impl.cc172
-rw-r--r--tests/Makefile.am44
-rw-r--r--tests/README.test72
-rw-r--r--tests/remotetest.idl11
-rw-r--r--tests/test.h130
-rw-r--r--tests/testanyref.cc97
-rw-r--r--tests/testbuffer.cc139
-rw-r--r--tests/testchangenotify.cc195
-rw-r--r--tests/testdispatcher.cc41
-rw-r--r--tests/testflowsystem.cc83
-rw-r--r--tests/testifacerepo.cc84
-rw-r--r--tests/testnotification.cc146
-rw-r--r--tests/testremote.cc176
-rw-r--r--tests/testwrapper.cc211
-rw-r--r--tests/value.idl18
-rw-r--r--tests/value_impl.cc94
-rw-r--r--tests/wrapper.idl27
-rw-r--r--x11/Makefile.am29
-rw-r--r--x11/X11GlobalComm.mcopclass3
-rw-r--r--x11/x11globalcomm.idl30
-rw-r--r--x11/x11globalcomm_impl.cc184
360 files changed, 111698 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..127b32a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,347 @@
+NOTE! The GPL below is copyrighted by the Free Software Foundation, but
+the instance of code that it refers to (the arts programs) are copyrighted
+by the authors who actually wrote it.
+
+---------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/COPYING.LIB b/COPYING.LIB
new file mode 100644
index 0000000..3fb952c
--- /dev/null
+++ b/COPYING.LIB
@@ -0,0 +1,486 @@
+NOTE! The LGPL below is copyrighted by the Free Software Foundation, but
+the instance of code that it refers to (the arts libraries) are copyrighted
+by the authors who actually wrote it.
+
+---------------------------------------------------------------------------
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330
+ Boston, MA 02111-1307, USA.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 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.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..f8bad0c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,176 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/kde/bin', `/usr/local/kde/lib', etc. You can specify an
+installation prefix other than `/usr/local/kde' by giving `configure'
+the option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/Makefile.am.in b/Makefile.am.in
new file mode 100644
index 0000000..e47ac1d
--- /dev/null
+++ b/Makefile.am.in
@@ -0,0 +1,32 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1996-1997 Matthias Kalle Dalheimer (kalle@kde.org)
+# (C) 1997,1998 Stephan Kulow (coolo@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 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
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+include admin/deps.am
+
+$(top_srcdir)/acinclude.m4: $(top_srcdir)/libltdl/ltdl.m4
+
+AUTOMAKE_OPTIONS = foreign 1.6.1
+COMPILE_FIRST = libltdl mcop mcopidl flow mcop_mt soundserver artsc examples tests doc
+EXTRA_DIST = admin
+
+dist-hook:
+ cd $(top_distdir) && perl admin/am_edit -padmin
+
+#DIST_SUBDIRS = mcop mcop_mt mcopidl flow soundserver artsc examples tests doc
+# gmcop x11 qtmcop kde knotify message
diff --git a/Makefile.cvs b/Makefile.cvs
new file mode 100644
index 0000000..cf82c8d
--- /dev/null
+++ b/Makefile.cvs
@@ -0,0 +1,22 @@
+
+all:
+ @echo "This Makefile is only for the CVS repository"
+ @echo "This will be deleted before making the distribution"
+ @echo ""
+ @if test ! -d admin; then \
+ echo "Please recheckout this module!" ;\
+ echo "for cvs: use checkout once and after that update again" ;\
+ echo "for cvsup: checkout kde-common from cvsup and" ;\
+ echo " link kde-common/admin to ./admin" ;\
+ exit 1 ;\
+ fi
+ @if test ! -d libltdl; then \
+ echo "Please recheckout this module!" ;\
+ echo "for cvs: use checkout once and after that update again" ;\
+ echo "for cvsup: checkout kdelibs from cvsup and" ;\
+ echo " cp -a ../kdelibs/libltdl ./libltdl" ;\
+ exit 1 ;\
+ fi
+ $(MAKE) -f admin/Makefile.common cvs
+
+.SILENT:
diff --git a/arts.lsm b/arts.lsm
new file mode 100644
index 0000000..9fc82e1
--- /dev/null
+++ b/arts.lsm
@@ -0,0 +1,11 @@
+Begin4
+Title: arts
+Version: 1.5.10
+Entered-date: 2008-08-26
+Description: Soundserver for the K Desktop Environment (KDE)
+Keywords: KDE X11 desktop Qt
+Author: http://bugs.kde.org/ (KDE Bugtracking System)
+Primary-site: http://www.kde.org/download/
+Platforms: Unix, Qt
+Copying-policy: LGPL, Artistic
+End
diff --git a/artsc/Makefile.am b/artsc/Makefile.am
new file mode 100644
index 0000000..7487633
--- /dev/null
+++ b/artsc/Makefile.am
@@ -0,0 +1,32 @@
+AM_CFLAGS = -DARTSC_BACKEND='"$(libdir)/libartscbackend.la"'
+AM_CPPFLAGS = -DCOMPILING_ARTSC
+lib_LTLIBRARIES = libartsc.la libartscbackend.la libartsdsp.la libartsdsp_st.la
+FLOWLIBS = $(top_builddir)/flow/libartsflow.la
+
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop -I$(top_srcdir)/flow \
+ -I$(top_builddir)/flow -I$(top_builddir)/soundserver \
+ -I$(top_srcdir)/libltdl $(all_includes)
+
+bin_SCRIPTS = artsc-config artsdsp
+
+libartsdsp_la_SOURCES = artsdsp.c
+libartsdsp_la_LDFLAGS = -no-undefined -module $(all_libraries)
+libartsdsp_la_LIBADD = libartsc.la
+
+libartsdsp_st_la_SOURCES = artsc.c artsdsp.c
+libartsdsp_st_la_LDFLAGS = -no-undefined -module $(all_libraries)
+libartsdsp_st_la_LIBADD = $(top_builddir)/libltdl/libltdlc.la
+
+libartsc_la_SOURCES = artsc.c
+libartsc_la_LDFLAGS = -no-undefined $(USE_THREADS) $(all_libraries)
+libartsc_la_LIBADD = $(top_builddir)/libltdl/libltdlc.la $(LIBPTHREAD)
+
+libartscbackend_la_SOURCES = artscbackend.cc
+libartscbackend_la_LDFLAGS = -no-undefined -module $(KDE_RPATH) $(all_libraries)
+libartscbackend_la_LIBADD = $(FLOWLIBS) \
+ $(top_builddir)/soundserver/libsoundserver_idl.la
+
+artscincludedir = $(includedir)/artsc
+artscinclude_HEADERS = artsc.h artsc_export.h
+
+artscbackend.lo: $(top_builddir)/soundserver/soundserver.h ../flow/artsflow.h
diff --git a/artsc/artsc-config.in b/artsc/artsc-config.in
new file mode 100755
index 0000000..8b9b578
--- /dev/null
+++ b/artsc/artsc-config.in
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+usage()
+{
+ echo "usage: $0 [OPTIONS]"
+cat << EOH
+
+options:
+ [--libs]
+ [--cflags]
+ [--version]
+ [--arts-version]
+ [--arts-prefix]
+EOH
+ exit 1;
+}
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+libdl=@LIBDL@
+
+flags=""
+
+while test $# -gt 0
+do
+ case $1 in
+ --libs)
+ flags="$flags -L$libdir $libdl -lartsc @USE_THREADS@ @LIBPTHREAD@ @GLIB_LDFLAGS@ @GLIB_LIBADD@"
+ ;;
+ --cflags)
+ flags="$flags -I$includedir/artsc @GLIB_CFLAGS@"
+ ;;
+ --version)
+ echo 0.9.5
+ ;;
+ --arts-version)
+ echo @ARTS_VERSION@
+ ;;
+ --arts-prefix)
+ echo $prefix
+ ;;
+ *)
+ echo "$0: unknown option $1"
+ echo
+ usage
+ ;;
+ esac
+ shift
+done
+
+if test -n "$flags"
+then
+ echo $flags
+fi
diff --git a/artsc/artsc.c b/artsc/artsc.c
new file mode 100644
index 0000000..61a02b6
--- /dev/null
+++ b/artsc/artsc.c
@@ -0,0 +1,226 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsc.h"
+#include "ltdl.h"
+#include <assert.h>
+
+typedef int (*backend_init_ptr)();
+typedef int (*backend_suspend_ptr)();
+typedef int (*backend_suspended_ptr)();
+typedef void (*backend_free_ptr)();
+typedef arts_stream_t (*backend_play_stream_ptr)(int,int,int,const char*);
+typedef arts_stream_t (*backend_record_stream_ptr)(int,int,int,const char*);
+typedef void (*backend_close_stream_ptr)(arts_stream_t);
+typedef int (*backend_read_ptr)(arts_stream_t,void*,int);
+typedef int (*backend_write_ptr)(arts_stream_t,const void*,int);
+typedef int (*backend_stream_set_ptr)(arts_stream_t, arts_parameter_t, int);
+typedef int (*backend_stream_get_ptr)(arts_stream_t, arts_parameter_t);
+
+static struct arts_backend {
+ int available;
+ int refcnt;
+ lt_dlhandle handle;
+
+ backend_init_ptr init;
+ backend_suspend_ptr suspend;
+ backend_suspended_ptr suspended;
+ backend_free_ptr free;
+ backend_play_stream_ptr play_stream;
+ backend_record_stream_ptr record_stream;
+ backend_close_stream_ptr close_stream;
+ backend_read_ptr read;
+ backend_write_ptr write;
+ backend_stream_set_ptr stream_set;
+ backend_stream_get_ptr stream_get;
+} backend = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+
+static void arts_backend_ref()
+{
+ if(backend.refcnt == 0)
+ {
+ lt_dlinit();
+ backend.handle = lt_dlopen(ARTSC_BACKEND);
+
+ if(backend.handle)
+ {
+ backend.init = (backend_init_ptr)
+ lt_dlsym(backend.handle, "arts_backend_init");
+ backend.suspend = (backend_suspend_ptr)
+ lt_dlsym(backend.handle, "arts_backend_suspend");
+ backend.suspended = (backend_suspended_ptr)
+ lt_dlsym(backend.handle, "arts_backend_suspended");
+ backend.free = (backend_free_ptr)
+ lt_dlsym(backend.handle, "arts_backend_free");
+ backend.play_stream = (backend_play_stream_ptr)
+ lt_dlsym(backend.handle, "arts_backend_play_stream");
+ backend.record_stream = (backend_record_stream_ptr)
+ lt_dlsym(backend.handle, "arts_backend_record_stream");
+ backend.close_stream = (backend_close_stream_ptr)
+ lt_dlsym(backend.handle, "arts_backend_close_stream");
+ backend.write = (backend_write_ptr)
+ lt_dlsym(backend.handle, "arts_backend_write");
+ backend.read = (backend_read_ptr)
+ lt_dlsym(backend.handle, "arts_backend_read");
+ backend.stream_set = (backend_stream_set_ptr)
+ lt_dlsym(backend.handle, "arts_backend_stream_set");
+ backend.stream_get = (backend_stream_get_ptr)
+ lt_dlsym(backend.handle, "arts_backend_stream_get");
+ }
+
+ if(backend.handle && backend.init && backend.free && backend.play_stream
+ && backend.record_stream && backend.close_stream && backend.write
+ && backend.read && backend.stream_set && backend.stream_get
+ && backend.suspend)
+ backend.available = 1;
+ else
+ backend.available = 0;
+ }
+ backend.refcnt++;
+}
+
+static void arts_backend_release()
+{
+ assert(backend.refcnt > 0);
+ backend.refcnt--;
+ if(backend.refcnt == 0)
+ {
+ if(backend.available)
+ {
+ backend.available = 0;
+
+ if(backend.handle) lt_dlclose(backend.handle);
+ }
+ lt_dlexit();
+ }
+}
+
+int arts_init()
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ arts_backend_ref();
+ if(backend.available) rc = backend.init();
+
+ /* init failed: the user may not call other arts_xxx functions now */
+ if(rc < 0) arts_backend_release();
+
+ return rc;
+}
+
+int arts_suspend()
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ if(backend.available) rc = backend.suspend();
+ return rc;
+}
+
+int arts_suspended()
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ if(backend.available && backend.suspended) rc = backend.suspended();
+ return rc;
+}
+
+void arts_free()
+{
+ if(backend.available)
+ {
+ backend.free();
+ arts_backend_release();
+ }
+}
+
+arts_stream_t arts_play_stream(int rate, int bits, int channels, const char *name)
+{
+ arts_stream_t rc = 0;
+
+ if(backend.available) rc = backend.play_stream(rate,bits,channels,name);
+ return rc;
+}
+
+arts_stream_t arts_record_stream(int rate, int bits, int channels, const char *name)
+{
+ arts_stream_t rc = 0;
+
+ if(backend.available) rc = backend.record_stream(rate,bits,channels,name);
+ return rc;
+}
+
+void arts_close_stream(arts_stream_t stream)
+{
+ if(backend.available) backend.close_stream(stream);
+}
+
+int arts_read(arts_stream_t stream, void *buffer, int count)
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ if(backend.available) rc = backend.read(stream,buffer,count);
+ return rc;
+}
+
+int arts_write(arts_stream_t stream, const void *buffer, int count)
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ if(backend.available) rc = backend.write(stream,buffer,count);
+ return rc;
+}
+
+int arts_stream_set(arts_stream_t stream, arts_parameter_t param, int value)
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ if(backend.available) rc = backend.stream_set(stream,param,value);
+ return rc;
+}
+
+int arts_stream_get(arts_stream_t stream, arts_parameter_t param)
+{
+ int rc = ARTS_E_NOBACKEND;
+
+ if(backend.available) rc = backend.stream_get(stream,param);
+ return rc;
+}
+
+const char *arts_error_text(int errorcode)
+{
+ switch(errorcode) {
+ case 0:
+ return "success";
+ case ARTS_E_NOSERVER:
+ return "can't connect to aRts soundserver";
+ case ARTS_E_NOBACKEND:
+ return "loading the aRts backend \""
+ ARTSC_BACKEND "\" failed";
+ case ARTS_E_NOIMPL:
+ return "this aRts function is not yet implemented";
+ case ARTS_E_NOINIT:
+ return "need to use arts_init() before using other functions";
+ case ARTS_E_NOSTREAM:
+ return "you passed no valid aRts stream to a function";
+ }
+ return "unknown arts error happened";
+}
diff --git a/artsc/artsc.h b/artsc/artsc.h
new file mode 100644
index 0000000..5cdf8f1
--- /dev/null
+++ b/artsc/artsc.h
@@ -0,0 +1,246 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTSC_H
+#define ARTSC_H
+
+#include "artsc_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @libdoc aRts plain C API
+ *
+ * The aRts plain C API aims at easily writing/porting plain C apps to the
+ * arts sound server. What is provided is streaming functionality, in a
+ * blocking way. So for most apps, you simply remove the few system calls
+ * that deal with your audio device, and replace them with the appropriate
+ * arts calls.
+ */
+
+/**
+ * the type of streams (simply treat these as black boxes)
+ */
+typedef void *arts_stream_t;
+
+/* error codes */
+
+#define ARTS_E_NOSERVER ( -1 )
+#define ARTS_E_NOBACKEND ( -2 )
+#define ARTS_E_NOSTREAM ( -3 )
+#define ARTS_E_NOINIT ( -4 )
+#define ARTS_E_NOIMPL ( -5 )
+
+/**
+ * the values for stream parameters
+ *
+ * @see arts_parameter_t
+ */
+enum arts_parameter_t_enum {
+ ARTS_P_BUFFER_SIZE = 1,
+ ARTS_P_BUFFER_TIME = 2,
+ ARTS_P_BUFFER_SPACE = 3,
+ ARTS_P_SERVER_LATENCY = 4,
+ ARTS_P_TOTAL_LATENCY = 5,
+ ARTS_P_BLOCKING = 6,
+ ARTS_P_PACKET_SIZE = 7,
+ ARTS_P_PACKET_COUNT = 8,
+ ARTS_P_PACKET_SETTINGS = 9
+};
+
+/**
+ * parameters for streams
+ *
+ * @li ARTS_P_BUFFER_SIZE (rw)
+ * The size of the internal buffers used for streaming to the server - this
+ * directly affects the latency that will occur. If you never set it
+ * explicitly, this value defaults to at least 65536 (64kb). Generally,
+ * it is important to know that the server itself gives some constraints
+ * which makes buffer sizes below a certain value impossible. So setting
+ * this parameter will always result in either getting what you wanted,
+ * or a larger streaming buffer due to server limitations.
+ *
+ * @li ARTS_P_BUFFER_TIME (rw)
+ * The time the buffer used for streaming to the server takes to play in
+ * milliseconds. This is just a more human readable method to set the buffer
+ * size, so setting ARTS_P_BUFFER_SIZE affects this parameter and the other
+ * way round. As aRts chooses reasonable buffer sizes for streaming (rather
+ * 3*16kb than 40234 bytes), setting this parameter will often end up with
+ * a slightly larger value than you requested.
+ *
+ * @li ARTS_P_BUFFER_SPACE (r)
+ * The amount of bytes that can be read/written without blocking (depending
+ * whether this is a record or play stream). As requesting this parameter
+ * does a few system calls (but no remote invocation) to verify that it is
+ * up-to-date, don't overuse it.
+ *
+ * @li ARTS_P_SERVER_LATENCY (r)
+ * The amount of latency the server creates (due to hardware buffering)
+ * in milliseconds.
+ *
+ * @li ARTS_P_TOTAL_LATENCY (r)
+ * The overall latency in milliseconds it takes (at most), from the time
+ * when you write a byte into a stream, until it gets played on the
+ * soundcard. This is simply a shortcut to the sum of ARTS_P_BUFFER_TIME
+ * and ARTS_P_SERVER_LATENCY.
+ *
+ * @li ARTS_P_BLOCKING (rw)
+ * If this parameter is 1 (the default), arts_read/arts_write will block
+ * when not all data can be read/written successfully, and wait until it
+ * works. If this parameter is 0, arts_read/arts_write will return
+ * the number of successfully read/written bytes immediately.
+ *
+ * @li ARTS_P_PACKET_SIZE (r)
+ * This returns the size of the packets used for buffering. The optimal
+ * size for arts_stream_write is always writing one packet. The buffering of
+ * streams works with audio packets. So the ARTS_P_BUFFER_SIZE parameter of
+ * streams (which specifies how many bytes of a stream are prebuffered),
+ * really consists of (ARTS_P_PACKET_SIZE) * (ARTS_P_PACKET_COUNT).
+ *
+ * @li ARTS_P_PACKET_COUNT (r)
+ * This returns the number of the packets are used for buffering. See
+ * ARTS_P_PACKET_SIZE for more.
+ *
+ * @li ARTS_P_PACKET_SETTINGS (rw)
+ * This is a way to configure packet size & packet count at the same time.
+ * The format is 0xCCCCSSSS, where 2^SSSS is the packet size, and CCCC is
+ * the packet count. Note that when writing this, you don't necessarily
+ * get the settings you requested.
+ */
+typedef enum arts_parameter_t_enum arts_parameter_t;
+
+/**
+ * initializes the aRts C API, and connects to the sound server
+ *
+ * @return 0 if everything is all right, an error code otherwise
+ */
+
+ARTSC_EXPORT int arts_init(void);
+
+/**
+ * disconnects from the sound server and frees the aRts C API internals
+ */
+ARTSC_EXPORT void arts_free(void);
+
+/**
+ * asks aRtsd to free the DSP device and return 1 if it was successful,
+ * 0 if there were active non-suspendable modules
+ */
+ARTSC_EXPORT int arts_suspend(void);
+
+/**
+ * asks aRtsd if the DSP device is free and return 1 if it is,
+ * 0 if not
+ */
+ARTSC_EXPORT int arts_suspended(void);
+
+
+/**
+ * converts an error code to a human readable error message
+ *
+ * @param errorcode the errorcode (from another arts function that failed)
+ * @returns a text string with the error message
+ */
+ARTSC_EXPORT const char *arts_error_text(int errorcode);
+
+/**
+ * open a stream for playing
+ *
+ * @param rate the sampling rate (something like 44100)
+ * @param bits how many bits each sample has (8 or 16)
+ * @param channels how many channels, 1 is mono, 2 is stereo
+ * @param name the name of the stream (these will be used so that the user can
+ * assign streams to effects/mixer channels and similar)
+ *
+ * @return a stream
+ */
+ARTSC_EXPORT arts_stream_t arts_play_stream(int rate, int bits, int channels, const char *name);
+
+/**
+ * open a stream for recording
+ *
+ * @param rate the sampling rate (something like 44100)
+ * @param bits how many bits each sample has (8 or 16)
+ * @param channels how many channels, 1 is mono, 2 is stereo
+ * @param name the name of the stream (these will be used so that the user can
+ * assign streams to effects/mixer channels and similar)
+ *
+ * @return a stream
+ */
+ARTSC_EXPORT arts_stream_t arts_record_stream(int rate, int bits, int channels, const char *name);
+
+/**
+ * close a stream
+ */
+ARTSC_EXPORT void arts_close_stream(arts_stream_t stream);
+
+/**
+ * read samples from stream
+ *
+ * @param stream a previously opened record stream
+ * @param buffer a buffer with sample data
+ * @param count the number of bytes contained in the buffer
+ *
+ * @returns number of read bytes on success or error code
+ */
+ARTSC_EXPORT int arts_read(arts_stream_t stream, void *buffer, int count);
+
+/**
+ * write samples to to stream
+ *
+ * @param stream a previously opened play stream
+ * @param buffer a buffer with sample data
+ * @param count the number of bytes contained in the buffer
+ *
+ * @returns number of written bytes on success or error code
+ */
+ARTSC_EXPORT int arts_write(arts_stream_t stream, const void *buffer, int count);
+
+/**
+ * configure a parameter of a stream
+ *
+ * @param stream an opened record or play stream
+ * @param parameter the parameter you want to modify
+ * @param value the new value
+ *
+ * @returns the new value of the parameter (which may or may not be the value
+ * you wanted to have), or an error code if something went wrong
+ */
+ARTSC_EXPORT int arts_stream_set(arts_stream_t stream, arts_parameter_t param, int value);
+
+/**
+ * query a parameter of a stream
+ *
+ * @param stream an opened record or play stream
+ * @param parameter the parameter you want to query
+ *
+ * @returns the value of the parameter, or an error code
+ */
+ARTSC_EXPORT int arts_stream_get(arts_stream_t stream, arts_parameter_t param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARTSC_H */
diff --git a/artsc/artsc_export.h.in b/artsc/artsc_export.h.in
new file mode 100644
index 0000000..85fd6ef
--- /dev/null
+++ b/artsc/artsc_export.h.in
@@ -0,0 +1,52 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2002-2003 KDE Team
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ARTSC_EXPORT_H
+#define ARTSC_EXPORT_H
+
+#undef __KDE_HAVE_GCC_VISIBILITY
+/**
+ * The ARTS_NO_EXPORT macro marks the symbol of the given variable
+ * to be hidden. A hidden symbol is stripped during the linking step,
+ * so it can't be used from outside the resulting library, which is similar
+ * to static. However, static limits the visibility to the current
+ * compilation unit. hidden symbols can still be used in multiple compilation
+ * units.
+ *
+ * \code
+ * int ARTSC_NO_EXPORT foo;
+ * int ARTSC_EXPORT bar;
+ * \end
+ */
+
+#if defined(__KDE_HAVE_GCC_VISIBILITY)
+/* Visibility is available for GCC newer than 3.4.
+ * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9283
+ */
+#define ARTSC_NO_EXPORT __attribute__ ((visibility("hidden")))
+#define ARTSC_EXPORT __attribute__ ((visibility("default")))
+#elif defined(_WIN32)
+#define ARTSC_NO_EXPORT
+#define ARTSC_EXPORT __declspec(dllexport)
+#else
+#define ARTSC_NO_EXPORT
+#define ARTSC_EXPORT
+#endif
+
+#endif /* ARTSC_EXPORTS */
diff --git a/artsc/artscbackend.cc b/artsc/artscbackend.cc
new file mode 100644
index 0000000..a9f3a91
--- /dev/null
+++ b/artsc/artscbackend.cc
@@ -0,0 +1,805 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+ 2001 Matthias Kretz
+ kretz@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsc.h"
+#include "soundserver.h"
+#include "stdsynthmodule.h"
+
+#include <iostream>
+#include <algorithm>
+#include <queue>
+
+#include <stdio.h>
+#include <cstring>
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+#include <assert.h>
+#include "arts_export.h"
+
+#define arts_backend_debug(x) ;
+
+using namespace std;
+using namespace Arts;
+
+/**
+ * Base class for streams
+ */
+class Stream
+{
+protected:
+ SoundServer server;
+ float serverBufferTime;
+
+ bool _finished, isAttached;
+ int _samplingRate, _bits, _channels, pos;
+ string _name;
+ queue< DataPacket<mcopbyte>* > streamqueue;
+
+ int packetCount, packetCapacity;
+ int blockingIO;
+
+ /**
+ * returns the amount of bytes that will be played in a given amount of
+ * time in milliseconds
+ */
+ int timeToBytes(float time)
+ {
+ float playSpeed = _channels * _samplingRate * _bits / 8;
+ return (int)(playSpeed * (time / 1000.0));
+ }
+
+ /**
+ * returns the time in milliseconds it takes with the current parameters
+ * to play a given amount of bytes
+ */
+ float bytesToTime(int size)
+ {
+ float playSpeed = _channels * _samplingRate * _bits / 8;
+ return (1000.0 * ((float)size) / playSpeed);
+ }
+
+ int bufferSize() {
+ return packetCount * packetCapacity;
+ }
+
+ float bufferTime() {
+ return bytesToTime(bufferSize());
+ }
+
+ int bufferSpace() {
+ int space = 0;
+
+ attach();
+
+ /* make sure that our information is up-to-date */
+ Dispatcher::the()->ioManager()->processOneEvent(false);
+
+ if(!streamqueue.empty())
+ {
+ space += packetCapacity - pos; /* the first, half filled packet */
+
+ if(streamqueue.size() > 1) /* and the other, empty packets */
+ space += (streamqueue.size()-1)*packetCapacity;
+ }
+ return space;
+ }
+
+ int setBufferSize(int size)
+ {
+ /* don't change sizes when already streaming */
+ if(isAttached)
+ return ARTS_E_NOIMPL;
+
+ /*
+ * these parameters are usually a bad idea ;-) however we have to start
+ * somewhere, and maybe in two years, with a highly optimized kernel
+ * this is possible - for now, don't request the impossible or don't
+ * complain if it doesn't work
+ */
+ packetCount = 3;
+ packetCapacity = 128;
+
+ /*
+ * - do not configure stream buffers smaller than the server
+ * recommended value
+ * - try to get more or less close to the value the application
+ * wants
+ */
+ int needSize = max(size, timeToBytes(server.minStreamBufferTime()));
+
+ while(bufferSize() < needSize)
+ {
+ packetCount++;
+ if(packetCount == 8)
+ {
+ packetCount /= 2;
+ packetCapacity *= 2;
+ }
+ }
+
+ return bufferSize();
+ }
+
+ int packetSettings()
+ {
+ int settings = 0;
+
+ int cap = packetCapacity;
+ while(cap > 1)
+ {
+ settings++;
+ cap /= 2;
+ }
+
+ settings |= packetCount << 16;
+ return settings;
+ }
+
+ int setPacketSettings(int settings)
+ {
+ /* don't change sizes when already streaming */
+ if(isAttached)
+ return ARTS_E_NOIMPL;
+
+ packetCount = settings >> 16;
+
+ packetCapacity = 1;
+ int c = settings & 0xffff;
+ while(c > 0) {
+ packetCapacity *= 2;
+ c--;
+ }
+
+ /*
+ * - do not configure stream buffers smaller than the server
+ * recommended value
+ * - keep the packetSize the applications specified
+ */
+ int needSize = timeToBytes(server.minStreamBufferTime());
+
+ while(bufferSize() < needSize)
+ packetCount++;
+
+ return packetSettings();
+ }
+
+ /**
+ * the stream has to attach itself
+ */
+ virtual void attach() = 0;
+
+public:
+ Stream(SoundServer server, int rate, int bits, int channels,
+ string name) : server(server), _finished(false), isAttached(false),
+ _samplingRate(rate), _bits(bits), _channels(channels), pos(0),
+ _name(name)
+ {
+ serverBufferTime = server.serverBufferTime();
+ stream_set(ARTS_P_BUFFER_SIZE,64*1024);
+ stream_set(ARTS_P_BLOCKING,1);
+ }
+ virtual ~Stream()
+ {
+ //
+ }
+
+ virtual int stream_set(arts_parameter_t param, int value)
+ {
+ int result;
+
+ switch(param) {
+ case ARTS_P_BUFFER_SIZE:
+ return setBufferSize(value);
+
+ case ARTS_P_BUFFER_TIME:
+ result = setBufferSize(timeToBytes(value));
+ if(result < 0) return result;
+ return (int)bufferTime();
+
+ case ARTS_P_PACKET_SETTINGS:
+ return setPacketSettings(value);
+
+ case ARTS_P_BLOCKING:
+ if(value != 0 && value != 1) return ARTS_E_NOIMPL;
+
+ blockingIO = value;
+ return blockingIO;
+ /*
+ * maybe ARTS_P_TOTAL_LATENCY _could_ be made writeable, the
+ * others are of course useless
+ */
+ case ARTS_P_BUFFER_SPACE:
+ case ARTS_P_SERVER_LATENCY:
+ case ARTS_P_TOTAL_LATENCY:
+ case ARTS_P_PACKET_SIZE:
+ case ARTS_P_PACKET_COUNT:
+ return ARTS_E_NOIMPL;
+ }
+ return ARTS_E_NOIMPL;
+ }
+
+ virtual int stream_get(arts_parameter_t param)
+ {
+ switch(param) {
+ case ARTS_P_BUFFER_SIZE:
+ return bufferSize();
+
+ case ARTS_P_BUFFER_TIME:
+ return (int)bufferTime();
+
+ case ARTS_P_BUFFER_SPACE:
+ return bufferSpace();
+
+ case ARTS_P_PACKET_SETTINGS:
+ return packetSettings();
+
+ case ARTS_P_SERVER_LATENCY:
+ return (int)serverBufferTime;
+
+ case ARTS_P_TOTAL_LATENCY:
+ return stream_get(ARTS_P_SERVER_LATENCY)
+ + stream_get(ARTS_P_BUFFER_TIME);
+
+ case ARTS_P_BLOCKING:
+ return blockingIO;
+
+ case ARTS_P_PACKET_SIZE:
+ return packetCapacity;
+
+ case ARTS_P_PACKET_COUNT:
+ return packetCount;
+ }
+ return ARTS_E_NOIMPL;
+ }
+
+ virtual int write(const mcopbyte * /*data*/, int /*size*/)
+ {
+ return ARTS_E_NOIMPL;
+ }
+
+ virtual int read(mcopbyte * /*data*/, int /*size*/)
+ {
+ return ARTS_E_NOIMPL;
+ }
+
+ virtual void close() = 0;
+
+ int suspend()
+ {
+ if(isAttached)
+ {
+ return server.suspend();
+ }
+ return 0;
+ }
+
+ int suspended()
+ {
+ if(isAttached)
+ {
+ return 0;
+ }
+ return server.suspended();
+ }
+};
+
+class Receiver : public ByteSoundReceiver_skel,
+ public StdSynthModule,
+ virtual public Stream
+{
+ /*
+ * FIXME: bsWrapper is a more or less ugly trick to be able to use
+ * this object although not using smartwrappers to access it
+ */
+ ByteSoundReceiver bsWrapper;
+
+protected:
+ virtual void attach()
+ {
+ if(!isAttached)
+ {
+ isAttached = true;
+
+ server.attachRecorder(bsWrapper);
+ start();
+
+ /*
+ * TODO: this processOneEvent looks a bit strange here... it is
+ * there since StdIOManager does block 5 seconds on the first
+ * arts_write if it isn't - although notifications are pending
+ *
+ * Probably the real solution is to rewrite the
+ * StdIOManager::processOneEvent function. (And maybe drop the
+ * assumption that aRts will not block when an infinite amount
+ * of notifications is pending - I mean: will it ever happen?)
+ */
+ Dispatcher::the()->ioManager()->processOneEvent(false);
+ }
+ }
+
+public:
+ Receiver(SoundServer server, int rate, int bits, int channels,
+ string name) : Stream( server, rate, bits, channels, name)
+ {
+ bsWrapper = ByteSoundReceiver::_from_base(this);
+ }
+
+ virtual ~Receiver() {
+ //
+ }
+
+ long samplingRate() { return _samplingRate; }
+ long channels() { return _channels; }
+ long bits() { return _bits; }
+ bool finished() { return _finished; }
+ string title() { return _name; }
+
+ void process_indata(DataPacket<mcopbyte> *packet)
+ {
+ streamqueue.push(packet);
+ }
+
+ void close()
+ {
+ if(isAttached)
+ {
+ /* remove all packets from the streamqueue */
+ while(!streamqueue.empty())
+ {
+ DataPacket<mcopbyte> *packet = streamqueue.front();
+ packet->processed();
+ streamqueue.pop();
+ }
+
+ server.detachRecorder(bsWrapper);
+ }
+ // similar effect like "delete this;"
+ bsWrapper = ByteSoundReceiver::null();
+ }
+
+ int read(mcopbyte *data, int size)
+ {
+ attach();
+
+ int remaining = size;
+ while(remaining)
+ {
+ if(blockingIO)
+ {
+ /* C API blocking style read */
+ while(streamqueue.empty())
+ Dispatcher::the()->ioManager()->processOneEvent(true);
+ }
+ else
+ {
+ /* non blocking I/O */
+ if(streamqueue.empty())
+ Dispatcher::the()->ioManager()->processOneEvent(false);
+
+ /* still no more packets to read? */
+ if(streamqueue.empty())
+ return size - remaining;
+ }
+
+ /* get a packet */
+ DataPacket<mcopbyte> *packet = streamqueue.front();
+
+ /* copy some data from there */
+ int tocopy = min(remaining,packet->size-pos);
+ memcpy(data,&packet->contents[pos],tocopy);
+ pos += tocopy;
+ data += tocopy;
+ remaining -= tocopy;
+
+ /* have we read the whole packet? then get rid of it */
+ if(pos == packet->size)
+ {
+ packet->processed();
+ streamqueue.pop();
+ pos = 0;
+ }
+ }
+
+ /* no possible error conditions */
+ return size;
+ }
+};
+
+class Sender : public ByteSoundProducerV2_skel,
+ public StdSynthModule,
+ virtual public Stream
+{
+ /*
+ * FIXME: bsWrapper is a more or less ugly trick to be able to use
+ * this object although not using smartwrappers to access it
+ */
+ ByteSoundProducerV2 bsWrapper;
+
+protected:
+ virtual void attach()
+ {
+ if(!isAttached)
+ {
+ isAttached = true;
+
+ server.attach(bsWrapper);
+ start();
+
+ /*
+ * TODO: this processOneEvent looks a bit strange here... it is
+ * there since StdIOManager does block 5 seconds on the first
+ * arts_write if it isn't - although notifications are pending
+ *
+ * Probably the real solution is to rewrite the
+ * StdIOManager::processOneEvent function. (And maybe drop the
+ * assumption that aRts will not block when an infinite amount
+ * of notifications is pending - I mean: will it ever happen?)
+ */
+ Dispatcher::the()->ioManager()->processOneEvent(false);
+ }
+ }
+
+public:
+ Sender(SoundServer server, int rate, int bits, int channels,
+ string name) : Stream( server, rate, bits, channels, name)
+ {
+ bsWrapper = ByteSoundProducerV2::_from_base(this);
+ }
+
+ virtual ~Sender() {
+ //
+ }
+
+ long samplingRate() { return _samplingRate; }
+ long channels() { return _channels; }
+ long bits() { return _bits; }
+ bool finished() { return _finished; }
+ string title() { return _name; }
+
+ void streamStart()
+ {
+ /*
+ * start streaming
+ */
+ outdata.setPull(packetCount, packetCapacity);
+ }
+
+ void request_outdata(DataPacket<mcopbyte> *packet)
+ {
+ streamqueue.push(packet);
+ }
+
+ void close()
+ {
+ if(isAttached)
+ {
+ if(pos != 0)
+ {
+ /* send the last half-filled packet */
+ DataPacket<mcopbyte> *packet = streamqueue.front();
+ packet->size = pos;
+ packet->send();
+ streamqueue.pop();
+ }
+ outdata.endPull();
+
+ /* remove all packets from the streamqueue */
+ while(!streamqueue.empty())
+ {
+ DataPacket<mcopbyte> *packet = streamqueue.front();
+ packet->size = 0;
+ packet->send();
+ streamqueue.pop();
+ }
+
+ server.detach(bsWrapper);
+ }
+ // similar effect like "delete this;"
+ Arts::ByteSoundProducerV2_base* x = _copy();
+ bsWrapper = ByteSoundProducerV2::null();
+ x->_release();
+ }
+
+ int write(const mcopbyte *data, int size)
+ {
+ attach();
+
+ int remaining = size;
+ while(remaining)
+ {
+ if(blockingIO)
+ {
+ /* C API blocking style write */
+ /* we're not waiting for any data here, but rather for
+ * DataPackets that we can fill */
+ while(streamqueue.empty())
+ Dispatcher::the()->ioManager()->processOneEvent(true);
+ }
+ else
+ {
+ /* non blocking I/O */
+ if(streamqueue.empty())
+ Dispatcher::the()->ioManager()->processOneEvent(false);
+
+ /* still no more space to write? */
+ if(streamqueue.empty())
+ return size - remaining;
+ }
+
+ /* get a packet */
+ DataPacket<mcopbyte> *packet = streamqueue.front();
+
+ /* copy some data there */
+ int tocopy = min(remaining,packetCapacity-pos);
+ memcpy(&packet->contents[pos],data,tocopy);
+ pos += tocopy;
+ data += tocopy;
+ remaining -= tocopy;
+
+ /* have we filled up the packet? then send it */
+ if(pos == packetCapacity)
+ {
+ packet->size = packetCapacity;
+ packet->send();
+ streamqueue.pop();
+ pos = 0;
+ }
+ }
+
+ /* no possible error conditions */
+ return size;
+ }
+};
+
+class ArtsCApi {
+protected:
+ static ArtsCApi *instance;
+ int refcnt;
+
+ Dispatcher dispatcher;
+ SoundServer server;
+
+ ArtsCApi() : refcnt(1), server(Reference("global:Arts_SoundServer"))
+ {
+ //
+ }
+
+public:
+// C Api commands
+ int init() {
+ if(server.isNull())
+ return ARTS_E_NOSERVER;
+
+ return 0;
+ }
+
+ int suspend() {
+ if(!server.isNull())
+ return server.suspend()? 1:0;
+ return ARTS_E_NOSERVER;
+ }
+
+ int suspended() {
+ if(!server.isNull())
+ return server.suspended()? 1:0;
+ return ARTS_E_NOSERVER;
+ }
+
+ void free() {
+ // nothing to do
+ }
+
+ arts_stream_t play_stream(int rate, int bits, int channels, const char *name)
+ {
+ if(server.isNull())
+ return 0;
+
+ return (arts_stream_t)static_cast<Stream *>(new Sender(server,rate,bits,channels,name));
+ }
+
+ arts_stream_t record_stream(int rate, int bits, int channels, const char *name)
+ {
+ if(server.isNull())
+ return 0;
+
+ return (arts_stream_t)static_cast<Stream *>(new Receiver(server,rate,bits,channels,name));
+ }
+
+ void close_stream(arts_stream_t stream)
+ {
+ if(server.isNull())
+ return;
+
+ if(!stream)
+ return;
+
+ static_cast<Stream *>(stream)->close();
+ }
+
+ int write(arts_stream_t stream, const void *data, int size)
+ {
+ if(server.isNull())
+ return ARTS_E_NOSERVER;
+
+ if(!stream)
+ return ARTS_E_NOSTREAM;
+
+ return static_cast<Stream *>(stream)->write((const mcopbyte *)data,size);
+ }
+
+ int read(arts_stream_t stream, void *data, int size)
+ {
+ if(server.isNull())
+ return ARTS_E_NOSERVER;
+
+ if(!stream)
+ return ARTS_E_NOSTREAM;
+
+ return static_cast<Stream *>(stream)->read((mcopbyte *)data,size);
+ }
+
+ int stream_set(arts_stream_t stream, arts_parameter_t param, int value)
+ {
+ if(server.isNull())
+ return ARTS_E_NOSERVER;
+
+ if(!stream)
+ return ARTS_E_NOSTREAM;
+
+ return static_cast<Stream *>(stream)->stream_set(param,value);
+ }
+
+ int stream_get(arts_stream_t stream, arts_parameter_t param)
+ {
+ if(server.isNull())
+ return ARTS_E_NOSERVER;
+
+ if(!stream)
+ return ARTS_E_NOSTREAM;
+
+ return static_cast<Stream *>(stream)->stream_get(param);
+ }
+
+// allocation and freeing of the class
+ static ArtsCApi *the() {
+ return instance;
+ }
+ static void ref() {
+ if(!instance)
+ instance = new ArtsCApi();
+ else
+ instance->refcnt++;
+ }
+ static void release() {
+ assert(instance);
+ assert(instance->refcnt > 0);
+ instance->refcnt--;
+ if(instance->refcnt == 0)
+ {
+ delete instance;
+ instance = 0;
+ }
+ }
+};
+
+//----------------------------- static members -------------------------------
+
+ArtsCApi *ArtsCApi::instance = 0;
+
+//------------------ wrappers from C to C++ class ----------------------------
+
+extern "C" ARTSC_EXPORT int arts_backend_init()
+{
+ arts_backend_debug("arts_backend_init");
+ ArtsCApi::ref();
+
+ // if init fails, don't expect free, and don't expect that the user
+ // continues using other API functions
+ int rc = ArtsCApi::the()->init();
+ if(rc < 0) ArtsCApi::release();
+ return rc;
+}
+
+extern "C" ARTSC_EXPORT int arts_backend_suspend()
+{
+ if(!ArtsCApi::the()) return ARTS_E_NOINIT;
+ arts_backend_debug("arts_backend_suspend");
+ return ArtsCApi::the()->suspend();
+}
+
+extern "C" ARTSC_EXPORT int arts_backend_suspended()
+{
+ if(!ArtsCApi::the()) return ARTS_E_NOINIT;
+ arts_backend_debug("arts_backend_suspended");
+ return ArtsCApi::the()->suspended();
+}
+
+extern "C" ARTSC_EXPORT void arts_backend_free()
+{
+ if(!ArtsCApi::the()) return;
+
+ arts_backend_debug("arts_backend_free");
+ ArtsCApi::the()->free();
+ ArtsCApi::release();
+}
+
+extern "C" ARTSC_EXPORT arts_stream_t arts_backend_play_stream(int rate, int bits, int channels, const char *name)
+{
+ if(!ArtsCApi::the()) return 0;
+
+ arts_backend_debug("arts_backend_play_stream");
+ return ArtsCApi::the()->play_stream(rate,bits,channels,name);
+}
+
+extern "C" ARTSC_EXPORT arts_stream_t arts_backend_record_stream(int rate, int bits, int channels, const char *name)
+{
+ if(!ArtsCApi::the()) return 0;
+
+ arts_backend_debug("arts_backend_record_stream");
+ return ArtsCApi::the()->record_stream(rate,bits,channels,name);
+}
+
+extern "C" ARTSC_EXPORT void arts_backend_close_stream(arts_stream_t stream)
+{
+ if(!ArtsCApi::the()) return;
+
+ arts_backend_debug("arts_backend_close_stream");
+ ArtsCApi::the()->close_stream(stream);
+}
+
+extern "C" ARTSC_EXPORT int arts_backend_read(arts_stream_t stream, void *buffer, int count)
+{
+ if(!ArtsCApi::the()) return ARTS_E_NOINIT;
+
+ arts_backend_debug("arts_backend_read");
+ return ArtsCApi::the()->read(stream,buffer,count);
+}
+
+extern "C" ARTSC_EXPORT int arts_backend_write(arts_stream_t stream, const void *buffer,
+ int count)
+{
+ if(!ArtsCApi::the()) return ARTS_E_NOINIT;
+
+ arts_backend_debug("arts_backend_write");
+ return ArtsCApi::the()->write(stream,buffer,count);
+}
+
+extern "C" ARTSC_EXPORT int arts_backend_stream_set(arts_stream_t stream,
+ arts_parameter_t param, int value)
+{
+ if(!ArtsCApi::the()) return ARTS_E_NOINIT;
+
+ arts_backend_debug("arts_stream_set");
+ return ArtsCApi::the()->stream_set(stream,param,value);
+}
+
+extern "C" ARTSC_EXPORT int arts_backend_stream_get(arts_stream_t stream,
+ arts_parameter_t param)
+{
+ if(!ArtsCApi::the()) return ARTS_E_NOINIT;
+
+ arts_backend_debug("arts_stream_get");
+ return ArtsCApi::the()->stream_get(stream,param);
+}
diff --git a/artsc/artsdsp.c b/artsc/artsdsp.c
new file mode 100644
index 0000000..368b15f
--- /dev/null
+++ b/artsc/artsdsp.c
@@ -0,0 +1,675 @@
+/* Evil evil evil hack to get OSS apps to cooperate with artsd
+ * This is based on the original esddsp, which esd uses to do the same.
+ *
+ * Copyright (C) 1998 Manish Singh <yosh@gimp.org>
+ * Copyright (C) 2000 Stefan Westerfeld <stefan@space.twc.de> (aRts port)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#define _GNU_SOURCE 1
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/soundcard.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+/* #include <sys/mman.h> */
+#include <fcntl.h>
+
+#include <artsc.h>
+#include <dlfcn.h>
+
+#include "arts_export.h"
+/*
+ * NOTE:
+ *
+ * To truly support non-blocking I/O, there is some stuff missing. Namely,
+ * select should be trapped and redirected, as well as the means for making
+ * a stream non-blocking and so on. Maybe poll, too.
+ *
+ * Currently, only apps that are doing blocking I/O will probably work right.
+ */
+
+/**
+ * the stream status: sndfd is -1 when unused, otherwise it is a useless fd
+ * which points to /dev/null, to ensure compatibility with more weird
+ * operations on streams
+ *
+ * settings contains what has already been set (speed, bits, channels), and
+ * is 7 when all of these are true
+ *
+ * stream contains an aRts stream or 0
+ */
+static int sndfd = -1;
+static int settings;
+static int arts_init_done = 0;
+static arts_stream_t stream = 0;
+static arts_stream_t record_stream = 0;
+static int bits = 0;
+static int speed = 0;
+static int channels = 0;
+static int frags;
+
+#if defined(HAVE_IOCTL_INT_INT_DOTS)
+typedef int ioctl_request_t;
+#elif defined(HAVE_IOCTL_INT_ULONG_DOTS)
+typedef unsigned long ioctl_request_t;
+#elif defined(HAVE_IOCTL_INT_ULONGINT_DOTS)
+typedef unsigned long int ioctl_request_t;
+#else
+#error "unknown ioctl type (check config.h, adapt configure test)..."
+#endif
+
+/*
+ * memory mapping emulation
+ */
+static int mmapemu = 0;
+static count_info mmapemu_ocount;
+static char *mmapemu_obuffer = 0;
+static int mmapemu_osize = 0;
+
+/*
+ * original C library functions
+ */
+typedef int (*orig_open_ptr)(const char *pathname, int flags, ...);
+typedef int (*orig_close_ptr)(int fd);
+typedef int (*orig_ioctl_ptr)(int fd, ioctl_request_t request, ...);
+typedef ssize_t (*orig_write_ptr)(int fd, const void *buf, size_t count);
+typedef ssize_t (*orig_read_ptr)(int fd, void *buf, size_t count);
+typedef void* (*orig_mmap_ptr)(void *start, size_t length, int prot,
+ int flags, int fd, off_t offset);
+typedef int (*orig_munmap_ptr)(void *start, size_t length);
+typedef FILE* (*orig_fopen_ptr)(const char *path, const char *mode);
+typedef int (*orig_access_ptr)(const char *pathname, int mode);
+
+static orig_open_ptr orig_open;
+static orig_close_ptr orig_close;
+static orig_ioctl_ptr orig_ioctl;
+static orig_write_ptr orig_write;
+static orig_read_ptr orig_read;
+static orig_mmap_ptr orig_mmap;
+static orig_munmap_ptr orig_munmap;
+static orig_fopen_ptr orig_fopen;
+static orig_access_ptr orig_access;
+
+static int artsdsp_debug = 0;
+static int artsdsp_init = 0;
+
+void *mmap(void *start, size_t length, int prot, int flags,
+ int fd, off_t offset);
+int munmap(void *start, size_t length);
+#define CHECK_INIT() if(!artsdsp_init) artsdsp_doinit();
+
+/*
+ * Initialization - maybe this should be either be a startup only called
+ * routine, or use pthread locks to prevent strange effects in multithreaded
+ * use (however it seems highly unlikely that an application would create
+ * multiple threads before even using one of redirected the system functions
+ * once).
+ */
+
+static void artsdsp_doinit()
+{
+ const char *env;
+ artsdsp_init = 1;
+
+ /* debugging? */
+ env = getenv("ARTSDSP_VERBOSE");
+ artsdsp_debug = env && !strcmp(env,"1");
+
+ /* mmap emulation? */
+ env = getenv("ARTSDSP_MMAP");
+ mmapemu = env && !strcmp(env,"1");
+
+ /* resolve original symbols */
+ orig_open = (orig_open_ptr)dlsym(RTLD_NEXT,"open");
+ orig_close = (orig_close_ptr)dlsym(RTLD_NEXT,"close");
+ orig_write = (orig_write_ptr)dlsym(RTLD_NEXT,"write");
+ orig_read = (orig_read_ptr)dlsym(RTLD_NEXT,"read");
+ orig_ioctl = (orig_ioctl_ptr)dlsym(RTLD_NEXT,"ioctl");
+ orig_mmap = (orig_mmap_ptr)dlsym(RTLD_NEXT,"mmap");
+ orig_munmap = (orig_munmap_ptr)dlsym(RTLD_NEXT,"munmap");
+ orig_fopen = (orig_fopen_ptr)dlsym(RTLD_NEXT,"fopen");
+ orig_access = (orig_access_ptr)dlsym(RTLD_NEXT,"access");
+}
+
+static void
+#ifdef __GNUC__
+ __attribute__( ( format ( printf, 1, 2 ) ) )
+#endif
+artsdspdebug(const char *fmt,...)
+{
+ CHECK_INIT();
+
+ if(artsdsp_debug)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+}
+
+static void mmapemu_flush()
+{
+ int space;
+
+ if (mmapemu_osize == 0) {
+ return;
+ }
+
+ space = arts_stream_get(stream, ARTS_P_BUFFER_SPACE);
+ artsdspdebug("space = %d\n",space);
+ while(space >= 4096)
+ {
+ arts_write(stream,&mmapemu_obuffer[mmapemu_ocount.ptr],4096);
+ space -= 4096;
+ mmapemu_ocount.ptr += 4096;
+ mmapemu_ocount.ptr %= mmapemu_osize;
+ mmapemu_ocount.blocks++;
+ mmapemu_ocount.bytes += 4096;
+ }
+}
+
+/* returns 1 if the filename points to a sound device */
+static int is_sound_device(const char *pathname)
+{
+ if(!pathname) return 0;
+ if(strcmp(pathname,"/dev/dsp") == 0) return 1;
+ if(strcmp(pathname,"/dev/sound/dsp") == 0) return 1;
+ return 0;
+}
+
+int open (const char *pathname, int flags, ...)
+{
+ va_list args;
+ mode_t mode = 0;
+
+ CHECK_INIT();
+
+ /*
+ * After the documentation, va_arg is not safe if there is no argument to
+ * get "random errors will occur", so only get it in case O_CREAT is set,
+ * and hope that passing 0 to the orig_open function in all other cases
+ * will work.
+ */
+ va_start(args,flags);
+ if(flags & O_CREAT) {
+ /* The compiler will select one of these at compile-tyime if -O is used.
+ * Otherwise, it may be deferred until runtime.
+ */
+ if (sizeof(int) >= sizeof(mode_t)) {
+ mode = va_arg(args, int);
+ } else {
+ mode = va_arg(args, mode_t);
+ }
+ }
+ va_end(args);
+
+ if (!is_sound_device(pathname)) /* original open for anything but sound */
+ return orig_open (pathname, flags, mode);
+
+ settings = 0;
+ frags = 0;
+ stream = 0;
+ record_stream = 0;
+
+ artsdspdebug ("aRts: hijacking /dev/dsp open...\n");
+
+ sndfd = orig_open("/dev/null",flags,mode);
+ if(sndfd >= 0)
+ {
+ if(!arts_init_done) {
+ int rc = arts_init();
+ if(rc < 0) {
+ artsdspdebug("error on aRts init: %s\n", arts_error_text(rc));
+ orig_close(sndfd);
+ sndfd = -1;
+ return orig_open (pathname, flags, mode);
+ }
+ else arts_init_done = 1;
+ }
+ }
+
+ /* success */
+ return sndfd;
+}
+
+int ioctl (int fd, ioctl_request_t request, ...)
+{
+ int space, size, latency, odelay;
+
+ /*
+ * FreeBSD needs ioctl with varargs. However I have no idea how to "forward"
+ * the variable args ioctl to the orig_ioctl routine. So I expect the ioctl
+ * to have exactly one pointer-like parameter and forward that, hoping that
+ * it works
+ */
+ va_list args;
+ void *argp;
+ va_start(args,request);
+ argp = va_arg(args, void *);
+ va_end(args);
+
+ CHECK_INIT();
+
+ if (fd != sndfd )
+ return orig_ioctl (fd, request, argp);
+ else if (sndfd != -1)
+ {
+ int *arg = (int *) argp;
+ artsdspdebug("aRts: hijacking /dev/dsp ioctl (%d : %x - %p)\n",
+ ( int ) fd, ( int ) request, ( void* ) argp);
+
+ switch (request)
+ {
+ struct audio_buf_info *audiop;
+#ifdef SNDCTL_DSP_RESET
+ case SNDCTL_DSP_RESET: /* _SIO ('P', 0) */
+ artsdspdebug("aRts: SNDCTL_DSP_RESET unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SYNC
+ case SNDCTL_DSP_SYNC: /* _SIO ('P', 1) */
+ artsdspdebug("aRts: SNDCTL_DSP_SYNC unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SPEED
+ case SNDCTL_DSP_SPEED: /* _SIOWR('P', 2, int) */
+ speed = *arg;
+ settings |= 2;
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_STEREO
+ case SNDCTL_DSP_STEREO: /* _SIOWR('P', 3, int) */
+ channels = (*arg)?2:1;
+ settings |= 4;
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETBLKSIZE
+ case SNDCTL_DSP_GETBLKSIZE: /* _SIOWR('P', 4, int) */
+ if(mmapemu)
+ *arg = 4096;
+ else if(stream)
+ *arg = arts_stream_get(stream,ARTS_P_PACKET_SIZE);
+ else
+ {
+ int fragSize = frags & 0x7fff;
+ if(fragSize > 1 && fragSize < 16)
+ *arg = (1 << fragSize);
+ else
+ *arg = 16384; /* no idea ;-) */
+ }
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SETFMT
+ case SNDCTL_DSP_SETFMT: /* _SIOWR('P',5, int) */
+ bits = (*arg & 0x30) ? 16 : 8;
+ settings |= 1;
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_CHANNELS
+ case SNDCTL_DSP_CHANNELS: /* _SIOWR('P', 6, int) */
+ channels = (*arg);
+ settings |= 4;
+ break;
+#endif
+
+#ifdef SOUND_PCM_WRITE_FILTER
+ case SOUND_PCM_WRITE_FILTER: /* _SIOWR('P', 7, int) */
+ artsdspdebug("aRts: SNDCTL_DSP_WRITE_FILTER(%d) unsupported\n",*arg);
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_POST
+ case SNDCTL_DSP_POST: /* _SIO ('P', 8) */
+ artsdspdebug("aRts: SNDCTL_DSP_POST unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SUBDIVIDE
+ case SNDCTL_DSP_SUBDIVIDE: /* _SIOWR('P', 9, int) */
+ artsdspdebug("aRts: SNDCTL_DSP_SUBDIVIDE(%d) unsupported\n",*arg);
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SETFRAGMENT
+ case SNDCTL_DSP_SETFRAGMENT: /* _SIOWR('P',10, int) */
+ artsdspdebug("aRts: SNDCTL_DSP_SETFRAGMENT(%x) partially supported\n",
+ *arg);
+ frags = *arg;
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETFMTS
+ case SNDCTL_DSP_GETFMTS: /* _SIOR ('P',11, int) */
+ *arg = 8 | 16;
+ break;
+#endif
+
+#if defined(SNDCTL_DSP_GETOSPACE) && defined(SNDCTL_DSP_GETISPACE)
+ case SNDCTL_DSP_GETOSPACE: /* _SIOR ('P',12, audio_buf_info) */
+ case SNDCTL_DSP_GETISPACE: /* _SIOR ('P',13, audio_buf_info) */
+ audiop = argp;
+ if(mmapemu)
+ {
+ audiop->fragstotal = 16;
+ audiop->fragsize = 4096;
+ audiop->bytes = 0; /* FIXME: is this right? */
+ audiop->fragments = 0;
+ }
+ else
+ {
+ audiop->fragstotal =
+ stream?arts_stream_get(stream, ARTS_P_PACKET_COUNT):10;
+ audiop->fragsize =
+ stream?arts_stream_get(stream, ARTS_P_PACKET_SIZE):16384;
+ audiop->bytes =
+ stream?arts_stream_get(stream, ARTS_P_BUFFER_SPACE):16384;
+ audiop->fragments = audiop->bytes / audiop->fragsize;
+ }
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_NONBLOCK
+ case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */
+ artsdspdebug("aRts: SNDCTL_DSP_NONBLOCK unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETCAPS
+ case SNDCTL_DSP_GETCAPS: /* _SIOR ('P',15, int) */
+ if(mmapemu)
+ *arg = DSP_CAP_MMAP | DSP_CAP_TRIGGER | DSP_CAP_REALTIME | DSP_CAP_DUPLEX;
+ else
+ *arg = DSP_CAP_DUPLEX;
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETTRIGGER
+ case SNDCTL_DSP_GETTRIGGER: /* _SIOR ('P',16, int) */
+ artsdspdebug("aRts: SNDCTL_DSP_GETTRIGGER unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SETTRIGGER
+ case SNDCTL_DSP_SETTRIGGER: /* _SIOW ('P',16, int) */
+ artsdspdebug("aRts: SNDCTL_DSP_SETTRIGGER unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETIPTR
+ case SNDCTL_DSP_GETIPTR: /* _SIOR ('P',17, count_info) */
+ artsdspdebug("aRts: SNDCTL_DSP_GETIPTR unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETOPTR
+ case SNDCTL_DSP_GETOPTR: /* _SIOR ('P',18, count_info) */
+ if(mmapemu)
+ {
+ mmapemu_flush();
+ *((count_info *)arg) = mmapemu_ocount;
+ mmapemu_ocount.blocks = 0;
+ }
+ else
+ {
+ artsdspdebug("aRts: SNDCTL_DSP_GETOPTR unsupported\n");
+ }
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_MAPINBUF
+ case SNDCTL_DSP_MAPINBUF: /* _SIOR ('P', 19, buffmem_desc) */
+ artsdspdebug("aRts: SNDCTL_DSP_MAPINBUF unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_MAPOUTBUF
+ case SNDCTL_DSP_MAPOUTBUF: /* _SIOR ('P', 20, buffmem_desc) */
+ artsdspdebug("aRts: SNDCTL_DSP_MAPOUTBUF unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SETSYNCRO
+ case SNDCTL_DSP_SETSYNCRO: /* _SIO ('P', 21) */
+ artsdspdebug("aRts: SNDCTL_DSP_SETSYNCHRO unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_SETDUPLEX
+ case SNDCTL_DSP_SETDUPLEX: /* _SIO ('P', 22) */
+ artsdspdebug("aRts: SNDCTL_DSP_SETDUPLEX unsupported\n");
+ break;
+#endif
+
+#ifdef SNDCTL_DSP_GETODELAY
+ case SNDCTL_DSP_GETODELAY: /* _SIOR ('P', 23, int) */
+ space = arts_stream_get(stream, ARTS_P_BUFFER_SPACE);
+ size = arts_stream_get(stream, ARTS_P_BUFFER_SIZE);
+ latency = arts_stream_get(stream, ARTS_P_SERVER_LATENCY);
+ odelay = size - space + (latency * speed * bits * channels) / 8000;
+ artsdspdebug("aRts: SNDCTL_DSP_GETODELAY returning %d\n", odelay);
+ *arg = odelay;
+ break;
+#endif
+
+ default:
+ artsdspdebug("aRts: unhandled /dev/dsp ioctl (%lx - %p)\n",request, argp);
+ break;
+ }
+
+ if (settings == 7 && !stream)
+ {
+ const char *name = getenv("ARTSDSP_NAME");
+ int fragSize = (frags & 0x7fff);
+ int fragCount = (frags & 0x7fff0000) >> 16;
+
+ artsdspdebug ("aRts: creating stream...\n");
+ stream = arts_play_stream(speed,bits,channels,name?name:"artsdsp");
+
+ if(fragSize > 1 && fragSize < 16)
+ {
+ /*
+ * if fragment settings are way too large (unrealistic), we
+ * will assume that the user didn't mean it, and let the C API
+ * choose a convenient number >= 3
+ */
+ if(fragCount < 2 || fragCount > 8192
+ || (fragCount * (1 << fragSize)) > 128*1024)
+ {
+ frags = 0x00030000+fragSize;
+ }
+
+ arts_stream_set(stream,ARTS_P_PACKET_SETTINGS,frags);
+ }
+ if(mmapemu)
+ {
+ arts_stream_set(stream,ARTS_P_PACKET_SETTINGS,0x0002000c);
+ mmapemu_ocount.ptr=mmapemu_ocount.blocks=mmapemu_ocount.bytes=0;
+ artsdspdebug("aRts: total latency = %dms, buffer latency = %dms\n",
+ arts_stream_get(stream,ARTS_P_TOTAL_LATENCY),
+ arts_stream_get(stream, ARTS_P_BUFFER_TIME));
+ }
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+int close(int fd)
+{
+ CHECK_INIT();
+
+ if (fd != sndfd)
+ return orig_close (fd);
+ else if (sndfd != -1)
+ {
+ artsdspdebug ("aRts: /dev/dsp close...\n");
+ if(stream)
+ {
+ arts_close_stream(stream);
+ stream = 0;
+ }
+ if (record_stream)
+ {
+ arts_close_stream(record_stream);
+ record_stream = 0;
+ }
+ if(mmapemu && mmapemu_obuffer)
+ {
+ free(mmapemu_obuffer);
+ mmapemu_obuffer = 0;
+ }
+
+ /*
+ * there are problems with library unloading in conjunction with X11,
+ * (Arts::X11GlobalComm), so we don't unload stuff again here
+ */
+
+ /* arts_free(); */
+
+ orig_close(sndfd);
+ sndfd = -1;
+ }
+ return 0;
+}
+
+int access(const char *pathname, int mode)
+{
+ CHECK_INIT();
+
+ if (!is_sound_device(pathname)) /* original open for anything but sound */
+ return orig_access (pathname, mode);
+ else
+ artsdspdebug ("aRts: /dev/dsp access...\n");
+ return 0;
+}
+
+ssize_t write (int fd, const void *buf, size_t count)
+{
+ CHECK_INIT();
+
+ if(fd != sndfd)
+ return orig_write(fd,buf,count);
+ else if(sndfd != -1)
+ {
+ artsdspdebug ("aRts: /dev/dsp write...\n");
+ if(stream != 0)
+ {
+ return arts_write(stream,buf,count);
+ }
+ }
+ return 0;
+}
+
+ssize_t read (int fd, void *buf, size_t count)
+{
+ CHECK_INIT();
+
+ if (fd != sndfd)
+ return orig_read(fd,buf,count);
+ else if (sndfd == -1)
+ return 0;
+
+ if (!record_stream)
+ record_stream = arts_record_stream(speed, bits, channels, "artsdsp");
+ artsdspdebug ( "aRts: /dev/dsp read...\n" );
+ return arts_read(record_stream, buf, count);
+}
+
+void *mmap(void *start, size_t length, int prot, int flags,
+ int fd, off_t offset)
+{
+ CHECK_INIT();
+
+ if(fd != sndfd || sndfd == -1)
+ return orig_mmap(start,length,prot,flags,fd,offset);
+ else
+ {
+ artsdspdebug ("aRts: mmap - start = %p, length = %zd, prot = %d\n",
+ start, length, prot);
+ artsdspdebug (" flags = %d, fd = %d, offset = %ld\n",flags, fd,offset);
+
+ if(mmapemu && length > 0)
+ {
+ mmapemu_osize = length;
+ mmapemu_obuffer = malloc(length);
+ mmapemu_ocount.ptr = mmapemu_ocount.blocks = mmapemu_ocount.bytes = 0;
+ return mmapemu_obuffer;
+ }
+ else artsdspdebug ("aRts: /dev/dsp mmap (unsupported, try -m option)...\n");
+ }
+ return (void *)-1;
+}
+
+int munmap(void *start, size_t length)
+{
+ CHECK_INIT();
+
+ if(start != mmapemu_obuffer || mmapemu_obuffer == 0)
+ return orig_munmap(start,length);
+
+ artsdspdebug ("aRts: /dev/dsp munmap...\n");
+ mmapemu_obuffer = 0;
+ free(start);
+
+ return 0;
+}
+
+#ifdef HAVE_ARTSDSP_STDIO_EMU
+
+/*
+ * use #include rather than linking, because we want to keep everything
+ * static inside artsdsp to be sure that we don't override application symbols
+ */
+#include "stdioemu.c"
+
+FILE* fopen(const char *path, const char *mode)
+{
+ CHECK_INIT();
+
+ if (!is_sound_device(path)) /* original open for anything but sound */
+ return orig_fopen (path, mode);
+
+ artsdspdebug ("aRts: hijacking /dev/dsp fopen...\n");
+
+ return fake_fopen(path, mode);
+}
+#endif
+
+#endif
+/*
+ * vim:ts=4
+ */
diff --git a/artsc/artsdsp.in b/artsc/artsdsp.in
new file mode 100755
index 0000000..084a716
--- /dev/null
+++ b/artsc/artsdsp.in
@@ -0,0 +1,106 @@
+#!/bin/sh
+# artsdsp - wrapper script to allow *some* binary only programs to use artsd
+# based on the esddsp script
+
+# keep this in sync with artsversion.h
+version="@ARTS_VERSION@"
+
+# default values for script variables
+verbose=0
+set_name=0
+single_thread=0
+
+# check for artsdsp options
+while test $# -gt 0; do
+
+ case "$1" in
+
+ -h|--help)
+ echo "artsdsp - attempt to reroute audio device to artsd"
+ echo " "
+ echo "artsdsp [options] application arguments"
+ echo " "
+ echo "options:"
+ echo "-h, --help show brief help"
+ echo "-n, --name=NAME use name to identify player to artsd"
+ echo "-m, --mmap emulate memory mapping (i.e. for quake)"
+ echo "-s, --single-threaded use the single-threaded version"
+ echo "-v, --verbose show parameters"
+ echo "-V, --version show version"
+ exit 0
+ ;;
+
+ -n)
+ shift
+ if test $# -gt 0; then
+ export ARTSDSP_NAME=$1
+ else
+ echo "no player name specified"
+ exit 1
+ fi
+ shift
+ set_name=1
+ ;;
+
+ --name*)
+ export ARTSDSP_NAME=`echo $1 | sed -e 's/^[^=]*=//g'`
+ set_name=1
+ shift
+ ;;
+
+ -v|--verbose)
+ verbose=1
+ shift
+ ;;
+
+ -V|--version)
+ echo "artsdsp $version"
+ exit
+ ;;
+
+ -m|--mmap)
+ export ARTSDSP_MMAP=1
+ shift
+ ;;
+
+ -s|--single-threaded)
+ single_thread=1
+ shift
+ ;;
+
+ *)
+ # no more artsdsp options, get on with life
+ break
+ ;;
+ esac
+done
+
+# echo options if verbose specified
+if test "$verbose" = 1; then
+ ARTSDSP_VERBOSE=1
+ export ARTSDSP_VERBOSE
+ echo "artsdsp: $version"
+ echo "name: $ARTSDSP_NAME"
+ echo "command line: $@"
+ if test "$single_thread" = 1; then
+ echo "threaded: no"
+ else
+ echo "threaded: yes"
+ fi
+fi
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+
+if test "$single_thread" = 1; then
+ LD_PRELOAD=${exec_prefix}/\$LIB/libartsdsp_st.so.0
+else
+ LD_PRELOAD=${exec_prefix}/\$LIB/libartsdsp.so.0:${exec_prefix}/\$LIB/libartsc.so.0
+fi
+if test -f ${exec_prefix}/\$LIB/libdl.so.2; then
+ LD_PRELOAD=$LD_PRELOAD:${exec_prefix}/\$LIB/libdl.so.2
+fi
+export LD_PRELOAD
+
+# invoke the program with the args given
+exec "$@"
diff --git a/artsc/stdioemu.c b/artsc/stdioemu.c
new file mode 100644
index 0000000..2b3bc1c
--- /dev/null
+++ b/artsc/stdioemu.c
@@ -0,0 +1,96 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * This source only exists because some very special programs think that
+ * it is a very special idea to access /dev/dsp by the means of stdio, so
+ * we need to fake FILE* access for artsdsp as well.
+ *
+ * To do so, it relies on glibc internals, so that it will probably not work
+ * on other systems - but then again, it might not be necessary on other
+ * systems, when fopen properly calls open, it might as well work unchanged.
+ */
+
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <libio.h>
+
+struct fd_cookie {
+ int fd;
+};
+
+static ssize_t fdc_read (void *cookie, char *buffer, size_t size)
+{
+ struct fd_cookie *fdc = (struct fd_cookie *)cookie;
+ return read(fdc->fd, buffer, size);
+}
+
+static ssize_t fdc_write (void *cookie, const char *buffer, size_t size)
+{
+ struct fd_cookie *fdc = (struct fd_cookie *)cookie;
+ return write(fdc->fd, buffer, size);
+}
+
+static int fdc_seek (void* cookie, off64_t* position, int whence)
+{
+ return -1;
+}
+
+static int fdc_clean (void *cookie)
+{
+ struct fd_cookie *fdc = (struct fd_cookie *)cookie;
+ int result = close(fdc->fd);
+ free(cookie);
+ return result;
+}
+
+static FILE *fake_fopen(const char *path, const char *mode)
+{
+ cookie_io_functions_t fns = { fdc_read, fdc_write, fdc_seek, fdc_clean };
+ struct fd_cookie *fdc =
+ (struct fd_cookie *)malloc(sizeof(struct fd_cookie));
+ const char *mptr;
+ int open_mode = 0;
+ FILE *result = 0;
+
+ for(mptr = mode; *mptr; mptr++)
+ {
+ if(*mptr == 'r') open_mode |= 1; /* 1 = read */
+ if(*mptr == 'w') open_mode |= 2; /* 2 = write */
+ if(*mptr == '+') open_mode |= 3; /* 3 = readwrite */
+ if(*mptr == 'a') open_mode |= 2; /* append -> write */
+ }
+ if(open_mode == 1) fdc->fd = open(path,O_RDONLY,0666);
+ if(open_mode == 2) fdc->fd = open(path,O_WRONLY,0666);
+ if(open_mode == 3) fdc->fd = open(path,O_RDWR,0666);
+
+ if(open_mode && fdc->fd > 0)
+ {
+ result = fopencookie (fdc,"w", fns);
+ result->_fileno = fdc->fd; /* ugly patchy slimy kludgy hack */
+ }
+ return result;
+}
diff --git a/configure.in.bot b/configure.in.bot
new file mode 100644
index 0000000..4f1129d
--- /dev/null
+++ b/configure.in.bot
@@ -0,0 +1,11 @@
+dnl put here things which have to be done as very last part of configure
+
+if test "x$arts_audiolib_found" = "xno"; then
+ echo ""
+ echo "You're missing libaudiofile. aRts won't be able to load or play"
+ echo "any samples without it, so please install it."
+ echo "Have a look at http://www.68k.org/~michael/audiofile/ or find a"
+ echo "binary package for your platform."
+ echo ""
+ all_tests=bad
+fi
diff --git a/configure.in.in b/configure.in.in
new file mode 100644
index 0000000..2cb7d6f
--- /dev/null
+++ b/configure.in.in
@@ -0,0 +1,851 @@
+# Original Author was Kalle@kde.org
+# I lifted it in some mater. (Stephan Kulow)
+# I used much code from Janos Farkas
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(acinclude.m4) dnl a source file from your sub dir
+
+dnl This is so we can use kde-common
+AC_CONFIG_AUX_DIR(admin)
+
+dnl right now: install aRts in the same prefix as KDE3.x currently
+KDE_SET_PREFIX_CORE
+
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+dnl Version (we /might/ want to use libtool versioning, too)
+ARTS_MAJOR_VERSION=1
+ARTS_MINOR_VERSION=5
+ARTS_MICRO_VERSION=10
+ARTS_VERSION=$ARTS_MAJOR_VERSION.$ARTS_MINOR_VERSION.$ARTS_MICRO_VERSION
+
+dnl Automake doc recommends to do this only here. (Janos)
+AM_INIT_AUTOMAKE(arts, $ARTS_VERSION) dnl searches for some needed programs
+
+AC_PROG_INSTALL
+
+dnl generate the config header
+AM_CONFIG_HEADER(config.h) dnl at the distribution this done
+
+dnl Checks for programs.
+AC_CHECK_COMPILERS
+AC_LIBLTDL_CONVENIENCE
+
+AC_ENABLE_SHARED(yes)
+AC_ENABLE_STATIC(no)
+KDE_PROG_LIBTOOL
+
+AC_LANG_SAVE
+AC_LANG_C
+KDE_LIB_LTDL
+AC_LANG_RESTORE
+
+# this checks for --with-extra-libs
+KDE_CHECK_EXTRA_LIBS
+KDE_MISC_TESTS
+dnl KDE_CHECK_LIBDL
+dnl AC_PROG_LIBTOOL
+KDE_CHECK_QT_DIRECT
+KDE_ENABLE_HIDDEN_VISIBILITY
+
+dnl for NLS support. Call them in this order!
+dnl WITH_NLS is for the po files, GNU_GETTEXT for the sources
+dnl AM_KDE_WITH_NLS
+dnl AM_KDE_GNU_GETTEXT
+
+dnl Checks for header files.
+KDE_CHECK_STL
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h sys/time.h unistd.h sys/cdefs.h fnmatch.h sysent.h strings.h sys/stat.h sys/select.h sys/socket.h linux/socket.h socketbits.h sigaction.h paths.h malloc.h monetary.h sys/param.h limits.h sys/mnttab.h mntent.h fstab.h)
+
+KDE_CHECK_HEADERS(sys/soundcard.h)
+
+dnl Checks for libraries.
+AC_BASE_PATH_KDE([don't test]) dnl arts is a special case
+AC_CHECK_LIB(compat, main, [LIBCOMPAT="-lcompat"]) dnl for FreeBSD
+AC_CHECK_LIB(util, main, [LIBUTIL="-lutil"]) dnl for FreeBSD
+AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(rt, sem_init, [LIBSEM="-lrt"]))
+
+AM_CONDITIONAL(HAVE_LIBJPEG, test -n "$LIBJPEG" )
+AM_CONDITIONAL(HAVE_LIBPNG, test -n "$LIBPNG" )
+AM_CONDITIONAL(HAVE_LIBTIFF, test -n "$LIBTIFF")
+
+# configure would do this very late. Too late for us!
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+
+AC_DEFINE_UNQUOTED(KDEDIR, "$prefix", [The prefix to use as fallback])
+
+ac_cpp_safe=$ac_cpp
+ac_cpp='$CXXCPP $CPPFLAGS $X_INCLUDES'
+KDE_CHECK_HEADERS(X11/ICE/ICElib.h)
+ac_cpp=$ac_cpp_safe
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_TIME
+AC_C_BIGENDIAN
+
+dnl check if the compiler has bool
+AC_CHECK_BOOL
+dnl AC_CHECK_GNU_EXTENSIONS
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(socket snprintf vsnprintf seteuid setegid random strfmon stpcpy mkstemp setmntent gettimeofday vasprintf)
+AC_FUNC_VFORK
+AC_CHECK_USLEEP
+AC_CHECK_SETENV
+AC_CHECK_GETHOSTNAME
+AC_CHECK_RANDOM
+AC_CHECK_S_ISSOCK
+AC_CHECK_SOCKLEN_T
+
+dnl output files
+AC_SUBST(x_includes)
+AC_SUBST(x_libraries)
+AC_SUBST(LIBSOCKET)
+AC_SUBST(LIBCOMPAT)
+AC_SUBST(LIBUTIL)
+AC_SUBST(LIBSEM)
+AC_SUBST(LIBICE)
+
+all_includes="$all_includes $INCLTDL"
+AC_SUBST(all_includes)
+
+AC_SUBST(EXTRA_SUBDIRS)
+
+topdir=`cd $srcdir && pwd`
+ac_configure_args="$ac_configure_args --with-auxdir=$topdir/admin"
+
+CXXFLAGS="$CXXFLAGS $USE_RTTI"
+
+dnl----------------------------------------------------------------------------
+dnl aRts specific configure tests
+dnl
+dnl Check for libaudioio (which can be used to get solaris audio support)
+AC_DEFUN([AC_CHECK_LIBAUDIOIO],
+[
+ ac_ldflags_save="$LDFLAGS"
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ LDFLAGS="$all_libraries $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+ arts_libaudioio_found=no
+ AC_LANG_SAVE
+ AC_LANG_C
+ kde_have_libaudioio=no
+ AC_CHECK_HEADER(libaudioio.h,
+ [
+ kde_have_libaudioio=yes
+ ])
+ if test "x$kde_have_libaudioio" = "xyes"; then
+ AC_CHECK_LIB(audioio,AudioIOGetVersion,[
+ dnl LDFLAGS in case it's in KDEDIR/lib
+ LIBAUDIOIO="$LDFLAGS -laudioio"
+ AC_DEFINE(HAVE_LIBAUDIOIO, 1,
+ [Define if you have libaudioIO (required if you want to have libaudioio support)])
+ arts_libaudioio_found=yes
+ ])
+ fi
+ AC_SUBST(LIBAUDIOIO)
+ AC_LANG_RESTORE
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ LDFLAGS="$ac_ldflags_save"
+])
+
+dnl aRts specific configure tests
+dnl
+dnl Check for libaudio (which can be used to get network audio support)
+AC_DEFUN([AC_CHECK_LIBAUDIONAS],
+[
+ ac_ldflags_save="$LDFLAGS"
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ LDFLAGS="$all_libraries $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+
+ AC_LANG_SAVE
+ AC_LANG_C
+ arts_libaudionas_include=no
+ AC_CHECK_HEADER(audio/audiolib.h,
+ [
+ arts_libaudionas_include=yes
+ ])
+ if test "x$arts_libaudionas_include" = "xyes"; then
+ AC_CHECK_LIB(audio,AuOpenServer,[
+ dnl LDFLAGS in case it's in KDEDIR/lib
+ LIBAUDIONAS="-laudio -lXt"
+ LIBAUDIONAS_LDFLAGS="$LDFLAGS"
+ AC_DEFINE(HAVE_LIBAUDIONAS, 1,
+ [Define if you have libaudio (required if you want to have NAS support)])
+ ])
+ fi
+ AC_SUBST(LIBAUDIONAS)
+ AC_SUBST(LIBAUDIONAS_LDFLAGS)
+ AC_LANG_RESTORE
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ LDFLAGS="$ac_ldflags_save"
+])
+
+dnl Check for libesd (for EsounD support)
+AC_DEFUN([AC_CHECK_LIBESD],
+[
+ ac_ldflags_save="$LDFLAGS"
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ LDFLAGS="$all_libraries $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+
+ AC_LANG_SAVE
+ AC_LANG_C
+ arts_libaudionas_include=no
+ AC_CHECK_HEADER(esd.h,
+ [
+ arts_libesd_include=yes
+ ])
+ if test "x$arts_libesd_include" = "xyes"; then
+ AC_CHECK_LIB(esd,esd_open_sound,[
+ dnl LDFLAGS in case it's in KDEDIR/lib
+ LIBESD="-lesd"
+ LIBESD_LDFLAGS="$LDFLAGS"
+ AC_DEFINE(HAVE_LIBESD, 1,
+ [Define if you have libesd (required if you want EsounD support)])
+ ])
+ fi
+ AC_SUBST(LIBESD)
+ AC_SUBST(LIBESD_LDFLAGS)
+ AC_LANG_RESTORE
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ LDFLAGS="$ac_ldflags_save"
+])
+
+dnl libaudiofile is used for loading wave files
+AC_DEFUN([AC_CHECK_LIBAUDIOFILE],
+[
+ ac_ldflags_save="$LDFLAGS"
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ LDFLAGS="$all_libraries $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+ arts_audiolib_found=no
+ dnl WAV reading
+ AC_LANG_SAVE
+ AC_LANG_C
+ kde_has_audio_lib=no
+ AC_CHECK_HEADER(audiofile.h,
+ [
+ kde_has_audio_lib=yes
+ ])
+ if test "x$kde_has_audio_lib" = "xyes"; then
+ KDE_CHECK_LIB(audiofile,afOpenFile,[
+ dnl LDFLAGS in case it's in KDEDIR/lib
+ LIBAUDIOFILE="-laudiofile"
+ LIBAUDIOFILE_LDFLAGS="$LDFLAGS"
+ AC_DEFINE(HAVE_LIBAUDIOFILE, 1,
+ [Define if you have libaudiofile (required for playing wavs with aRts)])
+ arts_audiolib_found=yes
+ ])
+ fi
+ AC_SUBST(LIBAUDIOFILE)
+ AC_SUBST(LIBAUDIOFILE_LDFLAGS)
+ AC_LANG_RESTORE
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ LDFLAGS="$ac_ldflags_save"
+])
+
+
+dnl check if sgi libaudio is present
+AC_DEFUN([AC_CHECK_SGILIBAUDIO],
+[
+ ac_ldflags_save="$LDFLAGS"
+ ac_CPPFLAGS_save="$CPPFLAGS"
+ LDFLAGS="$all_libraries $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $all_includes"
+
+ dnl SGI libaudio (required on IRIX)
+ AC_LANG_SAVE
+ AC_LANG_C
+ arts_dmedia_include=no
+ AC_CHECK_HEADER(dmedia/audio.h,
+ [
+ arts_dmedia_include=yes
+ ])
+ if test "x$arts_dmedia_include" = "xyes"; then
+ KDE_CHECK_LIB(audio,alOpenPort,[
+ SGILIBAUDIO="-laudio"
+ AC_DEFINE(HAVE_SGILIBAUDIO, 1,
+ [Define if you have libaudio (required for sound i/o on IRIX)])
+ ])
+ fi
+ AC_SUBST(SGILIBAUDIO)
+ AC_LANG_RESTORE
+ CPPFLAGS="$ac_CPPFLAGS_save"
+ LDFLAGS="$ac_ldflags_save"
+])
+
+dnl check if we want to build MAS support
+AC_DEFUN([AC_CHECK_LIBMAS],
+[
+AC_PATH_PROG(MAS_CONFIG, mas-config, no)
+
+if test "$MAS_CONFIG" != "no"; then
+ AC_DEFINE(HAVE_LIBMAS, 1,
+ [Define if you have libmas (required if you want MAS support)])
+ MAS_CFLAGS="`$MAS_CONFIG --cflags`"
+ tmp_mas_libs="`$MAS_CONFIG --libs` -lmas_jrtp"
+ MAS_LDFLAGS="`for i in $tmp_mas_libs; do echo $i; done |grep ^-L`"
+ MAS_LDFLAGS="$MAS_LDFLAGS `for i in $tmp_mas_libs; do echo $i; done |grep ^-L |sed s/^-L/-R/g`"
+ LIBMAS="$MAS_LDFLAGS"
+ for i in $tmp_mas_libs; do LIBMAS="$LIBMAS `echo $i |grep ^-l`"; done
+fi
+AC_SUBST(MAS_CFLAGS)
+AC_SUBST(MAS_LDFLAGS)
+AC_SUBST(LIBMAS)
+
+])
+
+dnl Posix realtime scheduling - this is helpful if you want arts to run with
+dnl higher priority than everthing else
+
+AC_DEFUN([ARTS_TRY_LINK_POSIX_REALTIME],
+[
+AC_TRY_LINK([
+#include <sched.h>
+],
+[
+sched_getscheduler(0);
+],
+arts_realtime_sched=yes,
+arts_realtime_sched=no)
+])
+
+AC_DEFUN([AC_CHECK_REALTIME_SCHED],
+[
+AC_MSG_CHECKING([for posix realtime scheduling support])
+save_LIBS="$LIBS"
+LIBPOSIX4=""
+ARTS_TRY_LINK_POSIX_REALTIME
+if test "x$arts_realtime_sched" = "xno"; then
+ LIBS="$LIBS -lposix4"
+ ARTS_TRY_LINK_POSIX_REALTIME
+ if test "x$arts_realtime_sched" = "xyes"; then
+ LIBPOSIX4="-lposix4"
+ fi
+fi
+LIBS="$save_LIBS"
+AC_SUBST(LIBPOSIX4)
+AC_MSG_RESULT($arts_realtime_sched)
+
+if test "x$arts_realtime_sched" = "xyes"; then
+ AC_DEFINE(HAVE_REALTIME_SCHED,1,
+ [Define if your system supports realtime scheduling])
+fi
+])
+
+dnl Type of the ioctl function test - after some tries, it seems that this
+dnl not required for Linux vs. FreeBSD (for which this test was written), and
+dnl that only the Linux documentation claims that it has an "int" as second
+dnl argument. But maybe there will pop up systems for which the signature
+dnl differs, later.
+
+AC_DEFUN([AC_CHECK_IOCTL_TYPE],
+[
+ AC_MSG_CHECKING([ioctl type])
+ AC_CACHE_VAL(ac_cv_ioctl_type,
+ [
+ AC_LANG_SAVE
+ AC_LANG_C
+
+ AC_TRY_COMPILE(
+ [
+ #include <unistd.h>
+ #include <sys/ioctl.h>
+ int ioctl(int d, int request,...);
+ ],
+ [
+ ],
+ ac_cv_ioctl_type=1)
+ AC_TRY_COMPILE(
+ [
+ #include <unistd.h>
+ #include <sys/ioctl.h>
+ int ioctl(int d, unsigned long request,...);
+ ],
+ [
+ ],
+ ac_cv_ioctl_type=2)
+ AC_TRY_COMPILE(
+ [
+ #include <unistd.h>
+ #include <sys/ioctl.h>
+ int ioctl(int d, unsigned long int request,...);
+ ],
+ [
+ ],
+ ac_cv_ioctl_type=3)
+ AC_LANG_RESTORE
+ ])
+ AC_MSG_RESULT($ac_cv_ioctl_type)
+
+
+if test "$ac_cv_ioctl_type" = "1"; then
+ AC_DEFINE(HAVE_IOCTL_INT_INT_DOTS,1,
+ [Define if ioctl is declared as int ioctl(int d, int request,...)])
+fi
+if test "$ac_cv_ioctl_type" = "2"; then
+ AC_DEFINE(HAVE_IOCTL_INT_ULONG_DOTS,2,
+ [Define if ioctl is declared as int ioctl(int d, unsigned long request,...)])
+fi
+if test "$ac_cv_ioctl_type" = "3"; then
+ AC_DEFINE(HAVE_IOCTL_INT_ULONGINT_DOTS,3,
+ [Define if ioctl is declared as int ioctl(int d, unsigned long int request,...)])
+fi
+])
+
+dnl check whether we can do rouding using asm optimization
+
+AC_DEFUN([AC_CHECK_X86_FLOAT_INT],
+[
+AC_MSG_CHECKING([for x86 float to int conversions])
+AC_CACHE_VAL(ac_cv_x86_float_int,
+[
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_TRY_LINK([
+#if defined(__i386__)
+static inline long QRound (float inval)
+{
+ long ret;
+ __asm__ ("fistpl %0" : "=m" (ret) : "t" (inval) : "st");
+ return ret;
+}
+#else
+error
+#endif
+],
+[
+long i = QRound(41.93); /* should be 42 */
+],
+ac_cv_x86_float_int=yes,
+ac_cv_x86_float_int=no)
+AC_LANG_RESTORE
+])
+AC_MSG_RESULT($ac_cv_x86_float_int)
+if test "x$ac_cv_x86_float_int" = "xyes"; then
+ AC_DEFINE(HAVE_X86_FLOAT_INT,1,
+ [Define if you want to use optimized x86 float to int conversion code])
+fi
+])
+
+dnl check if the assembler supports SSE instructions
+AC_DEFUN([AC_CHECK_X86_SSE],
+[
+AC_MSG_CHECKING([for x86 SSE instructions])
+AC_CACHE_VAL(ac_cv_x86_sse,
+[
+AC_TRY_COMPILE(,
+[
+#if defined(__GNUC__) && defined(__i386__)
+__asm__("movups %xmm0, (%esp)");
+#else
+/* IRIX's cc treats #error as a warning, make sure it errors out here */
+error Not gcc on x86
+#endif
+],
+ac_cv_x86_sse=yes,
+ac_cv_x86_sse=no)
+])
+AC_MSG_RESULT($ac_cv_x86_sse)
+if test "x$ac_cv_x86_sse" = "xyes"; then
+ AC_DEFINE(HAVE_X86_SSE,1,
+ [Define if your assembler supports x86 SSE instructions])
+fi
+])
+
+dnl check whether we should try to emulate stdio fopen/fclose via
+dnl glibc facilities (this *really* depends on glibc internals)
+
+AC_DEFUN([AC_CHECK_ARTSDSP_STDIO_EMU],
+[
+AC_MSG_CHECKING([for stdio emulation in artsdsp])
+AC_CACHE_VAL(ac_cv_artsdsp_stdio_emu,
+[
+AC_LANG_SAVE
+AC_LANG_C
+AC_TRY_LINK([
+#define _GNU_SOURCE
+#include <stdio.h>
+],
+[
+ cookie_io_functions_t fns = { 0, 0, 0, 0 };
+ struct fd_cookie *fdc = 0;
+ FILE *out = fopencookie (fdc,"w", fns);
+ out->_fileno = 0;
+],
+ac_cv_artsdsp_stdio_emu=yes,
+ac_cv_artsdsp_stdio_emu=no)
+])
+AC_LANG_RESTORE
+AC_MSG_RESULT($ac_cv_artsdsp_stdio_emu)
+if test "x$ac_cv_artsdsp_stdio_emu" = "xyes"; then
+ AC_DEFINE(HAVE_ARTSDSP_STDIO_EMU,1,
+ [Define if you want to use glibc facilities to emulate stdio accesses in artsdsp])
+fi
+])
+
+dnl call the tests
+AC_ARG_WITH(libaudioio,
+ [AC_HELP_STRING(--with-libaudioio,
+ [enable support for libaudioio @<:@default=check@:>@])],
+ [], with_libaudioio=check)
+
+if test "x$with_libaudioio" != xno; then
+ AC_CHECK_LIBAUDIOIO
+
+ if test "x$with_libaudioio" != xcheck && test -z "$LIBAUDIOIO"; then
+ AC_MSG_FAILURE([--with-libaudioio was given, but test for libaudioio failed])
+ fi
+fi
+
+AC_ARG_WITH(nas,
+ [AC_HELP_STRING(--with-nas,
+ [enable support for NAS @<:@default=check@:>@])],
+ [], with_nas=check)
+
+if test "x$with_nas" != xno; then
+ AC_CHECK_LIBAUDIONAS
+
+ if test "x$with_nas" != xcheck && test -z "$LIBAUDIONAS"; then
+ AC_MSG_FAILURE([--with-nas was given, but test for NAS failed])
+ fi
+fi
+
+AC_ARG_WITH(esd,
+ [AC_HELP_STRING(--with-esd,
+ [enable support for EsounD @<:@default=check@:>@])],
+ [], with_esd=check)
+
+if test "x$with_esd" != xno; then
+ AC_CHECK_LIBESD
+
+ if test "x$with_esd" != xcheck && test -z "$LIBESD"; then
+ AC_MSG_FAILURE([--with-esd was given, but test for EsounD failed])
+ fi
+fi
+
+AC_ARG_WITH(audiofile,
+ [AC_HELP_STRING(--with-audiofile,
+ [enable support for audiofile @<:@default=check@:>@])],
+ [], with_audiofile=check)
+
+if test "x$with_audiofile" != xno; then
+ AC_CHECK_LIBAUDIOFILE
+
+ if test "x$with_audiofile" != xcheck && test -z "$LIBAUDIOFILE"; then
+ AC_MSG_FAILURE([--with-audiofile was given, but test for audiofile failed])
+ fi
+fi
+AM_CONDITIONAL(HAVE_WAVSUPPORT, test -n "$LIBAUDIOFILE")
+
+AC_ARG_WITH(sgilibaudio,
+ [AC_HELP_STRING(--with-sgilibaudio,
+ [enable support for SGI libaudio @<:@default=check@:>@])],
+ [], with_sgilibaudio=check)
+
+if test "x$with_sgilibaudio" != xno; then
+ AC_CHECK_SGILIBAUDIO
+
+ if test "x$with_sgilibaudio" != xcheck && test -z "$SGILIBAUDIO"; then
+ AC_MSG_FAILURE([--with-sgilibaudio was given, but test for SGI libaudio failed])
+ fi
+fi
+
+AC_ARG_WITH(mas,
+ [AC_HELP_STRING(--with-mas,
+ [enable support for MAS @<:@default=check@:>@])],
+ [], with_mas=check)
+
+if test "x$with_mas" != xno; then
+ AC_CHECK_LIBMAS
+
+ if test "x$with_mas" != xcheck && test -z "$LIBMAS"; then
+ AC_MSG_FAILURE([--with-mas was given, but test for MAS failed])
+ fi
+fi
+
+AC_CHECK_REALTIME_SCHED
+AC_CHECK_GETDOMAINNAME
+AC_CHECK_IOCTL_TYPE
+AC_CHECK_X86_FLOAT_INT
+AC_CHECK_X86_SSE
+AC_CHECK_ARTSDSP_STDIO_EMU
+KDE_CHECK_THREADING
+
+dnl somewhat more deeply nested template code than gcc understands by default
+if test "$GXX" = "yes"; then
+ KDE_CHECK_COMPILER_FLAG(ftemplate-depth-99,
+ [
+ CXXFLAGS="$CXXFLAGS -ftemplate-depth-99"
+ ])
+fi
+
+dnl check for ALSA audio support
+arts_with_alsa=yes
+AC_ARG_WITH(alsa, [ --with-alsa enable aRts ALSA support],
+[arts_with_alsa=$withval])
+
+if test "$arts_with_alsa" = "yes"; then
+AC_DEFUN([AC_CHECK_LIBASOUND],
+[
+ ac_ldflags_save="$LDFLAGS"
+ LDFLAGS="$all_libraries $LDFLAGS"
+ kde_has_asoundlib=no
+
+ AC_CHECK_HEADERS([ sys/asoundlib.h alsa/asoundlib.h ],
+ [
+ kde_has_asoundlib=yes
+ ])
+
+ dnl trial and error version check for ALSA 0.5.x / ALSA 0.9.x
+ AC_LANG_SAVE
+ AC_LANG_C
+ if test "x$kde_has_asoundlib" = "xyes"; then
+ AC_TRY_COMPILE([
+ #include "confdefs.h"
+ #ifdef HAVE_SYS_ASOUNDLIB_H
+ #include <sys/asoundlib.h>
+ #endif
+ #ifdef HAVE_ALSA_ASOUNDLIB_H
+ #include <alsa/asoundlib.h>
+ #endif
+ ],[
+ #if (SND_LIB_MAJOR == 0) && (SND_LIB_MINOR == 9)
+ /* we have ALSA 0.9.x */
+ #else
+ #error not ALSA 0.9.x
+ #endif
+ ],
+ kde_has_alsa_0_9=yes,
+ kde_has_alsa_0_9=no)
+ fi
+
+ if test "x$kde_has_asoundlib" = "xyes"; then
+ AC_TRY_COMPILE([
+ #include "confdefs.h"
+ #ifdef HAVE_SYS_ASOUNDLIB_H
+ #include <sys/asoundlib.h>
+ #endif
+ #ifdef HAVE_ALSA_ASOUNDLIB_H
+ #include <alsa/asoundlib.h>
+ #endif
+ ],[
+ #if (SND_LIB_MAJOR == 1) && (SND_LIB_MINOR == 0)
+ /* we have ALSA 1.x */
+ #else
+ #error not ALSA 1.x
+ #endif
+ ],
+ kde_has_alsa_1_0=yes,
+ kde_has_alsa_1_0=no)
+ fi
+
+ if test "x$kde_has_asoundlib" = "xyes"; then
+ AC_TRY_COMPILE([
+ #include "confdefs.h"
+ #ifdef HAVE_SYS_ASOUNDLIB_H
+ #include <sys/asoundlib.h>
+ #endif
+ #ifdef HAVE_ALSA_ASOUNDLIB_H
+ #include <alsa/asoundlib.h>
+ #endif
+ ],[
+ #if (SND_LIB_MAJOR == 0) && (SND_LIB_MINOR == 5)
+ /* we have ALSA 0.5.x */
+ #else
+ #error not ALSA 0.5.x
+ #endif
+ ],
+ kde_has_alsa_0_5=yes,
+ kde_has_alsa_0_5=no)
+ fi
+ AC_LANG_RESTORE
+
+ if test "x$kde_has_asoundlib" = "xyes"; then
+ AC_CHECK_LIB(asound,snd_seq_create_simple_port,[
+ if test "x$kde_has_alsa_0_5" = "xyes"; then
+ LIBASOUND="-lasound"
+ AC_DEFINE(HAVE_LIBASOUND, 1,
+ [Define if you have libasound.so.1 (required for ALSA 0.5.x support)])
+ fi
+ if test "x$kde_has_alsa_0_9" = "xyes"; then
+ LIBASOUND="-lasound"
+ AC_DEFINE(HAVE_LIBASOUND2, 1,
+ [Define if you have libasound.so.2 (required for ALSA 0.9.x support)])
+ AC_CHECK_LIB(asound,snd_pcm_resume,[
+ AC_DEFINE(HAVE_SND_PCM_RESUME, 1,
+ [Define if libasound has snd_pcm_resume()])])
+ fi
+ if test "x$kde_has_alsa_1_0" = "xyes"; then
+ LIBASOUND="-lasound"
+ AC_DEFINE(HAVE_LIBASOUND2, 1,
+ [Define if you have libasound.so.2 (required for ALSA 0.9.x/1.x support)])
+ AC_DEFINE(ALSA_PCM_OLD_SW_PARAMS_API, 1,
+ [Define if you have alsa 1.x])
+ AC_DEFINE(ALSA_PCM_OLD_HW_PARAMS_API, 1,
+ [Define if you have alsa 1.x])
+ AC_CHECK_LIB(asound,snd_pcm_resume,[
+ AC_DEFINE(HAVE_SND_PCM_RESUME, 1,
+ [Define if libasound has snd_pcm_resume()])])
+ fi
+ ])
+ fi
+ AC_SUBST(LIBASOUND)
+ LDFLAGS="$ac_ldflags_save"
+])
+AC_CHECK_LIBASOUND
+fi
+
+AC_SUBST(LIBASOUND)
+
+dnl check for IRIX audio support
+AC_MSG_CHECKING([for IRIX])
+if test `uname` = "IRIX" -o `uname` = "IRIX64" ; then
+ AC_DEFINE(HAVE_IRIX, 1, [Define if you compile under IRIX])
+ AC_MSG_RESULT("yes")
+else
+ AC_MSG_RESULT("no")
+fi
+
+dnl check wether we want to use libcsl style sound I/O
+AC_ARG_ENABLE(csl,
+[ --enable-csl enable libcsl style sound I/O for aRts],
+[arts_want_csl="$enableval"],[arts_want_csl="no"])
+
+if test "$arts_want_csl" = "yes"; then
+ LIBCSL="-lcsl"
+ AC_DEFINE(HAVE_LIBCSL, 1,
+ [Define if you have libcsl (required if you want to have CSL support)])
+else
+ LIBCSL=""
+fi
+AC_SUBST(LIBCSL)
+
+dnl Check for pkg-config
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+
+if test "$PKG_CONFIG" = "no"; then
+ AC_MSG_ERROR([
+This package requires pkg-config.
+])
+fi
+
+dnl Check for Glib-2.0
+# GLIB_CFLAGS: cflags for compiling glib dependant sources
+# GLIB_LIBADD: glib libraries (-l options)
+# GLIB_LDFLAGS: flags containing path to glib libraries (-L options)
+
+GLIB_PACKAGES="gmodule-2.0 gthread-2.0"
+GLIB_VERSION="1.3.3"
+AC_MSG_CHECKING(for GLib-2.0 (at least $GLIB_VERSION))
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.15 ; then
+ if $PKG_CONFIG --atleast-version $GLIB_VERSION $GLIB_PACKAGES >/dev/null 2>&1 ; then
+ GLIB_CFLAGS="`$PKG_CONFIG --cflags $GLIB_PACKAGES`"
+ GLIB_LIBADD="`$PKG_CONFIG --libs-only-l --libs-only-other $GLIB_PACKAGES`"
+ GLIB_LDFLAGS="`$PKG_CONFIG --libs-only-L $GLIB_PACKAGES`"
+ AC_MSG_RESULT(yes)
+ fi
+else
+ if $PKG_CONFIG --atleast-version $GLIB_VERSION $GLIB_PACKAGES >/dev/null 2>&1 ; then
+ GLIB_CFLAGS="`$PKG_CONFIG --cflags $GLIB_PACKAGES`"
+ GLIB_LIBADD="`$PKG_CONFIG --libs $GLIB_PACKAGES`"
+ GLIB_LDFLAGS="`$PKG_CONFIG --libs-only-L $GLIB_PACKAGES`"
+ AC_MSG_RESULT(yes)
+ AC_MSG_WARN([you may need to run make LDFLAGS=-pthread to compile arts])
+ fi
+fi
+
+if test -z "$GLIB_LIBADD"; then
+ AC_MSG_RESULT(not installed)
+ AC_ERROR([
+ Please install glib-2.0 (see http://www.gtk.org).
+ ])
+ DO_NOT_COMPILE="$DO_NOT_COMPILE gmcop"
+fi
+
+CPPFLAGS="$CPPFLAGS $GLIB_CFLAGS"
+CFLAGS="$CFLAGS $GLIB_CFLAGS"
+
+AC_SUBST(GLIB_CFLAGS)
+AC_SUBST(GLIB_LIBADD)
+AC_SUBST(GLIB_LDFLAGS)
+
+AC_ARG_WITH(jack,
+ [AC_HELP_STRING(--with-jack,
+ [enable support for Jack @<:@default=check@:>@])],
+ [], with_jack=check)
+
+if test "x$with_jack" != xno; then
+ AC_MSG_CHECKING(for Jack Audio Connection Kit)
+ if $PKG_CONFIG --atleast-version 0.90 jack >/dev/null 2>&1 ; then
+ JACK_CFLAGS="`$PKG_CONFIG --cflags jack`"
+ JACK_LIBADD="`$PKG_CONFIG --libs-only-l jack`"
+ JACK_LDFLAGS="`$PKG_CONFIG --libs-only-L jack`"
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LIBJACK, 1,
+ [Define if you have libjack (required if you want Jack support)])
+ else
+ AC_MSG_RESULT(not installed)
+ fi
+ AC_SUBST(JACK_CFLAGS)
+ AC_SUBST(JACK_LIBADD)
+ AC_SUBST(JACK_LDFLAGS)
+
+ if test "x$with_jack" != xcheck && test -z "$JACK_LIBADD"; then
+ AC_MSG_FAILURE([--with-jack was given, but test for Jack failed])
+ fi
+fi
+
+dnl OpenBSD requires an -lossaudio and soundcard.h to provide OSS audio I/O
+AC_CHECK_HEADERS(soundcard.h)
+AC_CHECK_LIB(ossaudio, _oss_ioctl, [LIBOSSAUDIO="-lossaudio"])
+AC_SUBST(LIBOSSAUDIO)
+
+AM_CONFIG_HEADER(mcop/arts_export.h)
+AM_CONFIG_HEADER(artsc/artsc_export.h)
+
+dnl Don't remove !
+dnl AC_OUTPUT(artsc/artsc-config)
+
+dnl Check if we are building as part of KDE. Arts can also be built as
+dnl a standalone snapshot in which case KDE may not be present and things
+dnl that depend on KDE should not be built.
+dnl AC_MSG_CHECKING(if building standalone aRts snapshot without KDE)
+dnl if test "$DCOPIDL" = ""; then
+dnl AC_MSG_RESULT(yes)
+dnl ARTS_BUILD_KDE=""
+dnl MOC="true"
+dnl DCOPIDL="true"
+dnl DCOPIDL2CPP="true"
+dnl AC_SUBST(MOC)
+dnl AC_SUBST(DCOPIDL)
+dnl AC_SUBST(DCOPIDL2CPP)
+dnl else
+dnl AC_MSG_RESULT(no)
+dnl if test "x$kde_use_qt_emb" = "xyes"; then
+dnl ARTS_BUILD_KDE="qtmcop kde knotify message"
+dnl else
+dnl ARTS_BUILD_KDE="x11 qtmcop kde knotify message"
+dnl fi
+dnl fi
+dnl AC_SUBST(ARTS_BUILD_KDE)
+
+MCOPIDL='$(top_builddir)/mcopidl/mcopidl'
+AC_SUBST(MCOPIDL)
+
+AC_SUBST(ARTS_MAJOR_VERSION)
+AC_SUBST(ARTS_MINOR_VERSION)
+AC_SUBST(ARTS_MICRO_VERSION)
+AC_SUBST(ARTS_VERSION)
+
+dnl Don't remove !
+dnl AC_OUTPUT(artsc/artsdsp)
+dnl AC_OUTPUT(soundserver/artsversion-new.h)
+dnl AC_OUTPUT(flow/gsl/gslconfig.h)
+
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..a4c137b
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST = NEWS README TODO
diff --git a/doc/NEWS b/doc/NEWS
new file mode 100644
index 0000000..0b68fe4
--- /dev/null
+++ b/doc/NEWS
@@ -0,0 +1,58 @@
+aRts-1.2.0:
+- added EsounD support
+- fixed autosuspend in conjunction with full duplex
+
+aRts-1.1.0:
+- added functions to StdSynthModule to find if/how many other modules are
+ connected to the inputs and outputs of yourself
+
+aRts-1.0.0:
+- full duplex fixed
+
+aRts-0.7.0:
+- recording in the C API
+- new interface for video embedding (Arts::VideoPlayObject) via X11 embedding
+- threaded oss audio i/o (-a toss) which works better with some kernel drivers
+- irix audio i/o method (-a sgi)
+- ALSA-0.9.0 support
+- Preference=N lines in .mcopclass files make it possible to to choose one
+ implementation over another if they both implement the same interface
+
+aRts-0.6.1:
+- new artsdsp -s (single threaded) option for compatibility to more programs
+ (for instance netscape)
+- ALSA-0.9.0 support
+- bugfixes: artsdsp/artsc rpath fix, alsa crash without soundcard fixed, md5
+ cookie loading, oss driver endianess issue, compile fixes
+
+aRts-0.6.0:
+- new interfaces (Arts::InputStream, Arts::StreamPlayObject) for decoding
+ streams of data with PlayObjects (rather than just files)
+- new Arts::PitchablePlayObject for changing playing speed/pitch
+- support for streaming of data from kioslaves into PlayObjects
+- dynamic implementation of classes/attributes (Arts::DynamicSkeleton)
+
+(some of the items that are listed in aRts-0.6.0 have been done somewhere
+ between 0.4 and 0.6 and only now found its way into this)
+
+aRts-0.5.4:
+- fix random segfaults on solaris
+
+aRts-0.5.3:
+- performance improvement for aRts midi instruments (bus code rewritten)
+- structures designed by artsbuilder can be used modules in structures again
+ (and elsewhere), via generic Arts::Loader's
+
+aRts-0.5.2:
+- threading support (libmcop_mt)
+- glib-2.0 mainloop integration (libgmcop)
+- KArtsWidget makes it easy to use Arts::Widget implementations in conjunction
+ with qt widgets (i.e. no extra window), this also removes the annoying extra
+ window in artscontrol
+- generic gui factory used by noatun and artscontrol to create effect guis
+
+================================================================================
+This file starts in the middle of nowhere, because it hasn't always been
+here. But please update this if you do bigger changes (fixing a spelling
+error in a comment probably doesn't count, doing one of the TODO items
+most certainly does).
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..60a3beb
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,5 @@
+All of the aRts documentation is now in "The aRts Handbook" which is
+in KDE DocBook format, part of kdemultimedia. It should be found on a
+KDE system in $KDEDIR/share/doc/HTML/default/artsbuilder/index.html.
+
+An on-line version can be found at http://www.arts-project.org/doc/handbook
diff --git a/doc/TODO b/doc/TODO
new file mode 100644
index 0000000..37f856e
--- /dev/null
+++ b/doc/TODO
@@ -0,0 +1,215 @@
+- fix problems with REGISTER_IMPLEMENTATION:
+ => sometimes, global constructors don't work, so we'd better get rid
+ of them entierly ; instead, an init function needs to be added to
+ dynamically loaded modules
+- get rid of all error handling done by assert ; thus, one by one review
+ each assert if it can happen under any circumstances if yes, it needs
+ to be replaced by some other mechanism
+- report errors properly if some component could not be loaded ; right
+ now, it fails within assert(skel) in generated code, which doesn't
+ help users much to debug the problem
+- VERSION-INFO for modules?
+- md5auth isn't initialized properly in conjunction with ARTS_SERVER
+- make it possible to use C API and C++ API together
+- FIXME: what to do about apps which are not threaded but nevertheless
+ want to use the engine?
+- gsl: rounding should be used even for unsigned conversions
+
+## MCOP Core Infrastructure
+
+- offer sampleprecise timing
+- resource management (i.e. locate resources like "samples" or "structures"
+ in a similar uniform way KDE does with KStandardDirs)
+- check why adding thousand non-running objects degrades scheduling
+ performance quite a lot
+- recursive scheduling again (with loops & cycles)
+- obsoleting: use V2 implementations even if user requests a normal
+ implementation, since they have a newer version
+- error notification for connection breaks - this would enable intelligent
+ clients to immediately know when something goes wrong, so they can terminate
+ sanely instead of crashing
+- mcopidl: use unsigned char arrays instead of strings for inline marshalled
+ data in idl files - this will fix the "maximum string length" warnings and
+ while doing this improve space and speed
+- try to clean up notification manager, code generation and _copy() _release()
+ style referencing across functions in notification and Dispatcher - the
+ alternatives seem to be even more automatic referencing magic, or freeing
+ objects only if the stack is empty (idle freeing)
+- fix generated code for struct Foo { object bar; }
+- fix fallback into higher namespaces, the following idl file should be accepted
+ module A { interface Z; module B { interface Y : Z { }; }; };
+
+- debugging: if two alternating messages are emitted, the message compression
+ doesn't work, and the user will be flooded with debugging message, the X
+ server will crash, and so on - a possible strategy would be:
+ * make an always present MCOP object which can receive confirmations from
+ artsmessage
+ * start artsmessage as usual, but tell it about the MCOP object, so that
+ artsmessage can
+ - tell the MCOP object if it is done
+ - query the MCOP object for the repetition count of the message
+ * queue repeated messages as long as they are still visible on screen
+
+## aRts SoundServer
+
+- export configuration interfaces from the soundserver (so that
+ you can see and change the autosuspend timeout for instance)
+- support multiple artsd instances on one computer (like multiple displays),
+ and think of a clever way to register them
+- more support for different audio input/output methods (i.e. SDL)
+- support channels != 2
+- expand capabilities of shell utils (making them eventually as powerful as
+ artscontrol, or better ;)
+- make it possible to share a cookie between multiple hosts (like storing it
+ in nfs mounted home directory)
+- make it possible for artsd to cascade audio input/output to another artsd
+- ARTS_COOKIE, OSS_DEVICE
+
+## C API / artsdsp
+
+- implement an arts_stream_flush for writing half-written data packets
+ (useful for implementing SNDCTL_DSP_POST in artsdsp)
+- move to CSL (CSL a new common sound layer, especially intended to be
+ compatible between Gnome and KDE)
+- pkgconfig file
+- it might be useful to allow clients on big endian systems to pass their
+ 16bit data with their native byte order - for compatibility with older API
+ versions, its required to make this an extra parameter
+ as an efficiency bonus, one could also make the wire representation then
+ 16bit big endian, which requires support from the sound server though; its
+ not required to implement the feature, though (which is probably useful
+ for application writers on 16bit big endian machines)
+
+## GUI Support
+
+- port visual objects (beginnings are in kdemultimedia/arts/gui)
+- hbox, vbox
+- gui generation
+- hints via mcopidl
+
+## aRts Modules / Signal processing
+
+- midi recording for Brahms
+- StereoEffectStack should support reordering (and probably listing) effects
+ (maybe backport noatuns version)
+- hard disc recording
+- allow progressive loading for wave files
+- write blockwise caching (not requiring whole samples to be held in memory)
+- akai support
+- better interpolation / resampling
+- the Resampler class should do big endian and float as inputs
+- LADSPA support
+- provide a GUI for stereo_pitch_shift
+
+## kcmarts
+
+- add restart option to the control panel, so that you can restart artsd easier
+ if it crashed (it never crashes, does it ;) - close #38417 when done
+
+## artsbuilder (and runtime)
+
+- allow to give additional parameters (like names for sample files to play)
+ through .arts-map files
+- more examples (instruments, songs and such)
+- gui editing (or should is it better to write a new editor for that)
+- live editing of running structures
+- component bar where you can choose components without going through all
+ these submenus
+- property editor (like in delphi)
+- support pressing "return" in the various dialogs and close them on doing
+ that (rather than always having to click "ok" with the mouse)
+- i18n fixes
+
+## artscontrol
+
+- be able to remove midi ports *KDE2.2*
+- add a mixer
+- persistent state (Arts::Environment), so that the environment
+ can be restored on next login (or per song or something like that)
+- edit .arts-map files visually
+
+## Optimization (this section contains various optimization ideas)
+
+- use no floats for adressing the fractional part in resampling but integers
+ (that will be MUCH faster)
+- use short int for i16le resampling, instead of using a long and adding
+ sign manually (faster at least on athlon)
+- tune the MCOP transfer protocol
+ * rewrite Buffer not to use vector<char> to store data, but malloc'd blocks
+ * try to write "zero allocation" invocations, that means, try not to allocate
+ memory on performing an invocation. For instance Buffers could be kept in
+ pools, and be reused for further invocations, without the need to realloc
+ another memory block
+ * try to minimize the amount of copies of data, possibly even using something
+ like sharedmem to share data between the sending and receiving buffer
+ * hardcode frequently used calls in the Arts::Object interface
+
+## Documentation / Web
+
+- improve kdoc comments everywhere
+- write incomplete sections in The aRts Handbook; improve formatting
+
+## Misc
+
+- put streamwise blocking into MCOP, see artscat.cc to read really ugly
+ source which lives without that feature
+- implement plugins that transfer non-standard datatypes such as midi events,
+ video frames, fft packets, oscilloscope views, ... (which was impossible
+ with aRts on CORBA)
+- make aRts run inside Brahms, KWave or your-favorite-other-app, to do
+ signal processing where it is needed (similar to AudioLogic Environment,
+ for instance)
+- convince other people to use aRts, so that the usefulness of universal
+ plugins written for the API increases
+- when being crazy, implement gatewaying from MCOP to DCOP, CORBA, XMLRPC
+ or whatever else might be useful
+
+## Interoperability (GNOME/C)
+
+- write a gartscontrol (in C) as native Gnome/Gtk app
+- further work on CSL
+- C language binding, based on glib
+- mcopidl code generation for C
+
+## FlowSystem changes:
+
+It would be nice if the flowsystem became more "detached" from the normal
+operation, making it ideally runnable in one or more thread dedicated for
+audio processing.
+
+Flowsystem transactions:
+
+ these group operation like: starting, stopping, connecting, disconnecting,
+ ... to transactions which will later (asynchronously) executed by the
+ flowsystem
+
+Example: problematic assertion
+
+ assert(done[i] <= samples); /* synthschedule.cc:998 */
+
+ the problem with the assertion here is this - suppose some object reacts
+ in a way on some signal that will lead to the creation of new objects,
+ then those will get into the flowsystem, and we can't ultimately say
+ anything about how far these have been calculated so far
+
+ extremely problematic in this context are so-called call-ins, that is
+ you do calculateBlock, and during this, the dispatcher mainloop gets
+ called for some reason (I hope that this does not happen currently) -
+ if that would hypothetically happen, then there the whole flowsystem
+ could get restructured (because i.e. ordinary midi events could be
+ processed)
+
+## libartskde
+
+ * ensure that there is a pair of classes, like KAudioPlayStream and
+ KAudioRecordStream (or whatever they should be called) that can do
+ approximately what the C API can do
+
+ * don't export implementation details in the API - for instance
+ KAudio(Play|Record)Stream should probably only inherit from QObject, and
+ only "use" some aRts objects to do the actual work - that way, they can
+ be changed/modified more easily afterwards
+
+ * use Qt signals/slots as callbacks (at least as one possibility) for
+ "please produce new audio data" / "here is new audio data" - that way,
+ polling isn't necessary any longer
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..53c455c
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,97 @@
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_srcdir)/flow \
+ -I$(top_builddir)/flow -I$(top_srcdir)/soundserver \
+ -I$(top_builddir)/soundserver -I$(top_srcdir)/artsc \
+ -I$(top_builddir)/mcop -I$(top_builddir)/artsc \
+ $(all_includes)
+
+AM_LDFLAGS = $(all_libraries)
+LDADD = $(top_builddir)/mcop/libmcop.la
+FLOWLIBS = $(top_builddir)/flow/libartsflow.la
+
+####### Files
+
+check_PROGRAMS = helloserver helloclient referenceinfo \
+ irdemo x11commtest streamsound hellomain flow artsctest \
+ artscrec artsccat artscmt \
+ dcasttest hellodynamic hellodynamic2 testasubsys testaggregation \
+ playtofile testthreads testnothreads catfile testdhandle
+helloserver_SOURCES = hello.cc helloserver.cc hello_impl.cc
+helloclient_SOURCES = hello.cc helloclient.cc
+hellodynamic_SOURCES = hello.cc hellodynamic.cc hello_impl.cc
+hellodynamic2_SOURCES = hello.cc hellodynamic2.cc
+referenceinfo_SOURCES = referenceinfo.cc
+
+testdhandle_SOURCES = testdhandle.cc
+testdhandle.o: ../soundserver/soundserver.h ../flow/artsflow.h
+testdhandle_LDADD = $(FLOWLIBS) \
+ $(top_builddir)/soundserver/libsoundserver_idl.la \
+ $(top_builddir)/flow/gslpp/libgslpp.la
+
+irdemo_SOURCES = irdemo.cc
+x11commtest_SOURCES = x11commtest.cc
+hellomain_SOURCES = hellomain.cc hello.cc hello_impl.cc
+
+testasubsys_SOURCES = testasubsys.cc
+testasubsys_LDADD = $(FLOWLIBS)
+
+## testthreads/testnothreads:
+## if we link testthreads.cc against libmcop_mt, it will be able to use
+## real threading, if we don't, we won't
+testthreads_SOURCES = testthreads.cc
+testthreads_LDFLAGS = $(LDFLAGS)
+testthreads_LDADD = $(top_builddir)/mcop_mt/libmcop_mt.la
+testnothreads_SOURCES = testthreads.cc
+
+testaggregation_SOURCES = aggregation.cc testaggregation.cc
+
+flow_LDADD = $(FLOWLIBS)
+flow_SOURCES = flow.cc
+
+streamsound_LDADD = $(FLOWLIBS) \
+ $(top_builddir)/soundserver/libsoundserver_idl.la
+streamsound_SOURCES = streamsound.cc
+
+dcasttest_LDADD = $(FLOWLIBS) \
+ $(top_builddir)/soundserver/libsoundserver_idl.la
+dcasttest_SOURCES = dcasttest.cc
+
+artsctest_LDADD = $(top_builddir)/artsc/libartsc.la
+artsctest_SOURCES = artsctest.c
+
+artsccat_LDADD = $(top_builddir)/artsc/libartsc.la
+artsccat_SOURCES = artsccat.c
+
+artscrec_LDADD = $(top_builddir)/artsc/libartsc.la
+artscrec_SOURCES = artscrec.c
+
+artscmt_LDFLAGS = $(LDFLAGS) $(USE_THREADS)
+artscmt_LDADD = $(top_builddir)/artsc/libartsc.la -lm $(LIBPTHREAD) $(LIBPOSIX4)
+artscmt_SOURCES = artscmt.c
+
+playtofile_SOURCES = playtofile.cc playtofile_impl.cc playtofile_main.cc
+
+playtofile_LDADD = $(FLOWLIBS) \
+ $(top_builddir)/soundserver/libsoundserver_idl.la \
+ $(top_builddir)/soundserver/libkmedia2_idl.la
+
+catfile_SOURCES = catfile.cc
+
+catfile_LDADD = $(top_builddir)/soundserver/libkmedia2.la
+
+DISTCLEANFILES = hello.cc hello.h aggregation.cc aggregation.h \
+ playtofile.cc playtofile.h
+
+####### Implicit rules
+
+####### Build rules
+
+helloclient.o: hello.h
+hello.cc hello.h: $(top_srcdir)/examples/hello.idl $(MCOPIDL)
+ $(MCOPIDL) $(top_srcdir)/examples/hello.idl
+
+aggregation.cc aggregation.h: $(top_srcdir)/examples/aggregation.idl $(MCOPIDL)
+ $(MCOPIDL) $(top_srcdir)/examples/aggregation.idl
+
+playtofile.cc playtofile.h: $(srcdir)/playtofile.idl $(MCOPIDL)
+ $(MCOPIDL) -I$(top_srcdir)/flow $(srcdir)/playtofile.idl
+
diff --git a/examples/aggregation.idl b/examples/aggregation.idl
new file mode 100644
index 0000000..3c02d31
--- /dev/null
+++ b/examples/aggregation.idl
@@ -0,0 +1,27 @@
+/*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+interface String {
+ attribute string value;
+
+ void constructor(string value);
+};
diff --git a/examples/artsccat.c b/examples/artsccat.c
new file mode 100644
index 0000000..5f49f6f
--- /dev/null
+++ b/examples/artsccat.c
@@ -0,0 +1,115 @@
+ /*
+
+ Copyright (C) 2001 Matthias Kretz
+ kretz@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * This is another artscat written with aRts C API. It reads data from
+ * stdin, and plays it via the aRts soundserver.
+ *
+ * Compile programs using the aRts C API with
+ *
+ * cc -o artscdump artscdump.c `artsc-config --cflags` `artsc-config --libs`
+ *
+ * If you are using a makefile, it could look like this:
+ *
+ * CFLAGS=`artsc-config --cflags`
+ * LDFLAGS=`artsc-config --libs`
+ *
+ * artscdump: artscdump.c
+ */
+#include <artsc.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static void exitUsage(const char *progname)
+{
+ fprintf(stderr,"usage: %s [ options ] [ <filename> ]\n",progname);
+ fprintf(stderr,"-r <samplingrate> set samplingrate to use\n");
+ fprintf(stderr,"-b <bits> set number of bits (8 or 16)\n");
+ fprintf(stderr,"-c <channels> set number of channels (1 or 2)\n");
+ fprintf(stderr,"-h display this help and exit\n");
+ exit(1);
+}
+
+int main(int argc, char ** argv)
+{
+ int cfgSamplingRate = 44100;
+ int cfgBits = 16;
+ int cfgChannels = 2;
+ FILE *infile = stdin;
+ int pfd;
+ int packetsize;
+ char *buffer;
+ int size = 1024;
+ arts_stream_t stream;
+ int optch;
+ while((optch = getopt(argc,argv,"r:b:c:h")) > 0)
+ {
+ switch(optch)
+ {
+ case 'r': cfgSamplingRate = atoi(optarg);
+ break;
+ case 'b': cfgBits = atoi(optarg);
+ break;
+ case 'c': cfgChannels = atoi(optarg);
+ break;
+ case 'h':
+ default:
+ exitUsage(argc?argv[0]:"artsccat");
+ break;
+ }
+ }
+
+ if (optind < argc)
+ {
+ if(argv[optind] != "-")
+ {
+ infile = fopen(argv[optind],"w");
+ if(!infile)
+ {
+ fprintf( stderr, "Can't open file '%s'.\n", argv[optind] );
+ exit(1);
+ }
+ }
+ }
+
+ pfd = fileno( infile );
+
+ arts_init();
+ stream = arts_play_stream( cfgSamplingRate, cfgBits, cfgChannels, "artsccat" );
+ packetsize = arts_stream_get( stream, ARTS_P_PACKET_SIZE );
+ buffer = malloc(packetsize);
+
+ do {
+ size = read( pfd, buffer, packetsize );
+ size = arts_write( stream, buffer, size );
+ } while( size > 0 );
+
+ arts_close_stream( stream );
+ arts_free();
+
+ pclose( infile );
+ free(buffer);
+
+ return 0;
+}
diff --git a/examples/artscmt.c b/examples/artscmt.c
new file mode 100644
index 0000000..bc9e98d
--- /dev/null
+++ b/examples/artscmt.c
@@ -0,0 +1,143 @@
+ /*
+
+ Copyright (C) 2003 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * This is a threaded example using the aRts C API.
+ *
+ * Compile programs using the aRts C API with
+ *
+ * cc -o artscmt artscmt.c `artsc-config --cflags` `artsc-config --libs`
+ *
+ * If you are using a makefile, it could look like this:
+ *
+ * CFLAGS=`artsc-config --cflags`
+ * LDFLAGS=`artsc-config --libs`
+ *
+ * artscmt: artscmt.c
+ */
+#include <artsc.h>
+#include <pthread.h>
+#include <assert.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdio.h>
+
+pthread_mutex_t arts_mutex; /* pthread mutex */
+
+struct Writer
+{
+ pthread_t thread;
+ arts_stream_t stream;
+ float freq;
+};
+
+#define BUFFER_SIZE 1024
+
+static void* writer(void *arg)
+{
+ struct Writer *self = arg;
+ int pos = 0;
+
+ while(pos < 44100*10)
+ {
+ char buffer[BUFFER_SIZE], *to = buffer;
+ int i, written;
+
+ for(i=0;i<BUFFER_SIZE/4;i++)
+ {
+ /* generate two sin waves */
+ float fpos = ((float)pos)/44100.0;
+ long sample = (long)(sin(fpos*6.28*self->freq)*15000.0);
+ pos++;
+
+ /* put the samples in the packet */
+ *to++ = sample & 0xff;
+ *to++ = (sample >> 8) & 0xff;
+ *to++ = sample & 0xff;
+ *to++ = (sample >> 8) & 0xff;
+ }
+
+ written = 0;
+ do
+ {
+ int space;
+
+ /*
+ * Since there is more than one thread, it is important not to keep the lock
+ * for a long time. We definitely don't want arts_write to block, while we
+ * keep the lock, to ensure that other threads can do something as well. So
+ * we check the available buffer space before writing to avoid blocking.
+ */
+ pthread_mutex_lock(&arts_mutex);
+ space = arts_stream_get(self->stream, ARTS_P_BUFFER_SPACE);
+ if (space >= BUFFER_SIZE)
+ {
+ written = arts_write(self->stream, buffer, BUFFER_SIZE);
+ assert(written == BUFFER_SIZE); /* should handle errors here */
+ }
+ pthread_mutex_unlock(&arts_mutex);
+
+ /*
+ * If the buffer is full, wait some time to get free space again. The amout of
+ * time to wait needs to correspond to the buffer size we use for refilling.
+ */
+ if (!written)
+ usleep(10000); /* 10ms */
+ } while(!written);
+ }
+ return 0;
+}
+
+int main()
+{
+ struct Writer writer1, writer2;
+ int error;
+
+ error = arts_init();
+ if(error < 0)
+ {
+ fprintf(stderr, "error initializing aRts driver: %s\n", arts_error_text(error));
+ return 1;
+ }
+
+ pthread_mutex_init(&arts_mutex, 0);
+
+ writer1.stream = arts_play_stream(44100, 16, 2, "artscmt1");
+ writer1.freq = 440;
+ pthread_create(&writer1.thread, NULL, writer, &writer1);
+
+ writer2.stream = arts_play_stream(44100, 16, 2, "artscmt2");
+ writer2.freq = 880;
+ pthread_create(&writer2.thread, NULL, writer, &writer2);
+
+ pthread_join(writer1.thread, NULL);
+ pthread_join(writer2.thread, NULL);
+
+ arts_close_stream(writer1.stream);
+ arts_close_stream(writer2.stream);
+
+ pthread_mutex_destroy(&arts_mutex);
+
+ arts_free();
+
+ return 0;
+}
diff --git a/examples/artscrec.c b/examples/artscrec.c
new file mode 100644
index 0000000..80e91ae
--- /dev/null
+++ b/examples/artscrec.c
@@ -0,0 +1,115 @@
+ /*
+
+ Copyright (C) 2001 Matthias Kretz
+ kretz@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * This is another artsdump written with aRts C API. It reads data from
+ * the aRts soundserver and plays it via stdout.
+ *
+ * Compile programs using the aRts C API with
+ *
+ * cc -o artscdump artscdump.c `artsc-config --cflags` `artsc-config --libs`
+ *
+ * If you are using a makefile, it could look like this:
+ *
+ * CFLAGS=`artsc-config --cflags`
+ * LDFLAGS=`artsc-config --libs`
+ *
+ * artscdump: artscdump.c
+ */
+#include <artsc.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static void exitUsage(const char *progname)
+{
+ fprintf(stderr,"usage: %s [ options ] [ <filename> ]\n",progname);
+ fprintf(stderr,"-r <samplingrate> set samplingrate to use\n");
+ fprintf(stderr,"-b <bits> set number of bits (8 or 16)\n");
+ fprintf(stderr,"-c <channels> set number of channels (1 or 2)\n");
+ fprintf(stderr,"-h display this help and exit\n");
+ exit(1);
+}
+
+int main(int argc, char ** argv)
+{
+ int cfgSamplingRate = 44100;
+ int cfgBits = 16;
+ int cfgChannels = 2;
+ FILE *outfile = stdout;
+ int pfd;
+ int packetsize;
+ char *buffer;
+ int size;
+ arts_stream_t stream;
+ int optch;
+ while((optch = getopt(argc,argv,"r:b:c:h")) > 0)
+ {
+ switch(optch)
+ {
+ case 'r': cfgSamplingRate = atoi(optarg);
+ break;
+ case 'b': cfgBits = atoi(optarg);
+ break;
+ case 'c': cfgChannels = atoi(optarg);
+ break;
+ case 'h':
+ default:
+ exitUsage(argc?argv[0]:"artscdump");
+ break;
+ }
+ }
+
+ if (optind < argc)
+ {
+ if(argv[optind] != "-")
+ {
+ outfile = fopen(argv[optind],"w");
+ if(!outfile)
+ {
+ fprintf( stderr, "Can't open file '%s'.\n", argv[optind] );
+ exit(1);
+ }
+ }
+ }
+
+ pfd = fileno( outfile );
+
+ arts_init();
+ stream = arts_record_stream( cfgSamplingRate, cfgBits, cfgChannels, "artscdump" );
+ packetsize = arts_stream_get( stream, ARTS_P_PACKET_SIZE );
+ buffer = malloc(packetsize);
+
+ do {
+ size = arts_read( stream, buffer, packetsize );
+ size = write( pfd, buffer, size );
+ } while( size > 0 );
+
+ arts_close_stream( stream );
+ arts_free();
+
+ pclose( outfile );
+ free(buffer);
+
+ return 0;
+}
diff --git a/examples/artsctest.c b/examples/artsctest.c
new file mode 100644
index 0000000..9eb5a9b
--- /dev/null
+++ b/examples/artsctest.c
@@ -0,0 +1,72 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * This is another artscat written with aRts C API. It reads data from
+ * stdin, and plays it via the aRts soundserver.
+ *
+ * Compile programs using the aRts C API with
+ *
+ * cc -o artsctest artsctest.c `artsc-config --cflags` `artsc-config --libs`
+ *
+ * If you are using a makefile, it could look like this:
+ *
+ * CFLAGS=`artsc-config --cflags`
+ * LDFLAGS=`artsc-config --libs`
+ *
+ * artsctest: artsctest.c
+ */
+
+#include <artsc.h>
+#include <stdio.h>
+
+int main()
+{
+ arts_stream_t stream;
+ char buffer[8192];
+ int bytes;
+ int errorcode;
+
+ errorcode = arts_init();
+ if(errorcode < 0)
+ {
+ fprintf(stderr,"arts_init error: %s\n", arts_error_text(errorcode));
+ return 1;
+ }
+
+ stream = arts_play_stream(44100,16,2,"artsctest");
+
+ while((bytes = fread(buffer,1,8192,stdin)) > 0)
+ {
+ errorcode = arts_write(stream,buffer,bytes);
+ if(errorcode < 0)
+ {
+ fprintf(stderr,"arts_write error: %s\n",arts_error_text(errorcode));
+ return 1;
+ }
+ }
+
+ arts_close_stream(stream);
+ arts_free();
+
+ return 0;
+}
diff --git a/examples/catfile.cc b/examples/catfile.cc
new file mode 100644
index 0000000..2b34342
--- /dev/null
+++ b/examples/catfile.cc
@@ -0,0 +1,55 @@
+/*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <stdio.h>
+#include <kmedia2.h>
+#include <connect.h>
+
+using namespace std;
+using namespace Arts;
+
+int main(int argc, char **argv)
+{
+ if(argc != 2)
+ {
+ fprintf(stderr, "usage: catfile <file>\n");
+ exit(1);
+ }
+
+ Dispatcher dispatcher;
+ FileInputStream file;
+ StdoutWriter writer;
+
+ if(!file.open(argv[1]))
+ {
+ printf("can't open file %s\n",argv[1]);
+ exit(1);
+ }
+
+ connect(file, writer);
+
+ file.start();
+ writer.start();
+
+ while(!file.eof())
+ dispatcher.ioManager()->processOneEvent(false);
+}
diff --git a/examples/dcasttest.cc b/examples/dcasttest.cc
new file mode 100644
index 0000000..1d4127b
--- /dev/null
+++ b/examples/dcasttest.cc
@@ -0,0 +1,72 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include <stdio.h>
+#include <soundserver.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * This is a little test program that illustrates remote dynamic casting.
+ * Arts_SimpleSoundServer is a global object that is a SimpleSoundServer,
+ * so the first dynamic cast should succeed, while it is no Synth_PLAY,
+ * so the second dynamic cast should fail.
+ */
+
+int main()
+{
+ Dispatcher dispatcher;
+ Object obj = Reference("global:Arts_SimpleSoundServer");
+
+ if(obj.isNull())
+ {
+ cerr << "this test will only work if artsd is running" << endl;
+ exit(1);
+ }
+
+ /*
+ * TODO: fix this. This fails currently as in the first line only an
+ * Object_stub will get created, no SimpleSoundServer_stub, and _cast
+ * which is used by DynamicCast wil only try to cast the _stub object,
+ * not do any further tricks.
+ */
+ SimpleSoundServer server = DynamicCast(obj);
+ if(server.isNull())
+ {
+ cerr << "remote dynamic casting is too restrictive" << endl;
+ exit(1);
+ }
+
+ Synth_PLAY play = DynamicCast(obj);
+ if(!play.isNull())
+ {
+ cerr << "remote dynamic casting doesn't do proper checks" << endl;
+ exit(1);
+ }
+
+ cout << "remote dynamic casting seems to be fine" << endl;
+ return 0;
+}
diff --git a/examples/flow.cc b/examples/flow.cc
new file mode 100644
index 0000000..116c21b
--- /dev/null
+++ b/examples/flow.cc
@@ -0,0 +1,56 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld, stefan@space.twc.de
+ Nicolas Brodu, nicolas.brodu@free.fr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "artsflow.h"
+#include "connect.h"
+
+using namespace Arts;
+
+int main()
+{
+ Dispatcher dispatcher;
+
+ // object creation
+ Synth_FREQUENCY freq;
+ Synth_WAVE_SIN sin;
+ Synth_PLAY play;
+
+ // object initialization
+ setValue(freq, 440.0);
+
+ // object connection
+ connect(freq, sin);
+ connect(sin, play, "invalue_left");
+ connect(sin, play, "invalue_right");
+
+ // start all objects (maybe we should group objects like with QWidget
+ // parents and such?)
+ freq.start();
+ sin.start();
+ play.start();
+
+ // go
+ dispatcher.run();
+}
diff --git a/examples/hello.idl b/examples/hello.idl
new file mode 100644
index 0000000..8446500
--- /dev/null
+++ b/examples/hello.idl
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+ Modified by Nicolas Brodu, nicolas.brodu@free.fr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+// Test stuff:
+interface HelloBase {
+ void hellobase(string s);
+};
+
+interface Hello : HelloBase {
+ /*
+ * counter like functionality (init, adding, getting total value)
+ */
+ attribute long myValue;
+ void constructor(long i);
+ void add(long l);
+ void printTotal();
+
+ /*
+ * some hello world like stuff, string and number addition
+ */
+ void hello(string s);
+ long sum(long a,long b);
+ string concat(string s1, string s2);
+};
diff --git a/examples/hello_impl.cc b/examples/hello_impl.cc
new file mode 100644
index 0000000..a3be704
--- /dev/null
+++ b/examples/hello_impl.cc
@@ -0,0 +1,76 @@
+/*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+ Modified by Nicolas Brodu, nicolas.brodu@free.fr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+*/
+
+#include "hello_impl.h"
+#include <stdio.h>
+
+using namespace std;
+
+void Hello_impl::hellobase(const string& s)
+{
+ printf("Hellobase '%s'!\n",s.c_str());
+}
+
+void Hello_impl::hello(const string& s)
+{
+ printf("Hello '%s'!\n",s.c_str());
+}
+
+void Hello_impl::constructor(long i)
+{
+ myvalue=i;
+}
+
+long Hello_impl::myValue()
+{
+ return myvalue;
+}
+
+void Hello_impl::myValue(long newValue)
+{
+ myvalue=newValue;
+}
+
+void Hello_impl::add(long a)
+{
+ myvalue += a;
+}
+
+void Hello_impl::printTotal()
+{
+ printf("Total=%ld\n",myvalue);
+}
+
+long Hello_impl::sum(long a, long b)
+{
+ return a+b;
+}
+
+string Hello_impl::concat(const string& s1, const string& s2)
+{
+ return s1+s2;
+}
+
+REGISTER_IMPLEMENTATION(Hello_impl);
diff --git a/examples/hello_impl.h b/examples/hello_impl.h
new file mode 100644
index 0000000..484a890
--- /dev/null
+++ b/examples/hello_impl.h
@@ -0,0 +1,51 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+ Modified by Nicolas Brodu, nicolas.brodu@free.fr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#ifndef HELLO_IMPL_H
+#define HELLO_IMPL_H
+
+#include "hello.h"
+
+using namespace std;
+
+class Hello_impl : virtual public Hello_skel {
+private:
+ long myvalue;
+public:
+ long myValue();
+ void myValue(long newValue);
+ void constructor(long i);
+ void add(long increment);
+ void printTotal();
+
+ void hello(const string& s);
+ long sum(long a, long b);
+ string concat(const string& s1, const string& s2);
+
+ void hellobase(const string& s);
+};
+
+#endif /* HELLO_IMPL_H */
diff --git a/examples/helloclient.cc b/examples/helloclient.cc
new file mode 100644
index 0000000..c7d3022
--- /dev/null
+++ b/examples/helloclient.cc
@@ -0,0 +1,76 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "hello.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace Arts;
+
+int main(int argc, char **argv)
+{
+ if(argc != 2)
+ {
+ fprintf(stderr,"usage: %s <mcop reference>\n",argv[0]);
+ exit(1);
+ }
+
+ Dispatcher dispatcher;
+
+ Hello h = Reference(argv[1]);
+ if(h.isNull())
+ {
+ fprintf(stderr,"can't connect to the object\n");
+ exit(1);
+ }
+
+ const char *who = getenv("LOGNAME");
+ if(!who) who = "stefan";
+
+ printf("calling h.hello(\"%s\")\n", who);
+ h.hello(who);
+/*
+ printf("h->sum(2,4) is %ld\n",
+ h->sum2(2,4));
+
+ printf("h->sum(2,4,6) is %ld\n",
+ h->sum3(2,4,6));
+*/
+ h.myValue(6);
+ printf("h.myValue(6), h.myValue() is %ld\n",
+ h.myValue());
+
+ printf("h.concat(\"MCOP \",\"is great!\") is \"%s\"\n",
+ h.concat("MCOP ","is great!").c_str());
+
+ /*
+ int i,j = 0;
+ for(i=0;i<100000;i++)
+ j += h->sum2(2,4);
+ printf("%d\n",j);
+ */
+ return 0;
+}
diff --git a/examples/hellodynamic.cc b/examples/hellodynamic.cc
new file mode 100644
index 0000000..5dabec0
--- /dev/null
+++ b/examples/hellodynamic.cc
@@ -0,0 +1,94 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "hello.h"
+#include "dynamicrequest.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * Hellodynamic illustrates the usage of the DynamicRequest class to perform
+ * dynamic requests. There are two things you can try
+ *
+ * hellodynamic
+ *
+ * which will use a local implementation of a hello object, and
+ *
+ * hellodynamic <mcop reference>
+ *
+ * which will use a remote implementation of a hello object.
+ */
+int main(int argc, char **argv)
+{
+ Dispatcher dispatcher;
+ Hello h;
+
+ // Check if we should connect to a remote server:
+ if(argc == 2)
+ {
+ h = Reference(argv[1]);
+ if(h.isNull())
+ {
+ fprintf(stderr,"can't connect to the object\n");
+ exit(1);
+ }
+ }
+
+ // find out logname
+ const char *who = getenv("LOGNAME");
+ if(!who) who = "stefan";
+
+ printf("calling h.hello(\"%s\")\n", who);
+
+ // the dynamic equivalent to h.hello(who)
+ DynamicRequest hellorequest(h);
+
+ if(!hellorequest.method("hello").param(who).invoke())
+ cout << "dynamic invocation to h.hello(...) failed" << endl;
+
+ /*
+ Note: you could reuse hellorequest here, and indeed, if you
+ call the _same_ method over and over again, you'll get quite
+ some speed gain as the signature is only looked up once.
+ */
+
+ // set a value (no error checking here, I am lazy ;)
+ DynamicRequest(h).method("_set_myValue").param(42).invoke();
+
+ // get a value via "normal" interface
+ printf("h.myValue() is %ld (after setting it to 42)\n", h.myValue());
+
+ // call h.concat("MCOP ","rules.") dynamically
+ string s;
+ DynamicRequest(h).method("concat").param("MCOP ").param("rules.").invoke(s);
+ cout << "Conclusion of this test: " << s << endl;
+
+ return 0;
+}
diff --git a/examples/hellodynamic2.cc b/examples/hellodynamic2.cc
new file mode 100644
index 0000000..8f8a1e0
--- /dev/null
+++ b/examples/hellodynamic2.cc
@@ -0,0 +1,124 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "hello.h"
+#include "dynamicskeleton.h"
+#include "debug.h"
+#include "stdio.h"
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts { typedef DynamicSkeleton<Arts::Object_skel> Object_dskel; }
+
+class HelloDynamic : public Arts::Object_dskel {
+protected:
+ long myValue;
+
+public:
+ HelloDynamic() : Arts::Object_dskel("Hello") {
+ }
+ void process(long methodID, Arts::Buffer *request, Arts::Buffer *result)
+ {
+ const Arts::MethodDef& methodDef = getMethodDef(methodID);
+
+ if(methodDef.name == "hello") // void hello(string);
+ {
+ string s; request->readString(s);
+ printf("Hello '%s'!\n",s.c_str());
+ }
+ else if(methodDef.name == "_set_myValue") // attribute long myValue;
+ {
+ myValue = request->readLong();
+ }
+ else if(methodDef.name == "_get_myValue")
+ {
+ result->writeLong(myValue);
+ }
+ else if(methodDef.name == "concat")
+ {
+ string s1; request->readString(s1);
+ string s2; request->readString(s2);
+ result->writeString(s1+s2);
+ }
+ else if(methodDef.name == "sum")
+ {
+ long a = request->readLong();
+ long b = request->readLong();
+ result->writeLong(a+b);
+ }
+ else
+ {
+ arts_fatal("method %s unimplemented", methodDef.name.c_str());
+ }
+ }
+};
+
+/*
+ * this program illustrates that you /can/ implement an interface without
+ * using the IDL compiler skeleton do to so - this is useful if you want
+ * to create a language or object system binding, where you don't know
+ * all interfaces that are present at compile time
+ *
+ * however, it's definitely advanced stuff, and not for daily use ;)
+ */
+int main()
+{
+ Dispatcher dispatcher;
+
+ Object obj = Object::_from_base(new HelloDynamic());
+ if(obj.isNull())
+ arts_fatal("dimpl is no object?");
+
+ HelloBase b = DynamicCast(obj);
+ if(b.isNull())
+ arts_fatal("can't cast the object to HelloBase");
+
+
+ Hello h = DynamicCast(obj);
+ /*arts_info("%d",obj.isCompatibleWith("Hello"));*/
+
+ if(h.isNull())
+ arts_fatal("can't destringify to the object");
+
+ const char *who = getenv("LOGNAME");
+ if(!who) who = "stefan";
+
+ arts_info("calling h.hello(\"%s\")", who);
+ h.hello(who);
+
+ h.myValue(6);
+ arts_info("h.myValue(6), h.myValue() is %ld",
+ h.myValue());
+
+ arts_info("h.concat(\"MCOP \",\"is great!\") is \"%s\"",
+ h.concat("MCOP ","is great!").c_str());
+
+ /*
+ int i,j = 0;
+ for(i=0;i<100000;i++)
+ j += h.sum(2,4);
+ printf("%d\n",j);
+ */
+
+ return 0;
+}
diff --git a/examples/hellomain.cc b/examples/hellomain.cc
new file mode 100644
index 0000000..f194456
--- /dev/null
+++ b/examples/hellomain.cc
@@ -0,0 +1,77 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld stefan@space.twc.de
+ Nicolas Brodu, brodu@kde.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "hello.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+int main()
+{
+ Dispatcher dispatcher;
+
+ // Just use plain C++!
+ Hello server;
+ server.hello("server");
+
+ // creation from MCOP reference
+ Hello client( Reference( server.toString() ) );
+ if (!client.isNull()) client.hello("local test");
+ else cout << "fatal: a valid reference can't be decoded" << endl;
+
+ // creation from wrong reference
+ Hello xclient( Reference("fdshjkhdsf") );
+
+ // check result => should be null
+ if (xclient.isNull()) cout << "passed invalid reference test" << endl;
+ else cout << "fatal: an invalid reference can be decoded" << endl;
+
+ // using a constructor
+ Hello hint(3);
+ cout << hint.myValue() << endl;
+
+
+ Hello castsrc;
+ HelloBase casthint = castsrc;
+ casthint.hellobase("cast test passed");
+ if(castsrc.isNull()) cout << "cast problem with auto creation" << endl;
+ castsrc.hello("second cast test passed");
+
+ // Can copy (or here copy constructor) the objects
+ Hello hcopy = hint;
+ hcopy.add(5);
+ hcopy.printTotal();
+
+ // dynamic creation is OK
+ Hello* dyn = new Hello;
+ cout << dyn->concat("I am"," a dynamic hello") << endl;
+ dyn->hellobase("dynamic hellobase hello");
+ delete dyn;
+
+// dispatcher.run();
+ return 0;
+
+}
diff --git a/examples/helloserver.cc b/examples/helloserver.cc
new file mode 100644
index 0000000..2e37de5
--- /dev/null
+++ b/examples/helloserver.cc
@@ -0,0 +1,52 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "common.h"
+#include "hello_impl.h"
+
+#include <stdio.h>
+#include <vector>
+#include <string>
+
+using namespace std;
+using namespace Arts;
+
+int main()
+{
+ Dispatcher dispatcher(0,Dispatcher::startUnixServer);
+ Hello server;
+
+ string reference = server.toString();
+ printf("%s\n",reference.c_str());
+
+ Hello h = Reference(reference);
+ if(!h.isNull())
+ h.hello("local test");
+ else
+ printf("Local access to the Hello_impl object failed?\n");
+
+ dispatcher.run();
+ return 0;
+}
diff --git a/examples/irdemo.cc b/examples/irdemo.cc
new file mode 100644
index 0000000..4345235
--- /dev/null
+++ b/examples/irdemo.cc
@@ -0,0 +1,155 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+#include <string>
+
+using namespace std;
+using namespace Arts;
+
+static void printInterface(InterfaceDef id)
+{
+ string inherit;
+ if(id.inheritedInterfaces.size())
+ {
+ vector<string>::iterator ii;
+ bool first = true;
+ inherit = ": ";
+ for(ii = id.inheritedInterfaces.begin(); ii != id.inheritedInterfaces.end(); ii++)
+ {
+ if(!first) inherit +=",";
+ first = false;
+ inherit += (*ii)+" ";
+ }
+ }
+ printf("interface %s %s{\n",id.name.c_str(),inherit.c_str());
+ // attributes, streams
+ vector<AttributeDef>::iterator ai;
+ for(ai = id.attributes.begin(); ai != id.attributes.end(); ai++)
+ {
+ const AttributeDef& ad = *ai;
+ if(ad.flags & attributeAttribute)
+ {
+ /* readwrite */
+ if(ad.flags & (streamOut|streamIn) == (streamOut|streamIn))
+ {
+ printf(" attribute %s %s;\n",ad.type.c_str(), ad.name.c_str());
+ }
+ else
+ {
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ printf(" readonly attribute %s %s;\n",
+ ad.type.c_str(), ad.name.c_str());
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ printf(" ?writeonly? attribute %s %s;\n",
+ ad.type.c_str(), ad.name.c_str());
+ }
+ }
+ }
+ if(ad.flags & attributeStream)
+ {
+ const char *dir = (ad.flags & streamOut)?"out":"in";
+ const char *async = (ad.flags & streamAsync)?"async ":"";
+ string type = ad.type;
+ if(type == "float" && !(ad.flags & streamAsync)) type = "audio";
+
+ printf(" %s%s %s stream %s;\n",async,dir,
+ type.c_str(),ad.name.c_str());
+ }
+ }
+
+ // methods
+ vector<MethodDef>::iterator mi;
+ for(mi = id.methods.begin();mi != id.methods.end(); mi++)
+ {
+ MethodDef& md = *mi;
+ printf(" %s %s(",md.type.c_str(),md.name.c_str());
+
+ bool first = true;
+ vector<ParamDef>::iterator pi;
+ for(pi = md.signature.begin(); pi != md.signature.end(); pi++)
+ {
+ ParamDef& pd = *pi;
+ if(!first) printf(", ");
+ printf("%s %s",pd.type.c_str(),pd.name.c_str());
+ first = false;
+ }
+ printf(");\n");
+ }
+ printf("}\n");
+}
+
+/*
+ * This demo shows that you can find out what interface an object has and
+ * what types it needs to work without knowing anything but the object
+ * reference.
+ *
+ * The reason for that is that every object offers the _interfaceName
+ * _queryInterface and _queryType methods, which you can use to find out
+ * anything you need to know to talk to that object.
+ *
+ * Just pass this programm an MCOP object reference, and it will print out
+ * the corresponding interface.
+ *
+ * (TODO: one could make it print out all inherited interfaces and the
+ * types that are used in the interface, too. Ports, etc could be shown
+ * as well).
+ */
+
+/**
+ * Interface repository demo - reasonable testcase:
+ *
+ * - make sure artsd is running
+ * - irdemo global:Arts_SimpleSoundServer
+ */
+int main(int argc, char **argv)
+{
+ if(argc != 2)
+ {
+ fprintf(stderr,"usage: %s <mcop reference>\n",argv[0]);
+ exit(1);
+ }
+
+ Dispatcher dispatcher;
+ Object o = Reference(argv[1]);
+ if(o.isNull())
+ {
+ fprintf(stderr,"can't connect to the object\n");
+ exit(1);
+ }
+
+ string iname = o._interfaceName();
+ InterfaceDef idef = o._queryInterface(iname);
+ printInterface(idef);
+
+ return 0;
+}
diff --git a/examples/playtofile.idl b/examples/playtofile.idl
new file mode 100644
index 0000000..6aa341e
--- /dev/null
+++ b/examples/playtofile.idl
@@ -0,0 +1,41 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * this is an example interface which dumps things to a file
+ */
+#include <artsflow.idl>
+
+module Arts {
+ interface PlayToFile : SynthModule {
+ /**
+ * filename, - = default = stdout
+ */
+ attribute string filename;
+
+ /**
+ * write more data to file ;)
+ */
+ void goOn();
+ default in audio stream left, right;
+ };
+};
diff --git a/examples/playtofile_impl.cc b/examples/playtofile_impl.cc
new file mode 100644
index 0000000..63a5708
--- /dev/null
+++ b/examples/playtofile_impl.cc
@@ -0,0 +1,99 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "playtofile.h"
+#include "flowsystem.h"
+#include "stdsynthmodule.h"
+#include "convert.h"
+#include "stdio.h"
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+ class PlayToFile_impl : virtual public PlayToFile_skel,
+ virtual public StdSynthModule
+ {
+ typedef unsigned char uchar;
+ unsigned char *outblock;
+ unsigned long maxsamples;
+ string _filename;
+ FILE *out;
+ public:
+ PlayToFile_impl() : _filename("-")
+ {
+ }
+ void filename(const string& newfilename) {
+ _filename = newfilename;
+ filename_changed(_filename);
+ }
+
+ string filename() { return _filename; }
+
+ void streamInit() {
+ maxsamples = 0;
+ outblock = 0;
+ if(_filename == "-")
+ out = stdout;
+ else
+ out = fopen(_filename.c_str(),"w");
+ }
+ void streamEnd() {
+ if(outblock)
+ {
+ delete[] outblock;
+ outblock = 0;
+ }
+ if(out != stdout)
+ {
+ fclose(out);
+ }
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ if(samples > maxsamples)
+ {
+ maxsamples = samples;
+
+ if(outblock) delete[] outblock;
+ outblock = new uchar[maxsamples * 4]; // 2 channels, 16 bit
+ }
+
+ convert_stereo_2float_i16le(samples,left,right, outblock);
+ fwrite(outblock, 1, 4 * samples,out);
+ }
+
+ /*
+ * this is the most tricky part here - since we will run in a context
+ * where no audio hardware will play the "give me more data role",
+ * we'll have to request things ourselves (requireFlow() tells the
+ * flowsystem that more signal flow should happen, so that
+ * calculateBlock will get called
+ */
+ void goOn()
+ {
+ _node()->requireFlow();
+ }
+ };
+ REGISTER_IMPLEMENTATION(PlayToFile_impl);
+};
diff --git a/examples/playtofile_main.cc b/examples/playtofile_main.cc
new file mode 100644
index 0000000..c7f85fd
--- /dev/null
+++ b/examples/playtofile_main.cc
@@ -0,0 +1,147 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "playtofile.h"
+#include "kmedia2.h"
+#include "debug.h"
+#include "dynamicrequest.h"
+#include "connect.h"
+#include "flowsystem.h"
+#include <ctype.h>
+#include <iostream>
+
+using namespace Arts;
+using namespace std;
+
+/* copypasted from simplesoundserver_impl.cc */
+PlayObject createPlayObject(const string& filename)
+{
+ string objectType = "";
+
+ /*
+ * figure out extension (as lowercased letters)
+ */
+ string extension = "";
+ bool extensionok = false;
+ string::const_reverse_iterator i;
+ for(i = filename.rbegin(); i != filename.rend() && !extensionok; i++)
+ {
+ if(*i == '.')
+ extensionok = true;
+ else
+ extension = (char)tolower(*i) + extension;
+ }
+
+ /*
+ * query trader for PlayObjects which support this
+ */
+ if(extensionok)
+ {
+ arts_debug("search playobject, extension = %s",extension.c_str());
+
+ TraderQuery query;
+ query.supports("Interface","Arts::PlayObject");
+ query.supports("Extension",extension);
+
+ vector<TraderOffer> *offers = query.query();
+ if(!offers->empty())
+ objectType = offers->front().interfaceName(); // first offer
+
+ delete offers;
+ }
+
+ /*
+ * create a PlayObject and connect it
+ */
+ if(!objectType.empty())
+ {
+ arts_debug("creating %s to play file", objectType.c_str());
+
+ PlayObject result = SubClass(objectType);
+ if(result.loadMedia(filename))
+ {
+ result._node()->start();
+ return result;
+ }
+ else arts_warning("couldn't load file %s", filename.c_str());
+ }
+ else arts_warning("file format extension %s unsupported",extension.c_str());
+
+ return PlayObject::null();
+}
+
+/*
+ * This is an example for dumping things to a file. It demonstates, that
+ *
+ * a) you can use all aRts objects in a non-realtime environment (i.e.
+ * the time in the PlayObject will pass much faster than the outside
+ * time when dumping things to a file)
+ *
+ * b) complayObjectnents will be dynamically loaded as needed
+ *
+ * c) you need to do small tricks to get the signal flow going when you are
+ * not having audio modules around
+ *
+ * d) by implementing aRts modules, you can easily grab and insert data from/to
+ * arbitary non-aRts sources - for instance, a wave editor might implement
+ * own modules to get the wave from/to memory
+ */
+int main(int argc, char **argv)
+{
+ Dispatcher d;
+
+ if(argc != 2 && argc != 3)
+ {
+ cerr << "usage: playtofile <inputfile> [ <outputfile> ]" << endl;
+ exit(1);
+ }
+ PlayObject playObject = createPlayObject(argv[1]);
+ if(playObject.isNull())
+ {
+ cerr << "can't read inputfile " << argv[1] << endl;
+ exit(1);
+ }
+
+ playObject.play();
+
+ PlayToFile playToFile;
+ if(argc == 3) playToFile.filename(argv[2]);
+
+ connect(playObject, "left", playToFile,"left");
+ connect(playObject, "right", playToFile,"right");
+
+ // <ignore the following lines>
+ // special case when using mpeglib, do tell it not to block (internal
+ // interface) - we also put an usleep here to ensure that the threads
+ // and everything is fully initialized as soon as we start
+ usleep(100000);
+ if(playObject._base()->_isCompatibleWith("DecoderBaseObject"))
+ if(!DynamicRequest(playObject).method("_set_blocking").param(true).invoke())
+ cerr << "mpeglib, and blocking attribute can't be changed?" << endl;
+ // </ignore>
+
+ playToFile.start();
+ while(playObject.state() != posIdle)
+ playToFile.goOn();
+
+ return 0;
+}
diff --git a/examples/referenceinfo.cc b/examples/referenceinfo.cc
new file mode 100644
index 0000000..d73776c
--- /dev/null
+++ b/examples/referenceinfo.cc
@@ -0,0 +1,57 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "common.h"
+#include <stdio.h>
+
+using namespace Arts;
+
+int main(int argc, char **argv)
+{
+ Dispatcher dispatcher;
+ ObjectReference r;
+
+ if(argc != 2)
+ {
+ fprintf(stderr,"usage: %s <mcop reference>\n",argv[0]);
+ exit(1);
+ }
+
+ if(!dispatcher.stringToObjectReference(r,argv[1]))
+ {
+ fprintf(stderr,
+ "Can't read this object reference (invalid?)\n");
+ exit(1);
+ }
+ printf("serverID: %s\n",r.serverID.c_str());
+ printf("objectID: %ld\n\n",r.objectID);
+
+ printf("URLs:\n");
+ std::vector<std::string>::iterator ui;
+ for(ui = r.urls.begin(); ui != r.urls.end();ui++)
+ printf(" - %s\n",ui->c_str());
+
+ return 0;
+}
diff --git a/examples/streamsound.cc b/examples/streamsound.cc
new file mode 100644
index 0000000..a19bd27
--- /dev/null
+++ b/examples/streamsound.cc
@@ -0,0 +1,106 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "soundserver.h"
+#include "stdsynthmodule.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+#include <math.h>
+
+using namespace std;
+using namespace Arts;
+
+class Sender : public ByteSoundProducer_skel,
+ public StdSynthModule
+{
+ bool _finished;
+ int pos;
+public:
+ Sender() : _finished(false), pos(0)
+ {
+ }
+ long samplingRate() { return 44100; }
+ long channels() { return 2; }
+ long bits() { return 16; }
+ bool finished() { return _finished; }
+
+ static const int packetCount = 10, packetCapacity = 1024;
+ void streamStart()
+ {
+ /*
+ * start streaming
+ */
+ outdata.setPull(packetCount, packetCapacity);
+ }
+
+ void request_outdata(DataPacket<mcopbyte> *packet)
+ {
+ /*
+ * fill the packet with new data
+ */
+ // ----------------- audio fill up start -----------------
+
+ int j;
+ mcopbyte *to = &packet->contents[0];
+ for(j=0;j<packetCapacity/4;j++)
+ {
+ // generate two sin waves
+ float fpos = ((float)pos)/44100.0;
+ long left = (long)(sin(fpos*6.28*440.0)*30000.0);
+ long right = (long)(sin(fpos*6.28*880.0)*30000.0);
+ pos++;
+
+ // put the samples in the packet
+ *to++ = left & 0xff;
+ *to++ = (left >> 8) & 0xff;
+ *to++ = right & 0xff;
+ *to++ = (right >> 8) & 0xff;
+ }
+
+ // ------------------ audio fill up end ------------------
+ packet->send();
+ }
+};
+
+int main(int argc, char **argv)
+{
+ Dispatcher dispatcher;
+ SimpleSoundServer server = Reference("global:Arts_SimpleSoundServer");
+
+ if(server.isNull())
+ {
+ cerr << "Can't connect to sound server" << endl;
+ return 1;
+ }
+
+ ByteSoundProducer sender = ByteSoundProducer::_from_base(new Sender());
+ server.attach(sender);
+ sender.start();
+ dispatcher.run();
+ server.detach(sender); // in this example: not reached
+}
diff --git a/examples/testaggregation.cc b/examples/testaggregation.cc
new file mode 100644
index 0000000..76c2773
--- /dev/null
+++ b/examples/testaggregation.cc
@@ -0,0 +1,73 @@
+/*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include "aggregation.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+class String_impl : virtual public String_skel {
+ string _value;
+public:
+ void constructor(const std::string& value) { _value = value; }
+ string value() { return _value; }
+ void value(const std::string& newValue) { _value = newValue; }
+};
+
+REGISTER_IMPLEMENTATION(String_impl);
+
+void printall(Arts::Object o, std::string pre = "")
+{
+ String s;
+ s = DynamicCast(o);
+ if(!s.isNull())
+ cout << pre << " - " << s.value() << endl;
+
+ vector<string> *children = s._queryChildren();
+ vector<string>::iterator i;
+ for(i = children->begin(); i != children->end(); i++)
+ printall(s._getChild(*i), pre+" ");
+}
+
+/*
+ * Small test case for aggregation
+ *
+ * The idea behind all this is that you can add children to objects, building
+ * a tree (or if you like graph) of objects without the objects knowing anything
+ * about this. Aggregation has strong references, that means, the objects you
+ * add together in a tree will stay this way, as long as you keep a reference
+ * to the root.
+ */
+int main()
+{
+ Dispatcher d;
+
+ String s("spreadsheet");
+ s._addChild(String("chart"),"child1");
+ s._addChild(String("image"),"child2");
+ printall(s);
+
+ cout << "deleting \"child1\"" << endl;
+ if(!s._removeChild("child1")) cout << "FAIL" << endl;
+ printall(s);
+}
diff --git a/examples/testasubsys.cc b/examples/testasubsys.cc
new file mode 100644
index 0000000..e0480ed
--- /dev/null
+++ b/examples/testasubsys.cc
@@ -0,0 +1,142 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include <iostream>
+#include <math.h>
+#include "audiosubsys.h"
+#include "convert.h"
+#include "dispatcher.h"
+
+using namespace std;
+using namespace Arts;
+
+class SinTest : public ASProducer {
+protected:
+ int audiofd;
+ int done;
+ AudioSubSystem *as;
+ bool attached;
+
+public:
+ SinTest();
+ virtual ~SinTest();
+ void needMore();
+ void run(long samples);
+};
+
+SinTest::SinTest() : done(0), as(AudioSubSystem::the())
+{
+ // initialize and open audio subsystem (defaults to 44kHz, 16bit, stereo)
+ attached = as->attachProducer(this);
+ if(!attached)
+ {
+ cout << "audio subsystem is already used?" << endl;
+ }
+ else
+ {
+ if(as->open() == false)
+ {
+ cout << "audio subsystem init failed ("
+ << as->error() << ")" << endl;
+ audiofd = -1;
+ }
+ else
+ audiofd = as->selectWriteFD();
+ }
+}
+
+SinTest::~SinTest()
+{
+ // deinitialize the audio subsystem
+ if(attached)
+ as->detachProducer();
+}
+
+void SinTest::run(long samples)
+{
+ // run this loop until enough samples are produced
+ while(attached && audiofd >= 0 && (done < samples))
+ {
+ fd_set wfds, efds;
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+ FD_SET(audiofd, &wfds);
+ FD_SET(audiofd, &efds);
+
+ // look if the audio filedescriptor becomes writeable
+ int result = select(audiofd+1,0,&wfds,&efds,0);
+ if(result > 0)
+ {
+ // if yes, tell the audio subsystem to do something about it
+ if(FD_ISSET(audiofd, &wfds))
+ as->handleIO(AudioSubSystem::ioWrite);
+ if(FD_ISSET(audiofd, &efds))
+ as->handleIO(AudioSubSystem::ioExcept);
+ }
+ else
+ {
+ cout << "select returned " << result << endl;
+ }
+ }
+}
+
+/*
+ * needMore is a callback by the audio subsystem, which is made as soon as
+ * the internal buffers need a refill
+ */
+void SinTest::needMore()
+{
+ float left[100], right[100];
+ unsigned char out[400];
+
+ // generate two waves, one 440 Hz (left), one 880Hz (right)
+ for(int i=0;i<100;i++)
+ {
+ left[i] = sin((float)i*6.28/100.0);
+ right[i] = sin((float)i*6.28/50.0);
+ }
+ convert_stereo_2float_i16le(100, left, right, out);
+
+ // write them to the audio subsystem
+ as->write(out,400);
+ done += 100;
+}
+
+/*
+ * This is intended to help testing the audio subsystem with different
+ * hardware without needing to use the whole server.
+ *
+ * Warning: this is *not* an example how to use aRts (there are others),
+ * but a simple test program for debugging purposes.
+ */
+int main()
+{
+ Dispatcher d; // to get startup classes executed
+
+ // the test, generate 88100 samples (2 seconds) of pure sine wave test data
+ SinTest s;
+ s.run(88100);
+ return 0;
+}
diff --git a/examples/testdhandle.cc b/examples/testdhandle.cc
new file mode 100644
index 0000000..a42ad46
--- /dev/null
+++ b/examples/testdhandle.cc
@@ -0,0 +1,115 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "gslpp/datahandle.h"
+#include "soundserver.h"
+#include "stdsynthmodule.h"
+#include "artsflow.h"
+#include "connect.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+#include <math.h>
+
+using namespace std;
+using namespace Arts;
+
+int main(int argc, char **argv)
+{
+ if(argc<2)
+ {
+ cerr << "USAGE: " << argv[0] << " [filename]\n";
+ exit(1);
+ }
+
+ Dispatcher dispatcher;
+ SoundServer server = Reference("global:Arts_SoundServer");
+
+ cout << "opening '" << argv[1] << "' locally...\n";
+
+ GSL::WaveFileInfo info(argv[1]);
+ if(info.error())
+ {
+ cerr << "GSL error " << info.error() <<
+ " (" << gsl_strerror(info.error()) << ") while loading info.\n";
+ exit(1);
+ }
+ cout << "file contains " << info.waveCount() << " waves:\n";
+ for(int i=0; i<info.waveCount(); i++)
+ {
+ GSL::WaveDescription desc= info.waveDescription(i);
+ cout << " wave " << i << ": " << desc.name() <<
+ " (" << desc.channelCount() << " channels):\n";
+ for(int ci=0; ci<desc.chunkCount(); ci++)
+ {
+ GSL::WaveChunkDescription cDesc= desc.chunkDescription(ci);
+ cout << " chunk " << ci << ": "
+ << cDesc.oscillatorFrequency()
+ << "hz, recorded with " << cDesc.mixerFrequency()
+ << ", loop type: " << cDesc.loopType() << "\n";
+ }
+ }
+
+ cout << "opening '" << argv[1] << "' in soundserver for playback...\n";
+
+ if(server.isNull())
+ {
+ cerr << "Can't connect to sound server" << endl;
+ return 1;
+ }
+
+ WaveDataHandle handle = DynamicCast(server.createObject("Arts::WaveDataHandle"));
+ if(!handle.load(argv[1]))
+ {
+ cerr << "server can't load wave file '" << argv[1] << "'" << endl;
+ return 1;
+ }
+
+ printf("channels = %d\n", handle.channelCount());
+ //printf("samplingrate = %f\n", handle.samplingRate());
+ printf("length[values] = %ld\n", handle.valueCount());
+
+ DataHandlePlay phandle = handle.createPlayer();
+
+ /*DataHandlePlay phandle =
+ DynamicCast(server.createObject("Arts::DataHandlePlay"));
+
+ phandle.handle(handle);
+ // .createReversed() .createTranslated(0,100000,40000)
+ */
+
+ Synth_BUS_UPLINK bu =
+ DynamicCast(server.createObject("Arts::Synth_BUS_UPLINK"));
+ connect(phandle,"outvalue",bu,"left");
+ connect(phandle,"outvalue",bu,"right");
+ bu.busname("out_soundcard");
+ phandle.start();
+ bu.start();
+
+ while(!phandle.finished())
+ sleep(1);
+}
diff --git a/examples/testthreads.cc b/examples/testthreads.cc
new file mode 100644
index 0000000..0155f90
--- /dev/null
+++ b/examples/testthreads.cc
@@ -0,0 +1,64 @@
+/*
+
+ Copyright (C) 2001-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#include <stdio.h>
+#include <string>
+#include <unistd.h>
+#include "dispatcher.h"
+#include "thread.h"
+
+using namespace Arts;
+using namespace std;
+
+class Counter : public Arts::Thread
+{
+ string name;
+public:
+ Counter(const string& name) :name(name) {}
+
+ void run() {
+ for(int i = 0;i < 10;i++)
+ {
+ printf("[%s] %d\n",name.c_str(),i+1);
+ sleep(1);
+ }
+ printf("[%s] terminating.\n", static_cast<Counter *>
+ (SystemThreads::the()->getCurrentThread())->name.c_str());
+ }
+};
+
+int main()
+{
+ Dispatcher dispatcher;
+ Counter c1("counter1"), c2("counter2");
+
+ if(SystemThreads::supported())
+ printf("We have a system threads (counters should count parallel).\n");
+ else
+ printf("No system threads (counters will not count parallel).\n");
+
+ c1.start();
+ c2.start();
+ c1.waitDone();
+ c2.waitDone();
+ return 0;
+}
diff --git a/examples/x11commtest.cc b/examples/x11commtest.cc
new file mode 100644
index 0000000..fa793b4
--- /dev/null
+++ b/examples/x11commtest.cc
@@ -0,0 +1,76 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+ Modified by Nicolas Brodu, brodu@kde.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include <iostream>
+#include "common.h"
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * Test program for X11GlobalComm (communication over X11 root window
+ * properties), and since X11GlobalComm is an dynamically extension,
+ * extension loading is tested as well.
+ */
+int main(int argc, char **argv)
+{
+ Dispatcher dispatcher;
+ GlobalComm gcomm( SubClass("Arts::X11GlobalComm") );
+
+ if (gcomm.isNull()) {
+ cerr << "Cannot create a X11GlobalComm object" << endl;
+ return 2;
+ }
+
+ if(argc == 4)
+ {
+ if(string(argv[1]) == "put")
+ {
+ gcomm.put(argv[2],argv[3]);
+ return 0;
+ }
+ }
+ if(argc == 3)
+ {
+ if(string(argv[1]) == "get")
+ {
+ cout << gcomm.get(argv[2]) << endl;
+ return 0;
+ }
+ if(string(argv[1]) == "erase")
+ {
+ gcomm.erase(argv[2]);
+ return 0;
+ }
+ }
+
+ cerr << "This is a test for the X11GlobalComm class. Use" << endl << endl
+ << " " << argv[0] << " put <variable> <value>" << endl
+ << " " << argv[0] << " get <variable>" << endl
+ << " " << argv[0] << " erase <variable>" << endl << endl
+ << "to test the communication via X11 RootWindow properties." << endl;
+ return 1;
+}
diff --git a/flow/Makefile.am b/flow/Makefile.am
new file mode 100644
index 0000000..720ca47
--- /dev/null
+++ b/flow/Makefile.am
@@ -0,0 +1,49 @@
+
+SUBDIRS = mcopclass gsl gslpp
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop $(all_includes)
+AM_CXXFLAGS = $(MAS_CFLAGS) $(JACK_CFLAGS) -DQT_CLEAN_NAMESPACE
+
+####### Files
+
+lib_LTLIBRARIES = libartsflow_idl.la libartsflow.la
+
+libartsflow_idl_la_SOURCES = artsflow.cc
+libartsflow_idl_la_LDFLAGS = -no-undefined -version-info 1:0 $(all_libraries)
+libartsflow_idl_la_LIBADD = $(top_builddir)/mcop/libmcop.la $(LIBPOSIX4)
+
+libartsflow_la_LIBADD = $(top_builddir)/mcop/libmcop.la libartsflow_idl.la $(top_builddir)/flow/gslpp/libgslpp.la $(LIBAUDIOFILE) $(LIBASOUND) $(LIBAUDIOIO) $(LIBOSSAUDIO) $(LIBAUDIONAS) $(LIBCSL) $(SGILIBAUDIO) $(LIBESD) $(LIBMAS) $(JACK_LIBADD) -lm \
+ $(top_builddir)/flow/gsl/libgsl.la
+libartsflow_la_LDFLAGS = $(MAS_LDFLAGS) $(JACK_LDFLAGS) $(LIBAUDIOFILE_LDFLAGS) $(LIBAUDIONAS_LDFLAGS) $(LIBESD_LDFLAGS) -no-undefined -version-info 1:0
+libartsflow_la_COMPILE_FIRST = artsflow.h
+libartsflow_la_SOURCES = synth_play_impl.cc \
+ gslschedule.cc audiosubsys.cc \
+ pipebuffer.cc convert.cc synth_wave_sin_impl.cc synth_frequency_impl.cc \
+ synth_multi_add_impl.cc synth_add_impl.cc synth_mul_impl.cc \
+ synth_play_wav_impl.cc stdsynthmodule.cc cache.cc asyncschedule.cc \
+ bytestreamtoaudio_impl.cc stereovolumecontrol_impl.cc \
+ stereoeffectstack_impl.cc fft.c stereofftscope_impl.cc virtualports.cc \
+ bus.cc audiomanager_impl.cc synth_record_impl.cc resample.cc \
+ audioio.cc audioiooss.cc audioioalsa.cc audioioalsa9.cc \
+ audioionull.cc audioiolibaudioio.cc audioioesd.cc audioiojack.cc \
+ audioiosun.cc audioioaix.cc audioionas.cc cpuinfo.cc \
+ audioioossthreaded.cc audiotobytestream_impl.cc audioiosgi.cc \
+ audioiocsl.cc audioiomas.cc datahandle_impl.cc
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = artsflow.h audiosubsys.h cache.h \
+ cachedwav.h convert.h pipebuffer.h stdsynthmodule.h \
+ synthschedule.h fft.h artsflow.idl audioio.h resample.h \
+ cpuinfo.h bufferqueue.h gslschedule.h
+
+DISTCLEANFILES = artsflow.cc artsflow.h artsflow.mcoptype artsflow.mcopclass
+
+artsflow.cc artsflow.h: $(top_srcdir)/flow/artsflow.idl $(MCOPIDL)
+ $(MCOPIDL) -t $(top_srcdir)/flow/artsflow.idl
+
+artsflow.mcoptype: artsflow.h
+artsflow.mcopclass: artsflow.h
+
+######## install idl typeinfo files
+
+mcoptypedir = $(libdir)/mcop
+mcoptype_DATA = artsflow.mcoptype artsflow.mcopclass
diff --git a/flow/artsflow.idl b/flow/artsflow.idl
new file mode 100644
index 0000000..44424e0
--- /dev/null
+++ b/flow/artsflow.idl
@@ -0,0 +1,566 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * arts.idl - MCOP port. What's missing currently in MCOP?
+ *
+ * - namespaces (module)
+ */
+
+module Arts { // analog real time synthesizer
+
+enum AutoSuspendState { asNoSuspend, asSuspend, asSuspendStop, asSuspendMask = 0x3,
+ asProducer = 0x10, asConsumer = 0x20, asDirectionMask = 0x30 };
+
+/**
+ * The SynthModule interface is the base for all modules containing streams.
+ *
+ * There are two goals achieved by this interface. On one side, there is
+ * functionality which users of stream carrying modules want to use (which
+ * is: start streaming, stop streaming).
+ *
+ * On the other hand, there is functionality which the flow system will use
+ * to achieve these goals.
+ */
+interface SynthModule {
+ // interface for users of this module
+
+ /**
+ * This function starts the streaming (e.g. the module will start
+ * producing samples) - if you write a module, do not reimplement this,
+ * instead reimplement streamInit/streamStart
+ */
+ void start();
+
+ /**
+ * This function stops the streaming - if you write a plugin, do not
+ * reimplement this, instead reimplement streamEnd
+ */
+ void stop();
+
+ // interface for people implementing modules
+
+ /**
+ * this is supposed to be the initialization every module passes after
+ * all attributes have been set up (e.g. you can see which file to open,
+ * how to initialize your filter coefficients or whatever)
+ */
+ void streamInit();
+
+ /**
+ * starts the I/O of the module
+ */
+ void streamStart();
+
+ /**
+ * stop the thing again, and free data possibly allocated in streamInit
+ */
+ void streamEnd();
+
+ /**
+ * If you run a mixer desk (without anything connected), no calculations
+ * need to be done - since the output is silent anyway. For this reason,
+ * there exists this autosuspend attribute. It allows the flow system
+ * to detect the idle condition, and start suspending the calculations,
+ * until something "important" happens again.
+ *
+ * There are three possible values:
+ *
+ * @li asNoSuspend - this one is appropriate when you have a module that
+ * is active by itself
+ * @li asSuspend - this one is appropriate for modules that "do nothing"
+ * by themselves
+ * @li asSuspendStop - this one is for modules that should be stopped, when
+ * the system gets suspended, and restarted when the
+ * system will start again - an example for this is
+ * soundcard output
+ *
+ * A module should choose asSuspend (or asSuspendStop) only if the
+ * following conditions are true:
+ *
+ * @li given constant inputs (like 3.0 on all ports), the module will
+ * give constant output after some time
+ * @li given only 0.0 inputs, the module will give only 0.0 outputs
+ * after some time
+ * @li the module does not synchronize itself through signal flow (i.e.
+ * a midi sequence which "knows" when a second has passed through
+ * the signal flow breaks when suspension happens)
+ * @li the module can't be brought to do something with a method
+ * invocation (i.e. a module which starts generating noise for
+ * a second whenever the noise() method is called is not suspendable)
+ * @li the module has no internal state that changes over time when only
+ * constant inputs are given
+ *
+ * Typical examples for suspendable modules are arithmetic operations,
+ * filters, delay/hall/reverb.
+ *
+ * Typical examples for non-suspendable modules are sequences, midi stuff,
+ * oscillators, sample players,...
+ *
+ * To deal with modules which either input data from some external source
+ * (i.e. soundcard input) or output data to some external destination,
+ * (i.e. soundcard output) the following flags are available:
+ *
+ * @li asProducer - set this flag for modules which fulfill the conditions
+ * for a suspendable module, but produce non-zero output
+ * even when left alone
+ * @li asConsumer - set this flag for modules which write the data to
+ * some external destination - that is - definitely
+ * require constant input to be suspended
+ *
+ * The suspension algorithm will first divide the graph of modules into
+ * subgraphs of interconnected modules. A subgraph is suspendable if
+ * all of its modules are suspendable and the subgraph does not contain
+ * producer(s) and consumer(s) at the same time.
+ *
+ * Finally, our module graph is suspendable if all its subgraphs are.
+ */
+ readonly attribute AutoSuspendState autoSuspend;
+};
+
+/**
+ * Plays a stream of audio data to the soundcard
+ */
+interface Synth_PLAY : SynthModule {
+ // attribute string channels;
+ default in audio stream invalue_left,invalue_right;
+};
+
+/**
+ * Records a stream of audio data from the soundcard
+ */
+interface Synth_RECORD : SynthModule {
+ // attribute string channels;
+ default out audio stream left,right;
+};
+
+/**
+ * A frequency generator
+ *
+ * This kind of object is used to create frequencies. Oscillators are connected
+ * at the output of this object
+ */
+interface Synth_FREQUENCY : SynthModule {
+ in audio stream frequency;
+ out audio stream pos;
+};
+
+/**
+ * A sine wave
+ */
+interface Synth_WAVE_SIN : SynthModule {
+ in audio stream pos;
+ out audio stream outvalue;
+};
+
+/**
+ * A module which mixes an arbitary number of audio streams
+ */
+interface Synth_MULTI_ADD : SynthModule {
+ in multi audio stream invalue;
+ out audio stream outvalue;
+};
+
+/**
+ * A module which adds two audio streams
+ */
+interface Synth_ADD : SynthModule {
+ default in audio stream invalue1,invalue2;
+ out audio stream outvalue;
+};
+
+/**
+ * Multiplies two audio streams
+ */
+interface Synth_MUL : SynthModule {
+ in audio stream invalue1,invalue2;
+ out audio stream outvalue;
+ default invalue1, invalue2;
+};
+
+/**
+ * This plays a wave file
+ */
+interface Synth_PLAY_WAV : SynthModule {
+ /**
+ * How fast should it be played? 1.0 = normal speed
+ */
+ attribute float speed;
+ /**
+ * Which file should be played
+ */
+ attribute string filename;
+ /**
+ * Is true as soon as the file is finished
+ */
+ readonly attribute boolean finished;
+
+ out audio stream left, right;
+ default left, right;
+};
+
+/**
+ * sends data to a bus - busses are dynamic N:M connections - all signals
+ * from all uplinks are mixed together, and sent to all downlinks
+ */
+interface Synth_BUS_UPLINK : SynthModule {
+ /**
+ * the name of the bus to use
+ */
+ attribute string busname;
+
+ default in audio stream left,right;
+};
+
+/**
+ * receives data from a bus - busses are dynamic N:M connections - all signals
+ * from all uplinks are mixed together, and sent to all downlinks
+ */
+interface Synth_BUS_DOWNLINK : SynthModule {
+ /**
+ * the name of the bus to use
+ */
+ attribute string busname;
+
+ default out audio stream left,right;
+};
+
+
+/**
+ * Byte stream to audio conversion object
+ *
+ * Converts an asynchronous byte stream to a synchronous audio stream
+ */
+interface ByteStreamToAudio : SynthModule {
+ attribute long samplingRate;
+ attribute long channels;
+ attribute long bits;
+
+ /**
+ * is conversion currently running, or is it stalled due to the fact
+ * that there is not enough input input?
+ */
+ readonly attribute boolean running;
+
+ async in byte stream indata;
+
+ out audio stream left,right;
+ default left;
+ default right;
+};
+
+/**
+ * Audio to Byte stream conversion object
+ *
+ * Converts a synchronous audio stream to an asynchronous byte stream
+ */
+interface AudioToByteStream : SynthModule {
+ attribute long samplingRate;
+ attribute long channels;
+ attribute long bits;
+
+ async out byte stream outdata;
+
+ in audio stream left,right;
+ default left;
+ default right;
+};
+
+/**
+ * Base interface for all stereo effects
+ */
+interface StereoEffect : SynthModule {
+ default in audio stream inleft, inright;
+ default out audio stream outleft, outright;
+};
+
+/**
+ * this is a simple clipping stereo volume control
+ */
+interface StereoVolumeControl : StereoEffect {
+ attribute float scaleFactor;
+ readonly attribute float currentVolumeLeft;
+ readonly attribute float currentVolumeRight;
+};
+
+/**
+ * A funny FFT scope
+ */
+interface StereoFFTScope : StereoEffect {
+ readonly attribute sequence<float> scope;
+};
+
+/**
+ * A stack of stereo effects
+ */
+interface StereoEffectStack : StereoEffect {
+ /**
+ * inserts an effect at the top side (= directly after the input)
+ *
+ * @returns an ID which can be used to remove the effect again
+ */
+ long insertTop(StereoEffect effect, string name);
+
+ /**
+ * inserts an effect at the bottom (= close to the output) side
+ *
+ * @returns an ID which can be used to remove the effect again
+ */
+ long insertBottom(StereoEffect effect, string name);
+
+ /**
+ * removes an effect again
+ */
+ void remove(long ID);
+};
+
+/*
+ * Audio Manager stuff
+ */
+
+enum AudioManagerDirection { amPlay, amRecord };
+
+/**
+ * Information structure for audio manager clients
+ */
+struct AudioManagerInfo {
+ long ID;
+ string destination;
+
+ AudioManagerDirection direction;
+ string title, autoRestoreID;
+};
+
+/**
+ * an audio manager client
+ */
+interface AudioManagerClient {
+ readonly attribute long ID;
+ attribute AudioManagerDirection direction;
+ attribute string title, autoRestoreID;
+
+ void constructor(AudioManagerDirection direction, string title,
+ string autoRestoreID);
+};
+
+/**
+ * The audio manager interface
+ */
+interface AudioManager {
+ /**
+ * a list of destinations, where you can play/record data to/from
+ */
+ readonly attribute sequence<string> destinations;
+
+ /**
+ * a list of clients
+ */
+ readonly attribute sequence<AudioManagerInfo> clients;
+
+ /**
+ * this is incremented each time a change is made (i.e. new client attached)
+ * TODO: SHOULD GO AWAY WITH ATTRIBUTE WATCHING
+ */
+ readonly attribute long changes;
+
+ /**
+ * this is used to route a client to another destination
+ */
+ void setDestination(long ID, string destination);
+};
+/**
+ * This is a virtual output port, which you use to play data. Where exactly
+ * this data gets played is managed by the audiomanager.
+ *
+ * Creation: there are two ways to initialize a Synth_AMAN_PLAY - one is
+ * to set title and autoRestoreID to sensible (non empty) values. The other
+ * is to pass an already initialized AudioManagerClient on the constructor.
+ */
+interface Synth_AMAN_PLAY : SynthModule {
+ attribute string title, autoRestoreID;
+ void constructor(AudioManagerClient client);
+
+ default in audio stream left, right;
+};
+
+/**
+ * This is a virtual input port, which you use to record data. Where this
+ * data comes from is in turn managed by the audiomanager.
+ *
+ * Creation: there are two ways to initialize a Synth_AMAN_RECORD - one is
+ * to set title and autoRestoreID to sensible (non empty) values. The other
+ * is to pass an already initialized AudioManagerClient on the constructor.
+ */
+interface Synth_AMAN_RECORD : SynthModule {
+ attribute string title, autoRestoreID;
+ void constructor(AudioManagerClient client);
+
+ default out audio stream left, right;
+};
+
+/* --------------------------------------------------------------------- */
+
+/**
+ * Wraps a datahandle. That is an abstraction for a float value array
+ * which can be directly loaded data from a file or have some
+ * processing stages in between (caching, reversing, cropping...)
+ * which are hidden to this interface.
+ * In contrast to the underlying C++ API, this datahandle is already
+ * open()ed after creation, so you can access its information (like
+ * channelCount) without further action.
+ * A datahandle normally has one more important function: read() which
+ * is not wrapped in MCOP because of the overhead of the data
+ * transfer. (If there is need for sth. like that in the future,
+ * one could maybe find a solution.)
+ */
+interface DataHandle {
+ readonly attribute long bitDepth;
+ readonly attribute long channelCount;
+ readonly attribute long valueCount;
+ /**
+ * error code open() returned
+ */
+ readonly attribute long errorNo;
+};
+
+/**
+ * Represents a datahandle which delivers the data from the underlying
+ * sourceDatahandle in reverse order.
+ */
+interface ReversedDataHandle : DataHandle {
+ void init(DataHandle sourceHandle);
+};
+
+/**
+ * Represents a datahandle which delivers an "inner" part of the data
+ * from the underlying sourceDatahandle. You can cut away parts at the
+ * start and/or the end with this.
+ */
+interface CroppedDataHandle : DataHandle {
+ void init(DataHandle sourceHandle,
+ long headCutValueCount,
+ long tailCutValueCount);
+};
+
+/**
+ * Represents a datahandle which delivers the data from the underlying
+ * sourceDatahandle without the "inner" part containing the values
+ * [cutOffset..cutOffset+cutValueCount-1], which will be cut away.
+ */
+interface CutDataHandle : DataHandle {
+ void init(DataHandle sourceHandle,
+ long cutOffset,
+ long cutValueCount);
+};
+
+/**
+ * DataHandlePlay uses a gsl_wave_osc to play back data from a
+ * DataHandle using sophisticated anti-aliasing filtering and caching
+ * techniques. (Though not implemented at the time of writing this, it
+ * will be optimized for cases where the anti-aliasing is not needed
+ * because the mixerFrequency equals the current soundserver's.)
+ */
+interface DataHandlePlay : SynthModule {
+ /**
+ * Which data should be played?
+ */
+ attribute DataHandle handle;
+ /**
+ * What is the normal mixer frequency the data from the handle
+ * should be played back at? (default: current mixing frequency
+ * of the soundserver, e.g. 44100)
+ */
+ attribute float mixerFrequency;
+ /**
+ * Which channel of the datahandle should by played?
+ * (defaults to 0 = the first channel)
+ */
+ attribute long channelIndex;
+ /**
+ * How fast should the data be played?
+ * (defaults to 1.0 = normal speed, see mixerFrequency)
+ */
+ attribute float speed;
+ /**
+ * Current position while playing, in fact it's the index in the
+ * datahandle, so 0 <= pos < handle.valueCount
+ */
+ attribute long pos;
+ /**
+ * Is true as soon as the file is finished
+ */
+ readonly attribute boolean finished;
+ /**
+ * Can be used to pause and/or continue playing
+ */
+ attribute boolean paused;
+
+ default out audio stream outvalue;
+
+ DataHandlePlay clone();
+};
+
+/**
+ * DataHandle which represents sample data loaded from a file. Note
+ * that the samples from all channels are interleaved, that is, the
+ * samples of the first channel in a stereo file are found at offsets
+ * 0,2,4,6,.. etc.
+ */
+interface WaveDataHandle : DataHandle {
+ /**
+ * Properties of the loaded sample data. Note that those
+ * properties are only available from a WaveDataHandle, but may be
+ * available from a DataHandle in the future.
+ */
+ readonly attribute float mixerFrequency;
+ readonly attribute float oscillatorFrequency;
+
+ /**
+ * Load the first wavechunk from a file and return true on
+ * success. A more specific error code is not available at the
+ * moment.
+ */
+ boolean load(string filename);
+
+ /**
+ * Load a specific wavechunk from a file and return true on
+ * success. A more specific error code is not available at the
+ * moment.
+ */
+ boolean load(string filename,
+ long waveIndex, long chunkIndex);
+
+ /**
+ * Return true if and only if a wavechunk was successfully loaded
+ * from a file.
+ */
+ readonly attribute boolean isLoaded;
+
+ /**
+ * Creates a DataHandlePlay object with the important attributes
+ * handle, mixerFrequency and channelCount already set to play
+ * this WaveDataHandle.
+ */
+ DataHandlePlay createPlayer();
+};
+
+};
diff --git a/flow/asyncschedule.cc b/flow/asyncschedule.cc
new file mode 100644
index 0000000..b3251a7
--- /dev/null
+++ b/flow/asyncschedule.cc
@@ -0,0 +1,553 @@
+ /*
+
+ Copyright (C) 2000,2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <iostream>
+#include "asyncschedule.h"
+
+using namespace std;
+using namespace Arts;
+
+#include "debug.h"
+#include <stdio.h>
+
+/* Since this file is a tad bit more complex, here is some basic documentation:
+
+1) ASyncPort: There are asynchronous ports which are parts of the standard-
+ flowsystem schedule nodes. Their lifetime starts whenever an asynchronous
+ stream gets created by the flow system, and ends when the schedule node
+ gets destroyed. Basically, an ASyncPort has two functions:
+
+ * it is a "Port", which means that it gets connect(), disconnect() and
+ other calls from the flowsystem
+
+ * it is a "GenericDataChannel", which means that DataPackets can interact
+ with it
+
+ Although there will be ASyncPorts which only send data and ASyncPorts which
+ only receive data (there are none that do both), there are no distinct
+ classes for this.
+
+2) Standard case: a DataPacket that gets transported over a datachannel locally:
+
+ 1. the user allocates himself a datapacket "packet"
+ 2. the user calls "packet->send()", which in turn calls
+ ASyncPort::sendPacket(packet)
+ 3. the ASyncPort sends the DataPacket to every subscriber (incrementing the
+ useCount) over the NotificationManager
+ 4. the NotificationManager delivers the DataPackets to the receiver
+ 5. eventually, the receiver confirms using "packet->processed()"
+ 6. the packet informs the ASyncPort::processedPacket()
+ 7. the packet is freed
+
+variant (pulling):
+
+ 1. the user gets told by the ASyncPort: produce some data, here is a "packet"
+ 2. the user calls "packet->send()", which in turn calls
+ ASyncPort::sendPacket(packet)
+ 3. the ASyncPort sends the DataPacket to every subscriber (incrementing the
+ useCount) over the NotificationManager
+ 4. the NotificationManager delivers the DataPackets to the receiver
+ 5. eventually, the receiver confirms using "packet->processed()"
+ 6. the packet informs the ASyncPort::processedPacket()
+ 7. the ASyncPort restarts with 1.
+
+3) Remote case: the remote case follows from the local case by adding two extra
+things: one object that converts packets from their packet form to a message
+(ASyncNetSend), and one object that converts packets from the message form
+to a packet again. Effectively, the sending of a single packet looks like
+this, then:
+
+ 1-S. the user allocates himself a datapacket "packet"
+ 2-S. the user calls "packet->send()", which in turn calls
+ ASyncPort::sendPacket(packet)
+ 3-S. the ASyncPort sends the DataPacket to every subscriber (incrementing the
+ useCount) over the NotificationManager
+ 4-S. the NotificationManager delivers the DataPackets to the ASyncNetSend
+ 5-S. the ASyncNetSend::notify method gets called, which in turn converts
+ the packet to a network message
+
+ ... network transfer ...
+
+ 6-R. the ASyncNetReceive::receive method gets called - the method creates
+ a new data packet, and sends it using the NotificationManager again
+ 7-R. the NotificationManager delivers the DataPacket to the receiver
+ 8-R. eventually, the receiver confirms using "packet->processed()"
+ 9-R. the packet informs the ASyncNetReceive::processedPacket() which
+ frees the packet and tells the (remote) sender that it went all right
+
+ ... network transfer ...
+
+ 10-S. eventually, ASyncNetSend::processed() gets called, and confirms
+ the packet using "packet->processed()"
+ 11-S. the packet informs the ASyncPort::processedPacket()
+ 12-S. the packet is freed
+
+variant(pulling):
+
+ works the same as in the local case by exchanging steps 1-S and 12-S
+
+4) ownership:
+
+ * ASyncPort: is owned by the Object which it is a part of, if the object
+ dies, ASyncPort dies unconditionally
+
+ * DataPacket: is owned by the GenericDataChannel they are propagated over,
+ that is, the ASyncPort normally - however if the DataPacket is still in
+ use (i.e. in state 5 of the local case), it will take responsibility to
+ free itself once all processed() calls have been collected
+
+ * ASyncNetSend, ASyncNetReceive: own each other, so that if the sender dies,
+ the connection will die as well, and if the receiver dies, the same happens
+
+*/
+
+#undef DEBUG_ASYNC_TRANSFER
+
+ASyncPort::ASyncPort(const std::string& name, void *ptr, long flags,
+ StdScheduleNode* parent) : Port(name, ptr, flags, parent), pull(false)
+{
+ stream = (GenericAsyncStream *)ptr;
+ stream->channel = this;
+ stream->_notifyID = notifyID = parent->object()->_mkNotifyID();
+}
+
+ASyncPort::~ASyncPort()
+{
+ /*
+ * tell all outstanding packets that we don't exist any longer, so that
+ * if they feel like they need to confirm they have been processed now,
+ * they don't talk to an no longer existing object about it
+ */
+ while(!sent.empty())
+ {
+ sent.front()->channel = 0;
+ sent.pop_front();
+ }
+
+ /* disconnect remote connections (if present): the following things will
+ * need to be ensured here, since we are being deleted:
+ *
+ * - the senders should not talk to us after our destructor
+ * - all of our connections need to be disconnected
+ * - every connection needs to be closed exactly once
+ *
+ * (closing a connection can cause reentrancy due to mcop communication)
+ */
+ while(!netSenders.empty())
+ netSenders.front()->disconnect();
+
+ FlowSystemReceiver receiver = netReceiver;
+ if(!receiver.isNull())
+ receiver.disconnect();
+}
+
+//-------------------- GenericDataChannel interface -------------------------
+
+void ASyncPort::setPull(int packets, int capacity)
+{
+ pullNotification.receiver = parent->object();
+ pullNotification.ID = notifyID;
+ pullNotification.internal = 0;
+ pull = true;
+
+ for(int i=0;i<packets;i++)
+ {
+ GenericDataPacket *packet = stream->createPacket(capacity);
+ packet->useCount = 0;
+ pullNotification.data = packet;
+ NotificationManager::the()->send(pullNotification);
+ }
+}
+
+void ASyncPort::endPull()
+{
+ pull = false;
+ // TODO: maybe remove all pending pull packets here
+}
+
+void ASyncPort::processedPacket(GenericDataPacket *packet)
+{
+ int count = 0;
+ list<GenericDataPacket *>::iterator i = sent.begin();
+ while(i != sent.end())
+ {
+ if(*i == packet)
+ {
+ count++;
+ i = sent.erase(i);
+ }
+ else i++;
+ }
+ assert(count == 1);
+
+#ifdef DEBUG_ASYNC_TRANSFER
+ cout << "port::processedPacket" << endl;
+#endif
+ assert(packet->useCount == 0);
+ if(pull)
+ {
+ pullNotification.data = packet;
+ NotificationManager::the()->send(pullNotification);
+ }
+ else
+ {
+ stream->freePacket(packet);
+ }
+}
+
+void ASyncPort::sendPacket(GenericDataPacket *packet)
+{
+ bool sendOk = false;
+
+#ifdef DEBUG_ASYNC_TRANSFER
+ cout << "port::sendPacket" << endl;
+#endif
+
+ if(packet->size > 0)
+ {
+ vector<Notification>::iterator i;
+ for(i=subscribers.begin(); i != subscribers.end(); i++)
+ {
+ Notification n = *i;
+ n.data = packet;
+ packet->useCount++;
+#ifdef DEBUG_ASYNC_TRANSFER
+ cout << "sending notification " << n.ID << endl;
+#endif
+ NotificationManager::the()->send(n);
+ sendOk = true;
+ }
+ }
+
+ if(sendOk)
+ sent.push_back(packet);
+ else
+ stream->freePacket(packet);
+}
+
+//----------------------- Port interface ------------------------------------
+
+void ASyncPort::connect(Port *xsource)
+{
+ arts_debug("port(%s)::connect",_name.c_str());
+
+ ASyncPort *source = xsource->asyncPort();
+ assert(source);
+ addAutoDisconnect(xsource);
+
+ Notification n;
+ n.receiver = parent->object();
+ n.ID = notifyID;
+ n.internal = 0;
+ source->subscribers.push_back(n);
+}
+
+void ASyncPort::disconnect(Port *xsource)
+{
+ arts_debug("port::disconnect");
+
+ ASyncPort *source = xsource->asyncPort();
+ assert(source);
+ removeAutoDisconnect(xsource);
+
+ // remove our subscription from the source object
+ vector<Notification>::iterator si;
+ for(si = source->subscribers.begin(); si != source->subscribers.end(); si++)
+ {
+ if(si->receiver == parent->object())
+ {
+ source->subscribers.erase(si);
+ return;
+ }
+ }
+
+ // there should have been exactly one, so this shouldn't be reached
+ assert(false);
+}
+
+ASyncPort *ASyncPort::asyncPort()
+{
+ return this;
+}
+
+GenericAsyncStream *ASyncPort::receiveNetCreateStream()
+{
+ return stream->createNewStream();
+}
+
+NotificationClient *ASyncPort::receiveNetObject()
+{
+ return parent->object();
+}
+
+long ASyncPort::receiveNetNotifyID()
+{
+ return notifyID;
+}
+
+// Network transparency
+void ASyncPort::addSendNet(ASyncNetSend *netsend)
+{
+ Notification n;
+ n.receiver = netsend;
+ n.ID = netsend->notifyID();
+ n.internal = 0;
+ subscribers.push_back(n);
+ netSenders.push_back(netsend);
+}
+
+void ASyncPort::removeSendNet(ASyncNetSend *netsend)
+{
+ arts_return_if_fail(netsend != 0);
+ netSenders.remove(netsend);
+
+ vector<Notification>::iterator si;
+ for(si = subscribers.begin(); si != subscribers.end(); si++)
+ {
+ if(si->receiver == netsend)
+ {
+ subscribers.erase(si);
+ return;
+ }
+ }
+ arts_warning("Failed to remove ASyncNetSend (%p) from ASyncPort", netsend);
+}
+
+void ASyncPort::setNetReceiver(ASyncNetReceive *receiver)
+{
+ arts_return_if_fail(receiver != 0);
+
+ FlowSystemReceiver r = FlowSystemReceiver::_from_base(receiver->_copy());
+ netReceiver = r;
+}
+
+void ASyncPort::disconnectRemote(const string& dest)
+{
+ list<ASyncNetSend *>::iterator i;
+
+ for(i = netSenders.begin(); i != netSenders.end(); i++)
+ {
+ if((*i)->dest() == dest)
+ {
+ (*i)->disconnect();
+ return;
+ }
+ }
+ arts_warning("failed to disconnect %s in ASyncPort", dest.c_str());
+}
+
+ASyncNetSend::ASyncNetSend(ASyncPort *ap, const std::string& dest) : ap(ap)
+{
+ _dest = dest;
+ ap->addSendNet(this);
+}
+
+ASyncNetSend::~ASyncNetSend()
+{
+ while(!pqueue.empty())
+ {
+ pqueue.front()->processed();
+ pqueue.pop();
+ }
+ if(ap)
+ {
+ ap->removeSendNet(this);
+ ap = 0;
+ }
+}
+
+long ASyncNetSend::notifyID()
+{
+ return 1;
+}
+
+void ASyncNetSend::notify(const Notification& notification)
+{
+ // got a packet?
+ assert(notification.ID == notifyID());
+ GenericDataPacket *dp = (GenericDataPacket *)notification.data;
+ pqueue.push(dp);
+
+ /*
+ * since packets are delivered asynchronously, and since disconnection
+ * involves communication, it might happen that we get a packet without
+ * actually being connected any longer - in that case, silently forget it
+ */
+ if(!receiver.isNull())
+ {
+ // put it into a custom data message and send it to the receiver
+ Buffer *buffer = receiver._allocCustomMessage(receiveHandlerID);
+ dp->write(*buffer);
+ receiver._sendCustomMessage(buffer);
+ }
+}
+
+void ASyncNetSend::processed()
+{
+ assert(!pqueue.empty());
+ pqueue.front()->processed();
+ pqueue.pop();
+}
+
+void ASyncNetSend::setReceiver(FlowSystemReceiver newReceiver)
+{
+ receiver = newReceiver;
+ receiveHandlerID = newReceiver.receiveHandlerID();
+}
+
+void ASyncNetSend::disconnect()
+{
+ /* since disconnection will cause destruction (most likely immediate),
+ * we'll reference ourselves ... */
+ _copy();
+
+ if(!receiver.isNull())
+ {
+ FlowSystemReceiver r = receiver;
+ receiver = FlowSystemReceiver::null();
+ r.disconnect();
+ }
+ if(ap)
+ {
+ ap->removeSendNet(this);
+ ap = 0;
+ }
+
+ _release();
+}
+
+string ASyncNetSend::dest()
+{
+ return _dest;
+}
+
+/* dispatching function for custom message */
+
+static void _dispatch_ASyncNetReceive_receive(void *object, Buffer *buffer)
+{
+ ((ASyncNetReceive *)object)->receive(buffer);
+}
+
+ASyncNetReceive::ASyncNetReceive(ASyncPort *port, FlowSystemSender sender)
+{
+ port->setNetReceiver(this);
+ stream = port->receiveNetCreateStream();
+ stream->channel = this;
+ this->sender = sender;
+ /* stream->_notifyID = _mkNotifyID(); */
+
+ gotPacketNotification.ID = port->receiveNetNotifyID();
+ gotPacketNotification.receiver = port->receiveNetObject();
+ gotPacketNotification.internal = 0;
+ _receiveHandlerID =
+ _addCustomMessageHandler(_dispatch_ASyncNetReceive_receive,this);
+}
+
+ASyncNetReceive::~ASyncNetReceive()
+{
+ /* tell outstanding packets that we don't exist any longer */
+ while(!sent.empty())
+ {
+ sent.front()->channel = 0;
+ sent.pop_front();
+ }
+ delete stream;
+}
+
+long ASyncNetReceive::receiveHandlerID()
+{
+ return _receiveHandlerID;
+}
+
+void ASyncNetReceive::receive(Buffer *buffer)
+{
+ GenericDataPacket *dp = stream->createPacket(512);
+ dp->read(*buffer);
+ dp->useCount = 1;
+ gotPacketNotification.data = dp;
+ NotificationManager::the()->send(gotPacketNotification);
+ sent.push_back(dp);
+}
+
+/*
+ * It will happen that this routine is called in time critical situations,
+ * such as: while audio calculation is running, and must be finished in
+ * time. The routine is mostly harmless, because sender->processed() is
+ * a oneway function, which just queues the buffer for sending and returns
+ * back, so it should return at once.
+ *
+ * However there is an exception upon first call: when sender->processed()
+ * is called for the first time, the method processed has still to be looked
+ * up. Thus, a synchronous call to _lookupMethod is made. That means, upon
+ * first call, the method will send out an MCOP request and block until the
+ * remote process tells that id.
+ */
+void ASyncNetReceive::processedPacket(GenericDataPacket *packet)
+{
+ /*
+ * HACK! Upon disconnect, strange things will happen. One of them is
+ * that we might, for the reason of not being referenced any longer,
+ * cease to exist without warning. Another is that our nice "sender"
+ * reference will get a null reference without warning, see disconnect
+ * code (which will cause the attached stub to also disappear). As
+ * those objects (especially the stub) are not prepared for not
+ * being there any more in the middle of whatever they do, we here
+ * explicitly reference us, and them, *again*, so that no evil things
+ * will happen. A general solution for this would be garbage collection
+ * in a timer, but until this is implemented (if it ever will become
+ * implemented), we'll live with this hack.
+ */
+ _copy();
+ sent.remove(packet);
+ stream->freePacket(packet);
+ if(!sender.isNull())
+ {
+ FlowSystemSender xsender = sender;
+ xsender.processed();
+ }
+ _release();
+}
+
+void ASyncNetReceive::disconnect()
+{
+ if(!sender.isNull())
+ {
+ FlowSystemSender s = sender;
+ sender = FlowSystemSender::null();
+ s.disconnect();
+ }
+}
+
+void ASyncNetReceive::sendPacket(GenericDataPacket *)
+{
+ assert(false);
+}
+
+void ASyncNetReceive::setPull(int, int)
+{
+ assert(false);
+}
+
+void ASyncNetReceive::endPull()
+{
+ assert(false);
+}
diff --git a/flow/asyncschedule.h b/flow/asyncschedule.h
new file mode 100644
index 0000000..0477c9a
--- /dev/null
+++ b/flow/asyncschedule.h
@@ -0,0 +1,134 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ASYNCSCHEDULE_H
+#define ASYNCSCHEDULE_H
+
+#include "gslschedule.h"
+#include "datapacket.h"
+#include "weakreference.h"
+
+#include <queue>
+
+/*
+ * BC - Status (2002-03-08): ASyncNetSend, ASyncNetReceive, ASyncPort.
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of libartsflow's
+ * StdFlowSystem, and subject to change with the needs of it.
+ */
+
+namespace Arts {
+
+class ASyncPort;
+class ASyncNetSend : public FlowSystemSender_skel
+{
+protected:
+ ASyncPort *ap;
+ std::queue<GenericDataPacket *> pqueue;
+ FlowSystemReceiver receiver;
+ long receiveHandlerID;
+ std::string _dest;
+
+public:
+ ASyncNetSend(ASyncPort *ap, const std::string& dest);
+ ~ASyncNetSend();
+ long notifyID();
+ std::string dest();
+
+ /* this overwrites the Object::notify function */
+ void notify(const Notification& notification);
+ void processed();
+ void setReceiver(FlowSystemReceiver receiver);
+ void disconnect();
+};
+
+class ASyncNetReceive : public FlowSystemReceiver_skel,
+ public GenericDataChannel
+{
+protected:
+ GenericAsyncStream *stream;
+ FlowSystemSender sender;
+ Notification gotPacketNotification;
+ std::list<GenericDataPacket *> sent;
+ long _receiveHandlerID;
+
+public:
+ ASyncNetReceive(ASyncPort *port, FlowSystemSender sender);
+ ~ASyncNetReceive();
+
+ // GenericDataChannel interface
+ void processedPacket(GenericDataPacket *packet);
+ void sendPacket(GenericDataPacket *packet);
+ void setPull(int packets, int capacity);
+ void endPull();
+
+ // FlowSystemReceiver interface
+
+ long receiveHandlerID();
+ void disconnect();
+ void receive(Buffer *buffer); // custom data receiver
+};
+
+class ASyncPort :public Port, public GenericDataChannel {
+protected:
+ long notifyID;
+ std::vector<Notification> subscribers;
+ std::list<GenericDataPacket *> sent;
+ std::list<ASyncNetSend *> netSenders;
+ WeakReference<FlowSystemReceiver> netReceiver;
+
+ GenericAsyncStream *stream;
+
+ bool pull;
+ Notification pullNotification;
+
+public:
+ // GenericDataChannel interface
+ void processedPacket(GenericDataPacket *packet);
+ void sendPacket(GenericDataPacket *packet);
+ void setPull(int packets, int capacity);
+ void endPull();
+
+ // Port interface
+ ASyncPort(const std::string& name, void *ptr, long flags,
+ StdScheduleNode* parent);
+ ~ASyncPort();
+
+ void connect(Port *port);
+ void disconnect(Port *port);
+ ASyncPort *asyncPort();
+
+ // Network transparency
+ void addSendNet(ASyncNetSend *netsend); // send
+ void removeSendNet(ASyncNetSend *netsend);
+ void disconnectRemote(const std::string& dest);
+
+ long receiveNetNotifyID(); // receive
+ GenericAsyncStream *receiveNetCreateStream();
+ NotificationClient *receiveNetObject();
+ void setNetReceiver(ASyncNetReceive *receiver);
+};
+
+}
+
+#endif /* ASYNCSCHEDULE_H */
diff --git a/flow/audioio.cc b/flow/audioio.cc
new file mode 100644
index 0000000..e5924ab
--- /dev/null
+++ b/flow/audioio.cc
@@ -0,0 +1,165 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "audioio.h"
+#include <map>
+#include <list>
+#include <assert.h>
+#include <cstring>
+
+using namespace Arts;
+using namespace std;
+
+class Arts::AudioIOPrivate {
+public:
+ map<AudioIO::AudioParam, int> paramMap;
+ map<AudioIO::AudioParam, string> paramStrMap;
+};
+
+AudioIO::AudioIO() :d(new AudioIOPrivate)
+{
+}
+
+AudioIO::~AudioIO()
+{
+ delete d;
+}
+
+int& AudioIO::param(AudioParam param)
+{
+ /*
+ * returns d->paramMap[param], initializes new elements with -1 (for those
+ * parameters not handled explicitly by the derived AudioIO* class).
+ */
+
+ map<AudioIO::AudioParam, int>::iterator pi = d->paramMap.find(param);
+ if(pi == d->paramMap.end())
+ {
+ int& result = d->paramMap[param];
+ result = -1;
+ return result;
+ }
+ else return pi->second;
+}
+
+string& AudioIO::paramStr(AudioParam param)
+{
+ return d->paramStrMap[param];
+}
+
+void AudioIO::setParamStr(AudioParam p, const char *value)
+{
+ paramStr(p) = value;
+}
+
+void AudioIO::setParam(AudioParam p, int& value)
+{
+ param(p) = value;
+}
+
+int AudioIO::getParam(AudioParam p)
+{
+ return param(p);
+}
+
+const char *AudioIO::getParamStr(AudioParam p)
+{
+ return paramStr(p).c_str();
+}
+
+/* ---- factories ---- */
+
+static list<AudioIOFactory *> *audioIOFactories = 0;
+
+AudioIO *AudioIO::createAudioIO(const char *name)
+{
+ if(audioIOFactories)
+ {
+ list<AudioIOFactory *>::iterator i;
+ for(i = audioIOFactories->begin(); i != audioIOFactories->end(); i++)
+ {
+ AudioIOFactory *factory = *i;
+
+ if(strcmp(factory->name(),name) == 0)
+ return factory->createAudioIO();
+ }
+ }
+ return 0;
+}
+
+int AudioIO::queryAudioIOCount()
+{
+ return audioIOFactories->size();
+}
+
+int AudioIO::queryAudioIOParam(int /*audioIO*/, AudioParam /*p*/)
+{
+ return 0;
+}
+
+const char *AudioIO::queryAudioIOParamStr(int audioIO, AudioParam p)
+{
+ list<AudioIOFactory *>::iterator i = audioIOFactories->begin();
+
+ while(audioIO && i != audioIOFactories->end()) { i++; audioIO--; }
+ if(i == audioIOFactories->end()) return 0;
+
+ switch(p)
+ {
+ case name:
+ return (*i)->name();
+ case fullName:
+ return (*i)->fullName();
+ default:
+ return 0;
+ }
+}
+
+void AudioIO::addFactory(AudioIOFactory *factory)
+{
+ if(!audioIOFactories)
+ audioIOFactories = new list<AudioIOFactory *>;
+
+ audioIOFactories->push_back(factory);
+}
+
+void AudioIO::removeFactory(AudioIOFactory *factory)
+{
+ assert(audioIOFactories);
+
+ audioIOFactories->remove(factory);
+ if(audioIOFactories->empty())
+ {
+ delete audioIOFactories;
+ audioIOFactories = 0;
+ }
+}
+
+void AudioIOFactory::startup()
+{
+ AudioIO::addFactory(this);
+}
+
+void AudioIOFactory::shutdown()
+{
+ AudioIO::removeFactory(this);
+}
diff --git a/flow/audioio.h b/flow/audioio.h
new file mode 100644
index 0000000..ade96e2
--- /dev/null
+++ b/flow/audioio.h
@@ -0,0 +1,145 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_AUDIOIO_H
+#define ARTS_AUDIOIO_H
+
+#include <startupmanager.h>
+#include <string>
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): AudioIO, AudioIOFactory
+ *
+ * Right now, these classes are considered an implementation detail. No binary
+ * compatibility guaranteed, its safe to add virtual methods when required.
+ */
+
+/*
+ * The AudioIO class - it is used as follows:
+ *
+ * 1. check the settings with getParam, modify what you don't like
+ * 2. call open -> print getInfo(lastError) if it failed (returned false)
+ * 3. check whether the settings are still what you expected them to
+ * be (as the AudioIO class will maybe only know after open if the
+ * requested parameters can be achieved)
+ */
+
+namespace Arts {
+
+class AudioIOPrivate;
+class AudioIOFactory;
+
+class ARTS_EXPORT AudioIO {
+private:
+ class AudioIOPrivate *d;
+
+public:
+ enum AudioParam {
+/* the following has to be supported */
+ samplingRate = 1, /* usually 4000..48000 (Hz) */
+ channels = 2, /* usually 1 (mono) or 2 (stereo) */
+ format = 3, /* 8 = 8bit unsigned
+ * 16 = 16bit signed little endian
+ * 17 = 16bit signed big endian
+ * 32 = 32bit float */
+
+/* the following -can- be supported (value=-1 if they are not) */
+ direction = 101, /* 1 = read, 2 = write, 3 = read|write */
+ fragmentCount = 102,/* usually 3..16 (to control latency) */
+ fragmentSize = 103, /* usually 256,512,...8192 (a 2^N value) */
+ canRead = 104, /* the amount of bytes that can be read */
+ canWrite = 105, /* the amount of bytes that can be written */
+ selectReadFD = 106, /* filedescriptor to be select()ed on for reading */
+ selectWriteFD = 107,/* filedescriptor to be select()ed on for writing */
+ autoDetect = 108, /* 0 = don't use this as default
+ * 1 or higher = preference of using this as default
+ *
+ * if nothing else is specified, aRts asks all
+ * available AudioIO classes for the autoDetect
+ * value and chooses the one which returned the
+ * highest number */
+
+/* string parameters that have to be supported */
+ lastError = 201, /* the last error message as human readable text */
+
+/* string parameters that -can- be supported */
+ deviceName = 301, /* name of the device to open */
+
+/* class parameters: same semantics as above */
+ name = 1201, /* name of the driver (i.e. oss) */
+ fullName = 1202 /* full name (i.e. Open Sound System) */
+ };
+
+ enum {
+ directionRead = 1,
+ directionWrite = 2,
+ directionReadWrite = 3
+ };
+
+ AudioIO();
+ virtual ~AudioIO();
+
+ virtual void setParamStr(AudioParam param, const char *value);
+ virtual void setParam(AudioParam param, int& value);
+ virtual int getParam(AudioParam param);
+ virtual const char *getParamStr(AudioParam param);
+
+ virtual bool open() = 0;
+ virtual void close() = 0;
+ virtual int read(void *buffer, int size) = 0;
+ virtual int write(void *buffer, int size) = 0;
+
+/* ---- factory querying stuff ---- */
+ static int queryAudioIOCount();
+ static int queryAudioIOParam(int audioIO, AudioParam param);
+ static const char *queryAudioIOParamStr(int audioIO, AudioParam param);
+
+/* ---- factory stuff ---- */
+ static AudioIO *createAudioIO(const char *name);
+ static void addFactory(AudioIOFactory *factory);
+ static void removeFactory(AudioIOFactory *factory);
+
+protected:
+ int& param(AudioParam param);
+ std::string& paramStr(AudioParam param);
+};
+
+class ARTS_EXPORT AudioIOFactory : public StartupClass {
+public:
+ void startup();
+ void shutdown();
+ virtual AudioIO *createAudioIO() = 0;
+ virtual const char *name() = 0;
+ virtual const char *fullName() = 0;
+};
+
+}
+
+#define REGISTER_AUDIO_IO(impl,implName,implFullName) \
+ static class AudioIOFactory ## impl : public AudioIOFactory { \
+ public: \
+ AudioIO *createAudioIO() { return new impl(); } \
+ virtual const char *name() { return implName; } \
+ virtual const char *fullName() { return implFullName; } \
+ } The_ ## impl ## _Factory /* <- add semicolon when calling this macro */
+
+#endif /* ARTS_AUDIOIO_H */
diff --git a/flow/audioioaix.cc b/flow/audioioaix.cc
new file mode 100644
index 0000000..f36e9db
--- /dev/null
+++ b/flow/audioioaix.cc
@@ -0,0 +1,390 @@
+/*
+
+ Copyright (C) 2001 Carsten Griwodz
+ griff@ifi.uio.no
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef _AIX
+
+/*
+ * The audio header files exist even if there is not soundcard the
+ * the AIX machine. You won't be able to compile this code on AIX3
+ * which had ACPA support, so /dev/acpa is not checked here.
+ * I have no idea whether the Ultimedia Audio Adapter is actually
+ * working or what it is right now.
+ * For PCI machines including PowerSeries 850, baud or paud should
+ * work. The DSP (MWave?) of the 850 laptops may need microcode
+ * download. This is not implemented.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/machine.h>
+#undef BIG_ENDIAN
+#include <sys/audio.h>
+
+#ifndef AUDIO_BIG_ENDIAN
+#define AUDIO_BIG_ENDIAN BIG_ENDIAN
+#endif
+
+#include "debug.h"
+#include "audioio.h"
+
+namespace Arts {
+
+class AudioIOAIX : public AudioIO {
+ int openDevice();
+
+protected:
+ int audio_fd;
+
+public:
+ AudioIOAIX();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOAIX,"paud","Personal Audio Device");
+};
+
+using namespace std;
+using namespace Arts;
+
+int AudioIOAIX::openDevice()
+{
+ char devname[14];
+ int fd;
+ for ( int dev=0; dev<4; dev++ )
+ {
+ for ( int chan=1; chan<8; chan++ )
+ {
+ sprintf(devname,"/dev/paud%d/%d",dev,chan);
+ fd = ::open (devname, O_WRONLY, 0);
+ if ( fd >= 0 )
+ {
+ paramStr(deviceName) = devname;
+ return fd;
+ }
+ sprintf(devname,"/dev/baud%d/%d",dev,chan);
+ fd = ::open (devname, O_WRONLY, 0);
+ if ( fd >= 0 )
+ {
+ paramStr(deviceName) = devname;
+ return fd;
+ }
+ }
+ }
+ return -1;
+}
+
+AudioIOAIX::AudioIOAIX()
+{
+ int fd = openDevice();
+ if( fd >= 0 )
+ {
+ audio_status audioStatus;
+ memset( &audioStatus, 0, sizeof(audio_status) );
+ ioctl(fd, AUDIO_STATUS, &audioStatus);
+
+ audio_buffer audioBuffer;
+ memset( &audioBuffer, 0, sizeof(audio_buffer) );
+ ioctl(fd, AUDIO_BUFFER, &audioBuffer);
+
+ ::close( fd );
+
+ /*
+ * default parameters
+ */
+ param(samplingRate) = audioStatus.srate;
+ param(fragmentSize) = audioStatus.bsize;
+ param(fragmentCount) = audioBuffer.write_buf_cap / audioStatus.bsize;
+ param(channels) = audioStatus.channels;
+ param(direction) = 2;
+
+ param(format) = ( audioStatus.bits_per_sample==8 ) ? 8
+ : ( ( audioStatus.flags & AUDIO_BIG_ENDIAN ) ? 17 : 16 );
+ }
+}
+
+bool AudioIOAIX::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+
+ int mode;
+
+ switch( param(direction) )
+ {
+ case 1 : mode = O_RDONLY | O_NDELAY; break;
+ case 2 : mode = O_WRONLY | O_NDELAY; break;
+ case 3 :
+ _error = "open device twice to RDWR";
+ return false;
+ default :
+ _error = "invalid direction";
+ return false;
+ }
+
+ audio_fd = ::open(_deviceName.c_str(), mode, 0);
+
+ if(audio_fd == -1)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+
+ if( (_channels!=1) && (_channels!=2) )
+ {
+ _error = "internal error; set channels to 1 (mono) or 2 (stereo)";
+
+ close();
+ return false;
+ }
+
+ // int requeststereo = stereo;
+
+ // int speed = _samplingRate;
+
+ audio_init audioInit;
+ memset( &audioInit, 0, sizeof(audio_init) );
+ audioInit.srate = _samplingRate;
+ audioInit.bits_per_sample = ((_format==8)?8:16);
+ audioInit.bsize = _fragmentSize;
+ audioInit.mode = PCM;
+ audioInit.channels = _channels;
+ audioInit.flags = 0;
+ audioInit.flags |= (_format==17) ? AUDIO_BIG_ENDIAN : 0;
+ audioInit.flags |= (_format==8) ? 0 : SIGNED;
+ audioInit.operation = (param(direction)==1) ? RECORD : PLAY;
+
+ if ( ioctl(audio_fd, AUDIO_INIT, &audioInit) < 0 )
+ {
+ _error = "AUDIO_INIT failed - ";
+ _error += strerror(errno);
+ switch ( audioInit.rc )
+ {
+ case 1 :
+ _error += "Couldn't set audio format: DSP can't do play requests";
+ break;
+ case 2 :
+ _error += "Couldn't set audio format: DSP can't do record requests";
+ break;
+ case 4 :
+ _error += "Couldn't set audio format: request was invalid";
+ break;
+ case 5 :
+ _error += "Couldn't set audio format: conflict with open's flags";
+ break;
+ case 6 :
+ _error += "Couldn't set audio format: out of DSP MIPS or memory";
+ break;
+ default :
+ _error += "Couldn't set audio format: not documented in sys/audio.h";
+ break;
+ }
+
+ close();
+ return false;
+ }
+
+ if (audioInit.channels != _channels)
+ {
+ _error = "audio device doesn't support number of requested channels";
+ close();
+ return false;
+ }
+
+ switch( _format )
+ {
+ case 8 :
+ if (audioInit.flags&AUDIO_BIG_ENDIAN==1)
+ {
+ _error = "setting little endian format failed";
+ close();
+ return false;
+ }
+ if (audioInit.flags&SIGNED==1)
+ {
+ _error = "setting unsigned format failed";
+ close();
+ return false;
+ }
+ break;
+ case 16 :
+ if (audioInit.flags&AUDIO_BIG_ENDIAN==1)
+ {
+ _error = "setting little endian format failed";
+ close();
+ return false;
+ }
+ if (audioInit.flags&SIGNED==0)
+ {
+ _error = "setting signed format failed";
+ close();
+ return false;
+ }
+ break;
+ case 17 :
+ if (audioInit.flags&AUDIO_BIG_ENDIAN==0)
+ {
+ _error = "setting big endian format failed";
+ close();
+ return false;
+ }
+ if (audioInit.flags&SIGNED==0)
+ {
+ _error = "setting signed format failed";
+ close();
+ return false;
+ }
+ break;
+ default :
+ break;
+ }
+
+ /*
+ * Some soundcards seem to be able to only supply "nearly" the requested
+ * sampling rate, especially PAS 16 cards seem to quite radical supplying
+ * something different than the requested sampling rate ;)
+ *
+ * So we have a quite large tolerance here (when requesting 44100 Hz, it
+ * will accept anything between 38690 Hz and 49510 Hz). Most parts of the
+ * aRts code will do resampling where appropriate, so it shouldn't affect
+ * sound quality.
+ */
+ int tolerance = _samplingRate/10+1000;
+
+ if (abs(audioInit.srate - _samplingRate) > tolerance)
+ {
+ _error = "can't set requested samplingrate";
+
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %ld)",
+ _samplingRate, audioInit.srate);
+ _error += details;
+
+ close();
+ return false;
+ }
+ _samplingRate = audioInit.srate;
+
+ _fragmentSize = audioInit.bsize;
+ _fragmentCount = audioInit.bsize / audioInit.bits_per_sample;
+
+ audio_buffer buffer_info;
+ ioctl(audio_fd, AUDIO_BUFFER, &buffer_info);
+ _fragmentCount = buffer_info.write_buf_cap / audioInit.bsize;
+
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+ return true;
+}
+
+void AudioIOAIX::close()
+{
+ ::close(audio_fd);
+}
+
+void AudioIOAIX::setParam(AudioParam p, int& value)
+{
+ param(p) = value;
+}
+
+int AudioIOAIX::getParam(AudioParam p)
+{
+ audio_buffer info;
+ switch(p)
+ {
+ case canRead:
+ ioctl(audio_fd, AUDIO_BUFFER, &info);
+ return (info.read_buf_cap - info.read_buf_size);
+ break;
+
+ case canWrite:
+ ioctl(audio_fd, AUDIO_BUFFER, &info);
+ return (info.write_buf_cap - info.write_buf_size);
+ break;
+
+ case selectReadFD:
+ return (param(direction) & directionRead)?audio_fd:-1;
+ break;
+
+ case selectWriteFD:
+ return (param(direction) & directionWrite)?audio_fd:-1;
+ break;
+
+ case autoDetect:
+ /* You may prefer OSS if it works, e.g. on 43P 240
+ * or you may prefer UMS, if anyone bothers to write
+ * a module for it.
+ */
+ return 2;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOAIX::read(void *buffer, int size)
+{
+ arts_assert(audio_fd != 0);
+ return ::read(audio_fd,buffer,size);
+}
+
+int AudioIOAIX::write(void *buffer, int size)
+{
+ arts_assert(audio_fd != 0);
+ return ::write(audio_fd,buffer,size);
+}
+
+#endif
+
diff --git a/flow/audioioalsa.cc b/flow/audioioalsa.cc
new file mode 100644
index 0000000..303db16
--- /dev/null
+++ b/flow/audioioalsa.cc
@@ -0,0 +1,561 @@
+ /*
+
+ Copyright (C) 2000,2001 Jozef Kosoru
+ jozef.kosoru@pobox.sk
+ (C) 2000,2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile 'alsa' AudioIO class if configure thinks it is a good idea
+ */
+#ifdef HAVE_LIBASOUND
+
+#ifdef HAVE_ALSA_ASOUNDLIB_H
+#include <alsa/asoundlib.h>
+#elif defined(HAVE_SYS_ASOUNDLIB_H)
+#include <sys/asoundlib.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h> // Needed on some systems.
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+
+namespace Arts {
+
+class AudioIOALSA : public AudioIO {
+protected:
+ int audio_read_fd;
+ int audio_write_fd;
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+
+ enum BufferMode{block, stream};
+ int m_card;
+ int m_device;
+ int m_format;
+ BufferMode m_bufferMode;
+
+ snd_pcm_t *m_pcm_handle;
+ snd_pcm_channel_info_t m_cinfo;
+ snd_pcm_format_t m_cformat;
+ snd_pcm_channel_params_t m_params;
+ snd_pcm_channel_setup_t m_setup;
+
+ int setPcmParams(const int channel);
+ void checkCapabilities();
+
+public:
+ AudioIOALSA();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOALSA,"alsa","Advanced Linux Sound Architecture");
+};
+
+using namespace std;
+using namespace Arts;
+
+AudioIOALSA::AudioIOALSA()
+{
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = "/dev/dsp"; //!! alsa doesn't need this
+ requestedFragmentSize = param(fragmentSize) = 1024;
+ requestedFragmentCount = param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = directionWrite;
+
+ /*
+ * default parameters
+ */
+ m_card = snd_defaults_pcm_card(); //!! need interface !!
+ m_device = snd_defaults_pcm_device(); //!!
+#ifdef WORDS_BIGENDIAN
+ m_format = SND_PCM_SFMT_S16_BE;
+#else
+ m_format = SND_PCM_SFMT_S16_LE;
+#endif
+ m_bufferMode = block; //block/stream (stream mode doesn't work yet)
+
+ if(m_card >= 0) {
+ char* cardname = 0;
+
+ if(snd_card_get_name(m_card, &cardname) == 0 && cardname != 0)
+ {
+ //!! thats not what devicename is intended to do
+ //!! devicename is an input information into
+ //!! the "driver", to select which card to use
+ //!! not an output information
+ paramStr(deviceName) = cardname;
+ free(cardname);
+ }
+ }
+}
+
+bool AudioIOALSA::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _direction = param(direction);
+ int& _format = param(format);
+
+ /*
+ * initialize format - TODO: implement fallback (i.e. if no format given,
+ * it should try 16bit first, then fall back to 8bit)
+ */
+ switch(_format)
+ {
+ default: _format = 16;
+
+ case 16: // 16bit, signed little endian
+ m_format = SND_PCM_SFMT_S16_LE;
+ break;
+
+ case 17: // 16bit, signed big endian
+ m_format = SND_PCM_SFMT_S16_BE;
+ break;
+
+ case 8: // 8bit, unsigned
+ m_format = SND_PCM_SFMT_U8;
+ break;
+ }
+
+ /* open pcm device */
+ int mode = SND_PCM_OPEN_NONBLOCK;
+
+ if(_direction == directionReadWrite)
+ mode |= SND_PCM_OPEN_DUPLEX;
+ else if(_direction == directionWrite)
+ mode |= SND_PCM_OPEN_PLAYBACK;
+ else
+ {
+ _error = "invalid direction";
+ return false;
+ }
+
+ int err;
+ if((err = snd_pcm_open(&m_pcm_handle, m_card, m_device, mode)) < 0) {
+ _error = "device: ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened (";
+ _error += snd_strerror(err);
+ _error += ")";
+ return false;
+ }
+ else {
+ artsdebug("ALSA driver: %s", _deviceName.c_str());
+ }
+
+ snd_pcm_nonblock_mode(m_pcm_handle, 0);
+
+ /* flush buffers */
+ (void)snd_pcm_capture_flush(m_pcm_handle);
+ if(_direction & directionRead)
+ (void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE);
+ if(_direction & directionWrite)
+ (void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+
+ /* check device capabilities */
+ checkCapabilities();
+
+ /* set the fragment settings to what the user requested */
+ _fragmentSize = requestedFragmentSize;
+ _fragmentCount = requestedFragmentCount;
+
+ /* set PCM communication parameters */
+ if((_direction & directionRead) && setPcmParams(SND_PCM_CHANNEL_CAPTURE))
+ return false;
+ if((_direction & directionWrite) && setPcmParams(SND_PCM_CHANNEL_PLAYBACK))
+ return false;
+
+ /* prepare channel */
+ if((_direction & directionRead) &&
+ snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE) < 0)
+ {
+ _error = "Unable to prepare capture channel!";
+ return false;
+ }
+ if((_direction & directionWrite) &&
+ snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
+ {
+ _error = "Unable to prepare playback channel!";
+ return false;
+ }
+
+ /* obtain current PCM setup (may differ from requested one) */
+ (void)memset(&m_setup, 0, sizeof(m_setup));
+
+ m_setup.channel = SND_PCM_CHANNEL_PLAYBACK;
+ if(snd_pcm_channel_setup(m_pcm_handle, &m_setup) < 0) {
+ _error = "Unable to obtain channel setup!";
+ return false;
+ }
+
+ /* check samplerate */
+ const int tolerance = _samplingRate/10+1000;
+ if(abs(m_setup.format.rate-_samplingRate) > tolerance)
+ {
+ _error = "Can't set requested sampling rate!";
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, m_setup.format.rate);
+ _error += details;
+ return false;
+ }
+ _samplingRate = m_setup.format.rate;
+
+ /* check format */
+ if(m_setup.format.format != m_format) {
+ _error = "Can't set requested format:";
+ _error += snd_pcm_get_format_name(m_format);
+ return false;
+ }
+
+ /* check voices */
+ if(m_setup.format.voices != _channels) {
+ _error = "Audio device doesn't support number of requested channels!";
+ return false;
+ }
+
+ /* update fragment settings with what we got */
+ switch(m_bufferMode) {
+ case block:
+ _fragmentSize = m_setup.buf.block.frag_size;
+ _fragmentCount = m_setup.buf.block.frags_max-1;
+ break;
+ case stream:
+ _fragmentSize = m_setup.buf.stream.queue_size;
+ _fragmentCount = 1;
+ break;
+ }
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+ /* obtain PCM file descriptor(s) */
+ audio_read_fd = audio_write_fd = -1;
+
+ if(_direction & directionRead)
+ audio_read_fd = snd_pcm_file_descriptor(m_pcm_handle,
+ SND_PCM_CHANNEL_CAPTURE);
+ if(_direction & directionWrite)
+ audio_write_fd = snd_pcm_file_descriptor(m_pcm_handle,
+ SND_PCM_CHANNEL_PLAYBACK);
+
+ /* start recording */
+ if((_direction & directionRead) && snd_pcm_capture_go(m_pcm_handle)) {
+ _error = "Can't start recording!";
+ return false;
+ }
+
+ return true;
+}
+
+void AudioIOALSA::close()
+{
+ int& _direction = param(direction);
+ if(_direction & directionRead)
+ (void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE);
+ if(_direction & directionWrite)
+ (void)snd_pcm_channel_flush(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
+ (void)snd_pcm_close(m_pcm_handle);
+}
+
+void AudioIOALSA::setParam(AudioParam p, int& value)
+{
+ switch(p)
+ {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOALSA::getParam(AudioParam p)
+{
+ snd_pcm_channel_status_t status;
+ (void)memset(&status, 0, sizeof(status));
+
+ switch(p)
+ {
+ case canRead:
+ status.channel = SND_PCM_CHANNEL_CAPTURE;
+ if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
+ arts_warning("Capture channel status error!");
+ return -1;
+ }
+ return status.free;
+ break;
+
+ case canWrite:
+ status.channel = SND_PCM_CHANNEL_PLAYBACK;
+ if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
+ arts_warning("Playback channel status error!");
+ return -1;
+ }
+ return status.free;
+ break;
+
+ case selectReadFD:
+ return audio_read_fd;
+ break;
+
+ case selectWriteFD:
+ return audio_write_fd;
+ break;
+
+ case autoDetect:
+ /*
+ * that the ALSA driver could be compiled doesn't say anything
+ * about whether it will work (the user might be using an OSS
+ * kernel driver) so we'll use a value less than the OSS one
+ * here, because OSS will most certainly work (ALSA's OSS emu)
+ */
+ return 5;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOALSA::read(void *buffer, int size)
+{
+ int length;
+ do {
+ length = snd_pcm_read(m_pcm_handle, buffer, size);
+ } while (length == -EINTR);
+ if(length == -EPIPE) {
+ snd_pcm_channel_status_t status;
+ (void)memset(&status, 0, sizeof(status));
+ status.channel = SND_PCM_CHANNEL_CAPTURE;
+ if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
+ arts_info("Capture channel status error!");
+ return -1;
+ }
+ else if(status.status == SND_PCM_STATUS_RUNNING) {
+ length = 0;
+ }
+ else if(status.status == SND_PCM_STATUS_OVERRUN) {
+ artsdebug("Overrun at position: %d" ,status.scount);
+ if(snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_CAPTURE)<0)
+ {
+ arts_info("Overrun: capture prepare error!");
+ return -1;
+ }
+ length = 0;
+ }
+ else {
+ arts_info("Unknown capture error!");
+ return -1;
+ }
+ }
+ else if(length < 0) {
+ arts_info("Capture error: %s", snd_strerror(length));
+ return -1;
+ }
+ return length;
+}
+
+int AudioIOALSA::write(void *buffer, int size)
+{
+ int length;
+ while((length = snd_pcm_write(m_pcm_handle, buffer, size)) != size) {
+ if (length == -EINTR)
+ continue; // Try again
+ snd_pcm_channel_status_t status;
+ (void)memset(&status, 0, sizeof(status));
+ status.channel = SND_PCM_CHANNEL_PLAYBACK;
+
+ if(snd_pcm_channel_status(m_pcm_handle, &status) < 0) {
+ arts_warning("Playback channel status error!");
+ return -1;
+ }
+ else if(status.status == SND_PCM_STATUS_UNDERRUN) {
+ artsdebug("Underrun at position: %d", status.scount);
+ if(snd_pcm_channel_prepare(m_pcm_handle, SND_PCM_CHANNEL_PLAYBACK)
+ < 0) {
+ arts_warning("Underrun: playback prepare error!");
+ return -1;
+ }
+ }
+ else {
+ arts_warning("Unknown playback error!");
+ return -1;
+ }
+ }
+ return size;
+}
+
+int AudioIOALSA::setPcmParams(const int channel)
+{
+ int &_samplingRate = param(samplingRate);
+ int &_channels = param(channels);
+ int &_fragmentSize = param(fragmentSize);
+ int &_fragmentCount = param(fragmentCount);
+
+ (void)memset(&m_cformat, 0, sizeof(m_cformat));
+ m_cformat.interleave = 1;
+ m_cformat.format = m_format;
+ m_cformat.rate = _samplingRate;
+ m_cformat.voices = _channels;
+
+ (void)memset(&m_params, 0, sizeof(m_params));
+ switch(m_bufferMode){
+ case stream:
+ m_params.mode=SND_PCM_MODE_STREAM;
+ break;
+ case block:
+ m_params.mode=SND_PCM_MODE_BLOCK;
+ break;
+ }
+ m_params.channel=channel;
+ (void)memcpy(&m_params.format, &m_cformat, sizeof(m_cformat));
+ if(channel==SND_PCM_CHANNEL_CAPTURE){
+ m_params.start_mode=SND_PCM_START_GO;
+ m_params.stop_mode=SND_PCM_STOP_ROLLOVER;
+ }
+ else{ //SND_PCM_CHANNEL_PLAYBACK
+ m_params.start_mode= (m_bufferMode==block) ? SND_PCM_START_FULL : SND_PCM_START_DATA;
+ m_params.stop_mode=SND_PCM_STOP_ROLLOVER; // SND_PCM_STOP_STOP
+ //use this ^^^ if you want to track underruns
+ }
+
+ switch(m_bufferMode){
+ case stream:
+ m_params.buf.stream.queue_size=1024*1024; //_fragmentSize*_fragmentCount;
+ m_params.buf.stream.fill=SND_PCM_FILL_SILENCE_WHOLE;
+ m_params.buf.stream.max_fill=1024;
+ break;
+ case block:
+ m_params.buf.block.frag_size=_fragmentSize;
+ if(channel==SND_PCM_CHANNEL_CAPTURE){
+ m_params.buf.block.frags_max=1;
+ m_params.buf.block.frags_min=1;
+ }
+ else{ //SND_PCM_CHANNEL_PLAYBACK
+ m_params.buf.block.frags_max=_fragmentCount+1;
+ m_params.buf.block.frags_min=1;
+ }
+ }
+ if(snd_pcm_channel_params(m_pcm_handle, &m_params)<0){
+ paramStr(lastError) = "Unable to set channel params!";
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+void AudioIOALSA::checkCapabilities()
+{
+ snd_pcm_info_t info;
+ (void)memset(&info, 0, sizeof(info));
+ if(!snd_pcm_info(m_pcm_handle, &info)) {
+ string flags = "";
+ if(info.flags & SND_PCM_INFO_PLAYBACK) flags += "playback ";
+ if(info.flags & SND_PCM_INFO_CAPTURE) flags += "capture ";
+ if(info.flags & SND_PCM_INFO_DUPLEX) flags += "duplex ";
+ if(info.flags & SND_PCM_INFO_DUPLEX_RATE) flags += "duplex_rate ";
+ artsdebug(" type:%d id:%s\n"
+ " flags:%s\n"
+ " playback_subdevices:%d capture_subdevices:%d",
+ info.type, info.id,
+ flags.c_str(),
+ info.playback+1, info.capture+1);
+ }
+ else {
+ arts_warning("Can't get device info!"); //not fatal error
+ }
+
+ (void)memset(&m_cinfo, 0, sizeof(m_cinfo));
+ m_cinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
+ if(!snd_pcm_channel_info(m_pcm_handle, &m_cinfo)) {
+ string flags = "";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_MMAP) flags += "mmap ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_STREAM) flags += "stream ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_BLOCK) flags += "block ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_BATCH) flags += "batch ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_INTERLEAVE) flags += "interleave ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_NONINTERLEAVE) flags += "noninterleave ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_BLOCK_TRANSFER) flags += "block_transfer ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_OVERRANGE) flags += "overrange ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_MMAP_VALID) flags += "mmap_valid ";
+ if(m_cinfo.flags & SND_PCM_CHNINFO_PAUSE) flags += "pause ";
+
+ artsdebug(" subdevice:%d\n"
+ " flags:%s\n"
+ " min_rate:%d max_rate:%d\n"
+ " buffer_size:%d min_fragment_size:%d max_fragment_size:%d\n"
+ " fragment_align:%d fifo_size:%d transfer_block_size:%d\n"
+ " mmap_size:%d",
+ m_cinfo.subdevice,
+ flags.c_str(),
+ m_cinfo.min_rate, m_cinfo.max_rate,
+ m_cinfo.buffer_size, m_cinfo.min_fragment_size, m_cinfo.max_fragment_size,
+ m_cinfo.fragment_align, m_cinfo.fifo_size, m_cinfo.transfer_block_size,
+ m_cinfo.mmap_size);
+ }
+ else {
+ arts_warning("Can't get channel info!"); //not fatal error
+ }
+}
+
+#endif /* HAVE_LIBASOUND */
diff --git a/flow/audioioalsa9.cc b/flow/audioioalsa9.cc
new file mode 100644
index 0000000..8367da6
--- /dev/null
+++ b/flow/audioioalsa9.cc
@@ -0,0 +1,590 @@
+ /*
+
+ Copyright (C) 2001 Takashi Iwai <tiwai@suse.de>
+ Copyright (C) 2004 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ based on audioalsa.cc:
+ Copyright (C) 2000,2001 Jozef Kosoru
+ jozef.kosoru@pobox.sk
+ (C) 2000,2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile 'alsa' AudioIO class if configure thinks it is a good idea
+ */
+#ifdef HAVE_LIBASOUND2
+
+#ifdef HAVE_ALSA_ASOUNDLIB_H
+#include <alsa/asoundlib.h>
+#elif defined(HAVE_SYS_ASOUNDLIB_H)
+#include <sys/asoundlib.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "dispatcher.h"
+#include "iomanager.h"
+
+namespace Arts {
+
+class AudioIOALSA : public AudioIO, public IONotify {
+protected:
+ // List of file descriptors
+ struct poll_descriptors {
+ poll_descriptors() : nfds(0), pfds(0) {};
+ int nfds;
+ struct pollfd *pfds;
+ } audio_write_pds, audio_read_pds;
+
+ snd_pcm_t *m_pcm_playback;
+ snd_pcm_t *m_pcm_capture;
+ snd_pcm_format_t m_format;
+ int m_period_size, m_periods;
+
+ void startIO();
+ int setPcmParams(snd_pcm_t *pcm);
+ static int poll2iomanager(int pollTypes);
+ static int iomanager2poll(int ioTypes);
+ void getDescriptors(snd_pcm_t *pcm, poll_descriptors *pds);
+ void watchDescriptors(poll_descriptors *pds);
+
+ void notifyIO(int fd, int types);
+
+ int xrun(snd_pcm_t *pcm);
+#ifdef HAVE_SND_PCM_RESUME
+ int resume(snd_pcm_t *pcm);
+#endif
+
+public:
+ AudioIOALSA();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOALSA,"alsa","Advanced Linux Sound Architecture");
+}
+
+using namespace std;
+using namespace Arts;
+
+AudioIOALSA::AudioIOALSA()
+{
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = "default"; // ALSA pcm device name - not file name
+ param(fragmentSize) = 1024;
+ param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = directionWrite;
+ param(format) = 16;
+ /*
+ * default parameters
+ */
+ m_format = SND_PCM_FORMAT_S16_LE;
+ m_pcm_playback = NULL;
+ m_pcm_capture = NULL;
+}
+
+bool AudioIOALSA::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _direction = param(direction);
+ int& _format = param(format);
+
+ m_pcm_playback = NULL;
+ m_pcm_capture = NULL;
+
+ /* initialize format */
+ switch(_format) {
+ case 16: // 16bit, signed little endian
+ m_format = SND_PCM_FORMAT_S16_LE;
+ break;
+ case 17: // 16bit, signed big endian
+ m_format = SND_PCM_FORMAT_S16_BE;
+ break;
+ case 8: // 8bit, unsigned
+ m_format = SND_PCM_FORMAT_U8;
+ break;
+ default: // test later
+ m_format = SND_PCM_FORMAT_UNKNOWN;
+ break;
+ }
+
+ /* open pcm device */
+ int err;
+ if (_direction & directionWrite) {
+ if ((err = snd_pcm_open(&m_pcm_playback, _deviceName.c_str(),
+ SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+ _error = "device: ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened for playback (";
+ _error += snd_strerror(err);
+ _error += ")";
+ return false;
+ }
+ snd_pcm_nonblock(m_pcm_playback, 0);
+ }
+ if (_direction & directionRead) {
+ if ((err = snd_pcm_open(&m_pcm_capture, _deviceName.c_str(),
+ SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
+ _error = "device: ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened for capture (";
+ _error += snd_strerror(err);
+ _error += ")";
+ snd_pcm_close(m_pcm_playback);
+ return false;
+ }
+ snd_pcm_nonblock(m_pcm_capture, 0);
+ }
+
+ artsdebug("ALSA driver: %s", _deviceName.c_str());
+
+ /* check device capabilities */
+ // checkCapabilities();
+
+ /* set PCM communication parameters */
+ if (((_direction & directionWrite) && setPcmParams(m_pcm_playback)) ||
+ ((_direction & directionRead) && setPcmParams(m_pcm_capture))) {
+ snd_pcm_close(m_pcm_playback);
+ snd_pcm_close(m_pcm_capture);
+ return false;
+ }
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+
+ startIO();
+ /* restore the format value */
+ switch (m_format) {
+ case SND_PCM_FORMAT_S16_LE:
+ _format = 16;
+ break;
+ case SND_PCM_FORMAT_S16_BE:
+ _format = 17;
+ break;
+ case SND_PCM_FORMAT_U8:
+ _format = 8;
+ break;
+ default:
+ _error = "Unknown PCM format";
+ return false;
+ }
+
+ /* start recording */
+ if (_direction & directionRead)
+ snd_pcm_start(m_pcm_capture);
+
+ return true;
+}
+
+void AudioIOALSA::close()
+{
+ arts_debug("Closing ALSA-driver");
+ int& _direction = param(direction);
+ if ((_direction & directionRead) && m_pcm_capture) {
+ (void)snd_pcm_drop(m_pcm_capture);
+ (void)snd_pcm_close(m_pcm_capture);
+ m_pcm_capture = NULL;
+ }
+ if ((_direction & directionWrite) && m_pcm_playback) {
+ (void)snd_pcm_drop(m_pcm_playback);
+ (void)snd_pcm_close(m_pcm_playback);
+ m_pcm_playback = NULL;
+ }
+ Dispatcher::the()->ioManager()->remove(this, IOType::all);
+
+ delete[] audio_read_pds.pfds;
+ delete[] audio_write_pds.pfds;
+ audio_read_pds.pfds = NULL; audio_write_pds.pfds = NULL;
+ audio_read_pds.nfds = 0; audio_write_pds.nfds = 0;
+}
+
+void AudioIOALSA::setParam(AudioParam p, int& value)
+{
+ param(p) = value;
+ if (m_pcm_playback != NULL) {
+ setPcmParams(m_pcm_playback);
+ }
+ if (m_pcm_capture != NULL) {
+ setPcmParams(m_pcm_capture);
+ }
+}
+
+int AudioIOALSA::getParam(AudioParam p)
+{
+ snd_pcm_sframes_t avail;
+ switch(p) {
+
+ case canRead:
+ if (! m_pcm_capture) return -1;
+ while ((avail = snd_pcm_avail_update(m_pcm_capture)) < 0) {
+ if (avail == -EPIPE)
+ avail = xrun(m_pcm_capture);
+#ifdef HAVE_SND_PCM_RESUME
+ else if (avail == -ESTRPIPE)
+ avail = resume(m_pcm_capture);
+#endif
+ if (avail < 0) {
+ arts_info("Capture error: %s", snd_strerror(avail));
+ return -1;
+ }
+ }
+ return snd_pcm_frames_to_bytes(m_pcm_capture, avail);
+
+ case canWrite:
+ if (! m_pcm_playback) return -1;
+ while ((avail = snd_pcm_avail_update(m_pcm_playback)) < 0) {
+ if (avail == -EPIPE)
+ avail = xrun(m_pcm_playback);
+#ifdef HAVE_SND_PCM_RESUME
+ else if (avail == -ESTRPIPE)
+ avail = resume(m_pcm_playback);
+#endif
+ if (avail < 0) {
+ arts_info("Playback error: %s", snd_strerror(avail));
+ return -1;
+ }
+ }
+ return snd_pcm_frames_to_bytes(m_pcm_playback, avail);
+
+ case selectReadFD:
+ return -1;
+
+ case selectWriteFD:
+ return -1;
+
+ case autoDetect:
+ {
+ /*
+ * that the ALSA driver could be compiled doesn't say anything
+ * about whether it will work (the user might be using an OSS
+ * kernel driver).
+ * If we can open the device, it'll work - and we'll have to use
+ * a higher number than OSS to avoid buggy OSS emulation being used.
+ */
+ int card = -1;
+ if (snd_card_next(&card) < 0 || card < 0) {
+ // No ALSA drivers in use...
+ return 0;
+ }
+ return 15;
+ }
+
+ default:
+ return param(p);
+ }
+}
+
+void AudioIOALSA::startIO()
+{
+ /* get & watch PCM file descriptor(s) */
+ if (m_pcm_playback) {
+ getDescriptors(m_pcm_playback, &audio_write_pds);
+ watchDescriptors(&audio_write_pds);
+ }
+ if (m_pcm_capture) {
+ getDescriptors(m_pcm_capture, &audio_read_pds);
+ watchDescriptors(&audio_read_pds);
+ }
+
+}
+
+int AudioIOALSA::poll2iomanager(int pollTypes)
+{
+ int types = 0;
+
+ if(pollTypes & POLLIN)
+ types |= IOType::read;
+ if(pollTypes & POLLOUT)
+ types |= IOType::write;
+ if(pollTypes & POLLERR)
+ types |= IOType::except;
+
+ return types;
+}
+
+int AudioIOALSA::iomanager2poll(int ioTypes)
+{
+ int types = 0;
+
+ if(ioTypes & IOType::read)
+ types |= POLLIN;
+ if(ioTypes & IOType::write)
+ types |= POLLOUT;
+ if(ioTypes & IOType::except)
+ types |= POLLERR;
+
+ return types;
+}
+
+void AudioIOALSA::getDescriptors(snd_pcm_t *pcm, poll_descriptors *pds)
+{
+ pds->nfds = snd_pcm_poll_descriptors_count(pcm);
+ pds->pfds = new struct pollfd[pds->nfds];
+
+ if (snd_pcm_poll_descriptors(pcm, pds->pfds, pds->nfds) != pds->nfds) {
+ arts_info("Cannot get poll descriptor(s)\n");
+ }
+
+}
+
+void AudioIOALSA::watchDescriptors(poll_descriptors *pds)
+{
+ for(int i=0; i<pds->nfds; i++) {
+ // Check in which direction this handle is supposed to be watched
+ int types = poll2iomanager(pds->pfds[i].events);
+ Dispatcher::the()->ioManager()->watchFD(pds->pfds[i].fd, types, this);
+ }
+}
+
+int AudioIOALSA::xrun(snd_pcm_t *pcm)
+{
+ int err;
+ artsdebug("xrun!!\n");
+ if ((err = snd_pcm_prepare(pcm)) < 0)
+ return err;
+ if (pcm == m_pcm_capture)
+ snd_pcm_start(pcm); // ignore error here..
+ return 0;
+}
+
+#ifdef HAVE_SND_PCM_RESUME
+int AudioIOALSA::resume(snd_pcm_t *pcm)
+{
+ int err;
+ artsdebug("resume!\n");
+ while ((err = snd_pcm_resume(pcm)) == -EAGAIN)
+ sleep(1); /* wait until suspend flag is not released */
+ if (err < 0) {
+ if ((err = snd_pcm_prepare(pcm)) < 0)
+ return err;
+ if (pcm == m_pcm_capture)
+ snd_pcm_start(pcm); // ignore error here..
+ }
+ return 0;
+}
+#endif
+
+int AudioIOALSA::read(void *buffer, int size)
+{
+ int frames = snd_pcm_bytes_to_frames(m_pcm_capture, size);
+ int length;
+ while ((length = snd_pcm_readi(m_pcm_capture, buffer, frames)) < 0) {
+ if (length == -EINTR)
+ continue; // Try again
+ else if (length == -EPIPE)
+ length = xrun(m_pcm_capture);
+#ifdef HAVE_SND_PCM_RESUME
+ else if (length == -ESTRPIPE)
+ length = resume(m_pcm_capture);
+#endif
+ if (length < 0) {
+ arts_info("Capture error: %s", snd_strerror(length));
+ return -1;
+ }
+ }
+ return snd_pcm_frames_to_bytes(m_pcm_capture, length);
+}
+
+int AudioIOALSA::write(void *buffer, int size)
+{
+ int frames = snd_pcm_bytes_to_frames(m_pcm_playback, size);
+ int length;
+ while ((length = snd_pcm_writei(m_pcm_playback, buffer, frames)) < 0) {
+ if (length == -EINTR)
+ continue; // Try again
+ else if (length == -EPIPE)
+ length = xrun(m_pcm_playback);
+#ifdef HAVE_SND_PCM_RESUME
+ else if (length == -ESTRPIPE)
+ length = resume(m_pcm_playback);
+#endif
+ if (length < 0) {
+ arts_info("Playback error: %s", snd_strerror(length));
+ return -1;
+ }
+ }
+
+ // Start the sink if it needs it
+ if (snd_pcm_state( m_pcm_playback ) == SND_PCM_STATE_PREPARED)
+ snd_pcm_start(m_pcm_playback);
+
+ if (length == frames) // Sometimes the fragments are "odd" in alsa
+ return size;
+ else
+ return snd_pcm_frames_to_bytes(m_pcm_playback, length);
+}
+
+void AudioIOALSA::notifyIO(int fd, int type)
+{
+ int todo = 0;
+
+ // Translate from iomanager-types to poll-types,
+ // inorder to fake a snd_pcm_poll_descriptors_revents call.
+ if(m_pcm_playback) {
+ for(int i=0; i < audio_write_pds.nfds; i++) {
+ if(fd == audio_write_pds.pfds[i].fd) {
+ audio_write_pds.pfds[i].revents = iomanager2poll(type);
+ todo |= AudioSubSystem::ioWrite;
+ }
+ }
+ if (todo & AudioSubSystem::ioWrite) {
+ unsigned short revents;
+ snd_pcm_poll_descriptors_revents(m_pcm_playback,
+ audio_write_pds.pfds,
+ audio_write_pds.nfds,
+ &revents);
+ if (! (revents & POLLOUT)) todo &= ~AudioSubSystem::ioWrite;
+ }
+ }
+ if(m_pcm_capture) {
+ for(int i=0; i < audio_read_pds.nfds; i++) {
+ if(fd == audio_read_pds.pfds[i].fd) {
+ audio_read_pds.pfds[i].revents = iomanager2poll(type);
+ todo |= AudioSubSystem::ioRead;
+ }
+ }
+ if (todo & AudioSubSystem::ioRead) {
+ unsigned short revents;
+ snd_pcm_poll_descriptors_revents(m_pcm_capture,
+ audio_read_pds.pfds,
+ audio_read_pds.nfds,
+ &revents);
+ if (! (revents & POLLIN)) todo &= ~AudioSubSystem::ioRead;
+ }
+ }
+
+ if (type & IOType::except) todo |= AudioSubSystem::ioExcept;
+
+ if (todo != 0) AudioSubSystem::the()->handleIO(todo);
+}
+
+int AudioIOALSA::setPcmParams(snd_pcm_t *pcm)
+{
+ int &_samplingRate = param(samplingRate);
+ int &_channels = param(channels);
+ int &_fragmentSize = param(fragmentSize);
+ int &_fragmentCount = param(fragmentCount);
+ string& _error = paramStr(lastError);
+
+ snd_pcm_hw_params_t *hw;
+ snd_pcm_hw_params_alloca(&hw);
+ snd_pcm_hw_params_any(pcm, hw);
+
+ if (snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
+ _error = "Unable to set interleaved!";
+ return 1;
+ }
+ if (m_format == SND_PCM_FORMAT_UNKNOWN) {
+ // test the available formats
+ // try 16bit first, then fall back to 8bit
+ if (! snd_pcm_hw_params_test_format(pcm, hw, SND_PCM_FORMAT_S16_LE))
+ m_format = SND_PCM_FORMAT_S16_LE;
+ else if (! snd_pcm_hw_params_test_format(pcm, hw, SND_PCM_FORMAT_S16_BE))
+ m_format = SND_PCM_FORMAT_S16_BE;
+ else if (! snd_pcm_hw_params_test_format(pcm, hw, SND_PCM_FORMAT_U8))
+ m_format = SND_PCM_FORMAT_U8;
+ else
+ m_format = SND_PCM_FORMAT_UNKNOWN;
+ }
+ if (snd_pcm_hw_params_set_format(pcm, hw, m_format) < 0) {
+ _error = "Unable to set format!";
+ return 1;
+ }
+
+ unsigned int rate = snd_pcm_hw_params_set_rate_near(pcm, hw, _samplingRate, 0);
+ const unsigned int tolerance = _samplingRate/10+1000;
+ if (abs((int)rate - (int)_samplingRate) > (int)tolerance) {
+ _error = "Can't set requested sampling rate!";
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, rate);
+ _error += details;
+ return 1;
+ }
+ _samplingRate = rate;
+
+ if (snd_pcm_hw_params_set_channels(pcm, hw, _channels) < 0) {
+ _error = "Unable to set channels!";
+ return 1;
+ }
+
+ m_period_size = _fragmentSize;
+ if (m_format != SND_PCM_FORMAT_U8)
+ m_period_size <<= 1;
+ if (_channels > 1)
+ m_period_size /= _channels;
+ if ((m_period_size = snd_pcm_hw_params_set_period_size_near(pcm, hw, m_period_size, 0)) < 0) {
+ _error = "Unable to set period size!";
+ return 1;
+ }
+ m_periods = _fragmentCount;
+ if ((m_periods = snd_pcm_hw_params_set_periods_near(pcm, hw, m_periods, 0)) < 0) {
+ _error = "Unable to set periods!";
+ return 1;
+ }
+
+ if (snd_pcm_hw_params(pcm, hw) < 0) {
+ _error = "Unable to set hw params!";
+ return 1;
+ }
+
+ _fragmentSize = m_period_size;
+ _fragmentCount = m_periods;
+ if (m_format != SND_PCM_FORMAT_U8)
+ _fragmentSize >>= 1;
+ if (_channels > 1)
+ _fragmentSize *= _channels;
+
+ return 0; // ok, we're ready..
+}
+
+#endif /* HAVE_LIBASOUND2 */
diff --git a/flow/audioiocsl.cc b/flow/audioiocsl.cc
new file mode 100644
index 0000000..9a9b44e
--- /dev/null
+++ b/flow/audioiocsl.cc
@@ -0,0 +1,640 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile 'csl' AudioIO class if libcsl is present
+ */
+#ifdef HAVE_LIBCSL
+#include <csl/csl.h>
+
+/* g_newa */
+#include <gsl/gsldefs.h>
+
+#include <vector>
+
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "debug.h"
+#include "dispatcher.h"
+#include "iomanager.h"
+
+namespace Arts {
+
+class AudioIOCSL : public AudioIO,
+ public IONotify
+{
+protected:
+ CslPcmStream *inputStream, *outputStream;
+ CslDriver *cslDriver;
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+ const char *cslDriverName;
+
+ std::vector<CslPollFD> cslFds, cslOldFds;
+ int csl2iomanager(int cslTypes);
+ void updateFds();
+
+ void notifyIO(int fd, int types);
+ static void handleRead(void *user_data, CslPcmStream *stream);
+ static void handleWrite(void *user_data, CslPcmStream *stream);
+
+public:
+ AudioIOCSL(const char *driverName = 0);
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOCSL,"csl","Common Sound Layer");
+
+class AudioIOCSLFactory : public AudioIOFactory {
+protected:
+ const char *driverName;
+ std::string _name;
+ std::string _fullName;
+
+public:
+ AudioIOCSLFactory(const char *driverName)
+ : driverName(driverName)
+ {
+ _name = "csl-";
+ _name += driverName;
+
+ _fullName = "Common Sound Layer (";
+ _fullName += driverName;
+ _fullName += ")";
+ }
+ virtual ~AudioIOCSLFactory()
+ {
+ }
+ AudioIO *createAudioIO() { return new AudioIOCSL(driverName); }
+ virtual const char *name() { return _name.c_str(); }
+ virtual const char *fullName() { return _fullName.c_str(); }
+};
+
+static class AudioIOCSLInit {
+protected:
+ std::list<AudioIOCSLFactory *> factories;
+
+public:
+ AudioIOCSLInit()
+ {
+ unsigned int i,n;
+ const char **drivers = csl_list_drivers(&n);
+
+ for(i = 0; i < n; i++)
+ factories.push_back(new AudioIOCSLFactory(drivers[i]));
+ }
+ ~AudioIOCSLInit()
+ {
+ std::list<AudioIOCSLFactory *>::iterator i;
+ for(i = factories.begin(); i != factories.end(); i++)
+ delete (*i);
+
+ factories.clear();
+ }
+} aci;
+
+};
+
+using namespace std;
+using namespace Arts;
+
+AudioIOCSL::AudioIOCSL(const char *driverName)
+ : cslDriverName(driverName)
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = "todo";
+ requestedFragmentSize = param(fragmentSize) = 1024;
+ requestedFragmentCount = param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = 2;
+
+#ifdef WORDS_BIGENDIAN
+ param(format) = 17;
+#else
+ param(format) = 16;
+#endif
+}
+
+bool AudioIOCSL::open()
+{
+ string& errorMsg = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+ int fmt = 0;
+ char *env = 0;
+
+ if(cslDriverName && strcmp(cslDriverName, "arts") == 0)
+ env = arts_strdup_printf("ARTS_SERVER=%s",_deviceName.c_str());
+
+ if(env)
+ {
+ putenv(env);
+ arts_debug("AudioIOCsl: set %s\n",env);
+ }
+
+ CslErrorType error;
+ error = csl_driver_init(cslDriverName, &cslDriver); /* choose backend */
+
+ if(env)
+ {
+ putenv("ARTS_SERVER");
+ free(env);
+ }
+
+ if (error)
+ {
+ errorMsg = "unable to initialize CSL driver: ";
+ errorMsg += csl_strerror(error);
+ return false;
+ }
+
+ if(_format == 8)
+ fmt = CSL_PCM_FORMAT_U8;
+ else if(_format == 16)
+ fmt = CSL_PCM_FORMAT_S16_LE;
+ else if(_format == 17)
+ fmt = CSL_PCM_FORMAT_S16_BE;
+
+ inputStream = outputStream = 0;
+ if(param(direction) & directionRead)
+ {
+ /* open PCM output stream */
+ error = csl_pcm_open_output(cslDriver,
+ "artsd output",
+ _samplingRate,
+ _channels,
+ fmt, &inputStream);
+ if (error)
+ {
+ errorMsg = "failed to open CSL input stream: ";
+ errorMsg += csl_strerror(error);
+ return false;
+ }
+ csl_pcm_set_callback(inputStream, handleRead, 0, 0);
+ }
+ if(param(direction) & directionWrite)
+ {
+ /* open PCM output stream */
+ error = csl_pcm_open_output(cslDriver,
+ "artsd output",
+ _samplingRate,
+ _channels,
+ fmt, &outputStream);
+ if (error)
+ {
+ close();
+
+ errorMsg = "failed to open CSL output stream: ";
+ errorMsg += csl_strerror(error);
+ return false;
+ }
+ csl_pcm_set_callback(outputStream, handleWrite, 0, 0);
+ }
+#if 0
+ if (_format && (ossBits(gotFormat) != ossBits(requestedFormat)))
+ {
+ char details[80];
+ sprintf(details," (_format = %d, asked driver to give %d, got %d)",
+ _format, requestedFormat, gotFormat);
+
+ _error = "Can't set playback format";
+ _error += details;
+
+ close();
+ return false;
+ }
+
+ if(gotFormat == AFMT_U8)
+ _format = 8;
+ else if(gotFormat == AFMT_S16_LE)
+ _format = 16;
+ else if(gotFormat == AFMT_S16_BE)
+ _format = 17;
+ else
+ {
+ char details[80];
+ sprintf(details," (_format = %d, asked driver to give %d, got %d)",
+ _format, requestedFormat, gotFormat);
+
+ _error = "unknown format given by driver";
+ _error += details;
+
+ close();
+ return false;
+ }
+
+
+ int stereo=-1; /* 0=mono, 1=stereo */
+
+ if(_channels == 1)
+ {
+ stereo = 0;
+ }
+ if(_channels == 2)
+ {
+ stereo = 1;
+ }
+
+ if(stereo == -1)
+ {
+ _error = "internal error; set channels to 1 (mono) or 2 (stereo)";
+
+ close();
+ return false;
+ }
+
+ int requeststereo = stereo;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
+ {
+ _error = "SNDCTL_DSP_STEREO failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ if (requeststereo != stereo)
+ {
+ _error = "audio device doesn't support number of requested channels";
+
+ close();
+ return false;
+ }
+
+ int speed = _samplingRate;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
+ {
+ _error = "SNDCTL_DSP_SPEED failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ /*
+ * Some soundcards seem to be able to only supply "nearly" the requested
+ * sampling rate, especially PAS 16 cards seem to quite radical supplying
+ * something different than the requested sampling rate ;)
+ *
+ * So we have a quite large tolerance here (when requesting 44100 Hz, it
+ * will accept anything between 38690 Hz and 49510 Hz). Most parts of the
+ * aRts code will do resampling where appropriate, so it shouldn't affect
+ * sound quality.
+ */
+ int tolerance = _samplingRate/10+1000;
+
+ if (abs(speed-_samplingRate) > tolerance)
+ {
+ _error = "can't set requested samplingrate";
+
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, speed);
+ _error += details;
+
+ close();
+ return false;
+ }
+ _samplingRate = speed;
+
+ /*
+ * set the fragment settings to what the user requested
+ */
+
+ _fragmentSize = requestedFragmentSize;
+ _fragmentCount = requestedFragmentCount;
+
+ /*
+ * lower 16 bits are the fragment size (as 2^S)
+ * higher 16 bits are the number of fragments
+ */
+ int frag_arg = 0;
+
+ int size = _fragmentSize;
+ while(size > 1) { size /= 2; frag_arg++; }
+ frag_arg += (_fragmentCount << 16);
+ if(ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_arg) == -1)
+ {
+ char buffer[1024];
+ _error = "can't set requested fragments settings";
+ sprintf(buffer,"size%d:count%d\n",_fragmentSize,_fragmentCount);
+ close();
+ return false;
+ }
+
+ /*
+ * now see what we really got as cards aren't required to supply what
+ * we asked for
+ */
+ audio_buf_info info;
+ if(ioctl(audio_fd,SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
+ _error = "can't retrieve fragment settings";
+ close();
+ return false;
+ }
+
+ // update fragment settings with what we got
+ _fragmentSize = info.fragsize;
+ _fragmentCount = info.fragstotal;
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+ /*
+ * Workaround for broken kernel drivers: usually filling up the audio
+ * buffer is _only_ required if _fullDuplex is true. However, there
+ * are kernel drivers around (especially everything related to ES1370/1371)
+ * which will not trigger select()ing the file descriptor unless we have
+ * written something first.
+ */
+ char *zbuffer = (char *)calloc(sizeof(char), _fragmentSize);
+ if(_format == 8)
+ for(int zpos = 0; zpos < _fragmentSize; zpos++)
+ zbuffer[zpos] |= 0x80;
+
+ for(int fill = 0; fill < _fragmentCount; fill++)
+ {
+ int len = ::write(audio_fd,zbuffer,_fragmentSize);
+ if(len != _fragmentSize)
+ {
+ arts_debug("AudioIOCSL: failed prefilling audio buffer (might cause synchronization problems in conjunction with full duplex)");
+ fill = _fragmentCount+1;
+ }
+ }
+ free(zbuffer);
+
+ /*
+ * Triggering - the original aRts code did this for full duplex:
+ *
+ * - stop audio i/o using SETTRIGGER(~(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT))
+ * - fill buffer (see zbuffer code two lines above)
+ * - start audio i/o using SETTRIGGER(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT)
+ *
+ * this should guarantee synchronous start of input/output. Today, it
+ * seems there are too many broken drivers around for this.
+ */
+
+ if(device_caps & DSP_CAP_TRIGGER)
+ {
+ int enable_bits = 0;
+
+ if(param(direction) & 1) enable_bits |= PCM_ENABLE_INPUT;
+ if(param(direction) & 2) enable_bits |= PCM_ENABLE_OUTPUT;
+
+ if(ioctl(audio_fd,SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1)
+ {
+ _error = "can't start sound i/o";
+
+ close();
+ return false;
+ }
+ }
+#endif
+ updateFds();
+ return true;
+}
+
+void AudioIOCSL::close()
+{
+ if(inputStream)
+ {
+ csl_pcm_close(inputStream);
+ inputStream = 0;
+ }
+ if(outputStream)
+ {
+ csl_pcm_close(outputStream);
+ outputStream = 0;
+ }
+ updateFds();
+}
+
+void AudioIOCSL::setParam(AudioParam p, int& value)
+{
+ switch(p)
+ {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOCSL::getParam(AudioParam p)
+{
+ CslErrorType error;
+ CslPcmStatus status;
+
+ switch(p)
+ {
+ case canRead:
+ error = csl_pcm_get_status (inputStream, &status);
+ if (error) /* FIXME */
+ arts_fatal("unable to obtain csl stream status: %s",
+ csl_strerror (error));
+
+ updateFds();
+ return status.n_bytes_available;
+ break;
+
+ case canWrite:
+ error = csl_pcm_get_status(outputStream, &status);
+ if (error) /* FIXME */
+ arts_fatal("unable to obtain csl stream status: %s",
+ csl_strerror (error));
+
+ updateFds();
+ return status.n_bytes_available;
+ break;
+
+ case autoDetect:
+ /* CSL is pretty experimental currently */
+ return 1;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOCSL::read(void *buffer, int size)
+{
+ arts_assert(inputStream != 0);
+
+ int result = csl_pcm_read(inputStream, size, buffer);
+ updateFds();
+
+ return result;
+}
+
+void AudioIOCSL::handleRead(void *, CslPcmStream *)
+{
+ AudioSubSystem::the()->handleIO(AudioSubSystem::ioRead);
+}
+
+int AudioIOCSL::write(void *buffer, int size)
+{
+ arts_assert(outputStream != 0);
+
+ int result = csl_pcm_write(outputStream, size, buffer);
+ updateFds();
+
+ return result;
+}
+
+void AudioIOCSL::handleWrite(void *, CslPcmStream *)
+{
+ AudioSubSystem::the()->handleIO(AudioSubSystem::ioWrite);
+}
+
+/* mainloop integration: make CSL callbacks work inside the aRts mainloop */
+
+int AudioIOCSL::csl2iomanager(int cslTypes)
+{
+ /* FIXME: doublecheck this list */
+ int types = 0;
+
+ if(cslTypes & CSL_POLLIN)
+ types |= IOType::read;
+ if(cslTypes & CSL_POLLOUT)
+ types |= IOType::write;
+ if(cslTypes & CSL_POLLERR)
+ types |= IOType::except;
+
+ return types;
+}
+
+void AudioIOCSL::updateFds()
+{
+ unsigned int n_fds = csl_poll_count_fds(cslDriver);
+ CslPollFD *newFds = g_newa(CslPollFD, n_fds);
+
+ unsigned int have_fds = csl_poll_get_fds(cslDriver, n_fds, newFds);
+ arts_assert(have_fds == n_fds);
+
+ cslFds.clear();
+
+ unsigned int i;
+ for(i = 0; i < have_fds; i++)
+ cslFds.push_back(newFds[i]);
+
+ /* FIXME: if csl provided a flag for this, we could save some work here */
+ bool fdsChanged;
+ if(cslFds.size() == cslOldFds.size())
+ {
+ fdsChanged = false;
+ for(i = 0; i < have_fds; i++)
+ {
+ if(cslFds[i].events != cslOldFds[i].events)
+ fdsChanged = true;
+ if(cslFds[i].fd != cslOldFds[i].fd)
+ fdsChanged = true;
+ }
+ }
+ else
+ {
+ fdsChanged = true;
+ }
+ if(!fdsChanged)
+ return;
+
+ vector<CslPollFD>::iterator ci;
+
+ /* remove old watches */
+ /*
+ * UGLY! due to broken API, we can only remove all watches here, and not
+ * do anything selectively - its not a problem for the code here, but it
+ * might be a problem elsewhere. Unfortunately, it can't be fixed without
+ * breaking BC.
+ */
+ Dispatcher::the()->ioManager()->remove(this, IOType::all);
+ arts_debug("AudioIOCSL::updateFds(): removing watches");
+
+ /* add new watches */
+ for(ci = cslFds.begin(); ci < cslFds.end(); ci++)
+ {
+ int types = csl2iomanager(ci->events);
+ if(types)
+ {
+ Dispatcher::the()->ioManager()->watchFD(ci->fd, types, this);
+ arts_debug("AudioIOCSL::updateFds(): adding watch on %d", ci->fd);
+ }
+ }
+
+ cslOldFds = cslFds;
+}
+
+void AudioIOCSL::notifyIO(int fd, int type)
+{
+ vector<CslPollFD>::iterator fi;
+
+ for(fi = cslFds.begin(); fi != cslFds.end(); fi++)
+ {
+ if(fi->fd == fd)
+ {
+ int ftype = csl2iomanager(fi->events);
+ fi->revents = 0;
+
+ if(type & ftype & IOType::read)
+ fi->revents |= CSL_POLLIN;
+ if(type & ftype & IOType::write)
+ fi->revents |= CSL_POLLOUT;
+ if(type & ftype & IOType::except)
+ fi->revents |= CSL_POLLERR;
+
+ if(fi->revents)
+ csl_poll_handle_fds(cslDriver, 1, &(*fi));
+ }
+ }
+ updateFds();
+}
+
+#endif
diff --git a/flow/audioioesd.cc b/flow/audioioesd.cc
new file mode 100644
index 0000000..a3fa4b5
--- /dev/null
+++ b/flow/audioioesd.cc
@@ -0,0 +1,231 @@
+ /*
+
+ Copyright (C) 2001 Jochen Hoenicke
+ jochen@gnu.org
+
+ Copyright (C) 2003 Ian Chiew
+ ian@snork.net
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile esound AudioIO class if libesd was detected during
+ * configure
+ */
+#ifdef HAVE_LIBESD
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+#include <esd.h>
+
+#ifdef __BIG_ENDIAN__
+#define _format_bits 17
+#else
+#define _format_bits 16
+#endif
+
+namespace Arts {
+
+class AudioIOESD : public AudioIO, public IONotify {
+protected:
+ int server_fd, read_fd, write_fd;
+
+public:
+ AudioIOESD();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+ void notifyIO(int fd, int type);
+
+ bool open();
+ void close();
+ void run();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOESD,"esd","Enlightened Sound Daemon");
+}
+
+using namespace std;
+using namespace Arts;
+
+AudioIOESD::AudioIOESD()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = "null";
+ param(fragmentSize) = 1024;
+ param(fragmentCount) = 7;
+ param(format) = _format_bits;
+ param(channels) = 2;
+ param(direction) = 2;
+
+ server_fd = -1;
+ read_fd = -1;
+ write_fd = -1;
+}
+
+bool AudioIOESD::open()
+{
+ int& _channels = param(channels);
+ int& _direction = param(direction);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+ string& _error = paramStr(lastError);
+
+ if ((server_fd = esd_open_sound(NULL)) == -1)
+ {
+ _error = "Couldn't connect to server";
+ return false;
+ }
+
+ esd_server_info_t *server_info = esd_get_server_info(server_fd);
+
+ if (server_info == NULL)
+ {
+ _error = "Unable to query EsounD server";
+ return false;
+ }
+
+ esd_format_t server_format = server_info->format;
+
+ _samplingRate = server_info->rate;
+ _channels = (server_format & ESD_STEREO) ? 2 : 1;
+ _format = (server_format & ESD_BITS16) ? _format_bits : 8;
+
+ esd_free_server_info(server_info);
+
+ if (_direction & directionRead)
+ {
+ read_fd = esd_record_stream(server_format, _samplingRate,
+ NULL, "aRts");
+ if (read_fd == -1)
+ {
+ _error = "Couldn't create read uflow";
+ return false;
+ }
+ }
+
+ if (_direction & directionWrite)
+ {
+ write_fd = esd_play_stream(server_format, _samplingRate,
+ NULL, "aRts");
+ if (write_fd == -1)
+ {
+ _error = "Couldn't create write flow";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void AudioIOESD::notifyIO(int, int)
+{
+}
+
+void AudioIOESD::close()
+{
+ if (write_fd != -1)
+ esd_close(write_fd);
+
+ if (read_fd != -1)
+ esd_close(read_fd);
+
+ if (server_fd != -1)
+ esd_close(server_fd);
+}
+
+void AudioIOESD::setParam(AudioParam p, int& value)
+{
+ switch(p)
+ {
+ case channels:
+ case format:
+ case direction:
+ case samplingRate:
+ param(p) = value;
+ close();
+ open();
+ return;
+
+ default:
+ param(p) = value;
+ return;
+ }
+}
+
+int AudioIOESD::getParam(AudioParam p)
+{
+ switch(p)
+ {
+ case selectReadFD:
+ return read_fd;
+
+ case selectWriteFD:
+ return write_fd;
+
+ case canRead:
+ return ESD_BUF_SIZE;
+
+ case canWrite:
+ return ESD_BUF_SIZE;
+
+ // ESD handles are actually socket descriptors, and I know not
+ // of any portable way to peek at the socket's send or receive
+ // buffers.
+
+ default:
+ return param(p);
+ }
+}
+
+int AudioIOESD::read(void *buffer, int size)
+{
+ return ::read(read_fd, buffer, size);
+}
+
+int AudioIOESD::write(void *buffer, int size)
+{
+ return ::write(write_fd, buffer, size);
+}
+
+#endif
diff --git a/flow/audioiojack.cc b/flow/audioiojack.cc
new file mode 100644
index 0000000..787ac03
--- /dev/null
+++ b/flow/audioiojack.cc
@@ -0,0 +1,346 @@
+/*
+ Copyright (C) 2004 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBJACK
+
+#include <jack/jack.h>
+#include <jack/ringbuffer.h>
+
+#include "debug.h"
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#undef DEBUG_WAVEFORM
+#ifdef DEBUG_WAVEFORM
+#include <fstream>
+#endif
+
+#include <cstdlib>
+#include <cstring>
+
+namespace Arts {
+
+class AudioIOJack : public AudioIO, public TimeNotify {
+private:
+#ifdef DEBUG_WAVEFORM
+ std::ofstream plotfile;
+#endif
+ char * processBuffer;
+ size_t buffersize;
+
+protected:
+ jack_client_t *jack;
+ jack_port_t *outleft, *outright;
+ jack_port_t *inleft, *inright;
+ jack_ringbuffer_t *olb, *orb, *ilb, *irb;
+
+public:
+ AudioIOJack();
+
+ void notifyTime();
+
+ void setParam( AudioParam p, int & val );
+ int getParam(AudioParam param);
+
+ static int jackCallback( jack_nframes_t, void * );
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOJack,"jack","Jack Audio Connection Kit");
+}
+
+using namespace std;
+using namespace Arts;
+
+AudioIOJack::AudioIOJack()
+ :
+#ifdef DEBUG_WAVEFORM
+ plotfile( "/dev/shm/audioiojack.plot" ),
+#endif
+ jack( 0 )
+ , outleft( 0 )
+ , outright( 0 )
+ , inleft( 0 )
+ , inright( 0 )
+{
+ /*
+ * default parameters
+ */
+ param( samplingRate ) = 44100;
+ paramStr( deviceName ) = "jack";
+ param( fragmentSize ) = 512;
+ param( fragmentCount ) = 2;
+ param( channels ) = 2;
+ param( direction ) = 2;
+ param( format ) = 32;
+}
+
+bool AudioIOJack::open()
+{
+ string& _error = paramStr( lastError );
+ jack = jack_client_new( "artsd" );
+ if( jack == 0 )
+ {
+ _error = "Couldn't connect to jackd";
+ return false;
+ }
+
+ int& _sampleRate = param(samplingRate);
+ _sampleRate = jack_get_sample_rate( jack );
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+
+ /*
+ * don't allow unreasonable large fragmentSize/Count combinations,
+ * because "real" hardware also doesn't
+ */
+
+ if(_fragmentSize > 1024*8) _fragmentSize = 1024*8;
+
+ while(_fragmentSize * _fragmentCount > 1024*128)
+ _fragmentCount--;
+
+ jack_set_process_callback( jack, Arts::AudioIOJack::jackCallback, this );
+
+ if( param( direction ) & directionWrite )
+ {
+ outleft = jack_port_register( jack, "out_1",
+ JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
+ outright = jack_port_register( jack, "out_2",
+ JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
+ olb = jack_ringbuffer_create(
+ sizeof( jack_default_audio_sample_t ) *
+ _fragmentSize * _fragmentCount );
+ orb = jack_ringbuffer_create(
+ sizeof( jack_default_audio_sample_t ) *
+ _fragmentSize * _fragmentCount );
+ }
+ if( param( direction ) & directionRead )
+ {
+ inleft = jack_port_register( jack, "in_1",
+ JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
+ inright = jack_port_register( jack, "in_2",
+ JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
+ ilb = jack_ringbuffer_create(
+ sizeof( jack_default_audio_sample_t ) *
+ 1024 * 64 );
+ irb = jack_ringbuffer_create(
+ sizeof( jack_default_audio_sample_t ) *
+ 1024 * 64 );
+ }
+
+ if( jack_activate( jack ) )
+ {
+ _error = "Activating as jack client failed.";
+ return false;
+ }
+
+ const char **ports;
+ if( param( direction ) & directionRead )
+ {
+ ports = jack_get_ports( jack, 0, 0, JackPortIsPhysical
+ | JackPortIsOutput );
+ if( ports == 0 )
+ {
+ arts_warning( "Cannot find any capture ports to"
+ " connect to. You need to manually connect"
+ " the capture ports in jack" );
+ }
+ else
+ {
+ if( ports[ 0 ] != 0 )
+ jack_connect( jack, ports[ 0 ],
+ jack_port_name( inleft ) );
+ if( ports[ 1 ] != 0 )
+ jack_connect( jack, ports[ 1 ],
+ jack_port_name( inright ) );
+ free( ports );
+ }
+ }
+ if( param( direction ) & directionWrite )
+ {
+ ports = jack_get_ports( jack, 0, 0, JackPortIsPhysical
+ | JackPortIsInput );
+ if( ports == 0 )
+ {
+ arts_warning( "Cannot find any playback ports to"
+ " connect to. You need to manually connect"
+ " the playback ports in jack" );
+ }
+ else
+ {
+ if( ports[ 0 ] != 0 )
+ jack_connect( jack, jack_port_name( outleft ),
+ ports[ 0 ] );
+ if( ports[ 1 ] != 0 )
+ jack_connect( jack, jack_port_name( outright ),
+ ports[ 1 ] );
+ free( ports );
+ }
+ }
+
+ // Install the timer
+ Dispatcher::the()->ioManager()->addTimer(10, this);
+
+ return true;
+}
+
+void AudioIOJack::close()
+{
+ jack_client_close( jack );
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
+
+int AudioIOJack::jackCallback( jack_nframes_t nframes, void * args )
+{
+ AudioIOJack * that = static_cast<AudioIOJack*>( args );
+
+ that->buffersize = nframes * sizeof( jack_default_audio_sample_t );
+ if( that->outleft )
+ {
+ if( jack_ringbuffer_read_space( that->olb ) < that->buffersize )
+ {
+ that->processBuffer = static_cast<char *>(
+ jack_port_get_buffer( that->outleft, nframes ) );
+ memset( that->processBuffer, 0, that->buffersize );
+ that->processBuffer = static_cast<char *>(
+ jack_port_get_buffer( that->outright, nframes ) );
+ memset( that->processBuffer, 0, that->buffersize );
+ }
+ else
+ {
+ that->processBuffer = static_cast<char *>(
+ jack_port_get_buffer( that->outleft, nframes ) );
+ jack_ringbuffer_read( that->olb, that->processBuffer, that->buffersize );
+ that->processBuffer = static_cast<char *>(
+ jack_port_get_buffer( that->outright, nframes ) );
+ jack_ringbuffer_read( that->orb, that->processBuffer, that->buffersize );
+ }
+ }
+ if( that->inleft )
+ {
+ that->processBuffer = static_cast<char *>(
+ jack_port_get_buffer( that->inleft, nframes ) );
+ jack_ringbuffer_write( that->ilb, that->processBuffer, that->buffersize );
+ that->processBuffer = static_cast<char *>(
+ jack_port_get_buffer( that->inright, nframes ) );
+ jack_ringbuffer_write( that->irb, that->processBuffer, that->buffersize );
+ }
+ return 0;
+}
+
+void AudioIOJack::setParam( AudioParam p, int& val )
+{
+ // don't change the format - jack only supports 32 bit float
+ if( p == format )
+ return;
+ AudioIO::setParam( p, val );
+}
+
+int AudioIOJack::getParam(AudioParam p)
+{
+ switch(p)
+ {
+ case canRead:
+ return MIN( jack_ringbuffer_read_space( ilb ), jack_ringbuffer_read_space( irb ) ) * param( channels );
+ case canWrite:
+ return MIN( jack_ringbuffer_write_space( olb ), jack_ringbuffer_write_space( orb ) ) * param( channels );
+ default:
+ return AudioIO::getParam( p );
+ }
+}
+
+int AudioIOJack::read(void *buffer, int size)
+{
+ float * floatbuffer = static_cast<float *>( buffer );
+ if( param( channels ) == 2 )
+ {
+ float * end = ( float * )( static_cast<char *>( buffer ) + size );
+ while( floatbuffer < end )
+ {
+ jack_ringbuffer_read( ilb, ( char* )( floatbuffer++ ), sizeof( float ) );
+#ifdef DEBUG_WAVEFORM
+ plotfile << *( floatbuffer - 1 ) << "\n";
+#endif
+ jack_ringbuffer_read( irb, ( char* )( floatbuffer++ ), sizeof( float ) );
+ }
+ }
+ else if( param( channels ) == 1 )
+ {
+ jack_ringbuffer_read( ilb, ( char* )( floatbuffer ), size );
+ }
+ return size;
+}
+
+int AudioIOJack::write(void *buffer, int size)
+{
+ float * floatbuffer = static_cast<float *>( buffer );
+ if( param( channels ) == 2 )
+ {
+ float * end = ( float * )( static_cast<char *>( buffer ) + size );
+ while( floatbuffer < end )
+ {
+ jack_ringbuffer_write( olb, ( char* )( floatbuffer++ ), sizeof( float ) );
+ jack_ringbuffer_write( orb, ( char* )( floatbuffer++ ), sizeof( float ) );
+ }
+ }
+ else if( param( channels ) == 1 )
+ {
+ jack_ringbuffer_write( olb, ( char* )( floatbuffer ), size );
+ }
+ return size;
+}
+
+void AudioIOJack::notifyTime()
+{
+ int& _direction = param(direction);
+ int& _fragmentSize = param(fragmentSize);
+
+ for( ;; )
+ {
+ int todo = 0;
+ if( ( _direction & directionRead ) && ( getParam( canRead ) >= _fragmentSize ) )
+ todo |= AudioSubSystem::ioRead;
+
+ if( ( _direction & directionWrite ) && ( getParam( canWrite ) >= _fragmentSize ) )
+ todo |= AudioSubSystem::ioWrite;
+
+ if( ! todo )
+ return;
+
+ AudioSubSystem::the()->handleIO( todo );
+ }
+}
+
+#endif
+// vim: sw=4 ts=4
diff --git a/flow/audioiolibaudioio.cc b/flow/audioiolibaudioio.cc
new file mode 100644
index 0000000..e7c545e
--- /dev/null
+++ b/flow/audioiolibaudioio.cc
@@ -0,0 +1,236 @@
+ /*
+
+ Copyright (C) 2001 Robert Lunnon
+ bob@yarrabee.net.au
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile 'LibAudioIO' AudioIO class if libaudio was detected during
+ * configure
+ */
+#ifdef HAVE_LIBAUDIOIO
+
+#include <libaudioio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h> // Needed on some systems.
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+
+namespace Arts {
+
+class AudioIOLibAudioIO : public AudioIO {
+protected:
+ int audio_fd;
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+ SampleSpec_t spec;
+
+public:
+ AudioIOLibAudioIO();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOLibAudioIO,"libaudioio"," Portable Audio Library");
+};
+
+using namespace std;
+using namespace Arts;
+
+AudioIOLibAudioIO::AudioIOLibAudioIO()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = spec.rate=44100;
+ paramStr(deviceName) = "/dev/Audio";
+ requestedFragmentSize = param(fragmentSize) = 4096;
+ requestedFragmentCount =spec.max_blocks= param(fragmentCount) = 7;
+ param(channels) = spec.channels=2;
+ param(direction) = 2;
+}
+
+bool AudioIOLibAudioIO::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+
+ int mode;
+ spec.channels=_channels;
+ spec.max_blocks= param(fragmentCount);
+ spec.rate= _samplingRate;
+ spec.encoding= ENCODE_PCM;
+ spec.precision=16 ;
+ spec.endian=ENDIAN_NATURAL;
+ spec.disable_threads=1;
+
+ if(param(direction) == 3)
+ mode = O_RDWR|O_NDELAY;
+ else if(param(direction) == 2)
+ mode = O_WRONLY|O_NDELAY;
+ else
+ {
+ _error = "invalid direction";
+ return false;
+ }
+
+ audio_fd = ::AudioIOOpenX( mode, &spec,&spec );
+ if(audio_fd == -1)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+
+
+ /*
+ * since we use spec.endian=ENDIAN_NATURAL we'll have little endian audio
+ * on little endian machines and big endian audio on big endian machines:
+ */
+#ifdef WORDS_BIGENDIAN
+ _format = 17;
+#else
+ _format = 16;
+#endif
+
+ spec.channels=_channels;
+
+ spec.rate = _samplingRate;
+
+
+ _fragmentSize = requestedFragmentSize;
+ spec.max_blocks=_fragmentCount = requestedFragmentCount;
+
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+ return(true);
+}
+
+void AudioIOLibAudioIO::close()
+{
+ ::AudioIOClose();
+}
+
+void AudioIOLibAudioIO::setParam(AudioParam p, int& value)
+{
+ switch(p)
+ {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOLibAudioIO::getParam(AudioParam p)
+{
+ switch(p)
+ {
+ case canRead:
+ return AudioIOCheckRead();
+ break;
+
+ case canWrite:
+ return (AudioIOCheckWriteReady()) ? (16*1024) : 0;
+ // Assume if writable can write 16K
+ // Arts Really doesn't care
+ break;
+
+ case selectReadFD:
+ return (param(direction) & directionRead)?audio_fd:-1;
+ break;
+
+ case selectWriteFD:
+ return (param(direction) & directionWrite)?audio_fd:-1;
+ break;
+
+ case autoDetect:
+ /*
+ * if there is a "native" aRts driver, we'll rather use this
+ * than the generic libaudioio one, because the native one
+ * is likely to be better optimized to the needs of aRts than
+ * a generic driver, so keep the value small
+ */
+ return 3;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOLibAudioIO::read(void *buffer, int size)
+{
+ arts_assert(audio_fd != 0);
+ return ::AudioIORead(buffer,size);
+}
+
+int AudioIOLibAudioIO::write(void *buffer, int size)
+{
+ arts_assert(audio_fd != 0);
+ return ::AudioIOWrite(buffer,size);
+}
+
+#endif
diff --git a/flow/audioiomas.cc b/flow/audioiomas.cc
new file mode 100644
index 0000000..e49fec2
--- /dev/null
+++ b/flow/audioiomas.cc
@@ -0,0 +1,619 @@
+ /*
+
+ Copyright (C) 2001-2003 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * Only compile this AudioIO class if we have MAS
+ */
+#ifdef HAVE_LIBMAS
+
+extern "C" {
+#include <mas/mas.h>
+#include <mas/mas_getset.h>
+#include <mas/mas_source.h>
+}
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+namespace Arts {
+
+ class AudioIOMAS : public AudioIO, public TimeNotify {
+ protected:
+ mas_channel_t audio_channel;
+ mas_port_t mix_sink;
+ mas_port_t srate_source, srate_sink;
+ mas_port_t audio_source, audio_sink;
+ mas_port_t endian_sink, endian_source;
+ mas_port_t sbuf_source, sbuf_sink;
+ mas_port_t squant_sink, squant_source;
+ mas_port_t open_source; /* (!) */
+ mas_device_t endian;
+ mas_device_t srate;
+ mas_device_t squant;
+ mas_device_t sbuf;
+ mas_data *data;
+ mas_package package;
+ int32 mas_error;
+
+ std::list<mas_channel_t> allocated_channels;
+ std::list<mas_port_t> allocated_ports;
+ std::list<mas_device_t> allocated_devices;
+
+ double lastUpdate, bytesPerSec;
+ int readBufferAvailable;
+ int writeBufferAvailable;
+
+ double currentTime();
+ void updateBufferSizes();
+
+#ifdef WORDS_BIGENDIAN
+ static const int defaultFormat = 17;
+#else
+ static const int defaultFormat = 16;
+#endif
+ bool close_with_error(const std::string& text);
+ public:
+ AudioIOMAS();
+
+ // Timer callback
+ void notifyTime();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+ };
+
+ REGISTER_AUDIO_IO(AudioIOMAS,"mas","MAS Audio Input/Output");
+
+};
+
+using namespace std;
+using namespace Arts;
+
+AudioIOMAS::AudioIOMAS()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = ""; // TODO
+ param(fragmentSize) = 4096;
+ param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = 2;
+ param(format) = defaultFormat;
+}
+
+namespace {
+ int masInitCount = 0;
+}
+
+// Opens the audio device
+bool AudioIOMAS::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+
+ /* FIXME: do we need to free what we allocate with mas_init() in close() */
+ if (!masInitCount)
+ {
+ mas_error = mas_init();
+
+ if (mas_error < 0)
+ return close_with_error("error connecting to MAS server");
+ }
+ masInitCount++;
+
+ if (param(direction) != 2)
+ {
+ _error = "unsupported direction (currently no full duplex support)";
+ return false;
+ }
+
+ /*
+ * data path
+ *
+ * audio_sink
+ * audio_channel: data_channel ("artsd")
+ * audio_source
+ * |
+ * V
+ * endian_sink
+ * endian: instantiate_device ("endian")
+ * open_source = endian_source
+ * |
+ * V
+ * [squant_sink]
+ * [squant]
+ * [squant_source]
+ * |
+ * V
+ * [srate_sink]
+ * [srate]
+ * [srate_source]
+ * |
+ * V
+ * sbuf_sink
+ * sbuf
+ * sbuf_source
+ * |
+ * V
+ * mix_sink: port ("default_mix_sink")
+ */
+
+ // audio_channel, source & sink
+ mas_error = mas_make_data_channel("artsd", &audio_channel, &audio_source, &audio_sink);
+ if (mas_error < 0)
+ return close_with_error("error initializing MAS data channel");
+
+ allocated_channels.push_back(audio_channel);
+ allocated_ports.push_back(audio_source);
+ allocated_ports.push_back(audio_sink);
+
+ // endian, source & sink
+ mas_error = mas_asm_instantiate_device( "endian", 0, 0, &endian );
+ if ( mas_error < 0 )
+ return close_with_error("error initantiating MAS endian device");
+
+ allocated_devices.push_back(endian);
+
+ mas_error = mas_asm_get_port_by_name( endian, "sink", &endian_sink );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS endian device sink port");
+
+ allocated_ports.push_back(endian_sink);
+
+ mas_error = mas_asm_get_port_by_name( endian, "source", &endian_source );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS endian device source port");
+
+ allocated_ports.push_back(endian_source);
+
+ char ratestring[16], resolutionstring[16];
+ sprintf (ratestring, "%u", _samplingRate);
+ sprintf (resolutionstring, "%u", _format);
+
+ mas_data_characteristic* dc;
+
+ dc = (mas_data_characteristic *)MAS_NEW( dc );
+ masc_setup_dc( dc, 6 );
+ masc_append_dc_key_value( dc, "format", (_format==8) ? "ulinear":"linear" );
+
+ masc_append_dc_key_value( dc, "resolution", resolutionstring );
+ masc_append_dc_key_value( dc, "sampling rate", ratestring );
+ masc_append_dc_key_value( dc, "channels", "2" );
+ masc_append_dc_key_value( dc, "endian", "little" );
+
+ mas_error = mas_asm_connect_source_sink( audio_source, endian_sink, dc );
+ if ( mas_error < 0 )
+ return close_with_error("error connecting MAS net audio source to endian sink");
+
+ /* The next device is 'if needed' only. After the following if()
+ statement, open_source will contain the current unconnected
+ source in the path (will be either endian_source or
+ squant_source in this case)
+ */
+ open_source = endian_source;
+
+ if ( _format != 16 )
+ {
+ arts_debug("MAS output: Sample resolution is not 16 bit/sample, instantiating squant device.");
+
+ // squant, source & sink
+ mas_error = mas_asm_instantiate_device( "squant", 0, 0, &squant );
+ if ( mas_error < 0 )
+ return close_with_error("error creating MAS squant device");
+
+ allocated_devices.push_back(squant);
+
+ mas_error = mas_asm_get_port_by_name( squant, "sink", &squant_sink );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS squant device sink port");
+
+ allocated_ports.push_back(squant_sink);
+
+ mas_error = mas_asm_get_port_by_name( squant, "source", &squant_source );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS squant device source port");
+
+ allocated_ports.push_back(squant_source);
+
+ arts_debug( "MAS output: Connecting endian -> squant.");
+
+ masc_strike_dc( dc );
+ masc_setup_dc( dc, 6 );
+ masc_append_dc_key_value( dc,"format",(_format==8) ? "ulinear":"linear" );
+ masc_append_dc_key_value( dc, "resolution", resolutionstring );
+ masc_append_dc_key_value( dc, "sampling rate", ratestring );
+ masc_append_dc_key_value( dc, "channels", "2" );
+ masc_append_dc_key_value( dc, "endian", "host" );
+
+ mas_error = mas_asm_connect_source_sink( endian_source, squant_sink, dc );
+ if ( mas_error < 0 )
+ return close_with_error("error connecting MAS endian output to squant device");
+
+ /* sneaky: the squant device is optional -> pretend it isn't there */
+ open_source = squant_source;
+ }
+
+
+ /* Another 'if necessary' device, as above */
+ if ( _samplingRate != 44100 )
+ {
+ arts_debug ("MAS output: Sample rate is not 44100, instantiating srate device.");
+
+ // srate, source & sink
+ mas_error = mas_asm_instantiate_device( "srate", 0, 0, &srate );
+ if ( mas_error < 0 )
+ return close_with_error("error initantiating MAS srate device");
+
+ allocated_devices.push_back(srate);
+
+ mas_error = mas_asm_get_port_by_name( srate, "sink", &srate_sink );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS srate sink port");
+
+ allocated_ports.push_back(srate_sink);
+
+ mas_error = mas_asm_get_port_by_name( srate, "source", &srate_source );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS srate source port");
+
+ allocated_ports.push_back(srate_source);
+
+ arts_debug( "MAS output: Connecting to srate.");
+
+ masc_strike_dc( dc );
+ masc_setup_dc( dc, 6 );
+ masc_append_dc_key_value( dc, "format", "linear" );
+ masc_append_dc_key_value( dc, "resolution", "16" );
+ masc_append_dc_key_value( dc, "sampling rate", ratestring );
+ masc_append_dc_key_value( dc, "channels", "2" );
+ masc_append_dc_key_value( dc, "endian", "host" );
+
+ mas_error = mas_asm_connect_source_sink( open_source, srate_sink, dc );
+ if ( mas_error < 0 )
+ return close_with_error("error connecting to MAS srate device");
+
+ open_source = srate_source;
+ }
+
+ // sbuf, source & sink
+ mas_error = mas_asm_instantiate_device( "sbuf", 0, 0, &sbuf );
+ if ( mas_error < 0 )
+ return close_with_error("error initantiating MAS sbuf device");
+
+ allocated_devices.push_back(sbuf);
+
+ mas_error = mas_asm_get_port_by_name( sbuf, "sink", &sbuf_sink );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS sbuf device sink port");
+
+ allocated_ports.push_back(sbuf_sink);
+
+ mas_error = mas_asm_get_port_by_name( sbuf, "source", &sbuf_source );
+ if ( mas_error < 0 )
+ return close_with_error("error getting MAS sbuf device source port");
+
+ allocated_ports.push_back(sbuf_source);
+
+ masc_strike_dc( dc );
+ masc_setup_dc( dc, 6 );
+
+ masc_append_dc_key_value( dc, "format", "linear" );
+ masc_append_dc_key_value( dc, "resolution", "16" );
+ masc_append_dc_key_value( dc, "sampling rate", "44100" );
+ masc_append_dc_key_value( dc, "channels", "2" );
+ masc_append_dc_key_value( dc, "endian", "host" );
+
+ arts_debug("MAS output: Connecting to sbuf.");
+
+ mas_error = mas_asm_connect_source_sink( open_source, sbuf_sink, dc );
+ if ( mas_error < 0 )
+ return close_with_error("error connecting to MAS mixer device");
+
+ /* configure sbuf */
+
+ float BUFTIME_MS = _fragmentSize * _fragmentCount;
+ BUFTIME_MS *= 1000.0;
+ BUFTIME_MS /= (float)_channels;
+ if (_format > 8)
+ BUFTIME_MS /= 2.0;
+ BUFTIME_MS /= (float)_samplingRate;
+
+ arts_debug("MAS output: BUFTIME_MS = %f", BUFTIME_MS);
+
+ masc_setup_package( &package, NULL, 0, 0 );
+ masc_pushk_uint32( &package, "buftime_ms", (uint32) BUFTIME_MS );
+ masc_finalize_package( &package );
+ mas_set( sbuf, "buftime_ms", &package );
+ masc_strike_package( &package );
+
+ masc_setup_package( &package, NULL, 0, 0 );
+ masc_pushk_int32( &package, "mc_clkid", 9 );
+ masc_finalize_package( &package );
+ mas_set( sbuf, "mc_clkid", &package );
+ masc_strike_package( &package );
+
+ mas_source_play( sbuf );
+
+ // mix_sink
+ mas_error = mas_asm_get_port_by_name( 0, "default_mix_sink", &mix_sink );
+ if (mas_error < 0)
+ return close_with_error("error finding MAS default sink");
+
+ allocated_ports.push_back(mix_sink);
+
+ arts_debug("MAS output: Connecting sbuf to mix_sink.");
+
+ mas_error = mas_asm_connect_source_sink( sbuf_source, mix_sink, dc );
+ if ( mas_error < 0 )
+ return close_with_error("error connecting to MAS mixer device");
+
+ data = (mas_data *)MAS_NEW( data );
+ masc_setup_data( data, _fragmentSize ); /* we can reuse this */
+ data->length = _fragmentSize;
+ data->allocated_length = data->length;
+ data->header.type = 10;
+
+ arts_debug("MAS output: playing.");
+
+ // Install the timer
+ Dispatcher::the()->ioManager()->addTimer(10, this);
+
+ bytesPerSec = _channels * _samplingRate;
+ if (_format > 8)
+ bytesPerSec *= 2;
+
+ lastUpdate = 0;
+
+ return true;
+}
+
+double AudioIOMAS::currentTime()
+{
+ timeval tv;
+ gettimeofday(&tv,0);
+
+ return (double)tv.tv_sec + (double)tv.tv_usec/1000000.0;
+}
+
+bool AudioIOMAS::close_with_error(const string& text)
+{
+ string& error = paramStr(lastError);
+ error = text;
+ error += masc_strmerror (mas_error);
+ return false;
+}
+
+void AudioIOMAS::close()
+{
+ list<mas_port_t>::iterator pi;
+ for (pi = allocated_ports.begin(); pi != allocated_ports.end(); pi++)
+ mas_free_port (*pi);
+ allocated_ports.clear();
+
+ list<mas_channel_t>::iterator ci;
+ for (ci = allocated_channels.begin(); ci != allocated_channels.end(); ci++)
+ mas_free_channel (*ci);
+ allocated_channels.clear();
+
+ list<mas_device_t>::iterator di;
+ for (di = allocated_devices.begin(); di != allocated_devices.end(); di++)
+ {
+ mas_device_t device = *di;
+ mas_error = mas_asm_terminate_device_instance(device, 0);
+ if (mas_error < 0)
+ arts_warning ("MAS output: error while closing device: %s", masc_strmerror(mas_error));
+
+ mas_free_device(device);
+ }
+ allocated_devices.clear();
+
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
+
+void AudioIOMAS::updateBufferSizes()
+{
+ double time = currentTime();
+ double waterMark = param(fragmentSize);
+ waterMark *= 1.3;
+
+ if ((time - lastUpdate) * bytesPerSec < waterMark)
+ return;
+
+ lastUpdate = time;
+
+ uint32 inbuf_ms;
+ int32 mas_error;
+
+ mas_error = mas_get( sbuf, "inbuf_ms", 0 , &package );
+ if ( mas_error < 0 )
+ arts_fatal ("MAS output: error getting size of buffer: %s", masc_strmerror(mas_error));
+
+ masc_pull_uint32( &package, &inbuf_ms );
+ masc_strike_package( &package );
+
+ //arts_debug(" inbuf_ms = %u", inbuf_ms);
+
+ float bytes = inbuf_ms;
+ bytes /= 1000.0;
+ bytes *= param(samplingRate);
+ bytes *= param(channels);
+ if(param(format) > 8)
+ bytes *= 2;
+
+ int bytesFree = param(fragmentSize) * param(fragmentCount) - (int)bytes;
+
+ if (bytesFree < param(fragmentSize))
+ bytesFree = 0;
+
+ writeBufferAvailable = bytesFree;
+
+ arts_debug ("MAS output buffer: %6d / %6d bytes used => %6d bytes free",
+ (int)bytes, param(fragmentSize) * param(fragmentCount), writeBufferAvailable);
+}
+
+// This is called on each timer tick
+void AudioIOMAS::notifyTime()
+{
+ updateBufferSizes();
+
+ int& _direction = param(direction);
+ int& _fragmentSize = param(fragmentSize);
+
+ for (;;) {
+ int todo = 0;
+
+ if ((_direction & directionRead) && (getParam(canRead) >= _fragmentSize))
+ todo |= AudioSubSystem::ioRead;
+
+ if ((_direction & directionWrite) && (getParam(canWrite) >= _fragmentSize))
+ todo |= AudioSubSystem::ioWrite;
+
+ if (!todo)
+ return;
+
+ AudioSubSystem::the()->handleIO(todo);
+ }
+}
+
+void AudioIOMAS::setParam(AudioParam p, int& value)
+{
+ switch(p) {
+#if 0
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+#endif
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOMAS::getParam(AudioParam p)
+{
+ int bytes;
+ int count;
+
+ switch(p)
+ {
+#if 0
+ case canRead:
+ if (ioctl(audio_fd, AUDIO_GETINFO, &auinfo) < 0)
+ return (0);
+ bytes = (auinfo.record.samples * bytesPerSample) - bytesRead;
+ if (bytes < 0) {
+ printf("Error: bytes %d < 0, samples=%u, bytesRead=%u\n",
+ bytes, auinfo.record.samples, bytesRead);
+ bytes = 0;
+ }
+ return bytes;
+
+ case canWrite:
+ if (ioctl(audio_fd, AUDIO_GETINFO, &auinfo) < 0)
+ return (0);
+ count = SUN_MAX_BUFFER_SIZE -
+ (bytesWritten - (auinfo.play.samples * bytesPerSample));
+ return count;
+#endif
+ case canWrite:
+ return writeBufferAvailable;
+
+ case autoDetect:
+ /*
+ * Fairly small priority, for we haven't tested this a lot
+ */
+ return 3;
+
+ default:
+ return param(p);
+ }
+}
+
+int AudioIOMAS::read(void *buffer, int size)
+{
+#if 0
+ size = ::read(audio_fd, buffer, size);
+ if (size < 0)
+ return 0;
+
+ bytesRead += size;
+ return size;
+#endif
+ return 0;
+}
+
+int AudioIOMAS::write(void *buffer, int size)
+{
+ static int ts = 0;
+ static int seq = 0;
+ data->header.sequence = seq++;
+ data->header.media_timestamp = ts;
+ ts += size / 4;
+
+ assert(size == data->length);
+ memcpy(data->segment, buffer, size);
+
+ int32 mas_error = mas_send( audio_channel , data );
+ if (mas_error < 0)
+ arts_fatal ("MAS output: problem during mas_send: %s", masc_strmerror(mas_error));
+
+ writeBufferAvailable -= size;
+ return size;
+}
+
+#endif /* HAVE_LIBMAS */
diff --git a/flow/audioionas.cc b/flow/audioionas.cc
new file mode 100644
index 0000000..3106ade
--- /dev/null
+++ b/flow/audioionas.cc
@@ -0,0 +1,260 @@
+ /*
+
+ Copyright (C) 2001 Jochen Hoenicke
+ jochen@gnu.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile nas AudioIO class if libaudio was detected during
+ * configure
+ */
+#ifdef HAVE_LIBAUDIONAS
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+#include <audio/audiolib.h>
+
+namespace Arts {
+
+static AuBool
+eventHandler(AuServer *, AuEvent *ev, AuEventHandlerRec *handler);
+
+class AudioIONAS : public AudioIO, public IONotify {
+protected:
+ AuServer *aud;
+ AuDeviceID device;
+ AuFlowID flow;
+ AuElement elements[2];
+
+ int freeBytes;
+
+public:
+ AudioIONAS();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ void run();
+ void notifyIO(int, int);
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+
+ friend AuBool
+ eventHandler(AuServer *, AuEvent *ev, AuEventHandlerRec *handler);
+};
+
+REGISTER_AUDIO_IO(AudioIONAS,"nas","Network Audio System");
+}
+
+using namespace std;
+using namespace Arts;
+
+static AuBool
+Arts::eventHandler(AuServer *, AuEvent *ev, AuEventHandlerRec *handler)
+{
+ AudioIONAS *nas = (AudioIONAS *) handler->data;
+ if (ev->type == AuEventTypeElementNotify)
+ {
+ AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
+
+ switch (event->kind)
+ {
+ case AuElementNotifyKindLowWater:
+ nas->freeBytes += event->num_bytes;
+ AudioSubSystem::the()->handleIO
+ (AudioSubSystem::ioWrite);
+ break;
+ case AuElementNotifyKindState:
+ if (event->cur_state == AuStatePause
+ && event->reason != AuReasonUser)
+ {
+ nas->freeBytes += event->num_bytes;
+ AudioSubSystem::the()->handleIO
+ (AudioSubSystem::ioWrite);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+AudioIONAS::AudioIONAS()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 11025;
+ paramStr(deviceName) = "null";
+ param(fragmentSize) = 1024;
+ param(fragmentCount) = 7;
+ param(format) = 16;
+ param(channels) = 2;
+ param(direction) = 2;
+}
+
+bool AudioIONAS::open()
+{
+ char *server_msg;
+
+ int& _channels = param(channels);
+ int& _direction = param(direction);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+ string& _device = paramStr(deviceName);
+ string& _error = paramStr(lastError);
+ int _buf_samples, i;
+
+ if((_direction & directionRead))
+ {
+ _error = "no record audio device";
+ return false;
+ }
+
+ aud = AuOpenServer(_device.compare("null") == 0
+ ? NULL : _device.c_str(),
+ 0, NULL, 0, NULL, &server_msg);
+ if(aud == NULL)
+ {
+ _error = "device ";
+ _error += _device;
+ _error += " can't be opened (";
+ _error += server_msg;
+ _error += ")";
+ return false;
+ }
+
+ device = AuNone;
+ for (i = 0; i < AuServerNumDevices(aud); i++)
+ {
+ AuDeviceAttributes *devattr = AuServerDevice(aud, i);
+ if (AuDeviceKind(devattr) == AuComponentKindPhysicalOutput
+ && AuDeviceNumTracks(devattr) == _channels)
+ {
+ device = AuDeviceIdentifier(devattr);
+ break;
+ }
+ }
+
+ if (device == AuNone)
+ {
+ _error = "Couldn't find an output device";
+ return false;
+ }
+
+ if (!(flow = AuCreateFlow(aud, NULL)))
+ {
+ _error = "Couldn't create flow";
+ return false;
+ }
+
+ _buf_samples = _fragmentSize;
+ AuMakeElementImportClient(&elements[0], _samplingRate,
+ _format == 8 ? AuFormatLinearUnsigned8
+ : AuFormatLinearSigned16LSB,
+ _channels, AuTrue,
+ _buf_samples * _fragmentCount,
+ _buf_samples * (_fragmentCount)/2,
+ 0, NULL);
+ AuMakeElementExportDevice(&elements[1], 0, device, _samplingRate,
+ AuUnlimitedSamples, 0, NULL);
+ AuSetElements(aud, flow, AuTrue, 2, elements, NULL);
+ AuRegisterEventHandler(aud, AuEventHandlerIDMask, 0, flow,
+ eventHandler, (AuPointer) this);
+
+ freeBytes = 0;
+ AuStartFlow(aud, flow, NULL);
+
+ Dispatcher::the()->ioManager()->watchFD(aud->fd, IOType::read, this);
+
+ AuHandleEvents(aud);
+ return true;
+}
+
+void AudioIONAS::close()
+{
+ Dispatcher::the()->ioManager()->remove(this, IOType::all);
+ AuWriteElement(aud, flow, 0, 0, NULL, AuTrue, NULL);
+ AuCloseServer(aud);
+ aud = NULL;
+}
+
+void AudioIONAS::setParam(AudioParam p, int& value)
+{
+ param(p) = value;
+}
+
+int AudioIONAS::getParam(AudioParam p)
+{
+ switch(p)
+ {
+ case canWrite:
+ return freeBytes;
+
+ default:
+ return param(p);
+ }
+}
+
+void AudioIONAS::notifyIO(int, int)
+{
+ AuHandleEvents(aud);
+}
+
+int AudioIONAS::read(void *, int )
+{
+ return 0;
+}
+
+int AudioIONAS::write(void *buffer, int size)
+{
+ if (size > freeBytes)
+ size = freeBytes;
+ if (size > 0)
+ AuWriteElement(aud, flow, 0, size, buffer, AuFalse, NULL);
+ freeBytes -= size;
+ if (freeBytes > 0)
+ AudioSubSystem::the()->handleIO(AudioSubSystem::ioWrite);
+ return size;
+}
+
+#endif
diff --git a/flow/audioionull.cc b/flow/audioionull.cc
new file mode 100644
index 0000000..a8cd050
--- /dev/null
+++ b/flow/audioionull.cc
@@ -0,0 +1,184 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+#include <cstring>
+
+#include "debug.h"
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+namespace Arts {
+
+class AudioIONull : public AudioIO, public TimeNotify {
+protected:
+ timeval start;
+ double samplesRead, samplesWritten, bytesPerSec;
+
+public:
+ AudioIONull();
+
+ void notifyTime();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIONull,"null","No Audio Input/Output");
+}
+
+using namespace std;
+using namespace Arts;
+
+AudioIONull::AudioIONull()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = "null";
+ param(fragmentSize) = 1024;
+ param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = 2;
+}
+
+bool AudioIONull::open()
+{
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+ _format = 16;
+
+ /*
+ * don't allow unreasonable large fragmentSize/Count combinations,
+ * because "real" hardware also doesn't
+ */
+
+ if(_fragmentSize > 1024*128) _fragmentSize = 1024*128;
+
+ while(_fragmentSize * _fragmentCount > 1024*128)
+ _fragmentCount--;
+
+ Dispatcher::the()->ioManager()->addTimer(10, this);
+
+ samplesRead = samplesWritten = 0.0;
+ bytesPerSec = _channels * 2 * _samplingRate;
+ gettimeofday(&start,0);
+
+ return true;
+}
+
+void AudioIONull::close()
+{
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
+
+void AudioIONull::notifyTime()
+{
+ int& _direction = param(direction);
+ int& _fragmentSize = param(fragmentSize);
+
+ for(;;)
+ {
+ int todo = 0;
+
+ if((_direction & directionRead) && getParam(canRead) >= _fragmentSize)
+ todo |= AudioSubSystem::ioRead;
+
+ if((_direction & directionWrite) && getParam(canWrite) >= _fragmentSize)
+ todo |= AudioSubSystem::ioWrite;
+
+ if(!todo)
+ return;
+
+ AudioSubSystem::the()->handleIO(todo);
+ }
+}
+
+void AudioIONull::setParam(AudioParam p, int& value)
+{
+ param(p) = value;
+}
+
+int AudioIONull::getParam(AudioParam p)
+{
+ timeval now;
+ double delta;
+ int bytes;
+
+ switch(p)
+ {
+ case canRead:
+ case canWrite:
+ gettimeofday(&now,0);
+ delta = (double)now.tv_sec + (double)now.tv_usec/1000000.0;
+ delta -= (double)start.tv_sec + (double)start.tv_usec/1000000.0;
+ bytes = (int)( (delta * bytesPerSec)
+ - ((p == canRead)?samplesRead:samplesWritten)
+ );
+ return bytes;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIONull::read(void *buffer, int size)
+{
+ samplesRead += size;
+ memset(buffer, 0, size);
+ return size;
+}
+
+int AudioIONull::write(void *, int size)
+{
+ samplesWritten += size;
+ return size;
+}
diff --git a/flow/audioiooss.cc b/flow/audioiooss.cc
new file mode 100644
index 0000000..214cd3b
--- /dev/null
+++ b/flow/audioiooss.cc
@@ -0,0 +1,485 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#if defined(HAVE_SYS_SOUNDCARD_H)
+ #include <sys/soundcard.h>
+ #define COMPILE_AUDIOIO_OSS 1
+#elif defined(HAVE_SOUNDCARD_H)
+ #include <soundcard.h>
+ #define COMPILE_AUDIOIO_OSS 1
+#endif
+
+/**
+ * only compile 'oss' AudioIO class if sys/soundcard.h or soundcard.h is present
+ */
+#ifdef COMPILE_AUDIOIO_OSS
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_SELECT_H
+ #include <sys/select.h> // Needed on some systems.
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+#include <cstring>
+
+#include "debug.h"
+#include "audioio.h"
+
+namespace Arts {
+
+class AudioIOOSS : public AudioIO {
+protected:
+ int audio_fd;
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+
+ std::string findDefaultDevice();
+ int ossBits(int format);
+
+public:
+ AudioIOOSS();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+REGISTER_AUDIO_IO(AudioIOOSS,"oss","Open Sound System");
+}
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * Tries to figure out which is the OSS device we should write to
+ */
+string AudioIOOSS::findDefaultDevice()
+{
+ static const char *device[] = {
+ "/dev/dsp", /* The usual device */
+ // how does access(2) deal with a directory?
+ // I don't know, but, since /dev/sound/dsp is a linux bogosity
+ #if defined(__linux__)
+ "/dev/sound/dsp", /* Linux with devfs-only installation */
+ #else
+ "/dev/sound", /* NetBSD */
+ #endif
+ "/dev/audio", /* OpenBSD */
+ 0
+ };
+
+ for(int i = 0; device[i]; i++)
+ if(access(device[i],F_OK) == 0)
+ return device[i];
+
+ // Should this really return a valid device if we have access to none?
+ return device[0];
+}
+
+int AudioIOOSS::ossBits(int format)
+{
+ arts_return_val_if_fail (format == AFMT_U8
+ || format == AFMT_S16_LE
+ || format == AFMT_S16_BE, 16);
+
+ return (format == AFMT_U8)?8:16;
+}
+
+AudioIOOSS::AudioIOOSS()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = findDefaultDevice();
+ requestedFragmentSize = param(fragmentSize) = 1024;
+ requestedFragmentCount = param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = 2;
+}
+
+bool AudioIOOSS::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+
+ int mode;
+
+ if(param(direction) == 3)
+ mode = O_RDWR|O_NDELAY;
+ else if(param(direction) == 2)
+ mode = O_WRONLY|O_NDELAY;
+ else
+ {
+ _error = "invalid direction";
+ return false;
+ }
+
+ audio_fd = ::open(_deviceName.c_str(), mode, 0);
+
+ if(audio_fd == -1)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+ /*
+ * check device capabilities
+ */
+ int device_caps;
+ if(ioctl(audio_fd,SNDCTL_DSP_GETCAPS,&device_caps) == -1)
+ device_caps=0;
+
+ string caps = "";
+ if(device_caps & DSP_CAP_DUPLEX) caps += "duplex ";
+ if(device_caps & DSP_CAP_REALTIME) caps += "realtime ";
+ if(device_caps & DSP_CAP_BATCH) caps += "batch ";
+ if(device_caps & DSP_CAP_COPROC) caps += "coproc ";
+ if(device_caps & DSP_CAP_TRIGGER) caps += "trigger ";
+ if(device_caps & DSP_CAP_MMAP) caps += "mmap ";
+ artsdebug("device capabilities: revision%d %s",
+ device_caps & DSP_CAP_REVISION, caps.c_str());
+
+ int requestedFormat = (_format == 8)?AFMT_U8:AFMT_S16_LE;
+ int gotFormat = requestedFormat;
+ if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &gotFormat)==-1)
+ {
+ _error = "SNDCTL_DSP_SETFMT failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ if (_format && (ossBits(gotFormat) != ossBits(requestedFormat)))
+ {
+ char details[80];
+ sprintf(details," (_format = %d, asked driver to give %d, got %d)",
+ _format, requestedFormat, gotFormat);
+
+ _error = "Can't set playback format";
+ _error += details;
+
+ close();
+ return false;
+ }
+
+ if(gotFormat == AFMT_U8)
+ _format = 8;
+ else if(gotFormat == AFMT_S16_LE)
+ _format = 16;
+ else if(gotFormat == AFMT_S16_BE)
+ _format = 17;
+ else
+ {
+ char details[80];
+ sprintf(details," (_format = %d, asked driver to give %d, got %d)",
+ _format, requestedFormat, gotFormat);
+
+ _error = "unknown format given by driver";
+ _error += details;
+
+ close();
+ return false;
+ }
+
+
+ int stereo=-1; /* 0=mono, 1=stereo */
+
+ if(_channels == 1)
+ {
+ stereo = 0;
+ }
+ if(_channels == 2)
+ {
+ stereo = 1;
+ }
+
+ if(stereo == -1)
+ {
+ _error = "internal error; set channels to 1 (mono) or 2 (stereo)";
+
+ close();
+ return false;
+ }
+
+ int requeststereo = stereo;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
+ {
+ _error = "SNDCTL_DSP_STEREO failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ if (requeststereo != stereo)
+ {
+ _error = "audio device doesn't support number of requested channels";
+
+ close();
+ return false;
+ }
+
+ int speed = _samplingRate;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
+ {
+ _error = "SNDCTL_DSP_SPEED failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ /*
+ * Some soundcards seem to be able to only supply "nearly" the requested
+ * sampling rate, especially PAS 16 cards seem to quite radical supplying
+ * something different than the requested sampling rate ;)
+ *
+ * So we have a quite large tolerance here (when requesting 44100 Hz, it
+ * will accept anything between 38690 Hz and 49510 Hz). Most parts of the
+ * aRts code will do resampling where appropriate, so it shouldn't affect
+ * sound quality.
+ */
+ int tolerance = _samplingRate/10+1000;
+
+ if (abs(speed-_samplingRate) > tolerance)
+ {
+ _error = "can't set requested samplingrate";
+
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, speed);
+ _error += details;
+
+ close();
+ return false;
+ }
+ _samplingRate = speed;
+
+ /*
+ * set the fragment settings to what the user requested
+ */
+
+ _fragmentSize = requestedFragmentSize;
+ _fragmentCount = requestedFragmentCount;
+
+ /*
+ * lower 16 bits are the fragment size (as 2^S)
+ * higher 16 bits are the number of fragments
+ */
+ int frag_arg = 0;
+
+ int size = _fragmentSize;
+ while(size > 1) { size /= 2; frag_arg++; }
+ frag_arg += (_fragmentCount << 16);
+ if(ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_arg) == -1)
+ {
+ char buffer[1024];
+ _error = "can't set requested fragments settings";
+ sprintf(buffer,"size%d:count%d\n",_fragmentSize,_fragmentCount);
+ close();
+ return false;
+ }
+
+ /*
+ * now see what we really got as cards aren't required to supply what
+ * we asked for
+ */
+ audio_buf_info info;
+ if(ioctl(audio_fd,SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
+ _error = "can't retrieve fragment settings";
+ close();
+ return false;
+ }
+
+ // update fragment settings with what we got
+ _fragmentSize = info.fragsize;
+ _fragmentCount = info.fragstotal;
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+ /*
+ * Workaround for broken kernel drivers: usually filling up the audio
+ * buffer is _only_ required if _fullDuplex is true. However, there
+ * are kernel drivers around (especially everything related to ES1370/1371)
+ * which will not trigger select()ing the file descriptor unless we have
+ * written something first.
+ */
+ char *zbuffer = (char *)calloc(sizeof(char), _fragmentSize);
+ if(_format == 8)
+ for(int zpos = 0; zpos < _fragmentSize; zpos++)
+ zbuffer[zpos] |= 0x80;
+
+ for(int fill = 0; fill < _fragmentCount; fill++)
+ {
+ int len = write(zbuffer,_fragmentSize);
+ if(len != _fragmentSize)
+ {
+ arts_debug("AudioIOOSS: failed prefilling audio buffer (might cause synchronization problems in conjunction with full duplex)");
+ fill = _fragmentCount+1;
+ }
+ }
+ free(zbuffer);
+
+ /*
+ * Triggering - the original aRts code did this for full duplex:
+ *
+ * - stop audio i/o using SETTRIGGER(~(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT))
+ * - fill buffer (see zbuffer code two lines above)
+ * - start audio i/o using SETTRIGGER(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT)
+ *
+ * this should guarantee synchronous start of input/output. Today, it
+ * seems there are too many broken drivers around for this.
+ */
+
+ if(device_caps & DSP_CAP_TRIGGER)
+ {
+ int enable_bits = 0;
+
+ if(param(direction) & 1) enable_bits |= PCM_ENABLE_INPUT;
+ if(param(direction) & 2) enable_bits |= PCM_ENABLE_OUTPUT;
+
+ if(ioctl(audio_fd,SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1)
+ {
+ _error = "can't start sound i/o";
+
+ close();
+ return false;
+ }
+ }
+ return true;
+}
+
+void AudioIOOSS::close()
+{
+ ::close(audio_fd);
+}
+
+void AudioIOOSS::setParam(AudioParam p, int& value)
+{
+ switch(p)
+ {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOOSS::getParam(AudioParam p)
+{
+ audio_buf_info info;
+ switch(p)
+ {
+ case canRead:
+ ioctl(audio_fd, SNDCTL_DSP_GETISPACE, &info);
+ return info.bytes;
+ break;
+
+ case canWrite:
+ ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info);
+ return info.bytes;
+ break;
+
+ case selectReadFD:
+ return (param(direction) & directionRead)?audio_fd:-1;
+ break;
+
+ case selectWriteFD:
+ return (param(direction) & directionWrite)?audio_fd:-1;
+ break;
+
+ case autoDetect:
+ /* OSS works reasonable almost everywhere where it compiles */
+ return 10;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOOSS::read(void *buffer, int size)
+{
+ arts_assert(audio_fd != 0);
+
+ int result;
+ do {
+ result = ::read(audio_fd,buffer,size);
+ } while(result == -1 && errno == EINTR);
+
+ return result;
+}
+
+int AudioIOOSS::write(void *buffer, int size)
+{
+ arts_assert(audio_fd != 0);
+
+ int result;
+ do {
+ result = ::write(audio_fd,buffer,size);
+ } while(result == -1 && errno == EINTR);
+
+ return result;
+}
+
+#endif
diff --git a/flow/audioioossthreaded.cc b/flow/audioioossthreaded.cc
new file mode 100644
index 0000000..9b63c4a
--- /dev/null
+++ b/flow/audioioossthreaded.cc
@@ -0,0 +1,681 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ Multithreading support by
+ Matthias Welwarsky <matze@stud.fbi.fh-darmstadt.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#define COMPILE_AUDIOIO_OSS 1
+#endif
+
+#ifdef HAVE_SOUNDCARD_H
+#include <soundcard.h>
+#define COMPILE_AUDIOIO_OSS 1
+#endif
+
+/**
+ * only compile 'oss' AudioIO class if sys/soundcard.h or soundcard.h is present
+ * also, only compile if libpthread was found
+ */
+#if defined(COMPILE_AUDIOIO_OSS) && defined(HAVE_LIBPTHREAD)
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <cstring>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+// thread safe data queue implementation
+#include "thread.h"
+#include "bufferqueue.h"
+
+namespace Arts {
+
+class AudioIOOSSThreaded : public AudioIO, public TimeNotify {
+private:
+ class ReaderThread : public Arts::Thread {
+ public:
+ void run();
+ bool isRunning() { return runThread; }
+ void stop() { runThread = false; }
+ void setParent(AudioIOOSSThreaded* instance) { parent = instance; }
+
+ private:
+ bool runThread;
+ AudioIOOSSThreaded* parent;
+ };
+
+ class WriterThread : public Arts::Thread {
+ public:
+ void run();
+ bool isRunning() { return runThread; }
+ void stop() { runThread = false; }
+ void setParent(AudioIOOSSThreaded* instance) { parent = instance; }
+
+ private:
+ bool runThread;
+ AudioIOOSSThreaded* parent;
+ };
+
+ friend class ReaderThread;
+ friend class WriterThread;
+
+ void startThread();
+ void stopThread();
+
+ BufferQueue readerQueue;
+ BufferQueue writerQueue;
+
+ ReaderThread readerThread;
+ WriterThread writerThread;
+
+protected:
+ int audio_fd;
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+
+ std::string findDefaultDevice();
+ int ossBits(int format);
+
+public:
+ AudioIOOSSThreaded();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+
+ void notifyTime();
+};
+
+REGISTER_AUDIO_IO(AudioIOOSSThreaded,"toss","Threaded Open Sound System");
+}
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * Tries to figure out which is the OSS device we should write to
+ */
+string AudioIOOSSThreaded::findDefaultDevice()
+{
+ static const char *device[] = {
+ "/dev/dsp", /* Linux (and lots of others) */
+ "/dev/sound/dsp0", /* Linux with devfs-only installation */
+ "/dev/audio", /* OpenBSD */
+ 0
+ };
+
+ for(int i = 0; device[i]; i++)
+ if(access(device[i],F_OK) == 0)
+ return device[i];
+
+ return device[0];
+}
+
+int AudioIOOSSThreaded::ossBits(int format)
+{
+ arts_return_val_if_fail (format == AFMT_U8
+ || format == AFMT_S16_LE
+ || format == AFMT_S16_BE, 16);
+
+ return (format == AFMT_U8)?8:16;
+}
+
+AudioIOOSSThreaded::AudioIOOSSThreaded()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = findDefaultDevice();
+ requestedFragmentSize = param(fragmentSize) = 1024;
+ requestedFragmentCount = param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = 2;
+}
+
+bool AudioIOOSSThreaded::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+
+ if (!SystemThreads::supported()) {
+ _error = "System does not support multithreading";
+ return false;
+ }
+
+ int mode;
+
+ if(param(direction) == 3)
+ mode = O_RDWR;
+ else if(param(direction) == 2)
+ mode = O_WRONLY;
+ else
+ {
+ _error = "invalid direction";
+ return false;
+ }
+
+ audio_fd = ::open(_deviceName.c_str(), mode, 0);
+
+ if(audio_fd == -1)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+ /*
+ * check device capabilities
+ */
+ int device_caps;
+ if(ioctl(audio_fd,SNDCTL_DSP_GETCAPS,&device_caps) == -1)
+ device_caps=0;
+
+ string caps = "";
+ if(device_caps & DSP_CAP_DUPLEX) caps += "duplex ";
+ if(device_caps & DSP_CAP_REALTIME) caps += "realtime ";
+ if(device_caps & DSP_CAP_BATCH) caps += "batch ";
+ if(device_caps & DSP_CAP_COPROC) caps += "coproc ";
+ if(device_caps & DSP_CAP_TRIGGER) caps += "trigger ";
+ if(device_caps & DSP_CAP_MMAP) caps += "mmap ";
+ artsdebug("device capabilities: revision%d %s",
+ device_caps & DSP_CAP_REVISION, caps.c_str());
+
+ int requestedFormat = (_format == 8)?AFMT_U8:AFMT_S16_LE;
+ int gotFormat = requestedFormat;
+ if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &gotFormat)==-1)
+ {
+ _error = "SNDCTL_DSP_SETFMT failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ if (_format && (ossBits(gotFormat) != ossBits(requestedFormat)))
+ {
+ char details[80];
+ sprintf(details," (_format = %d, asked driver to give %d, got %d)",
+ _format, requestedFormat, gotFormat);
+
+ _error = "Can't set playback format";
+ _error += details;
+
+ close();
+ return false;
+ }
+
+ if(gotFormat == AFMT_U8)
+ _format = 8;
+ else if(gotFormat == AFMT_S16_LE)
+ _format = 16;
+ else if(gotFormat == AFMT_S16_BE)
+ _format = 17;
+ else
+ {
+ char details[80];
+ sprintf(details," (_format = %d, asked driver to give %d, got %d)",
+ _format, requestedFormat, gotFormat);
+
+ _error = "unknown format given by driver";
+ _error += details;
+
+ close();
+ return false;
+ }
+
+
+ int stereo=-1; /* 0=mono, 1=stereo */
+
+ if(_channels == 1)
+ {
+ stereo = 0;
+ }
+ if(_channels == 2)
+ {
+ stereo = 1;
+ }
+
+ if(stereo == -1)
+ {
+ _error = "internal error; set channels to 1 (mono) or 2 (stereo)";
+
+ close();
+ return false;
+ }
+
+ int requeststereo = stereo;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
+ {
+ _error = "SNDCTL_DSP_STEREO failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ if (requeststereo != stereo)
+ {
+ _error = "audio device doesn't support number of requested channels";
+
+ close();
+ return false;
+ }
+
+ int speed = _samplingRate;
+
+ if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed)==-1)
+ {
+ _error = "SNDCTL_DSP_SPEED failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+ /*
+ * Some soundcards seem to be able to only supply "nearly" the requested
+ * sampling rate, especially PAS 16 cards seem to quite radical supplying
+ * something different than the requested sampling rate ;)
+ *
+ * So we have a quite large tolerance here (when requesting 44100 Hz, it
+ * will accept anything between 38690 Hz and 49510 Hz). Most parts of the
+ * aRts code will do resampling where appropriate, so it shouldn't affect
+ * sound quality.
+ */
+ int tolerance = _samplingRate/10+1000;
+
+ if (abs(speed-_samplingRate) > tolerance)
+ {
+ _error = "can't set requested samplingrate";
+
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, speed);
+ _error += details;
+
+ close();
+ return false;
+ }
+ _samplingRate = speed;
+
+ /*
+ * set the fragment settings to what the user requested
+ */
+
+ _fragmentSize = requestedFragmentSize;
+ _fragmentCount = requestedFragmentCount;
+
+ /*
+ * lower 16 bits are the fragment size (as 2^S)
+ * higher 16 bits are the number of fragments
+ */
+ unsigned int frag_arg = 0;
+
+ unsigned int size = _fragmentSize;
+ while(size > 1) { size /= 2; frag_arg++; }
+ frag_arg += (_fragmentCount << 16);
+
+ //////////////////////////////////////////////////////////////////////
+ // MW
+ // stopping here because the fragment settings cannot be done
+ // is not sensible. Especially not as we check the settings in the
+ // very next step. We should handle this gracefully.
+ //
+ ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_arg);
+
+ /*
+ * now see what we really got as cards aren't required to supply what
+ * we asked for
+ */
+ audio_buf_info info;
+ if(ioctl(audio_fd,SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
+ _error = "can't retrieve fragment settings";
+ close();
+ return false;
+ }
+
+ // update fragment settings with what we got
+ //_fragmentSize = info.fragsize;
+ //_fragmentCount = info.fragstotal;
+
+ fprintf(stderr, "buffering: fragsize:%d fragstotal:%d\n",
+ _fragmentSize, _fragmentCount);
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+ // set the chunk size of the buffer queues.
+ readerQueue.setChunkSize(_fragmentSize);
+ writerQueue.setChunkSize(_fragmentSize);
+
+ /*
+ * Workaround for broken kernel drivers: usually filling up the audio
+ * buffer is _only_ required if _fullDuplex is true. However, there
+ * are kernel drivers around (especially everything related to ES1370/1371)
+ * which will not trigger select()ing the file descriptor unless we have
+ * written something first.
+ */
+ char *zbuffer = (char *)calloc(sizeof(char), _fragmentSize);
+ if(_format == 8)
+ for(int zpos = 0; zpos < _fragmentSize; zpos++)
+ zbuffer[zpos] |= 0x80;
+
+ for(int fill = 0; fill < _fragmentCount; fill++)
+ {
+ int len = ::write(audio_fd,zbuffer,_fragmentSize);
+ if(len != _fragmentSize)
+ {
+ arts_debug("AudioIOOSSThreaded: failed prefilling audio buffer (might cause synchronization problems in conjunction with full duplex)");
+ fill = _fragmentCount+1;
+ }
+ }
+ free(zbuffer);
+
+ /*
+ * Triggering - the original aRts code did this for full duplex:
+ *
+ * - stop audio i/o using SETTRIGGER(~(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT))
+ * - fill buffer (see zbuffer code two lines above
+ * - start audio i/o using SETTRIGGER(PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT)
+ *
+ * this should guarantee synchronous start of input/output. Today, it
+ * seems there are too many broken drivers around for this.
+ */
+
+ if(device_caps & DSP_CAP_TRIGGER)
+ {
+ int enable_bits = 0;
+
+ if(param(direction) & 1) enable_bits |= PCM_ENABLE_INPUT;
+ if(param(direction) & 2) enable_bits |= PCM_ENABLE_OUTPUT;
+
+ if(ioctl(audio_fd,SNDCTL_DSP_SETTRIGGER, &enable_bits) == -1)
+ {
+ _error = "can't start of sound i/o operation";
+
+ close();
+ return false;
+ }
+ }
+
+ startThread();
+
+ Dispatcher::the()->ioManager()->addTimer(10, this);
+
+ return true;
+}
+
+void AudioIOOSSThreaded::close()
+{
+ fprintf(stderr, "AudioIO::close(): entering\n");
+ Dispatcher::the()->ioManager()->removeTimer(this);
+
+ ::close(audio_fd);
+ stopThread();
+ fprintf(stderr, "AudioIO::close(): leaving\n");
+}
+
+void AudioIOOSSThreaded::notifyTime()
+{
+ int& _direction = param(direction);
+
+ for(int i=0; i < 3; i++) {
+ int todo = 0;
+
+ if((_direction & directionRead) && getParam(canRead) > 0)
+ todo |= AudioSubSystem::ioRead;
+
+ if((_direction & directionWrite) && getParam(canWrite) > 0)
+ todo |= AudioSubSystem::ioWrite;
+
+ //fprintf(stderr, "AudioIO: can write %d, fragment size %d, todo %d\n",
+ // getParam(canWrite), _fragmentSize, todo);
+
+ if(!todo) // break endless loop
+ break;
+
+ AudioSubSystem::the()->handleIO(todo);
+ }
+}
+
+void AudioIOOSSThreaded::setParam(AudioParam p, int& value)
+{
+ switch(p) {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOOSSThreaded::getParam(AudioParam p)
+{
+ switch(p) {
+ case canRead:
+ return readerQueue.bufferedChunks() * readerQueue.chunkSize();
+ break;
+
+ case canWrite:
+ return writerQueue.freeChunks() * writerQueue.chunkSize();
+ break;
+
+ case autoDetect:
+ /* It compiles, but Posix Threads don't work everywhere */
+ return 4;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOOSSThreaded::read(void *buffer, int size)
+{
+ int copied = 0;
+ int copySize;
+ ByteBuffer* tmpBuf = 0;
+ while (size > 0) {
+ if (!tmpBuf)
+ tmpBuf = readerQueue.waitProduced();
+
+ copySize = (size > tmpBuf->size())? tmpBuf->size():size;
+ memcpy(((char*)buffer)+copied, tmpBuf->get(), copySize);
+
+ if (tmpBuf->push(copySize) == 0) {
+ tmpBuf = 0;
+ readerQueue.consumed();
+ }
+
+ copied += copySize;
+ size -= copySize;
+ }
+ return copied;
+}
+
+int AudioIOOSSThreaded::write(void *buffer, int size)
+{
+ int copied = 0;
+ while (size > 0) {
+ int copySize = (size > writerQueue.chunkSize())?writerQueue.chunkSize():size;
+ if (!writerQueue.freeChunks())
+ fprintf(stderr, "AudioIO::write will block!\n");
+ writerQueue.write(buffer, copySize);
+ copied += copySize;
+ size -= copySize;
+ }
+ return copied;
+}
+
+/*
+ * posix thread to feed the audio device
+ */
+
+void AudioIOOSSThreaded::WriterThread::run()
+{
+ fprintf(stderr, "AudioIOOSSThreaded::writerThread() thread started\n");
+
+ setPriority(45);
+
+ runThread = true;
+
+ ssize_t size;
+ ByteBuffer* tmpBuf = 0;
+ while (runThread) {
+
+ if (!tmpBuf) {
+ tmpBuf = parent->writerQueue.waitProduced();
+
+ if (!tmpBuf->size()) {
+ tmpBuf = NULL;
+ parent->writerQueue.consumed();
+ continue;
+ }
+ }
+
+ size = ::write(parent->audio_fd, tmpBuf->get(), tmpBuf->size());
+
+ if (size >= 0) {
+ if (tmpBuf->push(size) == 0) {
+ tmpBuf = NULL;
+ parent->writerQueue.consumed();
+ }
+ } else if (errno != EINTR) {
+ // this is a fatal error. we cannot write to the fd any more.
+ runThread = false;
+ fprintf(stderr, "AudioIOOSSTHreaded::writerThread() fatal error writing to audio_fd\n");
+ }
+ }
+ fprintf(stderr, "AudioIOOSSThreaded::writerThread() thread stopped\n");
+}
+
+/*
+ * posix thread to read the audio device
+ */
+void AudioIOOSSThreaded::ReaderThread::run()
+{
+ fprintf(stderr, "AudioIOOSSThreaded::readerThread() thread started\n");
+
+ runThread = true;
+
+ ByteBuffer* tmpBuf;
+ ssize_t size;
+ while (runThread) {
+ tmpBuf = parent->readerQueue.waitConsumed();
+
+ size = ::read(parent->audio_fd, tmpBuf->reset(), tmpBuf->maxSize());
+
+ if (size >= 0) {
+ tmpBuf->set(size);
+ parent->readerQueue.produced();
+ } else if (errno != EINTR) {
+ runThread = false;
+ fprintf(stderr, "AudioIOOSSTHreaded::readerThread() fatal error reading from audio_fd\n");
+ }
+ }
+ fprintf(stderr, "AudioIOOSSThreaded::readerThread() thread stopped\n");
+}
+
+void AudioIOOSSThreaded::startThread()
+{
+ fprintf(stderr, "AudioIOOSSThreaded::startThread(): entering\n");
+
+ if (param(direction) & directionWrite) {
+ writerThread.setParent(this);
+ writerThread.start();
+ }
+ if (param(direction) & directionRead) {
+ readerThread.setParent(this);
+ readerThread.start();
+ }
+
+ fprintf(stderr, "AudioIOOSSThreaded::startThread(): leaving\n");
+}
+
+void AudioIOOSSThreaded::stopThread()
+{
+ fprintf(stderr, "AudioIOOSSThreaded::stopThread() entering\n");
+
+ if (param(direction) & directionWrite) {
+ writerThread.stop();
+ // make sure there's something to write, avoids race condition
+ if (writerQueue.isEmpty())
+ writerQueue.write(NULL, 0);
+ fprintf(stderr, "waiting for writerThread to finish\n");
+ writerThread.waitDone();
+ writerQueue.clear();
+ }
+
+ if (param(direction) & directionRead) {
+ readerThread.stop();
+ fprintf(stderr, "waiting for readerThread to finish\n");
+ readerThread.waitDone();
+ readerQueue.clear();
+ }
+
+ fprintf(stderr, "AudioIOOSSThreaded::stopThread(): leaving\n");
+}
+
+#endif
diff --git a/flow/audioiosgi.cc b/flow/audioiosgi.cc
new file mode 100644
index 0000000..96a677c
--- /dev/null
+++ b/flow/audioiosgi.cc
@@ -0,0 +1,274 @@
+ /*
+
+ Copyright (C) 2001 Carsten Kroll
+ ckroll@pinnaclesys.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/**
+ * only compile 'sgi' AudioIO class if compiled under IRIX
+ */
+#ifdef HAVE_IRIX
+
+#include <dmedia/audio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h> // Needed on some systems.
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+
+namespace Arts {
+
+class AudioIOSGI : public AudioIO {
+protected:
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+ ALport audio_port,audio_port1;
+ ALconfig audioconfig;
+ int framesz;
+
+public:
+ AudioIOSGI();
+
+ void setParam(AudioParam param, int& value);
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+};
+
+
+REGISTER_AUDIO_IO(AudioIOSGI,"sgi","SGI dmedia Audio I/O");
+};
+
+using namespace std;
+using namespace Arts;
+
+AudioIOSGI::AudioIOSGI()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ paramStr(deviceName) = "audioio";
+ requestedFragmentSize = param(fragmentSize) = 4096;
+ requestedFragmentCount = param(fragmentCount) = 10;
+ audio_port=0;
+ audio_port1=0;
+ param(format)=17;
+ param(channels) = 2;
+ param(direction) = 2;
+}
+
+bool AudioIOSGI::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+ int& _direction = param(direction);
+ int err;
+
+ if(_direction != 3 && _direction != 2){
+ _error = "invalid direction";
+ return false;
+ }
+ framesz=((_format & ~1) >> 3) * _channels;
+
+ audioconfig = alNewConfig();
+ alSetSampFmt(audioconfig,AL_SAMPFMT_TWOSCOMP);
+
+ alSetWidth(audioconfig, _format==8 ? AL_SAMPLE_8 : _format==16 || _format==17 ? AL_SAMPLE_16 : AL_SAMPLE_24);
+ alSetQueueSize(audioconfig,(requestedFragmentSize * requestedFragmentCount) / framesz);
+ alSetChannels(audioconfig,_channels);
+
+ audio_port = alOpenPort("out","w",audioconfig);
+
+
+ if (audio_port == (ALport) 0 ) {
+ err = oserror();
+ if (err == AL_BAD_NO_PORTS) {
+ _error = "System is out of audio ports";
+ } else if (err == AL_BAD_DEVICE_ACCESS) {
+ _error = "Couldn't access audio device";
+ } else if (err == AL_BAD_OUT_OF_MEM) {
+ _error = "Out of memory";
+ }
+ close();
+ return false;
+ }
+ if (_direction == 3){
+ audio_port1 = alOpenPort("in","r",audioconfig);
+ if (audio_port1 == (ALport) 0 ) {
+ err = oserror();
+ if (err == AL_BAD_NO_PORTS) {
+ _error = "System is out of audio ports";
+ } else if (err == AL_BAD_DEVICE_ACCESS) {
+ _error = "Couldn't access audio device";
+ } else if (err == AL_BAD_OUT_OF_MEM) {
+ _error = "Out of memory";
+ }
+ close();
+ return false;
+ }
+ }
+ /*
+ * Attempt to set a crystal-based sample-rate on the
+ * given device.
+ */
+ ALpv x[2];
+ x[0].param = AL_MASTER_CLOCK;
+ x[0].value.i = AL_CRYSTAL_MCLK_TYPE;
+ x[1].param = AL_RATE;
+ x[1].value.ll = alDoubleToFixed(double(_samplingRate));
+ if (alSetParams(alGetResource(audio_port),x, 2)<0) {
+ _error="setparams failed: ";
+ _error+=alGetErrorString(oserror());
+ close();
+ return false;
+ }
+ if (_direction == 3)
+ if (alSetParams(alGetResource(audio_port1),x, 2)<0) {
+ _error="setparams failed: ";
+ _error+=alGetErrorString(oserror());
+ close();
+ return false;
+ }
+ if (x[1].sizeOut < 0) {
+ _error="rate was invalid";
+ close();
+ return false;
+ }
+
+ alSetFillPoint(audio_port,(alGetQueueSize(audioconfig)*5)/10) ;//50 %
+ if (_direction == 3)
+ alSetFillPoint(audio_port1,(alGetQueueSize(audioconfig)*4)/10) ;//40 %
+ /*
+ * set the fragment settings to what the user requested
+ */
+
+ _fragmentSize = requestedFragmentSize;
+ _fragmentCount = requestedFragmentCount;
+
+
+ artsdebug("buffering: %d fragments with %d bytes "
+ "(audio latency is %1.1f ms)", _fragmentCount, _fragmentSize,
+ (float)(_fragmentSize*_fragmentCount) /
+ (float)(2.0 * _samplingRate * _channels)*1000.0);
+
+
+ return true;
+}
+
+void AudioIOSGI::close()
+{
+ alFreeConfig(audioconfig);
+ alClosePort(audio_port);
+ audio_port=0;
+ if (param(direction) == 3) {
+ alClosePort(audio_port1);
+ audio_port1=0;
+ }
+}
+
+void AudioIOSGI::setParam(AudioParam p, int& value)
+{
+ switch(p)
+ {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOSGI::getParam(AudioParam p)
+{
+ int frames;
+ switch(p)
+ {
+ case canRead:
+ frames=alGetFilled(audio_port);
+ return frames*framesz;
+ break;
+
+ case canWrite:
+ frames=alGetFillable(audio_port);
+ return frames*framesz;
+ break;
+
+ case selectReadFD:
+ return (param(direction) & directionRead)?
+ alGetFD(audio_port1):-1;
+ break;
+
+ case selectWriteFD:
+ return (param(direction) & directionWrite)?
+ alGetFD(audio_port):-1;
+ break;
+
+ default:
+ return param(p);
+ break;
+ }
+}
+
+int AudioIOSGI::read(void *buffer, int size)
+{
+ arts_assert(audio_port1 != 0);
+ ::alReadFrames(audio_port1,buffer,size/framesz);
+ return size;
+}
+
+int AudioIOSGI::write(void *buffer, int size)
+{
+ arts_assert(audio_port != 0);
+ ::alWriteFrames(audio_port,buffer,size/framesz);
+ return size;
+}
+
+#endif
diff --git a/flow/audioiosun.cc b/flow/audioiosun.cc
new file mode 100644
index 0000000..9b14aa4
--- /dev/null
+++ b/flow/audioiosun.cc
@@ -0,0 +1,442 @@
+ /*
+
+ Copyright (C) 2001 Aaron Williams
+ aaronw@home.com
+ (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * Audio support for Sun Solaris, written by Aaron Williams
+ *
+ *
+ * Please send comments to aaronw@home.com
+ *
+ * This code has been tested with Solaris 7 running on a Sun Ultra 5
+ *
+ * Note that in Solaris the select support appears to be broken.
+ * Because of this, we use a timer and a dispatcher instead so we
+ * arn't polling (and sucking up most of the CPU).
+ *
+ * Currently read support has not been tested and will likely break
+ * other code
+ *
+ * 8-bit audio support also does not work (which I don't consider a
+ * big deal).
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * Only compile this AudioIO class if we're on Solaris
+ */
+#ifdef USE_SOLARIS
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#include <sys/audioio.h>
+#include <stropts.h>
+#include <sys/conf.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+
+#include "debug.h"
+#include "audioio.h"
+#include "audiosubsys.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+
+// This looks like the maximum buffer size according to the sys/audio*.h
+// files on Solaris7
+#define SUN_MAX_BUFFER_SIZE (65536)
+
+namespace Arts {
+
+ class AudioIOSun : public AudioIO, public TimeNotify {
+ protected:
+ uint_t bytesRead, bytesWritten, bytesPerSec;
+ uint_t bytesPerSample;
+ timeval start;
+ int audio_fd;
+ int requestedFragmentSize;
+ int requestedFragmentCount;
+ audio_info_t auinfo;
+
+#ifdef WORDS_BIGENDIAN
+ static const int defaultFormat = 17;
+#else
+ static const int defaultFormat = 16;
+#endif
+
+ public:
+ AudioIOSun();
+
+ // Timer callback
+ void notifyTime();
+
+ void setParam(AudioParam param, int& value);
+
+ int getParam(AudioParam param);
+
+ bool open();
+ void close();
+ int read(void *buffer, int size);
+ int write(void *buffer, int size);
+ };
+
+ REGISTER_AUDIO_IO(AudioIOSun,"sun","Sun Audio Input/Output");
+
+};
+
+using namespace std;
+using namespace Arts;
+
+AudioIOSun::AudioIOSun()
+{
+ /*
+ * default parameters
+ */
+ param(samplingRate) = 44100;
+ // solaris convention to support SunRays run out-of-the-box
+ const char *audioDev = getenv("AUDIODEV");
+ paramStr(deviceName) = (audioDev != 0)?audioDev:"/dev/audio";
+ param(fragmentSize) = 1024;
+ param(fragmentCount) = 7;
+ param(channels) = 2;
+ param(direction) = 2;
+ param(format) = defaultFormat;
+}
+
+// Opens the audio device
+bool AudioIOSun::open()
+{
+ string& _error = paramStr(lastError);
+ string& _deviceName = paramStr(deviceName);
+ int& _channels = param(channels);
+ int& _fragmentSize = param(fragmentSize);
+ int& _fragmentCount = param(fragmentCount);
+ int& _samplingRate = param(samplingRate);
+ int& _format = param(format);
+
+ int mode;
+
+ if (param(direction) == 3)
+ mode = O_RDWR;
+ else if (param(direction) == 2)
+ mode = O_WRONLY;
+ else
+ {
+ _error = "invalid direction";
+ return false;
+ }
+
+ audio_fd = ::open(_deviceName.c_str(), mode, 0);
+
+ if (audio_fd < 0)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " can't be opened (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+
+ fcntl(audio_fd, F_SETFL, O_NDELAY);
+
+ AUDIO_INITINFO(&auinfo);
+
+ if (ioctl(audio_fd, AUDIO_GETINFO, &auinfo) < 0)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " AUDIO_GETINFO failed (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+
+ if(_format != 8) _format = defaultFormat;
+#if 0
+ printf("param(direction)=%d\n", param(direction));
+ printf("format: %d\n", _format);
+ printf("channels: %d\n", _channels);
+ printf("sampling rate: %d\n", _samplingRate);
+#endif
+
+ bytesPerSample = ((_format == 8) ? 8 : 16)/8 * _channels;
+
+ auinfo.play.precision = (_format == 8) ? 8 : 16;
+ if (param(direction) == 3)
+ auinfo.record.precision = (_format == 8) ? 8 : 16;
+
+ auinfo.play.encoding = AUDIO_ENCODING_LINEAR;
+ if (param(direction) == 3)
+ auinfo.record.encoding = AUDIO_ENCODING_LINEAR;
+
+ auinfo.play.channels = _channels;
+ if (param(direction) == 3)
+ auinfo.record.channels = _channels;
+
+ auinfo.play.sample_rate = _samplingRate;
+ if (param(direction) == 3)
+ auinfo.record.sample_rate = _samplingRate;
+
+ if (ioctl(audio_fd, AUDIO_SETINFO, &auinfo) < 0)
+ {
+ _error = "AUDIO_SETINFO failed - ";
+ _error += strerror(errno);
+
+ close();
+ return false;
+ }
+
+
+ if (ioctl(audio_fd, AUDIO_GETINFO, &auinfo) < 0)
+ {
+ _error = "device ";
+ _error += _deviceName.c_str();
+ _error += " AUDIO_GETINFO failed (";
+ _error += strerror(errno);
+ _error += ")";
+ return false;
+ }
+
+ if (auinfo.play.precision != (uint_t)((_format == 8) ? 8 : 16) ||
+ (param(direction) == 3 &&
+ auinfo.record.precision != (uint_t)((_format == 8) ? 8 : 16)))
+ {
+ char play_details[80];
+ char record_details[80];
+ sprintf(play_details,
+ " (_format = %d, asked driver to give %d, got %d)",
+ _format, _format, auinfo.play.precision);
+ if (param(direction) == 3)
+ sprintf(record_details,
+ " (_format = %d, asked driver to give %d, got %d)",
+ _format, _format, auinfo.record.precision);
+
+ _error = "Can't set playback and/or record format ";
+ _error += "Play format: ";
+ _error += play_details;
+ if (param(direction) == 3) {
+ _error += " Record format: ";
+ _error += record_details;
+ }
+ close();
+ return false;
+ }
+ if ((auinfo.play.encoding != (uint_t)AUDIO_ENCODING_LINEAR) ||
+ (param(direction) == 3 &&
+ auinfo.record.encoding != (uint_t)AUDIO_ENCODING_LINEAR))
+ {
+ char play_encoding[80], record_encoding[80];
+ sprintf(play_encoding, "(%d bits, %d encoding)",
+ auinfo.play.precision, auinfo.play.encoding);
+ sprintf(record_encoding, "(%d bits, %d encoding)",
+ auinfo.record.precision, auinfo.record.encoding);
+
+ _error = "Can't set playback and/or record format";
+ _error += "requested format was ";
+ _error += (_format == 8) ? "8-bit AUDIO_ENCODING_LINEAR" :
+ "16-bit AUDIO_ENCODING_LINEAR";
+ _error += ", got playback format ";
+ _error += play_encoding;
+ if (param(direction) == 3) {
+ _error += ", record format ";
+ _error += record_encoding;
+ }
+
+ close();
+ return false;
+ }
+
+ if (auinfo.play.channels != (uint_t)_channels) {
+ _error = "Audio device doesn't support number of ";
+ _error += "requested playback channels";
+ close();
+ return false;
+ }
+ if (param(direction) == 3 && auinfo.record.channels != (uint_t)_channels) {
+ _error = "Audio device doesn't support number of ";
+ _error += "requested record channels";
+ close();
+ return false;
+ }
+
+ int tolerance = _samplingRate/10+1000;
+
+ if (abs(int(auinfo.play.sample_rate - _samplingRate)) > tolerance)
+ {
+ _error = "can't set requested playback sampling rate";
+
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, auinfo.play.sample_rate);
+ _error += details;
+
+ close();
+ return false;
+ }
+
+ if (param(direction) == 3 &&
+ abs(int(auinfo.record.sample_rate - _samplingRate)) > tolerance)
+ {
+ _error = "can't set requested record sampling rate";
+
+ char details[80];
+ sprintf(details," (requested rate %d, got rate %d)",
+ _samplingRate, auinfo.play.sample_rate);
+ _error += details;
+
+ close();
+ return false;
+ }
+
+
+ /*
+ * don't allow unreasonable large fragmentSize/Count combinations,
+ * because "real" hardware also doesn't
+ */
+
+ if(_fragmentSize > SUN_MAX_BUFFER_SIZE)
+ _fragmentSize = SUN_MAX_BUFFER_SIZE;
+
+ while(_fragmentSize * _fragmentCount > SUN_MAX_BUFFER_SIZE)
+ _fragmentCount--;
+
+ bytesRead = bytesWritten = 0;
+ bytesPerSec = _channels * 2 * _samplingRate;
+
+ // Install the timer
+ Dispatcher::the()->ioManager()->addTimer(10, this);
+
+ gettimeofday(&start,0);
+
+ return true;
+}
+
+void AudioIOSun::close()
+{
+ ::close(audio_fd);
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
+
+// This is called on each timer tick
+void AudioIOSun::notifyTime()
+{
+ int& _direction = param(direction);
+ int& _fragmentSize = param(fragmentSize);
+
+ for (;;) {
+ int todo = 0;
+ if ((_direction & directionRead) && getParam(canRead) > _fragmentSize)
+ todo |= AudioSubSystem::ioRead;
+
+ if ((_direction & directionWrite) && getParam(canWrite) > _fragmentSize)
+ todo |= AudioSubSystem::ioWrite;
+
+ if (!todo)
+ return;
+
+ AudioSubSystem::the()->handleIO(todo);
+ }
+}
+
+void AudioIOSun::setParam(AudioParam p, int& value)
+{
+ switch(p) {
+ case fragmentSize:
+ param(p) = requestedFragmentSize = value;
+ break;
+ case fragmentCount:
+ param(p) = requestedFragmentCount = value;
+ break;
+ default:
+ param(p) = value;
+ break;
+ }
+}
+
+int AudioIOSun::getParam(AudioParam p)
+{
+ int bytes;
+ int count;
+
+ switch(p)
+ {
+ case canRead:
+ if (ioctl(audio_fd, AUDIO_GETINFO, &auinfo) < 0)
+ return (0);
+ bytes = (auinfo.record.samples * bytesPerSample) - bytesRead;
+ if (bytes < 0) {
+ printf("Error: bytes %d < 0, samples=%u, bytesRead=%u\n",
+ bytes, auinfo.record.samples, bytesRead);
+ bytes = 0;
+ }
+ return bytes;
+
+ case canWrite:
+ if (ioctl(audio_fd, AUDIO_GETINFO, &auinfo) < 0)
+ return (0);
+ count = SUN_MAX_BUFFER_SIZE -
+ (bytesWritten - (auinfo.play.samples * bytesPerSample));
+ return count;
+
+ case autoDetect:
+ /*
+ * If we're on Solaris, this driver is the one that will work,
+ * and if we're not on Solaris, it won't be compiled anyway.
+ */
+ return 12;
+
+ default:
+ return param(p);
+ }
+}
+
+int AudioIOSun::read(void *buffer, int size)
+{
+ size = ::read(audio_fd, buffer, size);
+ if (size < 0)
+ return 0;
+
+ bytesRead += size;
+ return size;
+}
+
+int AudioIOSun::write(void *buffer, int size)
+{
+ size = ::write(audio_fd, buffer, size);
+ bytesWritten += size;
+ return size;
+}
+
+#endif /* USE_SOLARIS */
diff --git a/flow/audiomanager_impl.cc b/flow/audiomanager_impl.cc
new file mode 100644
index 0000000..c2d2567
--- /dev/null
+++ b/flow/audiomanager_impl.cc
@@ -0,0 +1,325 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "flowsystem.h"
+#include "stdsynthmodule.h"
+#include "bus.h"
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+
+class AudioManagerClient_impl;
+
+class AudioManagerAssignable {
+public:
+ virtual long ID() = 0;
+ virtual void destination(const string& newDestination) = 0;
+};
+
+#ifdef __SUNPRO_CC
+/* Bloody SunPRO CC has problems with instantiation of the below two
+ templates, if the _clients and assignable member of AudioManager_impl
+ are declared to be directly the type list<xxx *>. So instead be move
+ a typedef in between, which makes it magically work.
+ We could also use an explicit instantiation, but this is not allowed
+ on all C++ compilers in this scope. Note also, that we don't need
+ to replace _all_ occurrences of list<xxx*> below, only the two in the
+ member declaration. What a mess. */
+typedef list<AudioManagerClient_impl *> L_AMC;
+typedef list<AudioManagerAssignable *> L_AMA;
+#else
+/* with normal compilers there is no need for this typedef. */
+#define L_AMC list<AudioManagerClient_impl *>
+#define L_AMA list<AudioManagerAssignable *>
+#endif
+
+class AudioManager_impl : virtual public AudioManager_skel
+{
+protected:
+ L_AMC _clients;
+ L_AMA assignable;
+ long _changes, nextID;
+ static AudioManager_impl *instance;
+public:
+ AudioManager_impl()
+ {
+ assert(!instance);
+ instance = this;
+ _changes = 0;
+ nextID = 1;
+ }
+ ~AudioManager_impl()
+ {
+ assert(instance);
+ instance = 0;
+ }
+ vector<string> *destinations() { return BusManager::the()->busList(); }
+ long changes() { return _changes; }
+
+ vector<AudioManagerInfo> *clients();
+ void setDestination(long ID, const string& newDestination);
+ AudioManagerClient_impl *findClient(long ID);
+
+ // non MCOP interface
+ static AudioManager_impl *the() {
+ assert(instance);
+ return instance;
+ }
+ long addClient(AudioManagerClient_impl *client) {
+ _clients.push_back(client);
+ _changes++;
+ return nextID++;
+ }
+ void removeClient(AudioManagerClient_impl *client) {
+ _changes++;
+ _clients.remove(client);
+ }
+ void addAssignable(AudioManagerAssignable *a);
+ void removeAssignable(AudioManagerAssignable *a) {
+ assignable.remove(a);
+ }
+};
+
+AudioManager_impl *AudioManager_impl::instance = 0;
+
+class AudioManagerClient_impl :virtual public AudioManagerClient_skel
+{
+protected:
+ string _title, _autoRestoreID;
+ long _ID;
+ AudioManagerDirection _direction;
+ string _destination;
+
+public:
+ AudioManagerClient_impl() {
+ _ID = AudioManager_impl::the()->addClient(this);
+ }
+ ~AudioManagerClient_impl() {
+ AudioManager_impl::the()->removeClient(this);
+ }
+
+ void title(const string& newvalue) { _title = newvalue; }
+ string title() { return _title; }
+
+ void autoRestoreID(const string& newvalue) { _autoRestoreID = newvalue; }
+ string autoRestoreID() { return _autoRestoreID; }
+
+ long ID() { return _ID; }
+
+ AudioManagerDirection direction() { return _direction; }
+ void direction(AudioManagerDirection newvalue) { _direction = newvalue; }
+
+ void constructor(AudioManagerDirection cdirection, const string& ctitle,
+ const string& cautoRestoreID)
+ {
+ direction(cdirection);
+ title(ctitle);
+ autoRestoreID(cautoRestoreID);
+ }
+
+ /* non MCOP interface */
+ string destination() { return _destination; }
+ void destination(const string& newvalue) { _destination = newvalue; }
+};
+
+// this suffers a tiny bit from copypasting due to simpler
+// inheritance hierarchy
+class Synth_AMAN_PLAY_impl :virtual public Synth_AMAN_PLAY_skel,
+ virtual public AudioManagerAssignable,
+ virtual public StdSynthModule
+{
+protected:
+ Synth_BUS_UPLINK uplink;
+ AudioManagerClient client;
+public:
+ /* forward requests for title/autoRestoreID to client */
+ void title(const string& newvalue) { client.title(newvalue); }
+ string title() { return client.title(); }
+
+ void autoRestoreID(const string& newvalue) {client.autoRestoreID(newvalue);}
+ string autoRestoreID() { return client.autoRestoreID(); }
+
+ /* assign an already well-known client */
+ void constructor(AudioManagerClient client) {
+ this->client = client;
+ assert(client.direction() == amPlay);
+ }
+
+ Synth_AMAN_PLAY_impl() {
+ // Set direction of the client to amPlay, but actually it would
+ // be nice to do that only when we know we won't get a different client
+ // to use.
+ client.direction(amPlay);
+ _node()->virtualize("left",uplink._node(),"left");
+ _node()->virtualize("right",uplink._node(),"right");
+ }
+ void streamInit() {
+ AudioManager_impl::the()->addAssignable(this);
+ uplink.start();
+ }
+ void streamEnd() {
+ AudioManager_impl::the()->removeAssignable(this);
+ uplink.stop();
+ }
+ AutoSuspendState autoSuspend() {
+ return asSuspend;
+ }
+
+ // Assignable:
+ void destination(const string& destination) { uplink.busname(destination); }
+ long ID() { return client.ID(); }
+};
+
+// this suffers a tiny bit from copypasting due to simpler
+// inheritance hierarchy
+class Synth_AMAN_RECORD_impl :virtual public Synth_AMAN_RECORD_skel,
+ virtual public AudioManagerAssignable,
+ virtual public StdSynthModule
+{
+protected:
+ Synth_BUS_DOWNLINK downlink;
+ AudioManagerClient client;
+public:
+ /* forward requests for title/autoRestoreID to client */
+ void title(const string& newvalue) { client.title(newvalue); }
+ string title() { return client.title(); }
+
+ void autoRestoreID(const string& newvalue) {client.autoRestoreID(newvalue);}
+ string autoRestoreID() { return client.autoRestoreID(); }
+
+ /* assign an already well-known client */
+ void constructor(AudioManagerClient client) {
+ this->client = client;
+ assert(client.direction() == amRecord);
+ }
+
+ Synth_AMAN_RECORD_impl() {
+ // Set direction of the client to amRecord, but actually it would
+ // be nice to do that only when we know we won't get a different client
+ // to use.
+ client.direction(amRecord);
+ _node()->virtualize("left",downlink._node(),"left");
+ _node()->virtualize("right",downlink._node(),"right");
+ }
+
+ void streamInit() {
+ AudioManager_impl::the()->addAssignable(this);
+ downlink.start();
+ }
+ void streamEnd() {
+ AudioManager_impl::the()->removeAssignable(this);
+ downlink.stop();
+ }
+
+ // Assignable:
+ void destination(const string& destination){downlink.busname(destination);}
+ long ID() { return client.ID(); }
+};
+
+vector<AudioManagerInfo> *AudioManager_impl::clients()
+{
+ vector<AudioManagerInfo> *result = new vector<AudioManagerInfo>;
+ list<AudioManagerClient_impl *>::iterator i;
+
+ for(i = _clients.begin(); i != _clients.end(); i++)
+ {
+ AudioManagerClient_impl *client = *i;
+
+ AudioManagerInfo info;
+ info.ID = client->ID();
+ info.direction = client->direction();
+ info.title = client->title();
+ info.autoRestoreID = client->autoRestoreID();
+ info.destination = client->destination();
+
+ result->push_back(info);
+ }
+ return result;
+}
+
+
+AudioManagerClient_impl *AudioManager_impl::findClient(long ID)
+{
+ list<AudioManagerClient_impl *>::iterator i;
+
+ for(i = _clients.begin(); i != _clients.end(); i++)
+ {
+ AudioManagerClient_impl *client = *i;
+
+ if(client->ID() == ID)
+ return client;
+ }
+ return 0;
+}
+
+void AudioManager_impl::setDestination(long ID, const string& newDestination)
+{
+ AudioManagerClient_impl *client = findClient(ID);
+ if(client)
+ {
+ client->destination(newDestination);
+
+ list<AudioManagerAssignable *>::iterator i;
+ for(i = assignable.begin(); i != assignable.end(); i++)
+ {
+ AudioManagerAssignable *a = *i;
+ if(a->ID() == ID) a->destination(newDestination);
+ }
+ _changes++;
+ }
+}
+
+void AudioManager_impl::addAssignable(AudioManagerAssignable *a)
+{
+ // ensure that this client is assigned properly
+ AudioManagerClient_impl *client = findClient(a->ID());
+ assert(client);
+
+ if(client->destination().empty())
+ {
+ // TODO: more flexible default assignment policies - load autoRestoreID
+ // related stuff here (or somewhere else)
+
+ switch(client->direction())
+ {
+ case amPlay: client->destination("out_soundcard");
+ break;
+ case amRecord: client->destination("in_soundcard");
+ break;
+ }
+ }
+
+ assignable.push_back(a);
+ a->destination(client->destination());
+}
+
+REGISTER_IMPLEMENTATION(AudioManagerClient_impl);
+REGISTER_IMPLEMENTATION(AudioManager_impl);
+REGISTER_IMPLEMENTATION(Synth_AMAN_PLAY_impl);
+REGISTER_IMPLEMENTATION(Synth_AMAN_RECORD_impl);
+
+}
+
+// vim: sw=4 ts=4 noet
diff --git a/flow/audiosubsys.cc b/flow/audiosubsys.cc
new file mode 100644
index 0000000..a1238fc
--- /dev/null
+++ b/flow/audiosubsys.cc
@@ -0,0 +1,645 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h> // Needed on some systems.
+#endif
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <iostream>
+#include <algorithm>
+#include <cstring>
+
+#include "debug.h"
+#include "audiosubsys.h"
+#include "audioio.h"
+
+#define DEFAULT_DEVICE_NAME "/dev/dsp"
+
+#undef DEBUG_WAVEFORM
+#ifdef DEBUG_WAVEFORM
+#include <fstream>
+#endif
+
+using namespace std;
+using namespace Arts;
+
+//--- automatic startup class
+
+static AudioSubSystemStart aStart;
+
+void AudioSubSystemStart::startup()
+{
+ _instance = new AudioSubSystem();
+}
+
+void AudioSubSystemStart::shutdown()
+{
+ delete _instance;
+}
+
+//--- AudioSubSystemPrivate data
+
+class Arts::AudioSubSystemPrivate
+{
+public:
+#ifdef DEBUG_WAVEFORM
+ ofstream plotfile;
+#endif
+ AudioIO *audioIO;
+ string audioIOName;
+ bool audioIOInit;
+
+ unsigned int adjustDuplexOffsetIndex;
+ int adjustDuplexOffset[4];
+ int adjustDuplexCount;
+};
+
+//--- AudioSubSystem implementation
+
+AudioSubSystem *AudioSubSystem::the()
+{
+ return aStart.the();
+}
+
+const char *AudioSubSystem::error()
+{
+ return _error.c_str();
+}
+
+AudioSubSystem::AudioSubSystem()
+{
+ d = new AudioSubSystemPrivate;
+#ifdef DEBUG_WAVEFORM
+ d->plotfile.open( "/dev/shm/audiosubsystem.plot" );
+#endif
+ d->audioIO = 0;
+ d->audioIOInit = false;
+
+ _running = false;
+ consumer = 0;
+ producer = 0;
+ fragment_buffer = 0;
+}
+
+AudioSubSystem::~AudioSubSystem()
+{
+ delete d->audioIO;
+ delete d;
+}
+
+bool AudioSubSystem::attachProducer(ASProducer *producer)
+{
+ assert(producer);
+ if(this->producer) return false;
+
+ this->producer = producer;
+ return true;
+}
+
+bool AudioSubSystem::attachConsumer(ASConsumer *consumer)
+{
+ assert(consumer);
+ if(this->consumer) return false;
+
+ this->consumer = consumer;
+ return true;
+}
+
+void AudioSubSystem::detachProducer()
+{
+ assert(producer);
+ producer = 0;
+
+ if(_running) close();
+}
+
+void AudioSubSystem::detachConsumer()
+{
+ assert(consumer);
+ consumer = 0;
+
+ if(_running) close();
+}
+
+/* initially creates default AudioIO */
+void AudioSubSystem::initAudioIO()
+{
+ /* auto detect */
+ if(!d->audioIOInit)
+ {
+ string bestName;
+ int bestValue = 0;
+
+ arts_debug("autodetecting driver: ");
+ for(int i = 0; i < AudioIO::queryAudioIOCount(); i++)
+ {
+ string name = AudioIO::queryAudioIOParamStr(i, AudioIO::name);
+ AudioIO *aio = AudioIO::createAudioIO(name.c_str());
+ int value = aio->getParam(AudioIO::autoDetect);
+
+ arts_debug(" - %s: %d", name.c_str(), value);
+ if(value > bestValue)
+ {
+ bestName = name;
+ bestValue = value;
+ }
+ delete aio;
+ }
+ if(bestValue)
+ {
+ arts_debug("... which means we'll default to %s", bestName.c_str());
+ audioIO(bestName);
+ }
+ else
+ {
+ arts_debug("... nothing we could use as default found");
+ }
+ }
+}
+
+void AudioSubSystem::audioIO(const string& audioIO)
+{
+ if(d->audioIO)
+ delete d->audioIO;
+
+ d->audioIOName = audioIO;
+ d->audioIO = AudioIO::createAudioIO(audioIO.c_str());
+ d->audioIOInit = true;
+}
+
+string AudioSubSystem::audioIO()
+{
+ initAudioIO();
+
+ return d->audioIOName;
+}
+
+void AudioSubSystem::deviceName(const string& deviceName)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ d->audioIO->setParamStr(AudioIO::deviceName, deviceName.c_str());
+}
+
+string AudioSubSystem::deviceName()
+{
+ initAudioIO();
+ if(!d->audioIO) return "";
+
+ return d->audioIO->getParamStr(AudioIO::deviceName);
+}
+
+void AudioSubSystem::fragmentCount(int fragmentCount)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ d->audioIO->setParam(AudioIO::fragmentCount, fragmentCount);
+}
+
+int AudioSubSystem::fragmentCount()
+{
+ initAudioIO();
+ if(!d->audioIO) return 0;
+
+ return d->audioIO->getParam(AudioIO::fragmentCount);
+}
+
+void AudioSubSystem::fragmentSize(int fragmentSize)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ d->audioIO->setParam(AudioIO::fragmentSize, fragmentSize);
+}
+
+int AudioSubSystem::fragmentSize()
+{
+ initAudioIO();
+ if(!d->audioIO) return 0;
+
+ return d->audioIO->getParam(AudioIO::fragmentSize);
+}
+
+void AudioSubSystem::samplingRate(int samplingRate)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ d->audioIO->setParam(AudioIO::samplingRate, samplingRate);
+}
+
+int AudioSubSystem::samplingRate()
+{
+ initAudioIO();
+ if(!d->audioIO) return 0;
+
+ return d->audioIO->getParam(AudioIO::samplingRate);
+}
+
+void AudioSubSystem::channels(int channels)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ d->audioIO->setParam(AudioIO::channels, channels);
+}
+
+int AudioSubSystem::channels()
+{
+ initAudioIO();
+ if(!d->audioIO) return 0;
+
+ return d->audioIO->getParam(AudioIO::channels);
+}
+
+void AudioSubSystem::format(int format)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ d->audioIO->setParam(AudioIO::format, format);
+}
+
+int AudioSubSystem::format()
+{
+ initAudioIO();
+ if(!d->audioIO) return 0;
+
+ return d->audioIO->getParam(AudioIO::format);
+}
+
+int AudioSubSystem::bits()
+{
+ int _format = format();
+ arts_assert(_format == 0 || _format == 8 || _format == 16 || _format == 17 || _format == 32);
+ return (_format & (32 | 16 | 8));
+}
+
+void AudioSubSystem::fullDuplex(bool fullDuplex)
+{
+ initAudioIO();
+ if(!d->audioIO) return;
+
+ int direction = fullDuplex?3:2;
+ d->audioIO->setParam(AudioIO::direction, direction);
+}
+
+bool AudioSubSystem::fullDuplex()
+{
+ initAudioIO();
+ if(!d->audioIO) return false;
+
+ return d->audioIO->getParam(AudioIO::direction) == 3;
+}
+
+int AudioSubSystem::selectReadFD()
+{
+ initAudioIO();
+ if(!d->audioIO) return false;
+
+ return d->audioIO->getParam(AudioIO::selectReadFD);
+}
+
+int AudioSubSystem::selectWriteFD()
+{
+ initAudioIO();
+ if(!d->audioIO) return false;
+
+ return d->audioIO->getParam(AudioIO::selectWriteFD);
+}
+
+bool AudioSubSystem::check()
+{
+ bool ok = open();
+
+ if(ok) close();
+ return ok;
+}
+
+bool AudioSubSystem::open()
+{
+ assert(!_running);
+
+ initAudioIO();
+ if(!d->audioIO)
+ {
+ if(d->audioIOName.empty())
+ _error = "couldn't auto detect which audio I/O method to use";
+ else
+ _error = "unable to select '"+d->audioIOName+"' style audio I/O";
+ return false;
+ }
+
+ if(d->audioIO->open())
+ {
+ _running = true;
+
+ _fragmentSize = d->audioIO->getParam(AudioIO::fragmentSize);
+ _fragmentCount = d->audioIO->getParam(AudioIO::fragmentCount);
+
+ // allocate global buffer to do I/O
+ assert(fragment_buffer == 0);
+ fragment_buffer = new char[_fragmentSize];
+
+ d->adjustDuplexCount = 0;
+ return true;
+ }
+ else
+ {
+ _error = d->audioIO->getParamStr(AudioIO::lastError);
+ return false;
+ }
+}
+
+void AudioSubSystem::close()
+{
+ assert(_running);
+ assert(d->audioIO);
+
+ d->audioIO->close();
+
+ wBuffer.clear();
+ rBuffer.clear();
+
+ _running = false;
+ if(fragment_buffer)
+ {
+ delete[] fragment_buffer;
+ fragment_buffer = 0;
+ }
+}
+
+bool AudioSubSystem::running()
+{
+ return _running;
+}
+
+void AudioSubSystem::handleIO(int type)
+{
+ assert(d->audioIO);
+
+ if(type & ioRead)
+ {
+ int len = d->audioIO->read(fragment_buffer,_fragmentSize);
+
+ if(len > 0)
+ {
+ if(rBuffer.size() < _fragmentSize * _fragmentCount * bits() / 8 * channels())
+ {
+ rBuffer.write(len,fragment_buffer);
+#ifdef DEBUG_WAVEFORM
+ float * end = (float *)(fragment_buffer + len);
+ float * floatbuffer = (float *)fragment_buffer;
+ while(floatbuffer < end)
+ {
+ d->plotfile << *floatbuffer++ << "\n";
+ ++floatbuffer;
+ }
+#endif
+ }
+ else
+ {
+ arts_debug( "AudioSubSystem: rBuffer is too full" );
+ }
+ }
+ }
+
+ if(type & ioWrite)
+ {
+ /*
+ * make sure that we have a fragment full of data at least
+ */
+Rewrite:
+ while(wBuffer.size() < _fragmentSize)
+ {
+ long wbsz = wBuffer.size();
+ producer->needMore();
+
+ if(wbsz == wBuffer.size())
+ {
+ /*
+ * Even though we asked the client to supply more
+ * data, he didn't give us more. So we can't supply
+ * output data as well. Bad luck. Might produce a
+ * buffer underrun - but we can't help here.
+ */
+ arts_info("full duplex: no more data available (underrun)");
+ return;
+ }
+ }
+
+ /*
+ * look how much we really can write without blocking
+ */
+ int space = d->audioIO->getParam(AudioIO::canWrite);
+ int can_write = min(space, _fragmentSize);
+
+ if(can_write > 0)
+ {
+ /*
+ * ok, so write it (as we checked that our buffer has enough data
+ * to do so and the soundcardbuffer has enough data to handle this
+ * write, nothing can go wrong here)
+ */
+ int rSize = wBuffer.read(can_write,fragment_buffer);
+ assert(rSize == can_write);
+
+ int len = d->audioIO->write(fragment_buffer,can_write);
+ if(len != can_write)
+ arts_fatal("AudioSubSystem::handleIO: write failed\n"
+ "len = %d, can_write = %d, errno = %d (%s)\n\n"
+ "This might be a sound hardware/driver specific problem"
+ " (see aRts FAQ)",len,can_write,errno,strerror(errno));
+
+ if(fullDuplex())
+ {
+ /*
+ * if we're running full duplex, here is a good place to check
+ * for full duplex drift
+ */
+ d->adjustDuplexCount += can_write;
+ if(d->adjustDuplexCount > samplingRate())
+ {
+ adjustDuplexBuffers();
+ d->adjustDuplexCount = 0;
+ }
+ }
+ }
+
+ // If we can write a fragment more, then do so right now:
+ if (space >= _fragmentSize*2) goto Rewrite;
+ }
+
+ assert((type & ioExcept) == 0);
+}
+
+void AudioSubSystem::read(void *buffer, int size)
+{
+ /* if not enough data can be read, produce some */
+ while(rBuffer.size() < size)
+ adjustInputBuffer(1);
+
+ /* finally, just take the data out of the input buffer */
+ int rSize = rBuffer.read(size,buffer);
+ assert(rSize == size);
+}
+
+void AudioSubSystem::write(void *buffer, int size)
+{
+ wBuffer.write(size,buffer);
+}
+
+float AudioSubSystem::outputDelay()
+{
+ int fsize = _fragmentSize;
+ int fcount = _fragmentCount;
+
+ if(fsize > 0 && fcount > 0) // not all AudioIO classes need to support this
+ {
+ double hardwareBuffer = fsize * fcount;
+ double freeOutputSpace = d->audioIO->getParam(AudioIO::canWrite);
+ double playSpeed = channels() * samplingRate() * (bits() / 8);
+
+ return (hardwareBuffer - freeOutputSpace) / playSpeed;
+ }
+ else return 0.0;
+}
+
+void AudioSubSystem::adjustDuplexBuffers()
+{
+ int fsize = _fragmentSize;
+ int fcount = _fragmentCount;
+
+ if(fsize > 0 && fcount > 0) // not all AudioIO classes need to support this
+ {
+ int bound = 2; //max(fcount/2, 1);
+ int optimalOffset = fsize * (fcount + bound);
+ int minOffset = fsize * fcount;
+ int maxOffset = fsize * (fcount + 2 * bound);
+
+ int canRead = d->audioIO->getParam(AudioIO::canRead);
+ if(canRead < 0)
+ {
+ arts_warning("AudioSubSystem::adjustDuplexBuffers: canRead < 0?");
+ canRead = 0;
+ }
+
+ int canWrite = d->audioIO->getParam(AudioIO::canWrite);
+ if(canWrite < 0)
+ {
+ arts_warning("AudioSubSystem::adjustDuplexBuffers: canWrite < 0?");
+ canWrite = 0;
+ }
+
+ int currentOffset = rBuffer.size() + wBuffer.size()
+ + canRead + max((fsize * fcount) - canWrite, 0);
+
+ d->adjustDuplexOffset[d->adjustDuplexOffsetIndex++ & 3] = currentOffset;
+ if(d->adjustDuplexOffsetIndex <= 4) return;
+
+ int avgOffset;
+ avgOffset = d->adjustDuplexOffset[0]
+ + d->adjustDuplexOffset[1]
+ + d->adjustDuplexOffset[2]
+ + d->adjustDuplexOffset[3];
+ avgOffset /= 4;
+
+ /*
+ printf("offset: %d avg %d min %d opt %d max %d\r", currentOffset,
+ avgOffset, minOffset, optimalOffset, maxOffset);
+ fflush(stdout);
+ */
+ if(minOffset <= avgOffset && avgOffset <= maxOffset)
+ return;
+
+ d->adjustDuplexOffsetIndex = 0;
+ int adjust = (optimalOffset - currentOffset) / _fragmentSize;
+ arts_debug("AudioSubSystem::adjustDuplexBuffers(%d)", adjust);
+ }
+}
+
+void AudioSubSystem::adjustInputBuffer(int count)
+{
+ if(format() == 8)
+ {
+ memset( fragment_buffer, 0x80, _fragmentSize );
+ }
+ else
+ {
+ memset( fragment_buffer, 0, _fragmentSize );
+ }
+
+ while(count > 0 && rBuffer.size() < _fragmentSize * _fragmentCount * 4)
+ {
+ rBuffer.write(_fragmentSize, fragment_buffer);
+#ifdef DEBUG_WAVEFORM
+ float * end = (float *)(fragment_buffer + _fragmentSize);
+ float * floatbuffer = (float *)fragment_buffer;
+ while(floatbuffer < end)
+ {
+ d->plotfile << *floatbuffer++ << "\n";
+ ++floatbuffer;
+ }
+#endif
+ count--;
+ }
+
+ while(count < 0 && rBuffer.size() >= _fragmentSize)
+ {
+ rBuffer.read(_fragmentSize, fragment_buffer);
+ count++;
+ }
+}
+
+void AudioSubSystem::emergencyCleanup()
+{
+ if(producer || consumer)
+ {
+ fprintf(stderr, "AudioSubSystem::emergencyCleanup\n");
+
+ if(producer)
+ detachProducer();
+ if(consumer)
+ detachConsumer();
+ }
+}
diff --git a/flow/audiosubsys.h b/flow/audiosubsys.h
new file mode 100644
index 0000000..ede38c2
--- /dev/null
+++ b/flow/audiosubsys.h
@@ -0,0 +1,236 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef AUDIOSUBSYS_H
+#define AUDIOSUBSYS_H
+#include <string>
+
+#include "arts_export.h"
+#include "pipebuffer.h"
+#include "startupmanager.h"
+
+/*
+ * BC - Status (2002-03-08): AudioSubSystem, ASProducer, ASConsumer.
+ *
+ * These classes are kept binary compatible. You can rely on them.
+ * AudioSubSystem has a private data pointer to do so. Even if ports to
+ * other architectures or hardware will require different organization
+ * (i.e. no fragments, direct memory access via mmap), the data members
+ * and functions exported here MAY NOT BE CHANGED. Use the private data
+ * pointer for adding data members.
+ *
+ * If ASProducer/ASConsumer doesn't suit the needs any longer, do NOT
+ * change them. Add new classes instead.
+ */
+
+namespace Arts {
+
+class ASProducer {
+public:
+ virtual void needMore() = 0;
+};
+
+// FIXME: haveMore won't be called currently
+class ASConsumer {
+public:
+ virtual void haveMore() = 0;
+};
+
+class ARTS_EXPORT AudioSubSystemStart :public StartupClass {
+protected:
+ class AudioSubSystem *_instance;
+public:
+ inline AudioSubSystem *the() { return _instance; };
+ void startup();
+ void shutdown();
+};
+
+class AudioSubSystemPrivate;
+
+class ARTS_EXPORT AudioSubSystem {
+ class AudioSubSystemPrivate *d;
+
+ std::string _error;
+ char *fragment_buffer;
+
+ int _fragmentCount;
+ int _fragmentSize;
+
+ bool _running;
+ PipeBuffer wBuffer, rBuffer;
+ ASConsumer *consumer;
+ ASProducer *producer;
+
+ friend class AudioSubSystemStart;
+ AudioSubSystem();
+ ~AudioSubSystem();
+
+ void close();
+ void initAudioIO();
+
+ /**
+ * checks that full duplex doesn't go out of sync
+ */
+ void adjustDuplexBuffers();
+
+ /**
+ * creates count empty fragments of input in rBuffer if count > 0
+ * removes count fragments of input from rBuffer if count < 0
+ */
+ void adjustInputBuffer(int count);
+
+public:
+ enum { ioRead=1, ioWrite=2, ioExcept=4 };
+
+ // singleton
+ static AudioSubSystem *the();
+
+ /*
+ * Currently, if you want to use the AudioSubSystem, you need to
+ *
+ * 1. - attach one producer
+ * - attach one consumer (only for full duplex)
+ * - open the audio subsystem using open (watch the fd)
+ * (in any order)
+ *
+ * 2. react on the callbacks you get for the producer
+ *
+ * 3. if you don't need the audio subsystem any longer, call detach
+ * both, the producer and the cosumer.
+ *
+ * Be careful that you don't read/write from/to the audio subsystem
+ * when running() is not true.
+ */
+
+ bool attachProducer(ASProducer *producer);
+ bool attachConsumer(ASConsumer *consumer);
+
+ void detachProducer();
+ void detachConsumer();
+
+ /*
+ * can be used to select the AudioIO class to use, reasonable choices
+ * may be "oss" or "alsa" at this point in time - you need to choose
+ * this before doing anything else
+ */
+ void audioIO(const std::string& audioIO);
+ std::string audioIO();
+
+ // which device to use for audio output (default /dev/dsp)
+ void deviceName(const std::string& deviceName);
+ std::string deviceName();
+
+ void fragmentSize(int size);
+ int fragmentSize();
+
+ void fragmentCount(int fragments);
+ int fragmentCount();
+
+ void samplingRate(int samplingrate);
+ int samplingRate();
+
+ void channels(int channels);
+ int channels();
+
+ void format(int format);
+ int format();
+
+ /**
+ * As opposed to format(), this one returns the number of bits used per
+ * sample. Thats sometimes a difference, for instance 16bit big endian
+ * encoding has the format() 17, whereas bits() would return 16.
+ */
+ int bits();
+
+ void fullDuplex(bool newFullDuplex);
+ bool fullDuplex();
+
+ bool check();
+
+ /**
+ * Opens the audio device.
+ *
+ * After opening, you must check selectReadFD() and selectWriteFD() to
+ * select() on the appropriate file descriptors. Whenever select()ing is
+ * successful, handleIO needs to be called.
+ *
+ * The type for handleIO must be set to ioRead if fd is ready for
+ * reading, ioWrite if fd is ready for writing, ioExcept if something
+ * special happend or any combination of these using bitwise or.
+ *
+ * @returns true if audio device has been opened successfully,
+ * false otherwise
+ */
+ bool open();
+
+ /**
+ * human readable error message that descibes why opening the audio device
+ * failed
+ */
+ const char *error();
+
+ /**
+ * File descriptor to select on for reading (@see open()), -1 if there is
+ * none.
+ */
+ int selectReadFD();
+
+ /**
+ * File descriptor to select on for writing (@see open()), -1 if there is
+ * none.
+ */
+ int selectWriteFD();
+
+ /**
+ * Needs to be called to handle I/O on the filedescriptors given by
+ * selectReadFD() and selectWriteFD() (@see open()).
+ */
+ void handleIO(int type);
+
+ void read(void *buffer, int size);
+ void write(void *buffer, int size);
+
+ /**
+ * this returns the time in seconds it will take until everything written
+ * to the AudioSubSystem so far will be played - in other words, it returns
+ * the time it will take until the next sample written by the application
+ * will be heard by the user
+ */
+ float outputDelay();
+
+ /**
+ * returns true as long as the audio subsystem is opened and active (that
+ * is, between successful opening, with attaching producer, and the first
+ * detachConsumer/detachProducer)
+ */
+ bool running();
+
+ /**
+ * called during crashes, to release the opened device (and other resources)
+ * don't use this method for other purposes than emergencies
+ */
+ void emergencyCleanup();
+};
+
+}
+
+#endif /* AUDIOSUBSYS_H */
diff --git a/flow/audiotobytestream_impl.cc b/flow/audiotobytestream_impl.cc
new file mode 100644
index 0000000..866b85a
--- /dev/null
+++ b/flow/audiotobytestream_impl.cc
@@ -0,0 +1,223 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+ 2001, 2003 Matthias Kretz
+ kretz@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+
+#include <vector>
+#include <iostream>
+#include <math.h>
+
+#undef DEBUG_MESSAGES
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class AudioToByteStream_impl : public AudioToByteStream_skel,
+ public StdSynthModule
+{
+ long _samplingRate, _channels, _bits;
+ long sampleSize;
+ double step;
+ bool interpolate;
+ vector<float> leftbuffer;
+ vector<float> rightbuffer;
+ int range;
+ double _pos;
+protected:
+ void updateSampleSize()
+ {
+ sampleSize = _channels * _bits / 8;
+ }
+
+public:
+ AudioToByteStream_impl() :
+ _pos(0)
+ {
+ samplingRate(44100);
+ channels(2);
+ bits(16);
+ }
+
+ long samplingRate() { return _samplingRate; }
+ void samplingRate(long newRate) {
+ double newStep = samplingRateFloat / (float)newRate;
+ arts_return_if_fail(newStep > 0);
+ _samplingRate = newRate;
+ step = newStep;
+
+ double delta = step - floor(step);
+ interpolate = fabs(delta) > 0.001;
+#ifdef DEBUG_MESSAGES
+ arts_debug( "samplingRate(%i): step = %e, delta = %e, interpolate: %i", newRate, step, delta, interpolate );
+#endif
+ }
+
+ long channels() { return _channels; }
+ void channels(long newChannels) {
+ arts_return_if_fail(newChannels == 1 || newChannels == 2);
+ _channels = newChannels;
+ updateSampleSize();
+ }
+
+ long bits() { return _bits; }
+ void bits(long newBits) {
+ arts_return_if_fail(newBits == 8 || newBits == 16);
+ _bits = newBits;
+ range = (newBits == 8 ) ? 128 : 32768;
+ updateSampleSize();
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ leftbuffer.resize( 1 + samples );
+ rightbuffer.resize( 1 + samples );
+ for( unsigned long i = 0; i < samples; ++i ) {
+ leftbuffer[1 + i] = (left[i] > 1.0f) ? 1.0f : (left[i] < -1.0f) ? -1.0f : left[i];
+ rightbuffer[1 + i] = (right[i] > 1.0f) ? 1.0f : (right[i] < -1.0f) ? -1.0f : right[i];
+ }
+
+ int samplestosend = (int)ceil(leftbuffer.size() / step);
+ DataPacket<mcopbyte> *packet = outdata.allocPacket( samplestosend * sampleSize );
+#ifdef DEBUG_MESSAGES
+ arts_debug( "calculateBlock(%i): send %i samples", samples, samplestosend );
+#endif
+
+ int processed = 0;
+ if( interpolate ) {
+ double pos = 0;
+ if( _channels == 2 ) {
+ if( _bits == 16 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ double error = modf(_pos, &pos);
+ int intpos = (int)pos;
+#ifdef DEBUG_MESSAGES
+ arts_debug( "pos=%i, error=%e", intpos, error );
+#endif
+ long leftchannel = long((leftbuffer[intpos] * (1.0 - error) + leftbuffer[intpos + 1] * error) * 32768) + 32768;
+ long rightchannel = long((rightbuffer[intpos] * (1.0 - error) + rightbuffer[intpos + 1] * error) * 32768) + 32768;
+ packet->contents[processed ] = leftchannel;
+ packet->contents[processed + 1] = (leftchannel >> 8) - 128;
+ packet->contents[processed + 2] = rightchannel;
+ packet->contents[processed + 3] = (rightchannel >> 8) - 128;
+ _pos += step;
+ processed += 4;
+ }
+ } else if( _bits == 8 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ double error = modf(_pos, &pos);
+ int intpos = (int)pos;
+ long leftchannel = long((leftbuffer[intpos] * (1.0 - error) + leftbuffer[intpos + 1] * error) * 128) + 128;
+ long rightchannel = long((rightbuffer[intpos] * (1.0 - error) + rightbuffer[intpos + 1] * error) * 128) + 128;
+ packet->contents[processed ] = leftchannel;
+ packet->contents[processed + 1] = rightchannel;
+ _pos += step;
+ processed += 2;
+ }
+ }
+ } else {
+ if( _bits == 16 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ double error = modf(_pos, &pos);
+ int intpos = (int)pos;
+ long leftchannel = long(((leftbuffer[intpos] + rightbuffer[intpos]) * (1.0 - error) + (leftbuffer[intpos + 1] + rightbuffer[intpos + 1]) * error) * 16384) + 32768;
+ packet->contents[processed ] = leftchannel;
+ packet->contents[processed + 1] = (leftchannel >> 8) - 128;
+ _pos += step;
+ processed += 2;
+ }
+ } else if( _bits == 8 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ double error = modf(_pos, &pos);
+ int intpos = (int)pos;
+ long leftchannel = long(((leftbuffer[intpos] + rightbuffer[intpos]) * (1.0 - error) + (leftbuffer[intpos + 1] + rightbuffer[intpos + 1]) * error) * 64) + 128;
+ packet->contents[processed] = leftchannel;
+ _pos += step;
+ ++processed;
+ }
+ }
+ }
+ } else {
+ if( _channels == 2 ) {
+ if( _bits == 16 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ int intpos = (int)_pos;
+ long leftchannel = long(leftbuffer[intpos] * 32768) + 32768;
+ long rightchannel = long(rightbuffer[intpos] * 32768) + 32768;
+ packet->contents[processed ] = leftchannel;
+ packet->contents[processed + 1] = (leftchannel >> 8) - 128;
+ packet->contents[processed + 2] = rightchannel;
+ packet->contents[processed + 3] = (rightchannel >> 8) - 128;
+ _pos += step;
+ processed += 4;
+ }
+ } else if( _bits == 8 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ int intpos = (int)_pos;
+ long leftchannel = long(leftbuffer[intpos] * 128) + 128;
+ long rightchannel = long(rightbuffer[intpos] * 128) + 128;
+ packet->contents[processed ] = leftchannel;
+ packet->contents[processed + 1] = rightchannel;
+ _pos += step;
+ processed += 2;
+ }
+ }
+ } else {
+ if( _bits == 16 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ int intpos = (int)_pos;
+ long leftchannel = long((leftbuffer[intpos] + rightbuffer[intpos]) * 16384) + 32768;
+ packet->contents[processed ] = leftchannel;
+ packet->contents[processed + 1] = (leftchannel >> 8) - 128;
+ _pos += step;
+ processed += 2;
+ }
+ } else if( _bits == 8 ) {
+ while( _pos < (double)leftbuffer.size() - 1 ) {
+ int intpos = (int)_pos;
+ long leftchannel = long((leftbuffer[intpos] + rightbuffer[intpos]) * 64) + 128;
+ packet->contents[processed] = leftchannel;
+ _pos += step;
+ ++processed;
+ }
+ }
+ }
+ }
+ leftbuffer[0] = leftbuffer.back();
+ rightbuffer[0] = rightbuffer.back();
+ _pos = _pos - floor(_pos);
+ packet->size = processed;
+ packet->send();
+#ifdef DEBUG_MESSAGES
+ arts_debug( "calculateBlock(%i): %i samples sent, _pos = %e", samples, processed / sampleSize, _pos );
+#endif
+ }
+};
+
+REGISTER_IMPLEMENTATION(AudioToByteStream_impl);
+
+}
diff --git a/flow/bufferqueue.h b/flow/bufferqueue.h
new file mode 100644
index 0000000..5344c4a
--- /dev/null
+++ b/flow/bufferqueue.h
@@ -0,0 +1,148 @@
+/*
+ * BC - Status (2002-03-08): ByteBuffer, BufferQueue
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of libartsflow's
+ * AudioSubSystem, and subject to change/disappearing due to optimization
+ * work.
+ */
+
+#ifndef _BUFFERQUEUE_H
+#define _BUFFERQUEUE_H
+
+#include "thread.h"
+
+#define _DEFAULT_CHUNK_SIZE 4096
+#define _MAX_CHUNKS 3
+
+namespace Arts
+{
+
+class ByteBuffer
+{
+ unsigned char* content;
+ int _size;
+ int _maxSize;
+ int rp;
+
+public:
+ ByteBuffer() {
+ _size = rp = 0;
+ _maxSize = _DEFAULT_CHUNK_SIZE;
+ content = new unsigned char[_DEFAULT_CHUNK_SIZE];
+ }
+ ByteBuffer(const void* s, int len) {
+ _maxSize = _DEFAULT_CHUNK_SIZE;
+ content = new unsigned char[_DEFAULT_CHUNK_SIZE];
+ put(s, len);
+ }
+
+ ~ByteBuffer() { delete [] content; }
+
+ void put(const void* s, int len) {
+ if ((_size = len) != 0)
+ memcpy(content, s, len);
+ rp = 0;
+ }
+
+ void* get() { return content+rp; }
+ void* reset() { _size = 0; rp = 0; return content; }
+ int push(int len) { _size -= len; rp += len; return _size; }
+ void set(int len) { _size = len; rp = 0; }
+ int size() const { return _size; }
+ int maxSize() const { return _maxSize; }
+
+ void setMaxSize(int size) {
+ delete [] content;
+ content = new unsigned char[size];
+ _maxSize = size;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class BufferQueue
+{
+private:
+ ByteBuffer bufs[_MAX_CHUNKS];
+ int rp;
+ int wp;
+ Arts::Semaphore* sema_produced;
+ Arts::Semaphore* sema_consumed;
+
+ void semaReinit() {
+ delete sema_consumed;
+ delete sema_produced;
+ sema_consumed = new Arts::Semaphore(0, _MAX_CHUNKS);
+ sema_produced = new Arts::Semaphore(0, 0);
+ }
+
+
+public:
+ BufferQueue() {
+ rp = wp = 0;
+ sema_consumed = new Arts::Semaphore(0, _MAX_CHUNKS);
+ sema_produced = new Arts::Semaphore(0, 0);
+ }
+
+ ~BufferQueue() {
+ delete sema_consumed;
+ delete sema_produced;
+ }
+
+ void write(void* data, int len);
+ ByteBuffer* waitConsumed();
+ void produced();
+
+ ByteBuffer* waitProduced();
+ void consumed();
+
+ bool isEmpty() const { return sema_produced->getValue() == 0; }
+ int bufferedChunks() const { return sema_produced->getValue(); }
+ int freeChunks() const { return sema_consumed->getValue(); }
+ int maxChunks() const { return _MAX_CHUNKS; }
+ int chunkSize() const { return bufs[0].maxSize(); }
+ void clear() { rp = wp = 0; semaReinit(); }
+ void setChunkSize(int size){
+ for (int i=0; i < maxChunks(); i++)
+ bufs[i].setMaxSize(size);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+inline void BufferQueue::write(void* data, int len)
+{
+ sema_consumed->wait();
+ bufs[wp].put(data, len);
+ ++wp %= _MAX_CHUNKS;
+ sema_produced->post();
+}
+
+inline ByteBuffer* BufferQueue::waitConsumed()
+{
+ sema_consumed->wait();
+ return &bufs[wp];
+}
+
+inline void BufferQueue::produced()
+{
+ ++wp %= _MAX_CHUNKS;
+ sema_produced->post();
+}
+
+inline ByteBuffer* BufferQueue::waitProduced()
+{
+ sema_produced->wait();
+ return &bufs[rp];
+}
+
+inline void BufferQueue::consumed()
+{
+ ++rp %=_MAX_CHUNKS;
+ sema_consumed->post();
+}
+
+}
+
+#endif
diff --git a/flow/bus.cc b/flow/bus.cc
new file mode 100644
index 0000000..ba5e778
--- /dev/null
+++ b/flow/bus.cc
@@ -0,0 +1,367 @@
+ /*
+
+ Copyright (C) 1998-2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "bus.h"
+#include "flowsystem.h"
+#include "debug.h"
+#include <iostream>
+#include <set>
+
+#ifdef __SUNPRO_CC
+/* SunPRO CC looses to link this when the_BusManager is static, because
+ later a template implementation file references this symbol. */
+#define the_BusManager __internal_aRts_the_BusManager__Bahh__
+#else
+static
+#endif
+ Arts::BusManager *the_BusManager = 0;
+
+using namespace Arts;
+using namespace std;
+
+// shutdown bus manager on termination
+
+namespace Arts {
+ static class BusManagerShutdown :public StartupClass
+ {
+ public:
+ void startup() { };
+ void shutdown()
+ {
+ if(::the_BusManager)
+ {
+ delete ::the_BusManager;
+ ::the_BusManager = 0;
+ }
+ }
+ } The_BusManagerShutdown;
+}
+
+BusManager::BusManager()
+{
+ // this constructor isn't public (Singleton)
+}
+
+BusManager *BusManager::the()
+{
+ if(!::the_BusManager) ::the_BusManager = new BusManager;
+ return(::the_BusManager);
+}
+
+BusManager::Bus *BusManager::findBus(const string& name)
+{
+ list<Bus *>::iterator bi;
+
+ for(bi = _busList.begin(); bi != _busList.end(); bi++)
+ {
+ if((*bi)->name == name) return(*bi);
+ }
+ Bus *bus = new Bus;
+ bus->left.start();
+ bus->right.start();
+ bus->name = name;
+ _busList.push_back(bus);
+
+ return(bus);
+}
+
+vector<string> *BusManager::busList()
+{
+ set<string> names;
+ set<string>::iterator si;
+
+ list<Bus *>::iterator bi;
+ for(bi = _busList.begin(); bi != _busList.end(); bi++)
+ names.insert((*bi)->name);
+
+ vector<string> *bl = new vector<string>;
+ for(si=names.begin();si != names.end();si++) bl->push_back(*si);
+ return bl;
+}
+
+void BusManager::addClient(const string& busname, BusClient *client)
+{
+ Bus *bus = findBus(busname);
+ bus->clients.push_back(client);
+
+ // attach the new client
+ client->snode()->virtualize("left", bus->left._node(), "invalue");
+ client->snode()->virtualize("right", bus->right._node(), "invalue");
+}
+
+void BusManager::removeClient(BusClient *client)
+{
+ list<Bus *>::iterator bi;
+ for(bi = _busList.begin(); bi != _busList.end(); bi++)
+ {
+ Bus *bus = *bi;
+
+ list<BusClient *>::iterator ci;
+ for(ci = bus->clients.begin(); ci != bus->clients.end(); ci++)
+ {
+ if(*ci == client)
+ {
+ bus->clients.erase(ci);
+
+ if(bus->clients.empty() && bus->servers.empty())
+ {
+ _busList.erase(bi);
+ delete bus;
+ }
+ else
+ {
+ client->snode()->devirtualize("left",
+ bus->left._node(), "invalue");
+ client->snode()->devirtualize("right",
+ bus->right._node(), "invalue");
+ }
+ return;
+ }
+ }
+ }
+}
+
+void BusManager::addServer(const string& busname, BusClient *server)
+{
+ Bus *bus = findBus(busname);
+ bus->servers.push_back(server);
+
+ server->snode()->virtualize("left",bus->left._node(),"outvalue");
+ server->snode()->virtualize("right",bus->right._node(),"outvalue");
+}
+
+void BusManager::removeServer(BusClient *server)
+{
+ list<Bus *>::iterator bi;
+
+ for(bi = _busList.begin(); bi != _busList.end(); bi++)
+ {
+ Bus *bus = *bi;
+
+ list<BusClient *>::iterator si;
+ for(si = bus->servers.begin(); si != bus->servers.end(); si++)
+ {
+ if(*si == server)
+ {
+ bus->servers.erase(si);
+ if(bus->clients.empty() && bus->servers.empty())
+ {
+ _busList.erase(bi);
+ delete bus;
+ }
+ else
+ {
+ server->snode()->devirtualize("left",
+ bus->left._node(), "outvalue");
+ server->snode()->devirtualize("right",
+ bus->right._node(),"outvalue");
+ }
+ return;
+ }
+ }
+ }
+}
+
+namespace Arts {
+
+class Synth_BUS_UPLINK_impl :public Synth_BUS_UPLINK_skel,
+ public StdSynthModule, public BusClient
+{
+ BusManager *bm;
+ bool running, active, relink;
+ string _busname;
+public:
+ Synth_BUS_UPLINK_impl();
+
+ string busname() { return _busname; }
+ void busname(const string& newname);
+ AutoSuspendState autoSuspend() { return asSuspend; }
+ void streamInit();
+ void streamEnd();
+ ScheduleNode *snode() { return _node(); }
+
+ void CallBack();
+
+ void connect();
+ void disconnect();
+};
+
+REGISTER_IMPLEMENTATION(Synth_BUS_UPLINK_impl);
+
+}
+
+Synth_BUS_UPLINK_impl::Synth_BUS_UPLINK_impl() :running(false)
+{
+ bm = BusManager::the();
+}
+
+void Synth_BUS_UPLINK_impl::streamInit()
+{
+ assert(!running);
+ running = true;
+ active = relink = false;
+
+ connect(); // connect to the BusManager
+}
+
+void Synth_BUS_UPLINK_impl::busname(const string& newname)
+{
+ _busname = newname;
+
+ /* TODO */
+ // to be sure that reconnection happens when outside the scheduling cycle
+ if(running)
+ {
+ relink = true;
+ CallBack();
+ }
+}
+
+void Synth_BUS_UPLINK_impl::connect()
+{
+ assert(active == false);
+ if(!_busname.empty())
+ {
+ active = true;
+ bm->addClient(_busname, this);
+ }
+}
+
+void Synth_BUS_UPLINK_impl::disconnect()
+{
+ if(active == true)
+ {
+ bm->removeClient(this);
+ active = false;
+ }
+}
+
+void Synth_BUS_UPLINK_impl::CallBack()
+{
+ if(relink)
+ {
+ disconnect();
+ connect();
+ relink = false;
+ }
+}
+
+void Synth_BUS_UPLINK_impl::streamEnd()
+{
+ disconnect();
+
+ assert(running);
+ running = false;
+}
+
+namespace Arts {
+
+class Synth_BUS_DOWNLINK_impl :public Synth_BUS_DOWNLINK_skel,
+ public StdSynthModule, public BusClient
+{
+ bool running, active, relink;
+ BusManager *bm;
+
+ string _busname;
+
+ void connect();
+ void disconnect();
+
+public:
+ string busname() { return _busname; }
+ void busname(const string& newname);
+
+ Synth_BUS_DOWNLINK_impl();
+ AutoSuspendState autoSuspend() { return asSuspend; }
+ void streamInit();
+ void streamEnd();
+ void CallBack();
+ ScheduleNode *snode() { return _node(); }
+};
+
+REGISTER_IMPLEMENTATION(Synth_BUS_DOWNLINK_impl);
+
+}
+
+Synth_BUS_DOWNLINK_impl::Synth_BUS_DOWNLINK_impl() :running(false)
+{
+ bm = BusManager::the();
+}
+
+void Synth_BUS_DOWNLINK_impl::streamInit()
+{
+ assert(!running);
+ running = true;
+
+ active = relink = false;
+ connect();
+}
+
+void Synth_BUS_DOWNLINK_impl::streamEnd()
+{
+ assert(running);
+ running = false;
+
+ disconnect();
+}
+
+void Synth_BUS_DOWNLINK_impl::connect()
+{
+ assert(active == false);
+ if(!_busname.empty())
+ {
+ active = true;
+ bm->addServer(_busname, this);
+ }
+}
+
+void Synth_BUS_DOWNLINK_impl::disconnect()
+{
+ if(active == true)
+ {
+ bm->removeServer(this);
+ active = false;
+ }
+}
+
+void Synth_BUS_DOWNLINK_impl::CallBack()
+{
+ if(relink)
+ {
+ disconnect();
+ connect();
+ relink = false;
+ }
+}
+
+void Synth_BUS_DOWNLINK_impl::busname(const string& newname)
+{
+ _busname = newname;
+
+ /* TODO */
+ // to be sure that reconnection happens when outside the scheduling cycle
+ if(running)
+ {
+ relink = true;
+ CallBack();
+ }
+}
diff --git a/flow/bus.h b/flow/bus.h
new file mode 100644
index 0000000..747932b
--- /dev/null
+++ b/flow/bus.h
@@ -0,0 +1,76 @@
+ /*
+
+ Copyright (C) 1998-2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_BUS_H
+#define ARTS_BUS_H
+
+#include "stdsynthmodule.h"
+#include "artsflow.h"
+
+/*
+ * BC - Status (2002-03-08): BusClient, BusManager
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of libartsflow's
+ * Synth_BUS_* and Synth_AMAN_* and AudioManager interfaces. Use these for
+ * public use instead, and don't touch this here.
+ */
+
+
+namespace Arts {
+
+class BusClient
+{
+public:
+ virtual Arts::ScheduleNode *snode() = 0;
+};
+
+
+class BusManager
+{
+protected:
+ struct Bus
+ {
+ std::string name;
+ std::list<BusClient *> clients;
+ std::list<BusClient *> servers;
+ Arts::Synth_MULTI_ADD left, right;
+ };
+ std::list<Bus *> _busList;
+
+ BusManager();
+
+public:
+ Bus* findBus(const std::string& name);
+
+ void addClient(const std::string& busname, BusClient *client);
+ void removeClient(BusClient *client);
+ void addServer(const std::string& busname, BusClient *server);
+ void removeServer(BusClient *server);
+
+ std::vector<std::string> *busList();
+
+ static BusManager *the();
+};
+}
+
+#endif /* ARTS_BUS_H */
diff --git a/flow/bytestreamtoaudio_impl.cc b/flow/bytestreamtoaudio_impl.cc
new file mode 100644
index 0000000..73714cf
--- /dev/null
+++ b/flow/bytestreamtoaudio_impl.cc
@@ -0,0 +1,119 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include "resample.h"
+
+#include <cstring>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class PacketRefiller : public Refiller {
+protected:
+ queue< DataPacket<mcopbyte>* > inqueue;
+ int pos;
+
+public:
+ PacketRefiller() : pos(0)
+ {
+ }
+ void process(DataPacket<mcopbyte>* packet)
+ {
+ inqueue.push(packet);
+ }
+ unsigned long read(unsigned char *buffer, unsigned long bytes)
+ {
+ unsigned long done = 0;
+ while(!inqueue.empty())
+ {
+ long tocopy = bytes - done;
+ if(tocopy == 0) return bytes; /* complete? */
+
+ DataPacket<mcopbyte> *packet = inqueue.front();
+ if(tocopy > (packet->size - pos))
+ tocopy = (packet->size - pos);
+
+ memcpy(&buffer[done],&packet->contents[pos],tocopy);
+ pos += tocopy;
+ done += tocopy;
+
+ if(pos == packet->size) {
+ packet->processed();
+ pos = 0;
+ inqueue.pop();
+ }
+ }
+ return done;
+ }
+};
+
+class ByteStreamToAudio_impl : public ByteStreamToAudio_skel,
+ public StdSynthModule
+{
+ PacketRefiller refiller;
+ Resampler resampler;
+ long _samplingRate, _channels, _bits;
+public:
+ ByteStreamToAudio_impl() :resampler(&refiller),
+ _samplingRate(44100), _channels(2), _bits(16)
+ {
+ //
+ }
+
+ long samplingRate() { return _samplingRate; }
+ void samplingRate(long newRate) {
+ _samplingRate = newRate;
+ resampler.setStep((float)_samplingRate / samplingRateFloat);
+ }
+
+ long channels() { return _channels; }
+ void channels(long newChannels) {
+ _channels = newChannels;
+ resampler.setChannels(_channels);
+ }
+
+ long bits() { return _bits; }
+ void bits(long newBits) {
+ _bits = newBits;
+ resampler.setBits(_bits);
+ }
+
+ bool running() { return !resampler.underrun(); }
+
+ void process_indata(DataPacket<mcopbyte> *packet)
+ {
+ refiller.process(packet);
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ resampler.run(left,right,samples);
+ }
+};
+
+REGISTER_IMPLEMENTATION(ByteStreamToAudio_impl);
+
+}
diff --git a/flow/cache.cc b/flow/cache.cc
new file mode 100644
index 0000000..0c7cfcc
--- /dev/null
+++ b/flow/cache.cc
@@ -0,0 +1,274 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "cache.h"
+#include "debug.h"
+#include "iomanager.h"
+#include "dispatcher.h"
+#include <iostream>
+#include <assert.h>
+
+using namespace std;
+using namespace Arts;
+
+bool CachedObject::isValid()
+{
+ return true;
+}
+
+void CachedObject::setKey(string key)
+{
+ _object_key = key;
+}
+
+string CachedObject::getKey()
+{
+ return _object_key;
+}
+
+void CachedObject::decRef()
+{
+ _ref_cnt--;
+ time(&_lastAccess);
+}
+
+void CachedObject::incRef()
+{
+ _ref_cnt++;
+}
+
+int CachedObject::refCnt()
+{
+ return _ref_cnt;
+}
+
+time_t CachedObject::lastAccess()
+{
+ return(_lastAccess);
+}
+
+CachedObject::CachedObject(Cache *cache)
+{
+ _ref_cnt = 1;
+ cache->add(this);
+}
+
+CachedObject::~CachedObject()
+{
+ assert(_ref_cnt == 0);
+}
+
+//------------------------- Cache implementation ---------------------------
+long Cache::memused = 0;
+
+CachedObject *Cache::get(string key)
+{
+ list<CachedObject *>::iterator i;
+
+ for(i=objects.begin();i != objects.end(); i++)
+ {
+ if((*i)->getKey() == key && (*i)->isValid())
+ {
+ (*i)->incRef();
+ return(*i);
+ }
+ }
+ return 0;
+}
+
+void Cache::add(CachedObject *object)
+{
+ objects.push_back(object);
+}
+
+long Cache::cleanUp(long cacheLimit)
+{
+ time_t lastAccess;
+
+ list<CachedObject *>::iterator i;
+ long memory = 0;
+
+ // delete all invalid unused entries (invalid entries that are still
+ // in use, e.g. cached wav files which have changed on disk but are
+ // still played can't be deleted!)
+
+ for(i=objects.begin();i != objects.end(); i++)
+ {
+ CachedObject *co = (*i);
+
+ if(co->refCnt() == 0 && !co->isValid())
+ {
+ objects.remove(co);
+ delete co;
+ i = objects.begin();
+ }
+ }
+
+ for(i=objects.begin();i != objects.end(); i++)
+ {
+ memory += (*i)->memoryUsage();
+ }
+
+ bool freeok = true;
+ while(memory > cacheLimit && freeok)
+ {
+ CachedObject *freeme;
+
+ freeok = false;
+
+ // only start freeing objects which have not been accessed
+ // in the last 5 seconds
+
+ time(&lastAccess);
+ lastAccess -= 5;
+
+
+ for(i=objects.begin();!freeok && (i != objects.end()); i++)
+ {
+ CachedObject *co = (*i);
+
+ assert(co->refCnt() >= 0);
+ if(co->refCnt() == 0 && (co->lastAccess() < lastAccess))
+ {
+ lastAccess = co->lastAccess();
+ freeme = co;
+ freeok = true;
+ }
+ else
+ {
+ //artsdebug("%d => %ld\n",co->refCnt(),co->lastAccess());
+ }
+ }
+
+ if(freeok)
+ {
+ memory -= freeme->memoryUsage();
+ objects.remove(freeme);
+ delete(freeme);
+ }
+ else
+ {
+ //artsdebug("cache problem: memory overused, but nothing there to free\n");
+ }
+ }
+
+ memused = memory/1024;
+ return(memory);
+}
+
+Cache *Cache::_instance = 0;
+
+Cache::Cache()
+{
+ assert(!_instance);
+ _instance = this;
+}
+
+Cache::~Cache()
+{
+ list<CachedObject *>::iterator i;
+ for(i=objects.begin(); i != objects.end(); i++)
+ delete (*i);
+ objects.clear();
+
+ assert(_instance);
+ _instance = 0;
+}
+
+
+Cache *Cache::the()
+{
+ if(!_instance) _instance = new Cache();
+ return _instance;
+}
+
+void Cache::shutdown()
+{
+ if(_instance)
+ {
+ list<CachedObject *>::iterator i;
+ long rcnt = 0;
+ for(i=_instance->objects.begin(); i != _instance->objects.end(); i++)
+ rcnt += (*i)->refCnt();
+
+ if(rcnt == 0)
+ {
+ delete _instance;
+ _instance = 0;
+ }
+ else
+ {
+ arts_warning("cache shutdown while still active objects in cache");
+ }
+ }
+}
+
+namespace Arts { // internal helpers
+
+// periodic cache clean
+class CacheClean : public TimeNotify {
+public:
+ CacheClean();
+ void notifyTime();
+ virtual ~CacheClean();
+};
+
+// cache startup & shutdown
+class CacheStartup :public StartupClass
+{
+public:
+ void startup();
+ void shutdown();
+private:
+ CacheClean *cacheClean;
+};
+
+}
+
+CacheClean::CacheClean()
+{
+ Dispatcher::the()->ioManager()->addTimer(5000, this);
+}
+
+void CacheClean::notifyTime()
+{
+ // TODO: make this configurable
+ Cache::the()->cleanUp(8192*1024);
+}
+
+CacheClean::~CacheClean()
+{
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
+
+void CacheStartup::startup()
+{
+ cacheClean = new CacheClean;
+}
+
+void CacheStartup::shutdown()
+{
+ delete cacheClean;
+ Cache::shutdown();
+}
+
+static CacheStartup cacheStartup;
diff --git a/flow/cache.h b/flow/cache.h
new file mode 100644
index 0000000..3f093df
--- /dev/null
+++ b/flow/cache.h
@@ -0,0 +1,92 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef _SYNTH_CACHE_H
+#define _SYNTH_CACHE_H
+
+#include <time.h>
+#include <list>
+#include <string>
+#include "startupmanager.h"
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Cache, CachedObject
+ *
+ * At the current point in time, there are NO GUARANTEES, so only use this
+ * in apps part of official KDE releases (such as kdemultimedia apps), which
+ * know what is happening here.
+ */
+
+namespace Arts {
+class Cache;
+
+class ARTS_EXPORT CachedObject
+{
+private:
+ std::string _object_key;
+ int _ref_cnt;
+ time_t _lastAccess;
+
+protected:
+ void setKey(std::string key);
+
+public:
+ std::string getKey();
+
+ time_t lastAccess();
+
+ void decRef();
+ void incRef();
+ int refCnt();
+
+ virtual bool isValid();
+ virtual int memoryUsage() = 0;
+
+ CachedObject(Cache *cache);
+ virtual ~CachedObject();
+};
+
+class ARTS_EXPORT Cache
+{
+protected:
+ std::list<CachedObject *> objects;
+ Cache();
+ ~Cache();
+
+ static Cache *_instance;
+
+public:
+ static Cache *the();
+ static void shutdown();
+
+ static long memused;
+
+ CachedObject *get(std::string key);
+ void add(CachedObject *object);
+
+ // garbage collection; returns amount of memory used (after cleaning)
+ long cleanUp(long cacheLimit);
+};
+
+}
+#endif
diff --git a/flow/cachedwav.h b/flow/cachedwav.h
new file mode 100644
index 0000000..99df156
--- /dev/null
+++ b/flow/cachedwav.h
@@ -0,0 +1,81 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef CACHEDWAV_H
+#define CACHEDWAV_H
+
+#include "config.h"
+#include "arts_export.h"
+#ifdef HAVE_LIBAUDIOFILE
+#include "cache.h"
+#include <sys/stat.h>
+#include <unistd.h>
+
+/*
+ * BC - Status (2002-03-08): CachedWav.
+ *
+ * At the current point in time, there are NO GUARANTEES, so only use this
+ * in apps part of official KDE releases (such as kdemultimedia apps), which
+ * know what is happening here. Especially, in SOME kde versions this class
+ * might not even exist, as it gets conditionally compiled.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT CachedWav : public CachedObject
+{
+protected:
+ struct stat oldstat;
+ std::string filename;
+ bool initOk;
+
+ CachedWav(Cache *cache, std::string filename);
+ ~CachedWav();
+
+ typedef unsigned char uchar;
+public:
+ double samplingRate;
+ long bufferSize;
+ int channelCount;
+ int sampleWidth;
+ unsigned char *buffer;
+
+ static CachedWav *load(Cache *cache, std::string filename);
+ /**
+ * validity test for the cache - returns false if the object is having
+ * reflecting the correct contents anymore (e.g. if the file on the
+ * disk has changed), and there is no point in keeping it in the cache any
+ * longer
+ */
+ bool isValid();
+ /**
+ * memory usage for the cache
+ */
+ int memoryUsage();
+
+ std::string mediaName() const { return filename; }
+};
+
+}
+
+#endif /* HAVE_LIBAUDIOFILE */
+#endif /* CACHEDWAV_H */
diff --git a/flow/convert.cc b/flow/convert.cc
new file mode 100644
index 0000000..d5ca2f8
--- /dev/null
+++ b/flow/convert.cc
@@ -0,0 +1,418 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "convert.h"
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+#include <config.h>
+
+#ifdef HAVE_X86_FLOAT_INT
+static inline long QRound (float inval)
+{
+#if (__GNUC__ == 3 && __GNUC_MINOR__ == 0)
+ volatile
+#warning "workaround for gcc-3.0 bug c++/2733 enabled"
+#endif
+ int ret;
+ __asm__ ("fistpl %0" : "=m" (ret) : "t" (inval) : "st");
+ return ret;
+}
+#else
+static inline long QRound (float inval)
+{
+ return (long)inval;
+}
+#endif
+
+/*---------------------------- new code begin -------------------------- */
+
+#define compose_16le(ptr) \
+ ((((*((ptr)+1)+128)&0xff) << 8)+*(ptr))
+
+#define compose_16be(ptr) \
+ ((((*(ptr)+128)&0xff) << 8)+*((ptr)+1))
+
+#define conv_16_float(x) \
+ ((float)((x)-32768)/32768.0)
+
+#define convert_16le_float(x) conv_16_float(compose_16le(&(x)))
+#define convert_16be_float(x) conv_16_float(compose_16be(&(x)))
+
+#define conv_8_float(x) \
+ ((float)((x)-128)/128.0)
+
+#define convert_8_float(x) \
+ ((float)((x)-128)/128.0)
+
+#define convert_float_float(x) x
+
+/*
+ * 16le, 16be, 8, float
+ */
+
+#define datatype_16le unsigned char
+#define datasize_16le 2
+
+#define datatype_16be unsigned char
+#define datasize_16be 2
+
+#define datatype_8 unsigned char
+#define datasize_8 1
+
+#define datatype_float float
+#define datasize_float 1
+
+#define mk_converter(from_format,to_format) \
+void Arts::convert_mono_ ## from_format ## _ ## to_format (unsigned long samples, \
+ datatype_ ## from_format *from, \
+ datatype_ ## to_format *to) \
+{ \
+ datatype_ ## to_format *end = to+samples * (datasize_ ## to_format); \
+ while(to<end) { \
+ *to = convert_ ## from_format ## _ ## to_format(*from); \
+ from += datasize_ ## from_format; \
+ to += datasize_ ## to_format; \
+ } \
+} \
+void Arts::interpolate_mono_ ## from_format ## _ ## to_format (unsigned long samples,\
+ double startpos, double speed, \
+ datatype_ ## from_format *from, \
+ datatype_ ## to_format *to) \
+{ \
+ double flpos = startpos; \
+ while(samples) { \
+ long position = ((long)(flpos)) * (datasize_ ## from_format); \
+ double error = flpos - floor(flpos); \
+ *to = (convert_ ## from_format ## _ ## to_format(from[position])) * \
+ (1.0-error) + (convert_ ## from_format ## _ ## \
+ to_format(from[position + datasize_ ## from_format])) * error; \
+ to += datasize_ ## to_format; \
+ flpos += speed; \
+ samples--; \
+ } \
+} \
+void Arts::convert_stereo_i ## from_format ## _2 ## to_format (unsigned long samples,\
+ datatype_ ## from_format *from, \
+ datatype_ ## to_format *left, \
+ datatype_ ## to_format *right) \
+{ \
+ datatype_ ## to_format *end = left+samples * (datasize_ ## to_format); \
+ while(left<end) { \
+ *left = convert_ ## from_format ## _ ## to_format(*from); \
+ from += datasize_ ## from_format; \
+ left += datasize_ ## to_format; \
+ *right = convert_ ## from_format ## _ ## to_format(*from); \
+ from += datasize_ ## from_format; \
+ right += datasize_ ## to_format; \
+ } \
+} \
+void Arts::interpolate_stereo_i ## from_format ## _2 ## to_format (unsigned long samples,\
+ double startpos, double speed, \
+ datatype_ ## from_format *from, \
+ datatype_ ## to_format *left, \
+ datatype_ ## to_format *right) \
+{ \
+ double flpos = startpos; \
+ while(samples) { \
+ long position = ((long)(flpos)) * (datasize_ ## from_format) * 2; \
+ double error = flpos - floor(flpos); \
+ *left = (convert_ ## from_format ## _ ## to_format(from[position])) * \
+ (1.0-error) + (convert_ ## from_format ## _ ## \
+ to_format(from[position + 2*datasize_ ## from_format]))*error; \
+ left += datasize_ ## to_format; \
+ position += datasize_ ## from_format; \
+ *right =(convert_ ## from_format ## _ ## to_format(from[position])) * \
+ (1.0-error) + (convert_ ## from_format ## _ ## \
+ to_format(from[position + 2*datasize_ ## from_format]))*error; \
+ right += datasize_ ## to_format; \
+ flpos += speed; \
+ samples--; \
+ } \
+}
+
+mk_converter(8,float)
+mk_converter(16le,float)
+mk_converter(16be,float)
+mk_converter(float,float)
+
+/*----------------------------- new code end --------------------------- */
+
+/*
+void old_convert_mono_8_float(unsigned long samples, unsigned char *from, float *to)
+{
+ float *end = to+samples;
+
+ while(to<end) *to++ = conv_8_float(*from++);
+}
+
+void old_convert_mono_16le_float(unsigned long samples, unsigned char *from, float *to)
+{
+ float *end = to+samples;
+
+ while(to<end)
+ {
+ *to++ = conv_16le_float(compose_16le(from));
+ from += 2;
+ }
+}
+
+
+void old_convert_stereo_i8_2float(unsigned long samples, unsigned char *from, float *left, float *right)
+{
+ float *end = left+samples;
+ while(left < end)
+ {
+ *left++ = conv_8_float(*from++);
+ *right++ = conv_8_float(*from++);
+ }
+}
+
+void old_convert_stereo_i16le_2float(unsigned long samples, unsigned char *from, float *left, float *right)
+{
+ float *end = left+samples;
+ while(left < end)
+ {
+ *left++ = conv_16le_float(compose_16le(from));
+ *right++ = conv_16le_float(compose_16le(from+2));
+ from += 4;
+ }
+}
+*/
+
+void Arts::convert_stereo_2float_i16le(unsigned long samples, float *left, float *right, unsigned char *to)
+{
+ float *end = left+samples;
+ long syn;
+
+ while(left < end)
+ {
+ syn = QRound((*left++)*32767);
+
+ if(syn < -32768) syn = -32768; /* clipping */
+ if(syn > 32767) syn = 32767;
+
+ *to++ = syn & 0xff;
+ *to++ = (syn >> 8) & 0xff;
+
+ syn = QRound((*right++)*32767);
+
+ if(syn < -32768) syn = -32768; /* clipping */
+ if(syn > 32767) syn = 32767;
+
+ *to++ = syn & 0xff;
+ *to++ = (syn >> 8) & 0xff;
+ }
+}
+
+void Arts::convert_mono_float_16le(unsigned long samples, float *from, unsigned char *to)
+{
+ float *end = from+samples;
+
+ while(from < end)
+ {
+ long syn = QRound((*from++)*32767);
+
+ if(syn < -32768) syn = -32768; /* clipping */
+ if(syn > 32767) syn = 32767;
+
+ *to++ = syn & 0xff;
+ *to++ = (syn >> 8) & 0xff;
+ }
+}
+
+void Arts::convert_stereo_2float_i16be(unsigned long samples, float *left, float *right, unsigned char *to)
+{
+ float *end = left+samples;
+ long syn;
+
+ while(left < end)
+ {
+ syn = QRound((*left++)*32767);
+
+ if(syn < -32768) syn = -32768; /* clipping */
+ if(syn > 32767) syn = 32767;
+
+ *to++ = (syn >> 8) & 0xff;
+ *to++ = syn & 0xff;
+
+ syn = QRound((*right++)*32767);
+
+ if(syn < -32768) syn = -32768; /* clipping */
+ if(syn > 32767) syn = 32767;
+
+ *to++ = (syn >> 8) & 0xff;
+ *to++ = syn & 0xff;
+ }
+}
+
+void Arts::convert_mono_float_16be(unsigned long samples, float *from, unsigned char *to)
+{
+ float *end = from+samples;
+
+ while(from < end)
+ {
+ long syn = QRound((*from++)*32767);
+
+ if(syn < -32768) syn = -32768; /* clipping */
+ if(syn > 32767) syn = 32767;
+
+ *to++ = (syn >> 8) & 0xff;
+ *to++ = syn & 0xff;
+ }
+}
+
+void Arts::convert_stereo_2float_i8(unsigned long samples, float *left, float *right, unsigned char *to)
+{
+ float *end = left+samples;
+ long syn;
+
+ while(left < end)
+ {
+ syn = (int)((*left++)*127+128);
+
+ if(syn < 0) syn = 0; /* clipping */
+ if(syn > 255) syn = 255;
+
+ *to++ = syn;
+
+ syn = (int)((*right++)*127+128);
+
+ if(syn < 0) syn = 0; /* clipping */
+ if(syn > 255) syn = 255;
+
+ *to++ = syn;
+ }
+}
+
+void Arts::convert_mono_float_8(unsigned long samples, float *from, unsigned char *to)
+{
+ float *end = from+samples;
+
+ while(from < end)
+ {
+ long syn = (int)((*from++)*127+128);
+
+ if(syn < 0) syn = 0; /* clipping */
+ if(syn > 255) syn = 255;
+
+ *to++ = syn;
+ }
+}
+
+unsigned long Arts::uni_convert_stereo_2float(
+ unsigned long samples, // number of required samples
+ unsigned char *from, // buffer containing the samples
+ unsigned long fromLen, // length of the buffer
+ unsigned int fromChannels, // channels stored in the buffer
+ unsigned int fromBits, // number of bits per sample
+ float *left, float *right, // output buffers for left and right channel
+ double speed, // speed (2.0 means twice as fast)
+ double startposition // startposition
+ )
+{
+ unsigned long doSamples = 0, sampleSize = fromBits/8;
+
+ if(fromBits == uni_convert_float_ne)
+ sampleSize = sizeof(float);
+
+ // how many samples does the from-buffer contain?
+ double allSamples = fromLen / (fromChannels * sampleSize);
+
+ // how many samples are remaining?
+ // subtract one due to interpolation and another against rounding errors
+ double fHaveSamples = allSamples - startposition - 2.0;
+ fHaveSamples /= speed;
+
+ // convert do "how many samples to do"?
+ if(fHaveSamples > 0)
+ {
+ doSamples = (int)fHaveSamples;
+ if(doSamples > samples) doSamples = samples;
+ }
+
+ // do conversion
+ if(doSamples)
+ {
+ if(fromChannels == 1)
+ {
+ if(fromBits == uni_convert_float_ne) {
+ interpolate_mono_float_float(doSamples,
+ startposition,speed,(float *)from,left);
+ }
+ else if(fromBits == uni_convert_s16_be) {
+ interpolate_mono_16be_float(doSamples,
+ startposition,speed,from,left);
+ }
+ else if(fromBits == uni_convert_s16_le) {
+ interpolate_mono_16le_float(doSamples,
+ startposition,speed,from,left);
+ }
+ else {
+ interpolate_mono_8_float(doSamples,
+ startposition,speed,from,left);
+ }
+ memcpy(right,left,sizeof(float)*doSamples);
+ }
+ else if(fromChannels == 2)
+ {
+ if(fromBits == uni_convert_float_ne) {
+ interpolate_stereo_ifloat_2float(doSamples,
+ startposition,speed,(float *)from,left,right);
+ }
+ else if(fromBits == uni_convert_s16_be) {
+ interpolate_stereo_i16be_2float(doSamples,
+ startposition,speed,from,left,right);
+ }
+ else if(fromBits == uni_convert_s16_le) {
+ interpolate_stereo_i16le_2float(doSamples,
+ startposition,speed,from,left,right);
+ }
+ else {
+ interpolate_stereo_i8_2float(doSamples,
+ startposition,speed,from,left,right);
+ }
+ } else {
+ assert(false);
+ }
+ }
+ return doSamples;
+}
+
+// undefine all that stuff (due to --enable-final)
+#undef compose_16le
+#undef compose_16be
+#undef conv_16_float
+#undef convert_16le_float
+#undef convert_16be_float
+#undef conv_8_float
+#undef convert_8_float
+#undef convert_float_float
+#undef datatype_16le
+#undef datasize_16le
+#undef datatype_16be
+#undef datasize_16be
+#undef datatype_8
+#undef datasize_8
+#undef datatype_float
+#undef datasize_float
+#undef mk_converter
diff --git a/flow/convert.h b/flow/convert.h
new file mode 100644
index 0000000..35551a1
--- /dev/null
+++ b/flow/convert.h
@@ -0,0 +1,164 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef _arts_convert_h
+#define _arts_convert_h
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): conversion functions
+ *
+ * None of them will be removed or changed, so it is safe to use them in
+ * your apps. It is *recommended* (though not necessary) to use the new
+ * resampling code (Resampler) where possible.
+ */
+
+namespace Arts {
+
+/*
+ * Simple conversion routines. The function names are chosen like
+ *
+ * convert_mono_FROM_TO for mono conversions
+ * convert_stereo_FROM_TO for stereo conversions
+ *
+ * while FROM/TO are
+ *
+ * 8 for 8bit signed data
+ * 16le for 16bit signed little endian
+ * float for float data between -1 and 1
+ *
+ * and may be prefixed by 2 to indicate that stereo is done with two seperate
+ * buffers or i to indicate interleaved stereo (one buffer which contains
+ * one sample left, one sample right, one sample left etc.)
+ *
+ * The parameter speed (for interpolations) is *not* the samplingrate, but
+ * a relative value. A speed of 2.0 means "play twice as fast".
+ */
+
+// upconversions from integer to float
+void ARTS_EXPORT convert_mono_8_float(unsigned long samples,
+ unsigned char *from, float *to);
+
+void ARTS_EXPORT interpolate_mono_8_float(unsigned long samples,
+ double startpos, double speed,
+ unsigned char *from, float *to);
+
+void ARTS_EXPORT convert_mono_16le_float(unsigned long samples,
+ unsigned char *from, float *to);
+
+void ARTS_EXPORT interpolate_mono_16le_float(unsigned long samples,
+ double startpos, double speed,
+ unsigned char *from, float *to);
+
+void ARTS_EXPORT convert_mono_16be_float(unsigned long samples,
+ unsigned char *from, float *to);
+
+void ARTS_EXPORT interpolate_mono_16be_float(unsigned long samples,
+ double startpos, double speed,
+ unsigned char *from, float *to);
+
+void ARTS_EXPORT convert_stereo_i8_2float(unsigned long samples,
+ unsigned char *from, float *left, float *right);
+
+void ARTS_EXPORT interpolate_stereo_i8_2float(unsigned long samples,
+ double startpos, double speed,
+ unsigned char *from, float *left, float *right);
+
+void ARTS_EXPORT convert_stereo_i16le_2float(unsigned long samples,
+ unsigned char *from, float *left, float *right);
+
+void ARTS_EXPORT interpolate_stereo_i16le_2float(unsigned long samples,
+ double startpos, double speed,
+ unsigned char *from, float *left, float *right);
+
+void ARTS_EXPORT convert_stereo_i16be_2float(unsigned long samples,
+ unsigned char *from, float *left, float *right);
+
+void ARTS_EXPORT interpolate_stereo_i16be_2float(unsigned long samples,
+ double startpos, double speed,
+ unsigned char *from, float *left, float *right);
+
+void ARTS_EXPORT convert_mono_float_float(unsigned long samples,
+ float *from, float *to);
+
+void ARTS_EXPORT interpolate_mono_float_float(unsigned long samples,
+ double startpos, double speed,
+ float *from, float *to);
+
+void ARTS_EXPORT convert_stereo_ifloat_2float(unsigned long samples,
+ float *from, float *left, float *right);
+
+void ARTS_EXPORT interpolate_stereo_ifloat_2float(unsigned long samples,
+ double startpos, double speed,
+ float *from, float *left, float *right);
+
+// downconversions from float to integer
+void ARTS_EXPORT convert_mono_float_16le(unsigned long samples,
+ float *from, unsigned char *to);
+
+void ARTS_EXPORT convert_stereo_2float_i16le(unsigned long samples,
+ float *left, float *right, unsigned char *to);
+
+void ARTS_EXPORT convert_mono_float_16be(unsigned long samples,
+ float *from, unsigned char *to);
+
+void ARTS_EXPORT convert_stereo_2float_i16be(unsigned long samples,
+ float *left, float *right, unsigned char *to);
+
+void ARTS_EXPORT convert_mono_float_8(unsigned long samples,
+ float *from, unsigned char *to);
+
+void ARTS_EXPORT convert_stereo_2float_i8(unsigned long samples,
+ float *left, float *right, unsigned char *to);
+
+
+/*
+ * This practical routine picks the right conversion routine for given
+ * parameters and makes boundary checks
+ */
+
+// returnvalue: number of samples generated
+
+/* formats for unified conversion */
+enum {
+ uni_convert_u8 = 8, // unsigned 8 bit
+ uni_convert_s16_le = 16, // signed 16 bit, little endian
+ uni_convert_s16_be = 17, // signed 16 bit, big endian
+ uni_convert_float_ne = 0x100 // float, in native size/byteorder
+};
+
+unsigned long ARTS_EXPORT uni_convert_stereo_2float(
+ unsigned long samples, // number of required samples
+ unsigned char *from, // buffer containing the samples
+ unsigned long fromLen, // length of the buffer
+ unsigned int fromChannels, // channels stored in the buffer
+ unsigned int fromBits, // number of bits per sample
+ // (also: uni_convert_ formats given above)
+ float *left, float *right, // output buffers for left and right channel
+ double speed, // speed (2.0 means twice as fast)
+ double startposition // startposition
+ );
+
+}
+
+#endif
diff --git a/flow/cpuinfo.cc b/flow/cpuinfo.cc
new file mode 100644
index 0000000..8b03295
--- /dev/null
+++ b/flow/cpuinfo.cc
@@ -0,0 +1,232 @@
+ /*
+
+ Copyright (C) 2001 Malte Starostik <malte@kde.org>
+ 2001 Darian Lanx <bio@gmx.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "startupmanager.h"
+#include "cpuinfo.h"
+
+#include <setjmp.h>
+#include <signal.h>
+
+using namespace Arts;
+
+int CpuInfo::s_flags = 0;
+
+namespace Arts
+{
+ class CpuInfoStartup : public StartupClass
+ {
+ public:
+ virtual void startup();
+
+ private:
+ static jmp_buf s_sseCheckEnv;
+ static void sseCheckHandler(int);
+ };
+}
+
+jmp_buf CpuInfoStartup::s_sseCheckEnv;
+
+void CpuInfoStartup::sseCheckHandler(int)
+{
+ longjmp(s_sseCheckEnv, 1);
+}
+
+void CpuInfoStartup::startup()
+{
+#ifdef HAVE_X86_SSE
+/*
+ * Taken with thanks from mmx.h:
+ *
+ * MultiMedia eXtensions GCC interface library for IA32.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/* Returns 1 if MMX instructions are supported,
+ * 3 if Cyrix MMX and Extended MMX instructions are supported
+ * 5 if AMD MMX and 3DNow! instructions are supported
+ * 9 if MMX and Intel ISSE instructions are supported
+ * 0 if hardware does not support any of these
+*/
+ __asm__ __volatile__ (
+ "pushl %%ebx \n\t"
+ "pushl %%ecx \n\t"
+ "pushl %%edx \n\t"
+
+ // See if CPUID instruction is supported ...
+ // ... Get copies of EFLAGS into eax and ecx
+ "pushf \n\t"
+ "popl %%eax \n\t"
+ "movl %%eax, %%ecx \n\t"
+
+ // ... Toggle the ID bit in one copy and store
+ // to the EFLAGS reg
+ "xorl $0x00200000, %%eax \n\t"
+ "push %%eax \n\t"
+ "popf \n\t"
+
+ // ... Get the (hopefully modified) EFLAGS
+ "pushf \n\t"
+ "popl %%eax \n\t"
+
+ // ... Compare and test result
+ "xorl %%eax, %%ecx \n\t"
+ "testl $0x00200000, %%ecx \n\t"
+ "jz NotSupported \n\t"
+
+ // Get standard CPUID information, and
+ // go to a specific vendor section
+ "movl $0, %%eax \n\t"
+ "cpuid \n\t"
+
+ // Check for Intel
+ "cmpl $0x756e6547, %%ebx \n\t" // Genu
+ "jne TryAMD \n\t"
+ "cmpl $0x49656e69, %%edx \n\t" // ineI
+ "jne TryAMD \n\t"
+ "cmpl $0x6c65746e, %%ecx \n\t" // ntel
+ "jne TryAMD \n\t"
+ "jmp Intel \n\t"
+
+ // Check for AMD
+ "TryAMD: \n\t"
+ "cmpl $0x68747541, %%ebx \n\t" // Auth
+ "jne TryCyrix \n\t"
+ "cmpl $0x69746e65, %%edx \n\t" // enti
+ "jne TryCyrix \n\t"
+ "cmpl $0x444d4163, %%ecx \n\t" // cAMD
+ "jne TryCyrix \n\t"
+ "jmp AMD \n\t"
+
+ // Check for Cyrix
+ "TryCyrix: \n\t"
+ "cmpl $0x69727943, %%ebx \n\t" // Cyri
+ "jne NotSupported \n\t"
+ "cmpl $0x736e4978, %%edx \n\t" // xIns
+ "jne NotSupported \n\t"
+ "cmpl $0x64616574, %%ecx \n\t" // tead
+ "jne NotSupported \n\t"
+ // Drop through to Cyrix...
+
+ // Cyrix Section
+ // See if extended CPUID is supported
+ "movl $0x80000000, %%eax \n\t"
+ "cpuid \n\t"
+ "cmpl $0x80000000, %%eax \n\t"
+ "jl MMXtest \n\t" // try std CPUID
+
+ // Extended CPUID supported, so get extended features
+ "movl $0x80000001, %%eax \n\t"
+ "cpuid \n\t"
+ "testl $0x00800000, %%eax \n\t" // test for MMX
+ "jz NotSupported \n\t" // no MMX
+ "movl $1, %0 \n\t" // has MMX
+ "testl $0x01000000, %%eax \n\t" // test for EMMX
+ "jz Return \n\t" // no EMMX
+ "addl $2, %0 \n\t" // has EMMX
+ "jmp Return \n\t"
+
+ // AMD Section
+ "AMD: \n\t"
+
+ // See if extended CPUID is supported
+ "movl $0x80000000, %%eax \n\t"
+ "cpuid \n\t"
+ "cmpl $0x80000000, %%eax \n\t"
+ "jl MMXtest \n\t" // try std CPUID
+
+ // Extended CPUID supported, so get extended features
+ "movl $0x80000001, %%eax \n\t"
+ "cpuid \n\t"
+ "testl $0x00800000, %%edx \n\t" // test for MMX
+ "jz NotSupported \n\t" // no MMX
+ "movl $1, %0 \n\t" // has MMX
+ "testl $0x80000000, %%edx \n\t" // test for 3DNow!
+ "jz Return \n\t"
+ "addl $4, %0 \n\t" // has 3DNow!
+ // Athlon(tm) XP has both 3DNow! and SSE
+ "pushl %%eax \n\t"
+ "movl $1, %%eax \n\t"
+ "cpuid \n\t"
+ "popl %%eax \n\t"
+ "testl $0x02000000, %%edx \n\t" // test for SSE
+ "jz Return \n\t" // no SSE
+ "addl $8, %0 \n\t" // has SSE
+ "jmp Return \n\t"
+
+ // Intel Section
+ "Intel: \n\t"
+
+ // Check for MMX
+ "MMXtest: \n\t"
+ "movl $1, %%eax \n\t"
+ "cpuid \n\t"
+ "testl $0x00800000, %%edx \n\t" // test for MMX
+ "jz NotSupported \n\t" // no MMX
+ "movl $1, %0 \n\t" // has MMX
+ "testl $0x02000000, %%edx \n\t" // test for SSE
+ "jz Return \n\t" // no SSE
+ "addl $8, %0 \n\t" // has SSE
+ "jmp Return \n\t"
+
+ // Nothing supported
+ "NotSupported: \n\t"
+ "movl $0, %0 \n\t"
+
+ "Return: \n\t"
+ "popl %%edx \n\t"
+ "popl %%ecx \n\t"
+ "popl %%ebx \n\t"
+ : "=a" (CpuInfo::s_flags)
+ : /* no input */
+ : "memory"
+ );
+ // SSE must be supported by the OS, if it's not, any SSE insn will
+ // trigger an invalid opcode exception, to check for this, a SIGILL
+ // handler is installed and a SSE insn run. If the handler is called,
+ // the SSE bit is cleared in CpuInfo::s_flags
+ if (CpuInfo::s_flags & CpuInfo::CpuSSE)
+ {
+ void (*oldHandler)(int) = signal(SIGILL, sseCheckHandler);
+ if (setjmp(s_sseCheckEnv))
+ {
+ CpuInfo::s_flags &= ~CpuInfo::CpuSSE;
+ }
+ else
+ {
+ __asm__ __volatile__ (
+ "subl $0x10, %esp \n"
+ "movups %xmm0, (%esp) \n"
+ "emms \n"
+ "addl $0x10, %esp \n"
+ );
+ }
+ signal(SIGILL, oldHandler);
+ }
+#endif /* HAVE_X86_SSE */
+}
+
+static CpuInfoStartup cpuInfoStartup;
diff --git a/flow/cpuinfo.h b/flow/cpuinfo.h
new file mode 100644
index 0000000..927f682
--- /dev/null
+++ b/flow/cpuinfo.h
@@ -0,0 +1,72 @@
+ /*
+
+ Copyright (C) 2001 Malte Starostik <malte@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef _arts_cpuinfo_h
+#define _arts_cpuinfo_h
+
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): CpuInfo
+ *
+ * This class will be kept binary compatible - it just exports the static
+ * CpuInfo::flags() function as only functionality.
+ */
+
+namespace Arts {
+
+ /**
+ * Provides information about the availability of the various
+ * "Multimedia extensions" the CPU supports. If you implement
+ * a routine in assembler, use @ref flags() to know which
+ * SIMD instructions the user's CPU knows about.
+ *
+ * @short Information about the CPU's SIMD implementation
+ */
+ class ARTS_EXPORT CpuInfo
+ {
+ public:
+ /**
+ * Values for the detected features of the CPU:
+ * @li CpuMMX - CPU supports MMX
+ * @li CpuEMMX - CPU supports Cyrix Extended MMX
+ * @li Cpu3DNow - CPU supports AMD 3DNow!
+ * @li CpuSSE - CPU supports Intel SSE
+ */
+ enum Flags
+ {
+ CpuMMX = 0x001, // Pentium MMX
+ CpuEMMX = 0x002, // Cyrix Extended MMX
+ Cpu3DNow = 0x004, // AMD 3DNow!
+ CpuSSE = 0x008 // Pentium III SSE
+ };
+ /**
+ * @return the @ref Flags values that correspond to the
+ * CPU's features. Multiple values are bitwised or'ed
+ */
+ static int flags() { return s_flags; }
+
+ private:
+ friend class CpuInfoStartup;
+ static int s_flags;
+ };
+}
+
+#endif // _arts_cpuinfo_h
diff --git a/flow/datahandle_impl.cc b/flow/datahandle_impl.cc
new file mode 100644
index 0000000..e576e75
--- /dev/null
+++ b/flow/datahandle_impl.cc
@@ -0,0 +1,499 @@
+ /*
+
+ Copyright (C) 2002 Hans Meine
+ hans_meine@gmx.net
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <gsl/gsldatahandle.h>
+#include <gsl/gslloader.h>
+#include <gsl/gslwaveosc.h>
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+#include <algorithm>
+#include <cstring>
+#include <gslpp/datahandle.h>
+
+using namespace std;
+
+namespace Arts {
+
+static GSL::DataHandle getDHandle(DataHandle handle);
+
+class DataHandle_impl : virtual public DataHandle_skel
+{
+protected:
+ GSL::DataHandle dhandle_;
+ long errno_;
+ friend GSL::DataHandle getDHandle(DataHandle handle);
+
+public:
+ DataHandle_impl(GSL::DataHandle dhandle = GSL::DataHandle::null())
+ : dhandle_(dhandle)
+ {
+ errno_ = dhandle_.isNull() ? 0 : dhandle_.open();
+ }
+
+ ~DataHandle_impl()
+ {
+ if(dhandle_.isOpen())
+ dhandle_.close();
+ }
+
+ long valueCount()
+ {
+ return dhandle_.valueCount();
+ }
+
+ long bitDepth()
+ {
+ return dhandle_.bitDepth();
+ }
+
+ long channelCount()
+ {
+ return dhandle_.channelCount();
+ }
+
+ long errorNo()
+ {
+ return errno_;
+ }
+
+ GSL::DataHandle createCropped(long headCutValueCount,
+ long tailCutValueCount)
+ {
+ return dhandle_.createCropped(headCutValueCount, tailCutValueCount);
+ }
+
+ GSL::DataHandle createCut(long cutOffset,
+ long cutValueCount)
+ {
+ return dhandle_.createCut(cutOffset, cutValueCount);
+ }
+
+ GSL::DataHandle createReversed()
+ {
+ return dhandle_.createReversed();
+ }
+};
+
+class ReversedDataHandle_impl : virtual public DataHandle_impl,
+ virtual public ReversedDataHandle_skel
+{
+ void init(DataHandle sourceHandle)
+ {
+ DataHandle_impl *impl = dynamic_cast<DataHandle_impl *>(sourceHandle._base());
+ dhandle_ = impl->createReversed();
+ }
+};
+
+class CroppedDataHandle_impl : virtual public DataHandle_impl,
+ virtual public CroppedDataHandle_skel
+{
+ void init(DataHandle sourceHandle,
+ long headCutValueCount,
+ long tailCutValueCount)
+ {
+ DataHandle_impl *impl = dynamic_cast<DataHandle_impl *>(sourceHandle._base());
+ dhandle_ = impl->createCropped(headCutValueCount, tailCutValueCount);
+ }
+};
+
+class CutDataHandle_impl : virtual public DataHandle_impl,
+ virtual public CutDataHandle_skel
+{
+ void init(DataHandle sourceHandle,
+ long cutOffset,
+ long cutValueCount)
+ {
+ DataHandle_impl *impl = dynamic_cast<DataHandle_impl *>(sourceHandle._base());
+ dhandle_ = impl->createCut(cutOffset, cutValueCount);
+ }
+};
+
+static GSL::DataHandle getDHandle(DataHandle handle)
+{
+ DataHandle_impl *impl = dynamic_cast<DataHandle_impl *>(handle._base());
+ if(impl)
+ return impl->dhandle_;
+ return GSL::DataHandle::null();
+}
+
+GslWaveChunk* const_wchunk_from_freq(gpointer wchunk_data, gfloat)
+{
+ return (GslWaveChunk*)wchunk_data;
+}
+
+// FIXME: Think about whether this is needed as a parameter like mixerFrequency
+#define OSCILLATOR_FREQUENCY 440.0f
+
+class DataHandlePlay_impl : virtual public DataHandlePlay_skel,
+ virtual public StdSynthModule
+{
+protected:
+ DataHandle dhandle_;
+
+ GSL::DataHandle gslDHandle_;
+ int errno_;
+ GslWaveChunk *wchunk_;
+ GslErrorType wchunkError_;
+ GslWaveOscData *wosc_;
+
+ float mixerFrequency_;
+ unsigned short channelIndex_;
+ float speed_;
+ unsigned long pos_;
+ bool finished_;
+ bool paused_;
+
+public:
+ DataHandlePlay_impl()
+ : dhandle_(DataHandle::null()),
+ gslDHandle_(GSL::DataHandle::null()),
+ wchunk_(NULL),
+ wosc_(NULL),
+ mixerFrequency_(0), // FIXME: doc says soundserver's freq
+ channelIndex_(0),
+ speed_(1.0f),
+ pos_(0),
+ finished_(false),
+ paused_(false)
+ {}
+
+ ~DataHandlePlay_impl()
+ {
+ handle(DataHandle::null());
+ }
+
+ DataHandle handle()
+ {
+ return dhandle_;
+ }
+
+ void handle(DataHandle handle)
+ {
+ deleteWaveChunk();
+
+ if(!gslDHandle_.isNull() && !errno_)
+ gslDHandle_.close();
+
+ dhandle_ = handle;
+
+ if(handle.isNull())
+ gslDHandle_ = GSL::DataHandle::null();
+ else
+ {
+ gslDHandle_ = getDHandle(dhandle_);
+
+ if(gslDHandle_.isNull())
+ {
+ arts_debug("ERROR: could not get internal GSL::DataHandle!");
+ finished(true); // FIXME: can this happen?
+ }
+ else
+ {
+ errno_ = gslDHandle_.open();
+ if(errno_)
+ arts_debug("DataHandlePlay got error from GSL::DataHandle.open(): '%s'",
+ strerror(errno_));
+ }
+ }
+ }
+
+ void streamInit()
+ {
+ if(!gslDHandle_.isNull() && !wosc_)
+ {
+ if(!wchunk_)
+ createWaveChunk();
+ configureWaveOsc();
+ }
+ }
+
+ float mixerFrequency() { return wosc_ ? wosc_->mix_freq : 0; }
+ void mixerFrequency(float f)
+ {
+ if(wchunk_)
+ arts_warning("DataHandlePlay: cannot change mixerFrequency after start of sound processing!");
+
+ if(mixerFrequency() != f)
+ {
+ mixerFrequency_ = f;
+ mixerFrequency_changed(f);
+ }
+ }
+
+ long channelIndex() { return channelIndex_; }
+ void channelIndex(long ci)
+ {
+ if(channelIndex_ != ci)
+ {
+ channelIndex_ = ci;
+ if(wosc_)
+ {
+ GslWaveOscConfig config = wosc_->config;
+ config.channel = ci;
+ gsl_wave_osc_config(wosc_, &config);
+ }
+ channelIndex_changed(ci);
+ }
+ }
+
+ float speed() { return speed_; }
+ void speed(float s)
+ {
+ if(speed_ != s)
+ {
+ speed_ = s;
+ if(wosc_)
+ {
+ GslWaveOscConfig config = wosc_->config;
+ config.cfreq = OSCILLATOR_FREQUENCY * speed();
+ gsl_wave_osc_config(wosc_, &config);
+ }
+ speed_changed(s);
+ }
+ }
+
+ long pos() { return wosc_ ? wosc_->block.offset : 0; }
+ void pos(long p)
+ {
+ if(pos() != p)
+ {
+ GslWaveOscConfig config = wosc_->config;
+ config.start_offset = p;
+ gsl_wave_osc_config(wosc_, &config);
+ pos_changed(p);
+ }
+ }
+
+ bool finished() { return finished_; }
+ void finished(bool f)
+ {
+ if(finished_ != f)
+ {
+ finished_ = f;
+ finished_changed(f);
+ }
+ }
+
+ bool paused() { return paused_; }
+ void paused(bool p)
+ {
+ paused_ = p;
+ }
+
+ void deleteWaveChunk()
+ {
+ deleteWaveOsc();
+
+ if(wchunk_)
+ {
+ arts_debug("DataHandlePlay_impl: close()ing gsl_wave_chunk");
+ gsl_wave_chunk_close(wchunk_);
+ gsl_wave_chunk_unref(wchunk_);
+ wchunk_ = NULL;
+ }
+ }
+
+ void createWaveChunk()
+ {
+ deleteWaveChunk();
+
+ if(!gslDHandle_.isNull() && gslDHandle_.isOpen())
+ {
+ GslDataCache *dcache = gslDHandle_.createGslDataCache();
+ if(!dcache)
+ {
+ arts_debug("FATAL: creating data cache failed!");
+ finished(true); // FIXME: can this happen?
+ }
+ else
+ {
+ wchunk_ =
+ gsl_wave_chunk_new(dcache,
+ OSCILLATOR_FREQUENCY,
+ mixerFrequency_,
+ GSL_WAVE_LOOP_NONE,
+ 0, 0, 0);
+ arts_debug("DataHandlePlay_impl: open()ing gsl_wave_chunk");
+ wchunkError_ = gsl_wave_chunk_open(wchunk_);
+ gsl_data_cache_unref(dcache);
+ }
+ }
+ }
+
+ void deleteWaveOsc()
+ {
+ if(wosc_)
+ {
+ gsl_wave_osc_shutdown(wosc_);
+ delete wosc_;
+ wosc_ = NULL;
+ }
+ }
+
+ void configureWaveOsc()
+ {
+ if(wchunk_)
+ {
+ GslWaveOscConfig config;
+ memset(&config, 0, sizeof (GslWaveOscConfig));
+ config.start_offset = 0;
+ config.play_dir = 1;
+ config.wchunk_data = (gpointer)wchunk_;
+ config.wchunk_from_freq = &const_wchunk_from_freq;
+ config.channel = channelIndex();
+ config.cfreq = OSCILLATOR_FREQUENCY * speed();
+
+ if(!wosc_)
+ {
+ wosc_ = new GslWaveOscData();
+ gsl_wave_osc_init(wosc_);
+ }
+
+ gsl_wave_osc_config(wosc_, &config);
+ }
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ if(!paused_ && wchunk_)
+ {
+ if (!gsl_wave_osc_process(wosc_, samples, 0, 0, 0, outvalue))
+ arts_debug("gsl_wave_osc_process failed.");
+ finished(wosc_->done);
+ }
+ else
+ for(unsigned long i = 0; i < samples; i++)
+ outvalue[i] = 0.f;
+ /*
+ unsigned long haveSamples = 0;
+
+ while(haveSamples != samples)
+ {
+ long n = min(gslDHandle_.valueCount() - pos_, samples - haveSamples);
+ long got = gslDHandle_.isNull() ?
+ 0 : gslDHandle_.read(pos_, n, &outvalue[haveSamples]);
+ if(got <= 0)
+ {
+ for(unsigned long i = haveSamples; i < samples; i++)
+ outvalue[i] = 0.f;
+ break;
+ }
+ pos_ += got;
+ haveSamples += got;
+ }
+ finished(pos_ >= gslDHandle_.valueCount());
+ */
+ }
+
+ DataHandlePlay clone()
+ {
+ arts_debug("DataHandlePlay_impl: clone()ing myself");
+ DataHandlePlay_impl *result = new DataHandlePlay_impl();
+
+ result->dhandle_ = dhandle_;
+ result->gslDHandle_ = gslDHandle_;
+ result->errno_ = errno_;
+
+ createWaveChunk();
+ if(wchunk_)
+ {
+ result->wchunk_ = wchunk_;
+ gsl_wave_chunk_ref(wchunk_);
+ result->wchunkError_ = gsl_wave_chunk_open(wchunk_);
+ }
+ else
+ result->wchunkError_ = wchunkError_;
+
+ result->mixerFrequency_ = mixerFrequency_;
+ result->channelIndex_ = channelIndex_;
+ result->speed_ = speed_;
+ result->pos_ = pos_;
+ result->finished_ = finished_;
+ result->paused_ = paused_;
+
+ return DataHandlePlay::_from_base(result);
+ }
+};
+
+class WaveDataHandle_impl : virtual public DataHandle_impl,
+ virtual public WaveDataHandle_skel
+{
+ GSL::WaveDataHandle wdhandle_;
+
+public:
+ WaveDataHandle_impl() : wdhandle_(GSL::WaveDataHandle::null()) {}
+
+ float mixerFrequency()
+ {
+ return wdhandle_.mixerFrequency();
+ }
+
+ float oscillatorFrequency()
+ {
+ return wdhandle_.oscillatorFrequency();
+ }
+
+ bool load(const string& filename)
+ {
+ return load(filename, 0, 0);
+ }
+
+ bool load(const string& filename,
+ long waveIndex,
+ long chunkIndex)
+ {
+ wdhandle_ = GSL::WaveDataHandle(filename, waveIndex, chunkIndex);
+ if(dhandle_.isOpen())
+ dhandle_.close();
+ dhandle_ = wdhandle_;
+ errno_ = dhandle_.isNull() ? 0 : dhandle_.open();
+ return isLoaded();
+ }
+
+ bool isLoaded()
+ {
+ if(wdhandle_.isNull())
+ return false;
+
+ return !wdhandle_.error();
+ }
+
+ DataHandlePlay createPlayer()
+ {
+ DataHandlePlay_impl *result= new DataHandlePlay_impl();
+
+ result->mixerFrequency(mixerFrequency());
+ result->handle(WaveDataHandle::_from_base(this->_copy()));
+
+ return DataHandlePlay::_from_base(result);
+ }
+};
+
+REGISTER_IMPLEMENTATION(DataHandlePlay_impl);
+REGISTER_IMPLEMENTATION(DataHandle_impl);
+REGISTER_IMPLEMENTATION(CroppedDataHandle_impl);
+REGISTER_IMPLEMENTATION(CutDataHandle_impl);
+REGISTER_IMPLEMENTATION(ReversedDataHandle_impl);
+REGISTER_IMPLEMENTATION(WaveDataHandle_impl);
+
+}
diff --git a/flow/fft.c b/flow/fft.c
new file mode 100644
index 0000000..15c821f
--- /dev/null
+++ b/flow/fft.c
@@ -0,0 +1,32 @@
+#include "gsl/gslfft.h"
+#include "fft.h"
+
+void arts_fft_float (
+ unsigned NumSamples,
+ int InverseTransform,
+ float *RealIn,
+ float *ImagIn,
+ float *RealOut,
+ float *ImagOut )
+{
+ double *ri_in = g_newa(double, NumSamples*4);
+ double *ri_out = ri_in + NumSamples*2;
+ unsigned int i;
+
+ for(i = 0; i < NumSamples; i++)
+ {
+ ri_in[2*i] = RealIn[i];
+ ri_in[2*i+1] = (ImagIn?ImagIn[i]:0.0);
+ }
+
+ if(InverseTransform == 0)
+ gsl_power2_fftac (NumSamples, ri_in, ri_out);
+ else
+ gsl_power2_fftsc (NumSamples, ri_in, ri_out);
+
+ for(i = 0; i < NumSamples; i++)
+ {
+ RealOut[i] = ri_out[2*i];
+ ImagOut[i] = ri_out[2*i+1];
+ }
+}
diff --git a/flow/fft.h b/flow/fft.h
new file mode 100644
index 0000000..009f764
--- /dev/null
+++ b/flow/fft.h
@@ -0,0 +1,32 @@
+#ifndef ARTS_FFT_H
+#define ARTS_FFT_H
+
+/*
+ * BC - Status (2002-03-08): arts_fft_float
+ *
+ * This fft interface should be obsoleted in the future in favour of one
+ * exploiting the capabilities of gsl fully. However, it will be kept binary
+ * compatible to avoid everybody to reimplement/duplicate their own fft.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * performs an fft
+ */
+void arts_fft_float (
+ unsigned NumSamples, /* must be a power of 2 */
+ int InverseTransform, /* 0=forward FFT, 1=inverse FFT */
+ float *RealIn, /* array of input's real samples */
+ float *ImaginaryIn, /* array of input's imag samples */
+ float *RealOut, /* array of output's reals */
+ float *ImaginaryOut ); /* array of output's imaginaries */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ARTS_FFT_H */
diff --git a/flow/gsl/Makefile.am b/flow/gsl/Makefile.am
new file mode 100644
index 0000000..41a4dab
--- /dev/null
+++ b/flow/gsl/Makefile.am
@@ -0,0 +1,24 @@
+
+EXTRA_DIST =
+CLEANFILES =
+MAINTAINERCLEANFILES =
+
+gslincludedir=$(includedir)/arts/gsl
+include gslmakefile.inc
+
+INCLUDES = -I$(top_srcdir)/flow -I$(top_builddir)/flow -I$(top_srcdir)/mcop -I$(top_builddir)/mcop -I$(top_builddir) $(all_includes)
+AM_CFLAGS = $(GSL_CFLAGS)
+
+noinst_LTLIBRARIES = libgsl.la
+
+libgsl_la_SOURCES = $(GSL_C_SRC) gslfilehash.c gslartsthreads.cc
+libgsl_la_LIBADD = $(top_builddir)/mcop/libmcop.la -lm $(LIBPOSIX4) $(GSL_LIBS) $(LIB_POLL) $(GLIB_LIBADD)
+libgsl_la_LDFLAGS = -no-undefined $(all_libraries)
+
+#noinst_PROGRAMS = $(GSL_NOINST_PROGS)
+
+GSL_progs_ldadd = libgsl.la -lm $(LIBPTHREAD)
+
+GSL_cc_dummy = dummy.cc
+$(srcdir)/dummy.cc: gslconfig.h
+
diff --git a/flow/gsl/arts-patches b/flow/gsl/arts-patches
new file mode 100644
index 0000000..e5bf761
--- /dev/null
+++ b/flow/gsl/arts-patches
@@ -0,0 +1,73 @@
+Those are aRts/KDE-specific changes which won't be backfolded into the
+original GSL repository but are needed here:
+
+--- gsldatahandle-vorbis.c Tue Jul 30 01:26:06 2002
++++ /usr/src/arts.dh/flow/gsl/gsldatahandle-vorbis.c Tue Jul 30 17:46:33 2002
+@@ -19,4 +19,5 @@
+ #include "gsldatahandle-vorbis.h"
+
++#if GSL_HAVE_OGGVORBIS
+ #include "gslfilehash.h"
+ #include <ogg/ogg.h>
+@@ -239,5 +240,9 @@ read_packet (VorbisHandle *vhandle)
+
+ vhandle->pcm_pos = ov_pcm_tell (&vhandle->ofile) - vhandle->soffset;
++#if GSL_HAVE_OGGVORBIS_RC3
+ vhandle->pcm_length = ov_read_float (&vhandle->ofile, &pcm, &stream_id);
++#else
++ vhandle->pcm_length = ov_read_float (&vhandle->ofile, &pcm, (~0U>>1), &stream_id);
++#endif
+ if (vhandle->pcm_pos < 0 || vhandle->pcm_length < 0 || stream_id != vhandle->stream)
+ {
+@@ -368,2 +373,4 @@ gsl_data_handle_new_ogg_vorbis (const gc
+ }
+ }
++#endif /* GSL_HAVE_OGGVORBIS */
++
+--- gsldefs.h Wed Jul 24 05:50:17 2002
++++ /usr/src/arts.dh/flow/gsl/gsldefs.h Tue Jul 30 02:29:55 2002
+@@ -20,5 +20,8 @@
+ #define __GSL_DEFS_H__
+
+-#ifdef GSL_WANT_GLIB_WRAPPER
++/* configure checks */
++#include <gsl/gslconfig.h>
++
++#if GSL_USE_GSL_GLIB
+ #include <gsl/gslglib.h> /* GSL just uses a certain subset of GLib */
+ #else
+@@ -26,9 +29,4 @@
+ #endif
+
+-
+-/* configure checks */
+-#include <gsl/gslconfig.h>
+-
+-
+ #ifdef __cplusplus
+ extern "C" {
+@@ -103,5 +101,5 @@ typedef void (*GslModuleFreeFunc)
+
+ #if defined (BSE_COMPILATION) || defined (BSE_PLUGIN_FALLBACK) \
+- || defined (GSL_WANT_GLIB_WRAPPER) || defined (GSL_EXTENSIONS)
++ || (GSL_USE_GSL_GLIB) || defined (GSL_EXTENSIONS)
+ # define if_expect(cond) if (GSL_GCC_EXPECT (cond))
+ # define if_reject(cond) if (GSL_GCC_REJECT (cond))
+--- gslloader-oggvorbis.c Tue Jul 30 01:26:06 2002
++++ /usr/src/arts.dh/flow/gsl/gslloader-oggvorbis.c Tue Jul 30 05:06:32 2002
+@@ -19,4 +19,5 @@
+ #include "gsl/gslloader.h"
+
++#if GSL_HAVE_OGGVORBIS
+ #include <gsl/gsldatahandle.h>
+ #include "gsldatahandle-vorbis.h"
+@@ -168,2 +169,9 @@ _gsl_init_loader_oggvorbis (void)
+ gsl_loader_register (&loader);
+ }
++#else
++void
++_gsl_init_loader_oggvorbis (void)
++{
++ /* dummy */
++}
++#endif /* GSL_HAVE_OGGVORBIS */
diff --git a/flow/gsl/configure.in.in b/flow/gsl/configure.in.in
new file mode 100644
index 0000000..3b147b9
--- /dev/null
+++ b/flow/gsl/configure.in.in
@@ -0,0 +1,224 @@
+dnl Portability defines that help interoperate with classic and modern autoconfs
+ifdef([AC_TR_SH],[
+define([GLIB_TR_SH],[AC_TR_SH([$1])])
+define([GLIB_TR_CPP],[AC_TR_CPP([$1])])
+], [
+define([GLIB_TR_SH],
+ [patsubst(translit([[$1]], [*+], [pp]), [[^a-zA-Z0-9_]], [_])])
+define([GLIB_TR_CPP],
+ [patsubst(translit([[$1]],
+ [*abcdefghijklmnopqrstuvwxyz],
+ [PABCDEFGHIJKLMNOPQRSTUVWXYZ]),
+ [[^A-Z0-9_]], [_])])
+])
+
+
+dnl GLIB_SIZEOF (INCLUDES, TYPE, ALIAS [, CROSS-SIZE])
+AC_DEFUN([GLIB_SIZEOF],
+[pushdef([glib_Sizeof], GLIB_TR_SH([glib_cv_sizeof_$3]))dnl
+AC_CACHE_CHECK([size of $2], glib_Sizeof,
+[AC_TRY_RUN([#include <stdio.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+$1
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof($2));
+ exit(0);
+}],
+ [glib_Sizeof=`cat conftestval` dnl''
+],
+ [glib_Sizeof=0],
+ ifelse([$4], [], [], [glib_Sizeof=$4]))])
+AC_DEFINE_UNQUOTED(GLIB_TR_CPP(glib_sizeof_$3), [$[]glib_Sizeof], [Size of $3])
+popdef([glib_Sizeof])dnl
+])
+
+AC_DEFUN([AC_GSL_REQUIREMENTS],
+[
+ dnl === Ogg/Vorbis check ===
+ AC_ARG_ENABLE(vorbis,
+ [ --disable-arts-vorbis disable arts Ogg Vorbis support],
+ [arts_want_vorbis="$enableval"],[arts_want_vorbis="yes"])
+
+ if test "$arts_want_vorbis" = "yes"; then
+ ov_headers=0
+ AC_CHECK_LIB(vorbisfile, ov_read_float,
+ [KDE_CHECK_HEADER(ogg/ogg.h, ov_headers=`expr $ov_headers + 1`)]
+ [KDE_CHECK_HEADER(vorbis/vorbisfile.h, ov_headers=`expr $ov_headers + 1`)]
+ [KDE_CHECK_HEADER(vorbis/vorbisenc.h, ov_headers=`expr $ov_headers + 1`)]
+ ,
+ ov_headers=0, -lvorbisenc -lvorbis -logg)
+ if test $ov_headers = 3 ; then
+ GSL_LIBS="$GSL_LIBS -lvorbisfile -lvorbisenc -lvorbis -logg"
+ GSL_HAVE_OGGVORBIS=1
+ else
+ GSL_HAVE_OGGVORBIS=0
+ fi
+ dnl AC_DEFINE(GSL_HAVE_OGGVORBIS,1,[Define if you want Ogg Vorbis support unconditionally])
+ else
+ GSL_HAVE_OGGVORBIS=0
+ dnl AC_MSG_WARN([failed to detect Ogg/Vorbis library (>=1.0rc3) or headers])
+ fi
+ AC_SUBST(GSL_HAVE_OGGVORBIS)
+
+ dnl check for ov_read_float parameter count (differs in 1.0 vs. rc3)
+ if test $GSL_HAVE_OGGVORBIS = 1; then
+ AC_MSG_CHECKING([for ov_read_float() from rc3])
+ AC_TRY_COMPILE([
+ #include <vorbis/vorbisfile.h>
+ ], [
+ ov_read_float(0,0,0);
+ ], [
+ GSL_HAVE_OGGVORBIS_RC3=1
+ AC_MSG_RESULT(yes)
+ ], [
+ GSL_HAVE_OGGVORBIS_RC3=0
+ AC_MSG_RESULT(no)
+ ])
+ AC_SUBST(GSL_HAVE_OGGVORBIS_RC3)
+ fi
+
+ dnl === libmad MPEG decoder check ===
+ AC_ARG_ENABLE(libmad,
+ [ --disable-libmad disable arts MAD mp3 decoder support],
+ [arts_want_libmad="$enableval"],[arts_want_libmad="yes"])
+
+ if test "$arts_want_libmad" = "yes"; then
+ mad_detect=0
+ AC_CHECK_LIB(mad, mad_synth_frame,
+ [AC_CHECK_HEADER(mad.h, mad_detect=1)]
+ ,
+ mad_detect=0, -lmad)
+ if test $mad_detect = 1 ; then
+ GSL_LIBS="$GSL_LIBS -lmad"
+ GSL_HAVE_LIBMAD=1
+ else
+ dnl AC_MSG_WARN([failed to detect libmad (MPEG I-III audio decoder) or headers])
+ GSL_HAVE_LIBMAD=0
+ fi
+ else
+ dnl AC_MSG_WARN([failed to detect libmad (MPEG I-III audio decoder) or headers])
+ GSL_HAVE_LIBMAD=0
+ fi
+ AC_SUBST(GSL_HAVE_LIBMAD)
+
+ dnl === Check library requirements ===
+ AC_MSG_CHECKING([the required GSL-Loader library set])
+ if true; then dnl echo $GSL_LIBS | grep ".*-lvorbis.*" >/dev/null ; then
+ AC_MSG_RESULT([complete])
+ else
+ AC_MSG_RESULT([])
+ AC_MSG_ERROR([Ogg/Vorbis is missing, but required])
+ fi
+ AC_SUBST(GSL_LIBS)
+
+ dnl === sizeof types ===
+ GLIB_SIZEOF([#include <pthread.h>], pthread_mutex_t, pth_mutex_t)
+ GSL_SIZEOF_PTH_MUTEX_T="$glib_cv_sizeof_pth_mutex_t"
+ AC_SUBST(GSL_SIZEOF_PTH_MUTEX_T)
+ GLIB_SIZEOF([#include <pthread.h>], pthread_cond_t, pth_cond_t)
+ GSL_SIZEOF_PTH_COND_T="$glib_cv_sizeof_pth_cond_t"
+ AC_SUBST(GSL_SIZEOF_PTH_COND_T)
+ GLIB_SIZEOF([#include <inttypes.h>], intmax_t, std_intmax_t)
+ GSL_SIZEOF_STD_INTMAX_T="$glib_cv_sizeof_std_intmax_t"
+ AC_SUBST(GSL_SIZEOF_STD_INTMAX_T)
+
+ dnl === pthread_mutexattr_settype ===
+ AC_MSG_CHECKING([for pthread_mutexattr_settype()])
+ AC_TRY_COMPILE([
+ #define _XOPEN_SOURCE 500
+ #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;
+ ],
+ GSL_HAVE_MUTEXATTR_SETTYPE=1
+ AC_MSG_RESULT(yes)
+ ,
+ GSL_HAVE_MUTEXATTR_SETTYPE=0
+ AC_MSG_RESULT(no)
+ )
+ AC_SUBST(GSL_HAVE_MUTEXATTR_SETTYPE)
+])
+
+AC_DEFUN([AC_GSL_GLIB_REQUIREMENTS],
+[
+ AC_CHECK_FUNCS(getcwd)
+ AC_FUNC_ALLOCA
+
+dnl **********************
+dnl *** va_copy checks ***
+dnl **********************
+dnl we currently check for all three va_copy possibilities, so we get
+dnl all results in config.log for bug reports.
+AC_CACHE_CHECK([for an implementation of va_copy()],glib_cv_va_copy,[
+ AC_TRY_RUN([
+ #include <stdarg.h>
+ void f (int i, ...) {
+ va_list args1, args2;
+ va_start (args1, i);
+ va_copy (args2, args1);
+ if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+ exit (1);
+ va_end (args1); va_end (args2);
+ }
+ int main() {
+ f (0, 42);
+ return 0;
+ }],
+ [glib_cv_va_copy=yes],
+ [glib_cv_va_copy=no],
+ [])
+])
+AC_CACHE_CHECK([for an implementation of __va_copy()],glib_cv___va_copy,[
+ AC_TRY_RUN([
+ #include <stdarg.h>
+ void f (int i, ...) {
+ va_list args1, args2;
+ va_start (args1, i);
+ __va_copy (args2, args1);
+ if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+ exit (1);
+ va_end (args1); va_end (args2);
+ }
+ int main() {
+ f (0, 42);
+ return 0;
+ }],
+ [glib_cv___va_copy=yes],
+ [glib_cv___va_copy=no],
+ [])
+])
+
+if test "x$glib_cv_va_copy" = "xyes"; then
+ g_va_copy_func=va_copy
+else if test "x$glib_cv___va_copy" = "xyes"; then
+ g_va_copy_func=__va_copy
+fi
+fi
+])
+
+AC_GSL_REQUIREMENTS
+AC_GSL_GLIB_REQUIREMENTS
+
+dnl get rid of lots and lots of useless warnings
+
+GSL_CFLAGS="$CFLAGS"
+for warn in -W -Wshadow -pedantic # -Wwrite-strings
+do
+ GSL_CFLAGS="`echo $GSL_CFLAGS | sed 's/ '$warn' / /g'`"
+done
+AC_SUBST(GSL_CFLAGS)
+
+dnl enable aRts version of glib / thread support
+
+GSL_USE_GSL_GLIB=1
+GSL_USE_ARTS_THREADS=1
+AC_SUBST(GSL_USE_GSL_GLIB)
+AC_SUBST(GSL_USE_ARTS_THREADS)
diff --git a/flow/gsl/dummy.cc b/flow/gsl/dummy.cc
new file mode 100644
index 0000000..9fde279
--- /dev/null
+++ b/flow/gsl/dummy.cc
@@ -0,0 +1,3 @@
+/* this is a C++ dummy source to force c++ linkage of the examples */
+
+namespace Arts { int arts_flow_gsl_dummy = 0; }
diff --git a/flow/gsl/gbsearcharray.h b/flow/gsl/gbsearcharray.h
new file mode 100644
index 0000000..df06231
--- /dev/null
+++ b/flow/gsl/gbsearcharray.h
@@ -0,0 +1,292 @@
+/* GBSearchArray - Binary Searchable Array implementation
+ * Copyright (C) 2000-2002 Tim Janik
+ *
+ * This software is provided "as is"; redistribution and modification
+ * is permitted, provided that the following disclaimer is retained.
+ *
+ * This software 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.
+ * In no event shall the authors or contributors be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential
+ * damages (including, but not limited to, procurement of substitute
+ * goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability, whether
+ * in contract, strict liability, or tort (including negligence or
+ * otherwise) arising in any way out of the use of this software, even
+ * if advised of the possibility of such damage.
+ */
+#ifndef __G_BSEARCH_ARRAY_H__
+#define __G_BSEARCH_ARRAY_H__
+
+#include <gsl/gsldefs.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* this implementation is intended to be usable in third-party code
+ * simply by pasting the contents of this file. as such, the
+ * implementation needs to be self-contained within this file.
+ */
+
+/* convenience macro to avoid signed overflow for value comparisons */
+#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) > (v2) ? +1 : (v1) == (v2) ? 0 : -1)
+
+
+/* --- typedefs --- */
+typedef gint (*GBSearchCompareFunc) (gconstpointer bsearch_node1, /* key */
+ gconstpointer bsearch_node2);
+typedef enum
+{
+ G_BSEARCH_ARRAY_ALIGN_POWER2 = 1 << 0, /* memory is power2 aligned */
+ G_BSEARCH_ARRAY_FORCE_SHRINK = 1 << 1 /* removal shrinks with realloc() */
+} GBSearchArrayFlags;
+
+
+/* --- structures --- */
+typedef struct
+{
+ guint sizeof_node;
+ GBSearchCompareFunc cmp_nodes;
+ guint flags;
+} GBSearchConfig;
+typedef union
+{
+ guint n_nodes;
+ /*< private >*/
+ gpointer alignment_dummy1;
+ glong alignment_dummy2;
+ gdouble alignment_dummy3;
+} GBSearchArray;
+
+
+/* --- public API --- */
+static inline GBSearchArray* g_bsearch_array_create (const GBSearchConfig *bconfig);
+static inline gpointer g_bsearch_array_get_nth (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ guint nth);
+static inline guint g_bsearch_array_get_index (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ gconstpointer node_in_array);
+static inline GBSearchArray* g_bsearch_array_remove (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ guint index);
+/* preserve uninitialized space at index for node insertion
+ */
+static inline GBSearchArray* g_bsearch_array_grow (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ guint index);
+/* insert key_node into array, or if it exists, replace
+ * the existing node's contents with key_node
+ */
+static inline GBSearchArray* g_bsearch_array_insert (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ gconstpointer key_node);
+static inline void g_bsearch_array_free (GBSearchArray *barray,
+ const GBSearchConfig *bconfig);
+#define g_bsearch_array_get_n_nodes(barray) (((GBSearchArray*) (barray))->n_nodes)
+
+/* g_bsearch_array_lookup():
+ * return NULL or exact match node
+ */
+#define g_bsearch_array_lookup(barray, bconfig, key_node) \
+ g_bsearch_array_lookup_fuzzy ((barray), (bconfig), (key_node), 0)
+
+/* g_bsearch_array_lookup_sibling():
+ * return NULL for barray->n_nodes==0, otherwise return the
+ * exact match node, or, if there's no such node, return the
+ * node last visited, which is pretty close to an exact match
+ * (will be one off into either direction).
+ */
+#define g_bsearch_array_lookup_sibling(barray, bconfig, key_node) \
+ g_bsearch_array_lookup_fuzzy ((barray), (bconfig), (key_node), 1)
+
+/* g_bsearch_array_lookup_insertion():
+ * return NULL for barray->n_nodes==0 or exact match, otherwise
+ * return the node where key_node should be inserted (may be one
+ * after end, i.e. g_bsearch_array_get_index(result) <= barray->n_nodes).
+ */
+#define g_bsearch_array_lookup_insertion(barray, bconfig, key_node) \
+ g_bsearch_array_lookup_fuzzy ((barray), (bconfig), (key_node), 2)
+
+
+
+/* --- implementation --- */
+/* helper macro to cut down realloc()s */
+#ifdef DISABLE_MEM_POOLS
+#define G_BSEARCH_UPPER_POWER2(n) (n)
+#else /* !DISABLE_MEM_POOLS */
+#define G_BSEARCH_UPPER_POWER2(n) ((n) ? 1 << g_bit_storage ((n) - 1) : 0)
+#endif /* !DISABLE_MEM_POOLS */
+#define G_BSEARCH_ARRAY_NODES(barray) (((guint8*) (barray)) + sizeof (GBSearchArray))
+static inline GBSearchArray*
+g_bsearch_array_create (const GBSearchConfig *bconfig)
+{
+ GBSearchArray *barray;
+ guint size;
+
+ g_return_val_if_fail (bconfig != NULL, NULL);
+
+ size = sizeof (GBSearchArray) + bconfig->sizeof_node;
+ if (bconfig->flags & G_BSEARCH_ARRAY_ALIGN_POWER2)
+ size = G_BSEARCH_UPPER_POWER2 (size);
+ barray = g_realloc (NULL, size);
+ memset (barray, 0, sizeof (GBSearchArray));
+
+ return barray;
+}
+static inline gpointer
+g_bsearch_array_lookup_fuzzy (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ gconstpointer key_node,
+ const guint sibling_or_after);
+static inline gpointer
+g_bsearch_array_lookup_fuzzy (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ gconstpointer key_node,
+ const guint sibling_or_after)
+{
+ GBSearchCompareFunc cmp_nodes = bconfig->cmp_nodes;
+ guint8 *check = NULL, *nodes = G_BSEARCH_ARRAY_NODES (barray);
+ guint n_nodes = barray->n_nodes, offs = 0;
+ guint sizeof_node = bconfig->sizeof_node;
+ gint cmp = 0;
+
+ while (offs < n_nodes)
+ {
+ guint i = (offs + n_nodes) >> 1;
+
+ check = nodes + i * sizeof_node;
+ cmp = cmp_nodes (key_node, check);
+ if (cmp == 0)
+ return sibling_or_after > 1 ? NULL : check;
+ else if (cmp < 0)
+ n_nodes = i;
+ else /* (cmp > 0) */
+ offs = i + 1;
+ }
+
+ /* check is last mismatch, cmp > 0 indicates greater key */
+ return !sibling_or_after ? NULL : (sibling_or_after > 1 && cmp > 0) ? check + sizeof_node : check;
+}
+static inline gpointer
+g_bsearch_array_get_nth (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ guint nth)
+{
+ return (nth < barray->n_nodes ?
+ G_BSEARCH_ARRAY_NODES (barray) + nth * bconfig->sizeof_node :
+ NULL);
+}
+static inline guint
+g_bsearch_array_get_index (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ gconstpointer node_in_array)
+{
+ guint distance = ((guint8*) node_in_array) - G_BSEARCH_ARRAY_NODES (barray);
+
+ g_return_val_if_fail (node_in_array != NULL, barray->n_nodes);
+
+ distance /= bconfig->sizeof_node;
+
+ return MIN (distance, barray->n_nodes + 1); /* may return one after end */
+}
+static inline GBSearchArray*
+g_bsearch_array_grow (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ guint index)
+{
+ guint old_size = barray->n_nodes * bconfig->sizeof_node;
+ guint new_size = old_size + bconfig->sizeof_node;
+ guint8 *node;
+
+ g_return_val_if_fail (index <= barray->n_nodes, NULL);
+
+ if (bconfig->flags & G_BSEARCH_ARRAY_ALIGN_POWER2)
+ {
+ new_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + new_size);
+ old_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + old_size);
+ if (old_size != new_size)
+ barray = g_realloc (barray, new_size);
+ }
+ else
+ barray = g_realloc (barray, sizeof (GBSearchArray) + new_size);
+ node = G_BSEARCH_ARRAY_NODES (barray) + index * bconfig->sizeof_node;
+ g_memmove (node + bconfig->sizeof_node, node, (barray->n_nodes - index) * bconfig->sizeof_node);
+ barray->n_nodes += 1;
+ return barray;
+}
+static inline GBSearchArray*
+g_bsearch_array_insert (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ gconstpointer key_node)
+{
+ guint8 *node;
+
+ if (!barray->n_nodes)
+ {
+ barray = g_bsearch_array_grow (barray, bconfig, 0);
+ node = G_BSEARCH_ARRAY_NODES (barray);
+ }
+ else
+ {
+ node = g_bsearch_array_lookup_insertion (barray, bconfig, key_node);
+ if (node)
+ {
+ guint index = g_bsearch_array_get_index (barray, bconfig, node);
+
+ /* grow and insert */
+ barray = g_bsearch_array_grow (barray, bconfig, index);
+ node = G_BSEARCH_ARRAY_NODES (barray) + index * bconfig->sizeof_node;
+ }
+ else /* replace (relookup is ok, replace is comparatively cheap anyways) */
+ node = g_bsearch_array_lookup (barray, bconfig, key_node);
+ }
+ memcpy (node, key_node, bconfig->sizeof_node);
+ return barray;
+}
+static inline GBSearchArray*
+g_bsearch_array_remove (GBSearchArray *barray,
+ const GBSearchConfig *bconfig,
+ guint index)
+{
+ guint8 *node;
+
+ g_return_val_if_fail (index < barray->n_nodes, NULL);
+
+ barray->n_nodes -= 1;
+ node = G_BSEARCH_ARRAY_NODES (barray) + index * bconfig->sizeof_node;
+ g_memmove (node, node + bconfig->sizeof_node, (barray->n_nodes - index) * bconfig->sizeof_node);
+ if (bconfig->flags & G_BSEARCH_ARRAY_FORCE_SHRINK)
+ {
+ guint new_size = barray->n_nodes * bconfig->sizeof_node;
+ guint old_size = new_size + bconfig->sizeof_node;
+
+ if (bconfig->flags & G_BSEARCH_ARRAY_ALIGN_POWER2)
+ {
+ new_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + new_size);
+ old_size = G_BSEARCH_UPPER_POWER2 (sizeof (GBSearchArray) + old_size);
+ if (old_size != new_size)
+ barray = g_realloc (barray, new_size);
+ }
+ else
+ barray = g_realloc (barray, sizeof (GBSearchArray) + new_size);
+ }
+ return barray;
+}
+static inline void
+g_bsearch_array_free (GBSearchArray *barray,
+ const GBSearchConfig *bconfig)
+{
+ g_return_if_fail (barray != NULL);
+
+ g_free (barray);
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !__G_BSEARCH_ARRAY_H__ */
diff --git a/flow/gsl/gsl-fftconf.sh b/flow/gsl/gsl-fftconf.sh
new file mode 100755
index 0000000..71f33c3
--- /dev/null
+++ b/flow/gsl/gsl-fftconf.sh
@@ -0,0 +1,468 @@
+#!/bin/sh
+# GSL-GENFFT - Power2 FFT C Code Generator
+# Copyright (C) 2001 Tim Janik
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+# include files
+echo "#include $2"
+echo "#include <math.h>"
+
+MKFFT="$1"
+IEEE_TYPE="double"
+OPTIONS="--double"
+
+# provide macros and inline stubs
+$MKFFT $OPTIONS 0
+
+#
+# generate small fft sizes, seperating stage 2
+#
+for dir in --analysis --synthesis ; do
+ DOPT="$OPTIONS --skip-macros $dir"
+ echo "Generating FFT functions: $dir" >&2
+ $MKFFT $DOPT 2 F # standalone fft2
+ $MKFFT $DOPT 4 S F # reusable fft4
+ $MKFFT $DOPT 4 F X # standalone fft4
+ $MKFFT $DOPT 8 s F F # reusable fft8 w/o input fft2
+ $MKFFT $DOPT 8 F s X # standalone fft8
+ $MKFFT $DOPT 16 s F F F # reusable fft16
+ $MKFFT $DOPT 16 F s s X # standalone fft16
+ $MKFFT $DOPT 32 s F F F F
+ $MKFFT $DOPT 32 F s s s X
+ $MKFFT $DOPT 64 s R R R R F # reusable fft64
+ $MKFFT $DOPT 64 F s s s s X # standalone fft64
+ $MKFFT $DOPT 128 s R R R R R F # reusable fft128
+ $MKFFT $DOPT 128 L s s s s s X #
+ $MKFFT $DOPT 256 s s s s s s X T # reuse fft128
+ $MKFFT $DOPT 256 L s s s s s s X #
+ $MKFFT $DOPT 512 s s s s s s X T T # reuse fft128
+ $MKFFT $DOPT 512 L s s s s s s s X # fft512
+ $MKFFT $DOPT 1024 s s s s s s s s X L #
+ $MKFFT $DOPT 1024 L s s s s s s s s X #
+ $MKFFT $DOPT 2048 s s s s s s s s X L L # reusable fft2048
+ $MKFFT $DOPT 2048 L s s s s s s s s s X #
+ $MKFFT $DOPT 4096 s s s s s s s s s s X L # reuses fft2048
+ $MKFFT $DOPT 4096 L s s s s s s s s s s X # fft4096
+ $MKFFT $DOPT 8192 s s s s s s s s s s s X L # reusable impl. for 8192, reuses 2048
+ $MKFFT $DOPT 8192 L s s s s s s s s s s s X # real impl. for 8192
+done
+
+#
+# generic variable length implementation
+#
+echo "Generating generic FFT function for sizes >8192" >&2
+cat <<__EOF
+
+
+/* public FFT frontends and generic handling of huge fft sizes */
+
+
+static void
+gsl_power2_fftc_big (const unsigned int n_values,
+ const $IEEE_TYPE *rivalues_in,
+ $IEEE_TYPE *rivalues,
+ const int esign)
+{
+ const unsigned int n_values2 = n_values << 1;
+ double theta = esign < 0 ? -3.1415926535897932384626433832795029 : 3.1415926535897932384626433832795029;
+ unsigned int i, block_size = 8192 << 1;
+ double last_sin;
+
+ if (esign > 0)
+ {
+ if (rivalues_in)
+ bitreverse_fft2analysis (n_values, rivalues_in, rivalues);
+ for (i = 0; i < n_values; i += 8192)
+ gsl_power2_fft8192analysis_skip2 (rivalues + (i << 1), rivalues + (i << 1));
+ }
+ else
+ {
+ if (rivalues_in)
+ bitreverse_fft2synthesis (n_values, rivalues_in, rivalues);
+ for (i = 0; i < n_values; i += 8192)
+ gsl_power2_fft8192synthesis_skip2 (rivalues + (i << 1), rivalues + (i << 1));
+ }
+ theta *= (double) 1.0 / 8192.;
+ last_sin = sin (theta);
+
+ /* we're not combining the first and second halves coefficients
+ * in the below loop, since for fft sizes beyond 8192, it'd actually
+ * harm performance due to paging
+ */
+ do
+ {
+ double Dre, Dim, Wre, Wim;
+ unsigned int k, i, half_block = block_size >> 1;
+ unsigned int block_size2 = block_size << 1;
+
+ theta *= 0.5;
+ Dim = last_sin;
+ last_sin = sin (theta);
+ Dre = last_sin * last_sin * -2.;
+
+ /* loop over first coefficient in each block ==> w == {1,0} */
+ for (i = 0; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_10 (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __1, __0);
+ }
+ Wre = Dre + 1.0; /* update Wk */
+ Wim = Dim; /* update Wk */
+ /* loop for every Wk in the first half of each subblock */
+ for (k = 2; k < half_block; k += 2)
+ {
+ /* loop over kth coefficient in each block */
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_XY (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, Dre, Dim); /* update Wk */
+ }
+ /* handle middle coefficient ==> w == {0,+-1} */
+ if (k < block_size)
+ {
+ /* loop over kth coefficient in each block */
+ if (esign > 0)
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_01 (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __0, __1);
+ }
+ else
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_0m (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __0, __1);
+ }
+ /* update Wk */
+ if (esign > 0)
+ {
+ Wre = -Dim;
+ Wim = Dre + 1.0;
+ }
+ else
+ {
+ Wre = Dim;
+ Wim = -Dre - 1.0;
+ }
+ k += 2;
+ }
+ /* loop for every Wk in the second half of each subblock */
+ for (; k < block_size; k += 2)
+ {
+ /* loop over kth coefficient in each block */
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_XY (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, Dre, Dim); /* update Wk */
+ }
+ block_size = block_size2;
+ }
+ while (block_size <= n_values);
+}
+__EOF
+
+
+#
+# public complex fft frontends
+#
+echo "Generating public complex FFT frontends" >&2
+cat <<__EOF
+void
+gsl_power2_fftac (const unsigned int n_values,
+ const $IEEE_TYPE *rivalues_in,
+ $IEEE_TYPE *rivalues_out)
+{
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 1);
+
+ switch (n_values)
+ {
+ case 1: rivalues_out[0] = rivalues_in[0], rivalues_out[1] = rivalues_in[1]; break;
+ case 2: gsl_power2_fft2analysis (rivalues_in, rivalues_out); break;
+ case 4: gsl_power2_fft4analysis (rivalues_in, rivalues_out); break;
+ case 8: gsl_power2_fft8analysis (rivalues_in, rivalues_out); break;
+ case 16: gsl_power2_fft16analysis (rivalues_in, rivalues_out); break;
+ case 32: gsl_power2_fft32analysis (rivalues_in, rivalues_out); break;
+ case 64: gsl_power2_fft64analysis (rivalues_in, rivalues_out); break;
+ case 128: gsl_power2_fft128analysis (rivalues_in, rivalues_out); break;
+ case 256: gsl_power2_fft256analysis (rivalues_in, rivalues_out); break;
+ case 512: gsl_power2_fft512analysis (rivalues_in, rivalues_out); break;
+ case 1024: gsl_power2_fft1024analysis (rivalues_in, rivalues_out); break;
+ case 2048: gsl_power2_fft2048analysis (rivalues_in, rivalues_out); break;
+ case 4096: gsl_power2_fft4096analysis (rivalues_in, rivalues_out); break;
+ case 8192: gsl_power2_fft8192analysis (rivalues_in, rivalues_out); break;
+ default: gsl_power2_fftc_big (n_values, rivalues_in, rivalues_out, +1);
+ }
+}
+void
+gsl_power2_fftsc (const unsigned int n_values,
+ const $IEEE_TYPE *rivalues_in,
+ $IEEE_TYPE *rivalues_out)
+{
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 1);
+
+ switch (n_values)
+ {
+ case 1: rivalues_out[0] = rivalues_in[0], rivalues_out[1] = rivalues_in[1]; break;
+ case 2: gsl_power2_fft2synthesis (rivalues_in, rivalues_out); break;
+ case 4: gsl_power2_fft4synthesis (rivalues_in, rivalues_out); break;
+ case 8: gsl_power2_fft8synthesis (rivalues_in, rivalues_out); break;
+ case 16: gsl_power2_fft16synthesis (rivalues_in, rivalues_out); break;
+ case 32: gsl_power2_fft32synthesis (rivalues_in, rivalues_out); break;
+ case 64: gsl_power2_fft64synthesis (rivalues_in, rivalues_out); break;
+ case 128: gsl_power2_fft128synthesis (rivalues_in, rivalues_out); break;
+ case 256: gsl_power2_fft256synthesis (rivalues_in, rivalues_out); break;
+ case 512: gsl_power2_fft512synthesis (rivalues_in, rivalues_out); break;
+ case 1024: gsl_power2_fft1024synthesis (rivalues_in, rivalues_out); break;
+ case 2048: gsl_power2_fft2048synthesis (rivalues_in, rivalues_out); break;
+ case 4096: gsl_power2_fft4096synthesis (rivalues_in, rivalues_out); break;
+ case 8192: gsl_power2_fft8192synthesis (rivalues_in, rivalues_out); break;
+ default: gsl_power2_fftc_big (n_values, rivalues_in, rivalues_out, -1);
+ }
+ /* { unsigned int i; for (i = 0; i < n_values << 1; i++) rivalues_out[i] *= (double) n_values; } */
+}
+__EOF
+
+
+#
+# public real fft frontends
+#
+echo "Generating public real FFT frontends" >&2
+cat <<__EOF
+void
+gsl_power2_fftar (const unsigned int n_values,
+ const $IEEE_TYPE *r_values_in,
+ $IEEE_TYPE *rivalues_out)
+{
+ unsigned int n_cvalues = n_values >> 1;
+ double Dre, Dim, Wre, Wim, theta;
+ unsigned int i;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ gsl_power2_fftac (n_cvalues, r_values_in, rivalues_out);
+ theta = 3.1415926535897932384626433832795029;
+ theta /= (double) n_cvalues;
+
+ Dre = sin (0.5 * theta);
+ Dim = sin (theta);
+ Dre = Dre * Dre;
+ Wre = 0.5 - Dre;
+ Dre *= -2.;
+ Wim = Dim * 0.5;
+ for (i = 2; i < n_values >> 1; i += 2)
+ {
+ double F1re, F1im, F2re, F2im, H1re, H1im, H2re, H2im;
+ unsigned int r = n_values - i;
+ double FEre = rivalues_out[i] + rivalues_out[r];
+ double FEim = rivalues_out[i + 1] - rivalues_out[r + 1];
+ double FOre = rivalues_out[r] - rivalues_out[i];
+ double FOim = rivalues_out[r + 1] + rivalues_out[i + 1];
+
+ FEre *= 0.5;
+ FEim *= 0.5;
+ F2re = FOre * Wim;
+ F2im = FOim * Wim;
+ F1re = FOre * Wre;
+ F1im = FOim * Wre;
+
+ H1im = F2im + F1re;
+ H1re = F1im - F2re;
+ H2re = F2re - F1im;
+ H2im = H1im - FEim;
+ H1re += FEre;
+ H2re += FEre;
+ H1im += FEim;
+ rivalues_out[i] = H1re;
+ rivalues_out[i + 1] = H1im;
+ rivalues_out[r] = H2re;
+ rivalues_out[r + 1] = H2im;
+ WMULTIPLY (Wre, Wim, Dre, Dim);
+ }
+ Dre = rivalues_out[0];
+ rivalues_out[0] = Dre + rivalues_out[1];
+ rivalues_out[1] = Dre - rivalues_out[1];
+}
+void
+gsl_power2_fftsr (const unsigned int n_values,
+ const double *rivalues_in,
+ double *r_values_out)
+{
+ unsigned int n_cvalues = n_values >> 1;
+ double Dre, Dim, Wre, Wim, theta, scale;
+ unsigned int i, ri;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ theta = -3.1415926535897932384626433832795029;
+ theta /= (double) n_cvalues;
+
+ Dre = sin (0.5 * theta);
+ Dim = sin (theta);
+ Dre = Dre * Dre;
+ Wre = 0.5 - Dre;
+ Dre *= -2.;
+ Wim = Dim * 0.5;
+ for (i = 2, ri = 0; i < n_values >> 1; i += 2)
+ {
+ double F1re, F1im, F2re, F2im, H1re, H1im, H2re, H2im;
+ unsigned int g = n_values - i, j = n_values >> 2, rg = n_values - (ri << 1) - 2;
+ double FEre = rivalues_in[i] + rivalues_in[g];
+ double FEim = rivalues_in[i + 1] - rivalues_in[g + 1];
+ double FOre = rivalues_in[g] - rivalues_in[i];
+ double FOim = rivalues_in[g + 1] + rivalues_in[i + 1];
+
+ while (ri >= j)
+ {
+ ri -= j;
+ j >>= 1;
+ }
+ ri |= j;
+
+ FOre = -FOre;
+ FOim = -FOim;
+ FEre *= 0.5;
+ FEim *= 0.5;
+ F2re = FOre * Wim;
+ F2im = FOim * Wim;
+ F1re = FOre * Wre;
+ F1im = FOim * Wre;
+
+ H1im = F2im + F1re;
+ H1re = F1im - F2re;
+ H2re = F2re - F1im;
+ H2im = H1im - FEim;
+ H1re += FEre;
+ H2re += FEre;
+ H1im += FEim;
+
+ j = ri << 1;
+ r_values_out[j] = H1re;
+ r_values_out[j + 1] = H1im;
+ r_values_out[rg] = H2re;
+ r_values_out[rg + 1] = H2im;
+ WMULTIPLY (Wre, Wim, Dre, Dim);
+ }
+ Dre = rivalues_in[0];
+ r_values_out[0] = Dre + rivalues_in[1];
+ r_values_out[1] = Dre - rivalues_in[1];
+ r_values_out[0] *= 0.5;
+ r_values_out[1] *= 0.5;
+ if (n_values < 4)
+ return;
+ r_values_out[2] = rivalues_in[i];
+ r_values_out[2 + 1] = rivalues_in[i + 1];
+ scale = n_cvalues;
+ scale = 1.0 / scale;
+ for (i = 0; i < n_values; i += 4)
+ BUTTERFLY_10scale (r_values_out[i], r_values_out[i + 1],
+ r_values_out[i + 2], r_values_out[i + 3],
+ r_values_out[i], r_values_out[i + 1],
+ r_values_out[i + 2], r_values_out[i + 3],
+ scale);
+ switch (n_cvalues)
+ {
+ case 2: break;
+ case 4: gsl_power2_fft4synthesis_skip2 (NULL, r_values_out); break;
+ case 8: gsl_power2_fft8synthesis_skip2 (NULL, r_values_out); break;
+ case 16: gsl_power2_fft16synthesis_skip2 (NULL, r_values_out); break;
+ case 32: gsl_power2_fft32synthesis_skip2 (NULL, r_values_out); break;
+ case 64: gsl_power2_fft64synthesis_skip2 (NULL, r_values_out); break;
+ case 128: gsl_power2_fft128synthesis_skip2 (NULL, r_values_out); break;
+ case 256: gsl_power2_fft256synthesis_skip2 (NULL, r_values_out); break;
+ case 512: gsl_power2_fft512synthesis_skip2 (NULL, r_values_out); break;
+ case 1024: gsl_power2_fft1024synthesis_skip2 (NULL, r_values_out); break;
+ case 2048: gsl_power2_fft2048synthesis_skip2 (NULL, r_values_out); break;
+ case 4096: gsl_power2_fft4096synthesis_skip2 (NULL, r_values_out); break;
+ case 8192: gsl_power2_fft8192synthesis_skip2 (NULL, r_values_out); break;
+ default: gsl_power2_fftc_big (n_cvalues, NULL, r_values_out, -1);
+ }
+}
+void
+gsl_power2_fftar_simple (const unsigned int n_values,
+ const float *real_values,
+ float *complex_values)
+{
+ double *rv, *cv;
+ guint i;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ rv = g_new (double, n_values * 2);
+ cv = rv + n_values;
+ i = n_values;
+ while (i--)
+ rv[i] = real_values[i];
+ gsl_power2_fftar (n_values, rv, cv);
+ i = n_values;
+ while (i--)
+ complex_values[i] = cv[i];
+ complex_values[n_values] = complex_values[1];
+ complex_values[1] = 0.0;
+ complex_values[n_values + 1] = 0.0;
+ g_free (rv);
+}
+void
+gsl_power2_fftsr_simple (const unsigned int n_values,
+ const float *complex_values,
+ float *real_values)
+{
+ double *cv, *rv;
+ guint i;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ cv = g_new (double, n_values * 2);
+ rv = cv + n_values;
+ i = n_values;
+ while (i--)
+ cv[i] = complex_values[i];
+ cv[1] = complex_values[n_values];
+ gsl_power2_fftsr (n_values, cv, rv);
+ i = n_values;
+ while (i--)
+ real_values[i] = rv[i];
+ g_free (cv);
+}
+__EOF
diff --git a/flow/gsl/gsl-fftgen.pl b/flow/gsl/gsl-fftgen.pl
new file mode 100755
index 0000000..551f8c3
--- /dev/null
+++ b/flow/gsl/gsl-fftgen.pl
@@ -0,0 +1,810 @@
+#!/usr/bin/perl -w
+# GSL-GENFFT - Power2 FFT C Code Generator
+# Copyright (C) 2001 Tim Janik
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+# TODO:
+# - optimize L case more
+# - join 2 or 3 stages
+
+my $indent = " ";
+my $PI = 3.1415926535897932384626433832795029;
+my $ieee_type = "float";
+my $tmp_ieee_type = "double"; # don't change, decreases precision _and_ performance
+
+# arguments
+my $max_fft_size = 0;
+my $gen_macros = 1;
+my $max_unroll = 256;
+my $min_split = 2048;
+my $min_compress = 512;
+my $fft2loop = 0;
+my $single_stage = 0;
+my $negate_sign = 0;
+my $Wtest = 0;
+
+#
+# parse options
+#
+while ($_ = $ARGV[0], defined $_ && /^-/) {
+ shift;
+ last if (/^--$/);
+ if (/^--fft2loop$/) { $fft2loop = 1 }
+ elsif (/^--analysis$/) { $negate_sign = 0 }
+ elsif (/^--synthesis$/) { $negate_sign = 1 }
+ elsif (/^--Wtest$/) { $Wtest = 1 }
+ elsif (/^--double$/) { $ieee_type = "double" }
+ elsif (/^--skip-macros$/) { $gen_macros = 0 }
+ elsif (/^--max-unroll$/) { $max_unroll = shift }
+ elsif (/^--split-at$/) { $min_split = shift }
+ elsif (/^--min-compress$/) { $min_compress = shift }
+ elsif (/^--single-stage$/) { $single_stage = shift }
+}
+# parse arguments
+my @arguments = 0;
+if (defined $ARGV[0]) {
+ $max_fft_size = $ARGV[0];
+ shift;
+}
+while (defined $ARGV[0]) {
+ push @arguments, $ARGV[0];
+ shift;
+}
+
+#
+# check arguments and provide help
+#
+if ($max_fft_size && ($max_fft_size < 2 || $max_fft_size & ($max_fft_size - 1))) {
+ print(STDERR "usage: gsl-genfft [options] <fftsize>\n".
+ "Produces C code to calculate an FFT of specified <size> which has\n".
+ "to be a power of 2.\n".
+ " --max-unroll <size> max fft size to unroll loops and bodies\n".
+ " --min-compress <size> min fft size to unroll only loop bodies\n".
+ " --split-at <size> max fft size for which recursive ffts are joined\n".
+ " --fft2loop force bitreversing fft2 part into a loop\n".
+ "");
+ # " |\n"
+ exit 0;
+}
+
+
+#
+# utility functions
+#
+sub bitreverse {
+ my $h = shift; # fft_size;
+ my $n = shift;
+ my $r = 0;
+
+ while ($n) {
+ $h >>= 1;
+ $r |= $h if ($n & 1);
+ $n >>= 1;
+ }
+ return $r;
+}
+sub Wexponent {
+ my $fft_size = shift;
+ my $n_points = shift;
+ my $nth = shift; # nth coefficient of this <n_points> stage
+
+ my $r = $nth * $fft_size / $n_points;
+
+ return $r;
+}
+sub Wreal {
+ my $n = shift; # fft_size
+ my $k = shift; # power
+
+ my $x = cos ($PI * (2. * $k / $n));
+
+ return $x == 0 ? 0 : $x; # -0.0 == 0
+}
+sub Wimag {
+ my $n = shift; # fft_size
+ my $k = shift;
+
+ my $x = sin ($PI * (2. * $k / $n));
+ $x = -$x if ($negate_sign);
+
+ return $x == 0 ? 0 : $x; # -0.0 == 0
+}
+
+
+#
+# unrolled fft generation
+#
+sub butterfly {
+ my $type = shift;
+ my $offset1 = shift;
+ my $offset2 = shift;
+ my $Wre = shift;
+ my $Wim = shift;
+ my $var = shift;
+
+ # define BUTTERFLY_XY(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim,T1re,T1im,T2re,T2im)
+ printf($indent."BUTTERFLY_%s (%s[%s], %s[%s + 1],\n".
+ $indent." %s[%s], %s[%s + 1],\n".
+ $indent." %s[%s], %s[%s + 1],\n".
+ $indent." %s[%s], %s[%s + 1],\n".
+ $indent." %s, %s);\n",
+ $type,
+ $var, $offset1, $var, $offset1,
+ $var, $offset2, $var, $offset2,
+ $var, $offset1, $var, $offset1,
+ $var, $offset2, $var, $offset2,
+ $Wre, $Wim);
+}
+sub butterfly_auto {
+ my $fft_size = shift;
+ my $index1 = shift;
+ my $index2 = $index1 + shift;
+ my $wk = shift;
+ my $ofs = shift;
+ my $inplace = shift;
+ my $ib = $inplace ? "Y" : "X";
+ my $rfact = Wreal ($fft_size, $wk);
+ my $ifact = Wimag ($fft_size, $wk);
+ my $index1r = !$inplace ? bitreverse ($fft_size, $index1 >> 1) << 1 : $index1;
+ my $index2r = !$inplace ? bitreverse ($fft_size, $index2 >> 1) << 1 : $index2;
+ my $btype = "XY";
+ my $optimize_10 = $wk == 0;
+ my $optimize_0x = $wk == $fft_size / 4;
+
+ if (abs ($rfact - 1.0) < 0.0000000000000005 &&
+ abs ($ifact - 0.0) < 0.0000000000000005) {
+ $btype = "10";
+ # print STDERR "10: ". $wk ."\n";
+ $optimize_10 = 0 if ($optimize_10);
+ } elsif (abs ($rfact - 0.0) < 0.0000000000000005 &&
+ abs ($ifact - 1.0) < 0.0000000000000005) {
+ $btype = "01";
+ # print STDERR "01: ". $wk ."\n";
+ $optimize_0x = 0 if ($optimize_0x);
+ } elsif (abs ($rfact - 0.0) < 0.0000000000000005 &&
+ abs ($ifact + 1.0) < 0.0000000000000005) {
+ $btype = "0m";
+ # print STDERR "0m: ". $wk ."\n";
+ $optimize_0x = 0 if ($optimize_0x);
+ } elsif (abs ($rfact - $ifact) < 0.0000000000000005) {
+ $btype = "XX"; # grr, this actually slows down the athlon (keep "XY")
+ } elsif (abs ($rfact + $ifact) < 0.0000000000000005) {
+ $btype = "yY"; # grr, this actually slows down the athlon (keep "XY")
+ }
+
+ if ($optimize_10 || $optimize_0x) {
+ die("optimization error for fft$fft_size: 10=". $optimize_10 .", 0x=". $optimize_0x .
+ ", Wre=". $rfact ." Wim=". $ifact .", wk=". $wk);
+ }
+
+ # BUTTERFLY_XY (X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim,T1re,T1im,T2re,T2im);
+ printf($indent."BUTTERFLY_%s (%s[%s%u], /* W%u */\n".
+ $indent." %s[%s%u + 1],\n".
+ $indent." %s[%s%u],\n".
+ $indent." %s[%s%u + 1],\n".
+ $indent." Y[%s%u],\n".
+ $indent." Y[%s%u + 1],\n".
+ $indent." Y[%s%u],\n".
+ $indent." Y[%s%u + 1],\n".
+ $indent." (%s) %+.15f, (%s) %+.15f);\n",
+ $btype,
+ $ib, $ofs, $index1r, $wk, $ib, $ofs, $index1r, $ib, $ofs, $index2r, $ib, $ofs, $index2r,
+ $ofs, $index1, $ofs, $index1, $ofs, $index2, $ofs, $index2,
+ $tmp_ieee_type, $rfact, $tmp_ieee_type, $ifact);
+}
+sub unroll_stage {
+ my $fft_size = shift;
+ my $n_points = shift;
+ my $n_rep = shift; # repetitions
+ my $unroll_outer = shift;
+
+ if ($unroll_outer && $n_points == 2) {
+ for (my $i = 0; $i < $n_points >> 1; $i++) {
+ for (my $j = 0; $j < $n_rep; $j++) {
+ my $offset1 = ($j * $n_points + $i) * 2;
+ my $offset2 = $offset1 + $n_points;
+ my $offset1r = bitreverse ($fft_size, $offset1 >> 1) << 1;
+ my $offset2r = bitreverse ($fft_size, $offset2 >> 1) << 1;
+ my $scale = !$negate_sign ? "__1, __0" : sprintf "1.0 / (%s) %u", $tmp_ieee_type, $fft_size;
+ printf($indent."BUTTERFLY_10%s (X[%s], X[%s + 1],\n".
+ $indent." X[%s], X[%s + 1],\n".
+ $indent." Y[%s], Y[%s + 1],\n".
+ $indent." Y[%s], Y[%s + 1],\n".
+ $indent." %s);\n",
+ $negate_sign ? "scale" : "",
+ $offset1r, $offset1r,
+ $offset2r, $offset2r,
+ $offset1, $offset1,
+ $offset2, $offset2,
+ $scale);
+ }
+ }
+ } elsif ($unroll_outer) {
+ for (my $i = 0; $i < $n_points >> 1; $i++) {
+ for (my $j = 0; $j < $n_rep; $j++) {
+ butterfly_auto ($fft_size,
+ ($j * $n_points + $i) * 2,
+ $n_points,
+ Wexponent ($fft_size, $n_points, $i),
+ "", $n_points != 2);
+ }
+ }
+ } else {
+ die "cannot skip outer loop unrolling for fft2" if $n_points == 2;
+
+ printf "%sfor (block = 0; block < %u; block += %u) {\n", $indent, $n_points * 2 * $n_rep, $n_points * 2;
+ $indent .= " ";
+ for (my $i = 0; $i < $n_points >> 1; $i++) {
+ butterfly_auto ($fft_size,
+ $i * 2,
+ $n_points,
+ Wexponent ($fft_size, $n_points, $i),
+ "block + ", $n_points != 2);
+ }
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ }
+}
+sub table_stage {
+ my $fft_size = shift;
+ my $n_points = shift;
+ my $n_rep = shift; # repetitions
+
+ die "cannot loop over coefficient table for fft2" if $n_points == 2;
+
+ printf "%s{\n", $indent;
+ $indent .= " ";
+ printf "%sstatic const %s Wconst%u[] = {\n", $indent, $tmp_ieee_type, $n_points;
+ for (my $i = 1; $i < $n_points >> 2; $i++) {
+ my $wk = Wexponent ($fft_size, $n_points, $i);
+ printf "%s %+.15f, %+.15f,\n", $indent, Wreal ($fft_size, $wk), Wimag ($fft_size, $wk);
+ }
+ printf "%s};\n", $indent;
+ printf "%sconst %s *W = Wconst%u - 2;\n", $indent, $tmp_ieee_type, $n_points;
+ printf "%s%s *Z = Y + %u;\n", $indent, $ieee_type, $n_points >> 1;
+
+ # first half loops
+ printf("%sfor (offset = 0; offset < %u; offset += %u) {\n",
+ $indent, $n_points * 2 * $n_rep, $n_points * 2);
+ $indent .= " ";
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ("10", "offset", $ofs2, "__1", "__0", "Y");
+ butterfly ($negate_sign ? "0m" : "01", "offset", $ofs2, "__0", "__1", "Z");
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ printf "%sfor (butterfly = 2; butterfly < %u; butterfly += 2) {\n", $indent, $n_points >> 1;
+ printf "%s Wre = W[butterfly]; Wim = W[butterfly + 1];\n", $indent;
+ printf "%s for (block = 0; block < %u; block += %u) {\n", $indent, $n_points * 2 * $n_rep, $n_points * 2;
+ $indent .= " ";
+ printf "%soffset = butterfly + block;\n", $indent;
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ("XY", "offset", $ofs2, "Wre", "Wim", "Y");
+ butterfly ($negate_sign ? "yX" : "Yx", "offset", $ofs2, "Wre", "Wim", "Z");
+ $indent =~ s/\ \ \ \ $//;
+ printf "%s }\n", $indent;
+ printf "%s}\n", $indent;
+
+ # second half loops
+ if (0) {
+ printf("%sfor (offset = %u; offset < %u + %u; offset += %u) {\n",
+ $indent, $n_points >> 1, $n_points >> 1, $n_points * 2 * $n_rep, $n_points * 2);
+ $indent .= " ";
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ($negate_sign ? "0m" : "01", "offset", $ofs2, "__0", "__1", "Y");
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ printf "%sW -= %u;\n", $indent, $n_points >> 1;
+ printf "%sfor (butterfly = %u + 2; butterfly < %u; butterfly += 2) {\n", $indent, $n_points >> 1, $n_points;
+ printf "%s Wre = W[butterfly]; Wim = W[butterfly + 1];\n", $indent;
+ printf "%s for (block = 0; block < %u; block += %u) {\n", $indent, $n_points * 2 * $n_rep, $n_points * 2;
+ $indent .= " ";
+ printf "%soffset = butterfly + block;\n", $indent;
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ($negate_sign ? "yX" : "Yx", "offset", $ofs2, "Wre", "Wim", "Y");
+ $indent =~ s/\ \ \ \ $//;
+ printf "%s }\n", $indent;
+ printf "%s}\n", $indent;
+ }
+
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+}
+sub bitreverse_fft2 {
+ # mul_result = gsl_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
+ printf "
+static inline void
+bitreverse_fft2analysis (const unsigned int n,
+ const %-6s *X,
+ %-6s *Y)
+{
+ const unsigned int n2 = n >> 1, n1 = n + n2, max = n >> 2;
+ unsigned int i, r;
+
+ BUTTERFLY_10 (X[0], X[1],
+ X[n], X[n + 1],
+ Y[0], Y[1],
+ Y[2], Y[3],
+ __1, __0);
+ BUTTERFLY_10 (X[n2], X[n2 + 1],
+ X[n1], X[n1 + 1],
+ Y[4], Y[5],
+ Y[6], Y[7],
+ __1, __0);
+ for (i = 1, r = 0; i < max; i++)
+ {
+ unsigned int k, j = n >> 1;
+
+ while (r >= j)
+ {
+ r -= j;
+ j >>= 1;
+ }
+ r |= j;
+
+ k = r >> 1;
+ j = i << 3;
+ BUTTERFLY_10 (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ __1, __0);
+ k += n2;
+ j += 4;
+ BUTTERFLY_10 (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ __1, __0);
+ }
+}
+static inline void
+bitreverse_fft2synthesis (const unsigned int n,
+ const %-6s *X,
+ %-6s *Y)
+{
+ const unsigned int n2 = n >> 1, n1 = n + n2, max = n >> 2;
+ unsigned int i, r;
+ %s scale = n;
+
+ scale = 1.0 / scale;
+ BUTTERFLY_10scale (X[0], X[1],
+ X[n], X[n + 1],
+ Y[0], Y[1],
+ Y[2], Y[3],
+ scale);
+ BUTTERFLY_10scale (X[n2], X[n2 + 1],
+ X[n1], X[n1 + 1],
+ Y[4], Y[5],
+ Y[6], Y[7],
+ scale);
+ for (i = 1, r = 0; i < max; i++)
+ {
+ unsigned int k, j = n >> 1;
+
+ while (r >= j)
+ {
+ r -= j;
+ j >>= 1;
+ }
+ r |= j;
+
+ k = r >> 1;
+ j = i << 3;
+ BUTTERFLY_10scale (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ scale);
+ k += n2;
+ j += 4;
+ BUTTERFLY_10scale (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ scale);
+ }
+}
+", $ieee_type, $ieee_type, $ieee_type, $ieee_type, $tmp_ieee_type;
+
+ # testing:
+ # define BUTTERFLY_10(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim,T1re,T1im,T2re,T2im) \
+ # { int a = &X1re-X, b = &X2re-X, c = &Y1re-Y; \
+ # printf ("bufferfly: [%u,%u] -> [%u,%u]\n", (a)>>1, (b)>>1, (c)>>1, (c+2)>>1); \
+ # if (((a)|(b)|(c))&1) perror("****eek, extraneous bits!");}
+ # int main (int argc, char *argv[]) {
+ # bitreverse_fft2a (atoi (argv[1]), 0, 0);
+ # return 0;
+ # }
+}
+
+#
+# fft generation routines
+#
+sub gen_fft_loop_unoptimized {
+ my $fft_size = shift;
+ my $n_points = shift;
+ my $n_rep = shift; # repetitions
+ my $ofs2;
+
+ die "invalid fft size: " . $n_points if ($n_points < 4);
+
+ # incremental coefficient W for this fft
+ my $theta = $PI / ($n_points >> 1);
+ $theta = -$theta if ($negate_sign);
+ my $re = sin (0.5 * $theta);
+ my $im = sin ($theta);
+ $re = $re * $re * -2.;
+
+ # init variables, start loops
+ printf "%sWre = 1.0; Wim = 0.0;\n", $indent;
+ printf "%sfor (butterfly = 0; butterfly < %u; butterfly += 2) {\n", $indent, $n_points;
+ $indent .= " ";
+ printf "%sfor (block = 0; block < %u; block += %u) {\n", $indent, $n_rep * $n_points << 1, $n_points << 1;
+ $indent .= " ";
+
+ # do the butterfly
+ printf "%soffset = butterfly + block;\n", $indent;
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ("XY", "offset", $ofs2, "Wre", "Wim", "Y");
+
+ # close inner loop, update W
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ printf("%sWMULTIPLY (Wre, Wim, %+.15f, %+.15f);\n",
+ $indent, $re, $im);
+
+ # close outer loop, done
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+}
+sub gen_fft_loop_o10o0x {
+ my $fft_size = shift;
+ my $n_points = shift;
+ my $n_rep = shift; # repetitions
+ my $ofs2;
+
+ die "invalid fft size: " . $n_points if ($n_points < 4);
+
+ # coefficient {1,0} loop
+ printf "%sfor (offset = 0; offset < %u; offset += %u) {\n", $indent, $n_rep * $n_points << 1, $n_points << 1;
+ $indent .= " ";
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ("10", "offset", $ofs2, "__1", "__0", "Y");
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+
+ # incremental coefficient W for this fft
+ my $theta = $PI / ($n_points >> 1);
+ $theta = -$theta if ($negate_sign);
+ my $re = sin (0.5 * $theta);
+ my $im = sin ($theta);
+ $re = $re * $re * -2.;
+
+ # loop first half
+ if (2 < $n_points >> 1) {
+ printf "%sWre = %+.15f; Wim = %+.15f;\n", $indent, $re + 1.0, $im;
+ printf "%sfor (butterfly = 2; butterfly < %u; butterfly += 2) {\n", $indent, $n_points >> 1;
+ $indent .= " ";
+ printf "%sfor (block = 0; block < %u; block += %u) {\n", $indent, $n_rep * $n_points << 1, $n_points << 1;
+ $indent .= " ";
+ # do the butterfly
+ printf "%soffset = butterfly + block;\n", $indent;
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ("XY", "offset", $ofs2, "Wre", "Wim", "Y");
+ # close inner loop, update W
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ printf("%sWMULTIPLY (Wre, Wim, %+.15f, %+.15f);\n",
+ $indent, $re, $im);
+ # close outer loop, done
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ }
+
+ # coefficient {0,1} loop
+ printf "%sfor (offset = %u; offset < %u; offset += %u) {\n", $indent, $n_points >> 1, $n_rep * $n_points << 1, $n_points << 1;
+ $indent .= " ";
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ($negate_sign ? "0m" : "01", "offset", $ofs2, "__0", "__1", "Y");
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+
+ # loop second half
+ if (($n_points >> 1) + 2 < $n_points) {
+ if ($negate_sign) {
+ printf "%sWre = %+.15f; Wim = %+.15f;\n", $indent, $im, -$re - 1.0;
+ } else {
+ printf "%sWre = %+.15f; Wim = %+.15f;\n", $indent, -$im, $re + 1.0;
+ }
+ printf "%sfor (butterfly = %u; butterfly < %u; butterfly += 2) {\n", $indent, ($n_points >> 1) + 2, $n_points;
+ $indent .= " ";
+ printf "%sfor (block = 0; block < %u; block += %u) {\n", $indent, $n_rep * $n_points << 1, $n_points << 1;
+ $indent .= " ";
+ # do the butterfly
+ printf "%soffset = butterfly + block;\n", $indent;
+ $ofs2 = sprintf "offset + %u", $n_points;
+ butterfly ("XY", "offset", $ofs2, "Wre", "Wim", "Y");
+ # close inner loop, update W
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ printf("%sWMULTIPLY (Wre, Wim, %+.15f, %+.15f);\n",
+ $indent, $re, $im);
+ # close outer loop, done
+ $indent =~ s/\ \ $//;
+ printf "%s}\n", $indent;
+ }
+}
+sub fft_loop_macros {
+ # mul_result = gsl_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
+ print "
+#define WMULTIPLY(Wre,Wim,Dre,Dim) { \\
+ register $tmp_ieee_type T1re, T1im, T2re, T2im; \\
+ T1re = Wre * Dre; \\
+ T1im = Wim * Dre; \\
+ T2re = Wim * Dim; \\
+ T2im = Wre * Dim; \\
+ T1re -= T2re; \\
+ T1im += T2im; \\
+ Wre += T1re; \\
+ Wim += T1im; \\
+}";
+}
+sub butterfly_macros {
+ # mul_result = gsl_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
+ # add_result = gsl_complex (c1.re + c2.re, c1.im + c2.im);
+ print "
+#define BUTTERFLY_XY(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \\
+ register $tmp_ieee_type T1re, T1im, T2re, T2im; \\
+ T1re = X2re * Wre; \\
+ T1im = X2im * Wre; \\
+ T2re = X2im * Wim; \\
+ T2im = X2re * Wim; \\
+ T1re -= T2re; \\
+ T1im += T2im; \\
+ T2re = X1re - T1re; \\
+ T2im = X1im - T1im; \\
+ Y1re = X1re + T1re; \\
+ Y1im = X1im + T1im; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_Yx(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \\
+ register $tmp_ieee_type T1re, T1im, T2re, T2im; \\
+ T1re = X2re * Wim; \\
+ T1im = X2im * Wim; \\
+ T2re = X2im * Wre; \\
+ T2im = X2re * Wre; \\
+ T1re += T2re; \\
+ T1im -= T2im; \\
+ T2re = X1re + T1re; \\
+ T2im = X1im + T1im; \\
+ Y1re = X1re - T1re; \\
+ Y1im = X1im - T1im; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_yX(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \\
+ register $tmp_ieee_type T1re, T1im, T2re, T2im; \\
+ T1re = X2re * Wim; \\
+ T1im = X2im * Wim; \\
+ T2re = X2im * Wre; \\
+ T2im = X2re * Wre; \\
+ T1re += T2re; \\
+ T1im -= T2im; \\
+ T2re = X1re - T1re; \\
+ T2im = X1im - T1im; \\
+ Y1re = X1re + T1re; \\
+ Y1im = X1im + T1im; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_10(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \\
+ register $tmp_ieee_type T2re, T2im; \\
+ T2re = X1re - X2re; \\
+ T2im = X1im - X2im; \\
+ Y1re = X1re + X2re; \\
+ Y1im = X1im + X2im; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_01(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \\
+ register $tmp_ieee_type T2re, T2im; \\
+ T2re = X1re + X2im; \\
+ T2im = X1im - X2re; \\
+ Y1re = X1re - X2im; \\
+ Y1im = X1im + X2re; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_0m(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \\
+ register $tmp_ieee_type T2re, T2im; \\
+ T2re = X1re - X2im; \\
+ T2im = X1im + X2re; \\
+ Y1re = X1re + X2im; \\
+ Y1im = X1im - X2re; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_XX(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,_2) { \\
+ register $tmp_ieee_type T1re, T1im, T2re, T2im; \\
+ T1re = X2re * Wre; \\
+ T1im = X2im * Wre; \\
+ T2re = T1im; \\
+ T2im = T1re; \\
+ T1re -= T2re; \\
+ T1im += T2im; \\
+ T2re = X1re - T1re; \\
+ T2im = X1im - T1im; \\
+ Y1re = X1re + T1re; \\
+ Y1im = X1im + T1im; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_yY(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,_2) { \\
+ register $tmp_ieee_type T1re, T1im, T2re, T2im; \\
+ T1re = X2re * Wre; \\
+ T1im = X2im * Wre; \\
+ T2re = T1im; \\
+ T2im = T1re; \\
+ T1re += T2re; \\
+ T1im -= T2im; \\
+ T2re = X1re - T1re; \\
+ T2im = X1im - T1im; \\
+ Y1re = X1re + T1re; \\
+ Y1im = X1im + T1im; \\
+ Y2re = T2re; \\
+ Y2im = T2im; \\
+}
+#define BUTTERFLY_10scale(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,S) { \\
+ register $tmp_ieee_type T2re, T2im; \\
+ T2re = X1re - X2re; \\
+ T2im = X1im - X2im; \\
+ Y1re = X1re + X2re; \\
+ Y1im = X1im + X2im; \\
+ Y2re = T2re * S; \\
+ Y2im = T2im * S; \\
+ Y1re *= S; \\
+ Y1im *= S; \\
+}
+";
+}
+
+
+#
+# stage generation
+#
+sub gen_stage {
+ my $fft_size = shift;
+ my $n_points = shift;
+ my $kind = shift;
+ my $times = $fft_size / $n_points;
+
+ if ($kind eq 'S') {
+ printf "\n%s/* skipping %u times fft%u */\n", $indent, $times, $n_points;
+ return;
+ }
+ if ($n_points == 2) { # input stage needs special handling
+ if ($kind eq 'L') {
+ printf "\n%s/* perform fft2 and bitreverse input */\n", $indent;
+ printf "%sbitreverse_fft2%s (%u, X, Y);\n", $indent, $negate_sign ? "synthesis" : "analysis", $fft_size;
+ } elsif ($kind eq 'F') {
+ printf "\n%s/* perform %u times fft2 */\n", $indent, $times;
+ unroll_stage ($fft_size, $n_points, $times, 1);
+ } else {
+ die "need one of 'L' or 'F' for input stage";
+ }
+ } else {
+ if ($kind eq 'L') {
+ printf "\n%s/* perform %u times fft%u */\n", $indent, $times, $n_points;
+ gen_fft_loop_o10o0x ($fft_size, $n_points, $times);
+ } elsif ($kind eq 'F') {
+ printf "\n%s/* perform %u times fft%u */\n", $indent, $times, $n_points;
+ unroll_stage ($fft_size, $n_points, $times, 1);
+ } elsif ($kind eq 'R') {
+ printf "\n%s/* perform %u times fft%u */\n", $indent, $times, $n_points;
+ unroll_stage ($fft_size, $n_points, $times, $times == 1);
+ } elsif ($kind eq 'T') {
+ printf "\n%s/* perform %u times fft%u */\n", $indent, $times, $n_points;
+ table_stage ($fft_size, $n_points, $times);
+ } elsif ($kind eq 'X') {
+ printf "\n%s/* perform %u times fft%u */\n", $indent, $times, $n_points;
+ for (my $i = 0; $i < $times; $i++) {
+ if ($i) {
+ printf($indent."gsl_power2_fft%u%s_skip2 (X + %u, Y + %u);\n",
+ $n_points, $negate_sign ? "synthesis" : "analysis", $n_points * $i << 1, $n_points * $i << 1);
+ } else {
+ printf($indent."gsl_power2_fft%u%s_skip2 (X, Y);\n",
+ $n_points, $negate_sign ? "synthesis" : "analysis");
+ }
+ }
+ } else {
+ die "unknown kind: $kind";
+ }
+ }
+}
+
+#
+# test output
+#
+if ($Wtest) {
+ my $fft_size = $max_fft_size;
+
+ for (my $i = 0; $i < $fft_size >> 1; $i++) {
+ my $wk = Wexponent ($fft_size, $fft_size, $i);
+ printf "$fft_size: %4u: %+.15f, %+.15f,\n", $i, Wreal ($fft_size, $wk), Wimag ($fft_size, $wk);
+ }
+ exit 0;
+}
+if (0) {
+ # reversal test
+ for (my $i = 0; $i < $fft_size; $i++) {
+ printf STDERR "%-3u <-> %3u %s\n", $i, bitreverse ($fft_size, $i), $i % 4 ? "" : "XXX";
+ }
+}
+
+
+#
+# main output
+#
+if ($gen_macros) {
+ butterfly_macros ();
+ fft_loop_macros ();
+ bitreverse_fft2 ();
+}
+exit 0 if (!$max_fft_size);
+
+my $max_stages = 0;
+for ($i = $max_fft_size >> 1; $i; $i >>= 1) {
+ $max_stages++;
+}
+die "missing stage specifications ($max_stages stages, $#arguments specs)" if ($max_stages > $#arguments);
+die "too many stage specifications ($max_stages stages, $#arguments specs)" if ($max_stages < $#arguments);
+print "/**\n";
+printf(" ** Generated data (by gsl-genfft $max_fft_size");
+for (my $i = 1; $i < @arguments; $i++) {
+ printf " %s", uc ($arguments[$i]);
+}
+printf ")\n";
+print " **/\n";
+{
+ my $fft_size = $max_fft_size;
+ my $skip2 = uc ($arguments[1]) eq 'S';
+
+ printf STDERR "FFT-%-5u: ", $fft_size;
+
+ printf "static void\n";
+ printf("gsl_power2_fft%u%s%s (const %s *X, %s *Y)\n{\n",
+ $fft_size, $negate_sign ? "synthesis" : "analysis",
+ $skip2 ? "_skip2" : "",
+ $ieee_type, $ieee_type);
+ printf "%sregister unsigned int butterfly, block, offset;\n", $indent;
+ printf "%sregister %s Wre, Wim;\n\n", $indent, $tmp_ieee_type, $tmp_ieee_type;
+ printf "%sbutterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */\n", $indent;
+
+ my $seen_rule = 0;
+ for (my $i = 1; $i < @arguments && 1 << $i <= $fft_size; $i++) {
+ my $stage = uc ($arguments[$i]);
+ printf STDERR "%u-%s ", 1 << $i, $stage;
+ die "X follows non Skip" if ($stage eq "X" && $seen_rule);
+ gen_stage ($fft_size, 1 << $i, $stage);
+ $seen_rule |= (1 << $i) > 2 && !($stage eq "S");
+ }
+ printf "}\n";
+ printf STDERR "\n";
+}
+print "\n/**\n";
+print " ** Generated data ends here\n";
+print " **/\n";
diff --git a/flow/gsl/gsl-iplan.txt b/flow/gsl/gsl-iplan.txt
new file mode 100644
index 0000000..e37b55d
--- /dev/null
+++ b/flow/gsl/gsl-iplan.txt
@@ -0,0 +1,57 @@
+How to integrate the GSL engine into artsd?
+
+Open issues:
+ - adapting the driver model
+ - adapting main loop callbacks
+ - adapting the start()/stop() semantics
+ - multi streams
+ - midi/audio timing
+ - synchronization
+ - threadsafe module api
+ - how to live without the threading layer
+
+[*] adapting main loop callbacks
+
+the engine uses a three-state mainloop callback, which consists of
+
+1. prepare
+2. check
+3. dispatch
+
+with the following rules applying
+
+1. you always need to prepare, to obtain pollfds
+2. you check to see whether something needs to be done
+3. you dispatch to make the engine do something
+
+which will need to be treated in aRts as two state strategy, which is:
+================================================================================
+INIT:
+ prepare -> register fds with the IOManager
+--
+ON NOTIFY:
+ unregister fds with the IOManager
+
+ reselect all fds
+ check -> check if engine needs work
+ dispatch -> make engine do something
+
+ prepare -> reregister fds with the IOManager
+
+as temporary measure, we could eventually build an imaginary fd into the
+engine, which could be used for triggering calculations manually - we might
+also take the real fd, on the other hand, which would only lead to the
+IOManager sending out two notifications, which is not too critical
+================================================================================
+problem:
+
+iomanager reentrancy - the engine probably needs to be partially reentrant,
+if we are to expect that a synchronous destruction of a module (such as in
+a remote unref) transactionsynchronizes itself with the engine - but if we
+expect this, then we will need to register some fds reentrant with the engine
+
+well - we could - for a start - try to NOT reselect all fds to get a snapshot
+of the whole world in one piece - but try to 1:1 map iomanager callbacks to
+revents - this might or might not work
+
+
diff --git a/flow/gsl/gsl-mplan.txt b/flow/gsl/gsl-mplan.txt
new file mode 100644
index 0000000..2a80811
--- /dev/null
+++ b/flow/gsl/gsl-mplan.txt
@@ -0,0 +1,226 @@
+The GSL Engine
+==============
+
+The following gives an outline of the conceptual approach to
+simulate flow-system behavior and carries details of the
+implementation along.
+
+Introductionary remarks:
+------------------------
+The GSL Engine simulates signal flow systems by mapping them
+onto a network of signal processing modules which are connected
+via signal streams.
+The signal streams are value quantized and time discrete, where
+floats are used to store the quantized values and the samples are
+taken at arbitrary but equidistant points in time. Also, the
+sampling periods are assumed to be synchronous for all nodes.
+In the public GSL C API, engine modules are exposed as GslModule
+structures, for the internal engine implementation, each
+GslModule is embedded in an OpNode structure.
+
+Node Model:
+-----------
+* a node has n_istreams input streams
+* a node has n_jstreams joint input streams facilities, that is,
+ an unlimited number of ouput streams can be connected to each
+ "joint" input stream
+* a node has n_ostreams output streams
+* all streams are equally value quantized as IEEE754 floats,
+ usually within the range -1..1
+* all streams are synchronously time discrete
+* the flow-system behavior can be iteratively approximated
+ by calculating a node's output streams from its input streams
+* since all streams are equally time discrete, n output
+ values for all output streams can be calculated from n input
+ values at all input streams of a single network
+* some nodes always react delayed ("deferred" nodes) and can
+ guarantee that they can always produce n output values ahead
+ of receiving the corresponding n input values, with n>=1
+* a node that has no output facilities (n_ostreams==0) is
+ considered a "consumer" and has to be processed // FIXME
+
+Node Methods:
+-------------
+->process()
+ This method specifies through one of its arguments
+ the number of iterations the node has to perform,
+ and therefore the number of values that are supplied
+ in its stream input buffers and which have to be supplied
+ in its stream output buffers.
+->process_deferred()
+ This method specifies the number of input values supplied
+ and the number of output values that should be supplied.
+ The number of input values may be smaller than the number
+ of output values requested, in which case the node may return
+ less output values than requested.
+
+Node Relationships:
+-------------------
+Node B is an "input" of node A if:
+ * one of A's input streams is connected to one of B's output streams,
+ or
+ * node C is an "input" of A and B is an "input" of C
+
+Processing Order:
+-----------------
+If node A has an input node B and A is not a deferred node, B has to
+be processed prior to processing A.
+
+Connection Cycles:
+------------------
+Nodes A and B "form a cycle" if A is an input to B and B is an
+input to A.
+
+Invalid Connections:
+--------------------
+For nodes A and B (not necessarily distinct) which form a cycle,
+the connections that the cycle consists of are only valid if
+the following is true:
+ (C is a deferred node) and
+ (C==A or C==B or (if C is completely disconnected, the nodes
+ A and B do not anymore form the cycle))
+
+
+Implementation Notes
+====================
+* if a node is deferred, all output channels are delayed
+* independent leaf nodes (nodes that have no inputs) can be
+ scheduled separately
+* nodes contained in a cycle have to be scheduled together
+
+Scheduling Algorithm
+--------------------
+To schedule a consumer and its dependency nodes, schedule_query() it:
+
+Query and Schedule Node:
+* tag current node
+* ignore scheduled input nodes
+* schedule_query_node on untagged input nodes, then do one of:
+ * schedule input node (if it has no cycles)
+ * resolve all input nodes cycles and then schedule
+ the input nodes cycle (if not self in cycle)
+ * take over cycle dependencies from input node
+* a tagged node is added to the precondition list (opens new cycle)
+* own leaf level is MAX() of input node leaf-levels + 1
+* untag node
+
+Resolving Cycles:
+* eliminate child from precondition list, once the list
+ is empty the cycle is resolved
+* at least one node being eliminated has to be deferred
+ for the cycle to be valid
+
+Scheduling:
+* nodes need to be processed in the order of leaf-level
+* within leaf-levels, processing is determined by a per-node
+ processing costs hint (cheap, normal, expensive)
+
+Implementation Considerations:
+------------------------------
+For deferred nodes, the number n specifying the amount of output
+values that are produced ahead of input can be considered
+mostly-fixed. that is, it's unlikely to change often and will do
+so only at block boundaries.
+Supporting n to be completely variable or considering it mostly
+fixed has certain implications. Here're the considerations that
+led to supporting a completely variable n for the implementation:
+
+n is block-boundary fixed:
++ for complex cycles (i.e. cycles that contain other cycles,
+ "subcycles"), the subcycles can be scheduled separately
+ if the n of the subcycle is >= block_size
+- if n is the only thing that changed at a block-boundary,
+ rescheduling the flow-graph is required in the cases
+ where n = old_n + x with old_n < block_size or if x < 0
+- deferred nodes can not change their delay in response to
+ values of an input stream
+
+n is variable for every iteration step:
++ no rescheduling is required if n changes at block-boundary
+- subcycles can not be scheduled separately from their outermost
+ cycle
++ the delay of deferred nodes can correlate to an input stream
+
+
+Threads, communication, main loops
+==================================
+
+Thread types:
+* UserThread; for the scope of the engine (the functions exposed in
+ gslengine.h), only one user thread may execute API functions
+ at a time.
+ i.e. if more than one user thread need to call engine API
+ functions, the user has to take measures to avoid concurrency
+ in calling these functions, e.g. by using a GslMutex which is
+ to be locked around engine API calls.
+* MasterThread; the engine, if configured accordingly,
+ sets up one master thread which
+ - processes transactions from the UserThread
+ - schedules processing order of engine modules
+ - processes single modules when required
+ - processes module cycles when required
+ - passes back processed transactions and flow jobs to the
+ UserThread for garbage collection
+* SlaveThread; the engine can be configured to spawn slave threads which,
+ in addition to the master thread
+ - process single modules when required
+ - process module cycles when required
+
+Communication at thread boundaries:
+* Job transaction queue; the UserThread constructs job transactions and
+ enqueues them for the MasterThread. The UserThread also dequeues already
+ processed transactions, in order for destroy functions of modules and
+ accessors to only be executed within the UserThread.
+ Also, the UserThread can wait (block) until all pending transactions
+ have been processed by the MasterThread (in order to sync state with
+ module network contained in the engine).
+* Flow job collection list; the MasterThread adds processed flow jobs into
+ a collection queue, the UserThread then collects the queued flow jobs
+ and frees them.
+* Module/cycle pool; the MasterThread fills in the module/cycle pool with
+ modules which need to be processed. The MasterThread and the SlaveThreads
+ pop modules/cycles from this pool, process them, and push back processed
+ nodes.
+* load control; // FIXME
+
+Main loop integration:
+in order to process certain engine modules only from within
+the UserThread and to drive the engine even without master
+or slave threads, the engine can be hooked up to a main loop
+mechanism supplied by the UserThread.
+The engine provides API entry points to:
+- export file descriptors and timeout, suitable for main loop backends
+ such as poll(2)
+- check whether dispatching is necessary
+- dispatch outstanding work to be performed by the engine
+FIXME: needs mentioning of pollfd/callback jobs
+
+
+TODO:
+=====
+- virtualization (poke ibuffer into outbuffer) flag (needs memcpy for deferred nodes)
+- flag UserThread nodes
+- sample timed jobs
+- need global timestamp
+- need async-queues that have time-stamped jobs
+- process only so much samples until a time-stamped
+ job needs to be processed
+- self-input cycles need to be resolved in parent as well
+- node-locale async timestamped jobs
+- engine-init: { block(pipe-fd), check }
+- sample-timed activation can offset node's block-boundary
+- need complete_blocks_only flag in node classes
+- cost rating: cost*n_inputs+cost*n_outputs
+- multi-input(joint) streams: job_disconnect(dmod,distr,smod,sistr); (jstreams)
+
+Jan 07 2002 Tim Janik
+ * cosmetic updates, flow jobs
+Aug 19 2001 Tim Janik
+ * notes on threads, communication, main loops
+Jul 29 2001 Tim Janik
+ * wording/spelling fixups
+May 05 2001 Tim Janik
+ * initial writeup
+
+LocalWords: GSL API GslModule OpNode istreams ostreams A's B's sync
+LocalWords: gslengine GslMutex UserThread MasterThread SlaveThread SlaveThreads
diff --git a/flow/gsl/gsl.3 b/flow/gsl/gsl.3
new file mode 100644
index 0000000..2f7bb31
--- /dev/null
+++ b/flow/gsl/gsl.3
@@ -0,0 +1,822 @@
+.TH "GSL-Functions" 3 "17 May 2002" "BEAST-0.4.1" "BEAST-0.4.1"
+.SH NAME
+GSL-Functions \- GSL Function Reference
+.SH SYNOPSIS
+\fBgsl_thread_wakeup\fP (\fIthread\fP);
+.br
+\fBgsl_thread_abort\fP (\fIthread\fP);
+.br
+\fBgsl_thread_queue_abort\fP (\fIthread\fP);
+.br
+\fBgsl_thread_aborted\fP ();
+.br
+\fBgsl_thread_sleep\fP (\fImax_msec\fP);
+.br
+\fBgsl_thread_awake_after\fP (\fItick_stamp\fP);
+.br
+\fBgsl_thread_awake_before\fP (\fItick_stamp\fP);
+.br
+\fBgsl_tick_stamp\fP ();
+.br
+\fBgsl_data_find_block\fP (\fIhandle\fP, \fIn_values\fP, \fIvalues\fP, \fIepsilon\fP);
+.br
+\fBgsl_module_tick_stamp\fP (\fImodule\fP);
+.br
+\fBgsl_job_integrate\fP (\fImodule\fP);
+.br
+\fBgsl_job_discard\fP (\fImodule\fP);
+.br
+\fBgsl_job_connect\fP (\fIsrc_module\fP, \fIsrc_ostream\fP, \fIdest_module\fP, \fIdest_istream\fP);
+.br
+\fBgsl_job_disconnect\fP (\fIdest_module\fP, \fIdest_istream\fP);
+.br
+\fBGslAccessFunc\fP (\fImodule\fP, \fIdata\fP);
+.br
+\fBgsl_job_access\fP (\fImodule\fP, \fIaccess_func\fP, \fIdata\fP, \fIfree_func\fP);
+.br
+\fBgsl_flow_job_access\fP (\fImodule\fP, \fItick_stamp\fP, \fIaccess_func\fP, \fIdata\fP, \fIfree_func\fP);
+.br
+\fBGslPollFunc\fP (\fIdata\fP, \fIn_values\fP, \fItimeout_p\fP, \fIn_fds\fP, \fIfds\fP, \fIrevents_filled\fP);
+.br
+\fBgsl_job_add_poll\fP (\fIpoll_func\fP, \fIdata\fP, \fIfree_func\fP, \fIn_fds\fP, \fIfds\fP);
+.br
+\fBgsl_job_remove_poll\fP (\fIpoll_func\fP, \fIdata\fP);
+.br
+\fBgsl_job_debug\fP (\fIdebug\fP);
+.br
+\fBgsl_trans_open\fP ();
+.br
+\fBgsl_trans_add\fP (\fItrans\fP, \fIjob\fP);
+.br
+\fBgsl_trans_commit\fP (\fItrans\fP);
+.br
+\fBgsl_trans_dismiss\fP (\fItrans\fP);
+.br
+\fBgsl_transact\fP (\fIjob\fP, \fI...\fP);
+.br
+\fBgsl_engine_init\fP (\fIrun_threaded\fP, \fIblock_size\fP, \fIsample_freq\fP, \fIsub_sample_mask\fP);
+.br
+\fBgsl_engine_wait_on_trans\fP ();
+.br
+\fBgsl_power2_fftac\fP (\fIn_values\fP, \fIri_values_in\fP, \fIri_values_out\fP);
+.br
+\fBgsl_power2_fftsc\fP (\fIn_values\fP, \fIri_values_in\fP, \fIri_values_out\fP);
+.br
+\fBgsl_power2_fftar\fP (\fIn_values\fP, \fIr_values_in\fP, \fIri_values_out\fP);
+.br
+\fBgsl_power2_fftsr\fP (\fIn_values\fP, \fIri_values_in\fP, \fIr_values_out\fP);
+.br
+\fBgsl_filter_tscheb2_steepness_db\fP (\fIiorder\fP, \fIc_freq\fP, \fIepsilon\fP, \fIstopband_db\fP);
+.br
+\fBgsl_filter_tscheb2_steepness\fP (\fIiorder\fP, \fIc_freq\fP, \fIepsilon\fP, \fIresidue\fP);
+.br
+\fBgsl_filter_butter_lp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb1_lp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb2_lp\fP (\fIiorder\fP, \fIfreq\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_butter_hp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb1_hp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb2_hp\fP (\fIiorder\fP, \fIfreq\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_butter_bp\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb1_bp\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb2_bp\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_butter_bs\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb1_bs\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_tscheb2_bs\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.br
+\fBgsl_filter_fir_approx\fP (\fIiorder\fP, \fIfreq\fP, \fIvalue\fP);
+.br
+\fBgsl_filter_sine_scan\fP (\fIorder\fP, \fIa\fP, \fIb\fP, \fIfreq\fP, \fIn_values\fP);
+.br
+\fBgsl_engine_garbage_collect\fP ();
+.br
+\fBgsl_signal_exp2\fP ();
+.br
+\fBgsl_approx_exp2\fP (\fIex\fP);
+.br
+\fBgsl_approx_atan1\fP (\fIx\fP);
+.br
+\fBgsl_approx_atan1_prescale\fP (\fIboost_amount\fP);
+.br
+\fBgsl_approx_qcircle1\fP (\fIx\fP);
+.br
+\fBgsl_approx_qcircle2\fP (\fIx\fP);
+.br
+\fBgsl_approx_qcircle3\fP (\fIx\fP);
+.br
+\fBgsl_approx_qcircle4\fP (\fIx\fP);
+.br
+.SH DESCRIPTION
+.SS \fBgsl_thread_wakeup\fP (\fIthread\fP);
+.PD 0
+.IP \fIGslThread*\ thread\fP 19
+thread to wake up
+.PD 1
+.PP
+Wake up a currently sleeping thread. In practice, this function simply causes the next call to \fBgsl_thread_sleep()\fP within \fIthread\fP to last for 0 seconds.
+.PD
+.SS \fBgsl_thread_abort\fP (\fIthread\fP);
+.PD 0
+.IP \fIGslThread*\ thread\fP 19
+thread to abort
+.PD 1
+.PP
+Abort a currently running thread. This function does not return until the thread in question terminated execution. Note that the thread handle gets invalidated with invocation of \fBgsl_thread_abort()\fP or \fBgsl_thread_queue_abort()\fP.
+.PD
+.SS \fBgsl_thread_queue_abort\fP (\fIthread\fP);
+.PD 0
+.IP \fIGslThread*\ thread\fP 19
+thread to abort
+.PD 1
+.PP
+Same as \fBgsl_thread_abort()\fP, but returns as soon as possible, even if thread hasn't stopped execution yet. Note that the thread handle gets invalidated with invocation of \fBgsl_thread_abort()\fP or \fBgsl_thread_queue_abort()\fP.
+.PD
+.SS \fBgsl_thread_aborted\fP ();
+.PD 0
+.IP \fIRETURNS:\fP 11
+\fITRUE\fP if the thread should abort execution
+.PD 1
+.PP
+Find out if the currently running thread should be aborted (the thread is supposed to return from its main thread function).
+.PD
+.SS \fBgsl_thread_sleep\fP (\fImax_msec\fP);
+.PD 0
+.IP \fIglong\ \ max_msec\fP 17
+maximum amount of milli seconds to sleep (-1 for infinite time)
+.IP \fIRETURNS:\fP 17
+\fITRUE\fP if the thread should continue execution
+.PD 1
+.PP
+Sleep for the amount of time given. This function may get interrupted by wakeup or abort requests, it returns whether the thread is supposed to continue execution after waking up.
+.PD
+.SS \fBgsl_thread_awake_after\fP (\fItick_stamp\fP);
+.PD 0
+.IP \fIguint64\ \ tick_stamp\fP 21
+tick stamp update to trigger wakeup
+.PD 1
+.PP
+Wakeup the currently running thread after the global tick stamp (see \fBgsl_tick_stamp()\fP) has been updated to \fItick_stamp\fP. (If the moment of wakeup has already passed by, the thread is woken up at the next global tick stamp update.)
+.PD
+.SS \fBgsl_thread_awake_before\fP (\fItick_stamp\fP);
+.PD 0
+.IP \fIguint64\ \ tick_stamp\fP 21
+tick stamp update to trigger wakeup
+.PD 1
+.PP
+Wakeup the currently running thread upon the last global tick stamp update (see \fBgsl_tick_stamp()\fP) that happens prior to updating the global tick stamp to \fItick_stamp\fP. (If the moment of wakeup has already passed by, the thread is woken up at the next global tick stamp update.)
+.PD
+.SS \fBgsl_tick_stamp\fP ();
+.PD 0
+.IP \fIRETURNS:\fP 11
+GSL's execution tick stamp as unsigned 64bit integer
+.PD 1
+.PP
+Retrive the GSL global tick stamp. GSL increments its global tick stamp at certain intervals, by specific amounts (refer to \fBgsl_engine_init()\fP for further details). The tick stamp is a non-wrapping, unsigned 64bit integer greater than 0. Threads can schedule sleep interruptions at certain tick stamps with \fBgsl_thread_awake_after()\fP and \fBgsl_thread_awake_before()\fP. Tick stamp updating occours at GSL engine block processing boundaries, so code that can guarantee to not run across those boundaries (for instance \fBGslProcessFunc()\fP functions) may use the macro \fIGSL_TICK_STAMP\fP to retrive the current tick in a faster manner (not involving mutex locking). See also \fBgsl_module_tick_stamp()\fP.
+.PD
+.SS \fBgsl_data_find_block\fP (\fIhandle\fP, \fIn_values\fP, \fIvalues\fP, \fIepsilon\fP);
+.PD 0
+.IP \fIGslDataHandle*\ handle\fP 25
+an open GslDataHandle
+.IP \fIguint\ \ \ \ \ \ \ \ \ \ n_values\fP 25
+amount of values to look for
+.IP \fIconst\ gfloat*\ \ values\fP 25
+values to find
+.IP \fIgfloat\ \ \ \ \ \ \ \ \ epsilon\fP 25
+maximum difference upon comparisions
+.IP \fIRETURNS:\fP 25
+position of values in data handle or -1
+.PD 1
+.PP
+Find the position of a block of values within a data handle, where all values compare to the reference values with a delta smaller than epsilon.
+.PD
+.SS \fBgsl_module_tick_stamp\fP (\fImodule\fP);
+.PD 0
+.IP \fIGslModule*\ module\fP 19
+a GSL engine module
+.IP \fIRETURNS:\fP 19
+the module's tick stamp, indicating its process status
+.PD 1
+.PP
+Any thread may call this function on a valid engine module. The module specific tick stamp is updated to \fBgsl_tick_stamp()\fP + \fIn_values\fP every time its \fBGslProcessFunc()\fP function was called. See also \fBgsl_tick_stamp()\fP.
+.PD
+.SS \fBgsl_job_integrate\fP (\fImodule\fP);
+.PD 0
+.IP \fIGslModule*\ module\fP 19
+The module to integrate
+.IP \fIRETURNS:\fP 19
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job to integrate \fImodule\fP into the engine.
+.PD
+.SS \fBgsl_job_discard\fP (\fImodule\fP);
+.PD 0
+.IP \fIGslModule*\ module\fP 19
+The module to discard
+.IP \fIRETURNS:\fP 19
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which removes \fImodule\fP from the engine and destroys it.
+.PD
+.SS \fBgsl_job_connect\fP (\fIsrc_module\fP, \fIsrc_ostream\fP, \fIdest_module\fP, \fIdest_istream\fP);
+.PD 0
+.IP \fIGslModule*\ src_module\fP 25
+Module with output stream
+.IP \fIguint\ \ \ \ \ \ src_ostream\fP 25
+Index of output stream of \fIsrc_module\fP
+.IP \fIGslModule*\ dest_module\fP 25
+Module with unconnected input stream
+.IP \fIguint\ \ \ \ \ \ dest_istream\fP 25
+Index of input stream of \fIdest_module\fP
+.IP \fIRETURNS:\fP 25
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which connects the ouput stream \fIsrc_ostream\fP of module \fIsrc_module\fP to the input stream \fIdest_istream\fP of module \fIdest_module\fP (it is an error if the input stream is already connected by the time the job is executed).
+.PD
+.SS \fBgsl_job_disconnect\fP (\fIdest_module\fP, \fIdest_istream\fP);
+.PD 0
+.IP \fIGslModule*\ dest_module\fP 25
+Module with connected input stream
+.IP \fIguint\ \ \ \ \ \ dest_istream\fP 25
+Index of input stream of \fIdest_module\fP
+.IP \fIRETURNS:\fP 25
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which causes the input stream \fIdest_istream\fP of \fIdest_module\fP to be disconnected (it is an error if the input stream isn't connected by the time the job is executed).
+.PD
+.SS \fBGslAccessFunc\fP (\fImodule\fP, \fIdata\fP);
+.PD 0
+.IP \fI\ module\fP 9
+Module to operate on
+.IP \fI\ data\fP 9
+Accessor data
+.PD 1
+.PP
+The GslAccessFunc is a user supplied callback function which can access a module in times it is not processing. Accessors are usually used to either read out a module's current state, or to modify its state. An accessor may only operate on the \fIdata\fP and the \fImodule\fP passed in to it.
+.PD
+.SS \fBgsl_job_access\fP (\fImodule\fP, \fIaccess_func\fP, \fIdata\fP, \fIfree_func\fP);
+.PD 0
+.IP \fIGslModule*\ \ \ \ \ module\fP 28
+The module to access
+.IP \fIGslAccessFunc\ \ access_func\fP 28
+The accessor function
+.IP \fIgpointer\ \ \ \ \ \ \ data\fP 28
+Data passed in to the accessor
+.IP \fIGslFreeFunc\ \ \ \ free_func\fP 28
+Function to free \fIdata\fP
+.IP \fIRETURNS:\fP 28
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which will invoke \fIaccess_func\fP on \fImodule\fP with \fIdata\fP when the transaction queue is processed to modify the module's state.
+.PD
+.SS \fBgsl_flow_job_access\fP (\fImodule\fP, \fItick_stamp\fP, \fIaccess_func\fP, \fIdata\fP, \fIfree_func\fP);
+.PD 0
+.IP \fIGslModule*\ \ \ \ \ module\fP 28
+
+.IP \fIguint64\ \ \ \ \ \ \ \ tick_stamp\fP 28
+
+.IP \fIGslAccessFunc\ \ access_func\fP 28
+
+.IP \fIgpointer\ \ \ \ \ \ \ data\fP 28
+
+.IP \fIGslFreeFunc\ \ \ \ free_func\fP 28
+
+.PD 1
+.PP
+
+.PD
+.SS \fBGslPollFunc\fP (\fIdata\fP, \fIn_values\fP, \fItimeout_p\fP, \fIn_fds\fP, \fIfds\fP, \fIrevents_filled\fP);
+.PD 0
+.IP \fI\ data\fP 17
+Data of poll function
+.IP \fI\ n_values\fP 17
+Minimum number of values the engine wants to process
+.IP \fI\ timeout_p\fP 17
+Location of timeout value
+.IP \fI\ n_fds\fP 17
+Number of file descriptors used for polling
+.IP \fI\ fds\fP 17
+File descriptors to be used for polling
+.IP \fI\ revents_filled\fP 17
+Indicates whether \fIfds\fP actually have their ->revents field filled with valid data.
+.IP \fIRETURNS:\fP 17
+A boolean value indicating whether the engine should process data right now
+.PD 1
+.PP
+The GslPollFunc is a user supplied callback function which can be hooked into the GSL engine. The engine uses the poll functions to determine whether processing of \fIn_values\fP in its module network is necessary. In order for the poll functions to react to extern events, such as device driver status changes, the engine will \fBpoll(2)\fP the \fIfds\fP of the poll function and invoke the callback with \fIrevents_filled\fP==\fITRUE\fP if any of its \fIfds\fP changed state. The callback may also be invoked at other random times with \fIrevents_filled\fP=\fIFALSE\fP. It is supposed to return \fITRUE\fP if network processing is currently necessary, and \fIFALSE\fP if not. If \fIFALSE\fP is returned, \fItimeout_p\fP may be filled with the number of milliseconds the engine should use for polling at maximum.
+.PD
+.SS \fBgsl_job_add_poll\fP (\fIpoll_func\fP, \fIdata\fP, \fIfree_func\fP, \fIn_fds\fP, \fIfds\fP);
+.PD 0
+.IP \fIGslPollFunc\ \ \ \ \ \ poll_func\fP 28
+Poll function to add
+.IP \fIgpointer\ \ \ \ \ \ \ \ \ data\fP 28
+Data of poll function
+.IP \fIGslFreeFunc\ \ \ \ \ \ free_func\fP 28
+Function to free \fIdata\fP
+.IP \fIguint\ \ \ \ \ \ \ \ \ \ \ \ n_fds\fP 28
+Number of poll file descriptors
+.IP \fIconst\ GslPollFD*\ fds\fP 28
+File descriptors to \fBselect(2)\fP or \fBpoll(2)\fP on
+.IP \fIRETURNS:\fP 28
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which adds a poll function to the engine. The poll function is used by the engine to determine whether processing is currently necessary.
+.PD
+.SS \fBgsl_job_remove_poll\fP (\fIpoll_func\fP, \fIdata\fP);
+.PD 0
+.IP \fIGslPollFunc\ \ poll_func\fP 24
+Poll function to remove
+.IP \fIgpointer\ \ \ \ \ data\fP 24
+Data of poll function
+.IP \fIRETURNS:\fP 24
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which removes a previously inserted poll function from the engine.
+.PD
+.SS \fBgsl_job_debug\fP (\fIdebug\fP);
+.PD 0
+.IP \fIconst\ gchar*\ debug\fP 20
+Debug message
+.IP \fIRETURNS:\fP 20
+New job suitable for \fBgsl_trans_add()\fP
+.PD 1
+.PP
+Create a new transaction job which issues \fIdebug\fP message when the job is executed. This function is meant for debugging purposes during development phase only and shouldn't be used in production code.
+.PD
+.SS \fBgsl_trans_open\fP ();
+.PD 0
+.IP \fIRETURNS:\fP 11
+Newly opened empty transaction
+.PD 1
+.PP
+Open up a new transaction to commit jobs to the GSL engine. This function may cause garbage collection (see \fBgsl_engine_garbage_collect()\fP).
+.PD
+.SS \fBgsl_trans_add\fP (\fItrans\fP, \fIjob\fP);
+.PD 0
+.IP \fIGslTrans*\ trans\fP 17
+Opened transaction
+.IP \fIGslJob*\ \ \ job\fP 17
+Job to add
+.PD 1
+.PP
+Append a job to an opened transaction.
+.PD
+.SS \fBgsl_trans_commit\fP (\fItrans\fP);
+.PD 0
+.IP \fIGslTrans*\ trans\fP 17
+Opened transaction
+.PD 1
+.PP
+Close the transaction and commit it to the engine. The engine will execute the jobs contained in this transaction as soon as it has completed its current processing cycle. The jobs will be executed in the exact order they were added to the transaction.
+.PD
+.SS \fBgsl_trans_dismiss\fP (\fItrans\fP);
+.PD 0
+.IP \fIGslTrans*\ trans\fP 17
+Opened transaction
+.PD 1
+.PP
+Close and discard the transaction, destroy all jobs currently contained in it and do not execute them. This function may cause garbage collection (see \fBgsl_engine_garbage_collect()\fP).
+.PD
+.SS \fBgsl_transact\fP (\fIjob\fP, \fI...\fP);
+.PD 0
+.IP \fI\ job\fP 6
+First job
+.IP \fI\ ...\fP 6
+\fINULL\fP terminated job list
+.PD 1
+.PP
+Convenience function which openes up a new transaction, collects the \fINULL\fP terminated job list passed to the function, and commits the transaction.
+.PD
+.SS \fBgsl_engine_init\fP (\fIrun_threaded\fP, \fIblock_size\fP, \fIsample_freq\fP, \fIsub_sample_mask\fP);
+.PD 0
+.IP \fIgboolean\ \ run_threaded\fP 27
+
+.IP \fIguint\ \ \ \ \ block_size\fP 27
+number of values to process block wise
+.IP \fIguint\ \ \ \ \ sample_freq\fP 27
+
+.IP \fIguint\ \ \ \ \ sub_sample_mask\fP 27
+
+.PD 1
+.PP
+Initialize the GSL engine, this function must be called prior to any other engine related function and can only be invoked once. The \fIblock_size\fP determines the amount by which the global tick stamp (see \fBgsl_tick_stamp()\fP) is updated everytime the whole module network completed processing \fIblock_size\fP values.
+.PD
+.SS \fBgsl_engine_wait_on_trans\fP ();
+.PD 0
+.PD 1
+.PP
+Wait until all pending transactions have been processed by the GSL Engine. This function may cause garbage collection (see \fBgsl_engine_garbage_collect()\fP).
+.PD
+.SS \fBgsl_power2_fftac\fP (\fIn_values\fP, \fIri_values_in\fP, \fIri_values_out\fP);
+.PD 0
+.IP \fI\ n_values\fP 16
+Number of complex values
+.IP \fI\ ri_values_in\fP 16
+Complex sample values [0..n_values*2-1]
+.IP \fI\ ri_values_out\fP 16
+Complex frequency values [0..n_values*2-1]
+.PD 1
+.PP
+This function performs a decimation in time fourier transformation in forward direction, where the input values are equidistant sampled data, and the output values contain the frequency proportions of the input. The input and output arrays are complex values with real and imaginery portions interleaved, adressable in the range [0..2*n_values-1], where n_values must be a power of two. Frequencies are stored in-order, the K-th output corresponds to the frequency K/n_values. (If you want to interpret negative frequencies, note that the frequencies -K/n_values and (n_values-K)/n_values are equivalent). Note that the transformation is performed out of place, the input array is not modified, and may not overlap with the output array.
+.PD
+.SS \fBgsl_power2_fftsc\fP (\fIn_values\fP, \fIri_values_in\fP, \fIri_values_out\fP);
+.PD 0
+.IP \fI\ n_values\fP 16
+Number of complex values
+.IP \fI\ ri_values_in\fP 16
+Complex frequency values [0..n_values*2-1]
+.IP \fI\ ri_values_out\fP 16
+Complex sample values [0..n_values*2-1]
+.PD 1
+.PP
+This function performs a decimation in time fourier transformation in backwards direction with normalization. As such, this function represents the counterpart to \fBgsl_power2_fftac()\fP, that is, a value array which is transformed into the frequency domain with \fBgsl_power2_fftac()\fP can be reconstructed by issuing \fBgsl_power2_fftsc()\fP on the transform. Note that the transformation is performed out of place, the input array is not modified, and may not overlap with the output array.
+.PD
+.SS \fBgsl_power2_fftar\fP (\fIn_values\fP, \fIr_values_in\fP, \fIri_values_out\fP);
+.PD 0
+.IP \fI\ n_values\fP 16
+Number of complex values
+.IP \fI\ r_values_in\fP 16
+Real sample values [0..n_values-1]
+.IP \fI\ ri_values_out\fP 16
+Complex frequency values [0..n_values-1]
+.PD 1
+.PP
+Real valued variant of \fBgsl_power2_fftac()\fP, the input array contains real valued equidistant sampled data [0..n_values-1], and the output array contains the positive frequency half of the complex valued fourier transform. Note, that the complex valued fourier transform H of a purely real valued set of data, satisfies \fBH(-f)\fP = Conj(\fBH(f)\fP), where \fBConj()\fP denotes the complex conjugate, so that just the positive frequency half suffices to describe the entire frequency spectrum. Even so, the resulting n_values/2 complex frequencies are one value off in storage size, but the resulting frequencies \fBH(0)\fP and \fBH(n_values/2)\fP are both real valued, so the real portion of \fBH(n_values/2)\fP is stored in ri_values_out[1] (the imaginery part of \fBH(0)\fP), so that both r_values_in and ri_values_out can be of size n_values. Note that the transformation is performed out of place, the input array is not modified, and may not overlap with the output array.
+.PD
+.SS \fBgsl_power2_fftsr\fP (\fIn_values\fP, \fIri_values_in\fP, \fIr_values_out\fP);
+.PD 0
+.IP \fI\ n_values\fP 15
+Number of complex values
+.IP \fI\ ri_values_in\fP 15
+Complex frequency values [0..n_values-1]
+.IP \fI\ r_values_out\fP 15
+Real sample values [0..n_values-1]
+.PD 1
+.PP
+Real valued variant of \fBgsl_power2_fftsc()\fP, counterpart to \fBgsl_power2_fftar()\fP, using the same frequency storage format. A real valued data set transformed into the frequency domain with \fBgsl_power2_fftar()\fP can be reconstructed using this function. Note that the transformation is performed out of place, the input array is not modified, and may not overlap with the output array.
+.PD
+.SS \fBgsl_filter_tscheb2_steepness_db\fP (\fIiorder\fP, \fIc_freq\fP, \fIepsilon\fP, \fIstopband_db\fP);
+.PD 0
+.IP \fIunsigned\ int\ \ iorder\fP 27
+filter order
+.IP \fIdouble\ \ \ \ \ \ \ \ c_freq\fP 27
+passband cutoff frequency (0..pi)
+.IP \fIdouble\ \ \ \ \ \ \ \ epsilon\fP 27
+fall off at passband frequency (0..1)
+.IP \fIdouble\ \ \ \ \ \ \ \ stopband_db\fP 27
+reduction in stopband in dB (>= 0)
+.PD 1
+.PP
+Calculates the steepness parameter for Tschebyscheff type 2 lowpass filter, based on the ripple residue in the stop band.
+.PD
+.SS \fBgsl_filter_tscheb2_steepness\fP (\fIiorder\fP, \fIc_freq\fP, \fIepsilon\fP, \fIresidue\fP);
+.PD 0
+.IP \fIunsigned\ int\ \ iorder\fP 23
+filter order
+.IP \fIdouble\ \ \ \ \ \ \ \ c_freq\fP 23
+passband cutoff frequency (0..pi)
+.IP \fIdouble\ \ \ \ \ \ \ \ epsilon\fP 23
+fall off at passband frequency (0..1)
+.IP \fIdouble\ \ \ \ \ \ \ \ residue\fP 23
+maximum of transfer function in stopband (0..1)
+.PD 1
+.PP
+Calculates the steepness parameter for Tschebyscheff type 2 lowpass filter, based on ripple residue in the stop band.
+.PD
+.SS \fBgsl_filter_butter_lp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order
+.IP \fI\ freq\fP 10
+cutoff frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at cutoff frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Butterworth lowpass filter.
+.PD
+.SS \fBgsl_filter_tscheb1_lp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order
+.IP \fI\ freq\fP 10
+cutoff frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at cutoff frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 1 lowpass filter.
+.PD
+.SS \fBgsl_filter_tscheb2_lp\fP (\fIiorder\fP, \fIfreq\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 12
+filter order
+.IP \fI\ freq\fP 12
+passband cutoff frequency (0..pi)
+.IP \fI\ steepness\fP 12
+frequency steepness (c_freq * steepness < pi)
+.IP \fI\ epsilon\fP 12
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 12
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 12
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 2 lowpass filter. To gain a transition band between freq1 and freq2, pass arguements \fIfreq\fP=freq1 and \fIsteepness\fP=freq2/freq1. To specify the transition band width in fractions of octaves, pass \fIsteepness\fP=2^octave_fraction.
+.PD
+.SS \fBgsl_filter_butter_hp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order
+.IP \fI\ freq\fP 10
+passband frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Butterworth highpass filter.
+.PD
+.SS \fBgsl_filter_tscheb1_hp\fP (\fIiorder\fP, \fIfreq\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order
+.IP \fI\ freq\fP 10
+passband frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 1 highpass filter.
+.PD
+.SS \fBgsl_filter_tscheb2_hp\fP (\fIiorder\fP, \fIfreq\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 12
+filter order
+.IP \fI\ freq\fP 12
+stopband frequency (0..pi)
+.IP \fI\ steepness\fP 12
+frequency steepness
+.IP \fI\ epsilon\fP 12
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 12
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 12
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 2 highpass filter.
+.PD
+.SS \fBgsl_filter_butter_bp\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order (must be even)
+.IP \fI\ freq1\fP 10
+stopband end frequency (0..pi)
+.IP \fI\ freq2\fP 10
+passband end frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Butterworth bandpass filter.
+.PD
+.SS \fBgsl_filter_tscheb1_bp\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order (must be even)
+.IP \fI\ freq1\fP 10
+stopband end frequency (0..pi)
+.IP \fI\ freq2\fP 10
+passband end frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 1 bandpass filter.
+.PD
+.SS \fBgsl_filter_tscheb2_bp\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 12
+filter order (must be even)
+.IP \fI\ freq1\fP 12
+stopband end frequency (0..pi)
+.IP \fI\ freq2\fP 12
+passband end frequency (0..pi)
+.IP \fI\ steepness\fP 12
+frequency steepness factor
+.IP \fI\ epsilon\fP 12
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 12
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 12
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 2 bandpass filter.
+.PD
+.SS \fBgsl_filter_butter_bs\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order (must be even)
+.IP \fI\ freq1\fP 10
+passband end frequency (0..pi)
+.IP \fI\ freq2\fP 10
+stopband end frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Butterworth bandstop filter.
+.PD
+.SS \fBgsl_filter_tscheb1_bs\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 10
+filter order (must be even)
+.IP \fI\ freq1\fP 10
+passband end frequency (0..pi)
+.IP \fI\ freq2\fP 10
+stopband end frequency (0..pi)
+.IP \fI\ epsilon\fP 10
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 10
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 10
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 1 bandstop filter.
+.PD
+.SS \fBgsl_filter_tscheb2_bs\fP (\fIiorder\fP, \fIfreq1\fP, \fIfreq2\fP, \fIsteepness\fP, \fIepsilon\fP, \fIa\fP, \fIb\fP);
+.PD 0
+.IP \fI\ iorder\fP 12
+filter order (must be even)
+.IP \fI\ freq1\fP 12
+passband end frequency (0..pi)
+.IP \fI\ freq2\fP 12
+stopband end frequency (0..pi)
+.IP \fI\ steepness\fP 12
+frequency steepness factor
+.IP \fI\ epsilon\fP 12
+fall off at passband frequency (0..1)
+.IP \fI\ a\fP 12
+root polynomial coefficients a[0..iorder]
+.IP \fI\ b\fP 12
+pole polynomial coefficients b[0..iorder]
+.PD 1
+.PP
+Tschebyscheff type 2 bandstop filter.
+.PD
+.SS \fBgsl_filter_fir_approx\fP (\fIiorder\fP, \fIfreq\fP, \fIvalue\fP);
+.PD 0
+.IP \fI\ iorder\fP 9
+order of the filter (must be oven, >= 2)
+.IP \fI\ freq\fP 9
+the frequencies of the transfer function
+.IP \fI\ value\fP 9
+the desired value of the transfer function
+.PD 1
+.PP
+Approximates a given transfer function with an iorder-coefficient FIR filter. It is recommended to provide enough frequency values, so that \fIn_points\fP >= \fIiorder\fP.
+.PD
+.SS \fBgsl_filter_sine_scan\fP (\fIorder\fP, \fIa\fP, \fIb\fP, \fIfreq\fP, \fIn_values\fP);
+.PD 0
+.IP \fIguint\ \ \ \ \ \ \ \ \ \ order\fP 25
+order of the iir filter
+.IP \fIconst\ gdouble*\ a\fP 25
+root polynomial coefficients of the filter a[0..order]
+.IP \fIconst\ gdouble*\ b\fP 25
+pole polynomial coefficients of the filter b[0..order]
+.IP \fIgdouble\ \ \ \ \ \ \ \ freq\fP 25
+frequency to test
+.IP \fIguint\ \ \ \ \ \ \ \ \ \ n_values\fP 25
+number of samples
+.PD 1
+.PP
+This function sends a sine signal of the desired frequency through an IIR filter, to test the value of the transfer function at a given point. It uses gsl_iir_filter_eval to do so. Compared to a "mathematical approach" of finding the transfer function, this function makes it possible to see the effects of finite arithmetic during filter evaluation. The first half of the output signal is not considered, since a lot of IIR filters have a transient phase where also overshoot is possible. For n_values, you should specify a reasonable large value. It should be a lot larger than the filter order, and large enough to let the input signal become (close to) 1.0 multiple times.
+.PD
+.SS \fBgsl_engine_garbage_collect\fP ();
+.PD 0
+.PD 1
+.PP
+GSL Engine user thread function. Collects processed jobs and transactions from the engine and frees them, this involves callback invocation of \fBGslFreeFunc()\fP functions, e.g. from \fBgsl_job_access()\fP or \fBgsl_flow_job_access()\fP jobs. This function may only be called from the user thread, as \fBGslFreeFunc()\fP functions are guranteed to be executed in the user thread.
+.PD
+.SS \fBgsl_signal_exp2\fP ();
+.PD 0
+.PD 1
+.PP
+Deprecated in favour of \fBgsl_approx_exp2()\fP.
+.PD
+.SS \fBgsl_approx_exp2\fP (\fIex\fP);
+.PD 0
+.IP \fIfloat\ \ ex\fP 11
+exponent within [-127..127]
+.IP \fIRETURNS:\fP 11
+y approximating 2^x
+.PD 1
+.PP
+Fast approximation of 2 raised to the power of x. Multiplicative error stays below 8e-6 and aproaches zero for integer values of x (i.e. x - floor (x) = 0).
+.PD
+.SS \fBgsl_approx_atan1\fP (\fIx\fP);
+.PD 0
+.IP \fIregister\ double\ \ x\fP 20
+
+.PD 1
+.PP
+Fast \fBatan(x)\fP/(PI/2) approximation, with maximum error < 0.01 and \fBgsl_approx_atan1(0)\fP==0, according to the formula: n1 = -0.41156875521951602506487246309908; n2 = -1.0091272542790025586079663559158; d1 = 0.81901156857081841441890603235599; d2 = 1.0091272542790025586079663559158; \fBpositive_atan1(x)\fP = 1 + (n1 * x + n2) / ((1 + d1 * x) * x + d2);
+.PD
+.SS \fBgsl_approx_atan1_prescale\fP (\fIboost_amount\fP);
+.PD 0
+.IP \fI\ boost_amount\fP 15
+boost amount between [0..1]
+.IP \fIRETURNS:\fP 15
+prescale factor for \fBgsl_approx_atan1()\fP
+.PD 1
+.PP
+Calculate the prescale factor for \fBgsl_approx_atan1(x*prescale)\fP from a linear boost factor, where 0.5 amounts to prescale=1.0, 1.0 results in maximum boost and 0.0 results in maximum attenuation.
+.PD
+.SS \fBgsl_approx_qcircle1\fP (\fIx\fP);
+.PD 0
+.IP \fIregister\ double\ \ x\fP 20
+x within [0..1]
+.IP \fIRETURNS:\fP 20
+y for circle approximation within [0..1]
+.PD 1
+.PP
+Fast approximation of the upper right quadrant of a circle. Errors at x=0 and x=1 are zero, for the rest of the curve, the error wasn't minimized, but distributed to best fit the curverture of a quarter circle. The maximum error is below 0.092.
+.PD
+.SS \fBgsl_approx_qcircle2\fP (\fIx\fP);
+.PD 0
+.IP \fIregister\ double\ \ x\fP 20
+x within [0..1]
+.IP \fIRETURNS:\fP 20
+y for circle approximation within [0..1]
+.PD 1
+.PP
+Fast approximation of the upper left quadrant of a circle. Errors at x=0 and x=1 are zero, for the rest of the curve, the error wasn't minimized, but distributed to best fit the curverture of a quarter circle. The maximum error is below 0.092.
+.PD
+.SS \fBgsl_approx_qcircle3\fP (\fIx\fP);
+.PD 0
+.IP \fIregister\ double\ \ x\fP 20
+x within [0..1]
+.IP \fIRETURNS:\fP 20
+y for circle approximation within [0..1]
+.PD 1
+.PP
+Fast approximation of the lower left quadrant of a circle. Errors at x=0 and x=1 are zero, for the rest of the curve, the error wasn't minimized, but distributed to best fit the curverture of a quarter circle. The maximum error is below 0.092.
+.PD
+.SS \fBgsl_approx_qcircle4\fP (\fIx\fP);
+.PD 0
+.IP \fIregister\ double\ \ x\fP 20
+x within [0..1]
+.IP \fIRETURNS:\fP 20
+y for circle approximation within [0..1]
+.PD 1
+.PP
+Fast approximation of the lower right quadrant of a circle. Errors at x=0 and x=1 are zero, for the rest of the curve, the error wasn't minimized, but distributed to best fit the curverture of a quarter circle. The maximum error is below 0.092.
+.PD
+
diff --git a/flow/gsl/gsl.gnuplot b/flow/gsl/gsl.gnuplot
new file mode 100644
index 0000000..e50c2ae
--- /dev/null
+++ b/flow/gsl/gsl.gnuplot
@@ -0,0 +1,5 @@
+dB(x)=20*log(abs(x))/log(10) # logarithmische Filterdarstellung in dB (s/20/10/ for abs(x)^2)
+s2z(s)=(1+s)/(1-s) # s-Ebene -> z-Ebene (bilinear Trans.)
+j={0,1} # sqrt(-1)
+Z(x)=exp({0,-1}*x) # gnuplot laufvariable x fuer H(z)
+set samples 4000 # more accuracy
diff --git a/flow/gsl/gslarrows b/flow/gsl/gslarrows
new file mode 100644
index 0000000..04ba5e4
--- /dev/null
+++ b/flow/gsl/gslarrows
@@ -0,0 +1,30 @@
+
+
+# $0+0 == number of arrows
+# $1+0 = first arrow
+# $2+0 = second arrow
+# e.g.
+# gnuplot> call "arrows" 3 "2*3" "0.5*pi" "sqrt(7)"
+
+#debug-args # 0:$0 1:$1 2:$2 3:$3 4:$4 5:$5 6:$6 7:$7 8:$8 9:$9
+
+
+arrow_line_type=0
+set arrow 1 from first $1+0,graph 0 to first $1+0,graph 1 nohead lt arrow_line_type
+set arrow 2 from first $2+0,graph 0 to first $2+0,graph 1 nohead lt arrow_line_type
+set arrow 3 from first $3+0,graph 0 to first $3+0,graph 1 nohead lt arrow_line_type
+set arrow 4 from first $4+0,graph 0 to first $4+0,graph 1 nohead lt arrow_line_type
+set arrow 5 from first $5+0,graph 0 to first $5+0,graph 1 nohead lt arrow_line_type
+set arrow 6 from first $6+0,graph 0 to first $6+0,graph 1 nohead lt arrow_line_type
+set arrow 7 from first $7+0,graph 0 to first $7+0,graph 1 nohead lt arrow_line_type
+set arrow 8 from first $8+0,graph 0 to first $8+0,graph 1 nohead lt arrow_line_type
+set arrow 9 from first $9+0,graph 0 to first $9+0,graph 1 nohead lt arrow_line_type
+if ($0+0 < 9) set noarrow 9
+if ($0+0 < 8) set noarrow 8
+if ($0+0 < 7) set noarrow 7
+if ($0+0 < 6) set noarrow 6
+if ($0+0 < 5) set noarrow 5
+if ($0+0 < 4) set noarrow 4
+if ($0+0 < 3) set noarrow 3
+if ($0+0 < 2) set noarrow 2
+if ($0+0 < 1) set noarrow 1
diff --git a/flow/gsl/gslartsthreads.cc b/flow/gsl/gslartsthreads.cc
new file mode 100644
index 0000000..98094b7
--- /dev/null
+++ b/flow/gsl/gslartsthreads.cc
@@ -0,0 +1,205 @@
+ /*
+
+ Copyright (C) 2001-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "thread.h"
+#include "debug.h"
+#include "gslglib.h"
+#include <pthread.h>
+
+#if defined(__DECCXX)
+#define EXTC extern "C"
+#else
+#define EXTC
+#endif
+
+EXTC gpointer
+gsl_arts_mutex_new ()
+{
+ return new Arts::Mutex;
+}
+
+EXTC void
+gsl_arts_mutex_free (gpointer mutex)
+{
+ Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex);
+ delete m;
+}
+
+EXTC void
+gsl_arts_mutex_lock (gpointer mutex)
+{
+ Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex);
+ m->lock();
+}
+
+EXTC gboolean
+gsl_arts_mutex_trylock (gpointer mutex)
+{
+ Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex);
+ return m->tryLock();
+}
+
+EXTC void
+gsl_arts_mutex_unlock (gpointer mutex)
+{
+ Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex);
+ m->unlock();
+}
+
+EXTC gpointer
+gsl_arts_cond_new ()
+{
+ return new Arts::ThreadCondition;
+}
+
+EXTC void
+gsl_arts_cond_free (gpointer cond)
+{
+ Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond);
+ delete c;
+}
+
+EXTC void
+gsl_arts_cond_signal (gpointer cond)
+{
+ Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond);
+ c->wakeOne();
+}
+
+EXTC void
+gsl_arts_cond_broadcast (gpointer cond)
+{
+ Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond);
+ c->wakeAll();
+}
+
+EXTC void
+gsl_arts_cond_wait (gpointer cond, gpointer mutex)
+{
+ Arts::ThreadCondition *c = static_cast<Arts::ThreadCondition *>(cond);
+ Arts::Mutex *m = static_cast<Arts::Mutex *>(mutex);
+
+ c->wait(*m);
+}
+
+EXTC void
+gsl_arts_cond_timed_wait (gpointer /*cond*/, gpointer /*mutex*/, GTimeVal * /*time*/)
+{
+ arts_assert(false);
+}
+
+
+class GslArtsThread : public Arts::Thread {
+protected:
+ gpointer (*func)(gpointer data);
+ gpointer data;
+ gpointer result;
+
+public:
+ GThread gthread;
+
+ GslArtsThread(gpointer (*func)(gpointer data), gpointer data)
+ : func(func), data(data)
+ {
+ gthread.data = 0;
+ }
+ void run()
+ {
+ result = func(data);
+ }
+};
+
+
+/* KCC (KAI C++) is buggy. If we write out the type of the first argument
+ to gsl_arts_thread_create(), ala
+ gsl_arts_thread_create (gpointer (*func) (gpointer data2), ...)
+ it becomes C++ linkage, i.e. it's name gets mangled, _despite_ declared
+ extern "C" in the header. Other sources only calling this function,
+ i.e. those only seeing the prototype correctly call the unmangled
+ extern "C" variant, but for the above reason it isn't defined anywhere.
+ The solution is to go through a typedef for that argument, _which must
+ also be declared extern "C"_. I'm not sure, but I think it's an error
+ of KCC, that it puts the invisible type of the first arg into C++ mode,
+ although the whole function should be C only. If one declares
+ two equal function types, one extern "C", one not, they are even assignment
+ compatible. But somehow KCC puts that type into C++ mode, which for
+ other strange reasons force the whole function to go into C++ linkage.
+ It's enough, when this typedef is local to this file. (matz) */
+
+/* Due to gcc's unhappyness with 'extern "C" typedef ...' we enclose
+ it in a real extern "C" {} block. */
+extern "C" {
+typedef gpointer (*t_func)(gpointer data2);
+}
+
+// This is C++:
+GThread* gsl_arts_thread_create_full_CPP(gpointer (*func)(gpointer data),
+ gpointer data,
+ gulong /*stack_size*/,
+ gboolean /*joinable*/,
+ gboolean /*bound*/,
+ GThreadPriority /*priority*/,
+ GError ** /*error*/)
+{
+ GslArtsThread *thread = new GslArtsThread(func, data);
+ return &thread->gthread;
+}
+
+// This is C:
+extern "C" GThread*
+gsl_arts_thread_create_full(gpointer (*func)(gpointer data),
+ gpointer data,
+ gulong stack_size,
+ gboolean joinable,
+ gboolean bound,
+ GThreadPriority priority,
+ GError **error)
+{
+ return gsl_arts_thread_create_full_CPP(func,
+ data,
+ stack_size,
+ joinable,
+ bound,
+ priority,
+ error);
+}
+
+EXTC gpointer
+gsl_arts_thread_self ()
+{
+ GslArtsThread *current = static_cast<GslArtsThread *>(Arts::SystemThreads::the()->getCurrentThread());
+
+ if(current)
+ return &current->gthread;
+ else
+ {
+ static GThread mainThread = { 0, };
+ return &mainThread;
+ }
+}
+
+EXTC void
+gsl_arts_thread_init (gpointer /*arg*/)
+{
+}
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gslartsthreads.h b/flow/gsl/gslartsthreads.h
new file mode 100644
index 0000000..c9ebf19
--- /dev/null
+++ b/flow/gsl/gslartsthreads.h
@@ -0,0 +1,102 @@
+ /*
+
+ Copyright (C) 2001-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef GSLARTSTHREADS_H
+#define GSLARTSTHREADS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* --- typedefs & structures --- */
+
+typedef struct _GError {
+ const char *message;
+} GError;
+
+typedef struct _GThread {
+ void *data;
+} GThread;
+
+typedef enum
+{
+ G_THREAD_PRIORITY_LOW,
+ G_THREAD_PRIORITY_NORMAL,
+ G_THREAD_PRIORITY_HIGH,
+ G_THREAD_PRIORITY_URGENT
+} GThreadPriority;
+
+#define g_mutex_lock gsl_arts_mutex_lock
+#define g_mutex_trylock gsl_arts_mutex_trylock
+#define g_mutex_unlock gsl_arts_mutex_unlock
+#define g_mutex_new gsl_arts_mutex_new
+#define g_mutex_free gsl_arts_mutex_free
+
+#define g_cond_new gsl_arts_cond_new
+#define g_cond_free gsl_arts_cond_free
+#define g_cond_signal gsl_arts_cond_signal
+#define g_cond_broadcast gsl_arts_cond_broadcast
+#define g_cond_wait gsl_arts_cond_wait
+#define g_cond_timed_wait gsl_arts_cond_timed_wait
+
+#define g_thread_create_full gsl_arts_thread_create_full
+#define g_thread_self gsl_arts_thread_self
+
+#define g_thread_init gsl_arts_thread_init
+
+#define g_error_free(x) g_assert_not_reached()
+
+/* --- prototypes --- */
+
+gpointer gsl_arts_mutex_new ();
+void gsl_arts_mutex_free (gpointer mutex);
+void gsl_arts_mutex_lock (gpointer mutex);
+gboolean gsl_arts_mutex_trylock (gpointer mutex);
+void gsl_arts_mutex_unlock (gpointer mutex);
+
+gpointer gsl_arts_cond_new ();
+void gsl_arts_cond_free (gpointer cond);
+void gsl_arts_cond_signal (gpointer cond);
+void gsl_arts_cond_broadcast (gpointer cond);
+void gsl_arts_cond_wait (gpointer cond, gpointer mutex);
+void gsl_arts_cond_timed_wait (gpointer cond, gpointer mutex, GTimeVal *abstime);
+
+GThread* gsl_arts_thread_create_full(gpointer (*func)(gpointer data),
+ gpointer data,
+ gulong stack_size,
+ gboolean joinable,
+ gboolean bound,
+ GThreadPriority priority,
+ GError **error);
+
+gpointer gsl_arts_thread_self ();
+
+void gsl_arts_thread_init (gpointer arg);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/* vim:set ts=8 sts=2 sw=2: */
+
+#endif // GSLARTSTHREADS_H
+
diff --git a/flow/gsl/gslcommon.c b/flow/gsl/gslcommon.c
new file mode 100644
index 0000000..cb16b05
--- /dev/null
+++ b/flow/gsl/gslcommon.c
@@ -0,0 +1,1651 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "gslcommon.h"
+#include "gsldatacache.h"
+
+/* some systems don't have ERESTART (which is what linux returns for system
+ * calls on pipes which are being interrupted). most propably just use EINTR,
+ * and maybe some can return both. so we check for both in the below code,
+ * and alias ERESTART to EINTR if it's not present. compilers are supposed
+ * to catch and optimize the doubled check arising from this.
+ */
+#ifndef ERESTART
+#define ERESTART EINTR
+#endif
+
+
+#define PREALLOC (8)
+#define SIMPLE_CACHE_SIZE (64)
+#define TS8_SIZE (MAX (sizeof (GTrashStack), 8))
+#define DBG8_SIZE (MAX (sizeof (gsize), 8))
+
+
+/* --- variables --- */
+volatile guint64 gsl_externvar_tick_stamp = 0;
+static guint64 tick_stamp_system_time = 0;
+static guint global_tick_stamp_leaps = 0;
+static GslDebugFlags gsl_debug_flags = 0;
+
+
+/* --- memory allocation --- */
+static GslMutex global_memory = { 0, };
+static GTrashStack *simple_cache[SIMPLE_CACHE_SIZE] = { 0, 0, 0, /* ... */ };
+static gulong memory_allocated = 0;
+
+const guint
+gsl_alloc_upper_power2 (const gulong number)
+{
+ return number ? 1 << g_bit_storage (number - 1) : 0;
+}
+
+static inline gpointer
+low_alloc (gsize mem_size)
+{
+ gpointer mem;
+
+ if (mem_size >= TS8_SIZE && mem_size / 8 < SIMPLE_CACHE_SIZE)
+ {
+ guint cell;
+
+ mem_size = (mem_size + 7) & ~0x7;
+ cell = (mem_size >> 3) - 1;
+ GSL_SPIN_LOCK (&global_memory);
+ mem = g_trash_stack_pop (simple_cache + cell);
+ GSL_SPIN_UNLOCK (&global_memory);
+ if (!mem)
+ {
+ guint8 *cache_mem = g_malloc (mem_size * PREALLOC);
+ guint i;
+
+ GSL_SPIN_LOCK (&global_memory);
+ memory_allocated += mem_size * PREALLOC;
+ for (i = 0; i < PREALLOC - 1; i++)
+ {
+ g_trash_stack_push (simple_cache + cell, cache_mem);
+ cache_mem += mem_size;
+ }
+ GSL_SPIN_UNLOCK (&global_memory);
+ mem = cache_mem;
+ }
+ }
+ else
+ {
+ mem = g_malloc (mem_size);
+ GSL_SPIN_LOCK (&global_memory);
+ memory_allocated += mem_size;
+ GSL_SPIN_UNLOCK (&global_memory);
+ }
+ return mem;
+}
+
+static inline void
+low_free (gsize mem_size,
+ gpointer mem)
+{
+ if (mem_size >= TS8_SIZE && mem_size / 8 < SIMPLE_CACHE_SIZE)
+ {
+ guint cell;
+
+ mem_size = (mem_size + 7) & ~0x7;
+ cell = (mem_size >> 3) - 1;
+ GSL_SPIN_LOCK (&global_memory);
+ g_trash_stack_push (simple_cache + cell, mem);
+ GSL_SPIN_UNLOCK (&global_memory);
+ }
+ else
+ {
+ g_free (mem);
+ GSL_SPIN_LOCK (&global_memory);
+ memory_allocated -= mem_size;
+ GSL_SPIN_UNLOCK (&global_memory);
+ }
+}
+
+gpointer
+gsl_alloc_memblock (gsize block_size)
+{
+ guint8 *cmem;
+ gsize *debug_size;
+
+ g_return_val_if_fail (block_size >= sizeof (gpointer), NULL); /* cache-link size */
+
+ cmem = low_alloc (block_size + DBG8_SIZE);
+ debug_size = (gsize*) cmem;
+ *debug_size = block_size;
+ cmem += DBG8_SIZE;
+
+ return cmem;
+}
+
+void
+gsl_free_memblock (gsize block_size,
+ gpointer mem)
+{
+ gsize *debug_size;
+ guint8 *cmem;
+
+ g_return_if_fail (mem != NULL);
+
+ cmem = mem;
+ cmem -= DBG8_SIZE;
+ debug_size = (gsize*) cmem;
+ g_return_if_fail (block_size == *debug_size);
+
+ low_free (block_size + DBG8_SIZE, cmem);
+}
+
+void
+gsl_alloc_report (void)
+{
+ guint cell, cached = 0;
+
+ GSL_SPIN_LOCK (&global_memory);
+ for (cell = 0; cell < SIMPLE_CACHE_SIZE; cell++)
+ {
+ GTrashStack *trash = simple_cache[cell];
+ guint memsize, n = 0;
+
+ while (trash)
+ {
+ n++;
+ trash = trash->next;
+ }
+
+ if (n)
+ {
+ memsize = (cell + 1) << 3;
+ g_message ("cell %4u): %u bytes in %u nodes", memsize, memsize * n, n);
+ cached += memsize * n;
+ }
+ }
+ g_message ("%lu bytes allocated from system, %u bytes unused in cache", memory_allocated, cached);
+ GSL_SPIN_UNLOCK (&global_memory);
+}
+
+gpointer
+gsl_alloc_memblock0 (gsize block_size)
+{
+ gpointer mem = gsl_alloc_memblock (block_size);
+
+ memset (mem, 0, block_size);
+
+ return mem;
+}
+
+static void
+gsl_free_node_list (gpointer mem,
+ gsize node_size)
+{
+ struct { gpointer next, data; } *tmp, *node = mem;
+
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (node_size >= 2 * sizeof (gpointer));
+
+ /* FIXME: this can be optimized to an O(1) operation with T-style links in mem-caches */
+ do
+ {
+ tmp = node->next;
+
+ gsl_free_memblock (node_size, node);
+ node = tmp;
+ }
+ while (node);
+}
+
+
+/* --- ring (circular-list) --- */
+static inline GslRing*
+gsl_ring_prepend_i (GslRing *head,
+ gpointer data)
+{
+ GslRing *ring = gsl_new_struct (GslRing, 1);
+
+ ring->data = data;
+ if (!head)
+ {
+ ring->prev = ring;
+ ring->next = ring;
+ }
+ else
+ {
+ ring->prev = head->prev;
+ ring->next = head;
+ head->prev->next = ring;
+ head->prev = ring;
+ }
+ return ring;
+}
+
+GslRing*
+gsl_ring_prepend (GslRing *head,
+ gpointer data)
+{
+ return gsl_ring_prepend_i (head, data);
+}
+
+GslRing*
+gsl_ring_prepend_uniq (GslRing *head,
+ gpointer data)
+{
+ GslRing *walk;
+
+ for (walk = head; walk; walk = gsl_ring_walk (head, walk))
+ if (walk->data == data)
+ return head;
+ return gsl_ring_prepend_i (head, data);
+}
+
+GslRing*
+gsl_ring_append (GslRing *head,
+ gpointer data)
+{
+ GslRing *ring;
+
+ ring = gsl_ring_prepend_i (head, data);
+
+ return head ? head : ring;
+}
+
+GslRing*
+gsl_ring_concat (GslRing *head1,
+ GslRing *head2)
+{
+ GslRing *tail1, *tail2;
+
+ if (!head1)
+ return head2;
+ if (!head2)
+ return head1;
+ tail1 = head1->prev;
+ tail2 = head2->prev;
+ head1->prev = tail2;
+ tail2->next = head1;
+ head2->prev = tail1;
+ tail1->next = head2;
+
+ return head1;
+}
+
+GslRing*
+gsl_ring_remove_node (GslRing *head,
+ GslRing *node)
+{
+ if (!head)
+ g_return_val_if_fail (head == NULL && node == NULL, NULL);
+ if (!head || !node)
+ return NULL;
+
+ /* special case one item ring */
+ if (head->prev == head)
+ {
+ g_return_val_if_fail (node == head, head);
+
+ gsl_delete_struct (GslRing, node);
+ return NULL;
+ }
+ g_return_val_if_fail (node != node->next, head); /* node can't be a one item ring here */
+
+ node->next->prev = node->prev;
+ node->prev->next = node->next;
+ if (head == node)
+ head = node->next;
+ gsl_delete_struct (GslRing, node);
+
+ return head;
+}
+
+GslRing*
+gsl_ring_remove (GslRing *head,
+ gpointer data)
+{
+ GslRing *walk;
+
+ if (!head)
+ return NULL;
+
+ /* make tail data removal an O(1) operation */
+ if (head->prev->data == data)
+ return gsl_ring_remove_node (head, head->prev);
+
+ for (walk = head; walk; walk = gsl_ring_walk (head, walk))
+ if (walk->data == data)
+ return gsl_ring_remove_node (head, walk);
+
+ g_warning (G_STRLOC ": couldn't find data item (%p) to remove from ring (%p)", data, head);
+
+ return head;
+}
+
+guint
+gsl_ring_length (GslRing *head)
+{
+ GslRing *ring;
+ guint i = 0;
+
+ for (ring = head; ring; ring = gsl_ring_walk (head, ring))
+ i++;
+
+ return i;
+}
+
+GslRing*
+gsl_ring_find (GslRing *head,
+ gconstpointer data)
+{
+ GslRing *ring;
+
+ for (ring = head; ring; ring = gsl_ring_walk (head, ring))
+ if (ring->data == (gpointer) data)
+ return ring;
+
+ return NULL;
+}
+
+GslRing*
+gsl_ring_nth (GslRing *head,
+ guint n)
+{
+ GslRing *ring = head;
+
+ while (n-- && ring)
+ ring = gsl_ring_walk (head, ring);
+
+ return ring;
+}
+
+gpointer
+gsl_ring_nth_data (GslRing *head,
+ guint n)
+{
+ GslRing *ring = head;
+
+ while (n-- && ring)
+ ring = gsl_ring_walk (head, ring);
+
+ return ring ? ring->data : ring;
+}
+
+void
+gsl_ring_free (GslRing *head)
+{
+ if (head)
+ {
+ head->prev->next = NULL;
+ gsl_free_node_list (head, sizeof (*head));
+ }
+}
+
+gpointer
+gsl_ring_pop_head (GslRing **head_p)
+{
+ gpointer data;
+
+ g_return_val_if_fail (head_p != NULL, NULL);
+
+ if (!*head_p)
+ return NULL;
+ data = (*head_p)->data;
+ *head_p = gsl_ring_remove_node (*head_p, *head_p);
+
+ return data;
+}
+
+gpointer
+gsl_ring_pop_tail (GslRing **head_p)
+{
+ gpointer data;
+
+ g_return_val_if_fail (head_p != NULL, NULL);
+
+ if (!*head_p)
+ return NULL;
+ data = (*head_p)->prev->data;
+ *head_p = gsl_ring_remove_node (*head_p, (*head_p)->prev);
+
+ return data;
+}
+
+GslRing*
+gsl_ring_insert_sorted (GslRing *head,
+ gpointer data,
+ GCompareFunc func)
+{
+ gint cmp;
+
+ g_return_val_if_fail (func != NULL, head);
+
+ if (!head)
+ return gsl_ring_prepend (head, data);
+
+ /* typedef gint (*GCompareFunc) (gconstpointer a,
+ * gconstpointer b);
+ */
+ cmp = func (data, head->data);
+
+ if (cmp >= 0) /* insert after head */
+ {
+ GslRing *tmp, *tail = head->prev;
+
+ /* make appending an O(1) operation */
+ if (head == tail || func (data, tail->data) >= 0)
+ return gsl_ring_append (head, data);
+
+ /* walk forward while data >= tmp (skipping equal nodes) */
+ for (tmp = head->next; tmp != tail; tmp = tmp->next)
+ if (func (data, tmp->data) < 0)
+ break;
+
+ /* insert before sibling which is greater than data */
+ gsl_ring_prepend (tmp, data); /* keep current head */
+ return head;
+ }
+ else /* cmp < 0 */
+ return gsl_ring_prepend (head, data);
+}
+
+
+/* --- GslThread --- */
+typedef struct
+{
+ GslThreadFunc func;
+ gpointer data;
+ gint wpipe[2];
+ volatile gint abort;
+ guint64 awake_stamp;
+ GslDebugFlags auxlog_reporter;
+ const gchar *auxlog_section;
+} ThreadData;
+static GslMutex global_thread = { 0, };
+static GslRing *global_thread_list = NULL;
+static GslCond global_thread_cond = { 0, };
+static GslRing *awake_tdata_list = NULL;
+static ThreadData *main_thread_tdata = NULL;
+static GslThread *main_thread = NULL;
+
+static inline ThreadData*
+thread_data_from_gsl_thread (GslThread *thread)
+{
+ GThread *gthread = (GThread*) thread;
+
+ /* if gthread->data==NULL, we assume this is the main thread */
+
+ return gthread->data ? gthread->data : main_thread_tdata;
+}
+
+static gpointer
+thread_wrapper (gpointer arg)
+{
+ GslThread *self = gsl_thread_self ();
+ ThreadData *tdata = arg;
+
+ g_assert (tdata == thread_data_from_gsl_thread (gsl_thread_self ()));
+
+ GSL_SYNC_LOCK (&global_thread);
+ global_thread_list = gsl_ring_prepend (global_thread_list, self);
+ gsl_cond_broadcast (&global_thread_cond);
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ tdata->func (tdata->data);
+
+ GSL_SYNC_LOCK (&global_thread);
+ global_thread_list = gsl_ring_remove (global_thread_list, self);
+ if (tdata->awake_stamp)
+ awake_tdata_list = gsl_ring_remove (awake_tdata_list, tdata);
+ gsl_cond_broadcast (&global_thread_cond);
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ close (tdata->wpipe[0]);
+ tdata->wpipe[0] = -1;
+ close (tdata->wpipe[1]);
+ tdata->wpipe[1] = -1;
+ gsl_delete_struct (ThreadData, tdata);
+
+ return NULL;
+}
+
+static ThreadData*
+create_tdata (void)
+{
+ ThreadData *tdata;
+ glong d_long;
+ gint error;
+
+ tdata = gsl_new_struct0 (ThreadData, 1);
+ tdata->func = NULL;
+ tdata->data = NULL;
+ tdata->wpipe[0] = -1;
+ tdata->wpipe[1] = -1;
+ tdata->abort = FALSE;
+ tdata->auxlog_reporter = 0;
+ tdata->auxlog_section = NULL;
+ error = pipe (tdata->wpipe);
+ if (error == 0)
+ {
+ d_long = fcntl (tdata->wpipe[0], F_GETFL, 0);
+ /* g_printerr ("pipe-readfd, blocking=%ld\n", d_long & O_NONBLOCK); */
+ d_long |= O_NONBLOCK;
+ error = fcntl (tdata->wpipe[0], F_SETFL, d_long);
+ }
+ if (error == 0)
+ {
+ d_long = fcntl (tdata->wpipe[1], F_GETFL, 0);
+ /* g_printerr ("pipe-writefd, blocking=%ld\n", d_long & O_NONBLOCK); */
+ d_long |= O_NONBLOCK;
+ error = fcntl (tdata->wpipe[1], F_SETFL, d_long);
+ }
+ if (error)
+ {
+ close (tdata->wpipe[0]);
+ close (tdata->wpipe[1]);
+ gsl_delete_struct (ThreadData, tdata);
+ tdata = NULL;
+ }
+ return tdata;
+}
+
+GslThread*
+gsl_thread_new (GslThreadFunc func,
+ gpointer user_data)
+{
+ gpointer gthread = NULL;
+ ThreadData *tdata;
+ GError *gerror = NULL;
+
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ tdata = create_tdata ();
+
+ if (tdata)
+ {
+ const gboolean joinable = FALSE;
+
+ /* don't dare setting joinable to TRUE, that prevents the thread's
+ * resources from being freed, since we don't offer pthread_join().
+ * so we'd just rn out of stack at some point.
+ */
+ tdata->func = func;
+ tdata->data = user_data;
+ gthread = g_thread_create_full (thread_wrapper, tdata, 0, joinable, FALSE,
+ G_THREAD_PRIORITY_NORMAL, &gerror);
+ }
+
+ if (gthread)
+ {
+ GSL_SYNC_LOCK (&global_thread);
+ while (!gsl_ring_find (global_thread_list, gthread))
+ gsl_cond_wait (&global_thread_cond, &global_thread);
+ GSL_SYNC_UNLOCK (&global_thread);
+ }
+ else
+ {
+ if (tdata)
+ {
+ close (tdata->wpipe[0]);
+ close (tdata->wpipe[1]);
+ gsl_delete_struct (ThreadData, tdata);
+ }
+ g_warning ("Failed to create thread: %s", gerror->message);
+ g_error_free (gerror);
+ }
+
+ return gthread;
+}
+
+GslThread*
+gsl_thread_self (void)
+{
+ gpointer gthread = g_thread_self ();
+
+ if (!gthread)
+ g_error ("gsl_thread_self() failed");
+
+ return gthread;
+}
+
+GslThread*
+gsl_thread_main (void)
+{
+ return main_thread;
+}
+
+guint
+gsl_threads_get_count (void)
+{
+ guint count;
+
+ GSL_SYNC_LOCK (&global_thread);
+ count = gsl_ring_length (global_thread_list);
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ return count;
+}
+
+static void
+thread_wakeup_I (ThreadData *tdata)
+{
+ guint8 data = 'W';
+ gint r;
+
+ do
+ r = write (tdata->wpipe[1], &data, 1);
+ while (r < 0 && (errno == EINTR || errno == ERESTART));
+}
+
+/**
+ * gsl_thread_wakeup
+ * @thread: thread to wake up
+ * Wake up a currently sleeping thread. In practice, this
+ * function simply causes the next call to gsl_thread_sleep()
+ * within @thread to last for 0 seconds.
+ */
+void
+gsl_thread_wakeup (GslThread *thread)
+{
+ ThreadData *tdata;
+
+ g_return_if_fail (thread != NULL);
+
+ GSL_SYNC_LOCK (&global_thread);
+ g_assert (gsl_ring_find (global_thread_list, thread));
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ tdata = thread_data_from_gsl_thread (thread);
+ thread_wakeup_I (tdata);
+}
+
+/**
+ * gsl_thread_abort
+ * @thread: thread to abort
+ * Abort a currently running thread. This function does not
+ * return until the thread in question terminated execution.
+ * Note that the thread handle gets invalidated with invocation
+ * of gsl_thread_abort() or gsl_thread_queue_abort().
+ */
+void
+gsl_thread_abort (GslThread *thread)
+{
+ ThreadData *tdata;
+
+ g_return_if_fail (thread != NULL);
+ g_return_if_fail (thread != main_thread);
+
+ GSL_SYNC_LOCK (&global_thread);
+ g_assert (gsl_ring_find (global_thread_list, thread));
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ tdata = thread_data_from_gsl_thread (thread);
+
+ GSL_SYNC_LOCK (&global_thread);
+ tdata->abort = TRUE;
+ thread_wakeup_I (tdata);
+
+ while (gsl_ring_find (global_thread_list, thread))
+ gsl_cond_wait (&global_thread_cond, &global_thread);
+ GSL_SYNC_UNLOCK (&global_thread);
+}
+
+/**
+ * gsl_thread_queue_abort
+ * @thread: thread to abort
+ * Same as gsl_thread_abort(), but returns as soon as possible,
+ * even if thread hasn't stopped execution yet.
+ * Note that the thread handle gets invalidated with invocation
+ * of gsl_thread_abort() or gsl_thread_queue_abort().
+ */
+void
+gsl_thread_queue_abort (GslThread *thread)
+{
+ ThreadData *tdata;
+
+ g_return_if_fail (thread != NULL);
+ g_return_if_fail (thread != main_thread);
+
+ GSL_SYNC_LOCK (&global_thread);
+ g_assert (gsl_ring_find (global_thread_list, thread));
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ tdata = thread_data_from_gsl_thread (thread);
+
+ GSL_SYNC_LOCK (&global_thread);
+ tdata->abort = TRUE;
+ thread_wakeup_I (tdata);
+ GSL_SYNC_UNLOCK (&global_thread);
+}
+
+/**
+ * gsl_thread_aborted
+ * @returns: %TRUE if the thread should abort execution
+ * Find out if the currently running thread should be aborted (the thread is
+ * supposed to return from its main thread function).
+ */
+gboolean
+gsl_thread_aborted (void)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+ gboolean aborted;
+
+ GSL_SYNC_LOCK (&global_thread);
+ aborted = tdata->abort != FALSE;
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ return aborted;
+}
+
+/**
+ * gsl_thread_sleep
+ * @max_msec: maximum amount of milli seconds to sleep (-1 for infinite time)
+ * @returns: %TRUE if the thread should continue execution
+ * Sleep for the amount of time given. This function may get interrupted
+ * by wakeup or abort requests, it returns whether the thread is supposed
+ * to continue execution after waking up. This function also processes
+ * remaining data from the thread's poll fd.
+ */
+gboolean
+gsl_thread_sleep (glong max_msec)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+ struct pollfd pfd;
+ gint r, aborted;
+
+ pfd.fd = tdata->wpipe[0];
+ pfd.events = G_IO_IN;
+ pfd.revents = 0;
+
+ r = poll (&pfd, 1, max_msec);
+
+ if (r < 0 && errno != EINTR)
+ g_message (G_STRLOC ": poll() error: %s\n", g_strerror (errno));
+ else if (pfd.revents & G_IO_IN)
+ {
+ guint8 data[64];
+
+ do
+ r = read (tdata->wpipe[0], data, sizeof (data));
+ while ((r < 0 && (errno == EINTR || errno == ERESTART)) || r == sizeof (data));
+ }
+
+ GSL_SYNC_LOCK (&global_thread);
+ aborted = tdata->abort != FALSE;
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ return !aborted;
+}
+
+/**
+ * gsl_thread_awake_after
+ * RETURNS: GPollFD for the current thread
+ * Get the GPollfd for the current thread which is used
+ * to signal thread wakeups (e.g. due to
+ * gsl_thread_abort() or gsl_thread_wakeup()).
+ */
+void
+gsl_thread_get_pollfd (GPollFD *pfd)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+
+ pfd->fd = tdata->wpipe[0];
+ pfd->events = G_IO_IN;
+ pfd->revents = 0;
+}
+
+/**
+ * gsl_thread_awake_after
+ * @tick_stamp: tick stamp update to trigger wakeup
+ * Wakeup the currently running thread after the global tick stamp
+ * (see gsl_tick_stamp()) has been updated to @tick_stamp.
+ * (If the moment of wakeup has already passed by, the thread is
+ * woken up at the next global tick stamp update.)
+ */
+void
+gsl_thread_awake_after (guint64 tick_stamp)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+
+ g_return_if_fail (tick_stamp > 0);
+
+ GSL_SYNC_LOCK (&global_thread);
+ if (!tdata->awake_stamp)
+ {
+ awake_tdata_list = gsl_ring_prepend (awake_tdata_list, tdata);
+ tdata->awake_stamp = tick_stamp;
+ }
+ else
+ tdata->awake_stamp = MIN (tdata->awake_stamp, tick_stamp);
+ GSL_SYNC_UNLOCK (&global_thread);
+}
+
+/**
+ * gsl_thread_awake_before
+ * @tick_stamp: tick stamp update to trigger wakeup
+ * Wakeup the currently running thread upon the last global tick stamp
+ * update (see gsl_tick_stamp()) that happens prior to updating the
+ * global tick stamp to @tick_stamp.
+ * (If the moment of wakeup has already passed by, the thread is
+ * woken up at the next global tick stamp update.)
+ */
+void
+gsl_thread_awake_before (guint64 tick_stamp)
+{
+ g_return_if_fail (tick_stamp > 0);
+
+ if (tick_stamp > global_tick_stamp_leaps)
+ gsl_thread_awake_after (tick_stamp - global_tick_stamp_leaps);
+ else
+ gsl_thread_awake_after (tick_stamp);
+}
+
+/**
+ * gsl_tick_stamp
+ * @RETURNS: GSL's execution tick stamp as unsigned 64bit integer
+ *
+ * Retrive the GSL global tick stamp.
+ * GSL increments its global tick stamp at certain intervals,
+ * by specific amounts (refer to gsl_engine_init() for further
+ * details). The tick stamp is a non-wrapping, unsigned 64bit
+ * integer greater than 0. Threads can schedule sleep interruptions
+ * at certain tick stamps with gsl_thread_awake_after() and
+ * gsl_thread_awake_before(). Tick stamp updating occours at
+ * GSL engine block processing boundaries, so code that can
+ * guarantee to not run across those boundaries (for instance
+ * GslProcessFunc() functions) may use the macro %GSL_TICK_STAMP
+ * to retrive the current tick in a faster manner (not involving
+ * mutex locking). See also gsl_module_tick_stamp().
+ * This function is MT-safe and may be called from any thread.
+ */
+guint64
+gsl_tick_stamp (void)
+{
+ guint64 stamp;
+
+ GSL_SYNC_LOCK (&global_thread);
+ stamp = gsl_externvar_tick_stamp;
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ return stamp;
+}
+
+void
+_gsl_tick_stamp_set_leap (guint ticks)
+{
+ GSL_SYNC_LOCK (&global_thread);
+ global_tick_stamp_leaps = ticks;
+ GSL_SYNC_UNLOCK (&global_thread);
+}
+
+/**
+ * gsl_time_system
+ * @RETURNS: Current system time in micro seconds
+ *
+ * Get the current system time in micro seconds.
+ * Subsequent calls to this function do not necessarily
+ * return growing values. In fact, a second call may return
+ * a value smaller than the first call under certainsystem
+ * conditions.
+ * This function is MT-safe and may be called from any thread.
+ */
+guint64
+gsl_time_system (void)
+{
+ struct timeval tv;
+ guint64 csys_time;
+ gint error;
+
+ error = gettimeofday (&tv, NULL);
+ if (error)
+ g_error ("gettimeofday() failed: %s", g_strerror (errno));
+ csys_time = tv.tv_sec;
+ csys_time = csys_time * 1000000 + tv.tv_usec;
+
+ return csys_time;
+}
+
+/**
+ * gsl_tick_stamp_last
+ * @RETURNS: Current tick stamp and system time in micro seconds
+ *
+ * Get the system time of the last GSL global tick stamp update.
+ * This function is MT-safe and may be called from any thread.
+ */
+GslTickStampUpdate
+gsl_tick_stamp_last (void)
+{
+ GslTickStampUpdate ustamp;
+
+ GSL_SYNC_LOCK (&global_thread);
+ ustamp.tick_stamp = gsl_externvar_tick_stamp;
+ ustamp.system_time = tick_stamp_system_time;
+ GSL_SYNC_UNLOCK (&global_thread);
+
+ return ustamp;
+}
+
+void
+_gsl_tick_stamp_inc (void)
+{
+ volatile guint64 newstamp;
+ GslRing *ring;
+ guint64 systime;
+
+ g_return_if_fail (global_tick_stamp_leaps > 0);
+
+ systime = gsl_time_system ();
+ newstamp = gsl_externvar_tick_stamp + global_tick_stamp_leaps;
+
+ GSL_SYNC_LOCK (&global_thread);
+ gsl_externvar_tick_stamp = newstamp;
+ tick_stamp_system_time = systime;
+ for (ring = awake_tdata_list; ring; )
+ {
+ ThreadData *tdata = ring->data;
+
+ if (tdata->awake_stamp <= GSL_TICK_STAMP)
+ {
+ GslRing *next = gsl_ring_walk (awake_tdata_list, ring);
+
+ tdata->awake_stamp = 0;
+ awake_tdata_list = gsl_ring_remove (awake_tdata_list, tdata);
+
+ thread_wakeup_I (tdata);
+ ring = next;
+ }
+ else
+ ring = gsl_ring_walk (awake_tdata_list, ring);
+ }
+ GSL_SYNC_UNLOCK (&global_thread);
+}
+
+
+/* --- GslMutex --- */
+static gboolean is_smp_system = FALSE;
+
+static void
+default_mutex_init (GslMutex *mutex)
+{
+ g_return_if_fail (mutex != NULL);
+
+ mutex->mutex_pointer = g_mutex_new ();
+}
+
+static int
+default_mutex_trylock (GslMutex *mutex)
+{
+ return g_mutex_trylock (mutex->mutex_pointer) ? 0 : -1;
+}
+
+static void
+default_mutex_lock (GslMutex *mutex)
+{
+ /* spin locks should be held only very short times,
+ * so frequently we should succeed here
+ */
+ if (g_mutex_trylock (mutex->mutex_pointer))
+ return;
+
+ if (!is_smp_system)
+ {
+ /* on uni processor systems, there's no point in busy spinning */
+ do
+ {
+#if defined(_POSIX_PRIORITY_SCHEDULING)
+ sched_yield ();
+#endif
+ if (g_mutex_trylock (mutex->mutex_pointer))
+ return;
+ }
+ while (TRUE);
+ }
+ else
+ {
+ /* for multi processor systems, mutex_lock() is hopefully implemented
+ * via spinning. note that we can't implement spinning ourselves with
+ * mutex_trylock(), since on some architectures that'd block memory
+ * bandwith due to constant bus locks
+ */
+ g_mutex_lock (mutex->mutex_pointer);
+ }
+}
+
+static void
+default_mutex_unlock (GslMutex *mutex)
+{
+ g_mutex_unlock (mutex->mutex_pointer);
+}
+
+static void
+default_mutex_destroy (GslMutex *mutex)
+{
+ g_mutex_free (mutex->mutex_pointer);
+ memset (mutex, 0, sizeof (*mutex));
+}
+
+static void
+default_rec_mutex_init (GslRecMutex *rec_mutex)
+{
+ rec_mutex->depth = 0;
+ rec_mutex->owner = NULL;
+ gsl_mutex_init (&rec_mutex->sync_mutex);
+}
+
+static int
+default_rec_mutex_trylock (GslRecMutex *rec_mutex)
+{
+ gpointer self = gsl_thread_self ();
+
+ if (rec_mutex->owner == self)
+ {
+ g_assert (rec_mutex->depth > 0); /* paranoid */
+ rec_mutex->depth += 1;
+ return 0;
+ }
+ else
+ {
+ if (gsl_mutex_trylock (&rec_mutex->sync_mutex))
+ {
+ g_assert (rec_mutex->owner == NULL && rec_mutex->depth == 0); /* paranoid */
+ rec_mutex->owner = self;
+ rec_mutex->depth = 1;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static void
+default_rec_mutex_lock (GslRecMutex *rec_mutex)
+{
+ gpointer self = gsl_thread_self ();
+
+ if (rec_mutex->owner == self)
+ {
+ g_assert (rec_mutex->depth > 0); /* paranoid */
+ rec_mutex->depth += 1;
+ }
+ else
+ {
+ GSL_SYNC_LOCK (&rec_mutex->sync_mutex);
+ g_assert (rec_mutex->owner == NULL && rec_mutex->depth == 0); /* paranoid */
+ rec_mutex->owner = self;
+ rec_mutex->depth = 1;
+ }
+}
+
+static void
+default_rec_mutex_unlock (GslRecMutex *rec_mutex)
+{
+ gpointer self = gsl_thread_self ();
+
+ if (rec_mutex->owner == self && rec_mutex->depth > 0)
+ {
+ rec_mutex->depth -= 1;
+ if (!rec_mutex->depth)
+ {
+ rec_mutex->owner = NULL;
+ GSL_SYNC_UNLOCK (&rec_mutex->sync_mutex);
+ }
+ }
+ else
+ g_warning ("unable to unlock recursive mutex with self %p != %p or depth %u < 1",
+ rec_mutex->owner, self, rec_mutex->depth);
+}
+
+static void
+default_rec_mutex_destroy (GslRecMutex *rec_mutex)
+{
+ if (rec_mutex->owner || rec_mutex->depth)
+ {
+ g_warning (G_STRLOC ": recursive mutex still locked during destruction");
+ return;
+ }
+ gsl_mutex_destroy (&rec_mutex->sync_mutex);
+ g_assert (rec_mutex->owner == NULL && rec_mutex->depth == 0);
+}
+
+static void
+default_cond_init (GslCond *cond)
+{
+ cond->cond_pointer = g_cond_new ();
+}
+
+static void
+default_cond_wait (GslCond *cond,
+ GslMutex *mutex)
+{
+ /* infinite wait */
+ g_cond_wait (cond->cond_pointer, mutex->mutex_pointer);
+}
+
+static void
+default_cond_signal (GslCond *cond)
+{
+ g_cond_signal (cond->cond_pointer);
+}
+
+static void
+default_cond_broadcast (GslCond *cond)
+{
+ g_cond_broadcast (cond->cond_pointer);
+}
+
+static void
+default_cond_destroy (GslCond *cond)
+{
+ g_cond_free (cond->cond_pointer);
+}
+
+static void
+default_cond_wait_timed (GslCond *cond,
+ GslMutex *mutex,
+ gulong abs_secs,
+ gulong abs_usecs)
+{
+ GTimeVal gtime;
+
+ gtime.tv_sec = abs_secs;
+ gtime.tv_usec = abs_usecs;
+ g_cond_timed_wait (cond->cond_pointer, mutex->mutex_pointer, &gtime);
+}
+
+GslMutexTable gsl_mutex_table = {
+ default_mutex_init,
+ default_mutex_lock,
+ default_mutex_trylock,
+ default_mutex_unlock,
+ default_mutex_destroy,
+ default_rec_mutex_init,
+ default_rec_mutex_lock,
+ default_rec_mutex_trylock,
+ default_rec_mutex_unlock,
+ default_rec_mutex_destroy,
+ default_cond_init,
+ default_cond_signal,
+ default_cond_broadcast,
+ default_cond_wait,
+ default_cond_wait_timed,
+ default_cond_destroy,
+};
+
+void
+gsl_cond_wait_timed (GslCond *cond,
+ GslMutex *mutex,
+ glong max_useconds)
+{
+ if (max_useconds < 0)
+ gsl_cond_wait (cond, mutex);
+ else
+ {
+ struct timeval now;
+ glong secs;
+
+ gettimeofday (&now, NULL);
+ secs = max_useconds / 1000000;
+ now.tv_sec += secs;
+ max_useconds -= secs * 1000000;
+ now.tv_usec += max_useconds;
+ if (now.tv_usec >= 1000000)
+ {
+ now.tv_usec -= 1000000;
+ now.tv_sec += 1;
+ }
+
+ /* linux on x86 with pthread has actually 10ms resolution */
+ gsl_mutex_table.cond_wait_timed (cond, mutex, now.tv_sec, now.tv_usec);
+ }
+}
+
+
+/* --- GslMessage --- */
+const gchar*
+gsl_strerror (GslErrorType error)
+{
+ switch (error)
+ {
+ case GSL_ERROR_NONE: return "Everything went well";
+ case GSL_ERROR_INTERNAL: return "Internal error (please report)";
+ case GSL_ERROR_UNKNOWN: return "Unknown error";
+ case GSL_ERROR_IO: return "I/O error";
+ case GSL_ERROR_PERMS: return "Insufficient permission";
+ case GSL_ERROR_BUSY: return "Resource currently busy";
+ case GSL_ERROR_EXISTS: return "Resource exists already";
+ case GSL_ERROR_TEMP: return "Temporary error";
+ case GSL_ERROR_EOF: return "File empty or premature EOF";
+ case GSL_ERROR_NOT_FOUND: return "Resource not found";
+ case GSL_ERROR_OPEN_FAILED: return "Open failed";
+ case GSL_ERROR_SEEK_FAILED: return "Seek failed";
+ case GSL_ERROR_READ_FAILED: return "Read failed";
+ case GSL_ERROR_WRITE_FAILED: return "Write failed";
+ case GSL_ERROR_FORMAT_INVALID: return "Invalid format";
+ case GSL_ERROR_FORMAT_UNKNOWN: return "Unknown format";
+ case GSL_ERROR_DATA_CORRUPT: return "Data corrupt";
+ case GSL_ERROR_CONTENT_GLITCH: return "Data glitch (junk) detected";
+ case GSL_ERROR_NO_RESOURCE: return "Out of memory, disk space or similar resource";
+ case GSL_ERROR_CODEC_FAILURE: return "CODEC failure";
+ default: return NULL;
+ }
+}
+
+static const GDebugKey gsl_static_debug_keys[] = {
+ { "notify", GSL_MSG_NOTIFY },
+ { "dcache", GSL_MSG_DATA_CACHE },
+ { "dhandle", GSL_MSG_DATA_HANDLE },
+ { "loader", GSL_MSG_LOADER },
+ { "osc", GSL_MSG_OSC },
+ { "engine", GSL_MSG_ENGINE },
+ { "jobs", GSL_MSG_JOBS },
+ { "fjobs", GSL_MSG_FJOBS },
+ { "sched", GSL_MSG_SCHED },
+ { "master", GSL_MSG_MASTER },
+ { "slave", GSL_MSG_SLAVE },
+};
+
+static const gchar*
+reporter_name (GslDebugFlags reporter)
+{
+ switch (reporter)
+ {
+ case GSL_MSG_NOTIFY: return "Notify";
+ case GSL_MSG_DATA_CACHE: return "DataCache";
+ case GSL_MSG_DATA_HANDLE: return "DataHandle";
+ case GSL_MSG_LOADER: return "Loader";
+ case GSL_MSG_OSC: return "Oscillator";
+ case GSL_MSG_ENGINE: return "Engine"; /* Engine */
+ case GSL_MSG_JOBS: return "Jobs"; /* Engine */
+ case GSL_MSG_FJOBS: return "FlowJobs"; /* Engine */
+ case GSL_MSG_SCHED: return "Sched"; /* Engine */
+ case GSL_MSG_MASTER: return "Master"; /* Engine */
+ case GSL_MSG_SLAVE: return "Slave"; /* Engine */
+ default: return "Custom";
+ }
+}
+
+const GDebugKey *gsl_debug_keys = gsl_static_debug_keys;
+const guint gsl_n_debug_keys = G_N_ELEMENTS (gsl_static_debug_keys);
+
+void
+gsl_message_send (GslDebugFlags reporter,
+ const gchar *section,
+ GslErrorType error,
+ const gchar *messagef,
+ ...)
+{
+ struct {
+ GslDebugFlags reporter;
+ gchar reporter_name[64];
+ gchar section[64]; /* auxillary information about reporter code portion */
+ GslErrorType error;
+ const gchar *error_str; /* gsl_strerror() of error */
+ gchar message[1024];
+ } tmsg, *msg = &tmsg;
+ gchar *string;
+ va_list args;
+
+ g_return_if_fail (messagef != NULL);
+
+ /* create message */
+ memset (msg, 0, sizeof (*msg));
+ msg->reporter = reporter;
+ strncpy (msg->reporter_name, reporter_name (msg->reporter), 63);
+ if (section)
+ strncpy (msg->section, section, 63);
+ msg->error = error;
+ msg->error_str = error ? gsl_strerror (msg->error) : NULL;
+
+ /* vsnprintf() replacement */
+ va_start (args, messagef);
+ string = g_strdup_vprintf (messagef, args);
+ va_end (args);
+ strncpy (msg->message, string, 1023);
+ g_free (string);
+
+ /* in current lack of a decent message queue, puke the message to stderr */
+ g_printerr ("GSL-%s%s%s: %s%s%s\n",
+ msg->reporter_name,
+ msg->section ? ":" : "",
+ msg->section ? msg->section : "",
+ msg->message,
+ msg->error_str ? ": " : "",
+ msg->error_str ? msg->error_str : "");
+}
+
+void
+gsl_debug_enable (GslDebugFlags dbg_flags)
+{
+ gsl_debug_flags |= dbg_flags;
+}
+
+void
+gsl_debug_disable (GslDebugFlags dbg_flags)
+{
+ gsl_debug_flags &= dbg_flags;
+}
+
+gboolean
+gsl_debug_check (GslDebugFlags dbg_flags)
+{
+ return (gsl_debug_flags & dbg_flags) != 0;
+}
+
+void
+gsl_debug (GslDebugFlags reporter,
+ const gchar *section,
+ const gchar *format,
+ ...)
+{
+ g_return_if_fail (format != NULL);
+
+ if (reporter & gsl_debug_flags)
+ {
+ va_list args;
+ gchar *string;
+
+ va_start (args, format);
+ string = g_strdup_vprintf (format, args);
+ va_end (args);
+ g_printerr ("DEBUG:GSL-%s%s%s: %s\n",
+ reporter_name (reporter),
+ section ? ":" : "",
+ section ? section : "",
+ string);
+ g_free (string);
+ }
+}
+
+void
+gsl_auxlog_push (GslDebugFlags reporter,
+ const gchar *section)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+
+ if (tdata)
+ {
+ tdata->auxlog_reporter = reporter;
+ tdata->auxlog_section = section;
+ }
+}
+
+void
+gsl_auxlog_debug (const gchar *format,
+ ...)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+ GslDebugFlags reporter = GSL_MSG_NOTIFY;
+ const gchar *section = NULL;
+ va_list args;
+ gchar *string;
+
+ if (tdata)
+ {
+ reporter = tdata->auxlog_reporter;
+ section = tdata->auxlog_section;
+ tdata->auxlog_reporter = 0;
+ tdata->auxlog_section = NULL;
+ }
+
+ g_return_if_fail (format != NULL);
+
+ va_start (args, format);
+ string = g_strdup_vprintf (format, args);
+ va_end (args);
+ gsl_debug (reporter, section, "%s", string);
+ g_free (string);
+}
+
+void
+gsl_auxlog_message (GslErrorType error,
+ const gchar *format,
+ ...)
+{
+ ThreadData *tdata = thread_data_from_gsl_thread (gsl_thread_self ());
+ GslDebugFlags reporter = GSL_MSG_NOTIFY;
+ const gchar *section = NULL;
+ va_list args;
+ gchar *string;
+
+ if (tdata)
+ {
+ reporter = tdata->auxlog_reporter;
+ section = tdata->auxlog_section;
+ tdata->auxlog_reporter = 0;
+ tdata->auxlog_section = NULL;
+ }
+
+ g_return_if_fail (format != NULL);
+
+ va_start (args, format);
+ string = g_strdup_vprintf (format, args);
+ va_end (args);
+ gsl_message_send (reporter, section, error, "%s", string);
+ g_free (string);
+}
+
+
+/* --- misc --- */
+const gchar*
+gsl_byte_order_to_string (guint byte_order)
+{
+ g_return_val_if_fail (byte_order == G_LITTLE_ENDIAN || byte_order == G_BIG_ENDIAN, NULL);
+
+ if (byte_order == G_LITTLE_ENDIAN)
+ return "little_endian";
+ if (byte_order == G_BIG_ENDIAN)
+ return "big_endian";
+
+ return NULL;
+}
+
+guint
+gsl_byte_order_from_string (const gchar *string)
+{
+ g_return_val_if_fail (string != NULL, 0);
+
+ while (*string == ' ')
+ string++;
+ if (strncasecmp (string, "little", 6) == 0)
+ return G_LITTLE_ENDIAN;
+ if (strncasecmp (string, "big", 3) == 0)
+ return G_BIG_ENDIAN;
+ return 0;
+}
+
+GslErrorType
+gsl_check_file (const gchar *file_name,
+ const gchar *mode)
+{
+ guint access_mask = 0;
+ guint check_file, check_dir, check_link;
+
+ if (strchr (mode, 'r')) /* readable */
+ access_mask |= R_OK;
+ if (strchr (mode, 'w')) /* writable */
+ access_mask |= W_OK;
+ if (strchr (mode, 'x')) /* executable */
+ access_mask |= X_OK;
+
+ if (access_mask && access (file_name, access_mask) < 0)
+ goto have_errno;
+
+ check_file = strchr (mode, 'f') != NULL; /* open as file */
+ check_dir = strchr (mode, 'd') != NULL; /* open as directory */
+ check_link = strchr (mode, 'l') != NULL; /* open as link */
+
+ if (check_file || check_dir || check_link)
+ {
+ struct stat st;
+
+ if (check_link)
+ {
+ if (lstat (file_name, &st) < 0)
+ goto have_errno;
+ }
+ else if (stat (file_name, &st) < 0)
+ goto have_errno;
+
+ if ((check_file && !S_ISREG (st.st_mode)) ||
+ (check_dir && !S_ISDIR (st.st_mode)) ||
+ (check_link && !S_ISLNK (st.st_mode)))
+ return GSL_ERROR_OPEN_FAILED;
+ }
+
+ return GSL_ERROR_NONE;
+
+ have_errno:
+ return gsl_error_from_errno (errno, GSL_ERROR_OPEN_FAILED);
+}
+
+GslErrorType
+gsl_error_from_errno (gint sys_errno,
+ GslErrorType fallback)
+{
+ switch (sys_errno)
+ {
+ case ELOOP:
+ case ENAMETOOLONG:
+ case ENOTDIR:
+ case ENOENT: return GSL_ERROR_NOT_FOUND;
+ case EROFS:
+ case EPERM:
+ case EACCES: return GSL_ERROR_PERMS;
+ case ENOMEM:
+ case ENOSPC:
+ case EFBIG:
+ case ENFILE:
+ case EMFILE: return GSL_ERROR_NO_RESOURCE;
+ case EISDIR:
+ case ESPIPE:
+ case EIO: return GSL_ERROR_IO;
+ case EEXIST: return GSL_ERROR_EXISTS;
+ case ETXTBSY:
+ case EBUSY: return GSL_ERROR_BUSY;
+ case EAGAIN:
+ case EINTR: return GSL_ERROR_TEMP;
+ case EINVAL:
+ case EFAULT:
+ case EBADF: return GSL_ERROR_INTERNAL;
+ default: return fallback;
+ }
+}
+
+
+/* --- global initialization --- */
+static guint
+get_n_processors (void)
+{
+#ifdef _SC_NPROCESSORS_ONLN
+ {
+ gint n = sysconf (_SC_NPROCESSORS_ONLN);
+
+ if (n > 0)
+ return n;
+ }
+#endif
+ return 1;
+}
+
+static const GslConfig *gsl_config = NULL;
+
+const GslConfig*
+gsl_get_config (void)
+{
+ return gsl_config;
+}
+
+#define ROUND(dblval) ((GslLong) ((dblval) + .5))
+
+void
+gsl_init (const GslConfigValue values[],
+ GslMutexTable *mtable)
+{
+ const GslConfigValue *config = values;
+ static GslConfig pconfig = { /* DEFAULTS */
+ 1, /* n_processors */
+ 2, /* wave_chunk_padding */
+ 4, /* wave_chunk_big_pad */
+ 512, /* dcache_block_size */
+ 1024 * 1024, /* dcache_cache_memory */
+ 69, /* midi_kammer_note */
+ 440, /* kammer_freq */
+ };
+
+ g_return_if_fail (gsl_config == NULL); /* assert single initialization */
+
+ /* get mutexes going first */
+ if (mtable)
+ gsl_mutex_table = *mtable;
+
+ gsl_externvar_tick_stamp = 1;
+
+ /* configure permanent config record */
+ if (config)
+ while (config->value_name)
+ {
+ if (strcmp ("wave_chunk_padding", config->value_name) == 0)
+ pconfig.wave_chunk_padding = ROUND (config->value);
+ else if (strcmp ("wave_chunk_big_pad", config->value_name) == 0)
+ pconfig.wave_chunk_big_pad = ROUND (config->value);
+ else if (strcmp ("dcache_cache_memory", config->value_name) == 0)
+ pconfig.dcache_cache_memory = ROUND (config->value);
+ else if (strcmp ("dcache_block_size", config->value_name) == 0)
+ pconfig.dcache_block_size = ROUND (config->value);
+ else if (strcmp ("midi_kammer_note", config->value_name) == 0)
+ pconfig.midi_kammer_note = ROUND (config->value);
+ else if (strcmp ("kammer_freq", config->value_name) == 0)
+ pconfig.kammer_freq = config->value;
+ config++;
+ }
+
+ /* constrain (user) config */
+ pconfig.wave_chunk_padding = MAX (1, pconfig.wave_chunk_padding);
+ pconfig.wave_chunk_big_pad = MAX (2 * pconfig.wave_chunk_padding, pconfig.wave_chunk_big_pad);
+ pconfig.dcache_block_size = MAX (2 * pconfig.wave_chunk_big_pad + sizeof (GslDataType), pconfig.dcache_block_size);
+ pconfig.dcache_block_size = gsl_alloc_upper_power2 (pconfig.dcache_block_size - 1);
+ /* pconfig.dcache_cache_memory = gsl_alloc_upper_power2 (pconfig.dcache_cache_memory); */
+
+ /* non-configurable config updates */
+ pconfig.n_processors = get_n_processors ();
+
+ /* export GSL configuration */
+ gsl_config = &pconfig;
+
+ /* initialize subsystems */
+ is_smp_system = GSL_CONFIG (n_processors) > 1;
+ gsl_mutex_init (&global_memory);
+ gsl_mutex_init (&global_thread);
+ gsl_cond_init (&global_thread_cond);
+ main_thread_tdata = create_tdata ();
+ g_assert (main_thread_tdata != NULL);
+ main_thread = gsl_thread_self ();
+ global_thread_list = gsl_ring_prepend (global_thread_list, main_thread);
+ _gsl_init_signal ();
+ _gsl_init_fd_pool ();
+ _gsl_init_data_caches ();
+ _gsl_init_engine_utils ();
+ _gsl_init_loader_gslwave ();
+ _gsl_init_loader_wav ();
+ _gsl_init_loader_oggvorbis ();
+ _gsl_init_loader_mad ();
+}
diff --git a/flow/gsl/gslcommon.h b/flow/gsl/gslcommon.h
new file mode 100644
index 0000000..6b74c77
--- /dev/null
+++ b/flow/gsl/gslcommon.h
@@ -0,0 +1,293 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_COMMON_H__
+#define __GSL_COMMON_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/* --- global initialization --- */
+typedef struct
+{
+ const char *value_name;
+ double value;
+} GslConfigValue;
+typedef struct
+{
+ guint n_processors;
+ /* # values to pad around wave chunk blocks per channel */
+ guint wave_chunk_padding;
+ guint wave_chunk_big_pad;
+ /* data (file) cache block size (aligned to power of 2) */
+ guint dcache_block_size;
+ /* amount of bytes to spare for memory cache */
+ guint dcache_cache_memory;
+ guint midi_kammer_note;
+ /* kammer frequency, normally 440Hz, historically 435Hz */
+ gfloat kammer_freq;
+} GslConfig;
+typedef struct _GslMutexTable GslMutexTable;
+void gsl_init (const GslConfigValue values[],
+ GslMutexTable *mtable);
+const GslConfig* gsl_get_config (void) G_GNUC_CONST;
+#define GSL_CONFIG(value) ((gsl_get_config () [0]) . value)
+
+
+/* --- memory allocation --- */
+#define gsl_new_struct(type, n) ((type*) gsl_alloc_memblock (sizeof (type) * (n)))
+#define gsl_new_struct0(type, n) ((type*) gsl_alloc_memblock0 (sizeof (type) * (n)))
+#define gsl_delete_struct(type, mem) gsl_delete_structs (type, 1, (mem))
+#ifndef __GNUC__
+# define gsl_delete_structs(type, n, mem) (gsl_free_memblock (sizeof (type) * (n), (mem)))
+#else /* provide typesafety if possible */
+# define gsl_delete_structs(type, n, mem) do { \
+ type *__typed_pointer = (mem); \
+ gsl_free_memblock (sizeof (type) * (n), __typed_pointer); \
+} while(0)
+#endif
+#define GSL_ALIGNED_SIZE(size,align) ((align) > 0 ? _GSL_INTERN_ALIGN (((gsize) (size)), ((gsize) (align))) : (gsize) (size))
+#define _GSL_INTERN_ALIGN(s, a) (((s + (a - 1)) / a) * a)
+#define GSL_STD_ALIGN (MAX (MAX (sizeof (float), sizeof (int)), sizeof (void*)))
+
+
+/* --- ring (circular-list) --- */
+struct _GslRing
+{
+ GslRing *next;
+ GslRing *prev;
+ gpointer data;
+};
+GslRing* gsl_ring_prepend (GslRing *head,
+ gpointer data);
+GslRing* gsl_ring_prepend_uniq (GslRing *head,
+ gpointer data);
+GslRing* gsl_ring_append (GslRing *head,
+ gpointer data);
+GslRing* gsl_ring_insert_sorted (GslRing *head,
+ gpointer data,
+ GCompareFunc func);
+GslRing* gsl_ring_remove_node (GslRing *head,
+ GslRing *node);
+GslRing* gsl_ring_remove (GslRing *head,
+ gpointer data);
+guint gsl_ring_length (GslRing *head);
+GslRing* gsl_ring_concat (GslRing *head1,
+ GslRing *head2);
+GslRing* gsl_ring_find (GslRing *head,
+ gconstpointer data);
+GslRing* gsl_ring_nth (GslRing *head,
+ guint n);
+gpointer gsl_ring_nth_data (GslRing *head,
+ guint n);
+gpointer gsl_ring_pop_head (GslRing **head);
+gpointer gsl_ring_pop_tail (GslRing **head);
+#define gsl_ring_push_head gsl_ring_prepend
+#define gsl_ring_push_tail gsl_ring_append
+void gsl_ring_free (GslRing *head);
+#define gsl_ring_walk(head,node) ((node) != (head)->prev ? (node)->next : NULL)
+
+
+/* --- GslMessage and debugging --- */
+typedef enum /*< skip >*/
+{
+ GSL_MSG_NOTIFY = 1 << 0,
+ GSL_MSG_DATA_CACHE = 1 << 1,
+ GSL_MSG_DATA_HANDLE = 1 << 2,
+ GSL_MSG_LOADER = 1 << 3,
+ GSL_MSG_OSC = 1 << 4,
+ GSL_MSG_ENGINE = 1 << 5,
+ GSL_MSG_JOBS = 1 << 6,
+ GSL_MSG_FJOBS = 1 << 7,
+ GSL_MSG_SCHED = 1 << 8,
+ GSL_MSG_MASTER = 1 << 9,
+ GSL_MSG_SLAVE = 1 << 10
+} GslDebugFlags;
+extern const GDebugKey *gsl_debug_keys;
+extern const guint gsl_n_debug_keys;
+void gsl_debug (GslDebugFlags reporter,
+ const gchar *section,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (3, 4);
+void gsl_debug_enable (GslDebugFlags dbg_flags);
+void gsl_debug_disable (GslDebugFlags dbg_flags);
+gboolean gsl_debug_check (GslDebugFlags dbg_flags);
+void gsl_message_send (GslDebugFlags reporter,
+ const gchar *section, /* maybe NULL */
+ GslErrorType error, /* maybe 0 */
+ const gchar *messagef,
+ ...) G_GNUC_PRINTF (4, 5);
+const gchar* gsl_strerror (GslErrorType error);
+
+/* provide message/debugging macro templates, so custom messages
+ * are done as:
+ * #define FOO_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_LOADER, "FOO")
+ * FOO_DEBUG ("some debug message and number: %d", 5);
+ */
+#define GSL_DEBUG_FUNCTION(reporter, section) _GSL_DEBUG_MACRO_IMPL((reporter), (section))
+#define GSL_MESSAGE_FUNCTION(reporter, section) _GSL_MESSAGE_MACRO_IMPL((reporter), (section))
+
+
+/* --- GslThread --- */
+typedef void (*GslThreadFunc) (gpointer user_data);
+GslThread* gsl_thread_new (GslThreadFunc func,
+ gpointer user_data);
+guint gsl_threads_get_count (void);
+GslThread* gsl_thread_self (void);
+GslThread* gsl_thread_main (void);
+
+
+/* --- tick stamps --- */
+typedef struct {
+ guint64 tick_stamp;
+ guint64 system_time;
+} GslTickStampUpdate;
+guint64 gsl_tick_stamp (void);
+guint64 gsl_time_system (void);
+GslTickStampUpdate gsl_tick_stamp_last (void);
+#define GSL_TICK_STAMP (_GSL_TICK_STAMP_VAL ())
+#define GSL_MAX_TICK_STAMP (G_MAXUINT64)
+
+
+/* --- thread syncronization --- */
+gboolean gsl_thread_sleep (glong max_msec);
+gboolean gsl_thread_aborted (void);
+void gsl_thread_queue_abort (GslThread *thread);
+void gsl_thread_abort (GslThread *thread);
+void gsl_thread_wakeup (GslThread *thread);
+void gsl_thread_awake_after (guint64 tick_stamp);
+void gsl_thread_awake_before (guint64 tick_stamp);
+void gsl_thread_get_pollfd (GPollFD *pfd);
+
+
+/* --- GslMutex --- */
+#define gsl_mutex_init(mutex) (gsl_mutex_table.mutex_init (mutex))
+#define GSL_SPIN_LOCK(mutex) (gsl_mutex_table.mutex_lock (mutex))
+#define GSL_SPIN_UNLOCK(mutex) (gsl_mutex_table.mutex_unlock (mutex))
+#define GSL_SYNC_LOCK(mutex) (gsl_mutex_table.mutex_lock (mutex))
+#define GSL_SYNC_UNLOCK(mutex) (gsl_mutex_table.mutex_unlock (mutex))
+#define gsl_mutex_trylock(mutex) (!gsl_mutex_table.mutex_trylock (mutex))
+#define gsl_mutex_destroy(mutex) (gsl_mutex_table.mutex_destroy (mutex))
+#define gsl_rec_mutex_init(rmutex) (gsl_mutex_table.rec_mutex_init (rmutex))
+#define gsl_rec_mutex_lock(rmutex) (gsl_mutex_table.rec_mutex_lock (rmutex))
+#define gsl_rec_mutex_unlock(rmutex) (gsl_mutex_table.rec_mutex_unlock (rmutex))
+#define gsl_rec_mutex_trylock(rmutex) (!gsl_mutex_table.rec_mutex_trylock (rmutex))
+#define gsl_rec_mutex_destroy(rmutex) (gsl_mutex_table.rec_mutex_destroy (rmutex))
+#define gsl_cond_init(cond) (gsl_mutex_table.cond_init (cond))
+#define gsl_cond_signal(cond) (gsl_mutex_table.cond_signal (cond))
+#define gsl_cond_broadcast(cond) (gsl_mutex_table.cond_broadcast (cond))
+#define gsl_cond_wait(cond, mutex) (gsl_mutex_table.cond_wait ((cond), (mutex)))
+#define gsl_cond_destroy(cond) (gsl_mutex_table.cond_destroy (cond))
+void gsl_cond_wait_timed (GslCond *cond,
+ GslMutex *mutex,
+ glong max_useconds);
+struct _GslMutexTable
+{
+ void (*mutex_init) (GslMutex *mutex);
+ void (*mutex_lock) (GslMutex *mutex);
+ int (*mutex_trylock) (GslMutex *mutex); /* 0==has_lock */
+ void (*mutex_unlock) (GslMutex *mutex);
+ void (*mutex_destroy) (GslMutex *mutex);
+ void (*rec_mutex_init) (GslRecMutex *mutex);
+ void (*rec_mutex_lock) (GslRecMutex *mutex);
+ int (*rec_mutex_trylock) (GslRecMutex *mutex); /* 0==has_lock */
+ void (*rec_mutex_unlock) (GslRecMutex *mutex);
+ void (*rec_mutex_destroy) (GslRecMutex *mutex);
+ void (*cond_init) (GslCond *cond);
+ void (*cond_signal) (GslCond *cond);
+ void (*cond_broadcast) (GslCond *cond);
+ void (*cond_wait) (GslCond *cond,
+ GslMutex *mutex);
+ void (*cond_wait_timed) (GslCond *cond,
+ GslMutex *mutex,
+ gulong abs_secs,
+ gulong abs_usecs);
+ void (*cond_destroy) (GslCond *cond);
+};
+
+
+/* --- misc --- */
+const gchar* gsl_byte_order_to_string (guint byte_order);
+guint gsl_byte_order_from_string (const gchar *string);
+GslErrorType gsl_error_from_errno (gint sys_errno,
+ GslErrorType fallback);
+GslErrorType gsl_check_file (const gchar *file_name,
+ const gchar *mode);
+
+
+/* --- implementation details --- */
+gpointer gsl_alloc_memblock (gsize size);
+gpointer gsl_alloc_memblock0 (gsize size);
+void gsl_free_memblock (gsize size,
+ gpointer memblock);
+void gsl_alloc_report (void);
+const guint gsl_alloc_upper_power2 (const gulong number);
+void _gsl_tick_stamp_inc (void);
+void _gsl_tick_stamp_set_leap (guint ticks);
+void _gsl_init_signal (void);
+void _gsl_init_fd_pool (void);
+void _gsl_init_data_caches (void);
+void _gsl_init_engine_utils (void);
+void _gsl_init_loader_gslwave (void);
+void _gsl_init_loader_wav (void);
+void _gsl_init_loader_oggvorbis (void);
+void _gsl_init_loader_mad (void);
+#define GSL_N_IO_RETRIES (5)
+#define _GSL_TICK_STAMP_VAL() (gsl_externvar_tick_stamp + 0)
+extern volatile guint64 gsl_externvar_tick_stamp;
+extern GslMutexTable gsl_mutex_table;
+
+/* we need to provide a REPORTER and SECTION string for the debugging
+ * and message generation functions. for GCC, we also want to make use
+ * of printf style format checking with G_GNUC_PRINTF(). for the non GCC
+ * case, we push REPORTER and SECTION as thread specific data before
+ * invoking the debugging/message generation function. for the GCC case
+ * we use GNUC varargs. (using ISO varargs wouldn't provide any benefit,
+ * for one, ISO vararg support is broken with gcc-2.95 and ansi/c++, and
+ * we only need the macro magic for GCC in the first place to make use
+ * of G_GNUC_PRINTF()).
+ */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define _GSL_DEBUG_MACRO_IMPL(reporter, section) gsl_debug ((reporter), (section), _GSL_DEBUG_GCCTAIL
+#define _GSL_DEBUG_GCCTAIL(GCCARGS...) GCCARGS )
+#define _GSL_MESSAGE_MACRO_IMPL(reporter, section) gsl_message_send ((reporter), (section), _GSL_MESSGAE_GCCTAIL
+#define _GSL_MESSGAE_GCCTAIL(GCCARGS...) GCCARGS )
+#else /* non GCC, push data and invoke function */
+#define _GSL_DEBUG_MACRO_IMPL(reporter, section) (gsl_auxlog_push ((reporter), (section)), gsl_auxlog_debug)
+#define _GSL_MESSAGE_MACRO_IMPL(reporter, section) (gsl_auxlog_push ((reporter), (section)), gsl_auxlog_message)
+#endif
+/* non-GCC message helpers */
+void gsl_auxlog_push (GslDebugFlags reporter,
+ const gchar *section);
+void gsl_auxlog_debug (const gchar *format,
+ ...);
+void gsl_auxlog_message (GslErrorType error,
+ const gchar *format,
+ ...);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_COMMON_H__ */
diff --git a/flow/gsl/gslconfig.h.in b/flow/gsl/gslconfig.h.in
new file mode 100644
index 0000000..6e91bd5
--- /dev/null
+++ b/flow/gsl/gslconfig.h.in
@@ -0,0 +1,11 @@
+#define GSL_SIZEOF_PTH_MUTEX_T (@GSL_SIZEOF_PTH_MUTEX_T@)
+#define GSL_SIZEOF_PTH_COND_T (@GSL_SIZEOF_PTH_COND_T@)
+#define GSL_HAVE_MUTEXATTR_SETTYPE (@GSL_HAVE_MUTEXATTR_SETTYPE@ && \
+ GSL_SIZEOF_PTH_MUTEX_T && \
+ GSL_SIZEOF_PTH_COND_T)
+#define GSL_SIZEOF_STD_INTMAX_T (@GSL_SIZEOF_STD_INTMAX_T@)
+#define GSL_HAVE_LIBMAD (@GSL_HAVE_LIBMAD@)
+#define GSL_HAVE_OGGVORBIS (@GSL_HAVE_OGGVORBIS@)
+#define GSL_HAVE_OGGVORBIS_RC3 (@GSL_HAVE_OGGVORBIS_RC3@)
+#define GSL_USE_GSL_GLIB (@GSL_USE_GSL_GLIB@)
+#define GSL_USE_ARTS_THREADS (@GSL_USE_ARTS_THREADS@)
diff --git a/flow/gsl/gslconvert.c b/flow/gsl/gslconvert.c
new file mode 100644
index 0000000..95db568
--- /dev/null
+++ b/flow/gsl/gslconvert.c
@@ -0,0 +1,57 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslconvert.h"
+#include <string.h>
+
+
+
+/* --- functions --- */
+gchar*
+gsl_convert_from_utf8 (const gchar *codeset,
+ const gchar *string)
+{
+ gchar *result;
+
+ g_return_val_if_fail (codeset != NULL, NULL);
+ if (!string)
+ return NULL;
+
+ result = g_convert (string, strlen (string), codeset, GSL_CODESET_UTF8, NULL, NULL, NULL);
+ if (!result)
+ result = g_strconcat ("??unknown-codeset:", codeset, "??", NULL);
+
+ return result;
+}
+
+gchar*
+gsl_convert_to_utf8 (const gchar *codeset,
+ const gchar *string)
+{
+ gchar *result;
+
+ g_return_val_if_fail (codeset != NULL, NULL);
+ if (!string)
+ return NULL;
+
+ result = g_convert (string, strlen (string), GSL_CODESET_UTF8, codeset, NULL, NULL, NULL);
+ if (!result)
+ result = g_strconcat ("??unknown-codeset:", codeset, "??", NULL);
+
+ return result;
+}
diff --git a/flow/gsl/gslconvert.h b/flow/gsl/gslconvert.h
new file mode 100644
index 0000000..10e685f
--- /dev/null
+++ b/flow/gsl/gslconvert.h
@@ -0,0 +1,43 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_CONVERT_H__
+#define __GSL_CONVERT_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GSL_CODESET_8859_1 "ISO-8859-1" /* LATIN-1 */
+#define GSL_CODESET_UTF8 "UTF8" /* "ISO-10646" */
+
+gchar* gsl_convert_from_utf8 (const gchar *codeset,
+ const gchar *string);
+gchar* gsl_convert_to_utf8 (const gchar *codeset,
+ const gchar *string);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_CONVERT_H__ */
diff --git a/flow/gsl/gsldatacache.c b/flow/gsl/gsldatacache.c
new file mode 100644
index 0000000..c1df215
--- /dev/null
+++ b/flow/gsl/gsldatacache.c
@@ -0,0 +1,633 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik
+ * Copyright (C) 2004 Stefan Westerfeld
+ *
+ * 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsldatacache.h"
+
+#include "gslcommon.h"
+#include "gsldatahandle.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+
+/* --- macros --- */
+#define NODEP_INDEX(dcache, node_p) ((node_p) - (dcache)->nodes)
+#define UPPER_POWER2(n) (gsl_alloc_upper_power2 (MAX (n, 4)))
+#define CONFIG_NODE_SIZE() (gsl_get_config ()->dcache_block_size)
+#define AGE_EPSILON (3) /* must be < smallest sweep */
+#define LOW_PERSISTENCY_SWEEP (5)
+
+/* we use one global lock to protect the dcache list, the list
+ * count (length) and the number of aged (unused) nodes.
+ * also, each dcache has its own mutext to protect updates in
+ * the reference count, nodes or node data blocks.
+ * in order to avoid deadlocks, if both locks need
+ * to be held, they always have to be acquired in the order
+ * 1) global lock, 2) dcache lock.
+ * asyncronous data block filling for a new node occours without
+ * the dcache lock being held (as most calls to GslDataHandle
+ * functions).
+ * however, assignment of the newly acquired data is again
+ * protected by the dcache lock. concurrent API entries
+ * which require demand loading of such data will wait on
+ * a global condition which is always signaled once a new data
+ * block read has been completed. using one global condition
+ * is considered sufficient until shown otherwise by further
+ * profiling/debugging measures.
+ */
+
+
+/* --- prototypes --- */
+static void dcache_free (GslDataCache *dcache);
+static GslDataCacheNode* data_cache_new_node_L (GslDataCache *dcache,
+ gsize offset,
+ guint pos,
+ gboolean demand_load);
+
+
+/* --- variables --- */
+static GslMutex global_dcache_mutex = { 0, };
+static GslCond global_dcache_cond_node_filled = { 0, };
+static GslRing *global_dcache_list = NULL;
+static guint global_dcache_count = 0;
+static guint global_dcache_n_aged_nodes = 0;
+
+
+/* --- functions --- */
+void
+_gsl_init_data_caches (void)
+{
+ static gboolean initialized = FALSE;
+
+ g_assert (initialized == FALSE);
+ initialized++;
+
+ g_assert (AGE_EPSILON < LOW_PERSISTENCY_SWEEP);
+ gsl_cond_init (&global_dcache_cond_node_filled);
+ gsl_mutex_init (&global_dcache_mutex);
+}
+
+GslDataCache*
+gsl_data_cache_new (GslDataHandle *dhandle,
+ guint padding)
+{
+ guint node_size = CONFIG_NODE_SIZE () / sizeof (GslDataType);
+ GslDataCache *dcache;
+
+ g_return_val_if_fail (dhandle != NULL, NULL);
+ g_return_val_if_fail (padding > 0, NULL);
+ g_return_val_if_fail (dhandle->name != NULL, NULL);
+ g_assert (node_size == gsl_alloc_upper_power2 (node_size));
+ g_return_val_if_fail (padding < node_size / 2, NULL);
+
+ /* allocate new closed dcache if necessary */
+ dcache = gsl_new_struct (GslDataCache, 1);
+ dcache->dhandle = gsl_data_handle_ref (dhandle);
+ dcache->open_count = 0;
+ gsl_mutex_init (&dcache->mutex);
+ dcache->ref_count = 1;
+ dcache->node_size = node_size;
+ dcache->padding = padding;
+ dcache->max_age = 0;
+ dcache->low_persistency = FALSE; /* FIXME: !gsl_data_handle_needs_cache (dcache->dhandle); */
+ dcache->n_nodes = 0;
+ dcache->nodes = g_renew (GslDataCacheNode*, NULL, UPPER_POWER2 (dcache->n_nodes));
+
+ GSL_SPIN_LOCK (&global_dcache_mutex);
+ global_dcache_list = gsl_ring_append (global_dcache_list, dcache);
+ global_dcache_count++;
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+
+ return dcache;
+}
+
+void
+gsl_data_cache_open (GslDataCache *dcache)
+{
+ g_return_if_fail (dcache != NULL);
+ g_return_if_fail (dcache->ref_count > 0);
+
+ GSL_SPIN_LOCK (&dcache->mutex);
+ if (!dcache->open_count)
+ {
+ GslErrorType error;
+
+ error = gsl_data_handle_open (dcache->dhandle);
+ if (error)
+ {
+ /* FIXME: this is pretty fatal, throw out zero blocks now? */
+ gsl_message_send (GSL_MSG_DATA_CACHE, "Open",
+ error,
+ "failed to open \"%s\": %s",
+ dcache->dhandle->name,
+ gsl_strerror (error));
+ }
+ else
+ {
+ dcache->open_count = 1;
+ dcache->ref_count++;
+ }
+ }
+ else
+ dcache->open_count++;
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+}
+
+void
+gsl_data_cache_close (GslDataCache *dcache)
+{
+ gboolean need_unref;
+
+ g_return_if_fail (dcache != NULL);
+ g_return_if_fail (dcache->ref_count > 0);
+ g_return_if_fail (dcache->open_count > 0);
+
+ GSL_SPIN_LOCK (&dcache->mutex);
+ dcache->open_count--;
+ need_unref = !dcache->open_count;
+ if (!dcache->open_count)
+ gsl_data_handle_close (dcache->dhandle);
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ if (need_unref)
+ gsl_data_cache_unref (dcache);
+}
+
+GslDataCache*
+gsl_data_cache_ref (GslDataCache *dcache)
+{
+ g_return_val_if_fail (dcache != NULL, NULL);
+ g_return_val_if_fail (dcache->ref_count > 0, NULL);
+
+ /* we might get invoked with global_dcache_mutex locked */
+ GSL_SPIN_LOCK (&dcache->mutex);
+ dcache->ref_count++;
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+
+ return dcache;
+}
+
+static void
+dcache_free (GslDataCache *dcache)
+{
+ guint i;
+
+ g_return_if_fail (dcache->ref_count == 0);
+ g_return_if_fail (dcache->open_count == 0);
+
+ gsl_data_handle_unref (dcache->dhandle);
+ gsl_mutex_destroy (&dcache->mutex);
+ for (i = 0; i < dcache->n_nodes; i++)
+ {
+ GslDataCacheNode *node = dcache->nodes[i];
+ guint size;
+
+ size = dcache->node_size + (dcache->padding << 1);
+ gsl_delete_structs (GslDataType, size, node->data - dcache->padding);
+ gsl_delete_struct (GslDataCacheNode, node);
+ }
+ g_free (dcache->nodes);
+ gsl_delete_struct (GslDataCache, dcache);
+}
+
+void
+gsl_data_cache_unref (GslDataCache *dcache)
+{
+ g_return_if_fail (dcache != NULL);
+ restart:
+ g_return_if_fail (dcache->ref_count > 0);
+
+ if (dcache->ref_count == 1) /* possible destruction, need global lock */
+ {
+ g_return_if_fail (dcache->open_count == 0);
+
+ GSL_SPIN_LOCK (&global_dcache_mutex);
+ GSL_SPIN_LOCK (&dcache->mutex);
+ if (dcache->ref_count != 1)
+ {
+ /* damn, some other thread trapped in, restart */
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ goto restart;
+ }
+ dcache->ref_count = 0;
+ global_dcache_list = gsl_ring_remove (global_dcache_list, dcache);
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ global_dcache_count--;
+ global_dcache_n_aged_nodes -= dcache->n_nodes;
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ dcache_free (dcache);
+ }
+ else
+ {
+ GSL_SPIN_LOCK (&dcache->mutex);
+ if (dcache->ref_count < 2)
+ {
+ /* damn, some other thread trapped in, restart */
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ goto restart;
+ }
+ dcache->ref_count--;
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ }
+}
+
+static inline GslDataCacheNode**
+data_cache_lookup_nextmost_node_L (GslDataCache *dcache,
+ gsize offset)
+{
+ if (dcache->n_nodes > 0)
+ {
+ GslDataCacheNode **check, **nodes = dcache->nodes;
+ guint n_nodes = dcache->n_nodes, node_size = dcache->node_size;
+
+ /* caller has to figure himself whether we return nextmost vs. exact match */
+ nodes -= 1;
+ do
+ {
+ register gint cmp;
+ register guint i;
+
+ i = (n_nodes + 1) >> 1;
+ check = nodes + i;
+ cmp = offset < (*check)->offset ? -1 : offset >= (*check)->offset + node_size;
+ if (cmp == 0)
+ return check; /* exact match */
+ else if (cmp > 0)
+ {
+ n_nodes -= i;
+ nodes = check;
+ }
+ else /* if (cmp < 0) */
+ n_nodes = i - 1;
+ }
+ while (n_nodes);
+
+ return check; /* nextmost */
+ }
+ return NULL;
+}
+
+static inline GslDataCacheNode*
+data_cache_new_node_L (GslDataCache *dcache,
+ gsize offset,
+ guint pos,
+ gboolean demand_load)
+{
+ GslDataCacheNode **node_p, *dnode;
+ GslDataCacheNode *left_node;
+ GslDataType *data, *node_data;
+ guint new_node_array_size, old_node_array_size = UPPER_POWER2 (dcache->n_nodes);
+ GslLong dhandle_length;
+ guint i, size;
+ gint result;
+
+ i = dcache->n_nodes++;
+ new_node_array_size = UPPER_POWER2 (dcache->n_nodes);
+ if (old_node_array_size != new_node_array_size)
+ dcache->nodes = g_renew (GslDataCacheNode*, dcache->nodes, new_node_array_size);
+ node_p = dcache->nodes + pos;
+ g_memmove (node_p + 1, node_p, (i - pos) * sizeof (*node_p));
+ dnode = gsl_new_struct (GslDataCacheNode, 1);
+ (*node_p) = dnode;
+ dnode->offset = offset & ~(dcache->node_size - 1);
+ dnode->ref_count = 1;
+ dnode->age = 0;
+ dnode->data = NULL;
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+
+ size = dcache->node_size + (dcache->padding << 1);
+ data = gsl_new_struct (GslDataType, size);
+ node_data = data + dcache->padding;
+ offset = dnode->offset;
+ if (dcache->padding > offset) /* pad out bytes before data start */
+ {
+ guint short_pad = dcache->padding - offset;
+
+ memset (data, 0, short_pad * sizeof (GslDataType));
+ size -= short_pad;
+ data += short_pad;
+ offset -= (dcache->padding - short_pad); /* should always result in offset=0 */
+ }
+ else
+ offset -= dcache->padding;
+ if (!demand_load)
+ g_message (G_STRLOC ":FIXME: lazy data loading not yet supported");
+
+ /* if we have a left node, and it contains data that we need, copy it */
+ left_node = pos ? dcache->nodes[pos - 1] : NULL;
+ if (left_node)
+ {
+ guint left_node_size = dcache->node_size;
+ gint left_node_offset = left_node->offset;
+ GslDataType *left_node_data = left_node->data;
+
+ /* padding around left_node */
+ left_node_size += (dcache->padding << 1);
+ left_node_offset -= dcache->padding;
+ left_node_data -= dcache->padding;
+
+ if (offset < left_node_offset + left_node_size)
+ {
+ guint left_node_copy = left_node_offset + left_node_size - offset;
+
+ memcpy (data, left_node_data + offset - left_node_offset,
+ left_node_copy * sizeof (GslDataType));
+
+ offset += left_node_copy;
+ size -= left_node_copy;
+ data += left_node_copy;
+ }
+ }
+ dhandle_length = gsl_data_handle_length (dcache->dhandle);
+ do
+ {
+ if (offset >= dhandle_length)
+ break;
+ size = MIN (size, dhandle_length - offset);
+ result = gsl_data_handle_read (dcache->dhandle, offset, size, data);
+ if (result < 0)
+ {
+ gsl_message_send (GSL_MSG_DATA_CACHE, "ReadAhead",
+ GSL_ERROR_READ_FAILED,
+ "reading from \"%s\"", dcache->dhandle->name);
+ break;
+ }
+ else
+ {
+ offset += result;
+ size -= result;
+ data += result;
+ }
+ }
+ while (size && result > 0);
+ memset (data, 0, size * sizeof (data[0]));
+
+ GSL_SPIN_LOCK (&dcache->mutex);
+ dnode->data = node_data;
+ gsl_cond_broadcast (&global_dcache_cond_node_filled);
+
+ return dnode;
+}
+
+GslDataCacheNode*
+gsl_data_cache_ref_node (GslDataCache *dcache,
+ gsize offset,
+ GslDataCacheRequest load_request)
+{
+ GslDataCacheNode **node_p, *node;
+ guint insertion_pos;
+
+ g_return_val_if_fail (dcache != NULL, NULL);
+ g_return_val_if_fail (dcache->ref_count > 0, NULL);
+ g_return_val_if_fail (dcache->open_count > 0, NULL);
+ g_return_val_if_fail (offset < gsl_data_handle_length (dcache->dhandle), NULL);
+
+ GSL_SPIN_LOCK (&dcache->mutex);
+ node_p = data_cache_lookup_nextmost_node_L (dcache, offset);
+ if (node_p)
+ {
+ node = *node_p;
+ if (offset >= node->offset && offset < node->offset + dcache->node_size)
+ {
+ gboolean rejuvenate_node = !node->ref_count;
+
+ if (load_request == GSL_DATA_CACHE_PEEK)
+ {
+ if (node->data)
+ node->ref_count++;
+ else
+ node = NULL;
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ if (node && rejuvenate_node)
+ {
+ GSL_SPIN_LOCK (&global_dcache_mutex); /* different lock */
+ global_dcache_n_aged_nodes--;
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ }
+ return node;
+ }
+
+ node->ref_count++;
+ if (load_request == GSL_DATA_CACHE_DEMAND_LOAD)
+ while (!node->data)
+ gsl_cond_wait (&global_dcache_cond_node_filled, &dcache->mutex);
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ /* g_printerr ("hit: %d :%d: %d\n", node->offset, offset, node->offset + dcache->node_size); */
+
+ if (rejuvenate_node)
+ {
+ GSL_SPIN_LOCK (&global_dcache_mutex); /* different lock */
+ global_dcache_n_aged_nodes--;
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ }
+
+ return node; /* exact match */
+ }
+ insertion_pos = NODEP_INDEX (dcache, node_p); /* insert before neighbour */
+ if (offset > node->offset) /* insert after neighbour */
+ insertion_pos += 1;
+ /* g_printerr ("mis: %d :%d: %d\n", node->offset, offset, node->offset + dcache->node_size); */
+ }
+ else
+ insertion_pos = 0; /* insert at start */
+
+ if (load_request != GSL_DATA_CACHE_PEEK)
+ node = data_cache_new_node_L (dcache, offset, insertion_pos, load_request == GSL_DATA_CACHE_DEMAND_LOAD);
+ else
+ node = NULL;
+
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+
+ return node;
+}
+
+static gboolean /* still locked */
+data_cache_free_olders_Lunlock (GslDataCache *dcache,
+ guint max_lru) /* how many lru nodes to keep */
+{
+ GslDataCacheNode **slot_p;
+ guint i, rejuvenate, size;
+ guint n_freed = 0;
+
+ g_return_val_if_fail (dcache != NULL, TRUE);
+
+ /* it doesn't make sense to free nodes below the jitter that
+ * AGE_EPSILON attempts to prevent.
+ */
+ max_lru = MAX (AGE_EPSILON, max_lru);
+ if (max_lru >= dcache->max_age)
+ return TRUE;
+
+ rejuvenate = dcache->max_age - max_lru;
+ if (0)
+ g_print ("start sweep: dcache (%p) with %u nodes, max_age: %u, rejuvenate: %u (max_lru: %u)\n",
+ dcache, dcache->n_nodes, dcache->max_age, rejuvenate, max_lru);
+ size = dcache->node_size + (dcache->padding << 1);
+ slot_p = NULL;
+ for (i = 0; i < dcache->n_nodes; i++)
+ {
+ GslDataCacheNode *node = dcache->nodes[i];
+
+ if (!node->ref_count && node->age <= rejuvenate)
+ {
+ gsl_delete_structs (GslDataType, size, node->data - dcache->padding);
+ gsl_delete_struct (GslDataCacheNode, node);
+ if (!slot_p)
+ slot_p = dcache->nodes + i;
+ n_freed++;
+ }
+ else
+ {
+ node->age -= MIN (rejuvenate, node->age);
+ if (slot_p)
+ {
+ *slot_p = node;
+ slot_p++;
+ }
+ }
+ }
+ dcache->max_age = max_lru;
+ if (slot_p)
+ dcache->n_nodes = NODEP_INDEX (dcache, slot_p);
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+
+ if (n_freed)
+ {
+ GSL_SPIN_LOCK (&global_dcache_mutex);
+ global_dcache_n_aged_nodes -= n_freed;
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ }
+
+ if (0)
+ g_printerr ("freed %u nodes (%u bytes) remaining %u bytes\n",
+ n_freed, n_freed * CONFIG_NODE_SIZE (),
+ global_dcache_n_aged_nodes * CONFIG_NODE_SIZE ());
+ return FALSE;
+}
+
+void
+gsl_data_cache_unref_node (GslDataCache *dcache,
+ GslDataCacheNode *node)
+{
+ GslDataCacheNode **node_p;
+ gboolean check_cache;
+
+ g_return_if_fail (dcache != NULL);
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (node->ref_count > 0);
+
+ GSL_SPIN_LOCK (&dcache->mutex);
+ node_p = data_cache_lookup_nextmost_node_L (dcache, node->offset);
+ g_assert (node_p && *node_p == node); /* paranoid check lookup, yeah! */
+ node->ref_count -= 1;
+ check_cache = !node->ref_count;
+ if (!node->ref_count &&
+ (node->age + AGE_EPSILON <= dcache->max_age ||
+ dcache->max_age < AGE_EPSILON))
+ node->age = ++dcache->max_age;
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+
+ if (check_cache)
+ {
+ guint node_size = CONFIG_NODE_SIZE ();
+ guint cache_mem = gsl_get_config ()->dcache_cache_memory;
+ guint current_mem;
+
+ /* FIXME: cache sweeping should not be done from _unref_node for high persistency caches */
+ GSL_SPIN_LOCK (&global_dcache_mutex);
+ global_dcache_n_aged_nodes++;
+ current_mem = node_size * global_dcache_n_aged_nodes;
+ if (current_mem > cache_mem)
+ {
+ guint dcache_count, needs_unlock;
+ dcache = gsl_ring_pop_head (&global_dcache_list);
+ GSL_SPIN_LOCK (&dcache->mutex);
+ dcache->ref_count++;
+ global_dcache_list = gsl_ring_append (global_dcache_list, dcache);
+ dcache_count = global_dcache_count;
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ if (dcache->low_persistency)
+ needs_unlock = data_cache_free_olders_Lunlock (dcache, LOW_PERSISTENCY_SWEEP);
+ else
+ {
+ guint max_lru;
+ /* try to free the actual cache overflow from the
+ * dcache we just picked, but don't free more than
+ * 25% of its nodes yet.
+ * overflow is actual overhang + ~6% of cache size,
+ * so cache sweeps are triggered less frequently.
+ */
+ current_mem -= cache_mem; /* overhang */
+ current_mem += cache_mem >> 4; /* overflow = overhang + 6% */
+ current_mem /= node_size; /* n_nodes to free */
+ current_mem = MIN (current_mem, dcache->n_nodes);
+ max_lru = dcache->n_nodes >> 1;
+ max_lru += max_lru >> 1; /* 75% of n_nodes */
+ max_lru = MAX (max_lru, dcache->n_nodes - current_mem);
+ needs_unlock = data_cache_free_olders_Lunlock (dcache, MAX (max_lru, LOW_PERSISTENCY_SWEEP));
+ }
+ if (needs_unlock)
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+ }
+ else
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ }
+}
+
+void
+gsl_data_cache_free_olders (GslDataCache *dcache,
+ guint max_age)
+{
+ gboolean needs_unlock;
+ g_return_if_fail (dcache != NULL);
+
+ GSL_SPIN_LOCK (&dcache->mutex);
+ needs_unlock = data_cache_free_olders_Lunlock (dcache, max_age);
+ if (needs_unlock)
+ GSL_SPIN_UNLOCK (&dcache->mutex);
+}
+
+GslDataCache*
+gsl_data_cache_from_dhandle (GslDataHandle *dhandle,
+ guint min_padding)
+{
+ GslRing *ring;
+
+ g_return_val_if_fail (dhandle != NULL, NULL);
+
+ GSL_SPIN_LOCK (&global_dcache_mutex);
+ for (ring = global_dcache_list; ring; ring = gsl_ring_walk (global_dcache_list, ring))
+ {
+ GslDataCache *dcache = ring->data;
+
+ if (dcache->dhandle == dhandle && dcache->padding >= min_padding)
+ {
+ gsl_data_cache_ref (dcache);
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+ return dcache;
+ }
+ }
+ GSL_SPIN_UNLOCK (&global_dcache_mutex);
+
+ return gsl_data_cache_new (dhandle, min_padding);
+}
diff --git a/flow/gsl/gsldatacache.h b/flow/gsl/gsldatacache.h
new file mode 100644
index 0000000..5eb3677
--- /dev/null
+++ b/flow/gsl/gsldatacache.h
@@ -0,0 +1,87 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_DATA_CACHE_H__
+#define __GSL_DATA_CACHE_H__
+
+#include <gsl/gslcommon.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- macros --- */
+#define GSL_DATA_CACHE_NODE_SIZE(dcache) (((GslDataCache*) (dcache))->node_size)
+
+
+/* --- typedefs & structures --- */
+typedef gfloat GslDataType;
+typedef struct _GslDataCacheNode GslDataCacheNode;
+struct _GslDataCache
+{
+ GslDataHandle *dhandle;
+ guint open_count;
+ GslMutex mutex;
+ guint ref_count;
+ guint node_size; /* power of 2, const for all dcaches */
+ guint padding; /* n_values around blocks */
+ guint max_age;
+ gboolean low_persistency;
+ guint n_nodes;
+ GslDataCacheNode **nodes;
+};
+struct _GslDataCacheNode
+{
+ gsize offset;
+ guint ref_count;
+ guint age;
+ GslDataType *data; /* NULL while busy */
+};
+typedef enum
+{
+ GSL_DATA_CACHE_REQUEST = FALSE, /* node->data may be NULL and will be filled */
+ GSL_DATA_CACHE_DEMAND_LOAD = TRUE, /* blocks until node->data != NULL */
+ GSL_DATA_CACHE_PEEK = 2 /* may return NULL node, data != NULL otherwise */
+} GslDataCacheRequest;
+
+
+/* --- prototypes --- */
+GslDataCache* gsl_data_cache_new (GslDataHandle *dhandle,
+ guint padding);
+GslDataCache* gsl_data_cache_ref (GslDataCache *dcache);
+void gsl_data_cache_unref (GslDataCache *dcache);
+void gsl_data_cache_open (GslDataCache *dcache);
+void gsl_data_cache_close (GslDataCache *dcache);
+GslDataCacheNode* gsl_data_cache_ref_node (GslDataCache *dcache,
+ gsize offset,
+ GslDataCacheRequest load_request);
+void gsl_data_cache_unref_node (GslDataCache *dcache,
+ GslDataCacheNode *node);
+void gsl_data_cache_free_olders (GslDataCache *dcache,
+ guint max_age);
+GslDataCache* gsl_data_cache_from_dhandle (GslDataHandle *dhandle,
+ guint min_padding);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_DATA_CACHE_H__ */
diff --git a/flow/gsl/gsldatahandle-lbuffer.c b/flow/gsl/gsldatahandle-lbuffer.c
new file mode 100644
index 0000000..99538bf
--- /dev/null
+++ b/flow/gsl/gsldatahandle-lbuffer.c
@@ -0,0 +1,11 @@
+
+
+typedef struct {
+ GslDataHandle dhandle;
+
+ GslLong pcm_pos;
+ guint pcm_length;
+ guint pcm_size;
+} LBufferHandle;
+
+/* ring buffer, caching the last n values read */
diff --git a/flow/gsl/gsldatahandle-mad.c b/flow/gsl/gsldatahandle-mad.c
new file mode 100644
index 0000000..fcfdd7f
--- /dev/null
+++ b/flow/gsl/gsldatahandle-mad.c
@@ -0,0 +1,711 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <gsl/gsldatahandle-mad.h>
+
+#include "gslfilehash.h"
+#include <gsl/gsldatautils.h>
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#if GSL_HAVE_LIBMAD
+#include <mad.h>
+
+
+/* --- debugging and errors --- */
+#define MAD_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_DATA_HANDLE, "MAD")
+#define MAD_MSG GSL_MESSAGE_FUNCTION (GSL_MSG_DATA_HANDLE, "MAD")
+
+
+/* --- defines --- */
+#define FILE_BUFFER_SIZE (1024 * 44) /* approximately 1 second at 320 kbit */
+#define SEEK_BY_READ_AHEAD(h) (((h)->sample_rate / ((h)->frame_size * 2))) /* FIXME */
+#define MAX_CHANNELS (5)
+
+
+/* --- typedefs & structures --- */
+typedef struct
+{
+ GslDataHandle dhandle;
+
+ /* setup data */
+ guint sample_rate;
+ guint frame_size;
+ guint stream_options;
+ guint accumulate_state_frames;
+ guint skip_seek_table : 1;
+
+ /* file IO */
+ guint eof : 1;
+ GslHFile *hfile;
+ guint file_pos;
+ const gchar *error;
+
+ /* seek table */
+ GTime seek_mtime;
+ guint n_seeks;
+ guint *seeks;
+
+ /* file read buffer */
+ guint bfill;
+ guint8 buffer[FILE_BUFFER_SIZE + MAD_BUFFER_GUARD];
+
+ /* pcm housekeeping */
+ GslLong pcm_pos, pcm_length, next_pcm_pos;
+
+ /* libmad structures */
+ struct mad_stream stream;
+ struct mad_frame frame;
+ struct mad_synth synth;
+} MadHandle;
+
+
+/* --- prototypes --- */
+static GslLong dh_mad_coarse_seek (GslDataHandle *data_handle,
+ GslLong voffset);
+
+
+/* --- functions --- */
+static gboolean /* FALSE: handle->eof || errno != 0 */
+stream_read (MadHandle *handle)
+{
+ struct mad_stream *stream = &handle->stream;
+ guint l;
+
+ /* no further data to read (flag must be reset upon seeks) */
+ if (handle->eof)
+ return FALSE;
+
+ /* keep remaining data in buffer */
+ if (stream->next_frame && handle->bfill)
+ {
+ handle->bfill = handle->buffer + handle->bfill - stream->next_frame;
+ memmove (handle->buffer, stream->next_frame, handle->bfill);
+ }
+
+ /* fill buffer */
+ l = gsl_hfile_pread (handle->hfile, handle->file_pos, FILE_BUFFER_SIZE - handle->bfill, handle->buffer + handle->bfill);
+ if (l > 0)
+ {
+ handle->bfill += l;
+ handle->file_pos += l;
+ }
+ else if (l == 0)
+ {
+ handle->eof = TRUE;
+ memset (handle->buffer + handle->bfill, 0, MAD_BUFFER_GUARD);
+ handle->bfill += MAD_BUFFER_GUARD;
+ handle->file_pos += MAD_BUFFER_GUARD; /* bogus, but doesn't matter at eof */
+ }
+
+ mad_stream_buffer (stream, handle->buffer, handle->bfill);
+
+ return l < 0 ? FALSE : TRUE;
+}
+
+static gboolean
+check_frame_validity (MadHandle *handle,
+ struct mad_header *header)
+{
+ guint frame_size = MAD_NSBSAMPLES (header) * 32;
+ gchar *reason = NULL;
+
+ if (frame_size <= 0)
+ reason = "frame_size < 1";
+
+ if (handle->frame_size && handle->dhandle.setup.n_channels)
+ {
+#if 0
+ if (frame_size != handle->frame_size)
+ reason = "frame with non-standard size";
+#endif
+ if (MAD_NCHANNELS (header) != handle->dhandle.setup.n_channels)
+ reason = "frame with non-standard channel count";
+ }
+
+ if (reason)
+ {
+ MAD_DEBUG ("skipping frame: %s", reason);
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+static gboolean
+read_next_frame_header (MadHandle *handle)
+{
+ gboolean succeeded = TRUE;
+
+ /* fetch next frame header */
+ if (mad_header_decode (&handle->frame.header, &handle->stream) < 0)
+ {
+ if (!MAD_RECOVERABLE (handle->stream.error) ||
+ handle->stream.error == MAD_ERROR_LOSTSYNC)
+ {
+ /* read on */
+ if (!stream_read (handle))
+ {
+ handle->error = handle->eof ? NULL : g_strerror (errno);
+ return FALSE;
+ }
+ return read_next_frame_header (handle); /* retry */
+ }
+
+ if (!check_frame_validity (handle, &handle->frame.header))
+ return read_next_frame_header (handle); /* retry */
+
+ succeeded = FALSE;
+ }
+
+ handle->error = handle->stream.error ? mad_stream_errorstr (&handle->stream) : NULL;
+
+ return succeeded;
+}
+
+static gboolean /* FALSE: handle->eof || handle->error != NULL */
+pcm_frame_read (MadHandle *handle,
+ gboolean synth)
+{
+ gboolean succeeded = TRUE;
+
+ if (mad_frame_decode (&handle->frame, &handle->stream) < 0)
+ {
+ if (!MAD_RECOVERABLE (handle->stream.error) ||
+ handle->stream.error == MAD_ERROR_LOSTSYNC)
+ {
+ /* MAD_RECOVERABLE()==TRUE: frame was read, decoding failed (about to skip frame)
+ * MAD_RECOVERABLE()==FALSE: frame was not read, need data
+ * note: MAD_RECOVERABLE (MAD_ERROR_LOSTSYNC) == TRUE
+ */
+
+ /* read on */
+ if (!stream_read (handle))
+ {
+ handle->error = handle->eof ? NULL : g_strerror (errno);
+ return FALSE;
+ }
+ return pcm_frame_read (handle, synth); /* retry */
+ }
+
+ succeeded = FALSE;
+ if (synth)
+ mad_frame_mute (&handle->frame);
+ }
+
+ handle->pcm_pos = handle->next_pcm_pos;
+ handle->pcm_length = handle->frame_size;
+ handle->next_pcm_pos += handle->pcm_length;
+
+ if (synth)
+ mad_synth_frame (&handle->synth, &handle->frame);
+
+ handle->error = handle->stream.error && !succeeded ? mad_stream_errorstr (&handle->stream) : NULL;
+
+ return succeeded;
+}
+
+static guint*
+create_seek_table (MadHandle *handle,
+ guint *n_seeks_p)
+{
+ guint *seeks = NULL;
+ guint offs, n_seeks = 0;
+
+ *n_seeks_p = 0;
+ mad_synth_finish (&handle->synth);
+ mad_frame_finish (&handle->frame);
+ mad_stream_finish (&handle->stream);
+ mad_stream_init (&handle->stream);
+ mad_frame_init (&handle->frame);
+ mad_synth_init (&handle->synth);
+ mad_stream_options (&handle->stream, handle->stream_options);
+
+ offs = 0;
+ /* lseek (handle->hfile, offs, SEEK_SET) */
+ handle->eof = FALSE;
+ handle->bfill = 0;
+ handle->file_pos = 0;
+
+ do
+ {
+ while (read_next_frame_header (handle))
+ {
+ guint this_pos = handle->file_pos - handle->bfill + handle->stream.this_frame - handle->buffer;
+ guint i = n_seeks++;
+
+ if (n_seeks > 256 * 1024) /* FIXME: max_frames */
+ {
+ g_free (seeks);
+ return NULL; /* FIXME: ETOOBIG */
+ }
+
+ if (gsl_alloc_upper_power2 (n_seeks) > gsl_alloc_upper_power2 (i))
+ seeks = g_renew (guint, seeks, gsl_alloc_upper_power2 (n_seeks));
+ seeks[i] = this_pos;
+
+ if (0)
+ {
+ if (mad_frame_decode (&handle->frame, &handle->stream) < 0)
+ MAD_DEBUG ("seektable frame read failed: %s", mad_stream_errorstr (&handle->stream));
+ mad_synth_frame (&handle->synth, &handle->frame);
+ MAD_DEBUG ("frame(%u) PCM:%u => FILE:%u FDIFF:%d (%x %x %x) br:%lu time:%ld/%lu mode:%u ext:%u flags:0x%x phase:%u",
+ i, i * handle->frame_size, this_pos, this_pos - seeks[MAX (i, 1) - 1],
+ handle->stream.this_frame[0], handle->stream.this_frame[1],
+ (handle->stream.this_frame[1] >> 1) & 3,
+ handle->frame.header.bitrate,
+ handle->frame.header.duration.seconds,
+ handle->frame.header.duration.fraction,
+ handle->frame.header.mode,
+ handle->frame.header.mode_extension,
+ handle->frame.header.flags,
+ handle->synth.phase);
+ }
+ }
+
+ if (!handle->eof)
+ {
+ MAD_DEBUG ("reading seektable frame failed: %s", handle->error ? handle->error : "Unknown");
+
+ /* frame read failed for a reason other than eof */
+ g_free (seeks);
+ return NULL; /* FIXME: EIO/errno */
+ }
+ }
+ while (!handle->eof);
+
+ /* reset file offset */
+ offs = 0;
+ /* lseek (handle->hfile, offs, SEEK_SET) */
+ handle->eof = FALSE;
+ handle->file_pos = 0;
+ handle->bfill = 0;
+
+ /* shrink table */
+ seeks = g_renew (guint, seeks, n_seeks);
+ *n_seeks_p = n_seeks;
+
+ return seeks;
+}
+
+static GslErrorType
+dh_mad_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ MadHandle *handle = (MadHandle*) dhandle;
+ GslHFile *hfile;
+ GslLong n;
+ gboolean seek_invalidated = FALSE;
+
+ hfile = gsl_hfile_open (handle->dhandle.name);
+ if (!hfile)
+ return gsl_error_from_errno (errno, GSL_ERROR_OPEN_FAILED);
+ handle->hfile = hfile;
+
+ seek_invalidated |= handle->seek_mtime != hfile->mtime;
+ handle->bfill = 0;
+ handle->eof = FALSE;
+ handle->pcm_pos = 0;
+ handle->pcm_length = 0;
+ handle->next_pcm_pos = 0;
+ handle->file_pos = 0;
+ mad_stream_init (&handle->stream);
+ mad_frame_init (&handle->frame);
+ mad_synth_init (&handle->synth);
+ mad_stream_options (&handle->stream, handle->stream_options);
+
+ /* fetch first frame */
+ if (!read_next_frame_header (handle))
+ goto OPEN_FAILED;
+
+ /* get n_channels, frame size and sample rate */
+ setup->bit_depth = 24;
+ setup->n_channels = MAD_NCHANNELS (&handle->frame.header);
+ n = MAD_NSBSAMPLES (&handle->frame.header) * 32;
+ seek_invalidated |= n != handle->frame_size;
+ handle->frame_size = n;
+ handle->sample_rate = handle->frame.header.samplerate;
+ if (setup->n_channels < 1 ||
+ setup->n_channels > MAX_CHANNELS ||
+ handle->frame_size < 1 ||
+ handle->sample_rate < 1)
+ goto OPEN_FAILED;
+
+ /* seek through the stream to collect frame positions */
+ if (seek_invalidated || !handle->n_seeks)
+ {
+ handle->seek_mtime = hfile->mtime;
+ handle->n_seeks = 0;
+ g_free (handle->seeks);
+ handle->seeks = NULL;
+ if (handle->skip_seek_table)
+ {
+ /* fake seek table */
+ handle->n_seeks = 1;
+ handle->seeks = g_new (guint, handle->n_seeks);
+ handle->seeks[0] = 0;
+ }
+ else
+ {
+ handle->seeks = create_seek_table (handle, &handle->n_seeks);
+ if (!handle->seeks)
+ goto OPEN_FAILED;
+ MAD_DEBUG ("frames in seektable: %u", handle->n_seeks);
+ }
+ }
+
+ /* validate/setup handle length */
+ n = handle->n_seeks * handle->frame_size * setup->n_channels;
+ if (n > 0)
+ setup->n_values = n;
+ else
+ goto OPEN_FAILED;
+
+ if (dh_mad_coarse_seek (&handle->dhandle, 0) != 0)
+ goto OPEN_FAILED;
+
+ return GSL_ERROR_NONE;
+
+ OPEN_FAILED:
+ g_free (handle->seeks);
+ handle->seeks = NULL;
+ handle->n_seeks = 0;
+ handle->seek_mtime = -1;
+ handle->bfill = 0;
+ handle->eof = FALSE;
+ handle->pcm_pos = 0;
+ handle->pcm_length = 0;
+ handle->next_pcm_pos = 0;
+ handle->file_pos = 0;
+ mad_synth_finish (&handle->synth);
+ mad_frame_finish (&handle->frame);
+ mad_stream_finish (&handle->stream);
+ gsl_hfile_close (handle->hfile);
+ handle->hfile = NULL;
+
+ return GSL_ERROR_OPEN_FAILED;
+}
+
+static GslLong
+dh_mad_read (GslDataHandle *dhandle,
+ GslLong voffset, /* in values */
+ GslLong n_values,
+ gfloat *values)
+{
+ MadHandle *handle = (MadHandle*) dhandle;
+ GslLong pos = voffset / dhandle->setup.n_channels;
+ gboolean frame_read_ok = TRUE;
+
+ if (pos < handle->pcm_pos ||
+ pos >= handle->pcm_pos + handle->pcm_length + SEEK_BY_READ_AHEAD (handle) * handle->frame_size)
+ {
+ GslLong tmp;
+
+ /* suckage, need to do lengthy seek in file */
+ tmp = dh_mad_coarse_seek (dhandle, voffset);
+ g_assert (tmp <= voffset);
+ }
+
+ while (pos >= handle->pcm_pos + handle->pcm_length)
+ frame_read_ok = pcm_frame_read (handle, TRUE);
+
+ /* check if the last call to pcm_frame_read() failed */
+ if (!frame_read_ok)
+ {
+ if (handle->stream.error == MAD_ERROR_BADDATAPTR)
+ {
+ /* if we encounter that the inter-frame accumulated layer-III state
+ * is not complete now, we'll try to increase the amount of frames
+ * we accumulate
+ */
+ if (handle->accumulate_state_frames < 10)
+ {
+ handle->accumulate_state_frames++;
+ MAD_DEBUG ("retrying seek with accumulate_state_frames=%d",
+ handle->accumulate_state_frames);
+
+ /* force dh_mad_read to retry the seek */
+ dh_mad_coarse_seek (dhandle, 0);
+ return dh_mad_read (dhandle, voffset, n_values, values);
+ }
+ else
+ {
+ MAD_DEBUG ("synthesizing frame failed, accumulate_state_frames is already %u: %s",
+ handle->accumulate_state_frames, handle->error);
+ return -1;
+ }
+ }
+ else
+ {
+ MAD_DEBUG ("failed to synthesize frame: %s", handle->error);
+ return -1;
+ }
+ }
+
+ n_values = MIN (n_values, handle->pcm_length * dhandle->setup.n_channels);
+
+ /* interleave into output buffer */
+ if (pos >= handle->pcm_pos && pos < handle->pcm_pos + handle->pcm_length)
+ {
+ guint offset = voffset - handle->pcm_pos * dhandle->setup.n_channels;
+ guint align = offset % dhandle->setup.n_channels;
+ guint n_samples = MIN (n_values, handle->pcm_length * dhandle->setup.n_channels - offset);
+ mad_fixed_t *pcm[MAX_CHANNELS];
+ gfloat *bound = values + n_samples;
+ guint i;
+
+ offset /= dhandle->setup.n_channels;
+ for (i = 0; i < dhandle->setup.n_channels; i++)
+ pcm[i] = handle->synth.pcm.samples[i] + offset + (i < align);
+
+ for (i = align; values < bound; values++)
+ {
+ mad_fixed_t mf = *(pcm[i]++);
+
+ *values = CLAMP (mf, -MAD_F_ONE, MAD_F_ONE) * (1. / (double) MAD_F_ONE);
+ if (++i >= dhandle->setup.n_channels)
+ i = 0;
+ }
+ return n_samples;
+ }
+ else /* something went wrong here, _badly_ */
+ {
+ MAD_MSG (GSL_ERROR_READ_FAILED,
+ "pcm position screwed (pos: %lu, handle-pos: %lu), aborting read",
+ pos, handle->pcm_pos);
+ return -1;
+ }
+}
+
+static GslLong
+dh_mad_coarse_seek (GslDataHandle *dhandle,
+ GslLong voffset)
+{
+ MadHandle *handle = (MadHandle*) dhandle;
+ GslLong opos = handle->pcm_pos, pos = voffset / dhandle->setup.n_channels;
+
+ if (voffset < 0) /* pcm_tell() */
+ return handle->pcm_pos * dhandle->setup.n_channels;
+
+ if (pos < handle->pcm_pos ||
+ pos >= handle->pcm_pos + handle->pcm_length + SEEK_BY_READ_AHEAD (handle))
+ {
+ GslLong offs = pos;
+ guint i, file_pos;
+
+ /* reset decoder state */
+ mad_synth_finish (&handle->synth);
+ mad_frame_finish (&handle->frame);
+ mad_stream_finish (&handle->stream);
+ mad_stream_init (&handle->stream);
+ mad_frame_init (&handle->frame);
+ mad_synth_init (&handle->synth);
+ mad_stream_options (&handle->stream, handle->stream_options);
+
+ /* seek to some frames read ahead to accumulate layer III IDCMT state */
+ offs -= (gint) (handle->frame_size * handle->accumulate_state_frames);
+ offs = CLAMP (offs, 0, (gint) (handle->n_seeks * handle->frame_size));
+
+ /* get file position from seek table */
+ i = offs / handle->frame_size;
+ file_pos = handle->seeks[i];
+
+ /* perform file seek and adjust positions */
+ /* lseek (handle->hfile, file_pos, SEEK_SET) */
+ handle->eof = FALSE;
+ handle->bfill = 0;
+ handle->file_pos = file_pos;
+ handle->pcm_pos = i * handle->frame_size;
+ handle->pcm_length = 0;
+ handle->next_pcm_pos = handle->pcm_pos;
+
+#if 0
+ /* adapt synth phase */
+ handle->synth.phase = ((i + 1) * (handle->frame_size / 32)) % 16;
+#endif
+
+ /* accumulate state */
+ if (pos >= handle->accumulate_state_frames * handle->frame_size)
+ {
+ guint i;
+ for (i = 0; i < handle->accumulate_state_frames; i++)
+ {
+ gboolean synth = i + 1 == handle->accumulate_state_frames;
+
+ if (!pcm_frame_read (handle, synth) && handle->stream.error != MAD_ERROR_BADDATAPTR)
+ MAD_DEBUG ("COARSE-SEEK: frame read ahead (%u): failed: %s", i, handle->error);
+ }
+ }
+
+ MAD_DEBUG ("seek-done: at %lu (f:%lu) want %lu (f:%lu) got %lu (f:%lu) diff %ld (diff-requested %ld)",
+ opos, opos / handle->frame_size,
+ pos, pos / handle->frame_size,
+ handle->pcm_pos, handle->pcm_pos / handle->frame_size,
+ handle->pcm_pos - opos, pos - opos);
+ }
+
+ return handle->pcm_pos * dhandle->setup.n_channels;
+}
+
+static void
+dh_mad_close (GslDataHandle *data_handle)
+{
+ MadHandle *handle = (MadHandle*) data_handle;
+
+ handle->bfill = 0;
+ handle->eof = FALSE;
+ handle->pcm_pos = 0;
+ handle->pcm_length = 0;
+ handle->next_pcm_pos = 0;
+ handle->file_pos = 0;
+ mad_synth_finish (&handle->synth);
+ mad_frame_finish (&handle->frame);
+ mad_stream_finish (&handle->stream);
+ gsl_hfile_close (handle->hfile);
+ handle->hfile = NULL;
+}
+
+static void
+dh_mad_destroy (GslDataHandle *data_handle)
+{
+ MadHandle *handle = (MadHandle*) data_handle;
+
+ g_free (handle->seeks);
+ handle->seeks = NULL;
+ handle->n_seeks = 0;
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (MadHandle, handle);
+}
+
+static GslDataHandleFuncs dh_mad_vtable = {
+ dh_mad_open,
+ dh_mad_read,
+ dh_mad_close,
+ dh_mad_destroy,
+ dh_mad_coarse_seek,
+};
+
+static GslDataHandle*
+dh_mad_new (const gchar *file_name,
+ gboolean skip_seek_keep_open)
+{
+ MadHandle *handle;
+ gboolean success;
+
+ handle = gsl_new_struct0 (MadHandle, 1);
+ success = gsl_data_handle_common_init (&handle->dhandle, file_name);
+ if (success)
+ {
+ GslErrorType error;
+
+ handle->dhandle.vtable = &dh_mad_vtable;
+ handle->sample_rate = 0;
+ handle->frame_size = 0;
+ handle->stream_options = MAD_OPTION_IGNORECRC;
+ handle->accumulate_state_frames = 0;
+ handle->eof = FALSE;
+ handle->hfile = NULL;
+ handle->file_pos = 0;
+ handle->error = NULL;
+ handle->n_seeks = 0;
+ handle->seeks = NULL;
+ handle->seek_mtime = -1;
+ handle->bfill = 0;
+ handle->pcm_pos = handle->pcm_length = handle->next_pcm_pos = 0;
+
+ /* we can only check matters upon opening
+ */
+ handle->skip_seek_table = skip_seek_keep_open != FALSE;
+ error = gsl_data_handle_open (&handle->dhandle);
+ if (!error)
+ {
+ if (!skip_seek_keep_open)
+ gsl_data_handle_close (&handle->dhandle);
+ return &handle->dhandle;
+ }
+ gsl_data_handle_unref (&handle->dhandle);
+ return NULL;
+ }
+ else
+ {
+ g_free (handle->seeks);
+ gsl_delete_struct (MadHandle, handle);
+ return NULL;
+ }
+}
+
+GslDataHandle*
+gsl_data_handle_new_mad (const gchar *file_name)
+{
+ g_return_val_if_fail (file_name != NULL, NULL);
+
+ return dh_mad_new (file_name, FALSE);
+}
+
+GslErrorType
+gsl_data_handle_mad_testopen (const gchar *file_name,
+ guint *n_channels,
+ gfloat *mix_freq)
+{
+ GslDataHandle *dhandle;
+ MadHandle *handle;
+
+ g_return_val_if_fail (file_name != NULL, GSL_ERROR_INTERNAL);
+
+ dhandle = dh_mad_new (file_name, TRUE);
+ if (!dhandle)
+ return GSL_ERROR_OPEN_FAILED;
+
+ handle = (MadHandle*) dhandle;
+ if (n_channels)
+ *n_channels = handle->dhandle.setup.n_channels;
+ if (mix_freq)
+ *mix_freq = handle->sample_rate;
+ gsl_data_handle_close (dhandle);
+ gsl_data_handle_unref (dhandle);
+
+ return GSL_ERROR_NONE;
+}
+
+#else /* !GSL_HAVE_LIBMAD */
+
+GslDataHandle*
+gsl_data_handle_new_mad (const gchar *file_name)
+{
+ return NULL;
+}
+
+GslErrorType
+gsl_data_handle_mad_testopen (const gchar *file_name,
+ guint *n_channels,
+ gfloat *mix_freq)
+{
+ return GSL_ERROR_FORMAT_UNKNOWN;
+}
+
+#endif /* !GSL_HAVE_LIBMAD */
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gsldatahandle-mad.h b/flow/gsl/gsldatahandle-mad.h
new file mode 100644
index 0000000..8c73ef7
--- /dev/null
+++ b/flow/gsl/gsldatahandle-mad.h
@@ -0,0 +1,42 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_DATA_HANDLE_MAD_H__
+#define __GSL_DATA_HANDLE_MAD_H__
+
+#include <gsl/gslcommon.h>
+#include <gsl/gsldatahandle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* linear-read handle. needs buffering handle wrapper
+ */
+GslDataHandle* gsl_data_handle_new_mad (const gchar *file_name);
+GslErrorType gsl_data_handle_mad_testopen (const gchar *file_name,
+ guint *n_channels,
+ gfloat *mix_freq);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_DATA_HANDLE_MAD_H__ */
diff --git a/flow/gsl/gsldatahandle-vorbis.c b/flow/gsl/gsldatahandle-vorbis.c
new file mode 100644
index 0000000..9b84ae0
--- /dev/null
+++ b/flow/gsl/gsldatahandle-vorbis.c
@@ -0,0 +1,376 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsldatahandle-vorbis.h"
+
+#if GSL_HAVE_OGGVORBIS
+#include "gslfilehash.h"
+#include <ogg/ogg.h>
+#include <vorbis/vorbisfile.h>
+#include <errno.h>
+
+
+/* --- defines --- */
+#define MAX_CHANNELS (16) /* hard limit, eases our life somewhat */
+/* number of values to decode and throw away instead of seeking. since
+ * seeking can be quite time consuming, this should cover a good range
+ * of seek-ahead space
+ */
+#define SEEK_BY_READ_AHEAD(vhandle) (vhandle->max_block_size * 8)
+
+
+/* --- structure --- */
+typedef struct {
+ GslDataHandle dhandle;
+
+ guint stream;
+ guint n_streams;
+
+ /* live data */
+ gint64 soffset; /* our PCM start offset */
+ guint max_block_size;
+
+ /* pcm read out cache */
+ GslLong pcm_pos, pcm_length;
+ gfloat *pcm[MAX_CHANNELS];
+
+ OggVorbis_File ofile;
+} VorbisHandle;
+
+
+/* --- functions --- */
+static GslErrorType
+ov_errno_to_error (gint ov_errno,
+ GslErrorType fallback)
+{
+ switch (ov_errno)
+ {
+ case OV_EOF: return GSL_ERROR_EOF;
+ case OV_EBADLINK:
+ case OV_EBADPACKET:
+ case OV_HOLE: return GSL_ERROR_DATA_CORRUPT;
+ case OV_EREAD: return GSL_ERROR_READ_FAILED;
+ case OV_ENOSEEK: return GSL_ERROR_SEEK_FAILED;
+ case OV_EFAULT:
+ case OV_EIMPL: return GSL_ERROR_CODEC_FAILURE;
+ case OV_EINVAL: return GSL_ERROR_INTERNAL;
+ case OV_ENOTAUDIO:
+ case OV_EVERSION:
+ case OV_EBADHEADER:
+ case OV_ENOTVORBIS: return GSL_ERROR_FORMAT_INVALID;
+ case OV_FALSE:
+ default: return fallback;
+ }
+}
+
+static size_t
+rfile_read (void *ptr,
+ size_t size,
+ size_t nmemb,
+ void *datasource)
+{
+ GslRFile *rfile = datasource;
+ return gsl_rfile_read (rfile, size * nmemb, ptr);
+}
+
+static int
+rfile_seek (void *datasource,
+ ogg_int64_t offset,
+ int whence)
+{
+ GslRFile *rfile = datasource;
+ GslLong l;
+ switch (whence)
+ {
+ default:
+ case SEEK_SET:
+ l = gsl_rfile_seek_set (rfile, offset);
+ break;
+ case SEEK_CUR:
+ l = gsl_rfile_position (rfile);
+ l = gsl_rfile_seek_set (rfile, l + offset);
+ break;
+ case SEEK_END:
+ l = gsl_rfile_length (rfile);
+ l = gsl_rfile_seek_set (rfile, l + offset);
+ break;
+ }
+ return l;
+}
+
+static int
+rfile_close (void *datasource)
+{
+ GslRFile *rfile = datasource;
+ gsl_rfile_close (rfile);
+ return 0;
+}
+
+static long
+rfile_tell (void *datasource)
+{
+ GslRFile *rfile = datasource;
+ return gsl_rfile_position (rfile);
+}
+
+static ov_callbacks rfile_ov_callbacks = {
+ rfile_read,
+ rfile_seek,
+ rfile_close,
+ rfile_tell,
+};
+
+static GslErrorType
+dh_vorbis_open (GslDataHandle *data_handle,
+ GslDataHandleSetup *setup)
+{
+ VorbisHandle *vhandle = (VorbisHandle*) data_handle;
+ GslRFile *rfile;
+ vorbis_info *vi;
+ GslLong n, i;
+ gint err;
+
+#if 0
+ file = fopen (vhandle->dhandle.name, "r");
+ if (!file)
+ return gsl_error_from_errno (errno, GSL_ERROR_OPEN_FAILED);
+ err = ov_open (file, &vhandle->ofile, NULL, 0);
+ if (err < 0)
+ {
+ fclose (file);
+ return ov_errno_to_error (err, GSL_ERROR_OPEN_FAILED);
+ }
+#endif
+
+ rfile = gsl_rfile_open (vhandle->dhandle.name);
+ if (!rfile)
+ return gsl_error_from_errno (errno, GSL_ERROR_OPEN_FAILED);
+ err = ov_open_callbacks (rfile, &vhandle->ofile, NULL, 0, rfile_ov_callbacks);
+ if (err < 0)
+ {
+ gsl_rfile_close (rfile);
+ return ov_errno_to_error (err, GSL_ERROR_OPEN_FAILED);
+ }
+
+ n = ov_streams (&vhandle->ofile);
+ if (n > vhandle->stream)
+ vhandle->n_streams = n;
+ else
+ {
+ ov_clear (&vhandle->ofile); /* closes file */
+ return GSL_ERROR_OPEN_FAILED;
+ }
+
+ vhandle->soffset = 0;
+ for (i = 0; i < vhandle->stream; i++)
+ vhandle->soffset += ov_pcm_total (&vhandle->ofile, i);
+
+ n = ov_pcm_total (&vhandle->ofile, vhandle->stream);
+ vi = ov_info (&vhandle->ofile, vhandle->stream);
+ if (n > 0 && vi && vi->channels && ov_pcm_seek (&vhandle->ofile, vhandle->soffset) >= 0)
+ {
+ setup->n_channels = vi->channels;
+ setup->n_values = n * setup->n_channels;
+ setup->bit_depth = 24;
+ }
+ else
+ {
+ ov_clear (&vhandle->ofile); /* closes file */
+ return GSL_ERROR_OPEN_FAILED;
+ }
+
+ vhandle->max_block_size = vorbis_info_blocksize (vi, 0);
+ n = vorbis_info_blocksize (vi, 1);
+ vhandle->max_block_size = MAX (vhandle->max_block_size, n);
+ vhandle->pcm_pos = 0;
+ vhandle->pcm_length = 0;
+
+ return GSL_ERROR_NONE;
+}
+
+static GslLong
+dh_vorbis_coarse_seek (GslDataHandle *dhandle,
+ GslLong voffset)
+{
+ VorbisHandle *vhandle = (VorbisHandle*) dhandle;
+ GslLong opos = vhandle->pcm_pos, pos = voffset / dhandle->setup.n_channels;
+
+ if (voffset < 0)
+ return vhandle->pcm_pos * dhandle->setup.n_channels;
+
+ if (pos < vhandle->pcm_pos ||
+ pos >= vhandle->pcm_pos + vhandle->pcm_length + SEEK_BY_READ_AHEAD (vhandle))
+ {
+ gint err = ov_pcm_seek_page (&vhandle->ofile, vhandle->soffset + pos);
+
+ if (err) /* eek */
+ err = ov_pcm_seek_page (&vhandle->ofile, vhandle->soffset);
+ else
+ vhandle->pcm_pos = ov_pcm_tell (&vhandle->ofile) - vhandle->soffset;
+ if (err || vhandle->pcm_pos < 0) /* urg, we're completely screwed */
+ vhandle->pcm_pos = 0;
+ vhandle->pcm_length = 0;
+ }
+ g_printerr ("OggS-SEEK: at %lu want %lu got %lu (diff-requested %ld)\n",
+ opos, pos, vhandle->pcm_pos, pos - opos);
+
+ return vhandle->pcm_pos * dhandle->setup.n_channels;
+}
+
+static void
+read_packet (VorbisHandle *vhandle)
+{
+ gfloat **pcm = NULL;
+ gint stream_id, i;
+
+ vhandle->pcm_pos = ov_pcm_tell (&vhandle->ofile) - vhandle->soffset;
+#if GSL_HAVE_OGGVORBIS_RC3
+ vhandle->pcm_length = ov_read_float (&vhandle->ofile, &pcm, &stream_id);
+#else
+ vhandle->pcm_length = ov_read_float (&vhandle->ofile, &pcm, (~0U>>1), &stream_id);
+#endif
+ if (vhandle->pcm_pos < 0 || vhandle->pcm_length < 0 || stream_id != vhandle->stream)
+ {
+ /* urg, this is bad! */
+ dh_vorbis_coarse_seek (&vhandle->dhandle, 0);
+ }
+ else
+ for (i = 0; i < vhandle->dhandle.setup.n_channels; i++)
+ vhandle->pcm[i] = pcm[i];
+}
+
+static GslLong
+dh_vorbis_read (GslDataHandle *dhandle,
+ GslLong voffset, /* in values */
+ GslLong n_values,
+ gfloat *values)
+{
+ VorbisHandle *vhandle = (VorbisHandle*) dhandle;
+ GslLong pos = voffset / dhandle->setup.n_channels;
+
+ if (pos < vhandle->pcm_pos ||
+ pos >= vhandle->pcm_pos + vhandle->pcm_length + SEEK_BY_READ_AHEAD (vhandle))
+ {
+ GslLong tmp;
+
+ /* suckage, needs to seek in file, this takes ages */
+ tmp = dh_vorbis_coarse_seek (dhandle, voffset);
+ g_assert (tmp <= voffset);
+ }
+
+ while (pos >= vhandle->pcm_pos + vhandle->pcm_length)
+ read_packet (vhandle);
+
+ n_values = MIN (n_values, vhandle->pcm_length * dhandle->setup.n_channels);
+
+ /* interleave into output buffer */
+ if (pos >= vhandle->pcm_pos && pos < vhandle->pcm_pos + vhandle->pcm_length)
+ {
+ guint offset = voffset - vhandle->pcm_pos * dhandle->setup.n_channels;
+ guint align = offset % dhandle->setup.n_channels;
+ guint n_samples = MIN (n_values, vhandle->pcm_length * dhandle->setup.n_channels - offset);
+ gfloat *pcm[MAX_CHANNELS], *bound = values + n_samples;
+ guint i;
+
+ offset /= dhandle->setup.n_channels;
+ for (i = 0; i < dhandle->setup.n_channels; i++)
+ pcm[i] = vhandle->pcm[i] + offset + (i < align);
+
+ for (i = align; values < bound; values++)
+ {
+ gfloat f = *(pcm[i]++);
+
+ f = CLAMP (f, -1.0, 1.0);
+ *values = f;
+ if (++i >= dhandle->setup.n_channels)
+ i = 0;
+ }
+ return n_samples;
+ }
+ else /* something went wrong here, _badly_ */
+ return 0;
+}
+
+static void
+dh_vorbis_close (GslDataHandle *dhandle)
+{
+ VorbisHandle *vhandle = (VorbisHandle*) dhandle;
+
+ ov_clear (&vhandle->ofile);
+ vhandle->pcm_pos = 0;
+ vhandle->pcm_length = 0;
+}
+
+static void
+dh_vorbis_destroy (GslDataHandle *data_handle)
+{
+ VorbisHandle *vhandle = (VorbisHandle*) data_handle;
+
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (VorbisHandle, vhandle);
+}
+
+static GslDataHandleFuncs dh_vorbis_vtable = {
+ dh_vorbis_open,
+ dh_vorbis_read,
+ dh_vorbis_close,
+ dh_vorbis_destroy,
+ dh_vorbis_coarse_seek,
+};
+
+GslDataHandle*
+gsl_data_handle_new_ogg_vorbis (const gchar *file_name,
+ guint lbitstream)
+{
+ VorbisHandle *vhandle;
+ gboolean success;
+
+ g_return_val_if_fail (file_name != NULL, NULL);
+
+ vhandle = gsl_new_struct0 (VorbisHandle, 1);
+ success = gsl_data_handle_common_init (&vhandle->dhandle, file_name);
+ if (success)
+ {
+ GslErrorType error;
+
+ vhandle->dhandle.vtable = &dh_vorbis_vtable;
+ vhandle->n_streams = 0;
+ vhandle->stream = lbitstream;
+
+ /* we can only check matters upon opening
+ */
+ error = gsl_data_handle_open (&vhandle->dhandle);
+ if (!error)
+ {
+ gsl_data_handle_close (&vhandle->dhandle);
+ return &vhandle->dhandle;
+ }
+ else
+ {
+ gsl_data_handle_unref (&vhandle->dhandle);
+ return NULL;
+ }
+ }
+ else
+ {
+ gsl_delete_struct (VorbisHandle, vhandle);
+ return NULL;
+ }
+}
+#endif /* GSL_HAVE_OGGVORBIS */
+
diff --git a/flow/gsl/gsldatahandle-vorbis.h b/flow/gsl/gsldatahandle-vorbis.h
new file mode 100644
index 0000000..8887923
--- /dev/null
+++ b/flow/gsl/gsldatahandle-vorbis.h
@@ -0,0 +1,41 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_DATA_HANDLE_VORBIS_H__
+#define __GSL_DATA_HANDLE_VORBIS_H__
+
+
+#include <gsl/gslcommon.h>
+#include <gsl/gsldatahandle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* linear-read handle! needs linbuffer handle wrapper
+ */
+GslDataHandle* gsl_data_handle_new_ogg_vorbis (const gchar *file_name,
+ guint lbitstream);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_DATA_HANDLE_VORBIS_H__ */
diff --git a/flow/gsl/gsldatahandle.c b/flow/gsl/gsldatahandle.c
new file mode 100644
index 0000000..c746ec7
--- /dev/null
+++ b/flow/gsl/gsldatahandle.c
@@ -0,0 +1,1241 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsldatahandle.h"
+
+#include "gslcommon.h"
+#include "gsldatacache.h"
+#include "gslfilehash.h"
+
+#include <string.h>
+#include <errno.h>
+
+
+/* --- typedefs --- */
+typedef struct {
+ GslDataHandle dhandle;
+ guint n_channels;
+ guint bit_depth;
+ GslLong n_values;
+ const gfloat *values;
+ void (*free_values) (gpointer);
+} MemHandle;
+typedef struct {
+ GslDataHandle dhandle;
+ GslDataHandle *src_handle;
+} ChainHandle;
+typedef ChainHandle ReversedHandle;
+typedef struct {
+ GslDataHandle dhandle;
+ GslDataHandle *src_handle; /* mirror ChainHandle */
+ GslLong cut_offset;
+ GslLong n_cut_values;
+ GslLong tail_cut;
+} CutHandle;
+typedef struct {
+ GslDataHandle dhandle;
+ GslDataHandle *src_handle; /* mirror ChainHandle */
+ GslLong requested_paste_offset;
+ GslLong paste_offset;
+ GslLong n_paste_values;
+ guint paste_bit_depth;
+ const gfloat *paste_values;
+ void (*free_values) (gpointer);
+} InsertHandle;
+typedef struct {
+ GslDataHandle dhandle;
+ GslDataHandle *src_handle; /* mirror ChainHandle */
+ GslLong requested_first;
+ GslLong requested_last;
+ GslLong loop_start;
+ GslLong loop_width;
+} LoopHandle;
+typedef struct {
+ GslDataHandle dhandle;
+ GslDataCache *dcache;
+ guint node_size;
+} DCacheHandle;
+typedef struct {
+ GslDataHandle dhandle;
+ guint n_channels;
+ GslWaveFormatType format;
+ guint byte_order;
+ GslLong byte_offset;
+ GslLong requested_length;
+ GslHFile *hfile;
+} WaveHandle;
+
+
+/* --- standard functions --- */
+gboolean
+gsl_data_handle_common_init (GslDataHandle *dhandle,
+ const gchar *file_name)
+{
+ g_return_val_if_fail (dhandle != NULL, FALSE);
+ g_return_val_if_fail (dhandle->vtable == NULL, FALSE);
+ g_return_val_if_fail (dhandle->name == NULL, FALSE);
+ g_return_val_if_fail (dhandle->ref_count == 0, FALSE);
+
+ dhandle->name = g_strdup (file_name);
+ gsl_mutex_init (&dhandle->mutex);
+ dhandle->ref_count = 1;
+ dhandle->open_count = 0;
+ memset (&dhandle->setup, 0, sizeof (dhandle->setup));
+
+ return TRUE;
+}
+
+GslDataHandle*
+gsl_data_handle_ref (GslDataHandle *dhandle)
+{
+ g_return_val_if_fail (dhandle != NULL, NULL);
+ g_return_val_if_fail (dhandle->ref_count > 0, NULL);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ dhandle->ref_count++;
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+
+ return dhandle;
+}
+
+void
+gsl_data_handle_common_free (GslDataHandle *dhandle)
+{
+ g_return_if_fail (dhandle != NULL);
+ g_return_if_fail (dhandle->vtable != NULL);
+ g_return_if_fail (dhandle->ref_count == 0);
+
+ g_free (dhandle->name);
+ dhandle->name = NULL;
+ gsl_mutex_destroy (&dhandle->mutex);
+}
+
+void
+gsl_data_handle_unref (GslDataHandle *dhandle)
+{
+ gboolean destroy;
+
+ g_return_if_fail (dhandle != NULL);
+ g_return_if_fail (dhandle->ref_count > 0);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ dhandle->ref_count--;
+ destroy = dhandle->ref_count == 0;
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+ if (destroy)
+ {
+ g_return_if_fail (dhandle->open_count == 0);
+ dhandle->vtable->destroy (dhandle);
+ }
+}
+
+GslErrorType
+gsl_data_handle_open (GslDataHandle *dhandle)
+{
+ g_return_val_if_fail (dhandle != NULL, GSL_ERROR_INTERNAL);
+ g_return_val_if_fail (dhandle->ref_count > 0, GSL_ERROR_INTERNAL);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ if (dhandle->open_count == 0)
+ {
+ GslErrorType error;
+
+ memset (&dhandle->setup, 0, sizeof (dhandle->setup));
+ error = dhandle->vtable->open (dhandle, &dhandle->setup);
+ if (!error && (dhandle->setup.n_values < 0 ||
+ dhandle->setup.n_channels < 1 ||
+ dhandle->setup.bit_depth < 1))
+ {
+ g_warning ("internal error in data handle open() (%p): nv=%ld nc=%u bd=%u",
+ dhandle->vtable->open, dhandle->setup.n_values, dhandle->setup.n_channels, dhandle->setup.bit_depth);
+ dhandle->vtable->close (dhandle);
+ error = GSL_ERROR_INTERNAL;
+ }
+ if (error)
+ {
+ memset (&dhandle->setup, 0, sizeof (dhandle->setup));
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+ return error;
+ }
+ dhandle->ref_count++;
+ dhandle->open_count++;
+ }
+ else
+ dhandle->open_count++;
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+
+ return GSL_ERROR_NONE;
+}
+
+void
+gsl_data_handle_close (GslDataHandle *dhandle)
+{
+ gboolean need_unref;
+
+ g_return_if_fail (dhandle != NULL);
+ g_return_if_fail (dhandle->ref_count > 0);
+ g_return_if_fail (dhandle->open_count > 0);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ dhandle->open_count--;
+ need_unref = !dhandle->open_count;
+ if (!dhandle->open_count)
+ dhandle->vtable->close (dhandle);
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+ if (need_unref)
+ gsl_data_handle_unref (dhandle);
+}
+
+GslLong
+gsl_data_handle_read (GslDataHandle *dhandle,
+ GslLong value_offset,
+ GslLong n_values,
+ gfloat *values)
+{
+ GslLong l;
+
+ g_return_val_if_fail (dhandle != NULL, -1);
+ g_return_val_if_fail (dhandle->open_count > 0, -1);
+ g_return_val_if_fail (value_offset >= 0, -1);
+ if (n_values < 1)
+ return 0;
+ g_return_val_if_fail (values != NULL, -1);
+ g_return_val_if_fail (value_offset < dhandle->setup.n_values, -1);
+
+ n_values = MIN (n_values, dhandle->setup.n_values - value_offset);
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ l = dhandle->vtable->read (dhandle, value_offset, n_values, values);
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+
+ return l;
+}
+
+GslLong
+gsl_data_handle_length (GslDataHandle *dhandle)
+{
+ GslLong l;
+
+ g_return_val_if_fail (dhandle != NULL, 0);
+ g_return_val_if_fail (dhandle->open_count > 0, 0);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ l = dhandle->open_count ? dhandle->setup.n_values : 0;
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+
+ return l;
+}
+
+guint
+gsl_data_handle_n_channels (GslDataHandle *dhandle)
+{
+ guint n;
+
+ g_return_val_if_fail (dhandle != NULL, 0);
+ g_return_val_if_fail (dhandle->open_count > 0, 0);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ n = dhandle->open_count ? dhandle->setup.n_channels : 0;
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+
+ return n;
+}
+
+guint
+gsl_data_handle_bit_depth (GslDataHandle *dhandle)
+{
+ guint n;
+
+ g_return_val_if_fail (dhandle != NULL, 0);
+ g_return_val_if_fail (dhandle->open_count > 0, 0);
+
+ GSL_SPIN_LOCK (&dhandle->mutex);
+ n = dhandle->open_count ? dhandle->setup.bit_depth : 0;
+ GSL_SPIN_UNLOCK (&dhandle->mutex);
+
+ return n;
+}
+
+const gchar*
+gsl_data_handle_name (GslDataHandle *dhandle)
+{
+ g_return_val_if_fail (dhandle != NULL, NULL);
+
+ return dhandle->name;
+}
+
+
+/* --- const memory handle --- */
+static GslErrorType
+mem_handle_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ MemHandle *mhandle = (MemHandle*) dhandle;
+
+ setup->n_values = mhandle->n_values;
+ setup->n_channels = mhandle->n_channels;
+ setup->bit_depth = mhandle->bit_depth;
+
+ return GSL_ERROR_NONE;
+}
+
+static void
+mem_handle_close (GslDataHandle *dhandle)
+{
+ /* MemHandle *mhandle = (MemHandle*) dhandle; */
+}
+
+static void
+mem_handle_destroy (GslDataHandle *dhandle)
+{
+ MemHandle *mhandle = (MemHandle*) dhandle;
+ void (*free_values) (gpointer) = mhandle->free_values;
+ const gfloat *mem_values = mhandle->values;
+
+ gsl_data_handle_common_free (dhandle);
+ mhandle->values = NULL;
+ mhandle->free_values = NULL;
+ gsl_delete_struct (MemHandle, mhandle);
+
+ if (free_values)
+ free_values ((gpointer) mem_values);
+}
+
+static GslLong
+mem_handle_read (GslDataHandle *dhandle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ MemHandle *mhandle = (MemHandle*) dhandle;
+
+ g_return_val_if_fail (voffset + n_values <= mhandle->n_values, -1);
+
+ memcpy (values, mhandle->values + voffset, n_values * sizeof (values[0]));
+
+ return n_values;
+}
+
+GslDataHandle*
+gsl_data_handle_new_mem (guint n_channels,
+ guint bit_depth,
+ GslLong n_values,
+ const gfloat *values,
+ void (*free) (gpointer values))
+{
+ static GslDataHandleFuncs mem_handle_vtable = {
+ mem_handle_open,
+ mem_handle_read,
+ mem_handle_close,
+ mem_handle_destroy,
+ };
+ MemHandle *mhandle;
+ gboolean success;
+
+ g_return_val_if_fail (n_channels > 0, NULL);
+ g_return_val_if_fail (bit_depth > 0, NULL);
+ g_return_val_if_fail (n_values >= n_channels, NULL);
+ if (n_values)
+ g_return_val_if_fail (values != NULL, NULL);
+
+ mhandle = gsl_new_struct0 (MemHandle, 1);
+ success = gsl_data_handle_common_init (&mhandle->dhandle, NULL);
+ if (success)
+ {
+ mhandle->dhandle.name = g_strconcat ("// #memory /", NULL);
+ mhandle->dhandle.vtable = &mem_handle_vtable;
+ mhandle->n_channels = n_channels;
+ mhandle->bit_depth = bit_depth;
+ mhandle->n_values = n_values / mhandle->n_channels;
+ mhandle->n_values *= mhandle->n_channels;
+ mhandle->values = values;
+ mhandle->free_values = free;
+ }
+ else
+ {
+ gsl_delete_struct (MemHandle, mhandle);
+ return NULL;
+ }
+ return &mhandle->dhandle;
+}
+
+
+/* --- chain handle --- */
+static GslErrorType
+chain_handle_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ ChainHandle *chandle = (ChainHandle*) dhandle;
+ GslErrorType error;
+
+ error = gsl_data_handle_open (chandle->src_handle);
+ if (error != GSL_ERROR_NONE)
+ return error;
+ *setup = chandle->src_handle->setup;
+
+ return GSL_ERROR_NONE;
+}
+
+static void
+chain_handle_close (GslDataHandle *dhandle)
+{
+ ChainHandle *chandle = (ChainHandle*) dhandle;
+
+ gsl_data_handle_close (chandle->src_handle);
+}
+
+
+/* --- reversed handle --- */
+static void
+reverse_handle_destroy (GslDataHandle *data_handle)
+{
+ ReversedHandle *rhandle = (ReversedHandle*) data_handle;
+
+ gsl_data_handle_unref (rhandle->src_handle);
+
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (ReversedHandle, rhandle);
+}
+
+static GslLong
+reverse_handle_read (GslDataHandle *dhandle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ ReversedHandle *rhandle = (ReversedHandle*) dhandle;
+ GslLong left, new_offset = dhandle->setup.n_values - (voffset + n_values);
+ gfloat *t, *p = values;
+
+ g_assert (new_offset >= 0);
+
+ left = n_values;
+ do
+ {
+ GslLong l = gsl_data_handle_read (rhandle->src_handle, new_offset, left, p);
+
+ if (l < 0)
+ return l; /* pass on errors */
+
+ new_offset += l;
+ left -= l;
+ p += l;
+ }
+ while (left > 0);
+
+ p = values;
+ t = values + n_values - 1;
+ while (p < t)
+ {
+ gfloat v = *t;
+
+ *t-- = *p;
+ *p++ = v;
+ }
+ return n_values;
+}
+
+GslDataHandle*
+gsl_data_handle_new_reverse (GslDataHandle *src_handle)
+{
+ static GslDataHandleFuncs reverse_handle_vtable = {
+ chain_handle_open,
+ reverse_handle_read,
+ chain_handle_close,
+ reverse_handle_destroy,
+ };
+ ReversedHandle *rhandle;
+ gboolean success;
+
+ g_return_val_if_fail (src_handle != NULL, NULL);
+
+ rhandle = gsl_new_struct0 (ReversedHandle, 1);
+ success = gsl_data_handle_common_init (&rhandle->dhandle, NULL);
+ if (success)
+ {
+ rhandle->dhandle.name = g_strconcat (src_handle->name, "// #reversed /", NULL);
+ rhandle->dhandle.vtable = &reverse_handle_vtable;
+ rhandle->src_handle = gsl_data_handle_ref (src_handle);
+ }
+ else
+ {
+ gsl_delete_struct (ReversedHandle, rhandle);
+ return NULL;
+ }
+ return &rhandle->dhandle;
+}
+
+
+/* --- cut handle --- */
+static GslErrorType
+cut_handle_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ CutHandle *chandle = (CutHandle*) dhandle;
+ GslErrorType error;
+
+ error = gsl_data_handle_open (chandle->src_handle);
+ if (error != GSL_ERROR_NONE)
+ return error;
+ *setup = chandle->src_handle->setup;
+ setup->n_values -= MIN (setup->n_values, chandle->tail_cut);
+ setup->n_values -= MIN (setup->n_values, chandle->n_cut_values);
+
+ return GSL_ERROR_NONE;
+}
+
+static void
+cut_handle_destroy (GslDataHandle *data_handle)
+{
+ CutHandle *chandle = (CutHandle*) data_handle;
+
+ gsl_data_handle_unref (chandle->src_handle);
+
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (CutHandle, chandle);
+}
+
+static GslLong
+cut_handle_read (GslDataHandle *dhandle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ CutHandle *chandle = (CutHandle*) dhandle;
+ GslLong orig_n_values = n_values;
+
+ if (voffset < chandle->cut_offset)
+ {
+ GslLong l = MIN (chandle->cut_offset - voffset, n_values);
+
+ l = gsl_data_handle_read (chandle->src_handle, voffset, l, values);
+ if (l < 0)
+ return l; /* pass on errors */
+ n_values -= l;
+ values += l;
+ voffset += l;
+ }
+
+ if (voffset >= chandle->cut_offset && n_values)
+ {
+ GslLong l = gsl_data_handle_read (chandle->src_handle, voffset + chandle->n_cut_values, n_values, values);
+
+ if (l < 0 && orig_n_values == n_values)
+ return l; /* pass on errors */
+ else if (l < 0)
+ l = 0;
+
+ n_values -= l;
+ }
+
+ return orig_n_values - n_values;
+}
+
+static GslDataHandle*
+gsl_data_handle_new_translate (GslDataHandle *src_handle,
+ GslLong cut_offset,
+ GslLong n_cut_values,
+ GslLong tail_cut)
+{
+ static GslDataHandleFuncs cut_handle_vtable = {
+ cut_handle_open,
+ cut_handle_read,
+ chain_handle_close,
+ cut_handle_destroy,
+ };
+ CutHandle *chandle;
+ gboolean success;
+
+ g_return_val_if_fail (src_handle != NULL, NULL);
+ g_return_val_if_fail (cut_offset >= 0 && n_cut_values >= 0 && tail_cut >= 0, NULL);
+
+ chandle = gsl_new_struct0 (CutHandle, 1);
+ success = gsl_data_handle_common_init (&chandle->dhandle, NULL);
+ if (success)
+ {
+ chandle->dhandle.name = g_strconcat (src_handle->name, "// #translate /", NULL);
+ chandle->dhandle.vtable = &cut_handle_vtable;
+ chandle->src_handle = gsl_data_handle_ref (src_handle);
+ chandle->cut_offset = n_cut_values ? cut_offset : 0;
+ chandle->n_cut_values = n_cut_values;
+ chandle->tail_cut = tail_cut;
+ }
+ else
+ {
+ gsl_delete_struct (CutHandle, chandle);
+ return NULL;
+ }
+ return &chandle->dhandle;
+}
+
+/**
+ * gsl_data_handle_new_cut
+ * @src_handle: source GslDataHandle
+ * @cut_offset: offset of gap into @src_handle
+ * @n_cut_values: length of gap in @src_handle
+ * @RETURNS: a newly created data handle
+ *
+ * Create a new data handle containing the contents of @src_handle
+ * minus @n_cut_values at offset @cut_offset.
+ */
+GslDataHandle*
+gsl_data_handle_new_cut (GslDataHandle *src_handle,
+ GslLong cut_offset,
+ GslLong n_cut_values)
+{
+ return gsl_data_handle_new_translate (src_handle, cut_offset, n_cut_values, 0);
+}
+
+/**
+ * gsl_data_handle_new_crop
+ * @src_handle: source GslDataHandle
+ * @n_head_cut: number of values to cut at data handle head
+ * @n_tail_cut: number of values to cut at data handle tail
+ * @RETURNS: a newly created data handle
+ *
+ * Create a new data handle containing the contents of @src_handle
+ * minus @n_head_cut values at the start and @n_tail_cut values at
+ * the end.
+ */
+GslDataHandle*
+gsl_data_handle_new_crop (GslDataHandle *src_handle,
+ GslLong n_head_cut,
+ GslLong n_tail_cut)
+{
+ return gsl_data_handle_new_translate (src_handle, 0, n_head_cut, n_tail_cut);
+}
+
+
+/* --- insert handle --- */
+static GslErrorType
+insert_handle_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ InsertHandle *ihandle = (InsertHandle*) dhandle;
+ GslErrorType error;
+
+ error = gsl_data_handle_open (ihandle->src_handle);
+ if (error != GSL_ERROR_NONE)
+ return error;
+ *setup = ihandle->src_handle->setup;
+ ihandle->paste_offset = ihandle->requested_paste_offset < 0 ? setup->n_values : ihandle->requested_paste_offset;
+ if (setup->n_values < ihandle->paste_offset)
+ setup->n_values = ihandle->paste_offset + ihandle->n_paste_values;
+ else
+ setup->n_values += ihandle->n_paste_values;
+ setup->bit_depth = MAX (setup->bit_depth, ihandle->paste_bit_depth);
+
+ return GSL_ERROR_NONE;
+}
+
+static void
+insert_handle_destroy (GslDataHandle *data_handle)
+{
+ InsertHandle *ihandle = (InsertHandle*) data_handle;
+ void (*free_values) (gpointer) = ihandle->free_values;
+ const gfloat *paste_values = ihandle->paste_values;
+
+ gsl_data_handle_unref (ihandle->src_handle);
+
+ gsl_data_handle_common_free (data_handle);
+ ihandle->paste_values = NULL;
+ ihandle->free_values = NULL;
+ gsl_delete_struct (InsertHandle, ihandle);
+
+ if (free_values)
+ free_values ((gpointer) paste_values);
+}
+
+static GslLong
+insert_handle_read (GslDataHandle *data_handle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ InsertHandle *ihandle = (InsertHandle*) data_handle;
+ GslLong l, orig_n_values = n_values;
+
+ if (voffset < ihandle->src_handle->setup.n_values &&
+ voffset < ihandle->paste_offset)
+ {
+ l = MIN (n_values, MIN (ihandle->paste_offset, ihandle->src_handle->setup.n_values) - voffset);
+ l = gsl_data_handle_read (ihandle->src_handle, voffset, l, values);
+ if (l < 0)
+ return l; /* pass on errors */
+
+ voffset += l;
+ n_values -= l;
+ values += l;
+ }
+
+ if (n_values && voffset >= ihandle->src_handle->setup.n_values && voffset < ihandle->paste_offset)
+ {
+ l = MIN (n_values, ihandle->paste_offset - voffset);
+ memset (values, 0, l * sizeof (values[0]));
+ voffset += l;
+ n_values -= l;
+ values += l;
+ }
+
+ if (n_values && voffset >= ihandle->paste_offset && voffset < ihandle->paste_offset + ihandle->n_paste_values)
+ {
+ l = MIN (n_values, ihandle->paste_offset + ihandle->n_paste_values - voffset);
+ memcpy (values, ihandle->paste_values + voffset - ihandle->paste_offset, l * sizeof (values[0]));
+ voffset += l;
+ n_values -= l;
+ values += l;
+ }
+
+ if (n_values && voffset >= ihandle->paste_offset + ihandle->n_paste_values)
+ {
+ l = gsl_data_handle_read (ihandle->src_handle, voffset - ihandle->n_paste_values, n_values, values);
+ if (l < 0 && orig_n_values == n_values)
+ return l; /* pass on errors */
+ else if (l < 0)
+ l = 0;
+ n_values -= l;
+ }
+
+ return orig_n_values - n_values;
+}
+
+GslDataHandle*
+gsl_data_handle_new_insert (GslDataHandle *src_handle,
+ guint paste_bit_depth,
+ GslLong insertion_offset,
+ GslLong n_paste_values,
+ const gfloat *paste_values,
+ void (*free) (gpointer values))
+{
+ static GslDataHandleFuncs insert_handle_vtable = {
+ insert_handle_open,
+ insert_handle_read,
+ chain_handle_close,
+ insert_handle_destroy,
+ };
+ InsertHandle *ihandle;
+ gboolean success;
+
+ g_return_val_if_fail (src_handle != NULL, NULL);
+ g_return_val_if_fail (n_paste_values >= 0, NULL);
+ if (n_paste_values)
+ g_return_val_if_fail (paste_values != NULL, NULL);
+
+ ihandle = gsl_new_struct0 (InsertHandle, 1);
+ success = gsl_data_handle_common_init (&ihandle->dhandle, NULL);
+ if (success)
+ {
+ ihandle->dhandle.name = g_strconcat (src_handle ? src_handle->name : "", "// #insert /", NULL);
+ ihandle->dhandle.vtable = &insert_handle_vtable;
+ ihandle->src_handle = gsl_data_handle_ref (src_handle);
+ ihandle->requested_paste_offset = insertion_offset;
+ ihandle->paste_offset = 0;
+ ihandle->n_paste_values = n_paste_values;
+ ihandle->paste_bit_depth = paste_bit_depth;
+ ihandle->paste_values = paste_values;
+ ihandle->free_values = free;
+ }
+ else
+ {
+ gsl_delete_struct (InsertHandle, ihandle);
+ return NULL;
+ }
+ return &ihandle->dhandle;
+}
+
+
+/* --- loop handle --- */
+static GslErrorType
+loop_handle_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ LoopHandle *lhandle = (LoopHandle*) dhandle;
+ GslErrorType error;
+
+ error = gsl_data_handle_open (lhandle->src_handle);
+ if (error != GSL_ERROR_NONE)
+ return error;
+
+ *setup = lhandle->src_handle->setup;
+ if (setup->n_values > lhandle->requested_last)
+ {
+ lhandle->loop_start = lhandle->requested_first;
+ lhandle->loop_width = lhandle->requested_last - lhandle->requested_first + 1;
+ setup->n_values = GSL_MAXLONG;
+ }
+ else /* cannot loop */
+ {
+ lhandle->loop_start = setup->n_values;
+ lhandle->loop_width = 0;
+ }
+
+ return GSL_ERROR_NONE;
+}
+
+static void
+loop_handle_destroy (GslDataHandle *data_handle)
+{
+ LoopHandle *lhandle = (LoopHandle*) data_handle;
+
+ gsl_data_handle_unref (lhandle->src_handle);
+
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (LoopHandle, lhandle);
+}
+
+static GslLong
+loop_handle_read (GslDataHandle *data_handle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ LoopHandle *lhandle = (LoopHandle*) data_handle;
+
+ if (voffset < lhandle->loop_start)
+ return gsl_data_handle_read (lhandle->src_handle, voffset,
+ MIN (lhandle->loop_start - voffset, n_values),
+ values);
+ else
+ {
+ GslLong noffset = voffset - lhandle->loop_start;
+
+ noffset %= lhandle->loop_width;
+
+ return gsl_data_handle_read (lhandle->src_handle,
+ lhandle->loop_start + noffset,
+ MIN (lhandle->loop_width - noffset, n_values),
+ values);
+ }
+}
+
+GslDataHandle*
+gsl_data_handle_new_looped (GslDataHandle *src_handle,
+ GslLong loop_first,
+ GslLong loop_last)
+{
+ static GslDataHandleFuncs loop_handle_vtable = {
+ loop_handle_open,
+ loop_handle_read,
+ chain_handle_close,
+ loop_handle_destroy,
+ };
+ LoopHandle *lhandle;
+ gboolean success;
+
+ g_return_val_if_fail (src_handle != NULL, NULL);
+ g_return_val_if_fail (loop_first >= 0, NULL);
+ g_return_val_if_fail (loop_last >= loop_first, NULL);
+
+ lhandle = gsl_new_struct0 (LoopHandle, 1);
+ success = gsl_data_handle_common_init (&lhandle->dhandle, NULL);
+ if (success)
+ {
+ lhandle->dhandle.name = g_strdup_printf ("%s// #loop(0x%lx:0x%lx) /", src_handle->name, loop_first, loop_last);
+ lhandle->dhandle.vtable = &loop_handle_vtable;
+ lhandle->src_handle = gsl_data_handle_ref (src_handle);
+ lhandle->requested_first = loop_first;
+ lhandle->requested_last = loop_last;
+ lhandle->loop_start = 0;
+ lhandle->loop_width = 0;
+ }
+ else
+ {
+ gsl_delete_struct (LoopHandle, lhandle);
+ return NULL;
+ }
+ return &lhandle->dhandle;
+}
+
+
+/* --- dcache handle --- */
+static void
+dcache_handle_destroy (GslDataHandle *data_handle)
+{
+ DCacheHandle *dhandle = (DCacheHandle*) data_handle;
+
+ gsl_data_cache_unref (dhandle->dcache);
+
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (DCacheHandle, dhandle);
+}
+
+static GslErrorType
+dcache_handle_open (GslDataHandle *dhandle,
+ GslDataHandleSetup *setup)
+{
+ DCacheHandle *chandle = (DCacheHandle*) dhandle;
+ GslErrorType error;
+
+ error = gsl_data_handle_open (chandle->dcache->dhandle);
+ if (error != GSL_ERROR_NONE)
+ return error;
+ gsl_data_cache_open (chandle->dcache);
+ *setup = chandle->dcache->dhandle->setup;
+ gsl_data_handle_close (chandle->dcache->dhandle);
+
+ return GSL_ERROR_NONE;
+}
+
+static void
+dcache_handle_close (GslDataHandle *data_handle)
+{
+ DCacheHandle *dhandle = (DCacheHandle*) data_handle;
+
+ gsl_data_cache_close (dhandle->dcache);
+}
+
+static GslLong
+dcache_handle_read (GslDataHandle *data_handle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ DCacheHandle *dhandle = (DCacheHandle*) data_handle;
+ GslDataCacheNode *node;
+
+ node = gsl_data_cache_ref_node (dhandle->dcache, voffset, TRUE);
+ voffset -= node->offset;
+ n_values = MIN (n_values, dhandle->node_size - voffset);
+ memcpy (values, node->data + voffset, sizeof (values[0]) * n_values);
+
+ return n_values;
+}
+
+GslDataHandle*
+gsl_data_handle_new_dcached (GslDataCache *dcache)
+{
+ static GslDataHandleFuncs dcache_handle_vtable = {
+ dcache_handle_open,
+ dcache_handle_read,
+ dcache_handle_close,
+ dcache_handle_destroy,
+ };
+ DCacheHandle *dhandle;
+ gboolean success;
+
+ g_return_val_if_fail (dcache != NULL, NULL);
+
+ dhandle = gsl_new_struct0 (DCacheHandle, 1);
+ success = gsl_data_handle_common_init (&dhandle->dhandle, NULL);
+ if (success)
+ {
+ dhandle->dhandle.name = g_strdup_printf ("%s// #dcache /", dcache->dhandle->name);
+ dhandle->dhandle.vtable = &dcache_handle_vtable;
+ dhandle->dcache = gsl_data_cache_ref (dcache);
+ dhandle->node_size = GSL_DATA_CACHE_NODE_SIZE (dcache) + dcache->padding;
+ }
+ else
+ {
+ gsl_delete_struct (DCacheHandle, dhandle);
+ return NULL;
+ }
+ return &dhandle->dhandle;
+}
+
+
+/* --- wave handle --- */
+static inline const guint G_GNUC_CONST
+wave_format_bit_depth (const GslWaveFormatType format)
+{
+ switch (format)
+ {
+ case GSL_WAVE_FORMAT_UNSIGNED_8:
+ case GSL_WAVE_FORMAT_SIGNED_8:
+ return 8;
+ case GSL_WAVE_FORMAT_UNSIGNED_12:
+ case GSL_WAVE_FORMAT_SIGNED_12:
+ return 12;
+ case GSL_WAVE_FORMAT_UNSIGNED_16:
+ case GSL_WAVE_FORMAT_SIGNED_16:
+ return 16;
+ case GSL_WAVE_FORMAT_FLOAT:
+ return 32;
+ default:
+ return 0;
+ }
+}
+#define wave_format_byte_width(f) ((wave_format_bit_depth (f) + 7) / 8)
+
+static void
+wave_handle_destroy (GslDataHandle *data_handle)
+{
+ WaveHandle *whandle = (WaveHandle*) data_handle;
+
+ gsl_data_handle_common_free (data_handle);
+ gsl_delete_struct (WaveHandle, whandle);
+}
+
+static GslErrorType
+wave_handle_open (GslDataHandle *data_handle,
+ GslDataHandleSetup *setup)
+{
+ WaveHandle *whandle = (WaveHandle*) data_handle;
+
+ whandle->hfile = gsl_hfile_open (whandle->dhandle.name);
+ if (!whandle->hfile)
+ return gsl_error_from_errno (errno, GSL_ERROR_OPEN_FAILED);
+ else
+ {
+ GslLong l, fwidth = wave_format_byte_width (whandle->format);
+ /* convert size into n_values, i.e. float length */
+ l = whandle->hfile->n_bytes;
+ l -= MIN (l, whandle->byte_offset);
+ if (l >= fwidth)
+ {
+ l /= fwidth;
+ if (whandle->requested_length < 0)
+ setup->n_values = l;
+ else
+ setup->n_values = MIN (l, whandle->requested_length);
+ }
+ else
+ setup->n_values = 0;
+ setup->n_channels = whandle->n_channels;
+ setup->bit_depth = wave_format_bit_depth (whandle->format);
+ return GSL_ERROR_NONE;
+ }
+}
+
+static void
+wave_handle_close (GslDataHandle *dhandle)
+{
+ WaveHandle *whandle = (WaveHandle*) dhandle;
+
+ gsl_hfile_close (whandle->hfile);
+ whandle->hfile = NULL;
+}
+
+static GslLong
+wave_handle_read (GslDataHandle *data_handle,
+ GslLong voffset,
+ GslLong n_values,
+ gfloat *values)
+{
+ WaveHandle *whandle = (WaveHandle*) data_handle;
+ gpointer buffer = values;
+ GslLong l, i, byte_offset;
+
+ byte_offset = voffset * wave_format_byte_width (whandle->format); /* float offset into bytes */
+ byte_offset += whandle->byte_offset;
+
+ switch (whandle->format)
+ {
+ guint8 *u8; gint8 *s8; guint16 *u16; guint32 *u32;
+ case GSL_WAVE_FORMAT_UNSIGNED_8:
+ u8 = buffer; u8 += n_values * 3;
+ l = gsl_hfile_pread (whandle->hfile, byte_offset, n_values, u8);
+ if (l < 1)
+ return l;
+ for (i = 0; i < l; i++)
+ {
+ int v = u8[i] - 128;
+ values[i] = v * (1. / 128.);
+ }
+ break;
+ case GSL_WAVE_FORMAT_SIGNED_8:
+ s8 = buffer; s8 += n_values * 3;
+ l = gsl_hfile_pread (whandle->hfile, byte_offset, n_values, s8);
+ if (l < 1)
+ return l;
+ for (i = 0; i < l; i++)
+ values[i] = s8[i] * (1. / 128.);
+ break;
+ case GSL_WAVE_FORMAT_SIGNED_12:
+ case GSL_WAVE_FORMAT_UNSIGNED_12:
+ case GSL_WAVE_FORMAT_SIGNED_16:
+ case GSL_WAVE_FORMAT_UNSIGNED_16:
+ u16 = buffer; u16 += n_values;
+ l = gsl_hfile_pread (whandle->hfile, byte_offset, n_values << 1, u16);
+ if (l < 2)
+ return l < 0 ? l : 0;
+ l >>= 1;
+ switch (whandle->format)
+ {
+ case GSL_WAVE_FORMAT_UNSIGNED_16:
+ if (whandle->byte_order != G_BYTE_ORDER)
+ for (i = 0; i < l; i++)
+ {
+ int v = GUINT16_SWAP_LE_BE (u16[i]); v -= 32768;
+ values[i] = v * (1. / 32768.);
+ }
+ else /* whandle->byte_order == G_BYTE_ORDER */
+ for (i = 0; i < l; i++)
+ {
+ int v = u16[i]; v -= 32768;
+ values[i] = v * (1. / 32768.);
+ }
+ break;
+ case GSL_WAVE_FORMAT_UNSIGNED_12:
+ if (whandle->byte_order != G_BYTE_ORDER)
+ for (i = 0; i < l; i++)
+ {
+ int v = GUINT16_SWAP_LE_BE (u16[i]); v &= 0x0fff; v -= 4096;
+ values[i] = v * (1. / 4096.);
+ }
+ else /* whandle->byte_order == G_BYTE_ORDER */
+ for (i = 0; i < l; i++)
+ {
+ int v = u16[i]; v &= 0x0fff; v -= 4096;
+ values[i] = v * (1. / 4096.);
+ }
+ break;
+ case GSL_WAVE_FORMAT_SIGNED_16:
+ if (whandle->byte_order != G_BYTE_ORDER)
+ for (i = 0; i < l; i++)
+ {
+ gint16 v = GUINT16_SWAP_LE_BE (u16[i]);
+ values[i] = v * (1. / 32768.);
+ }
+ else /* whandle->byte_order == G_BYTE_ORDER */
+ for (i = 0; i < l; i++)
+ {
+ gint16 v = u16[i];
+ values[i] = v * (1. / 32768.);
+ }
+ break;
+ case GSL_WAVE_FORMAT_SIGNED_12:
+ if (whandle->byte_order != G_BYTE_ORDER)
+ for (i = 0; i < l; i++)
+ {
+ gint16 v = GUINT16_SWAP_LE_BE (u16[i]);
+ values[i] = CLAMP (v, -4096, 4096) * (1. / 4096.);
+ }
+ else /* whandle->byte_order == G_BYTE_ORDER */
+ for (i = 0; i < l; i++)
+ {
+ gint16 v = u16[i];
+ values[i] = CLAMP (v, -4096, 4096) * (1. / 4096.);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ break;
+ case GSL_WAVE_FORMAT_FLOAT:
+ u32 = buffer;
+ l = gsl_hfile_pread (whandle->hfile, byte_offset, n_values << 2, u32);
+ if (l < 4)
+ return l < 0 ? l : 0;
+ l >>= 2;
+ if (whandle->byte_order != G_BYTE_ORDER)
+ for (i = 0; i < l; i++)
+ u32[i] = GUINT32_SWAP_LE_BE (u32[i]);
+ break;
+ default:
+ l = -1;
+ g_assert_not_reached ();
+ }
+
+ return l;
+}
+
+GslDataHandle*
+gsl_wave_handle_new (const gchar *file_name,
+ guint n_channels,
+ GslWaveFormatType format,
+ guint byte_order,
+ GslLong byte_offset,
+ GslLong n_values)
+{
+ static GslDataHandleFuncs wave_handle_vtable = {
+ wave_handle_open,
+ wave_handle_read,
+ wave_handle_close,
+ wave_handle_destroy,
+ };
+ WaveHandle *whandle;
+
+ g_return_val_if_fail (file_name != NULL, NULL);
+ g_return_val_if_fail (format > GSL_WAVE_FORMAT_NONE && format < GSL_WAVE_FORMAT_LAST, NULL);
+ g_return_val_if_fail (byte_order == G_LITTLE_ENDIAN || byte_order == G_BIG_ENDIAN, NULL);
+ g_return_val_if_fail (byte_offset >= 0, NULL);
+ g_return_val_if_fail (n_channels >= 1, NULL);
+ g_return_val_if_fail (n_values >= 1 || n_values == -1, NULL);
+
+ whandle = gsl_new_struct0 (WaveHandle, 1);
+ if (gsl_data_handle_common_init (&whandle->dhandle, file_name))
+ {
+ whandle->dhandle.vtable = &wave_handle_vtable;
+ whandle->n_channels = n_channels;
+ whandle->format = format;
+ whandle->byte_order = byte_order;
+ whandle->byte_offset = byte_offset;
+ whandle->requested_length = n_values;
+ whandle->hfile = NULL;
+ return &whandle->dhandle;
+ }
+ else
+ {
+ gsl_delete_struct (WaveHandle, whandle);
+ return NULL;
+ }
+}
+
+const gchar*
+gsl_wave_format_to_string (GslWaveFormatType format)
+{
+ switch (format)
+ {
+ case GSL_WAVE_FORMAT_UNSIGNED_8: return "unsigned_8";
+ case GSL_WAVE_FORMAT_SIGNED_8: return "signed_8";
+ case GSL_WAVE_FORMAT_UNSIGNED_12: return "unsigned_12";
+ case GSL_WAVE_FORMAT_SIGNED_12: return "signed_12";
+ case GSL_WAVE_FORMAT_UNSIGNED_16: return "unsigned_16";
+ case GSL_WAVE_FORMAT_SIGNED_16: return "signed_16";
+ case GSL_WAVE_FORMAT_FLOAT: return "float";
+ case GSL_WAVE_FORMAT_NONE:
+ case GSL_WAVE_FORMAT_LAST:
+ default:
+ g_return_val_if_fail (format >= GSL_WAVE_FORMAT_UNSIGNED_8 && format <= GSL_WAVE_FORMAT_FLOAT, NULL);
+ return NULL;
+ }
+}
+
+GslWaveFormatType
+gsl_wave_format_from_string (const gchar *string)
+{
+ gboolean is_unsigned = FALSE;
+
+ g_return_val_if_fail (string != NULL, GSL_WAVE_FORMAT_NONE);
+
+ while (*string == ' ')
+ string++;
+ if (strncasecmp (string, "float", 5) == 0)
+ return GSL_WAVE_FORMAT_FLOAT;
+ if ((string[0] == 'u' || string[0] == 'U') &&
+ (string[1] == 'n' || string[1] == 'N'))
+ {
+ is_unsigned = TRUE;
+ string += 2;
+ }
+ if (strncasecmp (string, "signed", 6) != 0)
+ return GSL_WAVE_FORMAT_NONE;
+ string += 6;
+ if (string[0] != '-' && string[0] != '_')
+ return GSL_WAVE_FORMAT_NONE;
+ string += 1;
+ if (string[0] == '8')
+ return is_unsigned ? GSL_WAVE_FORMAT_UNSIGNED_8 : GSL_WAVE_FORMAT_SIGNED_8;
+ if (string[0] != '1')
+ return GSL_WAVE_FORMAT_NONE;
+ string += 1;
+ if (string[0] == '2')
+ return is_unsigned ? GSL_WAVE_FORMAT_UNSIGNED_12 : GSL_WAVE_FORMAT_SIGNED_12;
+ if (string[0] == '6')
+ return is_unsigned ? GSL_WAVE_FORMAT_UNSIGNED_16 : GSL_WAVE_FORMAT_SIGNED_16;
+ return GSL_WAVE_FORMAT_NONE;
+}
diff --git a/flow/gsl/gsldatahandle.h b/flow/gsl/gsldatahandle.h
new file mode 100644
index 0000000..d67b44f
--- /dev/null
+++ b/flow/gsl/gsldatahandle.h
@@ -0,0 +1,143 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_DATA_HANDLE_H__
+#define __GSL_DATA_HANDLE_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gslcommon.h> /* GslErrorType */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- macros --- */
+#define GSL_DATA_HANDLE_OPENED(handle) (((GslDataHandle*) (handle))->open_count > 0)
+#define GSL_DATA_HANDLE_READ_LINEAR(handle) (((GslDataHandle*) (handle))->vtable->coarse_seek != NULL)
+
+
+/* --- typedefs & structures --- */
+typedef struct {
+ GslLong n_values;
+ guint n_channels;
+ guint bit_depth;
+} GslDataHandleSetup;
+struct _GslDataHandle
+{
+ /* constant members */
+ GslDataHandleFuncs *vtable;
+ gchar *name;
+ /* common members */
+ GslMutex mutex;
+ guint ref_count;
+ guint open_count;
+ /* opened data handle setup (open_count > 0) */
+ GslDataHandleSetup setup;
+};
+struct _GslDataHandleFuncs
+{
+ GslErrorType (*open) (GslDataHandle *data_handle,
+ GslDataHandleSetup *setup);
+ GslLong (*read) (GslDataHandle *data_handle,
+ GslLong voffset, /* in values */
+ GslLong n_values,
+ gfloat *values);
+ void (*close) (GslDataHandle *data_handle);
+ void (*destroy) (GslDataHandle *data_handle);
+ /* optional (for codecs) */
+ GslLong (*coarse_seek) (GslDataHandle *data_handle,
+ GslLong position);
+};
+
+
+
+/* --- standard functions --- */
+GslDataHandle* gsl_data_handle_ref (GslDataHandle *dhandle);
+void gsl_data_handle_unref (GslDataHandle *dhandle);
+GslErrorType gsl_data_handle_open (GslDataHandle *dhandle);
+void gsl_data_handle_close (GslDataHandle *dhandle);
+GslLong gsl_data_handle_length (GslDataHandle *data_handle);
+#define gsl_data_handle_n_values( dh) \
+ gsl_data_handle_length (dh)
+guint gsl_data_handle_n_channels (GslDataHandle *data_handle);
+guint gsl_data_handle_bit_depth (GslDataHandle *data_handle);
+const gchar* gsl_data_handle_name (GslDataHandle *data_handle);
+GslLong gsl_data_handle_read (GslDataHandle *data_handle,
+ GslLong value_offset,
+ GslLong n_values,
+ gfloat *values);
+GslDataHandle* gsl_data_handle_new_cut (GslDataHandle *src_handle,
+ GslLong cut_offset,
+ GslLong n_cut_values);
+GslDataHandle* gsl_data_handle_new_crop (GslDataHandle *src_handle,
+ GslLong n_head_cut,
+ GslLong n_tail_cut);
+GslDataHandle* gsl_data_handle_new_reverse (GslDataHandle *src_handle);
+GslDataHandle* gsl_data_handle_new_insert (GslDataHandle *src_handle,
+ guint paste_bit_depth,
+ GslLong insertion_offset,
+ GslLong n_paste_values,
+ const gfloat *paste_values,
+ void (*free) (gpointer values));
+GslDataHandle* gsl_data_handle_new_mem (guint n_channels,
+ guint bit_depth,
+ GslLong n_values,
+ const gfloat *values,
+ void (*free) (gpointer values));
+GslDataHandle* gsl_data_handle_new_dcached (GslDataCache *dcache);
+/* cheap and inefficient, testpurpose only */
+GslDataHandle* gsl_data_handle_new_looped (GslDataHandle *src_handle,
+ GslLong loop_first,
+ GslLong loop_last);
+
+
+/* --- wave specific functions --- */
+typedef enum /*< skip >*/
+{
+ GSL_WAVE_FORMAT_NONE,
+ GSL_WAVE_FORMAT_UNSIGNED_8,
+ GSL_WAVE_FORMAT_SIGNED_8,
+ GSL_WAVE_FORMAT_UNSIGNED_12,
+ GSL_WAVE_FORMAT_SIGNED_12,
+ GSL_WAVE_FORMAT_UNSIGNED_16,
+ GSL_WAVE_FORMAT_SIGNED_16,
+ GSL_WAVE_FORMAT_FLOAT,
+ GSL_WAVE_FORMAT_LAST
+} GslWaveFormatType;
+
+const gchar* gsl_wave_format_to_string (GslWaveFormatType format);
+GslWaveFormatType gsl_wave_format_from_string (const gchar *string);
+GslDataHandle* gsl_wave_handle_new (const gchar *file_name,
+ guint n_channels,
+ GslWaveFormatType format,
+ guint byte_order,
+ GslLong byte_offset,
+ GslLong n_values);
+
+
+/* --- auxillary functions --- */
+gboolean gsl_data_handle_common_init (GslDataHandle *dhandle,
+ const gchar *file_name);
+void gsl_data_handle_common_free (GslDataHandle *dhandle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_DATA_HANDLE_H__ */
diff --git a/flow/gsl/gsldatautils.c b/flow/gsl/gsldatautils.c
new file mode 100644
index 0000000..d8c52c0
--- /dev/null
+++ b/flow/gsl/gsldatautils.c
@@ -0,0 +1,462 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsldatautils.h"
+#include "gsldatacache.h"
+#include <errno.h>
+#include <unistd.h>
+
+
+#define BSIZE GSL_DATA_HANDLE_PEEK_BUFFER /* FIXME: global buffer size setting */
+
+
+/* --- functions --- */
+gfloat
+gsl_data_peek_value_f (GslDataHandle *dhandle,
+ GslLong pos,
+ GslDataPeekBuffer *peekbuf)
+{
+ if (pos < peekbuf->start || pos >= peekbuf->end)
+ {
+ GslLong dhandle_length = dhandle->setup.n_values;
+ GslLong inc, k, bsize = MIN (GSL_DATA_HANDLE_PEEK_BUFFER, dhandle_length);
+
+ g_return_val_if_fail (pos >= 0 && pos < dhandle_length, 0);
+
+ peekbuf->start = peekbuf->dir > 0 ? pos : peekbuf->dir < 0 ? pos - bsize + 1: pos - bsize / 2;
+ peekbuf->end = MIN (peekbuf->start + bsize, dhandle_length);
+ peekbuf->start = MAX (peekbuf->start, 0);
+ for (k = peekbuf->start; k < peekbuf->end; k += inc)
+ {
+ guint n_retries = 5; /* FIXME: need global retry strategy */
+
+ do
+ inc = gsl_data_handle_read (dhandle, k, peekbuf->end - k, peekbuf->data + k - peekbuf->start);
+ while (inc < 1 && n_retries-- && GSL_DATA_HANDLE_OPENED (dhandle));
+ if (inc < 1)
+ { /* pathologic */
+ peekbuf->data[k - peekbuf->start] = 0;
+ inc = 1;
+ gsl_message_send (GSL_MSG_DATA_HANDLE, "PeekBuffer",
+ GSL_ERROR_READ_FAILED, "unable to read from data handle (%p)", dhandle);
+ }
+ }
+ }
+ return peekbuf->data[pos - peekbuf->start];
+}
+
+gint /* errno */
+gsl_data_handle_dump (GslDataHandle *dhandle,
+ gint fd,
+ GslWaveFormatType format,
+ guint byte_order)
+{
+ GslLong l, offs = 0;
+
+ g_return_val_if_fail (dhandle != NULL, EINVAL);
+ g_return_val_if_fail (GSL_DATA_HANDLE_OPENED (dhandle), EINVAL);
+ g_return_val_if_fail (fd >= 0, EINVAL);
+ g_return_val_if_fail (format >= GSL_WAVE_FORMAT_UNSIGNED_8 && format <= GSL_WAVE_FORMAT_FLOAT, EINVAL);
+ g_return_val_if_fail (byte_order == G_LITTLE_ENDIAN || byte_order == G_BIG_ENDIAN, EINVAL);
+
+ l = dhandle->setup.n_values;
+ while (l)
+ {
+ GslLong retry, j, n = MIN (l, GSL_DATA_HANDLE_PEEK_BUFFER);
+ gfloat src[GSL_DATA_HANDLE_PEEK_BUFFER];
+
+ retry = GSL_N_IO_RETRIES;
+ do
+ n = gsl_data_handle_read (dhandle, offs, n, src);
+ while (n < 1 && retry--);
+ if (retry < 0)
+ return EIO;
+
+ l -= n;
+ offs += n;
+
+ n = gsl_conv_from_float_clip (format, byte_order, src, src, n);
+
+ do
+ j = write (fd, src, n);
+ while (j < 0 && errno == EINTR);
+ if (j < 0)
+ return errno ? errno : EIO;
+ }
+ return 0;
+}
+
+static void
+write_bytes (gint fd,
+ guint n_bytes,
+ const void *bytes)
+{
+ gint errold = errno;
+ guint j;
+
+ do
+ j = write (fd, bytes, n_bytes);
+ while (j < 0 && errno == EINTR);
+
+ if (!errno)
+ errno = errold;
+}
+
+static void
+write_uint32_le (gint fd,
+ guint32 val)
+{
+ val = GUINT32_TO_LE (val);
+ write_bytes (fd, 4, &val);
+}
+
+static void
+write_uint16_le (gint fd,
+ guint16 val)
+{
+ val = GUINT16_TO_LE (val);
+ write_bytes (fd, 2, &val);
+}
+
+gint /* errno */
+gsl_data_handle_dump_wav (GslDataHandle *dhandle,
+ gint fd,
+ guint n_bits,
+ guint n_channels,
+ guint sample_freq)
+{
+ guint data_length, file_length, byte_per_sample, byte_per_second;
+
+ g_return_val_if_fail (dhandle != NULL, EINVAL);
+ g_return_val_if_fail (GSL_DATA_HANDLE_OPENED (dhandle), EINVAL);
+ g_return_val_if_fail (fd >= 0, EINVAL);
+ g_return_val_if_fail (n_bits == 16 || n_bits == 8, EINVAL);
+ g_return_val_if_fail (n_channels >= 1, EINVAL);
+
+ data_length = dhandle->setup.n_values * (n_bits == 16 ? 2 : 1);
+ file_length = data_length;
+ file_length += 4 + 4; /* 'RIFF' header */
+ file_length += 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2; /* 'fmt ' header */
+ file_length += 4 + 4; /* 'data' header */
+ byte_per_sample = (n_bits == 16 ? 2 : 1) * n_channels;
+ byte_per_second = byte_per_sample * sample_freq;
+
+ errno = 0;
+ write_bytes (fd, 4, "RIFF"); /* main_chunk */
+ write_uint32_le (fd, file_length);
+ write_bytes (fd, 4, "WAVE"); /* chunk_type */
+ write_bytes (fd, 4, "fmt "); /* sub_chunk */
+ write_uint32_le (fd, 16); /* sub chunk length */
+ write_uint16_le (fd, 1); /* format (1=PCM) */
+ write_uint16_le (fd, n_channels);
+ write_uint32_le (fd, sample_freq);
+ write_uint32_le (fd, byte_per_second);
+ write_uint16_le (fd, byte_per_sample);
+ write_uint16_le (fd, n_bits);
+ write_bytes (fd, 4, "data"); /* data chunk */
+ write_uint32_le (fd, data_length);
+
+ if (errno)
+ return errno;
+
+ return gsl_data_handle_dump (dhandle, fd,
+ n_bits == 16 ? GSL_WAVE_FORMAT_SIGNED_16 : GSL_WAVE_FORMAT_UNSIGNED_8,
+ G_LITTLE_ENDIAN);
+}
+
+gboolean
+gsl_data_detect_signal (GslDataHandle *handle,
+ GslLong *sigstart_p,
+ GslLong *sigend_p)
+{
+ gfloat level_0, level_1, level_2, level_3, level_4;
+ gfloat signal_threshold = 16. * 16. * 16.; /* noise level threshold */
+ GslLong k, xcheck = -1, minsamp = -1, maxsamp = -2;
+ GslDataPeekBuffer peek_buffer = { +1 /* incremental direction */, 0, };
+
+ g_return_val_if_fail (handle != NULL, FALSE);
+ g_return_val_if_fail (GSL_DATA_HANDLE_OPENED (handle), FALSE);
+ g_return_val_if_fail (sigstart_p || sigend_p, FALSE);
+
+ /* keep open */
+ gsl_data_handle_open (handle);
+
+ /* find fadein/fadeout point */
+ k = 0;
+ level_4 = gsl_data_handle_peek_value (handle, k, &peek_buffer);
+ level_4 *= 32768;
+ level_0 = level_1 = level_2 = level_3 = level_4;
+ for (; k < handle->setup.n_values; k++)
+ {
+ gfloat mean, needx, current;
+
+ current = gsl_data_handle_peek_value (handle, k, &peek_buffer) * 32768.;
+ if (xcheck < 0 && ABS (current) >= 16)
+ xcheck = k;
+ mean = (level_0 + level_1 + level_2 + level_3 + level_4) / 5;
+ needx = (ABS (level_4 + current - (level_0 + level_1 + level_2 + level_3) / 2) *
+ ABS (level_4 - mean) * ABS (current - mean));
+ /* shift */
+ level_0 = level_1; level_1 = level_2; level_2 = level_3; level_3 = level_4; level_4 = current;
+ /* aprox. noise compare */
+ if (ABS (needx) > signal_threshold)
+ {
+ if (minsamp < 0)
+ minsamp = k;
+ if (maxsamp < k)
+ maxsamp = k;
+ }
+ /* if (minsamp >= 0 && xcheck >= 0)
+ * break;
+ */
+ }
+ if (xcheck - minsamp > 0)
+ g_printerr("###################");
+ g_printerr ("active area %ld .. %ld, signal>16 at: %ld\t diff: %ld\n",minsamp,maxsamp,xcheck, xcheck-minsamp);
+
+ /* release open reference */
+ gsl_data_handle_close (handle);
+
+ if (sigstart_p)
+ *sigstart_p = minsamp;
+ if (sigend_p)
+ *sigend_p = MAX (-1, maxsamp);
+
+ return maxsamp >= minsamp;
+}
+
+GslLong
+gsl_data_find_sample (GslDataHandle *dhandle,
+ gfloat min_value,
+ gfloat max_value,
+ GslLong start_offset,
+ gint direction)
+{
+ GslDataPeekBuffer peekbuf = { 0, 0, 0, };
+ GslLong i;
+
+ g_return_val_if_fail (dhandle != NULL, -1);
+ g_return_val_if_fail (direction == -1 || direction == +1, -1);
+
+ if (gsl_data_handle_open (dhandle) != GSL_ERROR_NONE ||
+ start_offset >= dhandle->setup.n_values)
+ return -1;
+
+ if (start_offset < 0)
+ start_offset = dhandle->setup.n_values - 1;
+
+ peekbuf.dir = direction;
+ if (min_value <= max_value)
+ for (i = start_offset; i < dhandle->setup.n_values && i >= 0; i += direction)
+ {
+ gfloat val = gsl_data_handle_peek_value (dhandle, i, &peekbuf);
+
+ /* g_print ("(%lu): %f <= %f <= %f\n", i, min_value, val, max_value); */
+ if (val >= min_value && val <= max_value)
+ break;
+ }
+ else
+ for (i = start_offset; i < dhandle->setup.n_values && i >= 0; i += direction)
+ {
+ gfloat val = gsl_data_handle_peek_value (dhandle, i, &peekbuf);
+
+ /* g_print ("(%lu): %f > %f || %f < %f\n", i, val, max_value, val, min_value); */
+ if (val > min_value || val < max_value)
+ break;
+ }
+
+ gsl_data_handle_close (dhandle);
+
+ return i >= dhandle->setup.n_values ? -1: i;
+}
+
+static inline gdouble
+tailmatch_score_loop (GslDataHandle *shandle,
+ GslDataHandle *dhandle,
+ GslLong start,
+ gdouble worst_score)
+{
+ GslLong l, length = MIN (shandle->setup.n_values, dhandle->setup.n_values);
+ gfloat v1[GSL_DATA_HANDLE_PEEK_BUFFER], v2[GSL_DATA_HANDLE_PEEK_BUFFER];
+ gdouble score = 0;
+
+ g_assert (start < length);
+
+ for (l = start; l < length; )
+ {
+ GslLong b = MIN (GSL_DATA_HANDLE_PEEK_BUFFER, length - l);
+
+ b = gsl_data_handle_read (shandle, l, b, v1);
+ b = gsl_data_handle_read (dhandle, l, b, v2);
+ g_assert (b >= 1);
+ l += b;
+
+ while (b--)
+ score += (v1[b] - v2[b]) * (v1[b] - v2[b]);
+
+ /* for performance, prematurely abort */
+ if (score > worst_score)
+ break;
+ }
+ return score;
+}
+
+gboolean
+gsl_data_find_tailmatch (GslDataHandle *dhandle,
+ const GslLoopSpec *lspec,
+ GslLong *loop_start_p,
+ GslLong *loop_end_p)
+{
+ GslDataHandle *shandle;
+ GslDataCache *dcache;
+ GslLong length, offset, l, lsize, pcount, start = 0, end = 0;
+ gdouble pbound, pval, best_score = GSL_MAXLONG;
+
+ g_return_val_if_fail (dhandle != NULL, FALSE);
+ g_return_val_if_fail (lspec != NULL, FALSE);
+ g_return_val_if_fail (loop_start_p != NULL, FALSE);
+ g_return_val_if_fail (loop_end_p != NULL, FALSE);
+ g_return_val_if_fail (lspec->head_skip >= 0, FALSE);
+ g_return_val_if_fail (lspec->tail_cut >= 0, FALSE);
+ g_return_val_if_fail (lspec->min_loop >= 1, FALSE);
+ g_return_val_if_fail (lspec->max_loop >= lspec->min_loop, FALSE);
+ g_return_val_if_fail (lspec->tail_cut >= lspec->max_loop, FALSE);
+
+ if (gsl_data_handle_open (dhandle) != GSL_ERROR_NONE)
+ return FALSE;
+ length = dhandle->setup.n_values;
+ if (lspec->head_skip < length)
+ {
+ gsl_data_handle_close (dhandle);
+ return FALSE;
+ }
+ offset = lspec->head_skip;
+ length -= offset;
+ if (lspec->tail_cut < length)
+ {
+ gsl_data_handle_close (dhandle);
+ return FALSE;
+ }
+ length -= lspec->tail_cut;
+ if (lspec->max_loop <= length)
+ {
+ gsl_data_handle_close (dhandle);
+ return FALSE;
+ }
+
+ dcache = gsl_data_cache_new (dhandle, 1);
+ shandle = gsl_data_handle_new_dcached (dcache);
+ gsl_data_cache_unref (dcache);
+ gsl_data_handle_open (shandle);
+ gsl_data_handle_close (dhandle);
+ gsl_data_handle_unref (shandle);
+ /* at this point, we just hold one open() count on shandle */
+
+ pbound = (lspec->max_loop - lspec->min_loop + 1.);
+ pbound *= length / 100.;
+ pval = 0;
+ pcount = 100;
+
+ for (lsize = lspec->min_loop; lsize <= lspec->max_loop; lsize++)
+ {
+ for (l = length - lsize; l >= 0; l--)
+ {
+ GslDataHandle *lhandle = gsl_data_handle_new_looped (shandle, offset + l, offset + l + lsize - 1);
+ gdouble score;
+
+ gsl_data_handle_open (lhandle);
+ score = tailmatch_score_loop (shandle, lhandle, offset + l, best_score);
+ gsl_data_handle_close (lhandle);
+ gsl_data_handle_unref (lhandle);
+
+ if (score < best_score)
+ {
+ start = offset + l;
+ end = offset + l + lsize - 1;
+ g_print ("\nimproved: %f < %f: [0x%lx..0x%lx] (%lu)\n", score, best_score, start, end, lsize);
+ best_score = score;
+ }
+ else
+ break;
+ }
+ if (!pcount--)
+ {
+ pcount = 100;
+ pval = lsize - lspec->min_loop;
+ pbound = (lspec->max_loop - lspec->min_loop + 1.);
+ g_print ("\rprocessed: %f%% \r", pval / pbound);
+ }
+ }
+ gsl_data_handle_close (shandle);
+
+ g_print ("\nhalted: %f: [0x%lx..0x%lx] (%lu)\n", best_score, start, end, end - start + 1);
+
+ *loop_start_p = start;
+ *loop_end_p = end;
+
+ return TRUE;
+}
+
+/**
+ * gsl_data_find_block
+ * @handle: an open GslDataHandle
+ * @n_values: amount of values to look for
+ * @values: values to find
+ * @epsilon: maximum difference upon comparisons
+ * @RETURNS: position of values in data handle or -1
+ *
+ * Find the position of a block of values within a
+ * data handle, where all values compare to the reference
+ * values with a delta smaller than epsilon.
+ */
+GslLong
+gsl_data_find_block (GslDataHandle *handle,
+ guint n_values,
+ const gfloat *values,
+ gfloat epsilon)
+{
+ GslDataPeekBuffer pbuf = { +1 /* random access: 0 */ };
+ guint i;
+
+ g_return_val_if_fail (handle != NULL, -1);
+ g_return_val_if_fail (GSL_DATA_HANDLE_OPENED (handle), -1);
+
+ if (n_values < 1)
+ return -1;
+ else
+ g_return_val_if_fail (values != NULL, -1);
+
+ for (i = 0; i < handle->setup.n_values; i++)
+ {
+ guint j;
+
+ if (n_values > handle->setup.n_values - i)
+ return -1;
+
+ for (j = 0; j < n_values; j++)
+ {
+ if (fabs (values[j] - gsl_data_handle_peek_value (handle, i + j, &pbuf)) >= epsilon)
+ break;
+ }
+ if (j >= n_values)
+ return i;
+ }
+ return -1;
+}
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gsldatautils.h b/flow/gsl/gsldatautils.h
new file mode 100644
index 0000000..0dea8c9
--- /dev/null
+++ b/flow/gsl/gsldatautils.h
@@ -0,0 +1,909 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_DATA_UTILS_H__
+#define __GSL_DATA_UTILS_H__
+
+#include <gsl/gslmath.h>
+#include <gsl/gsldatahandle.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- structures --- */
+#define GSL_DATA_HANDLE_PEEK_BUFFER (8192)
+typedef struct
+{
+ gint dir; /* initialize direction to -1 or +1 (or 0 for random access) */
+ GslLong start; /* initialize to 0 */
+ GslLong end; /* initialize to 0 */
+ gfloat data[GSL_DATA_HANDLE_PEEK_BUFFER];
+} GslDataPeekBuffer;
+typedef struct
+{
+ GslLong head_skip; /* FIXME: remove this */
+ GslLong tail_cut;
+ GslLong min_loop;
+ GslLong max_loop;
+} GslLoopSpec; /* rename this to ...Data... */
+
+
+/* --- data utils --- */
+gboolean gsl_data_detect_signal (GslDataHandle *handle,
+ GslLong *sigstart,
+ GslLong *sigend);
+GslLong gsl_data_find_sample (GslDataHandle *dhandle,
+ gfloat min_value,
+ gfloat max_value,
+ GslLong start_offset,
+ gint direction);
+gboolean gsl_data_find_tailmatch (GslDataHandle *dhandle,
+ const GslLoopSpec *lspec,
+ GslLong *loop_start_p,
+ GslLong *loop_end_p);
+GslLong gsl_data_find_block (GslDataHandle *handle,
+ guint n_values,
+ const gfloat *values,
+ gfloat epsilon);
+
+
+/* --- data handle utils --- */
+static inline gfloat gsl_data_handle_peek_value (GslDataHandle *dhandle,
+ GslLong position,
+ GslDataPeekBuffer *peekbuf);
+gint /* errno */ gsl_data_handle_dump (GslDataHandle *dhandle,
+ gint fd,
+ GslWaveFormatType format,
+ guint byte_order);
+gint /* errno */ gsl_data_handle_dump_wav (GslDataHandle *dhandle,
+ gint fd,
+ guint n_bits,
+ guint n_channels,
+ guint sample_freq);
+
+
+/* --- conversion utils --- */
+static inline guint gsl_conv_from_float (GslWaveFormatType format,
+ guint byte_order,
+ const gfloat *src,
+ gpointer dest,
+ guint n_values);
+static inline guint gsl_conv_from_float_clip (GslWaveFormatType format,
+ guint byte_order,
+ const gfloat *src,
+ gpointer dest,
+ guint n_values);
+static inline void gsl_conv_to_float (GslWaveFormatType format,
+ guint byte_order,
+ gconstpointer src,
+ gfloat *dest,
+ guint n_values);
+static inline guint gsl_conv_from_double (GslWaveFormatType format,
+ guint byte_order,
+ const gdouble *src,
+ gpointer dest,
+ guint n_values);
+static inline guint gsl_conv_from_double_clip (GslWaveFormatType format,
+ guint byte_order,
+ const gdouble *src,
+ gpointer dest,
+ guint n_values);
+static inline void gsl_conv_to_double (GslWaveFormatType format,
+ guint byte_order,
+ gconstpointer src,
+ gdouble *dest,
+ guint n_values);
+
+
+
+/* --- misc implementations --- */
+gfloat gsl_data_peek_value_f (GslDataHandle *dhandle,
+ GslLong pos,
+ GslDataPeekBuffer *peekbuf);
+
+static inline gfloat
+gsl_data_handle_peek_value (GslDataHandle *dhandle,
+ GslLong position,
+ GslDataPeekBuffer *peekbuf)
+{
+ return (position >= peekbuf->start && position < peekbuf->end ?
+ peekbuf->data[position - peekbuf->start] :
+ gsl_data_peek_value_f (dhandle, position, peekbuf));
+}
+
+#define GSL_CONV_FORMAT(format, endian_flag) (((endian_flag) << 16) | ((format) & 0xffff))
+
+static inline guint /* returns number of bytes used in dest */
+gsl_conv_from_float (GslWaveFormatType format,
+ guint byte_order,
+ const gfloat *src,
+ gpointer dest,
+ guint n_values)
+{
+ gint8 *i8 = (gint8*) dest;
+ guint8 *u8 = (guint8*) dest;
+ gint16 *i16 = (gint16*) dest;
+ guint16 *u16 = (guint16*) dest;
+ guint32 *u32dest = (guint32*) dest;
+ const gfloat *bound = src + n_values;
+ guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
+
+ if (!n_values)
+ return 0;
+
+ switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
+ {
+ GslFpuState fpu;
+ gfloat v;
+ gint16 vi16;
+ guint16 vu16;
+ guint32 vu32;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ *u8++ = *src++ * 128. + 128.5;
+ while (src < bound);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 128.;
+ *i8++ = gsl_ftoi (v);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *u16++ = *src++ * 2048. + 2048.5;
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *src++ * 2048. + 2048.5;
+ *u16++ = GUINT16_SWAP_LE_BE (vu16);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ *i16++ = gsl_ftoi (v);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ vi16 = gsl_ftoi (v);
+ *i16++ = GUINT16_SWAP_LE_BE (vi16);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *u16++ = *src++ * 32768. + 32768.5;
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *src++ * 32768. + 32768.5;
+ *u16++ = GUINT16_SWAP_LE_BE (vu16);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ *i16++ = gsl_ftoi (v);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ vi16 = gsl_ftoi (v);
+ *i16++ = GUINT16_SWAP_LE_BE (vi16);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
+ return n_values << 2;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu32 = *u32src++;
+ *u32dest++ = GUINT32_SWAP_LE_BE (vu32);
+ }
+ while (u32src < u32bound);
+ return n_values << 2;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+static inline guint /* returns number of bytes used in dest */
+gsl_conv_from_float_clip (GslWaveFormatType format,
+ guint byte_order,
+ const gfloat *src,
+ gpointer dest,
+ guint n_values)
+{
+ gint8 *i8 = (gint8*) dest;
+ guint8 *u8 = (guint8*) dest;
+ gint16 *i16 = (gint16*) dest;
+ guint16 *u16 = (guint16*) dest;
+ guint32 *u32dest = (guint32*) dest;
+ const gfloat *bound = src + n_values;
+ guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
+
+ if (!n_values)
+ return 0;
+
+ switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
+ {
+ GslFpuState fpu;
+ gfloat v;
+ guint32 vu32;
+ gint32 vi32;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 128. + 128.5;
+ *u8++ = CLAMP (vi32, 0, 255);
+ }
+ while (src < bound);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 128.;
+ vi32 = gsl_ftoi (v);
+ *i8++ = CLAMP (vi32, -128, 127);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 2048. + 2048.5;
+ *u16++ = CLAMP (vi32, 0, 4095);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 2048. + 2048.5;
+ vi32 = CLAMP (vi32, 0, 4095);
+ *u16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ vi32 = gsl_ftoi (v);
+ *i16++ = CLAMP (vi32, -2048, 2047);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ vi32 = gsl_ftoi (v);
+ vi32 = CLAMP (vi32, -2048, 2047);
+ *i16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 32768. + 32768.5;
+ *u16++ = CLAMP (vi32, 0, 65535);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 32768. + 32768.5;
+ vi32 = CLAMP (vi32, 0, 65535);
+ *u16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ vi32 = gsl_ftoi (v);
+ vi32 = CLAMP (vi32, -32768, 32767);
+ *i16++ = vi32;
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ vi32 = gsl_ftoi (v);
+ vi32 = CLAMP (vi32, -32768, 32767);
+ *i16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
+ return n_values << 2;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu32 = *u32src++;
+ *u32dest++ = GUINT32_SWAP_LE_BE (vu32);
+ }
+ while (u32src < u32bound);
+ return n_values << 2;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+static inline void
+gsl_conv_to_float (GslWaveFormatType format,
+ guint byte_order,
+ gconstpointer src,
+ gfloat *dest,
+ guint n_values)
+{
+ guint8 *u8 = (guint8*) src;
+ gint8 *i8 = (gint8*) src;
+ guint16 *u16 = (guint16*) src;
+ gint16 *i16 = (gint16*) src;
+ guint32 *u32src = (guint32*) src;
+ gfloat *bound = dest + n_values;
+ guint32 *u32dest = (guint32*) dest, *u32bound = (guint32*) bound;
+
+ if (!n_values)
+ return;
+
+ switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
+ {
+ gint16 vi16;
+ guint16 vu16;
+ guint32 vu32;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ *dest++ = (*u8++ - 128) * (1. / 128.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ *dest++ = *i8++ * (1. / 128.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *dest++ = ((*u16++ & 0x0fff) - 2048) * (1. / 2048.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *u16++;
+ *dest++ = ((GUINT16_SWAP_LE_BE (vu16) & 0x0fff) - 2048) * (1. / 2048.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ {
+ vi16 = *i16++;
+ *dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi16 = *i16++;
+ vi16 = GUINT16_SWAP_LE_BE (vi16);
+ *dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *dest++ = (*u16++ - 32768) * (1. / 32768.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *u16++;
+ *dest++ = (GUINT16_SWAP_LE_BE (vu16) - 32768) * (1. / 32768.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *dest++ = *i16++ * (1. / 32768.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi16 = *i16++;
+ *dest++ = GUINT16_SWAP_LE_BE (vi16) * (1. / 32768.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu32 = *u32src++;
+ *u32dest++ = GUINT32_SWAP_LE_BE (vu32);
+ }
+ while (u32dest < u32bound);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* same as above with s/float/double */
+static inline guint /* returns number of bytes used in dest */
+gsl_conv_from_double (GslWaveFormatType format,
+ guint byte_order,
+ const gdouble *src,
+ gpointer dest,
+ guint n_values)
+{
+ gint8 *i8 = (gint8*) dest;
+ guint8 *u8 = (guint8*) dest;
+ gint16 *i16 = (gint16*) dest;
+ guint16 *u16 = (guint16*) dest;
+ guint32 *u32dest = (guint32*) dest;
+ const gdouble *bound = src + n_values;
+ guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
+
+ if (!n_values)
+ return 0;
+
+ switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
+ {
+ GslFpuState fpu;
+ gdouble v;
+ gint16 vi16;
+ guint16 vu16;
+ guint32 vu32;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ *u8++ = *src++ * 128. + 128.5;
+ while (src < bound);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 128.;
+ *i8++ = gsl_ftoi (v);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *u16++ = *src++ * 2048. + 2048.5;
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *src++ * 2048. + 2048.5;
+ *u16++ = GUINT16_SWAP_LE_BE (vu16);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ *i16++ = gsl_ftoi (v);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ vi16 = gsl_ftoi (v);
+ *i16++ = GUINT16_SWAP_LE_BE (vi16);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *u16++ = *src++ * 32768. + 32768.5;
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *src++ * 32768. + 32768.5;
+ *u16++ = GUINT16_SWAP_LE_BE (vu16);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ *i16++ = gsl_ftoi (v);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ vi16 = gsl_ftoi (v);
+ *i16++ = GUINT16_SWAP_LE_BE (vi16);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
+ return n_values << 2;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu32 = *u32src++;
+ *u32dest++ = GUINT32_SWAP_LE_BE (vu32);
+ }
+ while (u32src < u32bound);
+ return n_values << 2;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+static inline guint /* returns number of bytes used in dest */
+gsl_conv_from_double_clip (GslWaveFormatType format,
+ guint byte_order,
+ const gdouble *src,
+ gpointer dest,
+ guint n_values)
+{
+ gint8 *i8 = (gint8*) dest;
+ guint8 *u8 = (guint8*) dest;
+ gint16 *i16 = (gint16*) dest;
+ guint16 *u16 = (guint16*) dest;
+ guint32 *u32dest = (guint32*) dest;
+ const gdouble *bound = src + n_values;
+ guint32 *u32src = (guint32*) src, *u32bound = (guint32*) bound;
+
+ if (!n_values)
+ return 0;
+
+ switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
+ {
+ GslFpuState fpu;
+ gdouble v;
+ guint32 vu32;
+ gint32 vi32;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 128. + 128.5;
+ *u8++ = CLAMP (vi32, 0, 255);
+ }
+ while (src < bound);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 128.;
+ vi32 = gsl_ftoi (v);
+ *i8++ = CLAMP (vi32, -128, 127);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 2048. + 2048.5;
+ *u16++ = CLAMP (vi32, 0, 4095);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 2048. + 2048.5;
+ vi32 = CLAMP (vi32, 0, 4095);
+ *u16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ vi32 = gsl_ftoi (v);
+ *i16++ = CLAMP (vi32, -2048, 2047);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 2048.;
+ vi32 = gsl_ftoi (v);
+ vi32 = CLAMP (vi32, -2048, 2047);
+ *i16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 32768. + 32768.5;
+ *u16++ = CLAMP (vi32, 0, 65535);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi32 = *src++ * 32768. + 32768.5;
+ vi32 = CLAMP (vi32, 0, 65535);
+ *u16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ vi32 = gsl_ftoi (v);
+ vi32 = CLAMP (vi32, -32768, 32767);
+ *i16++ = vi32;
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ gsl_fpu_setround (&fpu);
+ do
+ {
+ v = *src++;
+ v *= 32768.;
+ vi32 = gsl_ftoi (v);
+ vi32 = CLAMP (vi32, -32768, 32767);
+ *i16++ = GUINT16_SWAP_LE_BE (vi32);
+ }
+ while (src < bound);
+ gsl_fpu_restore (fpu);
+ return n_values << 1;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
+ return n_values << 2;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu32 = *u32src++;
+ *u32dest++ = GUINT32_SWAP_LE_BE (vu32);
+ }
+ while (u32src < u32bound);
+ return n_values << 2;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+static inline void
+gsl_conv_to_double (GslWaveFormatType format,
+ guint byte_order,
+ gconstpointer src,
+ gdouble *dest,
+ guint n_values)
+{
+ guint8 *u8 = (guint8*) src;
+ gint8 *i8 = (gint8*) src;
+ guint16 *u16 = (guint16*) src;
+ gint16 *i16 = (gint16*) src;
+ guint32 *u32src = (guint32*) src;
+ gdouble *bound = dest + n_values;
+ guint32 *u32dest = (guint32*) dest, *u32bound = (guint32*) bound;
+
+ if (!n_values)
+ return;
+
+ switch (GSL_CONV_FORMAT (format, byte_order == G_BYTE_ORDER))
+ {
+ gint16 vi16;
+ guint16 vu16;
+ guint32 vu32;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ *dest++ = (*u8++ - 128) * (1. / 128.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER == G_BYTE_ORDER):
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_8, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ *dest++ = *i8++ * (1. / 128.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *dest++ = ((*u16++ & 0x0fff) - 2048) * (1. / 2048.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *u16++;
+ *dest++ = ((GUINT16_SWAP_LE_BE (vu16) & 0x0fff) - 2048) * (1. / 2048.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ {
+ vi16 = *i16++;
+ *dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_12, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi16 = *i16++;
+ vi16 = GUINT16_SWAP_LE_BE (vi16);
+ *dest++ = CLAMP (vi16, -2048, 2048) * (1. / 2048.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *dest++ = (*u16++ - 32768) * (1. / 32768.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_UNSIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu16 = *u16++;
+ *dest++ = (GUINT16_SWAP_LE_BE (vu16) - 32768) * (1. / 32768.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER == G_BYTE_ORDER):
+ do
+ *dest++ = *i16++ * (1. / 32768.);
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_SIGNED_16, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vi16 = *i16++;
+ *dest++ = GUINT16_SWAP_LE_BE (vi16) * (1. / 32768.);
+ }
+ while (dest < bound);
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER == G_BYTE_ORDER):
+ break;
+ case GSL_CONV_FORMAT (GSL_WAVE_FORMAT_FLOAT, G_BYTE_ORDER != G_BYTE_ORDER):
+ do
+ {
+ vu32 = *u32src++;
+ *u32dest++ = GUINT32_SWAP_LE_BE (vu32);
+ }
+ while (u32dest < u32bound);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_DATA_UTILS_H__ */
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gsldefs.h b/flow/gsl/gsldefs.h
new file mode 100644
index 0000000..d610e9c
--- /dev/null
+++ b/flow/gsl/gsldefs.h
@@ -0,0 +1,136 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_DEFS_H__
+#define __GSL_DEFS_H__
+
+/* configure checks */
+#include <gsl/gslconfig.h>
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- forward decls --- */
+typedef struct _GslMagic GslMagic;
+typedef struct _GslClass GslClass;
+typedef struct _GslComplex GslComplex;
+typedef struct _GslDataCache GslDataCache;
+typedef struct _GslDataHandle GslDataHandle;
+typedef struct _GslDataHandleFuncs GslDataHandleFuncs;
+typedef struct _GslGlueContext GslGlueContext;
+typedef struct _GslJob GslJob;
+typedef struct _GslModule GslModule;
+typedef struct _GslIStream GslIStream;
+typedef struct _GslJStream GslJStream;
+typedef struct _GslLoader GslLoader;
+typedef struct _GslOStream GslOStream;
+typedef struct _GslThread GslThread;
+typedef struct _GslTrans GslTrans;
+typedef struct _GslWaveChunk GslWaveChunk;
+typedef struct _GslWaveChunkBlock GslWaveChunkBlock;
+typedef struct _GslRecMutex GslRecMutex;
+typedef struct _GslRing GslRing;
+typedef union _GslCond GslCond;
+typedef union _GslMutex GslMutex;
+/* ssize_t/off_t type used within Gsl */
+typedef glong GslLong;
+#define GSL_MAXLONG G_MAXLONG
+
+
+/* --- GSL errors --- */
+typedef enum /*< skip >*/
+{
+ GSL_ERROR_NONE,
+ GSL_ERROR_INTERNAL,
+ GSL_ERROR_UNKNOWN,
+ /* I/O errors */
+ GSL_ERROR_IO,
+ GSL_ERROR_PERMS,
+ GSL_ERROR_BUSY,
+ GSL_ERROR_EXISTS,
+ GSL_ERROR_TEMP,
+ GSL_ERROR_EOF,
+#define GSL_ERROR_FILE_EMPTY GSL_ERROR_EOF
+ GSL_ERROR_NOT_FOUND,
+ GSL_ERROR_OPEN_FAILED,
+ GSL_ERROR_SEEK_FAILED,
+ GSL_ERROR_READ_FAILED,
+ GSL_ERROR_WRITE_FAILED,
+ /* content errors */
+ GSL_ERROR_FORMAT_INVALID,
+ GSL_ERROR_FORMAT_UNKNOWN,
+ GSL_ERROR_DATA_CORRUPT,
+ GSL_ERROR_CONTENT_GLITCH,
+ /* miscellaneous errors */
+ GSL_ERROR_NO_RESOURCE,
+ GSL_ERROR_CODEC_FAILURE,
+ GSL_ERROR_LAST /* administrative */
+} GslErrorType;
+
+
+/* --- functions --- */
+typedef void (*GslAccessFunc) (GslModule *module,
+ gpointer data);
+typedef void (*GslFreeFunc) (gpointer data);
+typedef void (*GslModuleFreeFunc) (gpointer data,
+ const GslClass *klass);
+
+
+#if defined (BSE_COMPILATION) || defined (BSE_PLUGIN_FALLBACK) \
+ || (GSL_USE_GSL_GLIB) || defined (GSL_EXTENSIONS)
+# define if_expect(cond) if (GSL_GCC_EXPECT (cond))
+# define if_reject(cond) if (GSL_GCC_REJECT (cond))
+#endif
+
+
+/* --- implementation details --- */
+#define GSL_ENGINE_MAX_POLLFDS (128)
+union _GslCond
+{
+ gpointer cond_pointer;
+ guint8 cond_dummy[MAX (8, GSL_SIZEOF_PTH_COND_T)];
+};
+union _GslMutex
+{
+ gpointer mutex_pointer;
+ guint8 mutex_dummy[MAX (8, GSL_SIZEOF_PTH_MUTEX_T)];
+};
+struct _GslRecMutex
+{
+ GslMutex sync_mutex;
+ gpointer owner;
+ guint depth;
+};
+#if __GNUC__ >= 3 && defined __OPTIMIZE__
+# define GSL_GCC_EXPECT(cond) (__builtin_expect ((cond) != 0, 1))
+# define GSL_GCC_REJECT(cond) (__builtin_expect ((cond) != 0, 0))
+#else
+# define GSL_GCC_EXPECT(cond) cond
+# define GSL_GCC_REJECT(cond) cond
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_DEFS_H__ */
+
+/* vim:set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslengine.c b/flow/gsl/gslengine.c
new file mode 100644
index 0000000..65ee620
--- /dev/null
+++ b/flow/gsl/gslengine.c
@@ -0,0 +1,753 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslengine.h"
+
+#include "gslcommon.h"
+#include "gslopnode.h"
+#include "gslopmaster.h"
+
+
+/* --- prototypes --- */
+static void wakeup_master (void);
+
+
+/* --- UserThread --- */
+GslModule*
+gsl_module_new (const GslClass *klass,
+ gpointer user_data)
+{
+ EngineNode *node;
+ guint i;
+
+ g_return_val_if_fail (klass != NULL, NULL);
+ g_return_val_if_fail (klass->process != NULL || klass->process_defer != NULL, NULL);
+ if (klass->process_defer)
+ {
+ g_warning ("%s: Delay cycle processing not yet implemented", G_STRLOC);
+ return NULL;
+ }
+
+ node = gsl_new_struct0 (EngineNode, 1);
+
+ /* setup GslModule */
+ node->module.klass = klass;
+ node->module.user_data = user_data;
+ node->module.istreams = klass->n_istreams ? gsl_new_struct0 (GslIStream, ENGINE_NODE_N_ISTREAMS (node)) : NULL;
+ node->module.jstreams = klass->n_jstreams ? gsl_new_struct0 (GslJStream, ENGINE_NODE_N_JSTREAMS (node)) : NULL;
+ node->module.ostreams = _engine_alloc_ostreams (ENGINE_NODE_N_OSTREAMS (node));
+
+ /* setup EngineNode */
+ node->inputs = ENGINE_NODE_N_ISTREAMS (node) ? gsl_new_struct0 (EngineInput, ENGINE_NODE_N_ISTREAMS (node)) : NULL;
+ node->jinputs = ENGINE_NODE_N_JSTREAMS (node) ? gsl_new_struct0 (EngineJInput*, ENGINE_NODE_N_JSTREAMS (node)) : NULL;
+ node->outputs = ENGINE_NODE_N_OSTREAMS (node) ? gsl_new_struct0 (EngineOutput, ENGINE_NODE_N_OSTREAMS (node)) : NULL;
+ node->output_nodes = NULL;
+ node->integrated = FALSE;
+ gsl_rec_mutex_init (&node->rec_mutex);
+ for (i = 0; i < ENGINE_NODE_N_OSTREAMS (node); i++)
+ {
+ node->outputs[i].buffer = node->module.ostreams[i].values;
+ node->module.ostreams[i].sub_sample_pattern = gsl_engine_sub_sample_test (node->module.ostreams[i].values);
+ }
+ node->flow_jobs = NULL;
+ node->fjob_first = NULL;
+ node->fjob_last = NULL;
+
+ return &node->module;
+}
+
+/**
+ * gsl_module_tick_stamp
+ * @module: a GSL engine module
+ * @RETURNS: the module's tick stamp, indicating its process status
+ *
+ * Any thread may call this function on a valid engine module.
+ * The module specific tick stamp is updated to gsl_tick_stamp() +
+ * @n_values every time its GslProcessFunc() function was
+ * called. See also gsl_tick_stamp().
+ */
+guint64
+gsl_module_tick_stamp (GslModule *module)
+{
+ g_return_val_if_fail (module != NULL, 0);
+
+ return ENGINE_NODE (module)->counter;
+}
+
+/**
+ * gsl_job_integrate
+ * @module: The module to integrate
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job to integrate @module into the engine.
+ */
+GslJob*
+gsl_job_integrate (GslModule *module)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (module != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_INTEGRATE;
+ job->data.node = ENGINE_NODE (module);
+
+ return job;
+}
+
+/**
+ * gsl_job_discard
+ * @module: The module to discard
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which removes @module from the
+ * engine and destroys it.
+ */
+GslJob*
+gsl_job_discard (GslModule *module)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (module != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_DISCARD;
+ job->data.node = ENGINE_NODE (module);
+
+ return job;
+}
+
+/**
+ * gsl_job_connect
+ * @src_module: Module with output stream
+ * @src_ostream: Index of output stream of @src_module
+ * @dest_module: Module with unconnected input stream
+ * @dest_istream: Index of input stream of @dest_module
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which connects the output stream @src_ostream
+ * of module @src_module to the input stream @dest_istream of module @dest_module
+ * (it is an error if the input stream is already connected by the time the job
+ * is executed).
+ */
+GslJob*
+gsl_job_connect (GslModule *src_module,
+ guint src_ostream,
+ GslModule *dest_module,
+ guint dest_istream)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (src_module != NULL, NULL);
+ g_return_val_if_fail (src_ostream < src_module->klass->n_ostreams, NULL);
+ g_return_val_if_fail (dest_module != NULL, NULL);
+ g_return_val_if_fail (dest_istream < dest_module->klass->n_istreams, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_ICONNECT;
+ job->data.connection.dest_node = ENGINE_NODE (dest_module);
+ job->data.connection.dest_ijstream = dest_istream;
+ job->data.connection.src_node = ENGINE_NODE (src_module);
+ job->data.connection.src_ostream = src_ostream;
+
+ return job;
+}
+
+GslJob*
+gsl_job_jconnect (GslModule *src_module,
+ guint src_ostream,
+ GslModule *dest_module,
+ guint dest_jstream)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (src_module != NULL, NULL);
+ g_return_val_if_fail (src_ostream < src_module->klass->n_ostreams, NULL);
+ g_return_val_if_fail (dest_module != NULL, NULL);
+ g_return_val_if_fail (dest_jstream < dest_module->klass->n_jstreams, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_JCONNECT;
+ job->data.connection.dest_node = ENGINE_NODE (dest_module);
+ job->data.connection.dest_ijstream = dest_jstream;
+ job->data.connection.src_node = ENGINE_NODE (src_module);
+ job->data.connection.src_ostream = src_ostream;
+
+ return job;
+}
+
+/**
+ * gsl_job_disconnect
+ * @dest_module: Module with connected input stream
+ * @dest_istream: Index of input stream of @dest_module
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which causes the input stream @dest_istream
+ * of @dest_module to be disconnected (it is an error if the input stream isn't
+ * connected by the time the job is executed).
+ */
+GslJob*
+gsl_job_disconnect (GslModule *dest_module,
+ guint dest_istream)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (dest_module != NULL, NULL);
+ g_return_val_if_fail (dest_istream < dest_module->klass->n_istreams, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_IDISCONNECT;
+ job->data.connection.dest_node = ENGINE_NODE (dest_module);
+ job->data.connection.dest_ijstream = dest_istream;
+ job->data.connection.src_node = NULL;
+ job->data.connection.src_ostream = ~0;
+
+ return job;
+}
+
+GslJob*
+gsl_job_jdisconnect (GslModule *dest_module,
+ guint dest_jstream,
+ GslModule *src_module,
+ guint src_ostream)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (dest_module != NULL, NULL);
+ g_return_val_if_fail (dest_jstream < dest_module->klass->n_jstreams, NULL);
+ g_return_val_if_fail (src_module != NULL, NULL);
+ g_return_val_if_fail (src_ostream < src_module->klass->n_ostreams, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_JDISCONNECT;
+ job->data.connection.dest_node = ENGINE_NODE (dest_module);
+ job->data.connection.dest_ijstream = dest_jstream;
+ job->data.connection.src_node = ENGINE_NODE (src_module);
+ job->data.connection.src_ostream = src_ostream;
+
+ return job;
+}
+
+GslJob*
+gsl_job_set_consumer (GslModule *module,
+ gboolean is_toplevel_consumer)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (module != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = is_toplevel_consumer ? ENGINE_JOB_SET_CONSUMER : ENGINE_JOB_UNSET_CONSUMER;
+ job->data.node = ENGINE_NODE (module);
+
+ return job;
+}
+
+/**
+ * GslAccessFunc
+ * @module: Module to operate on
+ * @data: Accessor data
+ *
+ * The GslAccessFunc is a user supplied callback function which can access
+ * a module in times it is not processing. Accessors are usually used to
+ * either read out a module's current state, or to modify its state. An
+ * accessor may only operate on the @data and the @module passed
+ * in to it.
+ */
+/**
+ * gsl_job_access
+ * @module: The module to access
+ * @access_func: The accessor function
+ * @data: Data passed in to the accessor
+ * @free_func: Function to free @data
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which will invoke @access_func
+ * on @module with @data when the transaction queue is processed
+ * to modify the module's state.
+ */
+GslJob*
+gsl_job_access (GslModule *module,
+ GslAccessFunc access_func,
+ gpointer data,
+ GslFreeFunc free_func)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (module != NULL, NULL);
+ g_return_val_if_fail (access_func != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_ACCESS;
+ job->data.access.node = ENGINE_NODE (module);
+ job->data.access.access_func = access_func;
+ job->data.access.data = data;
+ job->data.access.free_func = free_func;
+
+ return job;
+}
+
+/**
+ * gsl_flow_job_access
+ */
+GslJob*
+gsl_flow_job_access (GslModule *module,
+ guint64 tick_stamp,
+ GslAccessFunc access_func,
+ gpointer data,
+ GslFreeFunc free_func)
+{
+ GslJob *job;
+ EngineFlowJob *fjob;
+
+ g_return_val_if_fail (module != NULL, NULL);
+ g_return_val_if_fail (access_func != NULL, NULL);
+
+ fjob = (EngineFlowJob*) gsl_new_struct0 (EngineFlowJobAccess, 1);
+ fjob->fjob_id = ENGINE_FLOW_JOB_ACCESS;
+ fjob->any.tick_stamp = tick_stamp;
+ fjob->access.access_func = access_func;
+ fjob->access.data = data;
+ fjob->access.free_func = free_func;
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_FLOW_JOB;
+ job->data.flow_job.node = ENGINE_NODE (module);
+ job->data.flow_job.fjob = fjob;
+
+ return job;
+}
+
+GslJob*
+gsl_flow_job_suspend (GslModule *module,
+ guint64 tick_stamp)
+{
+ GslJob *job;
+ EngineFlowJob *fjob;
+
+ g_return_val_if_fail (module != NULL, NULL);
+
+ fjob = (EngineFlowJob*) gsl_new_struct0 (EngineFlowJobAny, 1);
+ fjob->fjob_id = ENGINE_FLOW_JOB_SUSPEND;
+ fjob->any.tick_stamp = tick_stamp;
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_FLOW_JOB;
+ job->data.flow_job.node = ENGINE_NODE (module);
+ job->data.flow_job.fjob = fjob;
+
+ return job;
+}
+
+GslJob*
+gsl_flow_job_resume (GslModule *module,
+ guint64 tick_stamp)
+{
+ GslJob *job;
+ EngineFlowJob *fjob;
+
+ g_return_val_if_fail (module != NULL, NULL);
+
+ fjob = (EngineFlowJob*) gsl_new_struct0 (EngineFlowJobAny, 1);
+ fjob->fjob_id = ENGINE_FLOW_JOB_RESUME;
+ fjob->any.tick_stamp = tick_stamp;
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_FLOW_JOB;
+ job->data.flow_job.node = ENGINE_NODE (module);
+ job->data.flow_job.fjob = fjob;
+
+ return job;
+}
+
+/**
+ * GslPollFunc
+ * @data: Data of poll function
+ * @n_values: Minimum number of values the engine wants to process
+ * @timeout_p: Location of timeout value
+ * @n_fds: Number of file descriptors used for polling
+ * @fds: File descriptors to be used for polling
+ * @revents_filled: Indicates whether @fds actually have their ->revents field filled with valid data.
+ * @Returns: A boolean value indicating whether the engine should process data right now
+ *
+ * The GslPollFunc is a user supplied callback function which can be hooked into the
+ * GSL engine. The engine uses the poll functions to determine whether processing of
+ * @n_values in its module network is necessary.
+ * In order for the poll functions to react to extern events, such as device driver
+ * status changes, the engine will poll(2) the @fds of the poll function and invoke
+ * the callback with @revents_filled==%TRUE if any of its @fds changed state.
+ * The callback may also be invoked at other random times with @revents_filled=%FALSE.
+ * It is supposed to return %TRUE if network processing is currently necessary, and
+ * %FALSE if not.
+ * If %FALSE is returned, @timeout_p may be filled with the number of milliseconds
+ * the engine should use for polling at maximum.
+ */
+/**
+ * gsl_job_add_poll
+ * @poll_func: Poll function to add
+ * @data: Data of poll function
+ * @free_func: Function to free @data
+ * @n_fds: Number of poll file descriptors
+ * @fds: File descriptors to select(2) or poll(2) on
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which adds a poll function
+ * to the engine. The poll function is used by the engine to
+ * determine whether processing is currently necessary.
+ */
+GslJob*
+gsl_job_add_poll (GslPollFunc poll_func,
+ gpointer data,
+ GslFreeFunc free_func,
+ guint n_fds,
+ const GPollFD *fds)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (poll_func != NULL, NULL);
+ if (n_fds)
+ g_return_val_if_fail (fds != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_ADD_POLL;
+ job->data.poll.poll_func = poll_func;
+ job->data.poll.data = data;
+ job->data.poll.n_fds = n_fds;
+ job->data.poll.fds = g_memdup (fds, sizeof (fds[0]) * n_fds);
+
+ return job;
+}
+
+/**
+ * gsl_job_remove_poll
+ * @poll_func: Poll function to remove
+ * @data: Data of poll function
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which removes a previously inserted poll
+ * function from the engine.
+ */
+GslJob*
+gsl_job_remove_poll (GslPollFunc poll_func,
+ gpointer data)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (poll_func != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_REMOVE_POLL;
+ job->data.poll.poll_func = poll_func;
+ job->data.poll.data = data;
+ job->data.poll.free_func = NULL;
+ job->data.poll.fds = NULL;
+
+ return job;
+}
+
+/**
+ * gsl_job_debug
+ * @debug: Debug message
+ * @Returns: New job suitable for gsl_trans_add()
+ *
+ * Create a new transaction job which issues @debug message when
+ * the job is executed. This function is meant for debugging purposes
+ * during development phase only and shouldn't be used in production code.
+ */
+GslJob*
+gsl_job_debug (const gchar *debug)
+{
+ GslJob *job;
+
+ g_return_val_if_fail (debug != NULL, NULL);
+
+ job = gsl_new_struct0 (GslJob, 1);
+ job->job_id = ENGINE_JOB_DEBUG;
+ job->data.debug = g_strdup (debug);
+
+ return job;
+}
+
+/**
+ * gsl_trans_open
+ * @Returns: Newly opened empty transaction
+ *
+ * Open up a new transaction to commit jobs to the GSL engine.
+ * This function may cause garbage collection (see
+ * gsl_engine_garbage_collect()).
+ */
+GslTrans*
+gsl_trans_open (void)
+{
+ GslTrans *trans;
+
+ gsl_engine_garbage_collect ();
+
+ trans = gsl_new_struct0 (GslTrans, 1);
+
+ trans->jobs_head = NULL;
+ trans->jobs_tail = NULL;
+ trans->comitted = FALSE;
+ trans->cqt_next = NULL;
+
+ return trans;
+}
+
+/**
+ * gsl_trans_add
+ * @trans: Opened transaction
+ * @job: Job to add
+ *
+ * Append a job to an opened transaction.
+ */
+void
+gsl_trans_add (GslTrans *trans,
+ GslJob *job)
+{
+ g_return_if_fail (trans != NULL);
+ g_return_if_fail (trans->comitted == FALSE);
+ g_return_if_fail (job != NULL);
+ g_return_if_fail (job->next == NULL);
+
+ if (trans->jobs_tail)
+ trans->jobs_tail->next = job;
+ else
+ trans->jobs_head = job;
+ trans->jobs_tail = job;
+}
+
+/**
+ * gsl_trans_commit
+ * @trans: Opened transaction
+ *
+ * Close the transaction and commit it to the engine. The engine
+ * will execute the jobs contained in this transaction as soon as
+ * it has completed its current processing cycle. The jobs will be
+ * executed in the exact order they were added to the transaction.
+ */
+void
+gsl_trans_commit (GslTrans *trans)
+{
+ g_return_if_fail (trans != NULL);
+ g_return_if_fail (trans->comitted == FALSE);
+ g_return_if_fail (trans->cqt_next == NULL);
+
+ if (trans->jobs_head)
+ {
+ trans->comitted = TRUE;
+ _engine_enqueue_trans (trans);
+ wakeup_master ();
+ }
+ else
+ gsl_trans_dismiss (trans);
+}
+
+/**
+ * gsl_trans_dismiss
+ * @trans: Opened transaction
+ *
+ * Close and discard the transaction, destroy all jobs currently
+ * contained in it and do not execute them.
+ * This function may cause garbage collection (see
+ * gsl_engine_garbage_collect()).
+ */
+void
+gsl_trans_dismiss (GslTrans *trans)
+{
+ g_return_if_fail (trans != NULL);
+ g_return_if_fail (trans->comitted == FALSE);
+ g_return_if_fail (trans->cqt_next == NULL);
+
+ _engine_free_trans (trans);
+
+ gsl_engine_garbage_collect ();
+}
+
+/**
+ * gsl_transact
+ * @job: First job
+ * @...: %NULL terminated job list
+ *
+ * Convenience function which openes up a new transaction,
+ * collects the %NULL terminated job list passed to the function,
+ * and commits the transaction.
+ */
+void
+gsl_transact (GslJob *job,
+ ...)
+{
+ GslTrans *trans = gsl_trans_open ();
+ va_list var_args;
+
+ va_start (var_args, job);
+ while (job)
+ {
+ gsl_trans_add (trans, job);
+ job = va_arg (var_args, GslJob*);
+ }
+ va_end (var_args);
+ gsl_trans_commit (trans);
+}
+
+
+/* --- initialization --- */
+static void
+slave (gpointer data)
+{
+ gboolean run = TRUE;
+
+ while (run)
+ {
+ GslTrans *trans = gsl_trans_open ();
+ gchar *str = g_strdup_printf ("SLAVE(%p): idle", g_thread_self ());
+
+ gsl_trans_add (trans, gsl_job_debug (str));
+ g_free (str);
+ gsl_trans_add (trans, gsl_job_debug ("string2"));
+ gsl_trans_commit (trans);
+
+ trans = gsl_trans_open ();
+ gsl_trans_add (trans, gsl_job_debug ("trans2"));
+ gsl_trans_commit (trans);
+
+ g_usleep (1000*500);
+ }
+}
+
+/* --- setup & trigger --- */
+static gboolean gsl_engine_initialized = FALSE;
+static gboolean gsl_engine_threaded = FALSE;
+static GslThread *master_thread = NULL;
+guint gsl_externvar_bsize = 0;
+guint gsl_externvar_sample_freq = 0;
+guint gsl_externvar_sub_sample_mask = 0;
+guint gsl_externvar_sub_sample_steps = 0;
+
+/**
+ * gsl_engine_init
+ * @block_size: number of values to process block wise
+ *
+ * Initialize the GSL engine, this function must be called prior to
+ * any other engine related function and can only be invoked once.
+ * The @block_size determines the amount by which the global tick
+ * stamp (see gsl_tick_stamp()) is updated every time the whole
+ * module network completed processing @block_size values.
+ */
+void
+gsl_engine_init (gboolean run_threaded,
+ guint block_size,
+ guint sample_freq,
+ guint sub_sample_mask)
+{
+ g_return_if_fail (gsl_engine_initialized == FALSE);
+ g_return_if_fail (block_size > 0 && block_size <= GSL_STREAM_MAX_VALUES);
+ g_return_if_fail (sample_freq > 0);
+ g_return_if_fail (sub_sample_mask < block_size);
+ g_return_if_fail ((sub_sample_mask & (sub_sample_mask + 1)) == 0); /* power of 2 */
+
+ gsl_engine_initialized = TRUE;
+ gsl_engine_threaded = run_threaded;
+ gsl_externvar_bsize = block_size;
+ gsl_externvar_sample_freq = sample_freq;
+ gsl_externvar_sub_sample_mask = sub_sample_mask << 2; /* shift out sizeof (float) alignment */
+ gsl_externvar_sub_sample_steps = sub_sample_mask + 1;
+ _gsl_tick_stamp_set_leap (block_size);
+
+ ENG_DEBUG ("initialization: threaded=%s", gsl_engine_threaded ? "TRUE" : "FALSE");
+
+ if (gsl_engine_threaded)
+ {
+ if (!g_thread_supported ()) g_thread_init (NULL);
+ master_thread = gsl_thread_new (_engine_master_thread, NULL);
+ if (0)
+ gsl_thread_new (slave, NULL);
+ }
+}
+
+static void
+wakeup_master (void)
+{
+ if (master_thread)
+ gsl_thread_wakeup (master_thread);
+}
+
+gboolean
+gsl_engine_prepare (GslEngineLoop *loop)
+{
+ g_return_val_if_fail (loop != NULL, FALSE);
+ g_return_val_if_fail (gsl_engine_initialized == TRUE, FALSE);
+
+ if (!gsl_engine_threaded)
+ return _engine_master_prepare (loop);
+ else
+ {
+ loop->timeout = -1;
+ loop->fds_changed = FALSE;
+ loop->n_fds = 0;
+ loop->revents_filled = FALSE;
+ return FALSE;
+ }
+}
+
+gboolean
+gsl_engine_check (const GslEngineLoop *loop)
+{
+ g_return_val_if_fail (loop != NULL, FALSE);
+ if (loop->n_fds)
+ g_return_val_if_fail (loop->revents_filled == TRUE, FALSE);
+
+ if (!gsl_engine_threaded)
+ return _engine_master_check (loop);
+ else
+ return FALSE;
+}
+
+void
+gsl_engine_dispatch (void)
+{
+ g_return_if_fail (gsl_engine_initialized == TRUE);
+
+ if (!gsl_engine_threaded)
+ _engine_master_dispatch ();
+}
+
+/**
+ * gsl_engine_wait_on_trans
+ *
+ * Wait until all pending transactions have been processed
+ * by the GSL Engine.
+ * This function may cause garbage collection (see
+ * gsl_engine_garbage_collect()).
+ */
+void
+gsl_engine_wait_on_trans (void)
+{
+ g_return_if_fail (gsl_engine_initialized == TRUE);
+
+ /* non-threaded */
+ if (!gsl_engine_threaded)
+ _engine_master_dispatch_jobs ();
+
+ /* threaded */
+ _engine_wait_on_trans ();
+
+ /* call all free() functions */
+ gsl_engine_garbage_collect ();
+}
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gslengine.h b/flow/gsl/gslengine.h
new file mode 100644
index 0000000..34f8f80
--- /dev/null
+++ b/flow/gsl/gslengine.h
@@ -0,0 +1,206 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_ENGINE_H__
+#define __GSL_ENGINE_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/* --- constants --- */
+#define GSL_STREAM_MAX_VALUES (8192 /* power of 2, <= 16384 */) /* FIXME */
+#define GSL_MODULE_N_OSTREAMS(module) ((module)->klass->n_ostreams)
+#define GSL_MODULE_N_ISTREAMS(module) ((module)->klass->n_istreams)
+#define GSL_MODULE_N_JSTREAMS(module) ((module)->klass->n_jstreams)
+#define GSL_MODULE_ISTREAM(module, stream) ((module)->istreams[(stream)])
+#define GSL_MODULE_JSTREAM(module, stream) ((module)->jstreams[(stream)])
+#define GSL_MODULE_OSTREAM(module, stream) ((module)->ostreams[(stream)])
+#define GSL_MODULE_IBUFFER(module, stream) (GSL_MODULE_ISTREAM ((module), (stream)).values)
+#define GSL_MODULE_JBUFFER(module, stream, con) (GSL_MODULE_JSTREAM ((module), (stream)).values[con])
+#define GSL_MODULE_OBUFFER(module, stream) (GSL_MODULE_OSTREAM ((module), (stream)).values)
+
+
+/* --- typedefs --- */
+typedef gboolean (*GslPollFunc) (gpointer data,
+ guint n_values,
+ glong *timeout_p,
+ guint n_fds,
+ const GPollFD *fds,
+ gboolean revents_filled);
+typedef void (*GslProcessFunc) (GslModule *module,
+ guint n_values);
+typedef guint (*GslProcessDeferFunc) (GslModule *module,
+ guint n_ivalues,
+ guint n_ovalues);
+typedef void (*GslReconnectFunc) (GslModule *module);
+/* gsldefs.h:
+ * typedef void (*GslAccessFunc) (GslModule *module,
+ * gpointer data);
+ * typedef void (*GslFreeFunc) (gpointer data);
+ * typedef void (*GslModuleFreeFunc) (gpointer data,
+ * const GslClass *klass);
+ */
+typedef enum /*< skip >*/
+{
+ GSL_COST_NORMAL = 0,
+ GSL_COST_CHEAP = 1 << 0,
+ GSL_COST_EXPENSIVE = 1 << 1
+} GslModuleFlags;
+/* class, filled out by user */
+struct _GslClass
+{
+ guint n_istreams;
+ guint n_jstreams;
+ guint n_ostreams;
+ GslProcessFunc process; /* EngineThread */
+ GslProcessDeferFunc process_defer; /* EngineThread */
+ GslReconnectFunc reconnect; /* EngineThread */
+ GslModuleFreeFunc free; /* UserThread */
+ GslModuleFlags mflags;
+};
+/* module, constructed by engine */
+struct _GslModule
+{
+ const GslClass *klass;
+ gpointer user_data;
+ GslIStream *istreams; /* input streams */
+ GslJStream *jstreams; /* joint (multiconnect) input streams */
+ GslOStream *ostreams; /* output streams */
+};
+/* streams, constructed by engine */
+struct _GslJStream
+{
+ const gfloat **values;
+ guint n_connections;
+ guint reserved : 16;
+};
+struct _GslIStream
+{
+ const gfloat *values;
+ guint reserved : 16;
+ guint connected : 1;
+};
+struct _GslOStream
+{
+ gfloat *values;
+ guint sub_sample_pattern : 16;
+ guint connected : 1;
+};
+
+
+/* --- interface (UserThread functions) --- */
+GslModule* gsl_module_new (const GslClass *klass,
+ gpointer user_data);
+guint64 gsl_module_tick_stamp (GslModule *module);
+GslJob* gsl_job_connect (GslModule *src_module,
+ guint src_ostream,
+ GslModule *dest_module,
+ guint dest_istream);
+GslJob* gsl_job_jconnect (GslModule *src_module,
+ guint src_ostream,
+ GslModule *dest_module,
+ guint dest_jstream);
+GslJob* gsl_job_disconnect (GslModule *dest_module,
+ guint dest_istream);
+GslJob* gsl_job_jdisconnect (GslModule *dest_module,
+ guint dest_jstream,
+ GslModule *src_module,
+ guint src_ostream);
+GslJob* gsl_job_integrate (GslModule *module);
+GslJob* gsl_job_discard (GslModule *module);
+GslJob* gsl_job_access (GslModule *module,
+ GslAccessFunc access_func, /* EngineThread */
+ gpointer data,
+ GslFreeFunc free_func); /* UserThread */
+GslJob* gsl_job_set_consumer (GslModule *module,
+ gboolean is_toplevel_consumer);
+GslJob* gsl_job_debug (const gchar *debug);
+GslJob* gsl_job_add_poll (GslPollFunc poll_func,
+ gpointer data,
+ GslFreeFunc free_func,
+ guint n_fds,
+ const GPollFD *fds);
+GslJob* gsl_job_remove_poll (GslPollFunc poll_func,
+ gpointer data);
+GslTrans* gsl_trans_open (void);
+void gsl_trans_add (GslTrans *trans,
+ GslJob *job);
+void gsl_trans_commit (GslTrans *trans);
+void gsl_trans_dismiss (GslTrans *trans);
+void gsl_transact (GslJob *job,
+ ...);
+GslJob* gsl_flow_job_access (GslModule *module,
+ guint64 tick_stamp,
+ GslAccessFunc access_func, /* EngineThread */
+ gpointer data,
+ GslFreeFunc free_func); /* UserThread */
+GslJob* gsl_flow_job_suspend (GslModule *module,
+ guint64 tick_stamp);
+GslJob* gsl_flow_job_resume (GslModule *module,
+ guint64 tick_stamp);
+
+
+/* --- module utilities --- */
+gfloat* gsl_engine_const_values (gfloat value);
+
+
+/* --- initialization & main loop --- */
+void gsl_engine_init (gboolean threaded,
+ guint block_size,
+ guint sample_freq,
+ guint sub_sample_mask);
+typedef struct
+{
+ glong timeout;
+ gboolean fds_changed;
+ guint n_fds;
+ GPollFD *fds;
+ gboolean revents_filled;
+} GslEngineLoop;
+gboolean gsl_engine_prepare (GslEngineLoop *loop);
+gboolean gsl_engine_check (const GslEngineLoop *loop);
+void gsl_engine_dispatch (void);
+
+
+/* --- miscellaneous --- */
+void gsl_engine_garbage_collect (void);
+void gsl_engine_wait_on_trans (void);
+#define gsl_engine_block_size() ((const guint) gsl_externvar_bsize + 0)
+#define gsl_engine_sample_freq() ((const guint) gsl_externvar_sample_freq + 0)
+#define gsl_engine_sub_sample_mask() ((const guint) gsl_externvar_sub_sample_mask + 0)
+#define gsl_engine_sub_sample_steps() ((const guint) gsl_externvar_sub_sample_steps + 0)
+#define gsl_engine_sub_sample_test(ptr) (((guint) (ptr)) & gsl_engine_sub_sample_mask ())
+#define GSL_SUB_SAMPLE_MATCH(ptr,sspatrn) (gsl_engine_sub_sample_test (ptr) == (sspatrn))
+
+
+/*< private >*/
+extern guint gsl_externvar_bsize;
+extern guint gsl_externvar_sample_freq;
+extern guint gsl_externvar_sub_sample_mask;
+extern guint gsl_externvar_sub_sample_steps;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_ENGINE_H__ */
diff --git a/flow/gsl/gslfft.c b/flow/gsl/gslfft.c
new file mode 100644
index 0000000..48f56ef
--- /dev/null
+++ b/flow/gsl/gslfft.c
@@ -0,0 +1,9052 @@
+#include "gslfft.h"
+#include <math.h>
+
+#define BUTTERFLY_XY(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = X2re * Wre; \
+ T1im = X2im * Wre; \
+ T2re = X2im * Wim; \
+ T2im = X2re * Wim; \
+ T1re -= T2re; \
+ T1im += T2im; \
+ T2re = X1re - T1re; \
+ T2im = X1im - T1im; \
+ Y1re = X1re + T1re; \
+ Y1im = X1im + T1im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_Yx(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = X2re * Wim; \
+ T1im = X2im * Wim; \
+ T2re = X2im * Wre; \
+ T2im = X2re * Wre; \
+ T1re += T2re; \
+ T1im -= T2im; \
+ T2re = X1re + T1re; \
+ T2im = X1im + T1im; \
+ Y1re = X1re - T1re; \
+ Y1im = X1im - T1im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_yX(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = X2re * Wim; \
+ T1im = X2im * Wim; \
+ T2re = X2im * Wre; \
+ T2im = X2re * Wre; \
+ T1re += T2re; \
+ T1im -= T2im; \
+ T2re = X1re - T1re; \
+ T2im = X1im - T1im; \
+ Y1re = X1re + T1re; \
+ Y1im = X1im + T1im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_10(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \
+ register double T2re, T2im; \
+ T2re = X1re - X2re; \
+ T2im = X1im - X2im; \
+ Y1re = X1re + X2re; \
+ Y1im = X1im + X2im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_01(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \
+ register double T2re, T2im; \
+ T2re = X1re + X2im; \
+ T2im = X1im - X2re; \
+ Y1re = X1re - X2im; \
+ Y1im = X1im + X2re; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_0m(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \
+ register double T2re, T2im; \
+ T2re = X1re - X2im; \
+ T2im = X1im + X2re; \
+ Y1re = X1re + X2im; \
+ Y1im = X1im - X2re; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_XX(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,_2) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = X2re * Wre; \
+ T1im = X2im * Wre; \
+ T2re = T1im; \
+ T2im = T1re; \
+ T1re -= T2re; \
+ T1im += T2im; \
+ T2re = X1re - T1re; \
+ T2im = X1im - T1im; \
+ Y1re = X1re + T1re; \
+ Y1im = X1im + T1im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_yY(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,_2) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = X2re * Wre; \
+ T1im = X2im * Wre; \
+ T2re = T1im; \
+ T2im = T1re; \
+ T1re += T2re; \
+ T1im -= T2im; \
+ T2re = X1re - T1re; \
+ T2im = X1im - T1im; \
+ Y1re = X1re + T1re; \
+ Y1im = X1im + T1im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_10scale(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,S) { \
+ register double T2re, T2im; \
+ T2re = X1re - X2re; \
+ T2im = X1im - X2im; \
+ Y1re = X1re + X2re; \
+ Y1im = X1im + X2im; \
+ Y2re = T2re * S; \
+ Y2im = T2im * S; \
+ Y1re *= S; \
+ Y1im *= S; \
+}
+
+#define WMULTIPLY(Wre,Wim,Dre,Dim) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = Wre * Dre; \
+ T1im = Wim * Dre; \
+ T2re = Wim * Dim; \
+ T2im = Wre * Dim; \
+ T1re -= T2re; \
+ T1im += T2im; \
+ Wre += T1re; \
+ Wim += T1im; \
+}
+static inline void
+bitreverse_fft2analysis (const unsigned int n,
+ const double *X,
+ double *Y)
+{
+ const unsigned int n2 = n >> 1, n1 = n + n2, max = n >> 2;
+ unsigned int i, r;
+
+ BUTTERFLY_10 (X[0], X[1],
+ X[n], X[n + 1],
+ Y[0], Y[1],
+ Y[2], Y[3],
+ __1, __0);
+ BUTTERFLY_10 (X[n2], X[n2 + 1],
+ X[n1], X[n1 + 1],
+ Y[4], Y[5],
+ Y[6], Y[7],
+ __1, __0);
+ for (i = 1, r = 0; i < max; i++)
+ {
+ unsigned int k, j = n >> 1;
+
+ while (r >= j)
+ {
+ r -= j;
+ j >>= 1;
+ }
+ r |= j;
+
+ k = r >> 1;
+ j = i << 3;
+ BUTTERFLY_10 (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ __1, __0);
+ k += n2;
+ j += 4;
+ BUTTERFLY_10 (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ __1, __0);
+ }
+}
+static inline void
+bitreverse_fft2synthesis (const unsigned int n,
+ const double *X,
+ double *Y)
+{
+ const unsigned int n2 = n >> 1, n1 = n + n2, max = n >> 2;
+ unsigned int i, r;
+ double scale = n;
+
+ scale = 1.0 / scale;
+ BUTTERFLY_10scale (X[0], X[1],
+ X[n], X[n + 1],
+ Y[0], Y[1],
+ Y[2], Y[3],
+ scale);
+ BUTTERFLY_10scale (X[n2], X[n2 + 1],
+ X[n1], X[n1 + 1],
+ Y[4], Y[5],
+ Y[6], Y[7],
+ scale);
+ for (i = 1, r = 0; i < max; i++)
+ {
+ unsigned int k, j = n >> 1;
+
+ while (r >= j)
+ {
+ r -= j;
+ j >>= 1;
+ }
+ r |= j;
+
+ k = r >> 1;
+ j = i << 3;
+ BUTTERFLY_10scale (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ scale);
+ k += n2;
+ j += 4;
+ BUTTERFLY_10scale (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ scale);
+ }
+}
+/**
+ ** Generated data (by gsl-genfft 2 F)
+ **/
+static void
+gsl_power2_fft2analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 1 times fft2 */
+ BUTTERFLY_10 (X[0], X[0 + 1],
+ X[2], X[2 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ __1, __0);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4 S F)
+ **/
+static void
+gsl_power2_fft4analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 2 times fft2 */
+
+ /* perform 1 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_01 (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4 F X)
+ **/
+static void
+gsl_power2_fft4analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 2 times fft2 */
+ BUTTERFLY_10 (X[0], X[0 + 1],
+ X[4], X[4 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[2], X[2 + 1],
+ X[6], X[6 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ __1, __0);
+
+ /* perform 1 times fft4 */
+ gsl_power2_fft4analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8 S F F)
+ **/
+static void
+gsl_power2_fft8analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 4 times fft2 */
+
+ /* perform 2 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[8], /* W0 */
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_01 (Y[2], /* W2 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[10], /* W2 */
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+
+ /* perform 1 times fft8 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XX (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_01 (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_yY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8 F S X)
+ **/
+static void
+gsl_power2_fft8analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 4 times fft2 */
+ BUTTERFLY_10 (X[0], X[0 + 1],
+ X[8], X[8 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[4], X[4 + 1],
+ X[12], X[12 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[2], X[2 + 1],
+ X[10], X[10 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[6], X[6 + 1],
+ X[14], X[14 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ __1, __0);
+
+ /* skipping 2 times fft4 */
+
+ /* perform 1 times fft8 */
+ gsl_power2_fft8analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 16 S F F F)
+ **/
+static void
+gsl_power2_fft16analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 8 times fft2 */
+
+ /* perform 4 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[8], /* W0 */
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[24], /* W0 */
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_01 (Y[2], /* W4 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[10], /* W4 */
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[18], /* W4 */
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[26], /* W4 */
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+
+ /* perform 2 times fft8 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XX (Y[2], /* W2 */
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XX (Y[18], /* W2 */
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_01 (Y[4], /* W4 */
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[20], /* W4 */
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_yY (Y[6], /* W6 */
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_yY (Y[22], /* W6 */
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+
+ /* perform 1 times fft16 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XX (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_01 (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_yY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 16 F S S X)
+ **/
+static void
+gsl_power2_fft16analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 8 times fft2 */
+ BUTTERFLY_10 (X[0], X[0 + 1],
+ X[16], X[16 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[8], X[8 + 1],
+ X[24], X[24 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[4], X[4 + 1],
+ X[20], X[20 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[12], X[12 + 1],
+ X[28], X[28 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[2], X[2 + 1],
+ X[18], X[18 + 1],
+ Y[16], Y[16 + 1],
+ Y[18], Y[18 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[10], X[10 + 1],
+ X[26], X[26 + 1],
+ Y[20], Y[20 + 1],
+ Y[22], Y[22 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[6], X[6 + 1],
+ X[22], X[22 + 1],
+ Y[24], Y[24 + 1],
+ Y[26], Y[26 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[14], X[14 + 1],
+ X[30], X[30 + 1],
+ Y[28], Y[28 + 1],
+ Y[30], Y[30 + 1],
+ __1, __0);
+
+ /* skipping 4 times fft4 */
+
+ /* skipping 2 times fft8 */
+
+ /* perform 1 times fft16 */
+ gsl_power2_fft16analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 32 S F F F F)
+ **/
+static void
+gsl_power2_fft32analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 16 times fft2 */
+
+ /* perform 8 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[8], /* W0 */
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[24], /* W0 */
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[32], /* W0 */
+ Y[32 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[36],
+ Y[36 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[40], /* W0 */
+ Y[40 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[44],
+ Y[44 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[48], /* W0 */
+ Y[48 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[52],
+ Y[52 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[56], /* W0 */
+ Y[56 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_01 (Y[2], /* W8 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[10], /* W8 */
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[18], /* W8 */
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[26], /* W8 */
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[34], /* W8 */
+ Y[34 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[38],
+ Y[38 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[42], /* W8 */
+ Y[42 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[46],
+ Y[46 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[50], /* W8 */
+ Y[50 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[54],
+ Y[54 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[58], /* W8 */
+ Y[58 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+
+ /* perform 4 times fft8 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[32], /* W0 */
+ Y[32 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[40],
+ Y[40 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[48], /* W0 */
+ Y[48 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[56],
+ Y[56 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XX (Y[2], /* W4 */
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XX (Y[18], /* W4 */
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XX (Y[34], /* W4 */
+ Y[34 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[42],
+ Y[42 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XX (Y[50], /* W4 */
+ Y[50 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[58],
+ Y[58 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_01 (Y[4], /* W8 */
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[20], /* W8 */
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[36], /* W8 */
+ Y[36 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[44],
+ Y[44 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[52], /* W8 */
+ Y[52 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_yY (Y[6], /* W12 */
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_yY (Y[22], /* W12 */
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_yY (Y[38], /* W12 */
+ Y[38 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[46],
+ Y[46 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_yY (Y[54], /* W12 */
+ Y[54 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+
+ /* perform 2 times fft16 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[32], /* W0 */
+ Y[32 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[48],
+ Y[48 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W2 */
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[34], /* W2 */
+ Y[34 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[50],
+ Y[50 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XX (Y[4], /* W4 */
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XX (Y[36], /* W4 */
+ Y[36 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[52],
+ Y[52 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[6], /* W6 */
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[38], /* W6 */
+ Y[38 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[54],
+ Y[54 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_01 (Y[8], /* W8 */
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_01 (Y[40], /* W8 */
+ Y[40 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[56],
+ Y[56 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[10], /* W10 */
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[42], /* W10 */
+ Y[42 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[58],
+ Y[58 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_yY (Y[12], /* W12 */
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_yY (Y[44], /* W12 */
+ Y[44 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[14], /* W14 */
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[46], /* W14 */
+ Y[46 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+
+ /* perform 1 times fft32 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[32],
+ Y[32 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[34],
+ Y[34 + 1],
+ (double) +0.980785280403230, (double) +0.195090322016128);
+ BUTTERFLY_XY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[36],
+ Y[36 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[38],
+ Y[38 + 1],
+ (double) +0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XX (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[40],
+ Y[40 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[42],
+ Y[42 + 1],
+ (double) +0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[44],
+ Y[44 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[46],
+ Y[46 + 1],
+ (double) +0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_01 (Y[16], /* W8 */
+ Y[16 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[48],
+ Y[48 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[18], /* W9 */
+ Y[18 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[50],
+ Y[50 + 1],
+ (double) -0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[20], /* W10 */
+ Y[20 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[52],
+ Y[52 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[22], /* W11 */
+ Y[22 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[54],
+ Y[54 + 1],
+ (double) -0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_yY (Y[24], /* W12 */
+ Y[24 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[56],
+ Y[56 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[26], /* W13 */
+ Y[26 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[58],
+ Y[58 + 1],
+ (double) -0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[28], /* W14 */
+ Y[28 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[30], /* W15 */
+ Y[30 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) -0.980785280403230, (double) +0.195090322016129);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 32 F S S S X)
+ **/
+static void
+gsl_power2_fft32analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 16 times fft2 */
+ BUTTERFLY_10 (X[0], X[0 + 1],
+ X[32], X[32 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[16], X[16 + 1],
+ X[48], X[48 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[8], X[8 + 1],
+ X[40], X[40 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[24], X[24 + 1],
+ X[56], X[56 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[4], X[4 + 1],
+ X[36], X[36 + 1],
+ Y[16], Y[16 + 1],
+ Y[18], Y[18 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[20], X[20 + 1],
+ X[52], X[52 + 1],
+ Y[20], Y[20 + 1],
+ Y[22], Y[22 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[12], X[12 + 1],
+ X[44], X[44 + 1],
+ Y[24], Y[24 + 1],
+ Y[26], Y[26 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[28], X[28 + 1],
+ X[60], X[60 + 1],
+ Y[28], Y[28 + 1],
+ Y[30], Y[30 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[2], X[2 + 1],
+ X[34], X[34 + 1],
+ Y[32], Y[32 + 1],
+ Y[34], Y[34 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[18], X[18 + 1],
+ X[50], X[50 + 1],
+ Y[36], Y[36 + 1],
+ Y[38], Y[38 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[10], X[10 + 1],
+ X[42], X[42 + 1],
+ Y[40], Y[40 + 1],
+ Y[42], Y[42 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[26], X[26 + 1],
+ X[58], X[58 + 1],
+ Y[44], Y[44 + 1],
+ Y[46], Y[46 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[6], X[6 + 1],
+ X[38], X[38 + 1],
+ Y[48], Y[48 + 1],
+ Y[50], Y[50 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[22], X[22 + 1],
+ X[54], X[54 + 1],
+ Y[52], Y[52 + 1],
+ Y[54], Y[54 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[14], X[14 + 1],
+ X[46], X[46 + 1],
+ Y[56], Y[56 + 1],
+ Y[58], Y[58 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[30], X[30 + 1],
+ X[62], X[62 + 1],
+ Y[60], Y[60 + 1],
+ Y[62], Y[62 + 1],
+ __1, __0);
+
+ /* skipping 8 times fft4 */
+
+ /* skipping 4 times fft8 */
+
+ /* skipping 2 times fft16 */
+
+ /* perform 1 times fft32 */
+ gsl_power2_fft32analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 64 S R R R R F)
+ **/
+static void
+gsl_power2_fft64analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 32 times fft2 */
+
+ /* perform 16 times fft4 */
+ for (block = 0; block < 128; block += 8) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_01 (Y[block + 2], /* W16 */
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ }
+
+ /* perform 8 times fft8 */
+ for (block = 0; block < 128; block += 16) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XX (Y[block + 2], /* W8 */
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_01 (Y[block + 4], /* W16 */
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_yY (Y[block + 6], /* W24 */
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ }
+
+ /* perform 4 times fft16 */
+ for (block = 0; block < 128; block += 32) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W4 */
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XX (Y[block + 4], /* W8 */
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[block + 6], /* W12 */
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_01 (Y[block + 8], /* W16 */
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[block + 10], /* W20 */
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_yY (Y[block + 12], /* W24 */
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[block + 14], /* W28 */
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ }
+
+ /* perform 2 times fft32 */
+ for (block = 0; block < 128; block += 64) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W2 */
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ (double) +0.980785280403230, (double) +0.195090322016128);
+ BUTTERFLY_XY (Y[block + 4], /* W4 */
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[block + 6], /* W6 */
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ (double) +0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XX (Y[block + 8], /* W8 */
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[block + 10], /* W10 */
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ (double) +0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[block + 12], /* W12 */
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[block + 14], /* W14 */
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ (double) +0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_01 (Y[block + 16], /* W16 */
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[block + 18], /* W18 */
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ (double) -0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[block + 20], /* W20 */
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[block + 22], /* W22 */
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ (double) -0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_yY (Y[block + 24], /* W24 */
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[block + 26], /* W26 */
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ (double) -0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[block + 28], /* W28 */
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[block + 30], /* W30 */
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ (double) -0.980785280403230, (double) +0.195090322016129);
+ }
+
+ /* perform 1 times fft64 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[64],
+ Y[64 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[64],
+ Y[64 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[66],
+ Y[66 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[66],
+ Y[66 + 1],
+ (double) +0.995184726672197, (double) +0.098017140329561);
+ BUTTERFLY_XY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[68],
+ Y[68 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[68],
+ Y[68 + 1],
+ (double) +0.980785280403230, (double) +0.195090322016128);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[70],
+ Y[70 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[70],
+ Y[70 + 1],
+ (double) +0.956940335732209, (double) +0.290284677254462);
+ BUTTERFLY_XY (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[72],
+ Y[72 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[72],
+ Y[72 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[74],
+ Y[74 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[74],
+ Y[74 + 1],
+ (double) +0.881921264348355, (double) +0.471396736825998);
+ BUTTERFLY_XY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[76],
+ Y[76 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[76],
+ Y[76 + 1],
+ (double) +0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[78],
+ Y[78 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[78],
+ Y[78 + 1],
+ (double) +0.773010453362737, (double) +0.634393284163645);
+ BUTTERFLY_XX (Y[16], /* W8 */
+ Y[16 + 1],
+ Y[80],
+ Y[80 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[80],
+ Y[80 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[18], /* W9 */
+ Y[18 + 1],
+ Y[82],
+ Y[82 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[82],
+ Y[82 + 1],
+ (double) +0.634393284163645, (double) +0.773010453362737);
+ BUTTERFLY_XY (Y[20], /* W10 */
+ Y[20 + 1],
+ Y[84],
+ Y[84 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[84],
+ Y[84 + 1],
+ (double) +0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[22], /* W11 */
+ Y[22 + 1],
+ Y[86],
+ Y[86 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[86],
+ Y[86 + 1],
+ (double) +0.471396736825998, (double) +0.881921264348355);
+ BUTTERFLY_XY (Y[24], /* W12 */
+ Y[24 + 1],
+ Y[88],
+ Y[88 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[88],
+ Y[88 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[26], /* W13 */
+ Y[26 + 1],
+ Y[90],
+ Y[90 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[90],
+ Y[90 + 1],
+ (double) +0.290284677254462, (double) +0.956940335732209);
+ BUTTERFLY_XY (Y[28], /* W14 */
+ Y[28 + 1],
+ Y[92],
+ Y[92 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[92],
+ Y[92 + 1],
+ (double) +0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[30], /* W15 */
+ Y[30 + 1],
+ Y[94],
+ Y[94 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[94],
+ Y[94 + 1],
+ (double) +0.098017140329561, (double) +0.995184726672197);
+ BUTTERFLY_01 (Y[32], /* W16 */
+ Y[32 + 1],
+ Y[96],
+ Y[96 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[96],
+ Y[96 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[34], /* W17 */
+ Y[34 + 1],
+ Y[98],
+ Y[98 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[98],
+ Y[98 + 1],
+ (double) -0.098017140329561, (double) +0.995184726672197);
+ BUTTERFLY_XY (Y[36], /* W18 */
+ Y[36 + 1],
+ Y[100],
+ Y[100 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[100],
+ Y[100 + 1],
+ (double) -0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[38], /* W19 */
+ Y[38 + 1],
+ Y[102],
+ Y[102 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[102],
+ Y[102 + 1],
+ (double) -0.290284677254462, (double) +0.956940335732209);
+ BUTTERFLY_XY (Y[40], /* W20 */
+ Y[40 + 1],
+ Y[104],
+ Y[104 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[104],
+ Y[104 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[42], /* W21 */
+ Y[42 + 1],
+ Y[106],
+ Y[106 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[106],
+ Y[106 + 1],
+ (double) -0.471396736825998, (double) +0.881921264348355);
+ BUTTERFLY_XY (Y[44], /* W22 */
+ Y[44 + 1],
+ Y[108],
+ Y[108 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[108],
+ Y[108 + 1],
+ (double) -0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[46], /* W23 */
+ Y[46 + 1],
+ Y[110],
+ Y[110 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[110],
+ Y[110 + 1],
+ (double) -0.634393284163645, (double) +0.773010453362737);
+ BUTTERFLY_yY (Y[48], /* W24 */
+ Y[48 + 1],
+ Y[112],
+ Y[112 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[112],
+ Y[112 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[50], /* W25 */
+ Y[50 + 1],
+ Y[114],
+ Y[114 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[114],
+ Y[114 + 1],
+ (double) -0.773010453362737, (double) +0.634393284163645);
+ BUTTERFLY_XY (Y[52], /* W26 */
+ Y[52 + 1],
+ Y[116],
+ Y[116 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[116],
+ Y[116 + 1],
+ (double) -0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[54], /* W27 */
+ Y[54 + 1],
+ Y[118],
+ Y[118 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[118],
+ Y[118 + 1],
+ (double) -0.881921264348355, (double) +0.471396736825998);
+ BUTTERFLY_XY (Y[56], /* W28 */
+ Y[56 + 1],
+ Y[120],
+ Y[120 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[120],
+ Y[120 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[58], /* W29 */
+ Y[58 + 1],
+ Y[122],
+ Y[122 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[122],
+ Y[122 + 1],
+ (double) -0.956940335732209, (double) +0.290284677254462);
+ BUTTERFLY_XY (Y[60], /* W30 */
+ Y[60 + 1],
+ Y[124],
+ Y[124 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[124],
+ Y[124 + 1],
+ (double) -0.980785280403230, (double) +0.195090322016129);
+ BUTTERFLY_XY (Y[62], /* W31 */
+ Y[62 + 1],
+ Y[126],
+ Y[126 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[126],
+ Y[126 + 1],
+ (double) -0.995184726672197, (double) +0.098017140329561);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 64 F S S S S X)
+ **/
+static void
+gsl_power2_fft64analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 32 times fft2 */
+ BUTTERFLY_10 (X[0], X[0 + 1],
+ X[64], X[64 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[32], X[32 + 1],
+ X[96], X[96 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[16], X[16 + 1],
+ X[80], X[80 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[48], X[48 + 1],
+ X[112], X[112 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[8], X[8 + 1],
+ X[72], X[72 + 1],
+ Y[16], Y[16 + 1],
+ Y[18], Y[18 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[40], X[40 + 1],
+ X[104], X[104 + 1],
+ Y[20], Y[20 + 1],
+ Y[22], Y[22 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[24], X[24 + 1],
+ X[88], X[88 + 1],
+ Y[24], Y[24 + 1],
+ Y[26], Y[26 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[56], X[56 + 1],
+ X[120], X[120 + 1],
+ Y[28], Y[28 + 1],
+ Y[30], Y[30 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[4], X[4 + 1],
+ X[68], X[68 + 1],
+ Y[32], Y[32 + 1],
+ Y[34], Y[34 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[36], X[36 + 1],
+ X[100], X[100 + 1],
+ Y[36], Y[36 + 1],
+ Y[38], Y[38 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[20], X[20 + 1],
+ X[84], X[84 + 1],
+ Y[40], Y[40 + 1],
+ Y[42], Y[42 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[52], X[52 + 1],
+ X[116], X[116 + 1],
+ Y[44], Y[44 + 1],
+ Y[46], Y[46 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[12], X[12 + 1],
+ X[76], X[76 + 1],
+ Y[48], Y[48 + 1],
+ Y[50], Y[50 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[44], X[44 + 1],
+ X[108], X[108 + 1],
+ Y[52], Y[52 + 1],
+ Y[54], Y[54 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[28], X[28 + 1],
+ X[92], X[92 + 1],
+ Y[56], Y[56 + 1],
+ Y[58], Y[58 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[60], X[60 + 1],
+ X[124], X[124 + 1],
+ Y[60], Y[60 + 1],
+ Y[62], Y[62 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[2], X[2 + 1],
+ X[66], X[66 + 1],
+ Y[64], Y[64 + 1],
+ Y[66], Y[66 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[34], X[34 + 1],
+ X[98], X[98 + 1],
+ Y[68], Y[68 + 1],
+ Y[70], Y[70 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[18], X[18 + 1],
+ X[82], X[82 + 1],
+ Y[72], Y[72 + 1],
+ Y[74], Y[74 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[50], X[50 + 1],
+ X[114], X[114 + 1],
+ Y[76], Y[76 + 1],
+ Y[78], Y[78 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[10], X[10 + 1],
+ X[74], X[74 + 1],
+ Y[80], Y[80 + 1],
+ Y[82], Y[82 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[42], X[42 + 1],
+ X[106], X[106 + 1],
+ Y[84], Y[84 + 1],
+ Y[86], Y[86 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[26], X[26 + 1],
+ X[90], X[90 + 1],
+ Y[88], Y[88 + 1],
+ Y[90], Y[90 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[58], X[58 + 1],
+ X[122], X[122 + 1],
+ Y[92], Y[92 + 1],
+ Y[94], Y[94 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[6], X[6 + 1],
+ X[70], X[70 + 1],
+ Y[96], Y[96 + 1],
+ Y[98], Y[98 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[38], X[38 + 1],
+ X[102], X[102 + 1],
+ Y[100], Y[100 + 1],
+ Y[102], Y[102 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[22], X[22 + 1],
+ X[86], X[86 + 1],
+ Y[104], Y[104 + 1],
+ Y[106], Y[106 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[54], X[54 + 1],
+ X[118], X[118 + 1],
+ Y[108], Y[108 + 1],
+ Y[110], Y[110 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[14], X[14 + 1],
+ X[78], X[78 + 1],
+ Y[112], Y[112 + 1],
+ Y[114], Y[114 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[46], X[46 + 1],
+ X[110], X[110 + 1],
+ Y[116], Y[116 + 1],
+ Y[118], Y[118 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[30], X[30 + 1],
+ X[94], X[94 + 1],
+ Y[120], Y[120 + 1],
+ Y[122], Y[122 + 1],
+ __1, __0);
+ BUTTERFLY_10 (X[62], X[62 + 1],
+ X[126], X[126 + 1],
+ Y[124], Y[124 + 1],
+ Y[126], Y[126 + 1],
+ __1, __0);
+
+ /* skipping 16 times fft4 */
+
+ /* skipping 8 times fft8 */
+
+ /* skipping 4 times fft16 */
+
+ /* skipping 2 times fft32 */
+
+ /* perform 1 times fft64 */
+ gsl_power2_fft64analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 128 S R R R R R F)
+ **/
+static void
+gsl_power2_fft128analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 64 times fft2 */
+
+ /* perform 32 times fft4 */
+ for (block = 0; block < 256; block += 8) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_01 (Y[block + 2], /* W32 */
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ }
+
+ /* perform 16 times fft8 */
+ for (block = 0; block < 256; block += 16) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XX (Y[block + 2], /* W16 */
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_01 (Y[block + 4], /* W32 */
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_yY (Y[block + 6], /* W48 */
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ }
+
+ /* perform 8 times fft16 */
+ for (block = 0; block < 256; block += 32) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W8 */
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XX (Y[block + 4], /* W16 */
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[block + 6], /* W24 */
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_01 (Y[block + 8], /* W32 */
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[block + 10], /* W40 */
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_yY (Y[block + 12], /* W48 */
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[block + 14], /* W56 */
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ }
+
+ /* perform 4 times fft32 */
+ for (block = 0; block < 256; block += 64) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W4 */
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ (double) +0.980785280403230, (double) +0.195090322016128);
+ BUTTERFLY_XY (Y[block + 4], /* W8 */
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[block + 6], /* W12 */
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ (double) +0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XX (Y[block + 8], /* W16 */
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[block + 10], /* W20 */
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ (double) +0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[block + 12], /* W24 */
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[block + 14], /* W28 */
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ (double) +0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_01 (Y[block + 16], /* W32 */
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[block + 18], /* W36 */
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ (double) -0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[block + 20], /* W40 */
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[block + 22], /* W44 */
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ (double) -0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_yY (Y[block + 24], /* W48 */
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[block + 26], /* W52 */
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ (double) -0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[block + 28], /* W56 */
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[block + 30], /* W60 */
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ (double) -0.980785280403230, (double) +0.195090322016129);
+ }
+
+ /* perform 2 times fft64 */
+ for (block = 0; block < 256; block += 128) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 64],
+ Y[block + 64 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 64],
+ Y[block + 64 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W2 */
+ Y[block + 2 + 1],
+ Y[block + 66],
+ Y[block + 66 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 66],
+ Y[block + 66 + 1],
+ (double) +0.995184726672197, (double) +0.098017140329561);
+ BUTTERFLY_XY (Y[block + 4], /* W4 */
+ Y[block + 4 + 1],
+ Y[block + 68],
+ Y[block + 68 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 68],
+ Y[block + 68 + 1],
+ (double) +0.980785280403230, (double) +0.195090322016128);
+ BUTTERFLY_XY (Y[block + 6], /* W6 */
+ Y[block + 6 + 1],
+ Y[block + 70],
+ Y[block + 70 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 70],
+ Y[block + 70 + 1],
+ (double) +0.956940335732209, (double) +0.290284677254462);
+ BUTTERFLY_XY (Y[block + 8], /* W8 */
+ Y[block + 8 + 1],
+ Y[block + 72],
+ Y[block + 72 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 72],
+ Y[block + 72 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[block + 10], /* W10 */
+ Y[block + 10 + 1],
+ Y[block + 74],
+ Y[block + 74 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 74],
+ Y[block + 74 + 1],
+ (double) +0.881921264348355, (double) +0.471396736825998);
+ BUTTERFLY_XY (Y[block + 12], /* W12 */
+ Y[block + 12 + 1],
+ Y[block + 76],
+ Y[block + 76 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 76],
+ Y[block + 76 + 1],
+ (double) +0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[block + 14], /* W14 */
+ Y[block + 14 + 1],
+ Y[block + 78],
+ Y[block + 78 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 78],
+ Y[block + 78 + 1],
+ (double) +0.773010453362737, (double) +0.634393284163645);
+ BUTTERFLY_XX (Y[block + 16], /* W16 */
+ Y[block + 16 + 1],
+ Y[block + 80],
+ Y[block + 80 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 80],
+ Y[block + 80 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[block + 18], /* W18 */
+ Y[block + 18 + 1],
+ Y[block + 82],
+ Y[block + 82 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 82],
+ Y[block + 82 + 1],
+ (double) +0.634393284163645, (double) +0.773010453362737);
+ BUTTERFLY_XY (Y[block + 20], /* W20 */
+ Y[block + 20 + 1],
+ Y[block + 84],
+ Y[block + 84 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 84],
+ Y[block + 84 + 1],
+ (double) +0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[block + 22], /* W22 */
+ Y[block + 22 + 1],
+ Y[block + 86],
+ Y[block + 86 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 86],
+ Y[block + 86 + 1],
+ (double) +0.471396736825998, (double) +0.881921264348355);
+ BUTTERFLY_XY (Y[block + 24], /* W24 */
+ Y[block + 24 + 1],
+ Y[block + 88],
+ Y[block + 88 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 88],
+ Y[block + 88 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[block + 26], /* W26 */
+ Y[block + 26 + 1],
+ Y[block + 90],
+ Y[block + 90 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 90],
+ Y[block + 90 + 1],
+ (double) +0.290284677254462, (double) +0.956940335732209);
+ BUTTERFLY_XY (Y[block + 28], /* W28 */
+ Y[block + 28 + 1],
+ Y[block + 92],
+ Y[block + 92 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 92],
+ Y[block + 92 + 1],
+ (double) +0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[block + 30], /* W30 */
+ Y[block + 30 + 1],
+ Y[block + 94],
+ Y[block + 94 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 94],
+ Y[block + 94 + 1],
+ (double) +0.098017140329561, (double) +0.995184726672197);
+ BUTTERFLY_01 (Y[block + 32], /* W32 */
+ Y[block + 32 + 1],
+ Y[block + 96],
+ Y[block + 96 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ Y[block + 96],
+ Y[block + 96 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[block + 34], /* W34 */
+ Y[block + 34 + 1],
+ Y[block + 98],
+ Y[block + 98 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ Y[block + 98],
+ Y[block + 98 + 1],
+ (double) -0.098017140329561, (double) +0.995184726672197);
+ BUTTERFLY_XY (Y[block + 36], /* W36 */
+ Y[block + 36 + 1],
+ Y[block + 100],
+ Y[block + 100 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ Y[block + 100],
+ Y[block + 100 + 1],
+ (double) -0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[block + 38], /* W38 */
+ Y[block + 38 + 1],
+ Y[block + 102],
+ Y[block + 102 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ Y[block + 102],
+ Y[block + 102 + 1],
+ (double) -0.290284677254462, (double) +0.956940335732209);
+ BUTTERFLY_XY (Y[block + 40], /* W40 */
+ Y[block + 40 + 1],
+ Y[block + 104],
+ Y[block + 104 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ Y[block + 104],
+ Y[block + 104 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[block + 42], /* W42 */
+ Y[block + 42 + 1],
+ Y[block + 106],
+ Y[block + 106 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ Y[block + 106],
+ Y[block + 106 + 1],
+ (double) -0.471396736825998, (double) +0.881921264348355);
+ BUTTERFLY_XY (Y[block + 44], /* W44 */
+ Y[block + 44 + 1],
+ Y[block + 108],
+ Y[block + 108 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ Y[block + 108],
+ Y[block + 108 + 1],
+ (double) -0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[block + 46], /* W46 */
+ Y[block + 46 + 1],
+ Y[block + 110],
+ Y[block + 110 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ Y[block + 110],
+ Y[block + 110 + 1],
+ (double) -0.634393284163645, (double) +0.773010453362737);
+ BUTTERFLY_yY (Y[block + 48], /* W48 */
+ Y[block + 48 + 1],
+ Y[block + 112],
+ Y[block + 112 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ Y[block + 112],
+ Y[block + 112 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[block + 50], /* W50 */
+ Y[block + 50 + 1],
+ Y[block + 114],
+ Y[block + 114 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ Y[block + 114],
+ Y[block + 114 + 1],
+ (double) -0.773010453362737, (double) +0.634393284163645);
+ BUTTERFLY_XY (Y[block + 52], /* W52 */
+ Y[block + 52 + 1],
+ Y[block + 116],
+ Y[block + 116 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ Y[block + 116],
+ Y[block + 116 + 1],
+ (double) -0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[block + 54], /* W54 */
+ Y[block + 54 + 1],
+ Y[block + 118],
+ Y[block + 118 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ Y[block + 118],
+ Y[block + 118 + 1],
+ (double) -0.881921264348355, (double) +0.471396736825998);
+ BUTTERFLY_XY (Y[block + 56], /* W56 */
+ Y[block + 56 + 1],
+ Y[block + 120],
+ Y[block + 120 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ Y[block + 120],
+ Y[block + 120 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[block + 58], /* W58 */
+ Y[block + 58 + 1],
+ Y[block + 122],
+ Y[block + 122 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ Y[block + 122],
+ Y[block + 122 + 1],
+ (double) -0.956940335732209, (double) +0.290284677254462);
+ BUTTERFLY_XY (Y[block + 60], /* W60 */
+ Y[block + 60 + 1],
+ Y[block + 124],
+ Y[block + 124 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ Y[block + 124],
+ Y[block + 124 + 1],
+ (double) -0.980785280403230, (double) +0.195090322016129);
+ BUTTERFLY_XY (Y[block + 62], /* W62 */
+ Y[block + 62 + 1],
+ Y[block + 126],
+ Y[block + 126 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ Y[block + 126],
+ Y[block + 126 + 1],
+ (double) -0.995184726672197, (double) +0.098017140329561);
+ }
+
+ /* perform 1 times fft128 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[128],
+ Y[128 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[128],
+ Y[128 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[130],
+ Y[130 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[130],
+ Y[130 + 1],
+ (double) +0.998795456205172, (double) +0.049067674327418);
+ BUTTERFLY_XY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[132],
+ Y[132 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[132],
+ Y[132 + 1],
+ (double) +0.995184726672197, (double) +0.098017140329561);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[134],
+ Y[134 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[134],
+ Y[134 + 1],
+ (double) +0.989176509964781, (double) +0.146730474455362);
+ BUTTERFLY_XY (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[136],
+ Y[136 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[136],
+ Y[136 + 1],
+ (double) +0.980785280403230, (double) +0.195090322016128);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[138],
+ Y[138 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[138],
+ Y[138 + 1],
+ (double) +0.970031253194544, (double) +0.242980179903264);
+ BUTTERFLY_XY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[140],
+ Y[140 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[140],
+ Y[140 + 1],
+ (double) +0.956940335732209, (double) +0.290284677254462);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[142],
+ Y[142 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[142],
+ Y[142 + 1],
+ (double) +0.941544065183021, (double) +0.336889853392220);
+ BUTTERFLY_XY (Y[16], /* W8 */
+ Y[16 + 1],
+ Y[144],
+ Y[144 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[144],
+ Y[144 + 1],
+ (double) +0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[18], /* W9 */
+ Y[18 + 1],
+ Y[146],
+ Y[146 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[146],
+ Y[146 + 1],
+ (double) +0.903989293123443, (double) +0.427555093430282);
+ BUTTERFLY_XY (Y[20], /* W10 */
+ Y[20 + 1],
+ Y[148],
+ Y[148 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[148],
+ Y[148 + 1],
+ (double) +0.881921264348355, (double) +0.471396736825998);
+ BUTTERFLY_XY (Y[22], /* W11 */
+ Y[22 + 1],
+ Y[150],
+ Y[150 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[150],
+ Y[150 + 1],
+ (double) +0.857728610000272, (double) +0.514102744193222);
+ BUTTERFLY_XY (Y[24], /* W12 */
+ Y[24 + 1],
+ Y[152],
+ Y[152 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[152],
+ Y[152 + 1],
+ (double) +0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[26], /* W13 */
+ Y[26 + 1],
+ Y[154],
+ Y[154 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[154],
+ Y[154 + 1],
+ (double) +0.803207531480645, (double) +0.595699304492433);
+ BUTTERFLY_XY (Y[28], /* W14 */
+ Y[28 + 1],
+ Y[156],
+ Y[156 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[156],
+ Y[156 + 1],
+ (double) +0.773010453362737, (double) +0.634393284163645);
+ BUTTERFLY_XY (Y[30], /* W15 */
+ Y[30 + 1],
+ Y[158],
+ Y[158 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[158],
+ Y[158 + 1],
+ (double) +0.740951125354959, (double) +0.671558954847018);
+ BUTTERFLY_XX (Y[32], /* W16 */
+ Y[32 + 1],
+ Y[160],
+ Y[160 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[160],
+ Y[160 + 1],
+ (double) +0.707106781186548, (double) +0.707106781186547);
+ BUTTERFLY_XY (Y[34], /* W17 */
+ Y[34 + 1],
+ Y[162],
+ Y[162 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[162],
+ Y[162 + 1],
+ (double) +0.671558954847018, (double) +0.740951125354959);
+ BUTTERFLY_XY (Y[36], /* W18 */
+ Y[36 + 1],
+ Y[164],
+ Y[164 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[164],
+ Y[164 + 1],
+ (double) +0.634393284163645, (double) +0.773010453362737);
+ BUTTERFLY_XY (Y[38], /* W19 */
+ Y[38 + 1],
+ Y[166],
+ Y[166 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[166],
+ Y[166 + 1],
+ (double) +0.595699304492433, (double) +0.803207531480645);
+ BUTTERFLY_XY (Y[40], /* W20 */
+ Y[40 + 1],
+ Y[168],
+ Y[168 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[168],
+ Y[168 + 1],
+ (double) +0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[42], /* W21 */
+ Y[42 + 1],
+ Y[170],
+ Y[170 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[170],
+ Y[170 + 1],
+ (double) +0.514102744193222, (double) +0.857728610000272);
+ BUTTERFLY_XY (Y[44], /* W22 */
+ Y[44 + 1],
+ Y[172],
+ Y[172 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[172],
+ Y[172 + 1],
+ (double) +0.471396736825998, (double) +0.881921264348355);
+ BUTTERFLY_XY (Y[46], /* W23 */
+ Y[46 + 1],
+ Y[174],
+ Y[174 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[174],
+ Y[174 + 1],
+ (double) +0.427555093430282, (double) +0.903989293123443);
+ BUTTERFLY_XY (Y[48], /* W24 */
+ Y[48 + 1],
+ Y[176],
+ Y[176 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[176],
+ Y[176 + 1],
+ (double) +0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[50], /* W25 */
+ Y[50 + 1],
+ Y[178],
+ Y[178 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[178],
+ Y[178 + 1],
+ (double) +0.336889853392220, (double) +0.941544065183021);
+ BUTTERFLY_XY (Y[52], /* W26 */
+ Y[52 + 1],
+ Y[180],
+ Y[180 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[180],
+ Y[180 + 1],
+ (double) +0.290284677254462, (double) +0.956940335732209);
+ BUTTERFLY_XY (Y[54], /* W27 */
+ Y[54 + 1],
+ Y[182],
+ Y[182 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[182],
+ Y[182 + 1],
+ (double) +0.242980179903264, (double) +0.970031253194544);
+ BUTTERFLY_XY (Y[56], /* W28 */
+ Y[56 + 1],
+ Y[184],
+ Y[184 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[184],
+ Y[184 + 1],
+ (double) +0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[58], /* W29 */
+ Y[58 + 1],
+ Y[186],
+ Y[186 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[186],
+ Y[186 + 1],
+ (double) +0.146730474455362, (double) +0.989176509964781);
+ BUTTERFLY_XY (Y[60], /* W30 */
+ Y[60 + 1],
+ Y[188],
+ Y[188 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[188],
+ Y[188 + 1],
+ (double) +0.098017140329561, (double) +0.995184726672197);
+ BUTTERFLY_XY (Y[62], /* W31 */
+ Y[62 + 1],
+ Y[190],
+ Y[190 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[190],
+ Y[190 + 1],
+ (double) +0.049067674327418, (double) +0.998795456205172);
+ BUTTERFLY_01 (Y[64], /* W32 */
+ Y[64 + 1],
+ Y[192],
+ Y[192 + 1],
+ Y[64],
+ Y[64 + 1],
+ Y[192],
+ Y[192 + 1],
+ (double) +0.000000000000000, (double) +1.000000000000000);
+ BUTTERFLY_XY (Y[66], /* W33 */
+ Y[66 + 1],
+ Y[194],
+ Y[194 + 1],
+ Y[66],
+ Y[66 + 1],
+ Y[194],
+ Y[194 + 1],
+ (double) -0.049067674327418, (double) +0.998795456205172);
+ BUTTERFLY_XY (Y[68], /* W34 */
+ Y[68 + 1],
+ Y[196],
+ Y[196 + 1],
+ Y[68],
+ Y[68 + 1],
+ Y[196],
+ Y[196 + 1],
+ (double) -0.098017140329561, (double) +0.995184726672197);
+ BUTTERFLY_XY (Y[70], /* W35 */
+ Y[70 + 1],
+ Y[198],
+ Y[198 + 1],
+ Y[70],
+ Y[70 + 1],
+ Y[198],
+ Y[198 + 1],
+ (double) -0.146730474455362, (double) +0.989176509964781);
+ BUTTERFLY_XY (Y[72], /* W36 */
+ Y[72 + 1],
+ Y[200],
+ Y[200 + 1],
+ Y[72],
+ Y[72 + 1],
+ Y[200],
+ Y[200 + 1],
+ (double) -0.195090322016128, (double) +0.980785280403230);
+ BUTTERFLY_XY (Y[74], /* W37 */
+ Y[74 + 1],
+ Y[202],
+ Y[202 + 1],
+ Y[74],
+ Y[74 + 1],
+ Y[202],
+ Y[202 + 1],
+ (double) -0.242980179903264, (double) +0.970031253194544);
+ BUTTERFLY_XY (Y[76], /* W38 */
+ Y[76 + 1],
+ Y[204],
+ Y[204 + 1],
+ Y[76],
+ Y[76 + 1],
+ Y[204],
+ Y[204 + 1],
+ (double) -0.290284677254462, (double) +0.956940335732209);
+ BUTTERFLY_XY (Y[78], /* W39 */
+ Y[78 + 1],
+ Y[206],
+ Y[206 + 1],
+ Y[78],
+ Y[78 + 1],
+ Y[206],
+ Y[206 + 1],
+ (double) -0.336889853392220, (double) +0.941544065183021);
+ BUTTERFLY_XY (Y[80], /* W40 */
+ Y[80 + 1],
+ Y[208],
+ Y[208 + 1],
+ Y[80],
+ Y[80 + 1],
+ Y[208],
+ Y[208 + 1],
+ (double) -0.382683432365090, (double) +0.923879532511287);
+ BUTTERFLY_XY (Y[82], /* W41 */
+ Y[82 + 1],
+ Y[210],
+ Y[210 + 1],
+ Y[82],
+ Y[82 + 1],
+ Y[210],
+ Y[210 + 1],
+ (double) -0.427555093430282, (double) +0.903989293123443);
+ BUTTERFLY_XY (Y[84], /* W42 */
+ Y[84 + 1],
+ Y[212],
+ Y[212 + 1],
+ Y[84],
+ Y[84 + 1],
+ Y[212],
+ Y[212 + 1],
+ (double) -0.471396736825998, (double) +0.881921264348355);
+ BUTTERFLY_XY (Y[86], /* W43 */
+ Y[86 + 1],
+ Y[214],
+ Y[214 + 1],
+ Y[86],
+ Y[86 + 1],
+ Y[214],
+ Y[214 + 1],
+ (double) -0.514102744193222, (double) +0.857728610000272);
+ BUTTERFLY_XY (Y[88], /* W44 */
+ Y[88 + 1],
+ Y[216],
+ Y[216 + 1],
+ Y[88],
+ Y[88 + 1],
+ Y[216],
+ Y[216 + 1],
+ (double) -0.555570233019602, (double) +0.831469612302545);
+ BUTTERFLY_XY (Y[90], /* W45 */
+ Y[90 + 1],
+ Y[218],
+ Y[218 + 1],
+ Y[90],
+ Y[90 + 1],
+ Y[218],
+ Y[218 + 1],
+ (double) -0.595699304492433, (double) +0.803207531480645);
+ BUTTERFLY_XY (Y[92], /* W46 */
+ Y[92 + 1],
+ Y[220],
+ Y[220 + 1],
+ Y[92],
+ Y[92 + 1],
+ Y[220],
+ Y[220 + 1],
+ (double) -0.634393284163645, (double) +0.773010453362737);
+ BUTTERFLY_XY (Y[94], /* W47 */
+ Y[94 + 1],
+ Y[222],
+ Y[222 + 1],
+ Y[94],
+ Y[94 + 1],
+ Y[222],
+ Y[222 + 1],
+ (double) -0.671558954847018, (double) +0.740951125354959);
+ BUTTERFLY_yY (Y[96], /* W48 */
+ Y[96 + 1],
+ Y[224],
+ Y[224 + 1],
+ Y[96],
+ Y[96 + 1],
+ Y[224],
+ Y[224 + 1],
+ (double) -0.707106781186547, (double) +0.707106781186548);
+ BUTTERFLY_XY (Y[98], /* W49 */
+ Y[98 + 1],
+ Y[226],
+ Y[226 + 1],
+ Y[98],
+ Y[98 + 1],
+ Y[226],
+ Y[226 + 1],
+ (double) -0.740951125354959, (double) +0.671558954847019);
+ BUTTERFLY_XY (Y[100], /* W50 */
+ Y[100 + 1],
+ Y[228],
+ Y[228 + 1],
+ Y[100],
+ Y[100 + 1],
+ Y[228],
+ Y[228 + 1],
+ (double) -0.773010453362737, (double) +0.634393284163645);
+ BUTTERFLY_XY (Y[102], /* W51 */
+ Y[102 + 1],
+ Y[230],
+ Y[230 + 1],
+ Y[102],
+ Y[102 + 1],
+ Y[230],
+ Y[230 + 1],
+ (double) -0.803207531480645, (double) +0.595699304492433);
+ BUTTERFLY_XY (Y[104], /* W52 */
+ Y[104 + 1],
+ Y[232],
+ Y[232 + 1],
+ Y[104],
+ Y[104 + 1],
+ Y[232],
+ Y[232 + 1],
+ (double) -0.831469612302545, (double) +0.555570233019602);
+ BUTTERFLY_XY (Y[106], /* W53 */
+ Y[106 + 1],
+ Y[234],
+ Y[234 + 1],
+ Y[106],
+ Y[106 + 1],
+ Y[234],
+ Y[234 + 1],
+ (double) -0.857728610000272, (double) +0.514102744193222);
+ BUTTERFLY_XY (Y[108], /* W54 */
+ Y[108 + 1],
+ Y[236],
+ Y[236 + 1],
+ Y[108],
+ Y[108 + 1],
+ Y[236],
+ Y[236 + 1],
+ (double) -0.881921264348355, (double) +0.471396736825998);
+ BUTTERFLY_XY (Y[110], /* W55 */
+ Y[110 + 1],
+ Y[238],
+ Y[238 + 1],
+ Y[110],
+ Y[110 + 1],
+ Y[238],
+ Y[238 + 1],
+ (double) -0.903989293123443, (double) +0.427555093430282);
+ BUTTERFLY_XY (Y[112], /* W56 */
+ Y[112 + 1],
+ Y[240],
+ Y[240 + 1],
+ Y[112],
+ Y[112 + 1],
+ Y[240],
+ Y[240 + 1],
+ (double) -0.923879532511287, (double) +0.382683432365090);
+ BUTTERFLY_XY (Y[114], /* W57 */
+ Y[114 + 1],
+ Y[242],
+ Y[242 + 1],
+ Y[114],
+ Y[114 + 1],
+ Y[242],
+ Y[242 + 1],
+ (double) -0.941544065183021, (double) +0.336889853392220);
+ BUTTERFLY_XY (Y[116], /* W58 */
+ Y[116 + 1],
+ Y[244],
+ Y[244 + 1],
+ Y[116],
+ Y[116 + 1],
+ Y[244],
+ Y[244 + 1],
+ (double) -0.956940335732209, (double) +0.290284677254462);
+ BUTTERFLY_XY (Y[118], /* W59 */
+ Y[118 + 1],
+ Y[246],
+ Y[246 + 1],
+ Y[118],
+ Y[118 + 1],
+ Y[246],
+ Y[246 + 1],
+ (double) -0.970031253194544, (double) +0.242980179903264);
+ BUTTERFLY_XY (Y[120], /* W60 */
+ Y[120 + 1],
+ Y[248],
+ Y[248 + 1],
+ Y[120],
+ Y[120 + 1],
+ Y[248],
+ Y[248 + 1],
+ (double) -0.980785280403230, (double) +0.195090322016129);
+ BUTTERFLY_XY (Y[122], /* W61 */
+ Y[122 + 1],
+ Y[250],
+ Y[250 + 1],
+ Y[122],
+ Y[122 + 1],
+ Y[250],
+ Y[250 + 1],
+ (double) -0.989176509964781, (double) +0.146730474455362);
+ BUTTERFLY_XY (Y[124], /* W62 */
+ Y[124 + 1],
+ Y[252],
+ Y[252 + 1],
+ Y[124],
+ Y[124 + 1],
+ Y[252],
+ Y[252 + 1],
+ (double) -0.995184726672197, (double) +0.098017140329561);
+ BUTTERFLY_XY (Y[126], /* W63 */
+ Y[126 + 1],
+ Y[254],
+ Y[254 + 1],
+ Y[126],
+ Y[126 + 1],
+ Y[254],
+ Y[254 + 1],
+ (double) -0.998795456205172, (double) +0.049067674327418);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 128 L S S S S S X)
+ **/
+static void
+gsl_power2_fft128analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (128, X, Y);
+
+ /* skipping 32 times fft4 */
+
+ /* skipping 16 times fft8 */
+
+ /* skipping 8 times fft16 */
+
+ /* skipping 4 times fft32 */
+
+ /* skipping 2 times fft64 */
+
+ /* perform 1 times fft128 */
+ gsl_power2_fft128analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 256 S S S S S S X T)
+ **/
+static void
+gsl_power2_fft256analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 128 times fft2 */
+
+ /* skipping 64 times fft4 */
+
+ /* skipping 32 times fft8 */
+
+ /* skipping 16 times fft16 */
+
+ /* skipping 8 times fft32 */
+
+ /* skipping 4 times fft64 */
+
+ /* perform 2 times fft128 */
+ gsl_power2_fft128analysis_skip2 (X, Y);
+ gsl_power2_fft128analysis_skip2 (X + 256, Y + 256);
+
+ /* perform 1 times fft256 */
+ {
+ static const double Wconst256[] = {
+ +0.999698818696204, +0.024541228522912,
+ +0.998795456205172, +0.049067674327418,
+ +0.997290456678690, +0.073564563599667,
+ +0.995184726672197, +0.098017140329561,
+ +0.992479534598710, +0.122410675199216,
+ +0.989176509964781, +0.146730474455362,
+ +0.985277642388941, +0.170961888760301,
+ +0.980785280403230, +0.195090322016128,
+ +0.975702130038529, +0.219101240156870,
+ +0.970031253194544, +0.242980179903264,
+ +0.963776065795440, +0.266712757474898,
+ +0.956940335732209, +0.290284677254462,
+ +0.949528180593037, +0.313681740398892,
+ +0.941544065183021, +0.336889853392220,
+ +0.932992798834739, +0.359895036534988,
+ +0.923879532511287, +0.382683432365090,
+ +0.914209755703531, +0.405241314004990,
+ +0.903989293123443, +0.427555093430282,
+ +0.893224301195515, +0.449611329654607,
+ +0.881921264348355, +0.471396736825998,
+ +0.870086991108711, +0.492898192229784,
+ +0.857728610000272, +0.514102744193222,
+ +0.844853565249707, +0.534997619887097,
+ +0.831469612302545, +0.555570233019602,
+ +0.817584813151584, +0.575808191417845,
+ +0.803207531480645, +0.595699304492433,
+ +0.788346427626606, +0.615231590580627,
+ +0.773010453362737, +0.634393284163645,
+ +0.757208846506485, +0.653172842953777,
+ +0.740951125354959, +0.671558954847018,
+ +0.724247082951467, +0.689540544737067,
+ +0.707106781186548, +0.707106781186547,
+ +0.689540544737067, +0.724247082951467,
+ +0.671558954847018, +0.740951125354959,
+ +0.653172842953777, +0.757208846506484,
+ +0.634393284163645, +0.773010453362737,
+ +0.615231590580627, +0.788346427626606,
+ +0.595699304492433, +0.803207531480645,
+ +0.575808191417845, +0.817584813151584,
+ +0.555570233019602, +0.831469612302545,
+ +0.534997619887097, +0.844853565249707,
+ +0.514102744193222, +0.857728610000272,
+ +0.492898192229784, +0.870086991108711,
+ +0.471396736825998, +0.881921264348355,
+ +0.449611329654607, +0.893224301195515,
+ +0.427555093430282, +0.903989293123443,
+ +0.405241314004990, +0.914209755703531,
+ +0.382683432365090, +0.923879532511287,
+ +0.359895036534988, +0.932992798834739,
+ +0.336889853392220, +0.941544065183021,
+ +0.313681740398892, +0.949528180593037,
+ +0.290284677254462, +0.956940335732209,
+ +0.266712757474898, +0.963776065795440,
+ +0.242980179903264, +0.970031253194544,
+ +0.219101240156870, +0.975702130038529,
+ +0.195090322016128, +0.980785280403230,
+ +0.170961888760301, +0.985277642388941,
+ +0.146730474455362, +0.989176509964781,
+ +0.122410675199216, +0.992479534598710,
+ +0.098017140329561, +0.995184726672197,
+ +0.073564563599667, +0.997290456678690,
+ +0.049067674327418, +0.998795456205172,
+ +0.024541228522912, +0.999698818696204,
+ };
+ const double *W = Wconst256 - 2;
+ double *Z = Y + 128;
+ for (offset = 0; offset < 512; offset += 512) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ __1, __0);
+ BUTTERFLY_01 (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ __0, __1);
+ }
+ for (butterfly = 2; butterfly < 128; butterfly += 2) {
+ Wre = W[butterfly]; Wim = W[butterfly + 1];
+ for (block = 0; block < 512; block += 512) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Wre, Wim);
+ BUTTERFLY_Yx (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Wre, Wim);
+ }
+ }
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 256 L S S S S S S X)
+ **/
+static void
+gsl_power2_fft256analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (256, X, Y);
+
+ /* skipping 64 times fft4 */
+
+ /* skipping 32 times fft8 */
+
+ /* skipping 16 times fft16 */
+
+ /* skipping 8 times fft32 */
+
+ /* skipping 4 times fft64 */
+
+ /* skipping 2 times fft128 */
+
+ /* perform 1 times fft256 */
+ gsl_power2_fft256analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 512 S S S S S S X T T)
+ **/
+static void
+gsl_power2_fft512analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 256 times fft2 */
+
+ /* skipping 128 times fft4 */
+
+ /* skipping 64 times fft8 */
+
+ /* skipping 32 times fft16 */
+
+ /* skipping 16 times fft32 */
+
+ /* skipping 8 times fft64 */
+
+ /* perform 4 times fft128 */
+ gsl_power2_fft128analysis_skip2 (X, Y);
+ gsl_power2_fft128analysis_skip2 (X + 256, Y + 256);
+ gsl_power2_fft128analysis_skip2 (X + 512, Y + 512);
+ gsl_power2_fft128analysis_skip2 (X + 768, Y + 768);
+
+ /* perform 2 times fft256 */
+ {
+ static const double Wconst256[] = {
+ +0.999698818696204, +0.024541228522912,
+ +0.998795456205172, +0.049067674327418,
+ +0.997290456678690, +0.073564563599667,
+ +0.995184726672197, +0.098017140329561,
+ +0.992479534598710, +0.122410675199216,
+ +0.989176509964781, +0.146730474455362,
+ +0.985277642388941, +0.170961888760301,
+ +0.980785280403230, +0.195090322016128,
+ +0.975702130038529, +0.219101240156870,
+ +0.970031253194544, +0.242980179903264,
+ +0.963776065795440, +0.266712757474898,
+ +0.956940335732209, +0.290284677254462,
+ +0.949528180593037, +0.313681740398892,
+ +0.941544065183021, +0.336889853392220,
+ +0.932992798834739, +0.359895036534988,
+ +0.923879532511287, +0.382683432365090,
+ +0.914209755703531, +0.405241314004990,
+ +0.903989293123443, +0.427555093430282,
+ +0.893224301195515, +0.449611329654607,
+ +0.881921264348355, +0.471396736825998,
+ +0.870086991108711, +0.492898192229784,
+ +0.857728610000272, +0.514102744193222,
+ +0.844853565249707, +0.534997619887097,
+ +0.831469612302545, +0.555570233019602,
+ +0.817584813151584, +0.575808191417845,
+ +0.803207531480645, +0.595699304492433,
+ +0.788346427626606, +0.615231590580627,
+ +0.773010453362737, +0.634393284163645,
+ +0.757208846506485, +0.653172842953777,
+ +0.740951125354959, +0.671558954847018,
+ +0.724247082951467, +0.689540544737067,
+ +0.707106781186548, +0.707106781186547,
+ +0.689540544737067, +0.724247082951467,
+ +0.671558954847018, +0.740951125354959,
+ +0.653172842953777, +0.757208846506484,
+ +0.634393284163645, +0.773010453362737,
+ +0.615231590580627, +0.788346427626606,
+ +0.595699304492433, +0.803207531480645,
+ +0.575808191417845, +0.817584813151584,
+ +0.555570233019602, +0.831469612302545,
+ +0.534997619887097, +0.844853565249707,
+ +0.514102744193222, +0.857728610000272,
+ +0.492898192229784, +0.870086991108711,
+ +0.471396736825998, +0.881921264348355,
+ +0.449611329654607, +0.893224301195515,
+ +0.427555093430282, +0.903989293123443,
+ +0.405241314004990, +0.914209755703531,
+ +0.382683432365090, +0.923879532511287,
+ +0.359895036534988, +0.932992798834739,
+ +0.336889853392220, +0.941544065183021,
+ +0.313681740398892, +0.949528180593037,
+ +0.290284677254462, +0.956940335732209,
+ +0.266712757474898, +0.963776065795440,
+ +0.242980179903264, +0.970031253194544,
+ +0.219101240156870, +0.975702130038529,
+ +0.195090322016128, +0.980785280403230,
+ +0.170961888760301, +0.985277642388941,
+ +0.146730474455362, +0.989176509964781,
+ +0.122410675199216, +0.992479534598710,
+ +0.098017140329561, +0.995184726672197,
+ +0.073564563599667, +0.997290456678690,
+ +0.049067674327418, +0.998795456205172,
+ +0.024541228522912, +0.999698818696204,
+ };
+ const double *W = Wconst256 - 2;
+ double *Z = Y + 128;
+ for (offset = 0; offset < 1024; offset += 512) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ __1, __0);
+ BUTTERFLY_01 (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ __0, __1);
+ }
+ for (butterfly = 2; butterfly < 128; butterfly += 2) {
+ Wre = W[butterfly]; Wim = W[butterfly + 1];
+ for (block = 0; block < 1024; block += 512) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Wre, Wim);
+ BUTTERFLY_Yx (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Wre, Wim);
+ }
+ }
+ }
+
+ /* perform 1 times fft512 */
+ {
+ static const double Wconst512[] = {
+ +0.999924701839145, +0.012271538285720,
+ +0.999698818696204, +0.024541228522912,
+ +0.999322384588350, +0.036807222941359,
+ +0.998795456205172, +0.049067674327418,
+ +0.998118112900149, +0.061320736302209,
+ +0.997290456678690, +0.073564563599667,
+ +0.996312612182778, +0.085797312344440,
+ +0.995184726672197, +0.098017140329561,
+ +0.993906970002356, +0.110222207293883,
+ +0.992479534598710, +0.122410675199216,
+ +0.990902635427780, +0.134580708507126,
+ +0.989176509964781, +0.146730474455362,
+ +0.987301418157858, +0.158858143333861,
+ +0.985277642388941, +0.170961888760301,
+ +0.983105487431216, +0.183039887955141,
+ +0.980785280403230, +0.195090322016128,
+ +0.978317370719628, +0.207111376192219,
+ +0.975702130038529, +0.219101240156870,
+ +0.972939952205560, +0.231058108280671,
+ +0.970031253194544, +0.242980179903264,
+ +0.966976471044852, +0.254865659604515,
+ +0.963776065795440, +0.266712757474898,
+ +0.960430519415566, +0.278519689385053,
+ +0.956940335732209, +0.290284677254462,
+ +0.953306040354194, +0.302005949319228,
+ +0.949528180593037, +0.313681740398892,
+ +0.945607325380521, +0.325310292162263,
+ +0.941544065183021, +0.336889853392220,
+ +0.937339011912575, +0.348418680249435,
+ +0.932992798834739, +0.359895036534988,
+ +0.928506080473216, +0.371317193951838,
+ +0.923879532511287, +0.382683432365090,
+ +0.919113851690058, +0.393992040061048,
+ +0.914209755703531, +0.405241314004990,
+ +0.909167983090522, +0.416429560097637,
+ +0.903989293123443, +0.427555093430282,
+ +0.898674465693954, +0.438616238538528,
+ +0.893224301195515, +0.449611329654607,
+ +0.887639620402854, +0.460538710958240,
+ +0.881921264348355, +0.471396736825998,
+ +0.876070094195407, +0.482183772079123,
+ +0.870086991108711, +0.492898192229784,
+ +0.863972856121587, +0.503538383725718,
+ +0.857728610000272, +0.514102744193222,
+ +0.851355193105265, +0.524589682678469,
+ +0.844853565249707, +0.534997619887097,
+ +0.838224705554838, +0.545324988422046,
+ +0.831469612302545, +0.555570233019602,
+ +0.824589302785025, +0.565731810783613,
+ +0.817584813151584, +0.575808191417845,
+ +0.810457198252595, +0.585797857456439,
+ +0.803207531480645, +0.595699304492433,
+ +0.795836904608884, +0.605511041404326,
+ +0.788346427626606, +0.615231590580627,
+ +0.780737228572094, +0.624859488142386,
+ +0.773010453362737, +0.634393284163645,
+ +0.765167265622459, +0.643831542889791,
+ +0.757208846506485, +0.653172842953777,
+ +0.749136394523459, +0.662415777590172,
+ +0.740951125354959, +0.671558954847018,
+ +0.732654271672413, +0.680600997795453,
+ +0.724247082951467, +0.689540544737067,
+ +0.715730825283819, +0.698376249408973,
+ +0.707106781186548, +0.707106781186547,
+ +0.698376249408973, +0.715730825283819,
+ +0.689540544737067, +0.724247082951467,
+ +0.680600997795453, +0.732654271672413,
+ +0.671558954847018, +0.740951125354959,
+ +0.662415777590172, +0.749136394523459,
+ +0.653172842953777, +0.757208846506484,
+ +0.643831542889791, +0.765167265622459,
+ +0.634393284163645, +0.773010453362737,
+ +0.624859488142386, +0.780737228572094,
+ +0.615231590580627, +0.788346427626606,
+ +0.605511041404326, +0.795836904608883,
+ +0.595699304492433, +0.803207531480645,
+ +0.585797857456439, +0.810457198252595,
+ +0.575808191417845, +0.817584813151584,
+ +0.565731810783613, +0.824589302785025,
+ +0.555570233019602, +0.831469612302545,
+ +0.545324988422046, +0.838224705554838,
+ +0.534997619887097, +0.844853565249707,
+ +0.524589682678469, +0.851355193105265,
+ +0.514102744193222, +0.857728610000272,
+ +0.503538383725718, +0.863972856121587,
+ +0.492898192229784, +0.870086991108711,
+ +0.482183772079123, +0.876070094195407,
+ +0.471396736825998, +0.881921264348355,
+ +0.460538710958240, +0.887639620402854,
+ +0.449611329654607, +0.893224301195515,
+ +0.438616238538528, +0.898674465693954,
+ +0.427555093430282, +0.903989293123443,
+ +0.416429560097637, +0.909167983090522,
+ +0.405241314004990, +0.914209755703531,
+ +0.393992040061048, +0.919113851690058,
+ +0.382683432365090, +0.923879532511287,
+ +0.371317193951838, +0.928506080473215,
+ +0.359895036534988, +0.932992798834739,
+ +0.348418680249435, +0.937339011912575,
+ +0.336889853392220, +0.941544065183021,
+ +0.325310292162263, +0.945607325380521,
+ +0.313681740398892, +0.949528180593037,
+ +0.302005949319228, +0.953306040354194,
+ +0.290284677254462, +0.956940335732209,
+ +0.278519689385053, +0.960430519415566,
+ +0.266712757474898, +0.963776065795440,
+ +0.254865659604515, +0.966976471044852,
+ +0.242980179903264, +0.970031253194544,
+ +0.231058108280671, +0.972939952205560,
+ +0.219101240156870, +0.975702130038529,
+ +0.207111376192219, +0.978317370719628,
+ +0.195090322016128, +0.980785280403230,
+ +0.183039887955141, +0.983105487431216,
+ +0.170961888760301, +0.985277642388941,
+ +0.158858143333861, +0.987301418157858,
+ +0.146730474455362, +0.989176509964781,
+ +0.134580708507126, +0.990902635427780,
+ +0.122410675199216, +0.992479534598710,
+ +0.110222207293883, +0.993906970002356,
+ +0.098017140329561, +0.995184726672197,
+ +0.085797312344440, +0.996312612182778,
+ +0.073564563599667, +0.997290456678690,
+ +0.061320736302209, +0.998118112900149,
+ +0.049067674327418, +0.998795456205172,
+ +0.036807222941359, +0.999322384588350,
+ +0.024541228522912, +0.999698818696204,
+ +0.012271538285720, +0.999924701839145,
+ };
+ const double *W = Wconst512 - 2;
+ double *Z = Y + 256;
+ for (offset = 0; offset < 1024; offset += 1024) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ __1, __0);
+ BUTTERFLY_01 (Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ __0, __1);
+ }
+ for (butterfly = 2; butterfly < 256; butterfly += 2) {
+ Wre = W[butterfly]; Wim = W[butterfly + 1];
+ for (block = 0; block < 1024; block += 1024) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ Wre, Wim);
+ BUTTERFLY_Yx (Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ Wre, Wim);
+ }
+ }
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 512 L S S S S S S S X)
+ **/
+static void
+gsl_power2_fft512analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (512, X, Y);
+
+ /* skipping 128 times fft4 */
+
+ /* skipping 64 times fft8 */
+
+ /* skipping 32 times fft16 */
+
+ /* skipping 16 times fft32 */
+
+ /* skipping 8 times fft64 */
+
+ /* skipping 4 times fft128 */
+
+ /* skipping 2 times fft256 */
+
+ /* perform 1 times fft512 */
+ gsl_power2_fft512analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 1024 S S S S S S S S X L)
+ **/
+static void
+gsl_power2_fft1024analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 512 times fft2 */
+
+ /* skipping 256 times fft4 */
+
+ /* skipping 128 times fft8 */
+
+ /* skipping 64 times fft16 */
+
+ /* skipping 32 times fft32 */
+
+ /* skipping 16 times fft64 */
+
+ /* skipping 8 times fft128 */
+
+ /* skipping 4 times fft256 */
+
+ /* perform 2 times fft512 */
+ gsl_power2_fft512analysis_skip2 (X, Y);
+ gsl_power2_fft512analysis_skip2 (X + 1024, Y + 1024);
+
+ /* perform 1 times fft1024 */
+ for (offset = 0; offset < 2048; offset += 2048) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __1, __0);
+ }
+ Wre = +0.999981175282601; Wim = +0.006135884649154;
+ for (butterfly = 2; butterfly < 512; butterfly += 2) {
+ for (block = 0; block < 2048; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, +0.006135884649154);
+ }
+ for (offset = 512; offset < 2048; offset += 2048) {
+ BUTTERFLY_01 (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __0, __1);
+ }
+ Wre = -0.006135884649154; Wim = +0.999981175282601;
+ for (butterfly = 514; butterfly < 1024; butterfly += 2) {
+ for (block = 0; block < 2048; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, +0.006135884649154);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 1024 L S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft1024analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (1024, X, Y);
+
+ /* skipping 256 times fft4 */
+
+ /* skipping 128 times fft8 */
+
+ /* skipping 64 times fft16 */
+
+ /* skipping 32 times fft32 */
+
+ /* skipping 16 times fft64 */
+
+ /* skipping 8 times fft128 */
+
+ /* skipping 4 times fft256 */
+
+ /* skipping 2 times fft512 */
+
+ /* perform 1 times fft1024 */
+ gsl_power2_fft1024analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 2048 S S S S S S S S X L L)
+ **/
+static void
+gsl_power2_fft2048analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 1024 times fft2 */
+
+ /* skipping 512 times fft4 */
+
+ /* skipping 256 times fft8 */
+
+ /* skipping 128 times fft16 */
+
+ /* skipping 64 times fft32 */
+
+ /* skipping 32 times fft64 */
+
+ /* skipping 16 times fft128 */
+
+ /* skipping 8 times fft256 */
+
+ /* perform 4 times fft512 */
+ gsl_power2_fft512analysis_skip2 (X, Y);
+ gsl_power2_fft512analysis_skip2 (X + 1024, Y + 1024);
+ gsl_power2_fft512analysis_skip2 (X + 2048, Y + 2048);
+ gsl_power2_fft512analysis_skip2 (X + 3072, Y + 3072);
+
+ /* perform 2 times fft1024 */
+ for (offset = 0; offset < 4096; offset += 2048) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __1, __0);
+ }
+ Wre = +0.999981175282601; Wim = +0.006135884649154;
+ for (butterfly = 2; butterfly < 512; butterfly += 2) {
+ for (block = 0; block < 4096; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, +0.006135884649154);
+ }
+ for (offset = 512; offset < 4096; offset += 2048) {
+ BUTTERFLY_01 (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __0, __1);
+ }
+ Wre = -0.006135884649154; Wim = +0.999981175282601;
+ for (butterfly = 514; butterfly < 1024; butterfly += 2) {
+ for (block = 0; block < 4096; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, +0.006135884649154);
+ }
+
+ /* perform 1 times fft2048 */
+ for (offset = 0; offset < 4096; offset += 4096) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ __1, __0);
+ }
+ Wre = +0.999995293809576; Wim = +0.003067956762966;
+ for (butterfly = 2; butterfly < 1024; butterfly += 2) {
+ for (block = 0; block < 4096; block += 4096) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000004706190424, +0.003067956762966);
+ }
+ for (offset = 1024; offset < 4096; offset += 4096) {
+ BUTTERFLY_01 (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ __0, __1);
+ }
+ Wre = -0.003067956762966; Wim = +0.999995293809576;
+ for (butterfly = 1026; butterfly < 2048; butterfly += 2) {
+ for (block = 0; block < 4096; block += 4096) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000004706190424, +0.003067956762966);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 2048 L S S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft2048analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (2048, X, Y);
+
+ /* skipping 512 times fft4 */
+
+ /* skipping 256 times fft8 */
+
+ /* skipping 128 times fft16 */
+
+ /* skipping 64 times fft32 */
+
+ /* skipping 32 times fft64 */
+
+ /* skipping 16 times fft128 */
+
+ /* skipping 8 times fft256 */
+
+ /* skipping 4 times fft512 */
+
+ /* skipping 2 times fft1024 */
+
+ /* perform 1 times fft2048 */
+ gsl_power2_fft2048analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4096 S S S S S S S S S S X L)
+ **/
+static void
+gsl_power2_fft4096analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 2048 times fft2 */
+
+ /* skipping 1024 times fft4 */
+
+ /* skipping 512 times fft8 */
+
+ /* skipping 256 times fft16 */
+
+ /* skipping 128 times fft32 */
+
+ /* skipping 64 times fft64 */
+
+ /* skipping 32 times fft128 */
+
+ /* skipping 16 times fft256 */
+
+ /* skipping 8 times fft512 */
+
+ /* skipping 4 times fft1024 */
+
+ /* perform 2 times fft2048 */
+ gsl_power2_fft2048analysis_skip2 (X, Y);
+ gsl_power2_fft2048analysis_skip2 (X + 4096, Y + 4096);
+
+ /* perform 1 times fft4096 */
+ for (offset = 0; offset < 8192; offset += 8192) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ __1, __0);
+ }
+ Wre = +0.999998823451702; Wim = +0.001533980186285;
+ for (butterfly = 2; butterfly < 2048; butterfly += 2) {
+ for (block = 0; block < 8192; block += 8192) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000001176548298, +0.001533980186285);
+ }
+ for (offset = 2048; offset < 8192; offset += 8192) {
+ BUTTERFLY_01 (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ __0, __1);
+ }
+ Wre = -0.001533980186285; Wim = +0.999998823451702;
+ for (butterfly = 2050; butterfly < 4096; butterfly += 2) {
+ for (block = 0; block < 8192; block += 8192) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000001176548298, +0.001533980186285);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4096 L S S S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft4096analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (4096, X, Y);
+
+ /* skipping 1024 times fft4 */
+
+ /* skipping 512 times fft8 */
+
+ /* skipping 256 times fft16 */
+
+ /* skipping 128 times fft32 */
+
+ /* skipping 64 times fft64 */
+
+ /* skipping 32 times fft128 */
+
+ /* skipping 16 times fft256 */
+
+ /* skipping 8 times fft512 */
+
+ /* skipping 4 times fft1024 */
+
+ /* skipping 2 times fft2048 */
+
+ /* perform 1 times fft4096 */
+ gsl_power2_fft4096analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8192 S S S S S S S S S S S X L)
+ **/
+static void
+gsl_power2_fft8192analysis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 4096 times fft2 */
+
+ /* skipping 2048 times fft4 */
+
+ /* skipping 1024 times fft8 */
+
+ /* skipping 512 times fft16 */
+
+ /* skipping 256 times fft32 */
+
+ /* skipping 128 times fft64 */
+
+ /* skipping 64 times fft128 */
+
+ /* skipping 32 times fft256 */
+
+ /* skipping 16 times fft512 */
+
+ /* skipping 8 times fft1024 */
+
+ /* skipping 4 times fft2048 */
+
+ /* perform 2 times fft4096 */
+ gsl_power2_fft4096analysis_skip2 (X, Y);
+ gsl_power2_fft4096analysis_skip2 (X + 8192, Y + 8192);
+
+ /* perform 1 times fft8192 */
+ for (offset = 0; offset < 16384; offset += 16384) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ __1, __0);
+ }
+ Wre = +0.999999705862882; Wim = +0.000766990318743;
+ for (butterfly = 2; butterfly < 4096; butterfly += 2) {
+ for (block = 0; block < 16384; block += 16384) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000000294137118, +0.000766990318743);
+ }
+ for (offset = 4096; offset < 16384; offset += 16384) {
+ BUTTERFLY_01 (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ __0, __1);
+ }
+ Wre = -0.000766990318743; Wim = +0.999999705862882;
+ for (butterfly = 4098; butterfly < 8192; butterfly += 2) {
+ for (block = 0; block < 16384; block += 16384) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000000294137118, +0.000766990318743);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8192 L S S S S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft8192analysis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2analysis (8192, X, Y);
+
+ /* skipping 2048 times fft4 */
+
+ /* skipping 1024 times fft8 */
+
+ /* skipping 512 times fft16 */
+
+ /* skipping 256 times fft32 */
+
+ /* skipping 128 times fft64 */
+
+ /* skipping 64 times fft128 */
+
+ /* skipping 32 times fft256 */
+
+ /* skipping 16 times fft512 */
+
+ /* skipping 8 times fft1024 */
+
+ /* skipping 4 times fft2048 */
+
+ /* skipping 2 times fft4096 */
+
+ /* perform 1 times fft8192 */
+ gsl_power2_fft8192analysis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 2 F)
+ **/
+static void
+gsl_power2_fft2synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 1 times fft2 */
+ BUTTERFLY_10scale (X[0], X[0 + 1],
+ X[2], X[2 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ 1.0 / (double) 2);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4 S F)
+ **/
+static void
+gsl_power2_fft4synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 2 times fft2 */
+
+ /* perform 1 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_0m (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4 F X)
+ **/
+static void
+gsl_power2_fft4synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 2 times fft2 */
+ BUTTERFLY_10scale (X[0], X[0 + 1],
+ X[4], X[4 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ 1.0 / (double) 4);
+ BUTTERFLY_10scale (X[2], X[2 + 1],
+ X[6], X[6 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ 1.0 / (double) 4);
+
+ /* perform 1 times fft4 */
+ gsl_power2_fft4synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8 S F F)
+ **/
+static void
+gsl_power2_fft8synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 4 times fft2 */
+
+ /* perform 2 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[8], /* W0 */
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_0m (Y[2], /* W2 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[10], /* W2 */
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+
+ /* perform 1 times fft8 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_yY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_0m (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XX (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8 F S X)
+ **/
+static void
+gsl_power2_fft8synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 4 times fft2 */
+ BUTTERFLY_10scale (X[0], X[0 + 1],
+ X[8], X[8 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ 1.0 / (double) 8);
+ BUTTERFLY_10scale (X[4], X[4 + 1],
+ X[12], X[12 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ 1.0 / (double) 8);
+ BUTTERFLY_10scale (X[2], X[2 + 1],
+ X[10], X[10 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ 1.0 / (double) 8);
+ BUTTERFLY_10scale (X[6], X[6 + 1],
+ X[14], X[14 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ 1.0 / (double) 8);
+
+ /* skipping 2 times fft4 */
+
+ /* perform 1 times fft8 */
+ gsl_power2_fft8synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 16 S F F F)
+ **/
+static void
+gsl_power2_fft16synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 8 times fft2 */
+
+ /* perform 4 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[8], /* W0 */
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[24], /* W0 */
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_0m (Y[2], /* W4 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[10], /* W4 */
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[18], /* W4 */
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[26], /* W4 */
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+
+ /* perform 2 times fft8 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_yY (Y[2], /* W2 */
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_yY (Y[18], /* W2 */
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_0m (Y[4], /* W4 */
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[20], /* W4 */
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XX (Y[6], /* W6 */
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XX (Y[22], /* W6 */
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+
+ /* perform 1 times fft16 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_yY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_0m (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XX (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 16 F S S X)
+ **/
+static void
+gsl_power2_fft16synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 8 times fft2 */
+ BUTTERFLY_10scale (X[0], X[0 + 1],
+ X[16], X[16 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[8], X[8 + 1],
+ X[24], X[24 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[4], X[4 + 1],
+ X[20], X[20 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[12], X[12 + 1],
+ X[28], X[28 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[2], X[2 + 1],
+ X[18], X[18 + 1],
+ Y[16], Y[16 + 1],
+ Y[18], Y[18 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[10], X[10 + 1],
+ X[26], X[26 + 1],
+ Y[20], Y[20 + 1],
+ Y[22], Y[22 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[6], X[6 + 1],
+ X[22], X[22 + 1],
+ Y[24], Y[24 + 1],
+ Y[26], Y[26 + 1],
+ 1.0 / (double) 16);
+ BUTTERFLY_10scale (X[14], X[14 + 1],
+ X[30], X[30 + 1],
+ Y[28], Y[28 + 1],
+ Y[30], Y[30 + 1],
+ 1.0 / (double) 16);
+
+ /* skipping 4 times fft4 */
+
+ /* skipping 2 times fft8 */
+
+ /* perform 1 times fft16 */
+ gsl_power2_fft16synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 32 S F F F F)
+ **/
+static void
+gsl_power2_fft32synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 16 times fft2 */
+
+ /* perform 8 times fft4 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[4],
+ Y[4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[8], /* W0 */
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[24], /* W0 */
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[32], /* W0 */
+ Y[32 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[36],
+ Y[36 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[40], /* W0 */
+ Y[40 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[44],
+ Y[44 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[48], /* W0 */
+ Y[48 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[52],
+ Y[52 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[56], /* W0 */
+ Y[56 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_0m (Y[2], /* W8 */
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[6],
+ Y[6 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[10], /* W8 */
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[18], /* W8 */
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[26], /* W8 */
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[34], /* W8 */
+ Y[34 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[38],
+ Y[38 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[42], /* W8 */
+ Y[42 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[46],
+ Y[46 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[50], /* W8 */
+ Y[50 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[54],
+ Y[54 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[58], /* W8 */
+ Y[58 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+
+ /* perform 4 times fft8 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[8],
+ Y[8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[16], /* W0 */
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[32], /* W0 */
+ Y[32 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[40],
+ Y[40 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[48], /* W0 */
+ Y[48 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[56],
+ Y[56 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_yY (Y[2], /* W4 */
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[10],
+ Y[10 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_yY (Y[18], /* W4 */
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_yY (Y[34], /* W4 */
+ Y[34 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[42],
+ Y[42 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_yY (Y[50], /* W4 */
+ Y[50 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[58],
+ Y[58 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_0m (Y[4], /* W8 */
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[12],
+ Y[12 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[20], /* W8 */
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[36], /* W8 */
+ Y[36 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[44],
+ Y[44 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[52], /* W8 */
+ Y[52 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XX (Y[6], /* W12 */
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[14],
+ Y[14 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XX (Y[22], /* W12 */
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XX (Y[38], /* W12 */
+ Y[38 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[46],
+ Y[46 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XX (Y[54], /* W12 */
+ Y[54 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+
+ /* perform 2 times fft16 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[16],
+ Y[16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_10 (Y[32], /* W0 */
+ Y[32 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[48],
+ Y[48 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W2 */
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[18],
+ Y[18 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[34], /* W2 */
+ Y[34 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[50],
+ Y[50 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_yY (Y[4], /* W4 */
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[20],
+ Y[20 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_yY (Y[36], /* W4 */
+ Y[36 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[52],
+ Y[52 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[6], /* W6 */
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[22],
+ Y[22 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[38], /* W6 */
+ Y[38 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[54],
+ Y[54 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_0m (Y[8], /* W8 */
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[24],
+ Y[24 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_0m (Y[40], /* W8 */
+ Y[40 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[56],
+ Y[56 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[10], /* W10 */
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[26],
+ Y[26 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[42], /* W10 */
+ Y[42 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[58],
+ Y[58 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XX (Y[12], /* W12 */
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[28],
+ Y[28 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XX (Y[44], /* W12 */
+ Y[44 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[14], /* W14 */
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[30],
+ Y[30 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[46], /* W14 */
+ Y[46 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+
+ /* perform 1 times fft32 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[32],
+ Y[32 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[34],
+ Y[34 + 1],
+ (double) +0.980785280403230, (double) -0.195090322016128);
+ BUTTERFLY_XY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[36],
+ Y[36 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[38],
+ Y[38 + 1],
+ (double) +0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_yY (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[40],
+ Y[40 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[42],
+ Y[42 + 1],
+ (double) +0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[44],
+ Y[44 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[46],
+ Y[46 + 1],
+ (double) +0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_0m (Y[16], /* W8 */
+ Y[16 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[48],
+ Y[48 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[18], /* W9 */
+ Y[18 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[50],
+ Y[50 + 1],
+ (double) -0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[20], /* W10 */
+ Y[20 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[52],
+ Y[52 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[22], /* W11 */
+ Y[22 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[54],
+ Y[54 + 1],
+ (double) -0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XX (Y[24], /* W12 */
+ Y[24 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[56],
+ Y[56 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[26], /* W13 */
+ Y[26 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[58],
+ Y[58 + 1],
+ (double) -0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[28], /* W14 */
+ Y[28 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[60],
+ Y[60 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[30], /* W15 */
+ Y[30 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[62],
+ Y[62 + 1],
+ (double) -0.980785280403230, (double) -0.195090322016129);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 32 F S S S X)
+ **/
+static void
+gsl_power2_fft32synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 16 times fft2 */
+ BUTTERFLY_10scale (X[0], X[0 + 1],
+ X[32], X[32 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[16], X[16 + 1],
+ X[48], X[48 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[8], X[8 + 1],
+ X[40], X[40 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[24], X[24 + 1],
+ X[56], X[56 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[4], X[4 + 1],
+ X[36], X[36 + 1],
+ Y[16], Y[16 + 1],
+ Y[18], Y[18 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[20], X[20 + 1],
+ X[52], X[52 + 1],
+ Y[20], Y[20 + 1],
+ Y[22], Y[22 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[12], X[12 + 1],
+ X[44], X[44 + 1],
+ Y[24], Y[24 + 1],
+ Y[26], Y[26 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[28], X[28 + 1],
+ X[60], X[60 + 1],
+ Y[28], Y[28 + 1],
+ Y[30], Y[30 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[2], X[2 + 1],
+ X[34], X[34 + 1],
+ Y[32], Y[32 + 1],
+ Y[34], Y[34 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[18], X[18 + 1],
+ X[50], X[50 + 1],
+ Y[36], Y[36 + 1],
+ Y[38], Y[38 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[10], X[10 + 1],
+ X[42], X[42 + 1],
+ Y[40], Y[40 + 1],
+ Y[42], Y[42 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[26], X[26 + 1],
+ X[58], X[58 + 1],
+ Y[44], Y[44 + 1],
+ Y[46], Y[46 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[6], X[6 + 1],
+ X[38], X[38 + 1],
+ Y[48], Y[48 + 1],
+ Y[50], Y[50 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[22], X[22 + 1],
+ X[54], X[54 + 1],
+ Y[52], Y[52 + 1],
+ Y[54], Y[54 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[14], X[14 + 1],
+ X[46], X[46 + 1],
+ Y[56], Y[56 + 1],
+ Y[58], Y[58 + 1],
+ 1.0 / (double) 32);
+ BUTTERFLY_10scale (X[30], X[30 + 1],
+ X[62], X[62 + 1],
+ Y[60], Y[60 + 1],
+ Y[62], Y[62 + 1],
+ 1.0 / (double) 32);
+
+ /* skipping 8 times fft4 */
+
+ /* skipping 4 times fft8 */
+
+ /* skipping 2 times fft16 */
+
+ /* perform 1 times fft32 */
+ gsl_power2_fft32synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 64 S R R R R F)
+ **/
+static void
+gsl_power2_fft64synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 32 times fft2 */
+
+ /* perform 16 times fft4 */
+ for (block = 0; block < 128; block += 8) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_0m (Y[block + 2], /* W16 */
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ }
+
+ /* perform 8 times fft8 */
+ for (block = 0; block < 128; block += 16) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_yY (Y[block + 2], /* W8 */
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_0m (Y[block + 4], /* W16 */
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XX (Y[block + 6], /* W24 */
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ }
+
+ /* perform 4 times fft16 */
+ for (block = 0; block < 128; block += 32) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W4 */
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_yY (Y[block + 4], /* W8 */
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[block + 6], /* W12 */
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_0m (Y[block + 8], /* W16 */
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[block + 10], /* W20 */
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XX (Y[block + 12], /* W24 */
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[block + 14], /* W28 */
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ }
+
+ /* perform 2 times fft32 */
+ for (block = 0; block < 128; block += 64) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W2 */
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ (double) +0.980785280403230, (double) -0.195090322016128);
+ BUTTERFLY_XY (Y[block + 4], /* W4 */
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[block + 6], /* W6 */
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ (double) +0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_yY (Y[block + 8], /* W8 */
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[block + 10], /* W10 */
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ (double) +0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[block + 12], /* W12 */
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[block + 14], /* W14 */
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ (double) +0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_0m (Y[block + 16], /* W16 */
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[block + 18], /* W18 */
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ (double) -0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[block + 20], /* W20 */
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[block + 22], /* W22 */
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ (double) -0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XX (Y[block + 24], /* W24 */
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[block + 26], /* W26 */
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ (double) -0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[block + 28], /* W28 */
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[block + 30], /* W30 */
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ (double) -0.980785280403230, (double) -0.195090322016129);
+ }
+
+ /* perform 1 times fft64 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[64],
+ Y[64 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[64],
+ Y[64 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[66],
+ Y[66 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[66],
+ Y[66 + 1],
+ (double) +0.995184726672197, (double) -0.098017140329561);
+ BUTTERFLY_XY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[68],
+ Y[68 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[68],
+ Y[68 + 1],
+ (double) +0.980785280403230, (double) -0.195090322016128);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[70],
+ Y[70 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[70],
+ Y[70 + 1],
+ (double) +0.956940335732209, (double) -0.290284677254462);
+ BUTTERFLY_XY (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[72],
+ Y[72 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[72],
+ Y[72 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[74],
+ Y[74 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[74],
+ Y[74 + 1],
+ (double) +0.881921264348355, (double) -0.471396736825998);
+ BUTTERFLY_XY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[76],
+ Y[76 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[76],
+ Y[76 + 1],
+ (double) +0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[78],
+ Y[78 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[78],
+ Y[78 + 1],
+ (double) +0.773010453362737, (double) -0.634393284163645);
+ BUTTERFLY_yY (Y[16], /* W8 */
+ Y[16 + 1],
+ Y[80],
+ Y[80 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[80],
+ Y[80 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[18], /* W9 */
+ Y[18 + 1],
+ Y[82],
+ Y[82 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[82],
+ Y[82 + 1],
+ (double) +0.634393284163645, (double) -0.773010453362737);
+ BUTTERFLY_XY (Y[20], /* W10 */
+ Y[20 + 1],
+ Y[84],
+ Y[84 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[84],
+ Y[84 + 1],
+ (double) +0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[22], /* W11 */
+ Y[22 + 1],
+ Y[86],
+ Y[86 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[86],
+ Y[86 + 1],
+ (double) +0.471396736825998, (double) -0.881921264348355);
+ BUTTERFLY_XY (Y[24], /* W12 */
+ Y[24 + 1],
+ Y[88],
+ Y[88 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[88],
+ Y[88 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[26], /* W13 */
+ Y[26 + 1],
+ Y[90],
+ Y[90 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[90],
+ Y[90 + 1],
+ (double) +0.290284677254462, (double) -0.956940335732209);
+ BUTTERFLY_XY (Y[28], /* W14 */
+ Y[28 + 1],
+ Y[92],
+ Y[92 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[92],
+ Y[92 + 1],
+ (double) +0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[30], /* W15 */
+ Y[30 + 1],
+ Y[94],
+ Y[94 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[94],
+ Y[94 + 1],
+ (double) +0.098017140329561, (double) -0.995184726672197);
+ BUTTERFLY_0m (Y[32], /* W16 */
+ Y[32 + 1],
+ Y[96],
+ Y[96 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[96],
+ Y[96 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[34], /* W17 */
+ Y[34 + 1],
+ Y[98],
+ Y[98 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[98],
+ Y[98 + 1],
+ (double) -0.098017140329561, (double) -0.995184726672197);
+ BUTTERFLY_XY (Y[36], /* W18 */
+ Y[36 + 1],
+ Y[100],
+ Y[100 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[100],
+ Y[100 + 1],
+ (double) -0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[38], /* W19 */
+ Y[38 + 1],
+ Y[102],
+ Y[102 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[102],
+ Y[102 + 1],
+ (double) -0.290284677254462, (double) -0.956940335732209);
+ BUTTERFLY_XY (Y[40], /* W20 */
+ Y[40 + 1],
+ Y[104],
+ Y[104 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[104],
+ Y[104 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[42], /* W21 */
+ Y[42 + 1],
+ Y[106],
+ Y[106 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[106],
+ Y[106 + 1],
+ (double) -0.471396736825998, (double) -0.881921264348355);
+ BUTTERFLY_XY (Y[44], /* W22 */
+ Y[44 + 1],
+ Y[108],
+ Y[108 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[108],
+ Y[108 + 1],
+ (double) -0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[46], /* W23 */
+ Y[46 + 1],
+ Y[110],
+ Y[110 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[110],
+ Y[110 + 1],
+ (double) -0.634393284163645, (double) -0.773010453362737);
+ BUTTERFLY_XX (Y[48], /* W24 */
+ Y[48 + 1],
+ Y[112],
+ Y[112 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[112],
+ Y[112 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[50], /* W25 */
+ Y[50 + 1],
+ Y[114],
+ Y[114 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[114],
+ Y[114 + 1],
+ (double) -0.773010453362737, (double) -0.634393284163645);
+ BUTTERFLY_XY (Y[52], /* W26 */
+ Y[52 + 1],
+ Y[116],
+ Y[116 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[116],
+ Y[116 + 1],
+ (double) -0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[54], /* W27 */
+ Y[54 + 1],
+ Y[118],
+ Y[118 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[118],
+ Y[118 + 1],
+ (double) -0.881921264348355, (double) -0.471396736825998);
+ BUTTERFLY_XY (Y[56], /* W28 */
+ Y[56 + 1],
+ Y[120],
+ Y[120 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[120],
+ Y[120 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[58], /* W29 */
+ Y[58 + 1],
+ Y[122],
+ Y[122 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[122],
+ Y[122 + 1],
+ (double) -0.956940335732209, (double) -0.290284677254462);
+ BUTTERFLY_XY (Y[60], /* W30 */
+ Y[60 + 1],
+ Y[124],
+ Y[124 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[124],
+ Y[124 + 1],
+ (double) -0.980785280403230, (double) -0.195090322016129);
+ BUTTERFLY_XY (Y[62], /* W31 */
+ Y[62 + 1],
+ Y[126],
+ Y[126 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[126],
+ Y[126 + 1],
+ (double) -0.995184726672197, (double) -0.098017140329561);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 64 F S S S S X)
+ **/
+static void
+gsl_power2_fft64synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform 32 times fft2 */
+ BUTTERFLY_10scale (X[0], X[0 + 1],
+ X[64], X[64 + 1],
+ Y[0], Y[0 + 1],
+ Y[2], Y[2 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[32], X[32 + 1],
+ X[96], X[96 + 1],
+ Y[4], Y[4 + 1],
+ Y[6], Y[6 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[16], X[16 + 1],
+ X[80], X[80 + 1],
+ Y[8], Y[8 + 1],
+ Y[10], Y[10 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[48], X[48 + 1],
+ X[112], X[112 + 1],
+ Y[12], Y[12 + 1],
+ Y[14], Y[14 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[8], X[8 + 1],
+ X[72], X[72 + 1],
+ Y[16], Y[16 + 1],
+ Y[18], Y[18 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[40], X[40 + 1],
+ X[104], X[104 + 1],
+ Y[20], Y[20 + 1],
+ Y[22], Y[22 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[24], X[24 + 1],
+ X[88], X[88 + 1],
+ Y[24], Y[24 + 1],
+ Y[26], Y[26 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[56], X[56 + 1],
+ X[120], X[120 + 1],
+ Y[28], Y[28 + 1],
+ Y[30], Y[30 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[4], X[4 + 1],
+ X[68], X[68 + 1],
+ Y[32], Y[32 + 1],
+ Y[34], Y[34 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[36], X[36 + 1],
+ X[100], X[100 + 1],
+ Y[36], Y[36 + 1],
+ Y[38], Y[38 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[20], X[20 + 1],
+ X[84], X[84 + 1],
+ Y[40], Y[40 + 1],
+ Y[42], Y[42 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[52], X[52 + 1],
+ X[116], X[116 + 1],
+ Y[44], Y[44 + 1],
+ Y[46], Y[46 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[12], X[12 + 1],
+ X[76], X[76 + 1],
+ Y[48], Y[48 + 1],
+ Y[50], Y[50 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[44], X[44 + 1],
+ X[108], X[108 + 1],
+ Y[52], Y[52 + 1],
+ Y[54], Y[54 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[28], X[28 + 1],
+ X[92], X[92 + 1],
+ Y[56], Y[56 + 1],
+ Y[58], Y[58 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[60], X[60 + 1],
+ X[124], X[124 + 1],
+ Y[60], Y[60 + 1],
+ Y[62], Y[62 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[2], X[2 + 1],
+ X[66], X[66 + 1],
+ Y[64], Y[64 + 1],
+ Y[66], Y[66 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[34], X[34 + 1],
+ X[98], X[98 + 1],
+ Y[68], Y[68 + 1],
+ Y[70], Y[70 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[18], X[18 + 1],
+ X[82], X[82 + 1],
+ Y[72], Y[72 + 1],
+ Y[74], Y[74 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[50], X[50 + 1],
+ X[114], X[114 + 1],
+ Y[76], Y[76 + 1],
+ Y[78], Y[78 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[10], X[10 + 1],
+ X[74], X[74 + 1],
+ Y[80], Y[80 + 1],
+ Y[82], Y[82 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[42], X[42 + 1],
+ X[106], X[106 + 1],
+ Y[84], Y[84 + 1],
+ Y[86], Y[86 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[26], X[26 + 1],
+ X[90], X[90 + 1],
+ Y[88], Y[88 + 1],
+ Y[90], Y[90 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[58], X[58 + 1],
+ X[122], X[122 + 1],
+ Y[92], Y[92 + 1],
+ Y[94], Y[94 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[6], X[6 + 1],
+ X[70], X[70 + 1],
+ Y[96], Y[96 + 1],
+ Y[98], Y[98 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[38], X[38 + 1],
+ X[102], X[102 + 1],
+ Y[100], Y[100 + 1],
+ Y[102], Y[102 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[22], X[22 + 1],
+ X[86], X[86 + 1],
+ Y[104], Y[104 + 1],
+ Y[106], Y[106 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[54], X[54 + 1],
+ X[118], X[118 + 1],
+ Y[108], Y[108 + 1],
+ Y[110], Y[110 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[14], X[14 + 1],
+ X[78], X[78 + 1],
+ Y[112], Y[112 + 1],
+ Y[114], Y[114 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[46], X[46 + 1],
+ X[110], X[110 + 1],
+ Y[116], Y[116 + 1],
+ Y[118], Y[118 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[30], X[30 + 1],
+ X[94], X[94 + 1],
+ Y[120], Y[120 + 1],
+ Y[122], Y[122 + 1],
+ 1.0 / (double) 64);
+ BUTTERFLY_10scale (X[62], X[62 + 1],
+ X[126], X[126 + 1],
+ Y[124], Y[124 + 1],
+ Y[126], Y[126 + 1],
+ 1.0 / (double) 64);
+
+ /* skipping 16 times fft4 */
+
+ /* skipping 8 times fft8 */
+
+ /* skipping 4 times fft16 */
+
+ /* skipping 2 times fft32 */
+
+ /* perform 1 times fft64 */
+ gsl_power2_fft64synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 128 S R R R R R F)
+ **/
+static void
+gsl_power2_fft128synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 64 times fft2 */
+
+ /* perform 32 times fft4 */
+ for (block = 0; block < 256; block += 8) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_0m (Y[block + 2], /* W32 */
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ }
+
+ /* perform 16 times fft8 */
+ for (block = 0; block < 256; block += 16) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_yY (Y[block + 2], /* W16 */
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_0m (Y[block + 4], /* W32 */
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XX (Y[block + 6], /* W48 */
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ }
+
+ /* perform 8 times fft16 */
+ for (block = 0; block < 256; block += 32) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W8 */
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_yY (Y[block + 4], /* W16 */
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[block + 6], /* W24 */
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_0m (Y[block + 8], /* W32 */
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[block + 10], /* W40 */
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XX (Y[block + 12], /* W48 */
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[block + 14], /* W56 */
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ }
+
+ /* perform 4 times fft32 */
+ for (block = 0; block < 256; block += 64) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W4 */
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ (double) +0.980785280403230, (double) -0.195090322016128);
+ BUTTERFLY_XY (Y[block + 4], /* W8 */
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[block + 6], /* W12 */
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ (double) +0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_yY (Y[block + 8], /* W16 */
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[block + 10], /* W20 */
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ (double) +0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[block + 12], /* W24 */
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[block + 14], /* W28 */
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ (double) +0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_0m (Y[block + 16], /* W32 */
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[block + 18], /* W36 */
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ (double) -0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[block + 20], /* W40 */
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[block + 22], /* W44 */
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ (double) -0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XX (Y[block + 24], /* W48 */
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[block + 26], /* W52 */
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ (double) -0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[block + 28], /* W56 */
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[block + 30], /* W60 */
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ (double) -0.980785280403230, (double) -0.195090322016129);
+ }
+
+ /* perform 2 times fft64 */
+ for (block = 0; block < 256; block += 128) {
+ BUTTERFLY_10 (Y[block + 0], /* W0 */
+ Y[block + 0 + 1],
+ Y[block + 64],
+ Y[block + 64 + 1],
+ Y[block + 0],
+ Y[block + 0 + 1],
+ Y[block + 64],
+ Y[block + 64 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[block + 2], /* W2 */
+ Y[block + 2 + 1],
+ Y[block + 66],
+ Y[block + 66 + 1],
+ Y[block + 2],
+ Y[block + 2 + 1],
+ Y[block + 66],
+ Y[block + 66 + 1],
+ (double) +0.995184726672197, (double) -0.098017140329561);
+ BUTTERFLY_XY (Y[block + 4], /* W4 */
+ Y[block + 4 + 1],
+ Y[block + 68],
+ Y[block + 68 + 1],
+ Y[block + 4],
+ Y[block + 4 + 1],
+ Y[block + 68],
+ Y[block + 68 + 1],
+ (double) +0.980785280403230, (double) -0.195090322016128);
+ BUTTERFLY_XY (Y[block + 6], /* W6 */
+ Y[block + 6 + 1],
+ Y[block + 70],
+ Y[block + 70 + 1],
+ Y[block + 6],
+ Y[block + 6 + 1],
+ Y[block + 70],
+ Y[block + 70 + 1],
+ (double) +0.956940335732209, (double) -0.290284677254462);
+ BUTTERFLY_XY (Y[block + 8], /* W8 */
+ Y[block + 8 + 1],
+ Y[block + 72],
+ Y[block + 72 + 1],
+ Y[block + 8],
+ Y[block + 8 + 1],
+ Y[block + 72],
+ Y[block + 72 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[block + 10], /* W10 */
+ Y[block + 10 + 1],
+ Y[block + 74],
+ Y[block + 74 + 1],
+ Y[block + 10],
+ Y[block + 10 + 1],
+ Y[block + 74],
+ Y[block + 74 + 1],
+ (double) +0.881921264348355, (double) -0.471396736825998);
+ BUTTERFLY_XY (Y[block + 12], /* W12 */
+ Y[block + 12 + 1],
+ Y[block + 76],
+ Y[block + 76 + 1],
+ Y[block + 12],
+ Y[block + 12 + 1],
+ Y[block + 76],
+ Y[block + 76 + 1],
+ (double) +0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[block + 14], /* W14 */
+ Y[block + 14 + 1],
+ Y[block + 78],
+ Y[block + 78 + 1],
+ Y[block + 14],
+ Y[block + 14 + 1],
+ Y[block + 78],
+ Y[block + 78 + 1],
+ (double) +0.773010453362737, (double) -0.634393284163645);
+ BUTTERFLY_yY (Y[block + 16], /* W16 */
+ Y[block + 16 + 1],
+ Y[block + 80],
+ Y[block + 80 + 1],
+ Y[block + 16],
+ Y[block + 16 + 1],
+ Y[block + 80],
+ Y[block + 80 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[block + 18], /* W18 */
+ Y[block + 18 + 1],
+ Y[block + 82],
+ Y[block + 82 + 1],
+ Y[block + 18],
+ Y[block + 18 + 1],
+ Y[block + 82],
+ Y[block + 82 + 1],
+ (double) +0.634393284163645, (double) -0.773010453362737);
+ BUTTERFLY_XY (Y[block + 20], /* W20 */
+ Y[block + 20 + 1],
+ Y[block + 84],
+ Y[block + 84 + 1],
+ Y[block + 20],
+ Y[block + 20 + 1],
+ Y[block + 84],
+ Y[block + 84 + 1],
+ (double) +0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[block + 22], /* W22 */
+ Y[block + 22 + 1],
+ Y[block + 86],
+ Y[block + 86 + 1],
+ Y[block + 22],
+ Y[block + 22 + 1],
+ Y[block + 86],
+ Y[block + 86 + 1],
+ (double) +0.471396736825998, (double) -0.881921264348355);
+ BUTTERFLY_XY (Y[block + 24], /* W24 */
+ Y[block + 24 + 1],
+ Y[block + 88],
+ Y[block + 88 + 1],
+ Y[block + 24],
+ Y[block + 24 + 1],
+ Y[block + 88],
+ Y[block + 88 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[block + 26], /* W26 */
+ Y[block + 26 + 1],
+ Y[block + 90],
+ Y[block + 90 + 1],
+ Y[block + 26],
+ Y[block + 26 + 1],
+ Y[block + 90],
+ Y[block + 90 + 1],
+ (double) +0.290284677254462, (double) -0.956940335732209);
+ BUTTERFLY_XY (Y[block + 28], /* W28 */
+ Y[block + 28 + 1],
+ Y[block + 92],
+ Y[block + 92 + 1],
+ Y[block + 28],
+ Y[block + 28 + 1],
+ Y[block + 92],
+ Y[block + 92 + 1],
+ (double) +0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[block + 30], /* W30 */
+ Y[block + 30 + 1],
+ Y[block + 94],
+ Y[block + 94 + 1],
+ Y[block + 30],
+ Y[block + 30 + 1],
+ Y[block + 94],
+ Y[block + 94 + 1],
+ (double) +0.098017140329561, (double) -0.995184726672197);
+ BUTTERFLY_0m (Y[block + 32], /* W32 */
+ Y[block + 32 + 1],
+ Y[block + 96],
+ Y[block + 96 + 1],
+ Y[block + 32],
+ Y[block + 32 + 1],
+ Y[block + 96],
+ Y[block + 96 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[block + 34], /* W34 */
+ Y[block + 34 + 1],
+ Y[block + 98],
+ Y[block + 98 + 1],
+ Y[block + 34],
+ Y[block + 34 + 1],
+ Y[block + 98],
+ Y[block + 98 + 1],
+ (double) -0.098017140329561, (double) -0.995184726672197);
+ BUTTERFLY_XY (Y[block + 36], /* W36 */
+ Y[block + 36 + 1],
+ Y[block + 100],
+ Y[block + 100 + 1],
+ Y[block + 36],
+ Y[block + 36 + 1],
+ Y[block + 100],
+ Y[block + 100 + 1],
+ (double) -0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[block + 38], /* W38 */
+ Y[block + 38 + 1],
+ Y[block + 102],
+ Y[block + 102 + 1],
+ Y[block + 38],
+ Y[block + 38 + 1],
+ Y[block + 102],
+ Y[block + 102 + 1],
+ (double) -0.290284677254462, (double) -0.956940335732209);
+ BUTTERFLY_XY (Y[block + 40], /* W40 */
+ Y[block + 40 + 1],
+ Y[block + 104],
+ Y[block + 104 + 1],
+ Y[block + 40],
+ Y[block + 40 + 1],
+ Y[block + 104],
+ Y[block + 104 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[block + 42], /* W42 */
+ Y[block + 42 + 1],
+ Y[block + 106],
+ Y[block + 106 + 1],
+ Y[block + 42],
+ Y[block + 42 + 1],
+ Y[block + 106],
+ Y[block + 106 + 1],
+ (double) -0.471396736825998, (double) -0.881921264348355);
+ BUTTERFLY_XY (Y[block + 44], /* W44 */
+ Y[block + 44 + 1],
+ Y[block + 108],
+ Y[block + 108 + 1],
+ Y[block + 44],
+ Y[block + 44 + 1],
+ Y[block + 108],
+ Y[block + 108 + 1],
+ (double) -0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[block + 46], /* W46 */
+ Y[block + 46 + 1],
+ Y[block + 110],
+ Y[block + 110 + 1],
+ Y[block + 46],
+ Y[block + 46 + 1],
+ Y[block + 110],
+ Y[block + 110 + 1],
+ (double) -0.634393284163645, (double) -0.773010453362737);
+ BUTTERFLY_XX (Y[block + 48], /* W48 */
+ Y[block + 48 + 1],
+ Y[block + 112],
+ Y[block + 112 + 1],
+ Y[block + 48],
+ Y[block + 48 + 1],
+ Y[block + 112],
+ Y[block + 112 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[block + 50], /* W50 */
+ Y[block + 50 + 1],
+ Y[block + 114],
+ Y[block + 114 + 1],
+ Y[block + 50],
+ Y[block + 50 + 1],
+ Y[block + 114],
+ Y[block + 114 + 1],
+ (double) -0.773010453362737, (double) -0.634393284163645);
+ BUTTERFLY_XY (Y[block + 52], /* W52 */
+ Y[block + 52 + 1],
+ Y[block + 116],
+ Y[block + 116 + 1],
+ Y[block + 52],
+ Y[block + 52 + 1],
+ Y[block + 116],
+ Y[block + 116 + 1],
+ (double) -0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[block + 54], /* W54 */
+ Y[block + 54 + 1],
+ Y[block + 118],
+ Y[block + 118 + 1],
+ Y[block + 54],
+ Y[block + 54 + 1],
+ Y[block + 118],
+ Y[block + 118 + 1],
+ (double) -0.881921264348355, (double) -0.471396736825998);
+ BUTTERFLY_XY (Y[block + 56], /* W56 */
+ Y[block + 56 + 1],
+ Y[block + 120],
+ Y[block + 120 + 1],
+ Y[block + 56],
+ Y[block + 56 + 1],
+ Y[block + 120],
+ Y[block + 120 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[block + 58], /* W58 */
+ Y[block + 58 + 1],
+ Y[block + 122],
+ Y[block + 122 + 1],
+ Y[block + 58],
+ Y[block + 58 + 1],
+ Y[block + 122],
+ Y[block + 122 + 1],
+ (double) -0.956940335732209, (double) -0.290284677254462);
+ BUTTERFLY_XY (Y[block + 60], /* W60 */
+ Y[block + 60 + 1],
+ Y[block + 124],
+ Y[block + 124 + 1],
+ Y[block + 60],
+ Y[block + 60 + 1],
+ Y[block + 124],
+ Y[block + 124 + 1],
+ (double) -0.980785280403230, (double) -0.195090322016129);
+ BUTTERFLY_XY (Y[block + 62], /* W62 */
+ Y[block + 62 + 1],
+ Y[block + 126],
+ Y[block + 126 + 1],
+ Y[block + 62],
+ Y[block + 62 + 1],
+ Y[block + 126],
+ Y[block + 126 + 1],
+ (double) -0.995184726672197, (double) -0.098017140329561);
+ }
+
+ /* perform 1 times fft128 */
+ BUTTERFLY_10 (Y[0], /* W0 */
+ Y[0 + 1],
+ Y[128],
+ Y[128 + 1],
+ Y[0],
+ Y[0 + 1],
+ Y[128],
+ Y[128 + 1],
+ (double) +1.000000000000000, (double) +0.000000000000000);
+ BUTTERFLY_XY (Y[2], /* W1 */
+ Y[2 + 1],
+ Y[130],
+ Y[130 + 1],
+ Y[2],
+ Y[2 + 1],
+ Y[130],
+ Y[130 + 1],
+ (double) +0.998795456205172, (double) -0.049067674327418);
+ BUTTERFLY_XY (Y[4], /* W2 */
+ Y[4 + 1],
+ Y[132],
+ Y[132 + 1],
+ Y[4],
+ Y[4 + 1],
+ Y[132],
+ Y[132 + 1],
+ (double) +0.995184726672197, (double) -0.098017140329561);
+ BUTTERFLY_XY (Y[6], /* W3 */
+ Y[6 + 1],
+ Y[134],
+ Y[134 + 1],
+ Y[6],
+ Y[6 + 1],
+ Y[134],
+ Y[134 + 1],
+ (double) +0.989176509964781, (double) -0.146730474455362);
+ BUTTERFLY_XY (Y[8], /* W4 */
+ Y[8 + 1],
+ Y[136],
+ Y[136 + 1],
+ Y[8],
+ Y[8 + 1],
+ Y[136],
+ Y[136 + 1],
+ (double) +0.980785280403230, (double) -0.195090322016128);
+ BUTTERFLY_XY (Y[10], /* W5 */
+ Y[10 + 1],
+ Y[138],
+ Y[138 + 1],
+ Y[10],
+ Y[10 + 1],
+ Y[138],
+ Y[138 + 1],
+ (double) +0.970031253194544, (double) -0.242980179903264);
+ BUTTERFLY_XY (Y[12], /* W6 */
+ Y[12 + 1],
+ Y[140],
+ Y[140 + 1],
+ Y[12],
+ Y[12 + 1],
+ Y[140],
+ Y[140 + 1],
+ (double) +0.956940335732209, (double) -0.290284677254462);
+ BUTTERFLY_XY (Y[14], /* W7 */
+ Y[14 + 1],
+ Y[142],
+ Y[142 + 1],
+ Y[14],
+ Y[14 + 1],
+ Y[142],
+ Y[142 + 1],
+ (double) +0.941544065183021, (double) -0.336889853392220);
+ BUTTERFLY_XY (Y[16], /* W8 */
+ Y[16 + 1],
+ Y[144],
+ Y[144 + 1],
+ Y[16],
+ Y[16 + 1],
+ Y[144],
+ Y[144 + 1],
+ (double) +0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[18], /* W9 */
+ Y[18 + 1],
+ Y[146],
+ Y[146 + 1],
+ Y[18],
+ Y[18 + 1],
+ Y[146],
+ Y[146 + 1],
+ (double) +0.903989293123443, (double) -0.427555093430282);
+ BUTTERFLY_XY (Y[20], /* W10 */
+ Y[20 + 1],
+ Y[148],
+ Y[148 + 1],
+ Y[20],
+ Y[20 + 1],
+ Y[148],
+ Y[148 + 1],
+ (double) +0.881921264348355, (double) -0.471396736825998);
+ BUTTERFLY_XY (Y[22], /* W11 */
+ Y[22 + 1],
+ Y[150],
+ Y[150 + 1],
+ Y[22],
+ Y[22 + 1],
+ Y[150],
+ Y[150 + 1],
+ (double) +0.857728610000272, (double) -0.514102744193222);
+ BUTTERFLY_XY (Y[24], /* W12 */
+ Y[24 + 1],
+ Y[152],
+ Y[152 + 1],
+ Y[24],
+ Y[24 + 1],
+ Y[152],
+ Y[152 + 1],
+ (double) +0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[26], /* W13 */
+ Y[26 + 1],
+ Y[154],
+ Y[154 + 1],
+ Y[26],
+ Y[26 + 1],
+ Y[154],
+ Y[154 + 1],
+ (double) +0.803207531480645, (double) -0.595699304492433);
+ BUTTERFLY_XY (Y[28], /* W14 */
+ Y[28 + 1],
+ Y[156],
+ Y[156 + 1],
+ Y[28],
+ Y[28 + 1],
+ Y[156],
+ Y[156 + 1],
+ (double) +0.773010453362737, (double) -0.634393284163645);
+ BUTTERFLY_XY (Y[30], /* W15 */
+ Y[30 + 1],
+ Y[158],
+ Y[158 + 1],
+ Y[30],
+ Y[30 + 1],
+ Y[158],
+ Y[158 + 1],
+ (double) +0.740951125354959, (double) -0.671558954847018);
+ BUTTERFLY_yY (Y[32], /* W16 */
+ Y[32 + 1],
+ Y[160],
+ Y[160 + 1],
+ Y[32],
+ Y[32 + 1],
+ Y[160],
+ Y[160 + 1],
+ (double) +0.707106781186548, (double) -0.707106781186547);
+ BUTTERFLY_XY (Y[34], /* W17 */
+ Y[34 + 1],
+ Y[162],
+ Y[162 + 1],
+ Y[34],
+ Y[34 + 1],
+ Y[162],
+ Y[162 + 1],
+ (double) +0.671558954847018, (double) -0.740951125354959);
+ BUTTERFLY_XY (Y[36], /* W18 */
+ Y[36 + 1],
+ Y[164],
+ Y[164 + 1],
+ Y[36],
+ Y[36 + 1],
+ Y[164],
+ Y[164 + 1],
+ (double) +0.634393284163645, (double) -0.773010453362737);
+ BUTTERFLY_XY (Y[38], /* W19 */
+ Y[38 + 1],
+ Y[166],
+ Y[166 + 1],
+ Y[38],
+ Y[38 + 1],
+ Y[166],
+ Y[166 + 1],
+ (double) +0.595699304492433, (double) -0.803207531480645);
+ BUTTERFLY_XY (Y[40], /* W20 */
+ Y[40 + 1],
+ Y[168],
+ Y[168 + 1],
+ Y[40],
+ Y[40 + 1],
+ Y[168],
+ Y[168 + 1],
+ (double) +0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[42], /* W21 */
+ Y[42 + 1],
+ Y[170],
+ Y[170 + 1],
+ Y[42],
+ Y[42 + 1],
+ Y[170],
+ Y[170 + 1],
+ (double) +0.514102744193222, (double) -0.857728610000272);
+ BUTTERFLY_XY (Y[44], /* W22 */
+ Y[44 + 1],
+ Y[172],
+ Y[172 + 1],
+ Y[44],
+ Y[44 + 1],
+ Y[172],
+ Y[172 + 1],
+ (double) +0.471396736825998, (double) -0.881921264348355);
+ BUTTERFLY_XY (Y[46], /* W23 */
+ Y[46 + 1],
+ Y[174],
+ Y[174 + 1],
+ Y[46],
+ Y[46 + 1],
+ Y[174],
+ Y[174 + 1],
+ (double) +0.427555093430282, (double) -0.903989293123443);
+ BUTTERFLY_XY (Y[48], /* W24 */
+ Y[48 + 1],
+ Y[176],
+ Y[176 + 1],
+ Y[48],
+ Y[48 + 1],
+ Y[176],
+ Y[176 + 1],
+ (double) +0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[50], /* W25 */
+ Y[50 + 1],
+ Y[178],
+ Y[178 + 1],
+ Y[50],
+ Y[50 + 1],
+ Y[178],
+ Y[178 + 1],
+ (double) +0.336889853392220, (double) -0.941544065183021);
+ BUTTERFLY_XY (Y[52], /* W26 */
+ Y[52 + 1],
+ Y[180],
+ Y[180 + 1],
+ Y[52],
+ Y[52 + 1],
+ Y[180],
+ Y[180 + 1],
+ (double) +0.290284677254462, (double) -0.956940335732209);
+ BUTTERFLY_XY (Y[54], /* W27 */
+ Y[54 + 1],
+ Y[182],
+ Y[182 + 1],
+ Y[54],
+ Y[54 + 1],
+ Y[182],
+ Y[182 + 1],
+ (double) +0.242980179903264, (double) -0.970031253194544);
+ BUTTERFLY_XY (Y[56], /* W28 */
+ Y[56 + 1],
+ Y[184],
+ Y[184 + 1],
+ Y[56],
+ Y[56 + 1],
+ Y[184],
+ Y[184 + 1],
+ (double) +0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[58], /* W29 */
+ Y[58 + 1],
+ Y[186],
+ Y[186 + 1],
+ Y[58],
+ Y[58 + 1],
+ Y[186],
+ Y[186 + 1],
+ (double) +0.146730474455362, (double) -0.989176509964781);
+ BUTTERFLY_XY (Y[60], /* W30 */
+ Y[60 + 1],
+ Y[188],
+ Y[188 + 1],
+ Y[60],
+ Y[60 + 1],
+ Y[188],
+ Y[188 + 1],
+ (double) +0.098017140329561, (double) -0.995184726672197);
+ BUTTERFLY_XY (Y[62], /* W31 */
+ Y[62 + 1],
+ Y[190],
+ Y[190 + 1],
+ Y[62],
+ Y[62 + 1],
+ Y[190],
+ Y[190 + 1],
+ (double) +0.049067674327418, (double) -0.998795456205172);
+ BUTTERFLY_0m (Y[64], /* W32 */
+ Y[64 + 1],
+ Y[192],
+ Y[192 + 1],
+ Y[64],
+ Y[64 + 1],
+ Y[192],
+ Y[192 + 1],
+ (double) +0.000000000000000, (double) -1.000000000000000);
+ BUTTERFLY_XY (Y[66], /* W33 */
+ Y[66 + 1],
+ Y[194],
+ Y[194 + 1],
+ Y[66],
+ Y[66 + 1],
+ Y[194],
+ Y[194 + 1],
+ (double) -0.049067674327418, (double) -0.998795456205172);
+ BUTTERFLY_XY (Y[68], /* W34 */
+ Y[68 + 1],
+ Y[196],
+ Y[196 + 1],
+ Y[68],
+ Y[68 + 1],
+ Y[196],
+ Y[196 + 1],
+ (double) -0.098017140329561, (double) -0.995184726672197);
+ BUTTERFLY_XY (Y[70], /* W35 */
+ Y[70 + 1],
+ Y[198],
+ Y[198 + 1],
+ Y[70],
+ Y[70 + 1],
+ Y[198],
+ Y[198 + 1],
+ (double) -0.146730474455362, (double) -0.989176509964781);
+ BUTTERFLY_XY (Y[72], /* W36 */
+ Y[72 + 1],
+ Y[200],
+ Y[200 + 1],
+ Y[72],
+ Y[72 + 1],
+ Y[200],
+ Y[200 + 1],
+ (double) -0.195090322016128, (double) -0.980785280403230);
+ BUTTERFLY_XY (Y[74], /* W37 */
+ Y[74 + 1],
+ Y[202],
+ Y[202 + 1],
+ Y[74],
+ Y[74 + 1],
+ Y[202],
+ Y[202 + 1],
+ (double) -0.242980179903264, (double) -0.970031253194544);
+ BUTTERFLY_XY (Y[76], /* W38 */
+ Y[76 + 1],
+ Y[204],
+ Y[204 + 1],
+ Y[76],
+ Y[76 + 1],
+ Y[204],
+ Y[204 + 1],
+ (double) -0.290284677254462, (double) -0.956940335732209);
+ BUTTERFLY_XY (Y[78], /* W39 */
+ Y[78 + 1],
+ Y[206],
+ Y[206 + 1],
+ Y[78],
+ Y[78 + 1],
+ Y[206],
+ Y[206 + 1],
+ (double) -0.336889853392220, (double) -0.941544065183021);
+ BUTTERFLY_XY (Y[80], /* W40 */
+ Y[80 + 1],
+ Y[208],
+ Y[208 + 1],
+ Y[80],
+ Y[80 + 1],
+ Y[208],
+ Y[208 + 1],
+ (double) -0.382683432365090, (double) -0.923879532511287);
+ BUTTERFLY_XY (Y[82], /* W41 */
+ Y[82 + 1],
+ Y[210],
+ Y[210 + 1],
+ Y[82],
+ Y[82 + 1],
+ Y[210],
+ Y[210 + 1],
+ (double) -0.427555093430282, (double) -0.903989293123443);
+ BUTTERFLY_XY (Y[84], /* W42 */
+ Y[84 + 1],
+ Y[212],
+ Y[212 + 1],
+ Y[84],
+ Y[84 + 1],
+ Y[212],
+ Y[212 + 1],
+ (double) -0.471396736825998, (double) -0.881921264348355);
+ BUTTERFLY_XY (Y[86], /* W43 */
+ Y[86 + 1],
+ Y[214],
+ Y[214 + 1],
+ Y[86],
+ Y[86 + 1],
+ Y[214],
+ Y[214 + 1],
+ (double) -0.514102744193222, (double) -0.857728610000272);
+ BUTTERFLY_XY (Y[88], /* W44 */
+ Y[88 + 1],
+ Y[216],
+ Y[216 + 1],
+ Y[88],
+ Y[88 + 1],
+ Y[216],
+ Y[216 + 1],
+ (double) -0.555570233019602, (double) -0.831469612302545);
+ BUTTERFLY_XY (Y[90], /* W45 */
+ Y[90 + 1],
+ Y[218],
+ Y[218 + 1],
+ Y[90],
+ Y[90 + 1],
+ Y[218],
+ Y[218 + 1],
+ (double) -0.595699304492433, (double) -0.803207531480645);
+ BUTTERFLY_XY (Y[92], /* W46 */
+ Y[92 + 1],
+ Y[220],
+ Y[220 + 1],
+ Y[92],
+ Y[92 + 1],
+ Y[220],
+ Y[220 + 1],
+ (double) -0.634393284163645, (double) -0.773010453362737);
+ BUTTERFLY_XY (Y[94], /* W47 */
+ Y[94 + 1],
+ Y[222],
+ Y[222 + 1],
+ Y[94],
+ Y[94 + 1],
+ Y[222],
+ Y[222 + 1],
+ (double) -0.671558954847018, (double) -0.740951125354959);
+ BUTTERFLY_XX (Y[96], /* W48 */
+ Y[96 + 1],
+ Y[224],
+ Y[224 + 1],
+ Y[96],
+ Y[96 + 1],
+ Y[224],
+ Y[224 + 1],
+ (double) -0.707106781186547, (double) -0.707106781186548);
+ BUTTERFLY_XY (Y[98], /* W49 */
+ Y[98 + 1],
+ Y[226],
+ Y[226 + 1],
+ Y[98],
+ Y[98 + 1],
+ Y[226],
+ Y[226 + 1],
+ (double) -0.740951125354959, (double) -0.671558954847019);
+ BUTTERFLY_XY (Y[100], /* W50 */
+ Y[100 + 1],
+ Y[228],
+ Y[228 + 1],
+ Y[100],
+ Y[100 + 1],
+ Y[228],
+ Y[228 + 1],
+ (double) -0.773010453362737, (double) -0.634393284163645);
+ BUTTERFLY_XY (Y[102], /* W51 */
+ Y[102 + 1],
+ Y[230],
+ Y[230 + 1],
+ Y[102],
+ Y[102 + 1],
+ Y[230],
+ Y[230 + 1],
+ (double) -0.803207531480645, (double) -0.595699304492433);
+ BUTTERFLY_XY (Y[104], /* W52 */
+ Y[104 + 1],
+ Y[232],
+ Y[232 + 1],
+ Y[104],
+ Y[104 + 1],
+ Y[232],
+ Y[232 + 1],
+ (double) -0.831469612302545, (double) -0.555570233019602);
+ BUTTERFLY_XY (Y[106], /* W53 */
+ Y[106 + 1],
+ Y[234],
+ Y[234 + 1],
+ Y[106],
+ Y[106 + 1],
+ Y[234],
+ Y[234 + 1],
+ (double) -0.857728610000272, (double) -0.514102744193222);
+ BUTTERFLY_XY (Y[108], /* W54 */
+ Y[108 + 1],
+ Y[236],
+ Y[236 + 1],
+ Y[108],
+ Y[108 + 1],
+ Y[236],
+ Y[236 + 1],
+ (double) -0.881921264348355, (double) -0.471396736825998);
+ BUTTERFLY_XY (Y[110], /* W55 */
+ Y[110 + 1],
+ Y[238],
+ Y[238 + 1],
+ Y[110],
+ Y[110 + 1],
+ Y[238],
+ Y[238 + 1],
+ (double) -0.903989293123443, (double) -0.427555093430282);
+ BUTTERFLY_XY (Y[112], /* W56 */
+ Y[112 + 1],
+ Y[240],
+ Y[240 + 1],
+ Y[112],
+ Y[112 + 1],
+ Y[240],
+ Y[240 + 1],
+ (double) -0.923879532511287, (double) -0.382683432365090);
+ BUTTERFLY_XY (Y[114], /* W57 */
+ Y[114 + 1],
+ Y[242],
+ Y[242 + 1],
+ Y[114],
+ Y[114 + 1],
+ Y[242],
+ Y[242 + 1],
+ (double) -0.941544065183021, (double) -0.336889853392220);
+ BUTTERFLY_XY (Y[116], /* W58 */
+ Y[116 + 1],
+ Y[244],
+ Y[244 + 1],
+ Y[116],
+ Y[116 + 1],
+ Y[244],
+ Y[244 + 1],
+ (double) -0.956940335732209, (double) -0.290284677254462);
+ BUTTERFLY_XY (Y[118], /* W59 */
+ Y[118 + 1],
+ Y[246],
+ Y[246 + 1],
+ Y[118],
+ Y[118 + 1],
+ Y[246],
+ Y[246 + 1],
+ (double) -0.970031253194544, (double) -0.242980179903264);
+ BUTTERFLY_XY (Y[120], /* W60 */
+ Y[120 + 1],
+ Y[248],
+ Y[248 + 1],
+ Y[120],
+ Y[120 + 1],
+ Y[248],
+ Y[248 + 1],
+ (double) -0.980785280403230, (double) -0.195090322016129);
+ BUTTERFLY_XY (Y[122], /* W61 */
+ Y[122 + 1],
+ Y[250],
+ Y[250 + 1],
+ Y[122],
+ Y[122 + 1],
+ Y[250],
+ Y[250 + 1],
+ (double) -0.989176509964781, (double) -0.146730474455362);
+ BUTTERFLY_XY (Y[124], /* W62 */
+ Y[124 + 1],
+ Y[252],
+ Y[252 + 1],
+ Y[124],
+ Y[124 + 1],
+ Y[252],
+ Y[252 + 1],
+ (double) -0.995184726672197, (double) -0.098017140329561);
+ BUTTERFLY_XY (Y[126], /* W63 */
+ Y[126 + 1],
+ Y[254],
+ Y[254 + 1],
+ Y[126],
+ Y[126 + 1],
+ Y[254],
+ Y[254 + 1],
+ (double) -0.998795456205172, (double) -0.049067674327418);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 128 L S S S S S X)
+ **/
+static void
+gsl_power2_fft128synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (128, X, Y);
+
+ /* skipping 32 times fft4 */
+
+ /* skipping 16 times fft8 */
+
+ /* skipping 8 times fft16 */
+
+ /* skipping 4 times fft32 */
+
+ /* skipping 2 times fft64 */
+
+ /* perform 1 times fft128 */
+ gsl_power2_fft128synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 256 S S S S S S X T)
+ **/
+static void
+gsl_power2_fft256synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 128 times fft2 */
+
+ /* skipping 64 times fft4 */
+
+ /* skipping 32 times fft8 */
+
+ /* skipping 16 times fft16 */
+
+ /* skipping 8 times fft32 */
+
+ /* skipping 4 times fft64 */
+
+ /* perform 2 times fft128 */
+ gsl_power2_fft128synthesis_skip2 (X, Y);
+ gsl_power2_fft128synthesis_skip2 (X + 256, Y + 256);
+
+ /* perform 1 times fft256 */
+ {
+ static const double Wconst256[] = {
+ +0.999698818696204, -0.024541228522912,
+ +0.998795456205172, -0.049067674327418,
+ +0.997290456678690, -0.073564563599667,
+ +0.995184726672197, -0.098017140329561,
+ +0.992479534598710, -0.122410675199216,
+ +0.989176509964781, -0.146730474455362,
+ +0.985277642388941, -0.170961888760301,
+ +0.980785280403230, -0.195090322016128,
+ +0.975702130038529, -0.219101240156870,
+ +0.970031253194544, -0.242980179903264,
+ +0.963776065795440, -0.266712757474898,
+ +0.956940335732209, -0.290284677254462,
+ +0.949528180593037, -0.313681740398892,
+ +0.941544065183021, -0.336889853392220,
+ +0.932992798834739, -0.359895036534988,
+ +0.923879532511287, -0.382683432365090,
+ +0.914209755703531, -0.405241314004990,
+ +0.903989293123443, -0.427555093430282,
+ +0.893224301195515, -0.449611329654607,
+ +0.881921264348355, -0.471396736825998,
+ +0.870086991108711, -0.492898192229784,
+ +0.857728610000272, -0.514102744193222,
+ +0.844853565249707, -0.534997619887097,
+ +0.831469612302545, -0.555570233019602,
+ +0.817584813151584, -0.575808191417845,
+ +0.803207531480645, -0.595699304492433,
+ +0.788346427626606, -0.615231590580627,
+ +0.773010453362737, -0.634393284163645,
+ +0.757208846506485, -0.653172842953777,
+ +0.740951125354959, -0.671558954847018,
+ +0.724247082951467, -0.689540544737067,
+ +0.707106781186548, -0.707106781186547,
+ +0.689540544737067, -0.724247082951467,
+ +0.671558954847018, -0.740951125354959,
+ +0.653172842953777, -0.757208846506484,
+ +0.634393284163645, -0.773010453362737,
+ +0.615231590580627, -0.788346427626606,
+ +0.595699304492433, -0.803207531480645,
+ +0.575808191417845, -0.817584813151584,
+ +0.555570233019602, -0.831469612302545,
+ +0.534997619887097, -0.844853565249707,
+ +0.514102744193222, -0.857728610000272,
+ +0.492898192229784, -0.870086991108711,
+ +0.471396736825998, -0.881921264348355,
+ +0.449611329654607, -0.893224301195515,
+ +0.427555093430282, -0.903989293123443,
+ +0.405241314004990, -0.914209755703531,
+ +0.382683432365090, -0.923879532511287,
+ +0.359895036534988, -0.932992798834739,
+ +0.336889853392220, -0.941544065183021,
+ +0.313681740398892, -0.949528180593037,
+ +0.290284677254462, -0.956940335732209,
+ +0.266712757474898, -0.963776065795440,
+ +0.242980179903264, -0.970031253194544,
+ +0.219101240156870, -0.975702130038529,
+ +0.195090322016128, -0.980785280403230,
+ +0.170961888760301, -0.985277642388941,
+ +0.146730474455362, -0.989176509964781,
+ +0.122410675199216, -0.992479534598710,
+ +0.098017140329561, -0.995184726672197,
+ +0.073564563599667, -0.997290456678690,
+ +0.049067674327418, -0.998795456205172,
+ +0.024541228522912, -0.999698818696204,
+ };
+ const double *W = Wconst256 - 2;
+ double *Z = Y + 128;
+ for (offset = 0; offset < 512; offset += 512) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ __1, __0);
+ BUTTERFLY_0m (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ __0, __1);
+ }
+ for (butterfly = 2; butterfly < 128; butterfly += 2) {
+ Wre = W[butterfly]; Wim = W[butterfly + 1];
+ for (block = 0; block < 512; block += 512) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Wre, Wim);
+ BUTTERFLY_yX (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Wre, Wim);
+ }
+ }
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 256 L S S S S S S X)
+ **/
+static void
+gsl_power2_fft256synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (256, X, Y);
+
+ /* skipping 64 times fft4 */
+
+ /* skipping 32 times fft8 */
+
+ /* skipping 16 times fft16 */
+
+ /* skipping 8 times fft32 */
+
+ /* skipping 4 times fft64 */
+
+ /* skipping 2 times fft128 */
+
+ /* perform 1 times fft256 */
+ gsl_power2_fft256synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 512 S S S S S S X T T)
+ **/
+static void
+gsl_power2_fft512synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 256 times fft2 */
+
+ /* skipping 128 times fft4 */
+
+ /* skipping 64 times fft8 */
+
+ /* skipping 32 times fft16 */
+
+ /* skipping 16 times fft32 */
+
+ /* skipping 8 times fft64 */
+
+ /* perform 4 times fft128 */
+ gsl_power2_fft128synthesis_skip2 (X, Y);
+ gsl_power2_fft128synthesis_skip2 (X + 256, Y + 256);
+ gsl_power2_fft128synthesis_skip2 (X + 512, Y + 512);
+ gsl_power2_fft128synthesis_skip2 (X + 768, Y + 768);
+
+ /* perform 2 times fft256 */
+ {
+ static const double Wconst256[] = {
+ +0.999698818696204, -0.024541228522912,
+ +0.998795456205172, -0.049067674327418,
+ +0.997290456678690, -0.073564563599667,
+ +0.995184726672197, -0.098017140329561,
+ +0.992479534598710, -0.122410675199216,
+ +0.989176509964781, -0.146730474455362,
+ +0.985277642388941, -0.170961888760301,
+ +0.980785280403230, -0.195090322016128,
+ +0.975702130038529, -0.219101240156870,
+ +0.970031253194544, -0.242980179903264,
+ +0.963776065795440, -0.266712757474898,
+ +0.956940335732209, -0.290284677254462,
+ +0.949528180593037, -0.313681740398892,
+ +0.941544065183021, -0.336889853392220,
+ +0.932992798834739, -0.359895036534988,
+ +0.923879532511287, -0.382683432365090,
+ +0.914209755703531, -0.405241314004990,
+ +0.903989293123443, -0.427555093430282,
+ +0.893224301195515, -0.449611329654607,
+ +0.881921264348355, -0.471396736825998,
+ +0.870086991108711, -0.492898192229784,
+ +0.857728610000272, -0.514102744193222,
+ +0.844853565249707, -0.534997619887097,
+ +0.831469612302545, -0.555570233019602,
+ +0.817584813151584, -0.575808191417845,
+ +0.803207531480645, -0.595699304492433,
+ +0.788346427626606, -0.615231590580627,
+ +0.773010453362737, -0.634393284163645,
+ +0.757208846506485, -0.653172842953777,
+ +0.740951125354959, -0.671558954847018,
+ +0.724247082951467, -0.689540544737067,
+ +0.707106781186548, -0.707106781186547,
+ +0.689540544737067, -0.724247082951467,
+ +0.671558954847018, -0.740951125354959,
+ +0.653172842953777, -0.757208846506484,
+ +0.634393284163645, -0.773010453362737,
+ +0.615231590580627, -0.788346427626606,
+ +0.595699304492433, -0.803207531480645,
+ +0.575808191417845, -0.817584813151584,
+ +0.555570233019602, -0.831469612302545,
+ +0.534997619887097, -0.844853565249707,
+ +0.514102744193222, -0.857728610000272,
+ +0.492898192229784, -0.870086991108711,
+ +0.471396736825998, -0.881921264348355,
+ +0.449611329654607, -0.893224301195515,
+ +0.427555093430282, -0.903989293123443,
+ +0.405241314004990, -0.914209755703531,
+ +0.382683432365090, -0.923879532511287,
+ +0.359895036534988, -0.932992798834739,
+ +0.336889853392220, -0.941544065183021,
+ +0.313681740398892, -0.949528180593037,
+ +0.290284677254462, -0.956940335732209,
+ +0.266712757474898, -0.963776065795440,
+ +0.242980179903264, -0.970031253194544,
+ +0.219101240156870, -0.975702130038529,
+ +0.195090322016128, -0.980785280403230,
+ +0.170961888760301, -0.985277642388941,
+ +0.146730474455362, -0.989176509964781,
+ +0.122410675199216, -0.992479534598710,
+ +0.098017140329561, -0.995184726672197,
+ +0.073564563599667, -0.997290456678690,
+ +0.049067674327418, -0.998795456205172,
+ +0.024541228522912, -0.999698818696204,
+ };
+ const double *W = Wconst256 - 2;
+ double *Z = Y + 128;
+ for (offset = 0; offset < 1024; offset += 512) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ __1, __0);
+ BUTTERFLY_0m (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ __0, __1);
+ }
+ for (butterfly = 2; butterfly < 128; butterfly += 2) {
+ Wre = W[butterfly]; Wim = W[butterfly + 1];
+ for (block = 0; block < 1024; block += 512) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 256], Y[offset + 256 + 1],
+ Wre, Wim);
+ BUTTERFLY_yX (Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 256], Z[offset + 256 + 1],
+ Wre, Wim);
+ }
+ }
+ }
+
+ /* perform 1 times fft512 */
+ {
+ static const double Wconst512[] = {
+ +0.999924701839145, -0.012271538285720,
+ +0.999698818696204, -0.024541228522912,
+ +0.999322384588350, -0.036807222941359,
+ +0.998795456205172, -0.049067674327418,
+ +0.998118112900149, -0.061320736302209,
+ +0.997290456678690, -0.073564563599667,
+ +0.996312612182778, -0.085797312344440,
+ +0.995184726672197, -0.098017140329561,
+ +0.993906970002356, -0.110222207293883,
+ +0.992479534598710, -0.122410675199216,
+ +0.990902635427780, -0.134580708507126,
+ +0.989176509964781, -0.146730474455362,
+ +0.987301418157858, -0.158858143333861,
+ +0.985277642388941, -0.170961888760301,
+ +0.983105487431216, -0.183039887955141,
+ +0.980785280403230, -0.195090322016128,
+ +0.978317370719628, -0.207111376192219,
+ +0.975702130038529, -0.219101240156870,
+ +0.972939952205560, -0.231058108280671,
+ +0.970031253194544, -0.242980179903264,
+ +0.966976471044852, -0.254865659604515,
+ +0.963776065795440, -0.266712757474898,
+ +0.960430519415566, -0.278519689385053,
+ +0.956940335732209, -0.290284677254462,
+ +0.953306040354194, -0.302005949319228,
+ +0.949528180593037, -0.313681740398892,
+ +0.945607325380521, -0.325310292162263,
+ +0.941544065183021, -0.336889853392220,
+ +0.937339011912575, -0.348418680249435,
+ +0.932992798834739, -0.359895036534988,
+ +0.928506080473216, -0.371317193951838,
+ +0.923879532511287, -0.382683432365090,
+ +0.919113851690058, -0.393992040061048,
+ +0.914209755703531, -0.405241314004990,
+ +0.909167983090522, -0.416429560097637,
+ +0.903989293123443, -0.427555093430282,
+ +0.898674465693954, -0.438616238538528,
+ +0.893224301195515, -0.449611329654607,
+ +0.887639620402854, -0.460538710958240,
+ +0.881921264348355, -0.471396736825998,
+ +0.876070094195407, -0.482183772079123,
+ +0.870086991108711, -0.492898192229784,
+ +0.863972856121587, -0.503538383725718,
+ +0.857728610000272, -0.514102744193222,
+ +0.851355193105265, -0.524589682678469,
+ +0.844853565249707, -0.534997619887097,
+ +0.838224705554838, -0.545324988422046,
+ +0.831469612302545, -0.555570233019602,
+ +0.824589302785025, -0.565731810783613,
+ +0.817584813151584, -0.575808191417845,
+ +0.810457198252595, -0.585797857456439,
+ +0.803207531480645, -0.595699304492433,
+ +0.795836904608884, -0.605511041404326,
+ +0.788346427626606, -0.615231590580627,
+ +0.780737228572094, -0.624859488142386,
+ +0.773010453362737, -0.634393284163645,
+ +0.765167265622459, -0.643831542889791,
+ +0.757208846506485, -0.653172842953777,
+ +0.749136394523459, -0.662415777590172,
+ +0.740951125354959, -0.671558954847018,
+ +0.732654271672413, -0.680600997795453,
+ +0.724247082951467, -0.689540544737067,
+ +0.715730825283819, -0.698376249408973,
+ +0.707106781186548, -0.707106781186547,
+ +0.698376249408973, -0.715730825283819,
+ +0.689540544737067, -0.724247082951467,
+ +0.680600997795453, -0.732654271672413,
+ +0.671558954847018, -0.740951125354959,
+ +0.662415777590172, -0.749136394523459,
+ +0.653172842953777, -0.757208846506484,
+ +0.643831542889791, -0.765167265622459,
+ +0.634393284163645, -0.773010453362737,
+ +0.624859488142386, -0.780737228572094,
+ +0.615231590580627, -0.788346427626606,
+ +0.605511041404326, -0.795836904608883,
+ +0.595699304492433, -0.803207531480645,
+ +0.585797857456439, -0.810457198252595,
+ +0.575808191417845, -0.817584813151584,
+ +0.565731810783613, -0.824589302785025,
+ +0.555570233019602, -0.831469612302545,
+ +0.545324988422046, -0.838224705554838,
+ +0.534997619887097, -0.844853565249707,
+ +0.524589682678469, -0.851355193105265,
+ +0.514102744193222, -0.857728610000272,
+ +0.503538383725718, -0.863972856121587,
+ +0.492898192229784, -0.870086991108711,
+ +0.482183772079123, -0.876070094195407,
+ +0.471396736825998, -0.881921264348355,
+ +0.460538710958240, -0.887639620402854,
+ +0.449611329654607, -0.893224301195515,
+ +0.438616238538528, -0.898674465693954,
+ +0.427555093430282, -0.903989293123443,
+ +0.416429560097637, -0.909167983090522,
+ +0.405241314004990, -0.914209755703531,
+ +0.393992040061048, -0.919113851690058,
+ +0.382683432365090, -0.923879532511287,
+ +0.371317193951838, -0.928506080473215,
+ +0.359895036534988, -0.932992798834739,
+ +0.348418680249435, -0.937339011912575,
+ +0.336889853392220, -0.941544065183021,
+ +0.325310292162263, -0.945607325380521,
+ +0.313681740398892, -0.949528180593037,
+ +0.302005949319228, -0.953306040354194,
+ +0.290284677254462, -0.956940335732209,
+ +0.278519689385053, -0.960430519415566,
+ +0.266712757474898, -0.963776065795440,
+ +0.254865659604515, -0.966976471044852,
+ +0.242980179903264, -0.970031253194544,
+ +0.231058108280671, -0.972939952205560,
+ +0.219101240156870, -0.975702130038529,
+ +0.207111376192219, -0.978317370719628,
+ +0.195090322016128, -0.980785280403230,
+ +0.183039887955141, -0.983105487431216,
+ +0.170961888760301, -0.985277642388941,
+ +0.158858143333861, -0.987301418157858,
+ +0.146730474455362, -0.989176509964781,
+ +0.134580708507126, -0.990902635427780,
+ +0.122410675199216, -0.992479534598710,
+ +0.110222207293883, -0.993906970002356,
+ +0.098017140329561, -0.995184726672197,
+ +0.085797312344440, -0.996312612182778,
+ +0.073564563599667, -0.997290456678690,
+ +0.061320736302209, -0.998118112900149,
+ +0.049067674327418, -0.998795456205172,
+ +0.036807222941359, -0.999322384588350,
+ +0.024541228522912, -0.999698818696204,
+ +0.012271538285720, -0.999924701839145,
+ };
+ const double *W = Wconst512 - 2;
+ double *Z = Y + 256;
+ for (offset = 0; offset < 1024; offset += 1024) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ __1, __0);
+ BUTTERFLY_0m (Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ __0, __1);
+ }
+ for (butterfly = 2; butterfly < 256; butterfly += 2) {
+ Wre = W[butterfly]; Wim = W[butterfly + 1];
+ for (block = 0; block < 1024; block += 1024) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 512], Y[offset + 512 + 1],
+ Wre, Wim);
+ BUTTERFLY_yX (Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ Z[offset], Z[offset + 1],
+ Z[offset + 512], Z[offset + 512 + 1],
+ Wre, Wim);
+ }
+ }
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 512 L S S S S S S S X)
+ **/
+static void
+gsl_power2_fft512synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (512, X, Y);
+
+ /* skipping 128 times fft4 */
+
+ /* skipping 64 times fft8 */
+
+ /* skipping 32 times fft16 */
+
+ /* skipping 16 times fft32 */
+
+ /* skipping 8 times fft64 */
+
+ /* skipping 4 times fft128 */
+
+ /* skipping 2 times fft256 */
+
+ /* perform 1 times fft512 */
+ gsl_power2_fft512synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 1024 S S S S S S S S X L)
+ **/
+static void
+gsl_power2_fft1024synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 512 times fft2 */
+
+ /* skipping 256 times fft4 */
+
+ /* skipping 128 times fft8 */
+
+ /* skipping 64 times fft16 */
+
+ /* skipping 32 times fft32 */
+
+ /* skipping 16 times fft64 */
+
+ /* skipping 8 times fft128 */
+
+ /* skipping 4 times fft256 */
+
+ /* perform 2 times fft512 */
+ gsl_power2_fft512synthesis_skip2 (X, Y);
+ gsl_power2_fft512synthesis_skip2 (X + 1024, Y + 1024);
+
+ /* perform 1 times fft1024 */
+ for (offset = 0; offset < 2048; offset += 2048) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __1, __0);
+ }
+ Wre = +0.999981175282601; Wim = -0.006135884649154;
+ for (butterfly = 2; butterfly < 512; butterfly += 2) {
+ for (block = 0; block < 2048; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, -0.006135884649154);
+ }
+ for (offset = 512; offset < 2048; offset += 2048) {
+ BUTTERFLY_0m (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __0, __1);
+ }
+ Wre = -0.006135884649154; Wim = -0.999981175282601;
+ for (butterfly = 514; butterfly < 1024; butterfly += 2) {
+ for (block = 0; block < 2048; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, -0.006135884649154);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 1024 L S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft1024synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (1024, X, Y);
+
+ /* skipping 256 times fft4 */
+
+ /* skipping 128 times fft8 */
+
+ /* skipping 64 times fft16 */
+
+ /* skipping 32 times fft32 */
+
+ /* skipping 16 times fft64 */
+
+ /* skipping 8 times fft128 */
+
+ /* skipping 4 times fft256 */
+
+ /* skipping 2 times fft512 */
+
+ /* perform 1 times fft1024 */
+ gsl_power2_fft1024synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 2048 S S S S S S S S X L L)
+ **/
+static void
+gsl_power2_fft2048synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 1024 times fft2 */
+
+ /* skipping 512 times fft4 */
+
+ /* skipping 256 times fft8 */
+
+ /* skipping 128 times fft16 */
+
+ /* skipping 64 times fft32 */
+
+ /* skipping 32 times fft64 */
+
+ /* skipping 16 times fft128 */
+
+ /* skipping 8 times fft256 */
+
+ /* perform 4 times fft512 */
+ gsl_power2_fft512synthesis_skip2 (X, Y);
+ gsl_power2_fft512synthesis_skip2 (X + 1024, Y + 1024);
+ gsl_power2_fft512synthesis_skip2 (X + 2048, Y + 2048);
+ gsl_power2_fft512synthesis_skip2 (X + 3072, Y + 3072);
+
+ /* perform 2 times fft1024 */
+ for (offset = 0; offset < 4096; offset += 2048) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __1, __0);
+ }
+ Wre = +0.999981175282601; Wim = -0.006135884649154;
+ for (butterfly = 2; butterfly < 512; butterfly += 2) {
+ for (block = 0; block < 4096; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, -0.006135884649154);
+ }
+ for (offset = 512; offset < 4096; offset += 2048) {
+ BUTTERFLY_0m (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ __0, __1);
+ }
+ Wre = -0.006135884649154; Wim = -0.999981175282601;
+ for (butterfly = 514; butterfly < 1024; butterfly += 2) {
+ for (block = 0; block < 4096; block += 2048) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 1024], Y[offset + 1024 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000018824717399, -0.006135884649154);
+ }
+
+ /* perform 1 times fft2048 */
+ for (offset = 0; offset < 4096; offset += 4096) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ __1, __0);
+ }
+ Wre = +0.999995293809576; Wim = -0.003067956762966;
+ for (butterfly = 2; butterfly < 1024; butterfly += 2) {
+ for (block = 0; block < 4096; block += 4096) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000004706190424, -0.003067956762966);
+ }
+ for (offset = 1024; offset < 4096; offset += 4096) {
+ BUTTERFLY_0m (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ __0, __1);
+ }
+ Wre = -0.003067956762966; Wim = -0.999995293809576;
+ for (butterfly = 1026; butterfly < 2048; butterfly += 2) {
+ for (block = 0; block < 4096; block += 4096) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 2048], Y[offset + 2048 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000004706190424, -0.003067956762966);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 2048 L S S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft2048synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (2048, X, Y);
+
+ /* skipping 512 times fft4 */
+
+ /* skipping 256 times fft8 */
+
+ /* skipping 128 times fft16 */
+
+ /* skipping 64 times fft32 */
+
+ /* skipping 32 times fft64 */
+
+ /* skipping 16 times fft128 */
+
+ /* skipping 8 times fft256 */
+
+ /* skipping 4 times fft512 */
+
+ /* skipping 2 times fft1024 */
+
+ /* perform 1 times fft2048 */
+ gsl_power2_fft2048synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4096 S S S S S S S S S S X L)
+ **/
+static void
+gsl_power2_fft4096synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 2048 times fft2 */
+
+ /* skipping 1024 times fft4 */
+
+ /* skipping 512 times fft8 */
+
+ /* skipping 256 times fft16 */
+
+ /* skipping 128 times fft32 */
+
+ /* skipping 64 times fft64 */
+
+ /* skipping 32 times fft128 */
+
+ /* skipping 16 times fft256 */
+
+ /* skipping 8 times fft512 */
+
+ /* skipping 4 times fft1024 */
+
+ /* perform 2 times fft2048 */
+ gsl_power2_fft2048synthesis_skip2 (X, Y);
+ gsl_power2_fft2048synthesis_skip2 (X + 4096, Y + 4096);
+
+ /* perform 1 times fft4096 */
+ for (offset = 0; offset < 8192; offset += 8192) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ __1, __0);
+ }
+ Wre = +0.999998823451702; Wim = -0.001533980186285;
+ for (butterfly = 2; butterfly < 2048; butterfly += 2) {
+ for (block = 0; block < 8192; block += 8192) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000001176548298, -0.001533980186285);
+ }
+ for (offset = 2048; offset < 8192; offset += 8192) {
+ BUTTERFLY_0m (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ __0, __1);
+ }
+ Wre = -0.001533980186285; Wim = -0.999998823451702;
+ for (butterfly = 2050; butterfly < 4096; butterfly += 2) {
+ for (block = 0; block < 8192; block += 8192) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 4096], Y[offset + 4096 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000001176548298, -0.001533980186285);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 4096 L S S S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft4096synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (4096, X, Y);
+
+ /* skipping 1024 times fft4 */
+
+ /* skipping 512 times fft8 */
+
+ /* skipping 256 times fft16 */
+
+ /* skipping 128 times fft32 */
+
+ /* skipping 64 times fft64 */
+
+ /* skipping 32 times fft128 */
+
+ /* skipping 16 times fft256 */
+
+ /* skipping 8 times fft512 */
+
+ /* skipping 4 times fft1024 */
+
+ /* skipping 2 times fft2048 */
+
+ /* perform 1 times fft4096 */
+ gsl_power2_fft4096synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8192 S S S S S S S S S S S X L)
+ **/
+static void
+gsl_power2_fft8192synthesis_skip2 (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* skipping 4096 times fft2 */
+
+ /* skipping 2048 times fft4 */
+
+ /* skipping 1024 times fft8 */
+
+ /* skipping 512 times fft16 */
+
+ /* skipping 256 times fft32 */
+
+ /* skipping 128 times fft64 */
+
+ /* skipping 64 times fft128 */
+
+ /* skipping 32 times fft256 */
+
+ /* skipping 16 times fft512 */
+
+ /* skipping 8 times fft1024 */
+
+ /* skipping 4 times fft2048 */
+
+ /* perform 2 times fft4096 */
+ gsl_power2_fft4096synthesis_skip2 (X, Y);
+ gsl_power2_fft4096synthesis_skip2 (X + 8192, Y + 8192);
+
+ /* perform 1 times fft8192 */
+ for (offset = 0; offset < 16384; offset += 16384) {
+ BUTTERFLY_10 (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ __1, __0);
+ }
+ Wre = +0.999999705862882; Wim = -0.000766990318743;
+ for (butterfly = 2; butterfly < 4096; butterfly += 2) {
+ for (block = 0; block < 16384; block += 16384) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000000294137118, -0.000766990318743);
+ }
+ for (offset = 4096; offset < 16384; offset += 16384) {
+ BUTTERFLY_0m (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ __0, __1);
+ }
+ Wre = -0.000766990318743; Wim = -0.999999705862882;
+ for (butterfly = 4098; butterfly < 8192; butterfly += 2) {
+ for (block = 0; block < 16384; block += 16384) {
+ offset = butterfly + block;
+ BUTTERFLY_XY (Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Y[offset], Y[offset + 1],
+ Y[offset + 8192], Y[offset + 8192 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, -0.000000294137118, -0.000766990318743);
+ }
+}
+
+/**
+ ** Generated data ends here
+ **/
+/**
+ ** Generated data (by gsl-genfft 8192 L S S S S S S S S S S S X)
+ **/
+static void
+gsl_power2_fft8192synthesis (const double *X, double *Y)
+{
+ register unsigned int butterfly, block, offset;
+ register double Wre, Wim;
+
+ butterfly = block = offset = 0, Wre = Wim = 0.0; /* silence compiler */
+
+ /* perform fft2 and bitreverse input */
+ bitreverse_fft2synthesis (8192, X, Y);
+
+ /* skipping 2048 times fft4 */
+
+ /* skipping 1024 times fft8 */
+
+ /* skipping 512 times fft16 */
+
+ /* skipping 256 times fft32 */
+
+ /* skipping 128 times fft64 */
+
+ /* skipping 64 times fft128 */
+
+ /* skipping 32 times fft256 */
+
+ /* skipping 16 times fft512 */
+
+ /* skipping 8 times fft1024 */
+
+ /* skipping 4 times fft2048 */
+
+ /* skipping 2 times fft4096 */
+
+ /* perform 1 times fft8192 */
+ gsl_power2_fft8192synthesis_skip2 (X, Y);
+}
+
+/**
+ ** Generated data ends here
+ **/
+
+
+/* public FFT frontends and generic handling of huge fft sizes */
+
+
+static void
+gsl_power2_fftc_big (const unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues,
+ const int esign)
+{
+ const unsigned int n_values2 = n_values << 1;
+ double theta = esign < 0 ? -3.1415926535897932384626433832795029 : 3.1415926535897932384626433832795029;
+ unsigned int i, block_size = 8192 << 1;
+ double last_sin;
+
+ if (esign > 0)
+ {
+ if (rivalues_in)
+ bitreverse_fft2analysis (n_values, rivalues_in, rivalues);
+ for (i = 0; i < n_values; i += 8192)
+ gsl_power2_fft8192analysis_skip2 (rivalues + (i << 1), rivalues + (i << 1));
+ }
+ else
+ {
+ if (rivalues_in)
+ bitreverse_fft2synthesis (n_values, rivalues_in, rivalues);
+ for (i = 0; i < n_values; i += 8192)
+ gsl_power2_fft8192synthesis_skip2 (rivalues + (i << 1), rivalues + (i << 1));
+ }
+ theta *= (double) 1.0 / 8192.;
+ last_sin = sin (theta);
+
+ /* we're not combining the first and second halves coefficients
+ * in the below loop, since for fft sizes beyond 8192, it'd actually
+ * harm performance due to paging
+ */
+ do
+ {
+ double Dre, Dim, Wre, Wim;
+ unsigned int k, i, half_block = block_size >> 1;
+ unsigned int block_size2 = block_size << 1;
+
+ theta *= 0.5;
+ Dim = last_sin;
+ last_sin = sin (theta);
+ Dre = last_sin * last_sin * -2.;
+
+ /* loop over first coefficient in each block ==> w == {1,0} */
+ for (i = 0; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_10 (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __1, __0);
+ }
+ Wre = Dre + 1.0; /* update Wk */
+ Wim = Dim; /* update Wk */
+ /* loop for every Wk in the first half of each subblock */
+ for (k = 2; k < half_block; k += 2)
+ {
+ /* loop over kth coefficient in each block */
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_XY (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, Dre, Dim); /* update Wk */
+ }
+ /* handle middle coefficient ==> w == {0,+-1} */
+ if (k < block_size)
+ {
+ /* loop over kth coefficient in each block */
+ if (esign > 0)
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_01 (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __0, __1);
+ }
+ else
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_0m (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __0, __1);
+ }
+ /* update Wk */
+ if (esign > 0)
+ {
+ Wre = -Dim;
+ Wim = Dre + 1.0;
+ }
+ else
+ {
+ Wre = Dim;
+ Wim = -Dre - 1.0;
+ }
+ k += 2;
+ }
+ /* loop for every Wk in the second half of each subblock */
+ for (; k < block_size; k += 2)
+ {
+ /* loop over kth coefficient in each block */
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_XY (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, Dre, Dim); /* update Wk */
+ }
+ block_size = block_size2;
+ }
+ while (block_size <= n_values);
+}
+void
+gsl_power2_fftac (const unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues_out)
+{
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 1);
+
+ switch (n_values)
+ {
+ case 1: rivalues_out[0] = rivalues_in[0], rivalues_out[1] = rivalues_in[1]; break;
+ case 2: gsl_power2_fft2analysis (rivalues_in, rivalues_out); break;
+ case 4: gsl_power2_fft4analysis (rivalues_in, rivalues_out); break;
+ case 8: gsl_power2_fft8analysis (rivalues_in, rivalues_out); break;
+ case 16: gsl_power2_fft16analysis (rivalues_in, rivalues_out); break;
+ case 32: gsl_power2_fft32analysis (rivalues_in, rivalues_out); break;
+ case 64: gsl_power2_fft64analysis (rivalues_in, rivalues_out); break;
+ case 128: gsl_power2_fft128analysis (rivalues_in, rivalues_out); break;
+ case 256: gsl_power2_fft256analysis (rivalues_in, rivalues_out); break;
+ case 512: gsl_power2_fft512analysis (rivalues_in, rivalues_out); break;
+ case 1024: gsl_power2_fft1024analysis (rivalues_in, rivalues_out); break;
+ case 2048: gsl_power2_fft2048analysis (rivalues_in, rivalues_out); break;
+ case 4096: gsl_power2_fft4096analysis (rivalues_in, rivalues_out); break;
+ case 8192: gsl_power2_fft8192analysis (rivalues_in, rivalues_out); break;
+ default: gsl_power2_fftc_big (n_values, rivalues_in, rivalues_out, +1);
+ }
+}
+void
+gsl_power2_fftsc (const unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues_out)
+{
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 1);
+
+ switch (n_values)
+ {
+ case 1: rivalues_out[0] = rivalues_in[0], rivalues_out[1] = rivalues_in[1]; break;
+ case 2: gsl_power2_fft2synthesis (rivalues_in, rivalues_out); break;
+ case 4: gsl_power2_fft4synthesis (rivalues_in, rivalues_out); break;
+ case 8: gsl_power2_fft8synthesis (rivalues_in, rivalues_out); break;
+ case 16: gsl_power2_fft16synthesis (rivalues_in, rivalues_out); break;
+ case 32: gsl_power2_fft32synthesis (rivalues_in, rivalues_out); break;
+ case 64: gsl_power2_fft64synthesis (rivalues_in, rivalues_out); break;
+ case 128: gsl_power2_fft128synthesis (rivalues_in, rivalues_out); break;
+ case 256: gsl_power2_fft256synthesis (rivalues_in, rivalues_out); break;
+ case 512: gsl_power2_fft512synthesis (rivalues_in, rivalues_out); break;
+ case 1024: gsl_power2_fft1024synthesis (rivalues_in, rivalues_out); break;
+ case 2048: gsl_power2_fft2048synthesis (rivalues_in, rivalues_out); break;
+ case 4096: gsl_power2_fft4096synthesis (rivalues_in, rivalues_out); break;
+ case 8192: gsl_power2_fft8192synthesis (rivalues_in, rivalues_out); break;
+ default: gsl_power2_fftc_big (n_values, rivalues_in, rivalues_out, -1);
+ }
+ /* { unsigned int i; for (i = 0; i < n_values << 1; i++) rivalues_out[i] *= (double) n_values; } */
+}
+void
+gsl_power2_fftar (const unsigned int n_values,
+ const double *r_values_in,
+ double *rivalues_out)
+{
+ unsigned int n_cvalues = n_values >> 1;
+ double Dre, Dim, Wre, Wim, theta;
+ unsigned int i;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ gsl_power2_fftac (n_cvalues, r_values_in, rivalues_out);
+ theta = 3.1415926535897932384626433832795029;
+ theta /= (double) n_cvalues;
+
+ Dre = sin (0.5 * theta);
+ Dim = sin (theta);
+ Dre = Dre * Dre;
+ Wre = 0.5 - Dre;
+ Dre *= -2.;
+ Wim = Dim * 0.5;
+ for (i = 2; i < n_values >> 1; i += 2)
+ {
+ double F1re, F1im, F2re, F2im, H1re, H1im, H2re, H2im;
+ unsigned int r = n_values - i;
+ double FEre = rivalues_out[i] + rivalues_out[r];
+ double FEim = rivalues_out[i + 1] - rivalues_out[r + 1];
+ double FOre = rivalues_out[r] - rivalues_out[i];
+ double FOim = rivalues_out[r + 1] + rivalues_out[i + 1];
+
+ FEre *= 0.5;
+ FEim *= 0.5;
+ F2re = FOre * Wim;
+ F2im = FOim * Wim;
+ F1re = FOre * Wre;
+ F1im = FOim * Wre;
+
+ H1im = F2im + F1re;
+ H1re = F1im - F2re;
+ H2re = F2re - F1im;
+ H2im = H1im - FEim;
+ H1re += FEre;
+ H2re += FEre;
+ H1im += FEim;
+ rivalues_out[i] = H1re;
+ rivalues_out[i + 1] = H1im;
+ rivalues_out[r] = H2re;
+ rivalues_out[r + 1] = H2im;
+ WMULTIPLY (Wre, Wim, Dre, Dim);
+ }
+ Dre = rivalues_out[0];
+ rivalues_out[0] = Dre + rivalues_out[1];
+ rivalues_out[1] = Dre - rivalues_out[1];
+}
+void
+gsl_power2_fftsr (const unsigned int n_values,
+ const double *rivalues_in,
+ double *r_values_out)
+{
+ unsigned int n_cvalues = n_values >> 1;
+ double Dre, Dim, Wre, Wim, theta, scale;
+ unsigned int i, ri;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ theta = -3.1415926535897932384626433832795029;
+ theta /= (double) n_cvalues;
+
+ Dre = sin (0.5 * theta);
+ Dim = sin (theta);
+ Dre = Dre * Dre;
+ Wre = 0.5 - Dre;
+ Dre *= -2.;
+ Wim = Dim * 0.5;
+ for (i = 2, ri = 0; i < n_values >> 1; i += 2)
+ {
+ double F1re, F1im, F2re, F2im, H1re, H1im, H2re, H2im;
+ unsigned int g = n_values - i, j = n_values >> 2, rg = n_values - (ri << 1) - 2;
+ double FEre = rivalues_in[i] + rivalues_in[g];
+ double FEim = rivalues_in[i + 1] - rivalues_in[g + 1];
+ double FOre = rivalues_in[g] - rivalues_in[i];
+ double FOim = rivalues_in[g + 1] + rivalues_in[i + 1];
+
+ while (ri >= j)
+ {
+ ri -= j;
+ j >>= 1;
+ }
+ ri |= j;
+
+ FOre = -FOre;
+ FOim = -FOim;
+ FEre *= 0.5;
+ FEim *= 0.5;
+ F2re = FOre * Wim;
+ F2im = FOim * Wim;
+ F1re = FOre * Wre;
+ F1im = FOim * Wre;
+
+ H1im = F2im + F1re;
+ H1re = F1im - F2re;
+ H2re = F2re - F1im;
+ H2im = H1im - FEim;
+ H1re += FEre;
+ H2re += FEre;
+ H1im += FEim;
+
+ j = ri << 1;
+ r_values_out[j] = H1re;
+ r_values_out[j + 1] = H1im;
+ r_values_out[rg] = H2re;
+ r_values_out[rg + 1] = H2im;
+ WMULTIPLY (Wre, Wim, Dre, Dim);
+ }
+ Dre = rivalues_in[0];
+ r_values_out[0] = Dre + rivalues_in[1];
+ r_values_out[1] = Dre - rivalues_in[1];
+ r_values_out[0] *= 0.5;
+ r_values_out[1] *= 0.5;
+ if (n_values < 4)
+ return;
+ r_values_out[2] = rivalues_in[i];
+ r_values_out[2 + 1] = rivalues_in[i + 1];
+ scale = n_cvalues;
+ scale = 1.0 / scale;
+ for (i = 0; i < n_values; i += 4)
+ BUTTERFLY_10scale (r_values_out[i], r_values_out[i + 1],
+ r_values_out[i + 2], r_values_out[i + 3],
+ r_values_out[i], r_values_out[i + 1],
+ r_values_out[i + 2], r_values_out[i + 3],
+ scale);
+ switch (n_cvalues)
+ {
+ case 2: break;
+ case 4: gsl_power2_fft4synthesis_skip2 (NULL, r_values_out); break;
+ case 8: gsl_power2_fft8synthesis_skip2 (NULL, r_values_out); break;
+ case 16: gsl_power2_fft16synthesis_skip2 (NULL, r_values_out); break;
+ case 32: gsl_power2_fft32synthesis_skip2 (NULL, r_values_out); break;
+ case 64: gsl_power2_fft64synthesis_skip2 (NULL, r_values_out); break;
+ case 128: gsl_power2_fft128synthesis_skip2 (NULL, r_values_out); break;
+ case 256: gsl_power2_fft256synthesis_skip2 (NULL, r_values_out); break;
+ case 512: gsl_power2_fft512synthesis_skip2 (NULL, r_values_out); break;
+ case 1024: gsl_power2_fft1024synthesis_skip2 (NULL, r_values_out); break;
+ case 2048: gsl_power2_fft2048synthesis_skip2 (NULL, r_values_out); break;
+ case 4096: gsl_power2_fft4096synthesis_skip2 (NULL, r_values_out); break;
+ case 8192: gsl_power2_fft8192synthesis_skip2 (NULL, r_values_out); break;
+ default: gsl_power2_fftc_big (n_cvalues, NULL, r_values_out, -1);
+ }
+}
+void
+gsl_power2_fftar_simple (const unsigned int n_values,
+ const float *real_values,
+ float *complex_values)
+{
+ double *rv, *cv;
+ guint i;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ rv = g_new (double, n_values * 2);
+ cv = rv + n_values;
+ i = n_values;
+ while (i--)
+ rv[i] = real_values[i];
+ gsl_power2_fftar (n_values, rv, cv);
+ i = n_values;
+ while (i--)
+ complex_values[i] = cv[i];
+ complex_values[n_values] = complex_values[1];
+ complex_values[1] = 0.0;
+ complex_values[n_values + 1] = 0.0;
+ g_free (rv);
+}
+void
+gsl_power2_fftsr_simple (const unsigned int n_values,
+ const float *complex_values,
+ float *real_values)
+{
+ double *cv, *rv;
+ guint i;
+
+ g_return_if_fail ((n_values & (n_values - 1)) == 0 && n_values >= 2);
+
+ cv = g_new (double, n_values * 2);
+ rv = cv + n_values;
+ i = n_values;
+ while (i--)
+ cv[i] = complex_values[i];
+ cv[1] = complex_values[n_values];
+ gsl_power2_fftsr (n_values, cv, rv);
+ i = n_values;
+ while (i--)
+ real_values[i] = rv[i];
+ g_free (cv);
+}
diff --git a/flow/gsl/gslfft.h b/flow/gsl/gslfft.h
new file mode 100644
index 0000000..63e3892
--- /dev/null
+++ b/flow/gsl/gslfft.h
@@ -0,0 +1,126 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_FFT_H__
+#define __GSL_FFT_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/**
+ * gsl_power2_fftac
+ * @n_values: Number of complex values
+ * @ri_values_in: Complex sample values [0..n_values*2-1]
+ * @ri_values_out: Complex frequency values [0..n_values*2-1]
+ * This function performs a decimation in time fourier transformation
+ * in forward direction, where the input values are equidistant sampled
+ * data, and the output values contain the frequency proportions of the
+ * input.
+ * The input and output arrays are complex values with real and imaginery
+ * portions interleaved, adressable in the range [0..2*n_values-1], where
+ * n_values must be a power of two.
+ * Frequencies are stored in-order, the K-th output corresponds to the
+ * frequency K/n_values. (If you want to interpret negative frequencies,
+ * note that the frequencies -K/n_values and (n_values-K)/n_values are
+ * equivalent).
+ * Note that the transformation is performed out of place, the input
+ * array is not modified, and may not overlap with the output array.
+ */
+void gsl_power2_fftac (const unsigned int n_values,
+ const double *ri_values_in,
+ double *ri_values_out);
+
+/**
+ * gsl_power2_fftsc
+ * @n_values: Number of complex values
+ * @ri_values_in: Complex frequency values [0..n_values*2-1]
+ * @ri_values_out: Complex sample values [0..n_values*2-1]
+ * This function performs a decimation in time fourier transformation
+ * in backwards direction with normalization. As such, this function
+ * represents the counterpart to gsl_power2_fftac(), that is, a value
+ * array which is transformed into the frequency domain with
+ * gsl_power2_fftac() can be reconstructed by issuing gsl_power2_fftsc()
+ * on the transform.
+ * Note that the transformation is performed out of place, the input
+ * array is not modified, and may not overlap with the output array.
+ */
+void gsl_power2_fftsc (const unsigned int n_values,
+ const double *ri_values_in,
+ double *ri_values_out);
+
+/**
+ * gsl_power2_fftar
+ * @n_values: Number of complex values
+ * @r_values_in: Real sample values [0..n_values-1]
+ * @ri_values_out: Complex frequency values [0..n_values-1]
+ * Real valued variant of gsl_power2_fftac(), the input array contains
+ * real valued equidistant sampled data [0..n_values-1], and the output
+ * array contains the positive frequency half of the complex valued
+ * fourier transform. Note, that the complex valued fourier transform H
+ * of a purely real valued set of data, satisfies H(-f) = Conj(H(f)),
+ * where Conj() denotes the complex conjugate, so that just the positive
+ * frequency half suffices to describe the entire frequency spectrum.
+ * Even so, the resulting n_values/2 complex frequencies are one value
+ * off in storage size, but the resulting frequencies H(0) and
+ * H(n_values/2) are both real valued, so the real portion of
+ * H(n_values/2) is stored in ri_values_out[1] (the imaginery part of
+ * H(0)), so that both r_values_in and ri_values_out can be of size
+ * n_values.
+ * Note that the transformation is performed out of place, the input
+ * array is not modified, and may not overlap with the output array.
+ */
+void gsl_power2_fftar (const unsigned int n_values,
+ const double *r_values_in,
+ double *ri_values_out);
+
+/**
+ * gsl_power2_fftsr
+ * @n_values: Number of complex values
+ * @ri_values_in: Complex frequency values [0..n_values-1]
+ * @r_values_out: Real sample values [0..n_values-1]
+ * Real valued variant of gsl_power2_fftsc(), counterpart to
+ * gsl_power2_fftar(), using the same frequency storage format.
+ * A real valued data set transformed into the frequency domain
+ * with gsl_power2_fftar() can be reconstructed using this function.
+ * Note that the transformation is performed out of place, the input
+ * array is not modified, and may not overlap with the output array.
+ */
+void gsl_power2_fftsr (const unsigned int n_values,
+ const double *ri_values_in,
+ double *r_values_out);
+
+
+/* --- convenience wrappers --- */
+void gsl_power2_fftar_simple (const unsigned int n_values,
+ const float *real_values,
+ float *complex_values);
+void gsl_power2_fftsr_simple (const unsigned int n_values,
+ const float *complex_values,
+ float *real_values);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_FFT_H__ */ /* vim:set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslffttest.c b/flow/gsl/gslffttest.c
new file mode 100644
index 0000000..a568bc5
--- /dev/null
+++ b/flow/gsl/gslffttest.c
@@ -0,0 +1,435 @@
+/* GSL-GENFFT - Power2 FFT C Code Generator
+ * Copyright (C) 2001 Tim Janik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <gsl/gslcommon.h>
+#include <gsl/gslmath.h>
+#include <gsl/gslfft.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define MAX_FFT_SIZE (65536 * 2)
+#define EPSILON (4.8e-6)
+
+
+/* --- prototypes --- */
+static void reference_power2_fftc (unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues_out,
+ int esign);
+static void fill_rand (guint n,
+ double *a);
+static double diff (guint m,
+ guint p,
+ double *a1,
+ double *a2,
+ const gchar *str);
+
+
+/* --- variables --- */
+static double ref_fft_in[MAX_FFT_SIZE] = { 0, };
+static double ref_fft_aout[MAX_FFT_SIZE] = { 0, };
+static double ref_fft_sout[MAX_FFT_SIZE] = { 0, };
+static double work_fft_in[MAX_FFT_SIZE] = { 0, };
+static double work_fft_aout[MAX_FFT_SIZE] = { 0, };
+static double work_fft_sout[MAX_FFT_SIZE] = { 0, };
+
+
+/* --- functions --- */
+int
+main (int argc,
+ char *argv[])
+{
+ struct timeval tv;
+ guint i;
+
+ /* initialize GSL */
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+ gsl_init (NULL, NULL);
+
+ /* initialize random numbers */
+ gettimeofday (&tv, NULL);
+ srand (tv.tv_sec ^ tv.tv_usec);
+
+ /* run tests */
+ for (i = 2; i <= MAX_FFT_SIZE >> 1; i <<= 1)
+ {
+ double d;
+
+ g_print ("Testing fft code for size %u\n", i);
+
+ /* setup reference and work fft records */
+ fill_rand (i << 1, ref_fft_in);
+ memset (ref_fft_aout, 0, MAX_FFT_SIZE * sizeof (ref_fft_aout[0]));
+ memset (ref_fft_sout, 0, MAX_FFT_SIZE * sizeof (ref_fft_sout[0]));
+ memcpy (work_fft_in, ref_fft_in, MAX_FFT_SIZE * sizeof (work_fft_in[0]));
+ memset (work_fft_aout, 0, MAX_FFT_SIZE * sizeof (work_fft_aout[0]));
+ memset (work_fft_sout, 0, MAX_FFT_SIZE * sizeof (work_fft_sout[0]));
+ reference_power2_fftc (i, ref_fft_in, ref_fft_aout, +1);
+ reference_power2_fftc (i, ref_fft_in, ref_fft_sout, -1);
+
+ /* perform fft test */
+ gsl_power2_fftac (i, work_fft_in, work_fft_aout);
+ gsl_power2_fftsc (i, work_fft_in, work_fft_sout);
+
+ /* check differences */
+ d = diff (MAX_FFT_SIZE, 0, ref_fft_in, work_fft_in, "Checking input record");
+ if (d)
+ g_error ("Reference record was modified");
+ d = diff (MAX_FFT_SIZE, 0, ref_fft_aout, work_fft_aout, "Reference analysis against GSL analysis");
+ if (fabs (d) > EPSILON)
+ g_error ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ d = diff (MAX_FFT_SIZE, 0, ref_fft_sout, work_fft_sout, "Reference synthesis against GSL synthesis");
+ if (fabs (d) > EPSILON)
+ g_error ("Error sum in analysis FFT exceeds epsilon: %g > %g", d, EPSILON);
+ }
+
+ return 0;
+}
+
+static void
+fill_rand (guint n,
+ double *a)
+{
+ while (n--)
+ a[n] = -1. + 2. * rand() / (RAND_MAX + 1.0);
+}
+
+static double
+diff (guint m,
+ guint p,
+ double *a1,
+ double *a2,
+ const gchar *str)
+{
+ double d = 0, max = 0, min = 1e+32;
+ guint n;
+
+ g_print ("%s\n", str);
+ for (n = 0; n < m; n++)
+ {
+ double a = ABS (a1[n] - a2[n]);
+ if (n < p)
+ g_print ("%3u:%.3f) % 19.9f - % 19.9f = % 19.9f (% 19.9f)\n",
+ n, ((float) n) / (float) m,
+ a1[n], a2[n],
+ a1[n] - a2[n],
+ a1[n] / a2[n]);
+ d += a;
+ max = MAX (max, a);
+ min = MIN (min, a);
+ }
+ g_print ("Diff sum: %.9f, ", d);
+ g_print ("min/av/max: %.9f %.9f %.9f, ", min, d / (double) m, max);
+ g_print ("noise: %u %u %u\n",
+ g_bit_storage (1. / min),
+ g_bit_storage (m / d),
+ g_bit_storage (1. / max));
+ return d;
+}
+
+
+/* --- fft implementation --- */
+#define BUTTERFLY_XY(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,Wre,Wim) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = X2re * Wre; \
+ T1im = X2im * Wre; \
+ T2re = X2im * Wim; \
+ T2im = X2re * Wim; \
+ T1re -= T2re; \
+ T1im += T2im; \
+ T2re = X1re - T1re; \
+ T2im = X1im - T1im; \
+ Y1re = X1re + T1re; \
+ Y1im = X1im + T1im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_10(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \
+ register double T2re, T2im; \
+ T2re = X1re - X2re; \
+ T2im = X1im - X2im; \
+ Y1re = X1re + X2re; \
+ Y1im = X1im + X2im; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_01(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \
+ register double T2re, T2im; \
+ T2re = X1re + X2im; \
+ T2im = X1im - X2re; \
+ Y1re = X1re - X2im; \
+ Y1im = X1im + X2re; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_0m(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,_1,_2) { \
+ register double T2re, T2im; \
+ T2re = X1re - X2im; \
+ T2im = X1im + X2re; \
+ Y1re = X1re + X2im; \
+ Y1im = X1im - X2re; \
+ Y2re = T2re; \
+ Y2im = T2im; \
+}
+#define BUTTERFLY_10scale(X1re,X1im,X2re,X2im,Y1re,Y1im,Y2re,Y2im,S) { \
+ register double T2re, T2im; \
+ T2re = X1re - X2re; \
+ T2im = X1im - X2im; \
+ Y1re = X1re + X2re; \
+ Y1im = X1im + X2im; \
+ Y2re = T2re * S; \
+ Y2im = T2im * S; \
+ Y1re *= S; \
+ Y1im *= S; \
+}
+#define WMULTIPLY(Wre,Wim,Dre,Dim) { \
+ register double T1re, T1im, T2re, T2im; \
+ T1re = Wre * Dre; \
+ T1im = Wim * Dre; \
+ T2re = Wim * Dim; \
+ T2im = Wre * Dim; \
+ T1re -= T2re; \
+ T1im += T2im; \
+ Wre += T1re; \
+ Wim += T1im; \
+}
+
+static inline void
+reference_bitreverse_fft2analysis (const unsigned int n,
+ const double *X,
+ double *Y)
+{
+ const unsigned int n2 = n >> 1, n1 = n + n2, max = n >> 2;
+ unsigned int i, r;
+
+ BUTTERFLY_10 (X[0], X[1],
+ X[n], X[n + 1],
+ Y[0], Y[1],
+ Y[2], Y[3],
+ __1, __0);
+ if (n < 4)
+ return;
+ BUTTERFLY_10 (X[n2], X[n2 + 1],
+ X[n1], X[n1 + 1],
+ Y[4], Y[5],
+ Y[6], Y[7],
+ __1, __0);
+ if (n < 8)
+ return;
+ for (i = 1, r = 0; i < max; i++)
+ {
+ unsigned int k, j = n >> 1;
+
+ while (r >= j)
+ {
+ r -= j;
+ j >>= 1;
+ }
+ r |= j;
+
+ k = r >> 1;
+ j = i << 3;
+ BUTTERFLY_10 (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ __1, __0);
+ k += n2;
+ j += 4;
+ BUTTERFLY_10 (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ __1, __0);
+ }
+}
+
+static inline void
+reference_bitreverse_fft2synthesis (const unsigned int n,
+ const double *X,
+ double *Y)
+{
+ const unsigned int n2 = n >> 1, n1 = n + n2, max = n >> 2;
+ unsigned int i, r;
+ double scale = n;
+
+ scale = 1.0 / scale;
+ BUTTERFLY_10scale (X[0], X[1],
+ X[n], X[n + 1],
+ Y[0], Y[1],
+ Y[2], Y[3],
+ scale);
+ if (n < 4)
+ return;
+ BUTTERFLY_10scale (X[n2], X[n2 + 1],
+ X[n1], X[n1 + 1],
+ Y[4], Y[5],
+ Y[6], Y[7],
+ scale);
+ if (n < 8)
+ return;
+ for (i = 1, r = 0; i < max; i++)
+ {
+ unsigned int k, j = n >> 1;
+
+ while (r >= j)
+ {
+ r -= j;
+ j >>= 1;
+ }
+ r |= j;
+
+ k = r >> 1;
+ j = i << 3;
+ BUTTERFLY_10scale (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ scale);
+ k += n2;
+ j += 4;
+ BUTTERFLY_10scale (X[k], X[k + 1],
+ X[k + n], X[k + n + 1],
+ Y[j], Y[j + 1],
+ Y[j + 2], Y[j + 3],
+ scale);
+ }
+}
+
+static void
+reference_power2_fftc (unsigned int n_values,
+ const double *rivalues_in,
+ double *rivalues,
+ int esign)
+{
+ const unsigned int n_values2 = n_values << 1;
+ double theta = esign < 0 ? -3.1415926535897932384626433832795029 : 3.1415926535897932384626433832795029;
+ unsigned int block_size = 2 << 1;
+ double last_sin;
+
+ if (esign > 0)
+ reference_bitreverse_fft2analysis (n_values, rivalues_in, rivalues);
+ else
+ reference_bitreverse_fft2synthesis (n_values, rivalues_in, rivalues);
+ theta *= (double) 1.0 / 2.;
+ last_sin = sin (theta);
+
+ if (n_values < 4)
+ return;
+
+ do
+ {
+ double Dre, Dim, Wre, Wim;
+ unsigned int k, i, half_block = block_size >> 1;
+ unsigned int block_size2 = block_size << 1;
+
+ theta *= 0.5;
+ Dim = last_sin;
+ last_sin = sin (theta);
+ Dre = last_sin * last_sin * -2.;
+
+ /* loop over first coefficient in each block ==> w == {1,0} */
+ for (i = 0; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_10 (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __1, __0);
+ }
+ Wre = Dre + 1.0; /* update Wk */
+ Wim = Dim; /* update Wk */
+ /* loop for every Wk in the first half of each subblock */
+ for (k = 2; k < half_block; k += 2)
+ {
+ /* loop over kth coefficient in each block */
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_XY (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, Dre, Dim); /* update Wk */
+ }
+ /* handle middle coefficient ==> w == {0,+-1} */
+ if (k < block_size)
+ {
+ /* loop over kth coefficient in each block */
+ if (esign > 0)
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_01 (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __0, __1);
+ }
+ else
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_0m (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ __0, __1);
+ }
+ /* update Wk */
+ if (esign > 0)
+ {
+ Wre = -Dim;
+ Wim = Dre + 1.0;
+ }
+ else
+ {
+ Wre = Dim;
+ Wim = -Dre - 1.0;
+ }
+ k += 2;
+ }
+ /* loop for every Wk in the second half of each subblock */
+ for (; k < block_size; k += 2)
+ {
+ /* loop over kth coefficient in each block */
+ for (i = k; i < n_values2; i += block_size2)
+ {
+ unsigned int v1 = i, v2 = i + block_size;
+
+ BUTTERFLY_XY (rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ rivalues[v1], rivalues[v1 + 1],
+ rivalues[v2], rivalues[v2 + 1],
+ Wre, Wim);
+ }
+ WMULTIPLY (Wre, Wim, Dre, Dim); /* update Wk */
+ }
+ block_size = block_size2;
+ }
+ while (block_size <= n_values);
+}
diff --git a/flow/gsl/gslfilehash.c b/flow/gsl/gslfilehash.c
new file mode 100644
index 0000000..ac4c066
--- /dev/null
+++ b/flow/gsl/gslfilehash.c
@@ -0,0 +1,464 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "gslfilehash.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+
+/* macros */
+#if (GLIB_SIZEOF_LONG > 4)
+#define HASH_LONG(l) (l + (l >> 32))
+#else
+#define HASH_LONG(l) (l)
+#endif
+
+
+/* --- variables --- */
+static GslMutex fdpool_mutex = { 0, };
+static GHashTable *hfile_ht = NULL;
+
+
+/* --- functions --- */
+static guint
+hfile_hash (gconstpointer key)
+{
+ const GslHFile *hfile = key;
+ guint h;
+
+ h = HASH_LONG (hfile->mtime);
+ h ^= g_str_hash (hfile->file_name);
+ h ^= HASH_LONG (hfile->n_bytes);
+
+ return h;
+}
+
+static gboolean
+hfile_equals (gconstpointer key1,
+ gconstpointer key2)
+{
+ const GslHFile *hfile1 = key1;
+ const GslHFile *hfile2 = key2;
+
+ return (hfile1->mtime == hfile2->mtime &&
+ hfile1->n_bytes == hfile2->n_bytes &&
+ strcmp (hfile1->file_name, hfile2->file_name) == 0);
+}
+
+void
+_gsl_init_fd_pool (void)
+{
+ g_assert (hfile_ht == NULL);
+
+ gsl_mutex_init (&fdpool_mutex);
+ hfile_ht = g_hash_table_new (hfile_hash, hfile_equals);
+}
+
+static gboolean
+stat_fd (gint fd,
+ GTime *mtime,
+ GslLong *n_bytes)
+{
+ struct stat statbuf = { 0, };
+
+ if (fstat (fd, &statbuf) < 0)
+ return FALSE; /* have errno */
+ if (mtime)
+ *mtime = statbuf.st_mtime;
+ if (n_bytes)
+ *n_bytes = statbuf.st_size;
+ return TRUE;
+}
+
+static gboolean
+stat_file (const gchar *file_name,
+ GTime *mtime,
+ GslLong *n_bytes)
+{
+ struct stat statbuf = { 0, };
+
+ if (stat (file_name, &statbuf) < 0)
+ return FALSE; /* have errno */
+ if (mtime)
+ *mtime = statbuf.st_mtime;
+ if (n_bytes)
+ *n_bytes = statbuf.st_size;
+ return TRUE;
+}
+
+/**
+ * gsl_hfile_open
+ * @file_name: name of the file to open
+ * @RETURNS: a new opened #GslHFile or NULL if an error occoured (errno set)
+ *
+ * Open a file for reading and return the associated GSL hashed file.
+ * The motivation for using a #GslHFile over normal unix file
+ * descriptors is to reduce the amount of opened unix file descriptors and
+ * to ensure thread safety upon reading offset relative byte blocks.
+ * Multiple open #GslHFiles with equal file names will share a
+ * single unix file descriptor as long as the file wasn't modified meanwhile.
+ * This function is MT-safe and may be called from any thread.
+ */
+GslHFile*
+gsl_hfile_open (const gchar *file_name)
+{
+ GslHFile key, *hfile;
+ gint ret_errno;
+
+ errno = EFAULT;
+ g_return_val_if_fail (file_name != NULL, NULL);
+
+ key.file_name = (gchar*) file_name;
+ if (!stat_file (file_name, &key.mtime, &key.n_bytes))
+ return NULL; /* errno from stat() */
+
+ GSL_SYNC_LOCK (&fdpool_mutex);
+ hfile = g_hash_table_lookup (hfile_ht, &key);
+ if (hfile)
+ {
+ GSL_SYNC_LOCK (&hfile->mutex);
+ hfile->ocount++;
+ GSL_SYNC_UNLOCK (&hfile->mutex);
+ ret_errno = 0;
+ }
+ else
+ {
+ gint fd;
+
+ fd = open (file_name, O_RDONLY | O_NOCTTY, 0);
+ if (fd >= 0)
+ {
+ hfile = gsl_new_struct0 (GslHFile, 1);
+ hfile->file_name = g_strdup (file_name);
+ hfile->mtime = key.mtime;
+ hfile->n_bytes = key.n_bytes;
+ hfile->cpos = 0;
+ hfile->fd = fd;
+ hfile->ocount = 1;
+ gsl_mutex_init (&hfile->mutex);
+ g_hash_table_insert (hfile_ht, hfile, hfile);
+ ret_errno = 0;
+ }
+ else
+ ret_errno = errno;
+ }
+ GSL_SYNC_UNLOCK (&fdpool_mutex);
+
+ errno = ret_errno;
+ return hfile;
+}
+
+/**
+ * gsl_hfile_close
+ * @hfile: valid #GslHFile
+ *
+ * Close and destroy a #GslHFile.
+ * This function is MT-safe and may be called from any thread.
+ */
+void
+gsl_hfile_close (GslHFile *hfile)
+{
+ gboolean destroy = FALSE;
+
+ g_return_if_fail (hfile != NULL);
+ g_return_if_fail (hfile->ocount > 0);
+
+ GSL_SYNC_LOCK (&fdpool_mutex);
+ GSL_SYNC_LOCK (&hfile->mutex);
+ if (hfile->ocount > 1)
+ hfile->ocount--;
+ else
+ {
+ if (!g_hash_table_remove (hfile_ht, hfile))
+ g_warning ("%s: failed to unlink hashed file (%p)",
+ G_STRLOC, hfile);
+ else
+ {
+ hfile->ocount = 0;
+ destroy = TRUE;
+ }
+ }
+ GSL_SYNC_UNLOCK (&hfile->mutex);
+ GSL_SYNC_UNLOCK (&fdpool_mutex);
+
+ if (destroy)
+ {
+ gsl_mutex_destroy (&hfile->mutex);
+ close (hfile->fd);
+ g_free (hfile->file_name);
+ gsl_delete_struct (GslHFile, hfile);
+ }
+ errno = 0;
+}
+
+/**
+ * gsl_hfile_pread
+ * @hfile: valid GslHFile
+ * @offset: offset in bytes within 0 and file end
+ * @n_bytes: number of bytes to read
+ * @bytes: buffer to store read bytes
+ * @error_p: pointer to GslErrorType location
+ * @RETURNS: amount of bytes read or -1 if an error occoured (errno set)
+ *
+ * Read a block of bytes from a GslHFile.
+ * This function is MT-safe and may be called from any thread.
+ */
+GslLong
+gsl_hfile_pread (GslHFile *hfile,
+ GslLong offset,
+ GslLong n_bytes,
+ gpointer bytes)
+{
+ GslLong ret_bytes = -1;
+ gint ret_errno;
+
+ errno = EFAULT;
+ g_return_val_if_fail (hfile != NULL, -1);
+ g_return_val_if_fail (hfile->ocount > 0, -1);
+ g_return_val_if_fail (offset >= 0, -1);
+ if (offset >= hfile->n_bytes || n_bytes < 1)
+ {
+ errno = 0;
+ return 0;
+ }
+ g_return_val_if_fail (bytes != NULL, -1);
+
+ GSL_SYNC_LOCK (&hfile->mutex);
+ if (hfile->ocount)
+ {
+ if (hfile->cpos != offset)
+ {
+ hfile->cpos = lseek (hfile->fd, offset, SEEK_SET);
+ if (hfile->cpos < 0 && errno != EINVAL)
+ {
+ ret_errno = errno;
+ GSL_SYNC_UNLOCK (&hfile->mutex);
+ errno = ret_errno;
+ return -1;
+ }
+ }
+ if (hfile->cpos == offset)
+ {
+ do
+ ret_bytes = read (hfile->fd, bytes, n_bytes);
+ while (ret_bytes < 0 && errno == EINTR);
+ if (ret_bytes < 0)
+ {
+ ret_errno = errno;
+ ret_bytes = -1;
+ }
+ else
+ {
+ ret_errno = 0;
+ hfile->cpos += ret_bytes;
+ }
+ }
+ else /* this should only happen if the file changed since open() */
+ {
+ hfile->cpos = -1;
+ if (offset + n_bytes > hfile->n_bytes)
+ n_bytes = hfile->n_bytes - offset;
+ memset (bytes, 0, n_bytes);
+ ret_bytes = n_bytes;
+ ret_errno = 0;
+ }
+ }
+ else
+ ret_errno = EFAULT;
+ GSL_SYNC_UNLOCK (&hfile->mutex);
+
+ errno = ret_errno;
+ return ret_bytes;
+}
+
+/**
+ * gsl_rfile_open
+ * @file_name: name of the file to open
+ * @RETURNS: a new opened #GslRFile or NULL if an error occoured (errno set)
+ *
+ * Open a file for reading and create a GSL read only file handle for it.
+ * The motivation for using a #GslRFile over normal unix files
+ * is to reduce the amount of opened unix file descriptors by using
+ * a #GslHFile for the actual IO.
+ */
+GslRFile*
+gsl_rfile_open (const gchar *file_name)
+{
+ GslHFile *hfile = gsl_hfile_open (file_name);
+ GslRFile *rfile;
+
+ if (!hfile)
+ rfile = NULL;
+ else
+ {
+ rfile = gsl_new_struct0 (GslRFile, 1);
+ rfile->hfile = hfile;
+ rfile->offset = 0;
+ }
+ return rfile;
+}
+
+/**
+ * gsl_rfile_name
+ * @rfile: valid #GslRFile
+ * @RETURNS: the file name used to open this file
+ *
+ * Retrive the file name used to open @rfile.
+ */
+gchar*
+gsl_rfile_name (GslRFile *rfile)
+{
+ errno = EFAULT;
+ g_return_val_if_fail (rfile != NULL, NULL);
+
+ errno = 0;
+ return rfile->hfile->file_name;
+}
+
+/**
+ * gsl_rfile_seek_set
+ * @rfile: valid #GslRFile
+ * @offset: new seek position within 0 and gsl_rfile_length()+1
+ * @RETURNS: resulting position within 0 and gsl_rfile_length()+1
+ *
+ * Set the current #GslRFile seek position.
+ */
+GslLong
+gsl_rfile_seek_set (GslRFile *rfile,
+ GslLong offset)
+{
+ GslLong l;
+
+ errno = EFAULT;
+ g_return_val_if_fail (rfile != NULL, 0);
+
+ l = rfile->hfile->n_bytes;
+ rfile->offset = CLAMP (offset, 0, l);
+
+ errno = 0;
+ return rfile->offset;
+}
+
+/**
+ * gsl_rfile_position
+ * @rfile: valid #GslRFile
+ * @RETURNS: current position within 0 and gsl_rfile_length()
+ *
+ * Retrive the current #GslRFile seek position.
+ */
+GslLong
+gsl_rfile_position (GslRFile *rfile)
+{
+ errno = EFAULT;
+ g_return_val_if_fail (rfile != NULL, 0);
+
+ errno = 0;
+ return rfile->offset;
+}
+
+/**
+ * gsl_rfile_length
+ * @rfile: valid #GslRFile
+ * @RETURNS: total length of the #GslRFile in bytes
+ *
+ * Retrive the file length of @rfile in bytes.
+ */
+GslLong
+gsl_rfile_length (GslRFile *rfile)
+{
+ GslLong l;
+
+ errno = EFAULT;
+ g_return_val_if_fail (rfile != NULL, 0);
+
+ l = rfile->hfile->n_bytes;
+
+ errno = 0;
+ return l;
+}
+
+/**
+ * gsl_rfile_pread
+ * @rfile: valid GslRFile
+ * @offset: offset in bytes within 0 and gsl_rfile_length()
+ * @n_bytes: number of bytes to read
+ * @bytes: buffer to store read bytes
+ * @error_p: pointer to GslErrorType location
+ * @RETURNS: amount of bytes read or -1 if an error occoured (errno set)
+ *
+ * Read a block of bytes from a GslRFile at a specified position.
+ */
+GslLong
+gsl_rfile_pread (GslRFile *rfile,
+ GslLong offset,
+ GslLong n_bytes,
+ gpointer bytes)
+{
+ errno = EFAULT;
+ g_return_val_if_fail (rfile != NULL, -1);
+
+ return gsl_hfile_pread (rfile->hfile, offset, n_bytes, bytes);
+}
+
+/**
+ * gsl_rfile_read
+ * @rfile: valid GslRFile
+ * @n_bytes: number of bytes to read
+ * @bytes: buffer to store read bytes
+ * @error_p: pointer to GslErrorType location
+ * @RETURNS: amount of bytes read or -1 if an error occoured (errno set)
+ *
+ * Read a block of bytes from a GslRFile from the current seek position
+ * and advance the seek position.
+ */
+GslLong
+gsl_rfile_read (GslRFile *rfile,
+ GslLong n_bytes,
+ gpointer bytes)
+{
+ GslLong l;
+
+ errno = EFAULT;
+ g_return_val_if_fail (rfile != NULL, -1);
+
+ l = gsl_hfile_pread (rfile->hfile, rfile->offset, n_bytes, bytes);
+ if (l > 0)
+ rfile->offset += l;
+ return l;
+}
+
+/**
+ * gsl_rfile_close
+ * @rfile: valid #GslRFile
+ *
+ * Close and destroy a #GslRFile.
+ */
+void
+gsl_rfile_close (GslRFile *rfile)
+{
+ errno = EFAULT;
+ g_return_if_fail (rfile != NULL);
+
+ gsl_hfile_close (rfile->hfile);
+ gsl_delete_struct (GslRFile, rfile);
+ errno = 0;
+}
diff --git a/flow/gsl/gslfilehash.h b/flow/gsl/gslfilehash.h
new file mode 100644
index 0000000..cc70bee
--- /dev/null
+++ b/flow/gsl/gslfilehash.h
@@ -0,0 +1,77 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_FILE_HASH_H__
+#define __GSL_FILE_HASH_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gslcommon.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/* --- typedefs & structures --- */
+typedef struct {
+ gchar *file_name;
+ GTime mtime;
+ GslLong n_bytes;
+ /*< private >*/
+ GslLong cpos;
+ GslMutex mutex;
+ gint fd;
+ guint ocount;
+} GslHFile;
+typedef struct {
+ GslHFile *hfile;
+ GslLong offset;
+} GslRFile;
+
+
+/* --- GslHFile API --- */
+GslHFile* gsl_hfile_open (const gchar *file_name);
+GslLong gsl_hfile_pread (GslHFile *hfile,
+ GslLong offset,
+ GslLong n_bytes,
+ gpointer bytes);
+void gsl_hfile_close (GslHFile *hfile);
+
+
+/* --- GslRFile API --- */
+GslRFile* gsl_rfile_open (const gchar *file_name);
+gchar* gsl_rfile_name (GslRFile *rfile);
+GslLong gsl_rfile_pread (GslRFile *rfile,
+ GslLong offset,
+ GslLong n_bytes,
+ gpointer bytes);
+GslLong gsl_rfile_read (GslRFile *rfile,
+ GslLong n_bytes,
+ gpointer bytes);
+GslLong gsl_rfile_seek_set (GslRFile *rfile,
+ GslLong offset);
+GslLong gsl_rfile_position (GslRFile *rfile);
+GslLong gsl_rfile_length (GslRFile *rfile);
+void gsl_rfile_close (GslRFile *rfile);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_FILE_HASH_H__ */
diff --git a/flow/gsl/gslfilter.c b/flow/gsl/gslfilter.c
new file mode 100644
index 0000000..5bf8ff5
--- /dev/null
+++ b/flow/gsl/gslfilter.c
@@ -0,0 +1,1379 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslfilter.h"
+
+#include "gslfft.h"
+#include "gslsignal.h"
+#include <string.h>
+
+
+/* --- common utilities --- */
+static inline double
+cotan (double x)
+{
+ return - tan (x + GSL_PI * 0.5);
+}
+
+static double
+gsl_db_invert (double x)
+{
+ /* db = 20*log(x)/log(10); */
+ return exp (x * log (10) / 20.0);
+}
+
+static void
+band_filter_common (unsigned int iorder,
+ double p_freq, /* 0..pi */
+ double s_freq, /* 0..pi */
+ double epsilon,
+ GslComplex *roots,
+ GslComplex *poles,
+ double *a, /* [0..iorder] */
+ double *b,
+ gboolean band_pass,
+ gboolean t1_norm)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *poly = g_newa (GslComplex, iorder + 1);
+ GslComplex fpoly[2 + 1] = { { 0, }, { 0, }, { 1, 0 } };
+ double alpha, norm;
+ guint i;
+
+ epsilon = gsl_trans_zepsilon2ss (epsilon);
+ alpha = cos ((s_freq + p_freq) * 0.5) / cos ((s_freq - p_freq) * 0.5);
+
+ fpoly[0] = gsl_complex (1, 0);
+ fpoly[1] = gsl_complex (1, 0);
+ for (i = 0; i < iorder2; i++)
+ {
+ fpoly[0] = gsl_complex_mul (fpoly[0], gsl_complex_sub (gsl_complex (1, 0), gsl_complex_reciprocal (roots[i])));
+ fpoly[1] = gsl_complex_mul (fpoly[1], gsl_complex_sub (gsl_complex (1, 0), gsl_complex_reciprocal (poles[i])));
+ }
+ norm = gsl_complex_div (fpoly[1], fpoly[0]).re;
+
+ if ((iorder2 & 1) == 0) /* norm is fluctuation minimum */
+ norm *= sqrt (1.0 / (1.0 + epsilon * epsilon));
+
+ /* z nominator polynomial */
+ poly[0] = gsl_complex (norm, 0);
+ for (i = 0; i < iorder2; i++)
+ {
+ GslComplex t, alphac = gsl_complex (alpha, 0);
+
+ t = band_pass ? gsl_complex_inv (roots[i]) : roots[i];
+ fpoly[1] = gsl_complex_sub (gsl_complex_div (alphac, t), alphac);
+ fpoly[0] = gsl_complex_inv (gsl_complex_reciprocal (t));
+ gsl_cpoly_mul (poly, i * 2, poly, 2, fpoly);
+ }
+ for (i = 0; i <= iorder; i++)
+ a[i] = poly[i].re;
+
+ /* z denominator polynomial */
+ poly[0] = gsl_complex (1, 0);
+ for (i = 0; i < iorder2; i++)
+ {
+ GslComplex t, alphac = gsl_complex (alpha, 0);
+
+ t = band_pass ? gsl_complex_inv (poles[i]) : poles[i];
+ fpoly[1] = gsl_complex_sub (gsl_complex_div (alphac, t), alphac);
+ fpoly[0] = gsl_complex_inv (gsl_complex_reciprocal (t));
+ gsl_cpoly_mul (poly, i * 2, poly, 2, fpoly);
+ }
+ for (i = 0; i <= iorder; i++)
+ b[i] = poly[i].re;
+ gsl_poly_scale (iorder, a, 1.0 / b[0]);
+ gsl_poly_scale (iorder, b, 1.0 / b[0]);
+}
+
+static void
+filter_rp_to_z (unsigned int iorder,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ GslComplex *poly = g_newa (GslComplex, iorder + 1);
+ guint i;
+
+ /* z nominator polynomial */
+ poly[0] = gsl_complex (1, 0);
+ for (i = 0; i < iorder; i++)
+ gsl_cpoly_mul_reciprocal (i + 1, poly, roots[i]);
+ for (i = 0; i <= iorder; i++)
+ a[i] = poly[i].re;
+
+ /* z denominator polynomial */
+ poly[0] = gsl_complex (1, 0);
+ for (i = 0; i < iorder; i++)
+ gsl_cpoly_mul_reciprocal (i + 1, poly, poles[i]);
+ for (i = 0; i <= iorder; i++)
+ b[i] = poly[i].re;
+}
+
+static void
+filter_lp_invert (unsigned int iorder,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ guint i;
+
+ for (i = 1; i <= iorder; i +=2)
+ {
+ a[i] = -a[i];
+ b[i] = -b[i];
+ }
+}
+
+
+/* --- butterworth filter --- */
+void
+gsl_filter_butter_rp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles)
+{
+ double pi = GSL_PI, order = iorder;
+ double beta_mul = pi / (2.0 * order);
+ /* double kappa = gsl_trans_freq2s (freq); */
+ double kappa;
+ GslComplex root;
+ unsigned int i;
+
+ epsilon = gsl_trans_zepsilon2ss (epsilon);
+ kappa = gsl_trans_freq2s (freq) * pow (epsilon, -1.0 / order);
+
+ /* construct poles for butterworth filter */
+ for (i = 1; i <= iorder; i++)
+ {
+ double t = (i << 1) + iorder - 1;
+ double beta = t * beta_mul;
+
+ root.re = kappa * cos (beta);
+ root.im = kappa * sin (beta);
+ poles[i - 1] = gsl_trans_s2z (root);
+ }
+
+ /* z nominator polynomial */
+ for (i = 0; i < iorder; i++)
+ roots[i] = gsl_complex (-1, 0);
+}
+
+
+/* --- tschebyscheff type 1 filter --- */
+static double
+tschebyscheff_eval (unsigned int degree,
+ double x)
+{
+ double td = x, td_m_1 = 1;
+ unsigned int d = 1;
+
+ /* eval polynomial for a certain x */
+ if (degree == 0)
+ return 1;
+
+ while (d < degree)
+ {
+ double td1 = 2 * x * td - td_m_1;
+
+ td_m_1 = td;
+ td = td1;
+ d++;
+ }
+ return td;
+}
+
+static double
+tschebyscheff_inverse (unsigned int degree,
+ double x)
+{
+ /* note, that thebyscheff_eval(degree,x)=cosh(degree*acosh(x)) */
+ return cosh (acosh (x) / degree);
+}
+
+void
+gsl_filter_tscheb1_rp (unsigned int iorder,
+ double freq, /* 1..pi */
+ double epsilon,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles)
+{
+ double pi = GSL_PI, order = iorder;
+ double alpha;
+ double beta_mul = pi / (2.0 * order);
+ double kappa = gsl_trans_freq2s (freq);
+ GslComplex root;
+ unsigned int i;
+
+ epsilon = gsl_trans_zepsilon2ss (epsilon);
+ alpha = asinh (1.0 / epsilon) / order;
+
+ /* construct poles polynomial from tschebyscheff polynomial */
+ for (i = 1; i <= iorder; i++)
+ {
+ double t = (i << 1) + iorder - 1;
+ double beta = t * beta_mul;
+
+ root.re = kappa * sinh (alpha) * cos (beta);
+ root.im = kappa * cosh (alpha) * sin (beta);
+ poles[i - 1] = gsl_trans_s2z (root);
+ }
+
+ /* z nominator polynomial */
+ for (i = 0; i < iorder; i++)
+ roots[i] = gsl_complex (-1, 0);
+}
+
+
+/* --- tschebyscheff type 2 filter --- */
+void
+gsl_filter_tscheb2_rp (unsigned int iorder,
+ double c_freq, /* 1..pi */
+ double steepness,
+ double epsilon,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles)
+{
+ double pi = GSL_PI, order = iorder;
+ double r_freq = c_freq * steepness;
+ double kappa_c = gsl_trans_freq2s (c_freq);
+ double kappa_r = gsl_trans_freq2s (r_freq);
+ double tepsilon;
+ double alpha;
+ double beta_mul = pi / (2.0 * order);
+ GslComplex root;
+ unsigned int i;
+
+#if 0
+ /* triggers an internal compiler error with gcc-2.95.4 (and certain
+ * combinations of optimization options)
+ */
+ g_return_if_fail (c_freq * steepness < GSL_PI);
+#endif
+ g_return_if_fail (steepness > 1.0);
+
+ epsilon = gsl_trans_zepsilon2ss (epsilon);
+ tepsilon = epsilon * tschebyscheff_eval (iorder, kappa_r / kappa_c);
+ alpha = asinh (tepsilon) / order;
+
+ /* construct poles polynomial from tschebyscheff polynomial */
+ for (i = 1; i <= iorder; i++)
+ {
+ double t = (i << 1) + iorder - 1;
+ double beta = t * beta_mul;
+
+ root.re = sinh (alpha) * cos (beta);
+ root.im = cosh (alpha) * sin (beta);
+ root = gsl_complex_div (gsl_complex (kappa_r, 0), root);
+ root = gsl_trans_s2z (root);
+ poles[i - 1] = root;
+ }
+
+ /* construct roots polynomial from tschebyscheff polynomial */
+ for (i = 1; i <= iorder; i++)
+ {
+ double t = (i << 1) - 1;
+ GslComplex root = gsl_complex (0, cos (t * beta_mul));
+
+ if (fabs (root.im) > 1e-14)
+ {
+ root = gsl_complex_div (gsl_complex (kappa_r, 0), root);
+ root = gsl_trans_s2z (root);
+ }
+ else
+ root = gsl_complex (-1, 0);
+ roots[i - 1] = root;
+ }
+}
+
+/**
+ * gsl_filter_tscheb2_steepness_db
+ * @iorder: filter order
+ * @c_freq: passband cutoff frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @stopband_db: reduction in stopband in dB (>= 0)
+ * Calculates the steepness parameter for Tschebyscheff type 2 lowpass filter,
+ * based on the ripple residue in the stop band.
+ */
+double
+gsl_filter_tscheb2_steepness_db (unsigned int iorder,
+ double c_freq,
+ double epsilon,
+ double stopband_db)
+{
+ return gsl_filter_tscheb2_steepness (iorder, c_freq, epsilon, gsl_db_invert (-stopband_db));
+}
+
+/**
+ * gsl_filter_tscheb2_steepness
+ * @iorder: filter order
+ * @c_freq: passband cutoff frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @residue: maximum of transfer function in stopband (0..1)
+ * Calculates the steepness parameter for Tschebyscheff type 2 lowpass filter,
+ * based on ripple residue in the stop band.
+ */
+double
+gsl_filter_tscheb2_steepness (unsigned int iorder,
+ double c_freq,
+ double epsilon,
+ double residue)
+{
+ double kappa_c, kappa_r, r_freq;
+
+ epsilon = gsl_trans_zepsilon2ss (epsilon);
+ kappa_c = gsl_trans_freq2s (c_freq);
+ kappa_r = tschebyscheff_inverse (iorder, sqrt (1.0 / (residue * residue) - 1.0) / epsilon) * kappa_c;
+ r_freq = gsl_trans_freq2z (kappa_r);
+
+ return r_freq / c_freq;
+}
+
+
+/* --- lowpass filters --- */
+/**
+ * gsl_filter_butter_lp
+ * @iorder: filter order
+ * @freq: cutoff frequency (0..pi)
+ * @epsilon: fall off at cutoff frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Butterworth lowpass filter.
+ */
+void
+gsl_filter_butter_lp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ GslComplex *roots = g_newa (GslComplex, iorder);
+ GslComplex *poles = g_newa (GslComplex, iorder);
+ double norm;
+
+ g_return_if_fail (freq > 0 && freq < GSL_PI);
+
+ gsl_filter_butter_rp (iorder, freq, epsilon, roots, poles);
+ filter_rp_to_z (iorder, roots, poles, a, b);
+
+ /* scale maximum to 1.0 */
+ norm = gsl_poly_eval (iorder, b, 1) / gsl_poly_eval (iorder, a, 1);
+ gsl_poly_scale (iorder, a, norm);
+}
+
+/**
+ * gsl_filter_tscheb1_lp
+ * @iorder: filter order
+ * @freq: cutoff frequency (0..pi)
+ * @epsilon: fall off at cutoff frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 1 lowpass filter.
+ */
+void
+gsl_filter_tscheb1_lp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ GslComplex *roots = g_newa (GslComplex, iorder);
+ GslComplex *poles = g_newa (GslComplex, iorder);
+ double norm;
+
+ g_return_if_fail (freq > 0 && freq < GSL_PI);
+
+ gsl_filter_tscheb1_rp (iorder, freq, epsilon, roots, poles);
+ filter_rp_to_z (iorder, roots, poles, a, b);
+
+ /* scale maximum to 1.0 */
+ norm = gsl_poly_eval (iorder, b, 1) / gsl_poly_eval (iorder, a, 1);
+ if ((iorder & 1) == 0) /* norm is fluctuation minimum */
+ {
+ epsilon = gsl_trans_zepsilon2ss (epsilon);
+ norm *= sqrt (1.0 / (1.0 + epsilon * epsilon));
+ }
+ gsl_poly_scale (iorder, a, norm);
+}
+
+/**
+ * gsl_filter_tscheb2_lp
+ * @iorder: filter order
+ * @freq: passband cutoff frequency (0..pi)
+ * @steepness: frequency steepness (c_freq * steepness < pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 2 lowpass filter.
+ * To gain a transition band between freq1 and freq2, pass arguements
+ * @freq=freq1 and @steepness=freq2/freq1. To specify the transition
+ * band width in fractions of octaves, pass @steepness=2^octave_fraction.
+ */
+void
+gsl_filter_tscheb2_lp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ GslComplex *roots = g_newa (GslComplex, iorder);
+ GslComplex *poles = g_newa (GslComplex, iorder);
+ double norm;
+
+ g_return_if_fail (freq > 0 && freq < GSL_PI);
+ g_return_if_fail (freq * steepness < GSL_PI);
+ g_return_if_fail (steepness > 1.0);
+
+ gsl_filter_tscheb2_rp (iorder, freq, steepness, epsilon, roots, poles);
+ filter_rp_to_z (iorder, roots, poles, a, b);
+
+ /* scale maximum to 1.0 */
+ norm = gsl_poly_eval (iorder, b, 1) / gsl_poly_eval (iorder, a, 1); /* H(z=0):=1, e^(j*omega) for omega=0 => e^0==1 */
+ gsl_poly_scale (iorder, a, norm);
+}
+
+
+/* --- highpass filters --- */
+/**
+ * gsl_filter_butter_hp
+ * @iorder: filter order
+ * @freq: passband frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Butterworth highpass filter.
+ */
+void
+gsl_filter_butter_hp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ g_return_if_fail (freq > 0 && freq < GSL_PI);
+
+ freq = GSL_PI - freq;
+ gsl_filter_butter_lp (iorder, freq, epsilon, a, b);
+ filter_lp_invert (iorder, a, b);
+}
+
+/**
+ * gsl_filter_tscheb1_hp
+ * @iorder: filter order
+ * @freq: passband frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 1 highpass filter.
+ */
+void
+gsl_filter_tscheb1_hp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ g_return_if_fail (freq > 0 && freq < GSL_PI);
+
+ freq = GSL_PI - freq;
+ gsl_filter_tscheb1_lp (iorder, freq, epsilon, a, b);
+ filter_lp_invert (iorder, a, b);
+}
+
+/**
+ * gsl_filter_tscheb2_hp
+ * @iorder: filter order
+ * @freq: stopband frequency (0..pi)
+ * @steepness: frequency steepness
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 2 highpass filter.
+ */
+void
+gsl_filter_tscheb2_hp (unsigned int iorder,
+ double freq,
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ g_return_if_fail (freq > 0 && freq < GSL_PI);
+
+ freq = GSL_PI - freq;
+ gsl_filter_tscheb2_lp (iorder, freq, steepness, epsilon, a, b);
+ filter_lp_invert (iorder, a, b);
+}
+
+
+/* --- bandpass filters --- */
+/**
+ * gsl_filter_butter_bp
+ * @iorder: filter order (must be even)
+ * @freq1: stopband end frequency (0..pi)
+ * @freq2: passband end frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Butterworth bandpass filter.
+ */
+void
+gsl_filter_butter_bp (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *roots = g_newa (GslComplex, iorder2);
+ GslComplex *poles = g_newa (GslComplex, iorder2);
+ double theta;
+
+ g_return_if_fail ((iorder & 0x01) == 0);
+ g_return_if_fail (freq1 > 0);
+ g_return_if_fail (freq1 < freq2);
+ g_return_if_fail (freq2 < GSL_PI);
+
+ theta = 2. * atan2 (1., cotan ((freq2 - freq1) * 0.5));
+
+ gsl_filter_butter_rp (iorder2, theta, epsilon, roots, poles);
+ band_filter_common (iorder, freq1, freq2, epsilon, roots, poles, a, b, TRUE, FALSE);
+}
+
+/**
+ * gsl_filter_tscheb1_bp
+ * @iorder: filter order (must be even)
+ * @freq1: stopband end frequency (0..pi)
+ * @freq2: passband end frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 1 bandpass filter.
+ */
+void
+gsl_filter_tscheb1_bp (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *roots = g_newa (GslComplex, iorder2);
+ GslComplex *poles = g_newa (GslComplex, iorder2);
+ double theta;
+
+ g_return_if_fail ((iorder & 0x01) == 0);
+ g_return_if_fail (freq1 > 0);
+ g_return_if_fail (freq1 < freq2);
+ g_return_if_fail (freq2 < GSL_PI);
+
+ theta = 2. * atan2 (1., cotan ((freq2 - freq1) * 0.5));
+
+ gsl_filter_tscheb1_rp (iorder2, theta, epsilon, roots, poles);
+ band_filter_common (iorder, freq1, freq2, epsilon, roots, poles, a, b, TRUE, TRUE);
+}
+
+/**
+ * gsl_filter_tscheb2_bp
+ * @iorder: filter order (must be even)
+ * @freq1: stopband end frequency (0..pi)
+ * @freq2: passband end frequency (0..pi)
+ * @steepness: frequency steepness factor
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 2 bandpass filter.
+ */
+void
+gsl_filter_tscheb2_bp (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *roots = g_newa (GslComplex, iorder2);
+ GslComplex *poles = g_newa (GslComplex, iorder2);
+ double theta;
+
+ g_return_if_fail ((iorder & 0x01) == 0);
+ g_return_if_fail (freq1 > 0);
+ g_return_if_fail (freq1 < freq2);
+ g_return_if_fail (freq2 < GSL_PI);
+
+ theta = 2. * atan2 (1., cotan ((freq2 - freq1) * 0.5));
+
+ gsl_filter_tscheb2_rp (iorder2, theta, steepness, epsilon, roots, poles);
+ band_filter_common (iorder, freq1, freq2, epsilon, roots, poles, a, b, TRUE, FALSE);
+}
+
+
+/* --- bandstop filters --- */
+/**
+ * gsl_filter_butter_bs
+ * @iorder: filter order (must be even)
+ * @freq1: passband end frequency (0..pi)
+ * @freq2: stopband end frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Butterworth bandstop filter.
+ */
+void
+gsl_filter_butter_bs (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *roots = g_newa (GslComplex, iorder2);
+ GslComplex *poles = g_newa (GslComplex, iorder2);
+ double theta;
+
+ g_return_if_fail ((iorder & 0x01) == 0);
+ g_return_if_fail (freq1 > 0);
+ g_return_if_fail (freq1 < freq2);
+ g_return_if_fail (freq2 < GSL_PI);
+
+ theta = 2. * atan2 (1., tan ((freq2 - freq1) * 0.5));
+
+ gsl_filter_butter_rp (iorder2, theta, epsilon, roots, poles);
+ band_filter_common (iorder, freq1, freq2, epsilon, roots, poles, a, b, FALSE, FALSE);
+}
+
+/**
+ * gsl_filter_tscheb1_bs
+ * @iorder: filter order (must be even)
+ * @freq1: passband end frequency (0..pi)
+ * @freq2: stopband end frequency (0..pi)
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 1 bandstop filter.
+ */
+void
+gsl_filter_tscheb1_bs (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *roots = g_newa (GslComplex, iorder2);
+ GslComplex *poles = g_newa (GslComplex, iorder2);
+ double theta;
+
+ g_return_if_fail ((iorder & 0x01) == 0);
+ g_return_if_fail (freq1 > 0);
+ g_return_if_fail (freq1 < freq2);
+ g_return_if_fail (freq2 < GSL_PI);
+
+ theta = 2. * atan2 (1., tan ((freq2 - freq1) * 0.5));
+
+ gsl_filter_tscheb1_rp (iorder2, theta, epsilon, roots, poles);
+ band_filter_common (iorder, freq1, freq2, epsilon, roots, poles, a, b, FALSE, TRUE);
+}
+
+/**
+ * gsl_filter_tscheb2_bs
+ * @iorder: filter order (must be even)
+ * @freq1: passband end frequency (0..pi)
+ * @freq2: stopband end frequency (0..pi)
+ * @steepness: frequency steepness factor
+ * @epsilon: fall off at passband frequency (0..1)
+ * @a: root polynomial coefficients a[0..iorder]
+ * @b: pole polynomial coefficients b[0..iorder]
+ * Tschebyscheff type 2 bandstop filter.
+ */
+void
+gsl_filter_tscheb2_bs (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ unsigned int iorder2 = iorder >> 1;
+ GslComplex *roots = g_newa (GslComplex, iorder2);
+ GslComplex *poles = g_newa (GslComplex, iorder2);
+ double theta;
+
+ g_return_if_fail ((iorder & 0x01) == 0);
+ g_return_if_fail (freq1 > 0);
+ g_return_if_fail (freq1 < freq2);
+ g_return_if_fail (freq2 < GSL_PI);
+
+ theta = 2. * atan2 (1., tan ((freq2 - freq1) * 0.5));
+
+ gsl_filter_tscheb2_rp (iorder2, theta, steepness, epsilon, roots, poles);
+ band_filter_common (iorder, freq1, freq2, epsilon, roots, poles, a, b, FALSE, FALSE);
+}
+
+
+/* --- tschebyscheff type 1 via generic root-finding --- */
+#if 0
+static void
+tschebyscheff_poly (unsigned int degree,
+ double *v)
+{
+ /* construct all polynomial koefficients */
+ if (degree == 0)
+ v[0] = 1;
+ else if (degree == 1)
+ {
+ v[1] = 1; v[0] = 0;
+ }
+ else
+ {
+ double *u = g_newa (double, 1 + degree);
+
+ u[degree] = 0; u[degree - 1] = 0;
+ tschebyscheff_poly (degree - 2, u);
+
+ v[0] = 0;
+ tschebyscheff_poly (degree - 1, v + 1);
+ gsl_poly_scale (degree - 1, v + 1, 2);
+
+ gsl_poly_sub (degree, v, u);
+ }
+}
+
+static void
+gsl_filter_tscheb1_test (unsigned int iorder,
+ double zomega,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b)
+{
+ GslComplex *roots = g_newa (GslComplex, iorder * 2), *r;
+ GslComplex *zf = g_newa (GslComplex, 1 + iorder);
+ double *vk = g_newa (double, 1 + iorder), norm;
+ double *q = g_newa (double, 2 * (1 + iorder));
+ double O = gsl_trans_freq2s (zomega);
+ unsigned int i;
+
+ /* calc Vk() */
+ tschebyscheff_poly (iorder, vk);
+
+ /* calc q=1+e^2*Vk()^2 */
+ gsl_poly_mul (q, iorder >> 1, vk, iorder >> 1, vk);
+ iorder *= 2;
+ gsl_poly_scale (iorder, q, epsilon * epsilon);
+ q[0] += 1;
+
+ /* find roots, fix roots by 1/(jO) */
+ gsl_poly_complex_roots (iorder, q, roots);
+ for (i = 0; i < iorder; i++)
+ roots[i] = gsl_complex_mul (roots[i], gsl_complex (0, O));
+
+ /* choose roots from the left half-plane */
+ if (0)
+ g_print ("zhqr-root:\n%s\n", gsl_complex_list (iorder, roots, " "));
+ r = roots;
+ for (i = 0; i < iorder; i++)
+ if (roots[i].re < 0)
+ {
+ r->re = roots[i].re;
+ r->im = roots[i].im;
+ r++;
+ }
+ iorder /= 2;
+
+ /* assert roots found */
+ if (!(r - roots == iorder))
+ {
+ g_print ("ERROR: n_roots=%u != iorder=%u\n", r - roots, iorder);
+ abort ();
+ }
+
+ /* s => z */
+ for (i = 0; i < iorder; i++)
+ roots[i] = gsl_trans_s2z (roots[i]);
+
+ /* z denominator polynomial */
+ gsl_cpoly_from_roots (iorder, zf, roots);
+ for (i = 0; i <= iorder; i++)
+ b[i] = zf[i].re;
+
+ /* z nominator polynomial */
+ for (i = 0; i < iorder; i++)
+ {
+ roots[i].re = -1;
+ roots[i].im = 0;
+ }
+ gsl_cpoly_from_roots (iorder, zf, roots);
+ for (i = 0; i <= iorder; i++)
+ a[i] = zf[i].re;
+
+ /* scale for b[0]==1.0 */
+ gsl_poly_scale (iorder, b, 1.0 / b[0]);
+
+ /* scale maximum to 1.0 */
+ norm = gsl_poly_eval (iorder, a, 1) / gsl_poly_eval (iorder, b, 1);
+ if ((iorder & 0x01) == 0) /* norm is fluctuation minimum */
+ norm /= sqrt (1.0 / (1.0 + epsilon * epsilon));
+ gsl_poly_scale (iorder, a, 1.0 / norm);
+}
+#endif
+
+
+/* --- windowed fir approximation --- */
+/* returns a blackman window: x is supposed to be in the interval [0..1] */
+static inline double
+gsl_blackman_window (double x)
+{
+ if (x < 0)
+ return 0;
+ if (x > 1)
+ return 0;
+ return 0.42 - 0.5 * cos (GSL_PI * x * 2) + 0.08 * cos (4 * GSL_PI * x);
+}
+
+/**
+ * gsl_filter_fir_approx
+ *
+ * @iorder: order of the filter (must be oven, >= 2)
+ * @freq: the frequencies of the transfer function
+ * @value: the desired value of the transfer function
+ *
+ * Approximates a given transfer function with an iorder-coefficient FIR filter.
+ * It is recommended to provide enough frequency values, so that
+ * @n_points >= @iorder.
+ */
+void
+gsl_filter_fir_approx (unsigned int iorder,
+ double *a, /* [0..iorder] */
+ unsigned int n_points,
+ const double *freq,
+ const double *value)
+{
+ /* TODO:
+ *
+ * a) does fft_size matter for the quality of the approximation? i.e. do
+ * larger fft_sizes produce better filters?
+ * b) generalize windowing
+ */
+ unsigned int fft_size = 8;
+ unsigned int point = 0, i;
+ double lfreq = -2, lval = 1.0, rfreq = -1, rval = 1.0;
+ double *fft_in, *fft_out;
+ double ffact;
+
+ g_return_if_fail (iorder >= 2);
+ g_return_if_fail ((iorder & 1) == 0);
+
+ while (fft_size / 2 <= iorder)
+ fft_size *= 2;
+
+ fft_in = g_newa (double, fft_size*2);
+ fft_out = fft_in+fft_size;
+ ffact = 2.0 * GSL_PI / (double)fft_size;
+
+ for (i = 0; i <= fft_size / 2; i++)
+ {
+ double f = (double) i * ffact;
+ double pos, val;
+
+ while (f > rfreq && point != n_points)
+ {
+ lfreq = rfreq;
+ rfreq = freq[point];
+ lval = rval;
+ rval = value[point];
+ point++;
+ }
+
+ pos = (f - lfreq) / (rfreq - lfreq);
+ val = lval * (1.0 - pos) + rval * pos;
+
+ if (i != fft_size / 2)
+ {
+ fft_in[2 * i] = val;
+ fft_in[2 * i + 1] = 0.0;
+ }
+ else
+ fft_in[1] = val;
+ }
+
+ gsl_power2_fftsr (fft_size, fft_in, fft_out);
+
+ for (i = 0; i <= iorder / 2; i++)
+ {
+ double c = fft_out[i] * gsl_blackman_window (0.5 + (double) i / (iorder + 2.0));
+ a[iorder / 2 - i] = c;
+ a[iorder / 2 + i] = c;
+ }
+}
+
+
+/* --- filter evaluation --- */
+void
+gsl_iir_filter_setup (GslIIRFilter *f,
+ guint order,
+ const gdouble *a,
+ const gdouble *b,
+ gdouble *buffer) /* 4*(order+1) */
+{
+ guint i;
+
+ g_return_if_fail (f != NULL && a != NULL && b != NULL && buffer != NULL);
+ g_return_if_fail (order > 0);
+
+ f->order = order;
+ f->a = buffer;
+ f->b = f->a + order + 1;
+ f->w = f->b + order + 1;
+
+ memcpy (f->a, a, sizeof (a[0]) * (order + 1));
+ for (i = 0; i <= order; i++)
+ f->b[i] = -b[i];
+ memset (f->w, 0, sizeof (f->w[0]) * (order + 1) * 2);
+
+ g_return_if_fail (fabs (b[0] - 1.0) < 1e-14);
+}
+
+void
+gsl_iir_filter_change (GslIIRFilter *f,
+ guint order,
+ const gdouble *a,
+ const gdouble *b,
+ gdouble *buffer)
+{
+ guint i;
+
+ g_return_if_fail (f != NULL && a != NULL && b != NULL && buffer != NULL);
+ g_return_if_fail (order > 0);
+
+ /* there's no point in calling this function if f wasn't setup properly
+ * and it's only the As and Bs that changed
+ */
+ g_return_if_fail (f->a == buffer && f->b == f->a + f->order + 1 && f->w == f->b + f->order + 1);
+
+ /* if the order changed there's no chance preserving state */
+ if (f->order != order)
+ {
+ gsl_iir_filter_setup (f, order, a, b, buffer);
+ return;
+ }
+
+ memcpy (f->a, a, sizeof (a[0]) * (order + 1));
+ for (i = 0; i <= order; i++)
+ f->b[i] = -b[i];
+ /* leaving f->w to preserve state */
+
+ g_return_if_fail (fabs (b[0] - 1.0) < 1e-14);
+}
+
+static inline gdouble /* Y */
+filter_step_direct_canon_2 (GslIIRFilter *f,
+ gdouble X)
+{
+ register guint n = f->order;
+ gdouble *a = f->a, *b = f->b, *w = f->w;
+ gdouble x, y, v;
+
+ v = w[n];
+ x = b[n] * v;
+ y = a[n] * v;
+
+ while (--n)
+ {
+ gdouble t1, t2;
+
+ v = w[n];
+ t1 = v * b[n];
+ t2 = v * a[n];
+ w[n+1] = v;
+ x += t1;
+ y += t2;
+ }
+
+ x += X;
+ w[1] = x;
+ y += x * a[0];
+ /* w[0] unused */
+
+ return y;
+}
+
+static inline gdouble /* Y */
+filter_step_direct_canon_1 (GslIIRFilter *f,
+ gdouble X)
+{
+ register guint n = f->order;
+ gdouble *a = f->a, *b = f->b, *w = f->w;
+ gdouble y, v;
+
+ /* w[n] unused */
+ y = X * a[0] + w[0];
+ v = X * a[n] + y * b[n];
+
+ while (--n)
+ {
+ gdouble t = w[n];
+
+ w[n] = v;
+ t += X * a[n];
+ v = y * b[n];
+ v += t;
+ }
+ w[0] = v;
+
+ return y;
+}
+
+#define filter_step filter_step_direct_canon_1
+
+void
+gsl_iir_filter_eval (GslIIRFilter *f,
+ guint n_values,
+ const gfloat *x,
+ gfloat *y)
+{
+ const gfloat *bound;
+
+ g_return_if_fail (f != NULL && x != NULL && y != NULL);
+ g_return_if_fail (f->order > 0);
+
+ bound = x + n_values;
+ while (x < bound)
+ {
+ *y = filter_step (f, *x);
+ x++;
+ y++;
+ }
+}
+
+
+/* --- biquad filters --- */
+void
+gsl_biquad_config_init (GslBiquadConfig *c,
+ GslBiquadType type,
+ GslBiquadNormalize normalize)
+{
+ g_return_if_fail (c != NULL);
+
+ memset (c, 0, sizeof (*c));
+ c->type = type;
+ c->normalize = normalize;
+ gsl_biquad_config_setup (c, 0.5, 3, 1);
+ c->approx_values = TRUE; /* need _setup() */
+}
+
+void
+gsl_biquad_config_setup (GslBiquadConfig *c,
+ gfloat f_fn,
+ gfloat gain,
+ gfloat quality)
+{
+ g_return_if_fail (c != NULL);
+ g_return_if_fail (f_fn >= 0 && f_fn <= 1);
+
+ if (c->type == GSL_BIQUAD_RESONANT_HIGHPASS)
+ f_fn = 1.0 - f_fn;
+ c->f_fn = f_fn; /* nyquist relative (0=DC, 1=nyquist) */
+ c->gain = gain;
+ c->quality = quality; /* FIXME */
+ c->k = tan (c->f_fn * GSL_PI / 2.);
+ c->v = pow (10, c->gain / 20.); /* v=10^(gain[dB]/20) */
+ c->dirty = TRUE;
+ c->approx_values = FALSE;
+}
+
+void
+gsl_biquad_config_approx_freq (GslBiquadConfig *c,
+ gfloat f_fn)
+{
+ g_return_if_fail (f_fn >= 0 && f_fn <= 1);
+
+ if (c->type == GSL_BIQUAD_RESONANT_HIGHPASS)
+ f_fn = 1.0 - f_fn;
+ c->f_fn = f_fn; /* nyquist relative (0=DC, 1=nyquist) */
+ c->k = tan (c->f_fn * GSL_PI / 2.); /* FIXME */
+ c->dirty = TRUE;
+ c->approx_values = TRUE;
+}
+
+void
+gsl_biquad_config_approx_gain (GslBiquadConfig *c,
+ gfloat gain)
+{
+ c->gain = gain;
+ c->v = gsl_approx_exp2 (c->gain * GSL_LOG2POW20_10);
+ c->dirty = TRUE;
+ c->approx_values = TRUE;
+}
+
+static void
+biquad_lpreso (GslBiquadConfig *c,
+ GslBiquadFilter *f)
+{
+ gdouble kk, sqrt2_reso, denominator;
+ gdouble r2p_norm = 0; /* resonance gain to peak gain (pole: -sqrt2_reso+-j) */
+
+ kk = c->k * c->k;
+ sqrt2_reso = 1 / c->v;
+ denominator = 1 + (c->k + sqrt2_reso) * c->k;
+
+ switch (c->normalize)
+ {
+ case GSL_BIQUAD_NORMALIZE_PASSBAND:
+ r2p_norm = kk;
+ break;
+ case GSL_BIQUAD_NORMALIZE_RESONANCE_GAIN:
+ r2p_norm = kk * sqrt2_reso;
+ break;
+ case GSL_BIQUAD_NORMALIZE_PEAK_GAIN:
+ r2p_norm = (GSL_SQRT2 * sqrt2_reso - 1.0) / (sqrt2_reso * sqrt2_reso - 0.5);
+ r2p_norm = r2p_norm > 1 ? kk * sqrt2_reso : kk * r2p_norm * sqrt2_reso;
+ break;
+ }
+ f->xc0 = r2p_norm / denominator;
+ f->xc1 = 2 * f->xc0;
+ f->xc2 = f->xc0;
+ f->yc1 = 2 * (kk - 1) / denominator;
+ f->yc2 = (1 + (c->k - sqrt2_reso) * c->k) / denominator;
+}
+
+void
+gsl_biquad_filter_config (GslBiquadFilter *f,
+ GslBiquadConfig *c,
+ gboolean reset_state)
+{
+ g_return_if_fail (f != NULL);
+ g_return_if_fail (c != NULL);
+
+ if (c->dirty)
+ {
+ switch (c->type)
+ {
+ case GSL_BIQUAD_RESONANT_LOWPASS:
+ biquad_lpreso (c, f);
+ break;
+ case GSL_BIQUAD_RESONANT_HIGHPASS:
+ biquad_lpreso (c, f);
+ f->xc1 = -f->xc1;
+ f->yc1 = -f->yc1;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ c->dirty = FALSE;
+ }
+
+ if (reset_state)
+ f->xd1 = f->xd2 = f->yd1 = f->yd2 = 0;
+}
+
+void
+gsl_biquad_filter_eval (GslBiquadFilter *f,
+ guint n_values,
+ const gfloat *x,
+ gfloat *y)
+{
+ const gfloat *bound;
+ gdouble xc0, xc1, xc2, yc1, yc2, xd1, xd2, yd1, yd2;
+
+ g_return_if_fail (f != NULL && x != NULL && y != NULL);
+
+ xc0 = f->xc0;
+ xc1 = f->xc1;
+ xc2 = f->xc2;
+ yc1 = f->yc1;
+ yc2 = f->yc2;
+ xd1 = f->xd1;
+ xd2 = f->xd2;
+ yd1 = f->yd1;
+ yd2 = f->yd2;
+ bound = x + n_values;
+ while (x < bound)
+ {
+ gdouble k0, k1, k2;
+
+ k2 = xd2 * xc2;
+ k1 = xd1 * xc1;
+ xd2 = xd1;
+ xd1 = *x++;
+ k2 -= yd2 * yc2;
+ k1 -= yd1 * yc1;
+ yd2 = yd1;
+ k0 = xd1 * xc0;
+ yd1 = k2 + k1;
+ *y++ = yd1 += k0;
+ }
+ f->xd1 = xd1;
+ f->xd2 = xd2;
+ f->yd1 = yd1;
+ f->yd2 = yd2;
+}
+
+#if 0
+void
+gsl_biquad_lphp_reso (GslBiquadFilter *c,
+ gfloat f_fn, /* nyquist relative (0=DC, 1=nyquist) */
+ float gain,
+ gboolean design_highpass,
+ GslBiquadNormalize normalize)
+{
+ double k, kk, v;
+ double sqrt2_reso;
+ double denominator;
+ double r2p_norm = 0; /* resonance gain to peak gain (pole: -sqrt2_reso+-j) */
+
+ g_return_if_fail (c != NULL);
+ g_return_if_fail (f_fn >= 0 && f_fn <= 1);
+
+ if (design_highpass)
+ f_fn = 1.0 - f_fn;
+
+ v = pow (10, gain / 20.); /* v=10^(gain[dB]/20) */
+ k = tan (f_fn * GSL_PI / 2.);
+ kk = k * k;
+ sqrt2_reso = 1 / v;
+ denominator = 1 + (k + sqrt2_reso) * k;
+
+ if (0)
+ g_printerr ("BIQUAD-lp: R=%f\n", GSL_SQRT2 * sqrt2_reso);
+
+ switch (normalize)
+ {
+ case GSL_BIQUAD_NORMALIZE_PASSBAND:
+ r2p_norm = kk;
+ break;
+ case GSL_BIQUAD_NORMALIZE_RESONANCE_GAIN:
+ r2p_norm = kk * sqrt2_reso;
+ break;
+ case GSL_BIQUAD_NORMALIZE_PEAK_GAIN:
+ r2p_norm = (GSL_SQRT2 * sqrt2_reso - 1.0) / (sqrt2_reso * sqrt2_reso - 0.5);
+ g_print ("BIQUAD-lp: (peak-gain) r2p_norm = %f \n", r2p_norm);
+ r2p_norm = r2p_norm > 1 ? kk * sqrt2_reso : kk * r2p_norm * sqrt2_reso;
+ break;
+ }
+ c->xc0 = r2p_norm / denominator;
+ c->xc1 = 2 * c->xc0;
+ c->xc2 = c->xc0;
+ c->yc1 = 2 * (kk - 1) / denominator;
+ c->yc2 = (1 + (k - sqrt2_reso) * k) / denominator;
+
+ if (design_highpass)
+ {
+ c->xc1 = -c->xc1;
+ c->yc1 = -c->yc1;
+ }
+ /* normalization notes:
+ * pole: -sqrt2_reso+-j
+ * freq=0.5: reso->peak gain=8adjust:0.9799887, 9adjust:0.98415
+ * resonance gain = 1/(1-R)=sqrt2_reso
+ * sqrt2_reso*(1-R)=1
+ * 1-R=1/sqrt2_reso
+ * R= 1-1/sqrt2_reso
+ * peak gain = 2/(1-R^2)
+ * = 2 * (1 - (1 - 1 / sqrt2_reso) * (1 - 1 / sqrt2_reso))
+ * = 2 - 2 * (1 - 1 / sqrt2_reso)^2
+ */
+}
+#endif
+
+
+/* --- filter scanning -- */
+#define SINE_SCAN_SIZE 1024
+
+/**
+ * gsl_filter_sine_scan
+ *
+ * @order: order of the iir filter
+ * @a: root polynomial coefficients of the filter a[0..order]
+ * @b: pole polynomial coefficients of the filter b[0..order]
+ * @freq: frequency to test
+ * @n_values: number of samples
+ *
+ * This function sends a sine signal of the desired frequency through an IIR
+ * filter, to test the value of the transfer function at a given point. It uses
+ * gsl_iir_filter_eval to do so.
+ *
+ * Compared to a "mathematical approach" of finding the transfer function,
+ * this function makes it possible to see the effects of finite arithmetic
+ * during filter evaluation.
+ *
+ * The first half of the output signal is not considered, since a lot of IIR
+ * filters have a transient phase where also overshoot is possible.
+ *
+ * For n_values, you should specify a reasonable large value. It should be
+ * a lot larger than the filter order, and large enough to let the input
+ * signal become (close to) 1.0 multiple times.
+ */
+gdouble
+gsl_filter_sine_scan (guint order,
+ const gdouble *a,
+ const gdouble *b,
+ gdouble freq,
+ guint n_values)
+{
+ gfloat x[SINE_SCAN_SIZE], y[SINE_SCAN_SIZE];
+ gdouble pos = 0.0;
+ gdouble result = 0.0;
+ GslIIRFilter filter;
+ gdouble *filter_state;
+ guint scan_start = n_values / 2;
+
+ g_return_val_if_fail (order > 0, 0.0);
+ g_return_val_if_fail (a != NULL, 0.0);
+ g_return_val_if_fail (b != NULL, 0.0);
+ g_return_val_if_fail (freq > 0 && freq < GSL_PI, 0.0);
+ g_return_val_if_fail (n_values > 0, 0.0);
+
+ filter_state = g_newa (double, (order + 1) * 4);
+ gsl_iir_filter_setup (&filter, order, a, b, filter_state);
+
+ while (n_values)
+ {
+ guint todo = MIN (n_values, SINE_SCAN_SIZE);
+ guint i;
+
+ for (i = 0; i < todo; i++)
+ {
+ x[i] = sin (pos);
+ pos += freq;
+ }
+
+ gsl_iir_filter_eval (&filter, SINE_SCAN_SIZE, x, y);
+
+ for (i = 0; i < todo; i++)
+ if (n_values - i < scan_start)
+ result = MAX (y[i], result);
+
+ n_values -= todo;
+ }
+ return result;
+}
+
+
+
+
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gslfilter.h b/flow/gsl/gslfilter.h
new file mode 100644
index 0000000..3baa7e8
--- /dev/null
+++ b/flow/gsl/gslfilter.h
@@ -0,0 +1,281 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_FILTER_H__
+#define __GSL_FILTER_H__
+
+#include <gsl/gslmath.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- transformations --- */
+static inline GslComplex gsl_trans_s2z (GslComplex s);
+static inline double gsl_trans_freq2s (double w);
+static inline double gsl_trans_zepsilon2ss (double epsilon);
+
+
+/* --- filter roots and poles --- */
+void gsl_filter_butter_rp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles);
+void gsl_filter_tscheb1_rp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles);
+void gsl_filter_tscheb2_rp (unsigned int iorder,
+ double c_freq, /* 0..pi */
+ double steepness,
+ double epsilon,
+ GslComplex *roots, /* [0..iorder-1] */
+ GslComplex *poles);
+
+
+/* --- tschebyscheff type II steepness --- */
+double gsl_filter_tscheb2_steepness_db (unsigned int iorder,
+ double c_freq,
+ double epsilon,
+ double stopband_db);
+double gsl_filter_tscheb2_steepness (unsigned int iorder,
+ double c_freq,
+ double epsilon,
+ double residue);
+
+
+/* --- lowpass filters --- */
+void gsl_filter_butter_lp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb1_lp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb2_lp (unsigned int iorder,
+ double c_freq, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+
+
+/* --- highpass filters --- */
+void gsl_filter_butter_hp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb1_hp (unsigned int iorder,
+ double freq, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb2_hp (unsigned int iorder,
+ double c_freq, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+
+
+/* --- bandpass filters --- */
+void gsl_filter_butter_bp (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb1_bp (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb2_bp (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+
+
+/* --- bandstop filters --- */
+void gsl_filter_butter_bs (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb1_bs (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+void gsl_filter_tscheb2_bs (unsigned int iorder,
+ double freq1, /* 0..pi */
+ double freq2, /* 0..pi */
+ double steepness,
+ double epsilon,
+ double *a, /* [0..iorder] */
+ double *b);
+
+
+/* --- FIR Filters --- */
+void gsl_filter_fir_approx (unsigned int iorder,
+ double *a, /* [0..iorder] */
+ unsigned int n_points,
+ const double *freq,
+ const double *value);
+
+
+/* --- IIR Filter Evaluation --- */
+typedef struct {
+ guint order;
+ gdouble *a; /* [0..order] */
+ gdouble *b; /* [0..order] */
+ gdouble *w; /* [0..2*order] */
+} GslIIRFilter;
+void gsl_iir_filter_setup (GslIIRFilter *f,
+ guint order,
+ const gdouble *a,
+ const gdouble *b,
+ gdouble *buffer); /* 4*(order+1) */
+void gsl_iir_filter_change (GslIIRFilter *f,
+ guint order,
+ const gdouble *a,
+ const gdouble *b,
+ gdouble *buffer); /* 4*(order+1) */
+void gsl_iir_filter_eval (GslIIRFilter *f,
+ guint n_values,
+ const gfloat *x,
+ gfloat *y);
+
+
+/* --- Biquad Filters --- */
+typedef enum /*< skip >*/
+{
+ GSL_BIQUAD_NORMALIZE_PASSBAND,
+ GSL_BIQUAD_NORMALIZE_RESONANCE_GAIN,
+ GSL_BIQUAD_NORMALIZE_PEAK_GAIN
+} GslBiquadNormalize;
+
+typedef enum /*< skip >*/
+{
+ GSL_BIQUAD_RESONANT_LOWPASS = 1,
+ GSL_BIQUAD_RESONANT_HIGHPASS,
+ GSL_BIQUAD_LOWSHELVE,
+ GSL_BIQUAD_HIGHSHELVE,
+ GSL_BIQUAD_PEAK
+} GslBiquadType;
+
+typedef struct {
+ GslBiquadType type;
+ GslBiquadNormalize normalize; /* high/low pass */
+ gfloat f_fn;
+ gfloat gain;
+ gfloat quality; /* peak/notch */
+ guint dirty : 1; /* post filter_config() changes? */
+ guint approx_values : 1; /* biquad_config_approx_*() called? */
+ /*< private >*/
+ gdouble k, v;
+} GslBiquadConfig;
+
+typedef struct {
+ gdouble xc0, xc1, xc2;
+ gdouble yc1, yc2; /* yc0==1 */
+ gdouble xd1, xd2, yd1, yd2; /* history */
+} GslBiquadFilter;
+
+void gsl_biquad_config_init (GslBiquadConfig *c,
+ GslBiquadType type,
+ GslBiquadNormalize normalize);
+void gsl_biquad_config_setup (GslBiquadConfig *c,
+ gfloat f_fn,
+ gfloat gain,
+ gfloat quality);
+void gsl_biquad_config_approx_freq (GslBiquadConfig *c,
+ gfloat f_fn);
+void gsl_biquad_config_approx_gain (GslBiquadConfig *c,
+ gfloat gain);
+void gsl_biquad_filter_config (GslBiquadFilter *f,
+ GslBiquadConfig *c,
+ gboolean reset_state);
+void gsl_biquad_filter_eval (GslBiquadFilter *f,
+ guint n_values,
+ const gfloat *x,
+ gfloat *y);
+
+
+/* --- filter scanning -- */
+gdouble gsl_filter_sine_scan (guint order,
+ const gdouble *a,
+ const gdouble *b,
+ gdouble freq,
+ guint n_values);
+
+
+/* --- implementations --- */
+static inline GslComplex
+gsl_trans_s2z (GslComplex s)
+{
+ /* 1 + (Td/2) * s
+ * z = ----------------
+ * 1 - (Td/2) * s
+ */
+ GslComplex one = { 1, 0 };
+ return gsl_complex_div (gsl_complex_add (one, s), gsl_complex_sub (one, s));
+ /* return gsl_complex_div (gsl_complex_sub (s, one), gsl_complex_add (s, one)); */
+}
+static inline double
+gsl_trans_freq2s (double w)
+{
+ return tan (w / 2.);
+}
+static inline double
+gsl_trans_zepsilon2ss (double zepsilon)
+{
+ double e2 = (1.0 - zepsilon) * (1.0 - zepsilon);
+ /* 1___ _________________
+ * | \ | 1.0
+ * |-----\<---- 1 - zepsilon zepsilon = \ | ----------------
+ * |_______\________________ \| 1 + sepsilon^2
+ */
+ return sqrt ((1.0 - e2) / e2);
+}
+static inline double
+gsl_trans_freq2z (double w)
+{
+ return atan (w) * 2.;
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_FILTER_H__ */ /* vim:set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslglib.c b/flow/gsl/gslglib.c
new file mode 100644
index 0000000..f913df2
--- /dev/null
+++ b/flow/gsl/gslglib.c
@@ -0,0 +1,2400 @@
+#include "gsl/gslglib.h"
+#include "gsl/gsldefs.h"
+
+#include <locale.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define GLIB_SIZEOF_INTMAX (GSL_SIZEOF_STD_INTMAX_T ? GSL_SIZEOF_STD_INTMAX_T : 8 /* educated guess */)
+
+gpointer g_malloc (gulong n_bytes) { void*p = malloc(n_bytes); GSL_ASSERT(p!=0); return p; }
+gpointer g_malloc0 (gulong n_bytes) { return memset(g_malloc(n_bytes),0,n_bytes); }
+gpointer g_realloc (gpointer mem,
+ gulong n_bytes) { void*p = realloc(mem,n_bytes); GSL_ASSERT(p!=0); return p; }
+void g_free (gpointer mem) { if (mem) free(mem); }
+void g_usleep (unsigned long usec) { usleep (usec); }
+char* g_strerror(int e) { return strerror (e); }
+
+
+gpointer g_memdup (gconstpointer mem, guint byte_size) { gpointer new_mem; if (mem) { new_mem = g_malloc (byte_size); memcpy (new_mem, mem, byte_size); } else new_mem = NULL; return new_mem; }
+gchar* g_strdup (const gchar *str) { gchar *new_str; if (str) { new_str = g_new (char, strlen (str) + 1); strcpy (new_str, str); } else new_str = NULL; return new_str; }
+gchar* g_strndup (const gchar *str, gsize n) { gchar *new_str; if (str) { new_str = g_new (gchar, n + 1); strncpy (new_str, str, n); new_str[n] = '\0'; } else new_str = NULL; return new_str; }
+gchar*g_strconcat (const gchar *string1, ...){ gsize l; va_list args; gchar *s; gchar *concat; gchar *ptr; g_return_val_if_fail (string1 != NULL, NULL); l = 1 + strlen (string1); va_start (args, string1); s = va_arg (args, gchar*); while (s) { l += strlen (s); s = va_arg (args, gchar*); } va_end (args); concat = g_new (gchar, l); ptr = concat; ptr = g_stpcpy (ptr, string1); va_start (args, string1); s = va_arg (args, gchar*); while (s) { ptr = g_stpcpy (ptr, s); s = va_arg (args, gchar*); } va_end (args); return concat; }
+
+gchar*
+g_strdup_printf (const gchar *format,
+ ...)
+{
+ gchar *buffer;
+ va_list args;
+
+ va_start (args, format);
+ buffer = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ return buffer;
+}
+
+
+gchar*
+g_strdup_vprintf (const gchar *format,
+ va_list args1)
+{
+ gchar *buffer;
+#ifdef HAVE_VASPRINTF
+ if (vasprintf (&buffer, format, args1) < 0)
+ buffer = NULL;
+#else
+ va_list args2;
+
+ G_VA_COPY (args2, args1);
+
+ buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
+
+ vsprintf (buffer, format, args2);
+ va_end (args2);
+#endif
+ return buffer;
+}
+gchar *
+g_stpcpy (gchar *dest,
+ const gchar *src)
+{
+#ifdef GLIB_HAVE_STPCPY
+ g_return_val_if_fail (dest != NULL, NULL);
+ g_return_val_if_fail (src != NULL, NULL);
+ return stpcpy (dest, src);
+#else
+ register gchar *d = dest;
+ register const gchar *s = src;
+
+ g_return_val_if_fail (dest != NULL, NULL);
+ g_return_val_if_fail (src != NULL, NULL);
+ do
+ *d++ = *s;
+ while (*s++ != '\0');
+
+ return d - 1;
+#endif
+}
+
+gchar *
+g_strescape (const gchar *source,
+ const gchar *exceptions)
+{
+ const guchar *p;
+ gchar *dest;
+ gchar *q;
+ guchar excmap[256];
+
+ g_return_val_if_fail (source != NULL, NULL);
+
+ p = (guchar *) source;
+ /* Each source byte needs maximally four destination chars (\777) */
+ q = dest = g_malloc (strlen (source) * 4 + 1);
+
+ memset (excmap, 0, 256);
+ if (exceptions)
+ {
+ guchar *e = (guchar *) exceptions;
+
+ while (*e)
+ {
+ excmap[*e] = 1;
+ e++;
+ }
+ }
+
+ while (*p)
+ {
+ if (excmap[*p])
+ *q++ = *p;
+ else
+ {
+ switch (*p)
+ {
+ case '\b':
+ *q++ = '\\';
+ *q++ = 'b';
+ break;
+ case '\f':
+ *q++ = '\\';
+ *q++ = 'f';
+ break;
+ case '\n':
+ *q++ = '\\';
+ *q++ = 'n';
+ break;
+ case '\r':
+ *q++ = '\\';
+ *q++ = 'r';
+ break;
+ case '\t':
+ *q++ = '\\';
+ *q++ = 't';
+ break;
+ case '\\':
+ *q++ = '\\';
+ *q++ = '\\';
+ break;
+ case '"':
+ *q++ = '\\';
+ *q++ = '"';
+ break;
+ default:
+ if ((*p < ' ') || (*p >= 0177))
+ {
+ *q++ = '\\';
+ *q++ = '0' + (((*p) >> 6) & 07);
+ *q++ = '0' + (((*p) >> 3) & 07);
+ *q++ = '0' + ((*p) & 07);
+ }
+ else
+ *q++ = *p;
+ break;
+ }
+ }
+ p++;
+ }
+ *q = 0;
+ return dest;
+}
+
+
+
+
+guint g_direct_hash (gconstpointer v) { return GPOINTER_TO_UINT (v); }
+gboolean g_direct_equal (gconstpointer v1, gconstpointer v2) { return v1 == v2; }
+gboolean g_str_equal (gconstpointer v1, gconstpointer v2) { const gchar *string1 = v1; const gchar *string2 = v2; return strcmp (string1, string2) == 0; }
+guint g_str_hash (gconstpointer key) { const char *p = key; guint h = *p; if (h) for (p += 1; *p != '\0'; p++) h = (h << 5) - h + *p; return h; }
+
+
+void
+gsl_g_log (const gchar*msg,const char *format, va_list ap)
+{
+ if (msg) printf ("\n%s",msg);
+ vprintf(format, ap);
+ if (msg) printf ("\n");
+}
+
+void
+gsl_g_print_fd (int fd, const char *format, va_list ap)
+{
+ g_return_if_fail (fd == 1 || fd == 2);
+ if (fd == 1)
+ vprintf (format, ap);
+ else
+ vfprintf (stderr, format, ap);
+}
+
+gchar*
+gsl_g_convert (const gchar *str,
+ gsize len, /* gssize */
+ const gchar *to_codeset,
+ const gchar *from_codeset,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ void **error) /* GError */
+{
+ g_error ("g_convert not implemented");
+
+ /* not reached: */
+ return 0;
+}
+
+
+/* --- GScanner --- */
+
+#ifdef HAVE_SNPRINTF
+/* FIXME: might want to do the configure test in gsl instead of arts */
+#define g_snprintf snprintf
+#else
+#define g_snprintf gsl_g_snprintf
+static void
+gsl_g_snprintf (gchar *out_buffer,
+ size_t size,
+ const gchar *format,
+ ...)
+{
+ gchar *buffer;
+ va_list args;
+
+ /* print string into large enough buffer */
+ va_start (args, format);
+ buffer = g_strdup_printf (format, args);
+ va_end (args);
+
+ /* copy the first size bytes into out_buffer */
+ strncpy (out_buffer, buffer, size);
+ out_buffer[ size - 1 ] = '\0';
+ g_free (buffer);
+}
+#endif
+
+
+struct _GString
+{
+ gchar *str;
+ guint len;
+};
+
+static GString*
+g_string_new(const gchar* s)
+{
+ GString *gstr=g_new0(GString,1);
+ gstr->str= g_strdup(s);
+ gstr->len=strlen(s);
+ return gstr;
+}
+static GString*
+g_string_append_c(GString*gstr, int ch)
+{
+ gstr->str=g_renew(gchar,gstr->str,++gstr->len + 1);
+ gstr->str[gstr->len-1]=ch;
+ gstr->str[gstr->len]=0;
+ return gstr;
+}
+static void
+g_string_free(GString*gstr, int freeme)
+{
+ if(freeme)g_free(gstr->str);g_free(gstr);
+}
+
+
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GScanner: Flexible lexical scanner for general purpose.
+ * Copyright (C) 1997, 1998 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+/*
+ * MT safe
+ */
+
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* --- defines --- */
+#define to_lower(c) ( \
+ (guchar) ( \
+ ( (((guchar)(c))>='A' && ((guchar)(c))<='Z') * ('a'-'A') ) | \
+ ( (((guchar)(c))>=192 && ((guchar)(c))<=214) * (224-192) ) | \
+ ( (((guchar)(c))>=216 && ((guchar)(c))<=222) * (248-216) ) | \
+ ((guchar)(c)) \
+ ) \
+)
+#define READ_BUFFER_SIZE (4000)
+
+
+/* --- typedefs --- */
+typedef struct _GScannerKey GScannerKey;
+
+struct _GScannerKey
+{
+ guint scope_id;
+ gchar *symbol;
+ gpointer value;
+};
+
+
+
+/* --- variables --- */
+#define g_scanner_config_template _cplusplus_wont_have_a_problem_with_this_foog_scanner_config_template
+static GScannerConfig g_scanner_config_template =
+{
+ (
+ " \t\r\n"
+ ) /* cset_skip_characters */,
+ (
+ G_CSET_a_2_z
+ "_"
+ G_CSET_A_2_Z
+ ) /* cset_identifier_first */,
+ (
+ G_CSET_a_2_z
+ "_"
+ G_CSET_A_2_Z
+ G_CSET_DIGITS
+ G_CSET_LATINS
+ G_CSET_LATINC
+ ) /* cset_identifier_nth */,
+ ( "#\n" ) /* cpair_comment_single */,
+
+ FALSE /* case_sensitive */,
+
+ TRUE /* skip_comment_multi */,
+ TRUE /* skip_comment_single */,
+ TRUE /* scan_comment_multi */,
+ TRUE /* scan_identifier */,
+ FALSE /* scan_identifier_1char */,
+ FALSE /* scan_identifier_NULL */,
+ TRUE /* scan_symbols */,
+ FALSE /* scan_binary */,
+ TRUE /* scan_octal */,
+ TRUE /* scan_float */,
+ TRUE /* scan_hex */,
+ FALSE /* scan_hex_dollar */,
+ TRUE /* scan_string_sq */,
+ TRUE /* scan_string_dq */,
+ TRUE /* numbers_2_int */,
+ FALSE /* int_2_float */,
+ FALSE /* identifier_2_string */,
+ TRUE /* char_2_token */,
+ FALSE /* symbol_2_token */,
+ FALSE /* scope_0_fallback */,
+};
+
+
+/* --- prototypes --- */
+static inline
+GScannerKey* g_scanner_lookup_internal (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol);
+static gboolean g_scanner_key_equal (gconstpointer v1,
+ gconstpointer v2);
+static guint g_scanner_key_hash (gconstpointer v);
+static void g_scanner_get_token_ll (GScanner *scanner,
+ GTokenType *token_p,
+ GTokenValue *value_p,
+ guint *line_p,
+ guint *position_p);
+static void g_scanner_get_token_i (GScanner *scanner,
+ GTokenType *token_p,
+ GTokenValue *value_p,
+ guint *line_p,
+ guint *position_p);
+
+static guchar g_scanner_peek_next_char (GScanner *scanner);
+static guchar g_scanner_get_char (GScanner *scanner,
+ guint *line_p,
+ guint *position_p);
+static void g_scanner_msg_handler (GScanner *scanner,
+ gchar *message,
+ gint is_error);
+
+
+/* --- functions --- */
+static inline gint
+g_scanner_char_2_num (guchar c,
+ guchar base)
+{
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ return -1;
+
+ if (c < base)
+ return c;
+
+ return -1;
+}
+
+GScanner*
+g_scanner_new (const GScannerConfig *config_templ)
+{
+ GScanner *scanner;
+
+ if (!config_templ)
+ config_templ = &g_scanner_config_template;
+
+ scanner = g_new0 (GScanner, 1);
+
+ scanner->user_data = NULL;
+ scanner->max_parse_errors = 0;
+ scanner->parse_errors = 0;
+ scanner->input_name = NULL;
+ /* g_datalist_init (&scanner->qdata); */
+
+ scanner->config = g_new0 (GScannerConfig, 1);
+
+ scanner->config->case_sensitive = config_templ->case_sensitive;
+ scanner->config->cset_skip_characters = config_templ->cset_skip_characters;
+ if (!scanner->config->cset_skip_characters)
+ scanner->config->cset_skip_characters = "";
+ scanner->config->cset_identifier_first = config_templ->cset_identifier_first;
+ scanner->config->cset_identifier_nth = config_templ->cset_identifier_nth;
+ scanner->config->cpair_comment_single = config_templ->cpair_comment_single;
+ scanner->config->skip_comment_multi = config_templ->skip_comment_multi;
+ scanner->config->skip_comment_single = config_templ->skip_comment_single;
+ scanner->config->scan_comment_multi = config_templ->scan_comment_multi;
+ scanner->config->scan_identifier = config_templ->scan_identifier;
+ scanner->config->scan_identifier_1char = config_templ->scan_identifier_1char;
+ scanner->config->scan_identifier_NULL = config_templ->scan_identifier_NULL;
+ scanner->config->scan_symbols = config_templ->scan_symbols;
+ scanner->config->scan_binary = config_templ->scan_binary;
+ scanner->config->scan_octal = config_templ->scan_octal;
+ scanner->config->scan_float = config_templ->scan_float;
+ scanner->config->scan_hex = config_templ->scan_hex;
+ scanner->config->scan_hex_dollar = config_templ->scan_hex_dollar;
+ scanner->config->scan_string_sq = config_templ->scan_string_sq;
+ scanner->config->scan_string_dq = config_templ->scan_string_dq;
+ scanner->config->numbers_2_int = config_templ->numbers_2_int;
+ scanner->config->int_2_float = config_templ->int_2_float;
+ scanner->config->identifier_2_string = config_templ->identifier_2_string;
+ scanner->config->char_2_token = config_templ->char_2_token;
+ scanner->config->symbol_2_token = config_templ->symbol_2_token;
+ scanner->config->scope_0_fallback = config_templ->scope_0_fallback;
+
+ scanner->token = G_TOKEN_NONE;
+ scanner->value.v_int = 0;
+ scanner->line = 1;
+ scanner->position = 0;
+
+ scanner->next_token = G_TOKEN_NONE;
+ scanner->next_value.v_int = 0;
+ scanner->next_line = 1;
+ scanner->next_position = 0;
+
+ scanner->symbol_table = g_hash_table_new (g_scanner_key_hash, g_scanner_key_equal);
+ scanner->input_fd = -1;
+ scanner->text = NULL;
+ scanner->text_end = NULL;
+ scanner->buffer = NULL;
+ scanner->scope_id = 0;
+
+ scanner->msg_handler = g_scanner_msg_handler;
+
+ return scanner;
+}
+
+static inline void
+g_scanner_free_value (GTokenType *token_p,
+ GTokenValue *value_p)
+{
+ switch (*token_p)
+ {
+ case G_TOKEN_STRING:
+ case G_TOKEN_IDENTIFIER:
+ case G_TOKEN_IDENTIFIER_NULL:
+ case G_TOKEN_COMMENT_SINGLE:
+ case G_TOKEN_COMMENT_MULTI:
+ g_free (value_p->v_string);
+ break;
+
+ default:
+ break;
+ }
+
+ *token_p = G_TOKEN_NONE;
+}
+
+static void
+g_scanner_destroy_symbol_table_entry (gpointer _key,
+ gpointer _value,
+ gpointer _data)
+{
+ GScannerKey *key = _key;
+
+ g_free (key->symbol);
+ g_free (key);
+}
+
+void
+g_scanner_destroy (GScanner *scanner)
+{
+ g_return_if_fail (scanner != NULL);
+
+ /* g_datalist_clear (&scanner->qdata); */
+ g_hash_table_foreach (scanner->symbol_table,
+ g_scanner_destroy_symbol_table_entry, NULL);
+ g_hash_table_destroy (scanner->symbol_table);
+ g_scanner_free_value (&scanner->token, &scanner->value);
+ g_scanner_free_value (&scanner->next_token, &scanner->next_value);
+ g_free (scanner->config);
+ g_free (scanner->buffer);
+ g_free (scanner);
+}
+
+static void
+g_scanner_msg_handler (GScanner *scanner,
+ gchar *message,
+ gint is_error)
+{
+ g_return_if_fail (scanner != NULL);
+
+ fprintf (stderr, "%s:%d: ", scanner->input_name, scanner->line);
+ if (is_error)
+ fprintf (stderr, "error: ");
+ fprintf (stderr, "%s\n", message);
+}
+
+void
+g_scanner_error (GScanner *scanner,
+ const gchar *format,
+ ...)
+{
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (format != NULL);
+
+ scanner->parse_errors++;
+
+ if (scanner->msg_handler)
+ {
+ va_list args;
+ gchar *string;
+
+ va_start (args, format);
+ string = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ scanner->msg_handler (scanner, string, TRUE);
+
+ g_free (string);
+ }
+}
+
+void
+g_scanner_warn (GScanner *scanner,
+ const gchar *format,
+ ...)
+{
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (format != NULL);
+
+ if (scanner->msg_handler)
+ {
+ va_list args;
+ gchar *string;
+
+ va_start (args, format);
+ string = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ scanner->msg_handler (scanner, string, FALSE);
+
+ g_free (string);
+ }
+}
+
+static gboolean
+g_scanner_key_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const GScannerKey *key1 = v1;
+ const GScannerKey *key2 = v2;
+
+ return (key1->scope_id == key2->scope_id) && (strcmp (key1->symbol, key2->symbol) == 0);
+}
+
+static guint
+g_scanner_key_hash (gconstpointer v)
+{
+ const GScannerKey *key = v;
+ gchar *c;
+ guint h;
+
+ h = key->scope_id;
+ for (c = key->symbol; *c; c++)
+ h = (h << 5) - h + *c;
+
+ return h;
+}
+
+static inline GScannerKey*
+g_scanner_lookup_internal (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol)
+{
+ GScannerKey *key_p;
+ GScannerKey key;
+
+ key.scope_id = scope_id;
+
+ if (!scanner->config->case_sensitive)
+ {
+ gchar *d;
+ const gchar *c;
+
+ key.symbol = g_new (gchar, strlen (symbol) + 1);
+ for (d = key.symbol, c = symbol; *c; c++, d++)
+ *d = to_lower (*c);
+ *d = 0;
+ key_p = g_hash_table_lookup (scanner->symbol_table, &key);
+ g_free (key.symbol);
+ }
+ else
+ {
+ key.symbol = (gchar*) symbol;
+ key_p = g_hash_table_lookup (scanner->symbol_table, &key);
+ }
+
+ return key_p;
+}
+
+void
+g_scanner_scope_add_symbol (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol,
+ gpointer value)
+{
+ GScannerKey *key;
+
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (symbol != NULL);
+
+ key = g_scanner_lookup_internal (scanner, scope_id, symbol);
+
+ if (!key)
+ {
+ key = g_new (GScannerKey, 1);
+ key->scope_id = scope_id;
+ key->symbol = g_strdup (symbol);
+ key->value = value;
+ if (!scanner->config->case_sensitive)
+ {
+ gchar *c;
+
+ c = key->symbol;
+ while (*c != 0)
+ {
+ *c = to_lower (*c);
+ c++;
+ }
+ }
+ g_hash_table_insert (scanner->symbol_table, key, key);
+ }
+ else
+ key->value = value;
+}
+
+void
+g_scanner_scope_remove_symbol (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol)
+{
+ GScannerKey *key;
+
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (symbol != NULL);
+
+ key = g_scanner_lookup_internal (scanner, scope_id, symbol);
+
+ if (key)
+ {
+ g_hash_table_remove (scanner->symbol_table, key);
+ g_free (key->symbol);
+ g_free (key);
+ }
+}
+
+gpointer
+g_scanner_lookup_symbol (GScanner *scanner,
+ const gchar *symbol)
+{
+ GScannerKey *key;
+ guint scope_id;
+
+ g_return_val_if_fail (scanner != NULL, NULL);
+
+ if (!symbol)
+ return NULL;
+
+ scope_id = scanner->scope_id;
+ key = g_scanner_lookup_internal (scanner, scope_id, symbol);
+ if (!key && scope_id && scanner->config->scope_0_fallback)
+ key = g_scanner_lookup_internal (scanner, 0, symbol);
+
+ if (key)
+ return key->value;
+ else
+ return NULL;
+}
+
+gpointer
+g_scanner_scope_lookup_symbol (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol)
+{
+ GScannerKey *key;
+
+ g_return_val_if_fail (scanner != NULL, NULL);
+
+ if (!symbol)
+ return NULL;
+
+ key = g_scanner_lookup_internal (scanner, scope_id, symbol);
+
+ if (key)
+ return key->value;
+ else
+ return NULL;
+}
+
+guint
+g_scanner_set_scope (GScanner *scanner,
+ guint scope_id)
+{
+ guint old_scope_id;
+
+ g_return_val_if_fail (scanner != NULL, 0);
+
+ old_scope_id = scanner->scope_id;
+ scanner->scope_id = scope_id;
+
+ return old_scope_id;
+}
+
+static void
+g_scanner_foreach_internal (gpointer _key,
+ gpointer _value,
+ gpointer _user_data)
+{
+ GScannerKey *key;
+ gpointer *d;
+ GHFunc func;
+ gpointer user_data;
+ guint *scope_id;
+
+ d = _user_data;
+ func = (GHFunc) d[0];
+ user_data = d[1];
+ scope_id = d[2];
+ key = _value;
+
+ if (key->scope_id == *scope_id)
+ func (key->symbol, key->value, user_data);
+}
+
+void
+g_scanner_scope_foreach_symbol (GScanner *scanner,
+ guint scope_id,
+ GHFunc func,
+ gpointer user_data)
+{
+ gpointer d[3];
+
+ g_return_if_fail (scanner != NULL);
+
+ d[0] = (gpointer) func;
+ d[1] = user_data;
+ d[2] = &scope_id;
+
+ g_hash_table_foreach (scanner->symbol_table, g_scanner_foreach_internal, d);
+}
+
+GTokenType
+g_scanner_peek_next_token (GScanner *scanner)
+{
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
+
+ if (scanner->next_token == G_TOKEN_NONE)
+ {
+ scanner->next_line = scanner->line;
+ scanner->next_position = scanner->position;
+ g_scanner_get_token_i (scanner,
+ &scanner->next_token,
+ &scanner->next_value,
+ &scanner->next_line,
+ &scanner->next_position);
+ }
+
+ return scanner->next_token;
+}
+
+GTokenType
+g_scanner_get_next_token (GScanner *scanner)
+{
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
+
+ if (scanner->next_token != G_TOKEN_NONE)
+ {
+ g_scanner_free_value (&scanner->token, &scanner->value);
+
+ scanner->token = scanner->next_token;
+ scanner->value = scanner->next_value;
+ scanner->line = scanner->next_line;
+ scanner->position = scanner->next_position;
+ scanner->next_token = G_TOKEN_NONE;
+ }
+ else
+ g_scanner_get_token_i (scanner,
+ &scanner->token,
+ &scanner->value,
+ &scanner->line,
+ &scanner->position);
+
+ return scanner->token;
+}
+
+GTokenType
+g_scanner_cur_token (GScanner *scanner)
+{
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_EOF);
+
+ return scanner->token;
+}
+
+GTokenValue
+g_scanner_cur_value (GScanner *scanner)
+{
+ GTokenValue v;
+
+ v.v_int = 0;
+
+ g_return_val_if_fail (scanner != NULL, v);
+
+ /* MSC isn't capable of handling return scanner->value; ? */
+
+ v = scanner->value;
+
+ return v;
+}
+
+guint
+g_scanner_cur_line (GScanner *scanner)
+{
+ g_return_val_if_fail (scanner != NULL, 0);
+
+ return scanner->line;
+}
+
+guint
+g_scanner_cur_position (GScanner *scanner)
+{
+ g_return_val_if_fail (scanner != NULL, 0);
+
+ return scanner->position;
+}
+
+gboolean
+g_scanner_eof (GScanner *scanner)
+{
+ g_return_val_if_fail (scanner != NULL, TRUE);
+
+ return scanner->token == G_TOKEN_EOF;
+}
+
+void
+g_scanner_input_file (GScanner *scanner,
+ gint input_fd)
+{
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (input_fd >= 0);
+
+ if (scanner->input_fd >= 0)
+ g_scanner_sync_file_offset (scanner);
+
+ scanner->token = G_TOKEN_NONE;
+ scanner->value.v_int = 0;
+ scanner->line = 1;
+ scanner->position = 0;
+ scanner->next_token = G_TOKEN_NONE;
+
+ scanner->input_fd = input_fd;
+ scanner->text = NULL;
+ scanner->text_end = NULL;
+
+ if (!scanner->buffer)
+ scanner->buffer = g_new (gchar, READ_BUFFER_SIZE + 1);
+}
+
+void
+g_scanner_input_text (GScanner *scanner,
+ const gchar *text,
+ guint text_len)
+{
+ g_return_if_fail (scanner != NULL);
+ if (text_len)
+ g_return_if_fail (text != NULL);
+ else
+ text = NULL;
+
+ if (scanner->input_fd >= 0)
+ g_scanner_sync_file_offset (scanner);
+
+ scanner->token = G_TOKEN_NONE;
+ scanner->value.v_int = 0;
+ scanner->line = 1;
+ scanner->position = 0;
+ scanner->next_token = G_TOKEN_NONE;
+
+ scanner->input_fd = -1;
+ scanner->text = text;
+ scanner->text_end = text + text_len;
+
+ if (scanner->buffer)
+ {
+ g_free (scanner->buffer);
+ scanner->buffer = NULL;
+ }
+}
+
+static guchar
+g_scanner_peek_next_char (GScanner *scanner)
+{
+ if (scanner->text < scanner->text_end)
+ {
+ return *scanner->text;
+ }
+ else if (scanner->input_fd >= 0)
+ {
+ gint count;
+ gchar *buffer;
+
+ buffer = scanner->buffer;
+ do
+ {
+ count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
+ }
+ while (count == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (count < 1)
+ {
+ scanner->input_fd = -1;
+
+ return 0;
+ }
+ else
+ {
+ scanner->text = buffer;
+ scanner->text_end = buffer + count;
+
+ return *buffer;
+ }
+ }
+ else
+ return 0;
+}
+
+void
+g_scanner_sync_file_offset (GScanner *scanner)
+{
+ g_return_if_fail (scanner != NULL);
+
+ /* for file input, rewind the filedescriptor to the current
+ * buffer position and blow the file read ahead buffer. useful for
+ * third party uses of our filedescriptor, which hooks onto the current
+ * scanning position.
+ */
+
+ if (scanner->input_fd >= 0 && scanner->text_end > scanner->text)
+ {
+ gint buffered;
+
+ buffered = scanner->text_end - scanner->text;
+ if (lseek (scanner->input_fd, - buffered, SEEK_CUR) >= 0)
+ {
+ /* we succeeded, blow our buffer's contents now */
+ scanner->text = NULL;
+ scanner->text_end = NULL;
+ }
+ else
+ errno = 0;
+ }
+}
+
+static guchar
+g_scanner_get_char (GScanner *scanner,
+ guint *line_p,
+ guint *position_p)
+{
+ guchar fchar;
+
+ if (scanner->text < scanner->text_end)
+ fchar = *(scanner->text++);
+ else if (scanner->input_fd >= 0)
+ {
+ gint count;
+ gchar *buffer;
+
+ buffer = scanner->buffer;
+ do
+ {
+ count = read (scanner->input_fd, buffer, READ_BUFFER_SIZE);
+ }
+ while (count == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (count < 1)
+ {
+ scanner->input_fd = -1;
+ fchar = 0;
+ }
+ else
+ {
+ scanner->text = buffer + 1;
+ scanner->text_end = buffer + count;
+ fchar = *buffer;
+ if (!fchar)
+ {
+ g_scanner_sync_file_offset (scanner);
+ scanner->text_end = scanner->text;
+ scanner->input_fd = -1;
+ }
+ }
+ }
+ else
+ fchar = 0;
+
+ if (fchar == '\n')
+ {
+ (*position_p) = 0;
+ (*line_p)++;
+ }
+ else if (fchar)
+ {
+ (*position_p)++;
+ }
+
+ return fchar;
+}
+
+void
+g_scanner_unexp_token (GScanner *scanner,
+ GTokenType expected_token,
+ const gchar *identifier_spec,
+ const gchar *symbol_spec,
+ const gchar *symbol_name,
+ const gchar *message,
+ gint is_error)
+{
+ gchar *token_string;
+ guint token_string_len;
+ gchar *expected_string;
+ guint expected_string_len;
+ const gchar *message_prefix;
+ gboolean print_unexp;
+ void (*msg_handler) (GScanner*, const gchar*, ...);
+
+ g_return_if_fail (scanner != NULL);
+
+ if (is_error)
+ msg_handler = g_scanner_error;
+ else
+ msg_handler = g_scanner_warn;
+
+ if (!identifier_spec)
+ identifier_spec = "identifier";
+ if (!symbol_spec)
+ symbol_spec = "symbol";
+
+ token_string_len = 56;
+ token_string = g_new (gchar, token_string_len + 1);
+ expected_string_len = 64;
+ expected_string = g_new (gchar, expected_string_len + 1);
+ print_unexp = TRUE;
+
+ switch (scanner->token)
+ {
+ case G_TOKEN_EOF:
+ g_snprintf (token_string, token_string_len, "end of file");
+ break;
+
+ default:
+ if (scanner->token >= 1 && scanner->token <= 255)
+ {
+ if ((scanner->token >= ' ' && scanner->token <= '~') ||
+ strchr (scanner->config->cset_identifier_first, scanner->token) ||
+ strchr (scanner->config->cset_identifier_nth, scanner->token))
+ g_snprintf (token_string, expected_string_len, "character `%c'", scanner->token);
+ else
+ g_snprintf (token_string, expected_string_len, "character `\\%o'", scanner->token);
+ break;
+ }
+ else if (!scanner->config->symbol_2_token)
+ {
+ g_snprintf (token_string, token_string_len, "(unknown) token <%d>", scanner->token);
+ break;
+ }
+ /* fall through */
+ case G_TOKEN_SYMBOL:
+ if (expected_token == G_TOKEN_SYMBOL ||
+ (scanner->config->symbol_2_token &&
+ expected_token > G_TOKEN_LAST))
+ print_unexp = FALSE;
+ if (symbol_name)
+ g_snprintf (token_string,
+ token_string_len,
+ "%s%s `%s'",
+ print_unexp ? "" : "invalid ",
+ symbol_spec,
+ symbol_name);
+ else
+ g_snprintf (token_string,
+ token_string_len,
+ "%s%s",
+ print_unexp ? "" : "invalid ",
+ symbol_spec);
+ break;
+
+ case G_TOKEN_ERROR:
+ print_unexp = FALSE;
+ expected_token = G_TOKEN_NONE;
+ switch (scanner->value.v_error)
+ {
+ case G_ERR_UNEXP_EOF:
+ g_snprintf (token_string, token_string_len, "scanner: unexpected end of file");
+ break;
+
+ case G_ERR_UNEXP_EOF_IN_STRING:
+ g_snprintf (token_string, token_string_len, "scanner: unterminated string constant");
+ break;
+
+ case G_ERR_UNEXP_EOF_IN_COMMENT:
+ g_snprintf (token_string, token_string_len, "scanner: unterminated comment");
+ break;
+
+ case G_ERR_NON_DIGIT_IN_CONST:
+ g_snprintf (token_string, token_string_len, "scanner: non digit in constant");
+ break;
+
+ case G_ERR_FLOAT_RADIX:
+ g_snprintf (token_string, token_string_len, "scanner: invalid radix for floating constant");
+ break;
+
+ case G_ERR_FLOAT_MALFORMED:
+ g_snprintf (token_string, token_string_len, "scanner: malformed floating constant");
+ break;
+
+ case G_ERR_DIGIT_RADIX:
+ g_snprintf (token_string, token_string_len, "scanner: digit is beyond radix");
+ break;
+
+ case G_ERR_UNKNOWN:
+ default:
+ g_snprintf (token_string, token_string_len, "scanner: unknown error");
+ break;
+ }
+ break;
+
+ case G_TOKEN_CHAR:
+ g_snprintf (token_string, token_string_len, "character `%c'", scanner->value.v_char);
+ break;
+
+ case G_TOKEN_IDENTIFIER:
+ case G_TOKEN_IDENTIFIER_NULL:
+ if (expected_token == G_TOKEN_IDENTIFIER ||
+ expected_token == G_TOKEN_IDENTIFIER_NULL)
+ print_unexp = FALSE;
+ g_snprintf (token_string,
+ token_string_len,
+ "%s%s `%s'",
+ print_unexp ? "" : "invalid ",
+ identifier_spec,
+ scanner->token == G_TOKEN_IDENTIFIER ? scanner->value.v_string : "null");
+ break;
+
+ case G_TOKEN_BINARY:
+ case G_TOKEN_OCTAL:
+ case G_TOKEN_INT:
+ case G_TOKEN_HEX:
+ g_snprintf (token_string, token_string_len, "number `%ld'", scanner->value.v_int);
+ break;
+
+ case G_TOKEN_FLOAT:
+ g_snprintf (token_string, token_string_len, "number `%.3f'", scanner->value.v_float);
+ break;
+
+ case G_TOKEN_STRING:
+ if (expected_token == G_TOKEN_STRING)
+ print_unexp = FALSE;
+ g_snprintf (token_string,
+ token_string_len,
+ "%s%sstring constant \"%s\"",
+ print_unexp ? "" : "invalid ",
+ scanner->value.v_string[0] == 0 ? "empty " : "",
+ scanner->value.v_string);
+ token_string[token_string_len - 2] = '"';
+ token_string[token_string_len - 1] = 0;
+ break;
+
+ case G_TOKEN_COMMENT_SINGLE:
+ case G_TOKEN_COMMENT_MULTI:
+ g_snprintf (token_string, token_string_len, "comment");
+ break;
+
+ case G_TOKEN_NONE:
+ /* somehow the user's parsing code is screwed, there isn't much
+ * we can do about it.
+ * Note, a common case to trigger this is
+ * g_scanner_peek_next_token(); g_scanner_unexp_token();
+ * without an intermediate g_scanner_get_next_token().
+ */
+ g_assert_not_reached ();
+ break;
+ }
+
+
+ switch (expected_token)
+ {
+ gboolean need_valid;
+
+ default:
+ if (expected_token >= 1 && expected_token <= 255)
+ {
+ if ((expected_token >= ' ' && expected_token <= '~') ||
+ strchr (scanner->config->cset_identifier_first, expected_token) ||
+ strchr (scanner->config->cset_identifier_nth, expected_token))
+ g_snprintf (expected_string, expected_string_len, "character `%c'", expected_token);
+ else
+ g_snprintf (expected_string, expected_string_len, "character `\\%o'", expected_token);
+ break;
+ }
+ else if (!scanner->config->symbol_2_token)
+ {
+ g_snprintf (expected_string, expected_string_len, "(unknown) token <%d>", expected_token);
+ break;
+ }
+ /* fall through */
+ case G_TOKEN_SYMBOL:
+ need_valid = (scanner->token == G_TOKEN_SYMBOL ||
+ (scanner->config->symbol_2_token &&
+ scanner->token > G_TOKEN_LAST));
+ g_snprintf (expected_string,
+ expected_string_len,
+ "%s%s",
+ need_valid ? "valid " : "",
+ symbol_spec);
+ /* FIXME: should we attempt to lookup the symbol_name for symbol_2_token? */
+ break;
+
+ case G_TOKEN_INT:
+ g_snprintf (expected_string, expected_string_len, "%snumber (integer)",
+ scanner->token == G_TOKEN_INT ? "valid " : "");
+ break;
+
+ case G_TOKEN_FLOAT:
+ g_snprintf (expected_string, expected_string_len, "%snumber (float)",
+ scanner->token == G_TOKEN_FLOAT ? "valid " : "");
+ break;
+
+ case G_TOKEN_STRING:
+ g_snprintf (expected_string,
+ expected_string_len,
+ "%sstring constant",
+ scanner->token == G_TOKEN_STRING ? "valid " : "");
+ break;
+
+ case G_TOKEN_IDENTIFIER:
+ case G_TOKEN_IDENTIFIER_NULL:
+ g_snprintf (expected_string,
+ expected_string_len,
+ "%s%s",
+ (scanner->token == G_TOKEN_IDENTIFIER_NULL ||
+ scanner->token == G_TOKEN_IDENTIFIER ? "valid " : ""),
+ identifier_spec);
+ break;
+
+ case G_TOKEN_EOF:
+ g_snprintf (expected_string, expected_string_len, "end of file");
+ break;
+
+ case G_TOKEN_NONE:
+ break;
+ }
+
+ if (message && message[0] != 0)
+ message_prefix = " - ";
+ else
+ {
+ message_prefix = "";
+ message = "";
+ }
+
+ if (expected_token != G_TOKEN_NONE)
+ {
+ if (print_unexp)
+ msg_handler (scanner,
+ "unexpected %s, expected %s%s%s",
+ token_string,
+ expected_string,
+ message_prefix,
+ message);
+ else
+ msg_handler (scanner,
+ "%s, expected %s%s%s",
+ token_string,
+ expected_string,
+ message_prefix,
+ message);
+ }
+ else
+ {
+ if (print_unexp)
+ msg_handler (scanner,
+ "unexpected %s%s%s",
+ token_string,
+ message_prefix,
+ message);
+ else
+ msg_handler (scanner,
+ "%s%s%s",
+ token_string,
+ message_prefix,
+ message);
+ }
+
+ g_free (token_string);
+ g_free (expected_string);
+}
+
+static void
+g_scanner_get_token_i (GScanner *scanner,
+ GTokenType *token_p,
+ GTokenValue *value_p,
+ guint *line_p,
+ guint *position_p)
+{
+ do
+ {
+ g_scanner_free_value (token_p, value_p);
+ g_scanner_get_token_ll (scanner, token_p, value_p, line_p, position_p);
+ }
+ while (((*token_p > 0 && *token_p < 256) &&
+ strchr (scanner->config->cset_skip_characters, *token_p)) ||
+ (*token_p == G_TOKEN_CHAR &&
+ strchr (scanner->config->cset_skip_characters, value_p->v_char)) ||
+ (*token_p == G_TOKEN_COMMENT_MULTI &&
+ scanner->config->skip_comment_multi) ||
+ (*token_p == G_TOKEN_COMMENT_SINGLE &&
+ scanner->config->skip_comment_single));
+
+ switch (*token_p)
+ {
+ case G_TOKEN_IDENTIFIER:
+ if (scanner->config->identifier_2_string)
+ *token_p = G_TOKEN_STRING;
+ break;
+
+ case G_TOKEN_SYMBOL:
+ if (scanner->config->symbol_2_token)
+ *token_p = (GTokenType) value_p->v_symbol;
+ break;
+
+ case G_TOKEN_BINARY:
+ case G_TOKEN_OCTAL:
+ case G_TOKEN_HEX:
+ if (scanner->config->numbers_2_int)
+ *token_p = G_TOKEN_INT;
+ break;
+
+ default:
+ break;
+ }
+
+ if (*token_p == G_TOKEN_INT &&
+ scanner->config->int_2_float)
+ {
+ *token_p = G_TOKEN_FLOAT;
+ value_p->v_float = value_p->v_int;
+ }
+
+ errno = 0;
+}
+
+static void
+g_scanner_get_token_ll (GScanner *scanner,
+ GTokenType *token_p,
+ GTokenValue *value_p,
+ guint *line_p,
+ guint *position_p)
+{
+ GScannerConfig *config;
+ GTokenType token;
+ gboolean in_comment_multi;
+ gboolean in_comment_single;
+ gboolean in_string_sq;
+ gboolean in_string_dq;
+ GString *gstring;
+ GTokenValue value;
+ guchar ch;
+
+ config = scanner->config;
+ (*value_p).v_int = 0;
+
+ if ((scanner->text >= scanner->text_end && scanner->input_fd < 0) ||
+ scanner->token == G_TOKEN_EOF)
+ {
+ *token_p = G_TOKEN_EOF;
+ return;
+ }
+
+ in_comment_multi = FALSE;
+ in_comment_single = FALSE;
+ in_string_sq = FALSE;
+ in_string_dq = FALSE;
+ gstring = NULL;
+
+ do /* while (ch != 0) */
+ {
+ gboolean dotted_float = FALSE;
+
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+
+ value.v_int = 0;
+ token = G_TOKEN_NONE;
+
+ /* this is *evil*, but needed ;(
+ * we first check for identifier first character, because it
+ * might interfere with other key chars like slashes or numbers
+ */
+ if (config->scan_identifier &&
+ ch && strchr (config->cset_identifier_first, ch))
+ goto identifier_precedence;
+
+ switch (ch)
+ {
+ case 0:
+ token = G_TOKEN_EOF;
+ (*position_p)++;
+ /* ch = 0; */
+ break;
+
+ case '/':
+ if (!config->scan_comment_multi ||
+ g_scanner_peek_next_char (scanner) != '*')
+ goto default_case;
+ g_scanner_get_char (scanner, line_p, position_p);
+ token = G_TOKEN_COMMENT_MULTI;
+ in_comment_multi = TRUE;
+ gstring = g_string_new ("");
+ while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
+ {
+ if (ch == '*' && g_scanner_peek_next_char (scanner) == '/')
+ {
+ g_scanner_get_char (scanner, line_p, position_p);
+ in_comment_multi = FALSE;
+ break;
+ }
+ else
+ g_string_append_c (gstring, ch);
+ }
+ ch = 0;
+ break;
+
+ case '\'':
+ if (!config->scan_string_sq)
+ goto default_case;
+ token = G_TOKEN_STRING;
+ in_string_sq = TRUE;
+ gstring = g_string_new ("");
+ while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
+ {
+ if (ch == '\'')
+ {
+ in_string_sq = FALSE;
+ break;
+ }
+ else
+ gstring = g_string_append_c (gstring, ch);
+ }
+ ch = 0;
+ break;
+
+ case '"':
+ if (!config->scan_string_dq)
+ goto default_case;
+ token = G_TOKEN_STRING;
+ in_string_dq = TRUE;
+ gstring = g_string_new ("");
+ while ((ch = g_scanner_get_char (scanner, line_p, position_p)) != 0)
+ {
+ if (ch == '"')
+ {
+ in_string_dq = FALSE;
+ break;
+ }
+ else
+ {
+ if (ch == '\\')
+ {
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ switch (ch)
+ {
+ guint i;
+ guint fchar;
+
+ case 0:
+ break;
+
+ case '\\':
+ gstring = g_string_append_c (gstring, '\\');
+ break;
+
+ case 'n':
+ gstring = g_string_append_c (gstring, '\n');
+ break;
+
+ case 't':
+ gstring = g_string_append_c (gstring, '\t');
+ break;
+
+ case 'r':
+ gstring = g_string_append_c (gstring, '\r');
+ break;
+
+ case 'b':
+ gstring = g_string_append_c (gstring, '\b');
+ break;
+
+ case 'f':
+ gstring = g_string_append_c (gstring, '\f');
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ i = ch - '0';
+ fchar = g_scanner_peek_next_char (scanner);
+ if (fchar >= '0' && fchar <= '7')
+ {
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ i = i * 8 + ch - '0';
+ fchar = g_scanner_peek_next_char (scanner);
+ if (fchar >= '0' && fchar <= '7')
+ {
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ i = i * 8 + ch - '0';
+ }
+ }
+ gstring = g_string_append_c (gstring, i);
+ break;
+
+ default:
+ gstring = g_string_append_c (gstring, ch);
+ break;
+ }
+ }
+ else
+ gstring = g_string_append_c (gstring, ch);
+ }
+ }
+ ch = 0;
+ break;
+
+ case '.':
+ if (!config->scan_float)
+ goto default_case;
+ token = G_TOKEN_FLOAT;
+ dotted_float = TRUE;
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ goto number_parsing;
+
+ case '$':
+ if (!config->scan_hex_dollar)
+ goto default_case;
+ token = G_TOKEN_HEX;
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ goto number_parsing;
+
+ case '0':
+ if (config->scan_octal)
+ token = G_TOKEN_OCTAL;
+ else
+ token = G_TOKEN_INT;
+ ch = g_scanner_peek_next_char (scanner);
+ if (config->scan_hex && (ch == 'x' || ch == 'X'))
+ {
+ token = G_TOKEN_HEX;
+ g_scanner_get_char (scanner, line_p, position_p);
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ if (ch == 0)
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_UNEXP_EOF;
+ (*position_p)++;
+ break;
+ }
+ if (g_scanner_char_2_num (ch, 16) < 0)
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_DIGIT_RADIX;
+ ch = 0;
+ break;
+ }
+ }
+ else if (config->scan_binary && (ch == 'b' || ch == 'B'))
+ {
+ token = G_TOKEN_BINARY;
+ g_scanner_get_char (scanner, line_p, position_p);
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ if (ch == 0)
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_UNEXP_EOF;
+ (*position_p)++;
+ break;
+ }
+ if (g_scanner_char_2_num (ch, 10) < 0)
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+ ch = 0;
+ break;
+ }
+ }
+ else
+ ch = '0';
+ /* fall through */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ number_parsing:
+ {
+ gboolean in_number = TRUE;
+ gchar *endptr;
+
+ if (token == G_TOKEN_NONE)
+ token = G_TOKEN_INT;
+
+ gstring = g_string_new (dotted_float ? "0." : "");
+ gstring = g_string_append_c (gstring, ch);
+
+ do /* while (in_number) */
+ {
+ gboolean is_E;
+
+ is_E = token == G_TOKEN_FLOAT && (ch == 'e' || ch == 'E');
+
+ ch = g_scanner_peek_next_char (scanner);
+
+ if (g_scanner_char_2_num (ch, 36) >= 0 ||
+ (config->scan_float && ch == '.') ||
+ (is_E && (ch == '+' || ch == '-')))
+ {
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+
+ switch (ch)
+ {
+ case '.':
+ if (token != G_TOKEN_INT && token != G_TOKEN_OCTAL)
+ {
+ value.v_error = token == G_TOKEN_FLOAT ? G_ERR_FLOAT_MALFORMED : G_ERR_FLOAT_RADIX;
+ token = G_TOKEN_ERROR;
+ in_number = FALSE;
+ }
+ else
+ {
+ token = G_TOKEN_FLOAT;
+ gstring = g_string_append_c (gstring, ch);
+ }
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ gstring = g_string_append_c (gstring, ch);
+ break;
+
+ case '-':
+ case '+':
+ if (token != G_TOKEN_FLOAT)
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+ in_number = FALSE;
+ }
+ else
+ gstring = g_string_append_c (gstring, ch);
+ break;
+
+ case 'e':
+ case 'E':
+ if ((token != G_TOKEN_HEX && !config->scan_float) ||
+ (token != G_TOKEN_HEX &&
+ token != G_TOKEN_OCTAL &&
+ token != G_TOKEN_FLOAT &&
+ token != G_TOKEN_INT))
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+ in_number = FALSE;
+ }
+ else
+ {
+ if (token != G_TOKEN_HEX)
+ token = G_TOKEN_FLOAT;
+ gstring = g_string_append_c (gstring, ch);
+ }
+ break;
+
+ default:
+ if (token != G_TOKEN_HEX)
+ {
+ token = G_TOKEN_ERROR;
+ value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+ in_number = FALSE;
+ }
+ else
+ gstring = g_string_append_c (gstring, ch);
+ break;
+ }
+ }
+ else
+ in_number = FALSE;
+ }
+ while (in_number);
+
+ endptr = NULL;
+ switch (token)
+ {
+ case G_TOKEN_BINARY:
+ value.v_binary = strtol (gstring->str, &endptr, 2);
+ break;
+
+ case G_TOKEN_OCTAL:
+ value.v_octal = strtol (gstring->str, &endptr, 8);
+ break;
+
+ case G_TOKEN_INT:
+ value.v_int = strtol (gstring->str, &endptr, 10);
+ break;
+
+ case G_TOKEN_FLOAT:
+ value.v_float = g_strtod (gstring->str, &endptr);
+ break;
+
+ case G_TOKEN_HEX:
+ value.v_hex = strtol (gstring->str, &endptr, 16);
+ break;
+
+ default:
+ break;
+ }
+ if (endptr && *endptr)
+ {
+ token = G_TOKEN_ERROR;
+ if (*endptr == 'e' || *endptr == 'E')
+ value.v_error = G_ERR_NON_DIGIT_IN_CONST;
+ else
+ value.v_error = G_ERR_DIGIT_RADIX;
+ }
+ g_string_free (gstring, TRUE);
+ gstring = NULL;
+ ch = 0;
+ } /* number_parsing:... */
+ break;
+
+ default:
+ default_case:
+ {
+ if (config->cpair_comment_single &&
+ ch == config->cpair_comment_single[0])
+ {
+ token = G_TOKEN_COMMENT_SINGLE;
+ in_comment_single = TRUE;
+ gstring = g_string_new ("");
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ while (ch != 0)
+ {
+ if (ch == config->cpair_comment_single[1])
+ {
+ in_comment_single = FALSE;
+ ch = 0;
+ break;
+ }
+
+ gstring = g_string_append_c (gstring, ch);
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ }
+ }
+ else if (config->scan_identifier && ch &&
+ strchr (config->cset_identifier_first, ch))
+ {
+ identifier_precedence:
+
+ if (config->cset_identifier_nth && ch &&
+ strchr (config->cset_identifier_nth,
+ g_scanner_peek_next_char (scanner)))
+ {
+ token = G_TOKEN_IDENTIFIER;
+ gstring = g_string_new ("");
+ gstring = g_string_append_c (gstring, ch);
+ do
+ {
+ ch = g_scanner_get_char (scanner, line_p, position_p);
+ gstring = g_string_append_c (gstring, ch);
+ ch = g_scanner_peek_next_char (scanner);
+ }
+ while (ch && strchr (config->cset_identifier_nth, ch));
+ ch = 0;
+ }
+ else if (config->scan_identifier_1char)
+ {
+ token = G_TOKEN_IDENTIFIER;
+ value.v_identifier = g_new0 (gchar, 2);
+ value.v_identifier[0] = ch;
+ ch = 0;
+ }
+ }
+ if (ch)
+ {
+ if (config->char_2_token)
+ token = ch;
+ else
+ {
+ token = G_TOKEN_CHAR;
+ value.v_char = ch;
+ }
+ ch = 0;
+ }
+ } /* default_case:... */
+ break;
+ }
+ g_assert (ch == 0 && token != G_TOKEN_NONE); /* paranoid */
+ }
+ while (ch != 0);
+
+ if (in_comment_multi || in_comment_single ||
+ in_string_sq || in_string_dq)
+ {
+ token = G_TOKEN_ERROR;
+ if (gstring)
+ {
+ g_string_free (gstring, TRUE);
+ gstring = NULL;
+ }
+ (*position_p)++;
+ if (in_comment_multi || in_comment_single)
+ value.v_error = G_ERR_UNEXP_EOF_IN_COMMENT;
+ else /* (in_string_sq || in_string_dq) */
+ value.v_error = G_ERR_UNEXP_EOF_IN_STRING;
+ }
+
+ if (gstring)
+ {
+ value.v_string = gstring->str;
+ g_string_free (gstring, FALSE);
+ gstring = NULL;
+ }
+
+ if (token == G_TOKEN_IDENTIFIER)
+ {
+ if (config->scan_symbols)
+ {
+ GScannerKey *key;
+ guint scope_id;
+
+ scope_id = scanner->scope_id;
+ key = g_scanner_lookup_internal (scanner, scope_id, value.v_identifier);
+ if (!key && scope_id && scanner->config->scope_0_fallback)
+ key = g_scanner_lookup_internal (scanner, 0, value.v_identifier);
+
+ if (key)
+ {
+ g_free (value.v_identifier);
+ token = G_TOKEN_SYMBOL;
+ value.v_symbol = key->value;
+ }
+ }
+
+ if (token == G_TOKEN_IDENTIFIER &&
+ config->scan_identifier_NULL &&
+ strlen (value.v_identifier) == 4)
+ {
+ const gchar *null_upper = "NULL";
+ const gchar *null_lower = "null";
+
+ if (scanner->config->case_sensitive)
+ {
+ if (value.v_identifier[0] == null_upper[0] &&
+ value.v_identifier[1] == null_upper[1] &&
+ value.v_identifier[2] == null_upper[2] &&
+ value.v_identifier[3] == null_upper[3])
+ token = G_TOKEN_IDENTIFIER_NULL;
+ }
+ else
+ {
+ if ((value.v_identifier[0] == null_upper[0] ||
+ value.v_identifier[0] == null_lower[0]) &&
+ (value.v_identifier[1] == null_upper[1] ||
+ value.v_identifier[1] == null_lower[1]) &&
+ (value.v_identifier[2] == null_upper[2] ||
+ value.v_identifier[2] == null_lower[2]) &&
+ (value.v_identifier[3] == null_upper[3] ||
+ value.v_identifier[3] == null_lower[3]))
+ token = G_TOKEN_IDENTIFIER_NULL;
+ }
+ }
+ }
+
+ *token_p = token;
+ *value_p = value;
+}
+
+
+
+
+gdouble
+g_strtod (const gchar *nptr,
+ gchar **endptr)
+{
+ gchar *fail_pos_1;
+ gchar *fail_pos_2;
+ gdouble val_1;
+ gdouble val_2 = 0;
+
+ g_return_val_if_fail (nptr != NULL, 0);
+
+ fail_pos_1 = NULL;
+ fail_pos_2 = NULL;
+
+ val_1 = strtod (nptr, &fail_pos_1);
+
+ if (fail_pos_1 && fail_pos_1[0] != 0)
+ {
+ gchar *old_locale;
+
+ old_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
+ setlocale (LC_NUMERIC, "C");
+ val_2 = strtod (nptr, &fail_pos_2);
+ setlocale (LC_NUMERIC, old_locale);
+ g_free (old_locale);
+ }
+
+ if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
+ {
+ if (endptr)
+ *endptr = fail_pos_1;
+ return val_1;
+ }
+ else
+ {
+ if (endptr)
+ *endptr = fail_pos_2;
+ return val_2;
+ }
+}
+
+
+#ifndef MB_LEN_MAX
+# define MB_LEN_MAX 8
+#endif
+
+typedef struct
+{
+ guint min_width;
+ guint precision;
+ gboolean alternate_format, zero_padding, adjust_left, locale_grouping;
+ gboolean add_space, add_sign, possible_sign, seen_precision;
+ gboolean mod_half, mod_long, mod_extra_long;
+} PrintfArgSpec;
+
+
+static gsize
+printf_string_upper_bound (const gchar *format,
+ gboolean may_warn,
+ va_list args)
+{
+ static gboolean honour_longs = sizeof(long) > 4 || sizeof(void*) > 4;
+ gsize len = 1;
+
+ if (!format)
+ return len;
+
+ while (*format)
+ {
+ register gchar c = *format++;
+
+ if (c != '%')
+ len += 1;
+ else /* (c == '%') */
+ {
+ PrintfArgSpec spec = { 0, };
+ gboolean seen_l = FALSE, conv_done = FALSE;
+ gsize conv_len = 0;
+ const gchar *spec_start = format;
+
+ do
+ {
+ c = *format++;
+ switch (c)
+ {
+ GDoubleIEEE754 u_double;
+ guint v_uint;
+ gint v_int;
+ const gchar *v_string;
+
+ /* beware of positional parameters
+ */
+ case '$':
+ if (may_warn)
+ g_warning (G_STRLOC ": unable to handle positional parameters (%%n$)");
+ len += 1024; /* try adding some safety padding */
+ break;
+
+ /* parse flags
+ */
+ case '#':
+ spec.alternate_format = TRUE;
+ break;
+ case '0':
+ spec.zero_padding = TRUE;
+ break;
+ case '-':
+ spec.adjust_left = TRUE;
+ break;
+ case ' ':
+ spec.add_space = TRUE;
+ break;
+ case '+':
+ spec.add_sign = TRUE;
+ break;
+ case '\'':
+ spec.locale_grouping = TRUE;
+ break;
+
+ /* parse output size specifications
+ */
+ case '.':
+ spec.seen_precision = TRUE;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ v_uint = c - '0';
+ c = *format;
+ while (c >= '0' && c <= '9')
+ {
+ format++;
+ v_uint = v_uint * 10 + c - '0';
+ c = *format;
+ }
+ if (spec.seen_precision)
+ spec.precision = MAX (spec.precision, v_uint);
+ else
+ spec.min_width = MAX (spec.min_width, v_uint);
+ break;
+ case '*':
+ v_int = va_arg (args, int);
+ if (spec.seen_precision)
+ {
+ /* forget about negative precision */
+ if (v_int >= 0)
+ spec.precision = MAX (spec.precision, v_int);
+ }
+ else
+ {
+ if (v_int < 0)
+ {
+ v_int = - v_int;
+ spec.adjust_left = TRUE;
+ }
+ spec.min_width = MAX (spec.min_width, v_int);
+ }
+ break;
+
+ /* parse type modifiers
+ */
+ case 'h':
+ spec.mod_half = TRUE;
+ break;
+ case 'l':
+ if (!seen_l)
+ {
+ spec.mod_long = TRUE;
+ seen_l = TRUE;
+ break;
+ }
+ /* else, fall through */
+ case 'L':
+ case 'q':
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ break;
+ case 'z':
+ case 'Z':
+ if (sizeof(size_t))
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+ case 't':
+ if (sizeof(ptrdiff_t) > 4)
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+ case 'j':
+ if (GLIB_SIZEOF_INTMAX > 4)
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+
+ /* parse output conversions
+ */
+ case '%':
+ conv_len += 1;
+ break;
+ case 'O':
+ case 'D':
+ case 'I':
+ case 'U':
+ /* some C libraries feature long variants for these as well? */
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 'o':
+ conv_len += 2;
+ /* fall through */
+ case 'd':
+ case 'i':
+ conv_len += 1; /* sign */
+ /* fall through */
+ case 'u':
+ conv_len += 4;
+ /* fall through */
+ case 'x':
+ case 'X':
+ spec.possible_sign = TRUE;
+ conv_len += 10;
+ if (spec.mod_long && honour_longs)
+ conv_len *= 2;
+ if (spec.mod_extra_long)
+ conv_len *= 2;
+ if (spec.mod_extra_long)
+ {
+ (void) va_arg (args, gint64);
+ }
+ else if (spec.mod_long)
+ (void) va_arg (args, long);
+ else
+ (void) va_arg (args, int);
+ break;
+ case 'A':
+ case 'a':
+ /* 0x */
+ conv_len += 2;
+ /* fall through */
+ case 'g':
+ case 'G':
+ case 'e':
+ case 'E':
+ case 'f':
+ spec.possible_sign = TRUE;
+ /* n . dddddddddddddddddddddddd E +- eeee */
+ conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
+ if (may_warn && spec.mod_extra_long)
+ g_warning (G_STRLOC ": unable to handle long double, collecting double only");
+#ifdef HAVE_LONG_DOUBLE
+#error need to implement special handling for long double
+#endif
+ u_double.v_double = va_arg (args, double);
+ /* %f can expand up to all significant digits before '.' (308) */
+ if (c == 'f' &&
+ u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
+ {
+ gint exp = u_double.mpn.biased_exponent;
+
+ exp -= G_IEEE754_DOUBLE_BIAS;
+ exp = exp * G_LOG_2_BASE_10 + 1;
+ conv_len += ABS (exp); /* exp can be <0 */
+ }
+ /* some printf() implementations require extra padding for rounding */
+ conv_len += 2;
+ /* we can't really handle locale specific grouping here */
+ if (spec.locale_grouping)
+ conv_len *= 2;
+ break;
+ case 'C':
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 'c':
+ conv_len += spec.mod_long ? MB_LEN_MAX : 1;
+ (void) va_arg (args, int);
+ break;
+ case 'S':
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 's':
+ v_string = va_arg (args, char*);
+ if (!v_string)
+ conv_len += 8; /* hold "(null)" */
+ else if (spec.seen_precision)
+ conv_len += spec.precision;
+ else
+ conv_len += strlen (v_string);
+ conv_done = TRUE;
+ if (spec.mod_long)
+ {
+ if (may_warn)
+ g_warning (G_STRLOC": unable to handle wide char strings");
+ len += 1024; /* try adding some safety padding */
+ }
+ break;
+ case 'P': /* do we actually need this? */
+ /* fall through */
+ case 'p':
+ spec.alternate_format = TRUE;
+ conv_len += 10;
+ if (honour_longs)
+ conv_len *= 2;
+ /* fall through */
+ case 'n':
+ conv_done = TRUE;
+ (void) va_arg (args, void*);
+ break;
+ case 'm':
+ /* there's not much we can do to be clever */
+ v_string = g_strerror (errno);
+ v_uint = v_string ? strlen (v_string) : 0;
+ conv_len += MAX (256, v_uint);
+ break;
+
+ /* handle invalid cases
+ */
+ case '\000':
+ /* no conversion specification, bad bad */
+ conv_len += format - spec_start;
+ break;
+ default:
+ if (may_warn)
+ g_warning (G_STRLOC": unable to handle `%c' while parsing format",
+ c);
+ break;
+ }
+ conv_done |= conv_len > 0;
+ }
+ while (!conv_done);
+ /* handle width specifications */
+ conv_len = MAX (conv_len, MAX (spec.precision, spec.min_width));
+ /* handle flags */
+ conv_len += spec.alternate_format ? 2 : 0;
+ conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
+ /* finally done */
+ len += conv_len;
+ } /* else (c == '%') */
+ } /* while (*format) */
+
+ return len;
+}
+
+
+
+gsize
+g_printf_string_upper_bound (const gchar *format,
+ va_list args)
+{
+ return printf_string_upper_bound (format, TRUE, args);
+}
+
+gchar*
+g_get_current_dir (void)
+{
+ gchar *buffer = NULL;
+ gchar *dir = NULL;
+ static gulong max_len = 0;
+
+ if (max_len == 0)
+ max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
+
+ /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
+ * and, if that wasn't bad enough, hangs in doing so.
+ */
+#if (defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
+ buffer = g_new (gchar, max_len + 1);
+ *buffer = 0;
+ dir = getwd (buffer);
+#else /* !sun || !HAVE_GETCWD */
+ while (max_len < G_MAXULONG / 2)
+ {
+ buffer = g_new (gchar, max_len + 1);
+ *buffer = 0;
+ dir = getcwd (buffer, max_len);
+
+ if (dir || errno != ERANGE)
+ break;
+
+ g_free (buffer);
+ max_len *= 2;
+ }
+#endif /* !sun || !HAVE_GETCWD */
+
+ if (!dir || !*buffer)
+ {
+ /* hm, should we g_error() out here?
+ * this can happen if e.g. "./" has mode \0000
+ */
+ buffer[0] = G_DIR_SEPARATOR;
+ buffer[1] = 0;
+ }
+
+ dir = g_strdup (buffer);
+ g_free (buffer);
+
+ return dir;
+}
+
+gboolean
+g_path_is_absolute (const gchar *file_name)
+{
+ g_return_val_if_fail (file_name != NULL, FALSE);
+
+ if (file_name[0] == G_DIR_SEPARATOR
+#ifdef G_OS_WIN32
+ || file_name[0] == '/'
+#endif
+ )
+ return TRUE;
+
+#ifdef G_OS_WIN32
+ /* Recognize drive letter on native Windows */
+ if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && (file_name[2] == G_DIR_SEPARATOR || file_name[2] == '/'))
+ return TRUE;
+#endif /* G_OS_WIN32 */
+
+ return FALSE;
+}
+
+/* vim:set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslglib.h b/flow/gsl/gslglib.h
new file mode 100644
index 0000000..cd1f952
--- /dev/null
+++ b/flow/gsl/gslglib.h
@@ -0,0 +1,858 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_GLIB_H__
+#define __GSL_GLIB_H__
+
+#ifndef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "GSL"
+#endif
+
+
+#include <limits.h>
+#include <float.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* for -ansi -pedantic */
+#ifdef __GNUC__
+#define asm __asm__
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GSL_ASSERT(foo) do { if (!(foo)) g_error ("assertion failed `%s'", #foo); } while (0)
+
+/* --- GLib typedefs --- */
+typedef void* gpointer;
+typedef const void* gconstpointer;
+typedef char gchar;
+typedef unsigned char guchar;
+typedef signed short gshort;
+typedef unsigned short gushort;
+typedef signed int gint;
+typedef unsigned int guint;
+typedef signed long glong;
+typedef unsigned long gulong;
+typedef float gfloat;
+typedef double gdouble;
+typedef size_t gsize;
+typedef gchar gint8;
+typedef guchar guint8;
+typedef gshort gint16;
+typedef gushort guint16;
+typedef gint gint32;
+typedef guint guint32;
+typedef gint gboolean;
+typedef gint32 GTime;
+#ifdef __alpha
+typedef long int gint64;
+typedef unsigned long int guint64;
+#else
+typedef long long int gint64;
+typedef unsigned long long int guint64;
+#endif
+typedef struct _GString GString;
+typedef struct _GDebugKey GDebugKey;
+struct _GDebugKey
+{
+ const gchar *key;
+ guint value;
+};
+typedef struct _GTimeVal GTimeVal;
+struct _GTimeVal
+{
+ glong tv_sec;
+ glong tv_usec;
+};
+typedef gint (*GCompareFunc) (gconstpointer a,
+ gconstpointer b);
+
+
+/* --- standard macros --- */
+#ifndef ABS
+#define ABS(a) ((a) > 0 ? (a) : -(a))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef CLAMP
+#define CLAMP(v,l,h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v))
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+
+/* --- glib macros --- */
+#define G_MINFLOAT FLT_MIN
+#define G_MAXFLOAT FLT_MAX
+#define G_MINDOUBLE DBL_MIN
+#define G_MAXDOUBLE DBL_MAX
+#define G_MINSHORT SHRT_MIN
+#define G_MAXSHORT SHRT_MAX
+#define G_MAXUSHORT USHRT_MAX
+#define G_MININT INT_MIN
+#define G_MININT64 ((gint64) 0x8000000000000000)
+#define G_MAXINT INT_MAX
+#define G_MAXINT64 ((gint64) 0x7fffffffffffffff)
+#define G_MAXUINT UINT_MAX
+#define G_MAXUINT64 ((guint64) 0xffffffffffffffff)
+#define G_MINLONG LONG_MIN
+#define G_MAXLONG LONG_MAX
+#define G_MAXULONG ULONG_MAX
+#define G_USEC_PER_SEC 1000000
+#define G_LITTLE_ENDIAN 1234
+#define G_BIG_ENDIAN 4321
+
+#define G_DIR_SEPARATOR '/'
+#ifdef MAXPATHLEN
+#define G_PATH_LENGTH MAXPATHLEN
+#elif defined (PATH_MAX)
+#define G_PATH_LENGTH PATH_MAX
+#elif defined (_PC_PATH_MAX)
+#define G_PATH_LENGTH sysconf(_PC_PATH_MAX)
+#else
+#define G_PATH_LENGTH 2048
+#endif
+
+#define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
+#define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string)
+#define G_STRINGIFY_ARG(contents) #contents
+#define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__)
+#if !(defined (G_STMT_START) && defined (G_STMT_END))
+# if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
+# define G_STMT_START (void)(
+# define G_STMT_END )
+# else
+# if (defined (sun) || defined (__sun__))
+# define G_STMT_START if (1)
+# define G_STMT_END else (void)0
+# else
+# define G_STMT_START do
+# define G_STMT_END while (0)
+# endif
+# endif
+#endif
+#define G_STRUCT_OFFSET(struct_type, member) \
+ ((glong) ((guint8*) &((struct_type*) 0)->member))
+#define G_STRUCT_MEMBER_P(struct_p, struct_offset) \
+ ((gpointer) ((guint8*) (struct_p) + (glong) (struct_offset)))
+#define G_STRUCT_MEMBER(member_type, struct_p, struct_offset) \
+ (*(member_type*) G_STRUCT_MEMBER_P ((struct_p), (struct_offset)))
+#define GINT_TO_POINTER(i) ((gpointer) (int) (i))
+#define GUINT_TO_POINTER(i) ((gpointer) (guint) (i))
+#define GPOINTER_TO_INT(p) ((int) (p))
+#define GPOINTER_TO_UINT(p) ((guint) (p))
+#define GUINT16_SWAP_LE_BE(val) ((guint16) ( \
+ (((guint16) (val) & (guint16) 0x00ffU) << 8) | \
+ (((guint16) (val) & (guint16) 0xff00U) >> 8)))
+#define GUINT32_SWAP_LE_BE(val) ((guint32) ( \
+ (((guint32) (val) & (guint32) 0x000000ffU) << 24) | \
+ (((guint32) (val) & (guint32) 0x0000ff00U) << 8) | \
+ (((guint32) (val) & (guint32) 0x00ff0000U) >> 8) | \
+ (((guint32) (val) & (guint32) 0xff000000U) >> 24)))
+
+#ifdef WORDS_BIGENDIAN
+#define GUINT16_TO_LE(val) GUINT16_SWAP_LE_BE(val)
+#define GUINT32_TO_LE(val) GUINT32_SWAP_LE_BE(val)
+#define GUINT16_TO_BE(val) ((guint16) (val))
+#define GUINT32_TO_BE(val) ((guint32) (val))
+#else /* LITTLEENDIAN */
+#define GUINT16_TO_LE(val) ((guint16) (val))
+#define GUINT32_TO_LE(val) ((guint32) (val))
+#define GUINT16_TO_BE(val) GUINT16_SWAP_LE_BE(val)
+#define GUINT32_TO_BE(val) GUINT32_SWAP_LE_BE(val)
+#endif
+
+#define GUINT16_FROM_LE(val) (GUINT16_TO_LE (val))
+#define GUINT16_FROM_BE(val) (GUINT16_TO_BE (val))
+#define GUINT32_FROM_LE(val) (GUINT32_TO_LE (val))
+#define GUINT32_FROM_BE(val) (GUINT32_TO_BE (val))
+
+
+#define g_memmove memmove
+#define g_assert GSL_ASSERT
+#define g_assert_not_reached() g_assert(!G_STRLOC": should not be reached")
+#define g_return_if_fail(foo) do { if (!(foo)) g_message (G_STRLOC ": assertion failed `%s'", #foo); } while (0)
+#define g_return_val_if_fail(foo,v) do { if (!(foo)) { g_message (G_STRLOC ": assertion failed `%s'", #foo); return(v);}} while (0)
+
+/* from galloca.h */
+
+#ifdef __GNUC__
+/* GCC does the right thing */
+# undef alloca
+# define alloca(size) __builtin_alloca (size)
+#elif defined (GLIB_HAVE_ALLOCA_H)
+/* a native and working alloca.h is there */
+# include <alloca.h>
+#else /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else /* !_MSC_VER */
+# ifdef _AIX
+ #pragma alloca
+# else /* !_AIX */
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif /* !alloca */
+# endif /* !_AIX */
+# endif /* !_MSC_VER */
+#endif /* !__GNUC__ && !GLIB_HAVE_ALLOCA_H */
+
+#define g_alloca(size) alloca (size)
+#define g_newa(struct_type, n_structs) ((struct_type*) g_alloca (sizeof (struct_type) * (gsize) (n_structs)))
+
+/* needs inline configure check */
+#if defined (__xlc__)
+# if !defined (inline)
+# define inline _Inline
+# endif
+#elif defined (__GNUC__)
+#define inline __inline__
+#else
+#define inline /* no inline */
+#endif
+
+
+/* --- inline functions --- */
+void
+gsl_g_log (const gchar*msg,const char *format, va_list ap);
+void
+gsl_g_print_fd (int fd,const char *format, va_list ap);
+static inline void
+g_error (const gchar *format,
+ ...)
+{
+ va_list args;
+ va_start (args, format);
+ gsl_g_log ("**ERROR**", format, args);
+ va_end (args);
+}
+static inline void
+g_message (const gchar *format,
+ ...)
+{
+ va_list args;
+ va_start (args, format);
+ gsl_g_log ("**MESSAGE**", format, args);
+ va_end (args);
+}
+static inline void
+g_critical (const gchar *format,
+ ...)
+{
+ va_list args;
+ va_start (args, format);
+ gsl_g_log ("**CRITICAL**", format, args);
+ va_end (args);
+}
+static inline void
+g_warning (const gchar *format,
+ ...)
+{
+ va_list args;
+ va_start (args, format);
+ gsl_g_log ("**WARNING**", format, args);
+ va_end (args);
+}
+static inline void
+g_print (const gchar *format,
+ ...)
+{
+ va_list args;
+ va_start (args, format);
+ gsl_g_print_fd (1, format, args);
+ va_end (args);
+}
+static inline void
+g_printerr (const gchar *format,
+ ...)
+{
+ va_list args;
+ va_start (args, format);
+ gsl_g_print_fd (2, format, args);
+ va_end (args);
+}
+typedef struct _GTrashStack GTrashStack;
+struct _GTrashStack
+{
+ GTrashStack *next;
+};
+static inline guint
+g_bit_storage (gulong number)
+{
+ register guint n_bits = 0;
+
+ do
+ {
+ n_bits++;
+ number >>= 1;
+ }
+ while (number);
+ return n_bits;
+}
+static inline void
+g_trash_stack_push (GTrashStack **stack_p,
+ gpointer data_p)
+{
+ GTrashStack *data = (GTrashStack *) data_p;
+
+ data->next = *stack_p;
+ *stack_p = data;
+}
+static inline gpointer
+g_trash_stack_pop (GTrashStack **stack_p)
+{
+ GTrashStack *data;
+
+ data = *stack_p;
+ if (data)
+ {
+ *stack_p = data->next;
+ /* NULLify private pointer here, most platforms store NULL as
+ * subsequent 0 bytes
+ */
+ data->next = NULL;
+ }
+
+ return data;
+}
+static inline gpointer
+g_trash_stack_peek (GTrashStack **stack_p)
+{
+ GTrashStack *data;
+
+ data = *stack_p;
+
+ return data;
+}
+static inline guint
+g_trash_stack_height (GTrashStack **stack_p)
+{
+ GTrashStack *data;
+ guint i = 0;
+
+ for (data = *stack_p; data; data = data->next)
+ i++;
+
+ return i;
+}
+
+
+/* --- GCC features --- */
+#if __GNUC__ >= 2 && __GNUC_MINOR__ > 95
+#define G_GNUC_PRINTF( format_idx, arg_idx ) \
+ __attribute__((format (printf, format_idx, arg_idx)))
+#define G_GNUC_SCANF( format_idx, arg_idx ) \
+ __attribute__((format (scanf, format_idx, arg_idx)))
+#define G_GNUC_FORMAT( arg_idx ) \
+ __attribute__((format_arg (arg_idx)))
+#define G_GNUC_NORETURN \
+ __attribute__((noreturn))
+#define G_GNUC_CONST \
+ __attribute__((const))
+#define G_GNUC_UNUSED \
+ __attribute__((unused))
+#define G_GNUC_NO_INSTRUMENT \
+ __attribute__((no_instrument_function))
+#else /* !__GNUC__ */
+#define G_GNUC_PRINTF( format_idx, arg_idx )
+#define G_GNUC_SCANF( format_idx, arg_idx )
+#define G_GNUC_FORMAT( arg_idx )
+#define G_GNUC_NORETURN
+#define G_GNUC_CONST
+#define G_GNUC_UNUSED
+#define G_GNUC_NO_INSTRUMENT
+#endif /* !__GNUC__ */
+
+
+
+/* --- GPollFD (for poll(2)) --- */
+#define G_IO_IN (0x0001 /* There is data to read */)
+#define G_IO_PRI (0x0002 /* There is urgent data to read */)
+#define G_IO_OUT (0x0004 /* Writing now will not block */)
+#define G_IO_ERR (0x0008 /* Error condition */)
+#define G_IO_HUP (0x0010 /* Hung up */)
+#define G_IO_NVAL (0x0020 /* Invalid request: fd not open */)
+typedef struct
+{
+ gint fd;
+ gushort events;
+ gushort revents;
+} GPollFD;
+
+
+
+/* --- functions --- */
+#define g_malloc gsl_g_malloc
+#define g_malloc0 gsl_g_malloc0
+#define g_realloc gsl_g_realloc
+#define g_free gsl_g_free
+#define g_strdup gsl_g_strdup
+#define g_strndup gsl_g_strndup
+#define g_memdup gsl_g_memdup
+#define g_strdup_printf gsl_g_strdup_printf
+#define g_strdup_vprintf gsl_g_strdup_vprintf
+#define g_strndup gsl_g_strndup
+#define g_strconcat gsl_g_strconcat
+#define g_usleep gsl_g_usleep
+#define g_strerror gsl_g_strerror
+#define g_convert gsl_g_convert
+#define g_direct_hash gsl_g_direct_hash
+#define g_direct_equal gsl_g_direct_equal
+#define g_str_equal gsl_g_str_equal
+#define g_str_hash gsl_g_str_hash
+#define g_strtod gsl_g_strtod
+#define g_stpcpy gsl_g_stpcpy
+#define g_strescape gsl_g_strescape
+#define g_get_current_dir gsl_g_get_current_dir
+#define g_path_is_absolute gsl_g_path_is_absolute
+#define g_printf_string_upper_bound gsl_g_printf_string_upper_bound
+
+gpointer g_malloc (gulong n_bytes);
+gpointer g_malloc0 (gulong n_bytes);
+gpointer g_realloc (gpointer mem,
+ gulong n_bytes);
+void g_free (gpointer mem);
+gpointer g_memdup (gconstpointer mem,
+ guint byte_size);
+gchar* g_strdup (const gchar *str);
+gchar* g_strndup (const gchar *str,
+ gsize n);
+gchar* g_strdup_printf (const gchar *format,
+ ...) G_GNUC_PRINTF (1, 2);
+gchar* g_strdup_vprintf (const gchar *format,
+ va_list args);
+gchar* g_strndup (const gchar *str,
+ gsize n);
+gchar* g_strconcat (const gchar *string1,
+ ...); /* NULL terminated */
+gchar* g_convert (const gchar *str,
+ gsize len, /* gssize */
+ const gchar *to_codeset,
+ const gchar *from_codeset,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ void **error); /* GError */
+void g_usleep(unsigned long usec);
+char* g_strerror(int e);
+guint g_direct_hash (gconstpointer v);
+gboolean g_direct_equal (gconstpointer v1, gconstpointer v2);
+gboolean g_str_equal (gconstpointer v1, gconstpointer v2);
+guint g_str_hash (gconstpointer key);
+gdouble g_strtod (const gchar *nptr, gchar **endptr);
+gsize g_printf_string_upper_bound (const gchar *format, va_list args);
+gchar * g_stpcpy (gchar *dest, const gchar *src);
+gchar * g_strescape (const gchar *source, const gchar *exceptions);
+gchar * g_get_current_dir (void);
+gboolean g_path_is_absolute (const gchar *file_name);
+
+
+
+/* --- function defines --- */
+#define g_new(struct_type, n_structs) \
+ ((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+#define g_new0(struct_type, n_structs) \
+ ((struct_type *) g_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+#define g_renew(struct_type, mem, n_structs) \
+ ((struct_type *) g_realloc ((mem), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+#define g_try_malloc malloc
+#define g_try_realloc realloc
+
+
+
+/* --- configure stuff!!! --- */
+#ifdef WORDS_BIGENDIAN
+#define G_BYTE_ORDER G_BIG_ENDIAN
+#else
+#define G_BYTE_ORDER G_LITTLE_ENDIAN
+#endif
+
+/* #define GLIB_HAVE_STPCPY 1 */
+/* Define G_VA_COPY() to do the right thing for copying va_list variables.
+ * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
+ */
+#if !defined (G_VA_COPY)
+# if defined (__GNUC__) && ( defined (__PPC__) || defined (__s390__) ) && (defined (_CALL_SYSV) || defined (_WIN32) || defined (__s390__) )
+# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
+# elif defined (G_VA_COPY_AS_ARRAY)
+# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list))
+# else /* va_list is a pointer */
+# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2))
+# endif /* va_list is a pointer */
+#endif /* !G_VA_COPY */
+
+
+
+
+/* subtract from biased_exponent to form base2 exponent (normal numbers) */
+typedef union _GDoubleIEEE754 GDoubleIEEE754;
+typedef union _GFloatIEEE754 GFloatIEEE754;
+#define G_IEEE754_FLOAT_BIAS (127)
+#define G_IEEE754_DOUBLE_BIAS (1023)
+/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
+#define G_LOG_2_BASE_10 (0.30102999566398119521)
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+union _GFloatIEEE754
+{
+ gfloat v_float;
+ struct {
+ guint mantissa : 23;
+ guint biased_exponent : 8;
+ guint sign : 1;
+ } mpn;
+};
+union _GDoubleIEEE754
+{
+ gdouble v_double;
+ struct {
+ guint mantissa_low : 32;
+ guint mantissa_high : 20;
+ guint biased_exponent : 11;
+ guint sign : 1;
+ } mpn;
+};
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+union _GFloatIEEE754
+{
+ gfloat v_float;
+ struct {
+ guint sign : 1;
+ guint biased_exponent : 8;
+ guint mantissa : 23;
+ } mpn;
+};
+union _GDoubleIEEE754
+{
+ gdouble v_double;
+ struct {
+ guint sign : 1;
+ guint biased_exponent : 11;
+ guint mantissa_high : 20;
+ guint mantissa_low : 32;
+ } mpn;
+};
+#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+#error unknown ENDIAN type
+#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+
+
+
+/* --- GHashTable --- */
+typedef struct _GHashTable GHashTable;
+typedef gboolean (*GHRFunc) (gpointer key,
+ gpointer value,
+ gpointer user_data);
+typedef void (*GHFunc) (gpointer key,
+ gpointer value,
+ gpointer user_data);
+typedef guint (*GHashFunc) (gconstpointer key);
+typedef gboolean (*GEqualFunc) (gconstpointer a,
+ gconstpointer b);
+typedef void (*GDestroyNotify) (gpointer data);
+#define g_hash_table_new gsl_g_hash_table_new
+#define g_hash_table_new_full gsl_g_hash_table_new_full
+#define g_hash_table_destroy gsl_g_hash_table_destroy
+#define g_hash_table_insert gsl_g_hash_table_insert
+#define g_hash_table_replace gsl_g_hash_table_replace
+#define g_hash_table_remove gsl_g_hash_table_remove
+#define g_hash_table_steal gsl_g_hash_table_steal
+#define g_hash_table_lookup gsl_g_hash_table_lookup
+#define g_hash_table_lookup_extended gsl_g_hash_table_lookup_extended
+#define g_hash_table_foreach gsl_g_hash_table_foreach
+#define g_hash_table_foreach_remove gsl_g_hash_table_foreach_remove
+#define g_hash_table_foreach_steal gsl_g_hash_table_foreach_steal
+#define g_hash_table_size gsl_g_hash_table_size
+GHashTable* g_hash_table_new (GHashFunc hash_func,
+ GEqualFunc key_equal_func);
+GHashTable* g_hash_table_new_full (GHashFunc hash_func,
+ GEqualFunc key_equal_func,
+ GDestroyNotify key_destroy_func,
+ GDestroyNotify value_destroy_func);
+void g_hash_table_destroy (GHashTable *hash_table);
+void g_hash_table_insert (GHashTable *hash_table,
+ gpointer key,
+ gpointer value);
+void g_hash_table_replace (GHashTable *hash_table,
+ gpointer key,
+ gpointer value);
+gboolean g_hash_table_remove (GHashTable *hash_table,
+ gconstpointer key);
+gboolean g_hash_table_steal (GHashTable *hash_table,
+ gconstpointer key);
+gpointer g_hash_table_lookup (GHashTable *hash_table,
+ gconstpointer key);
+gboolean g_hash_table_lookup_extended (GHashTable *hash_table,
+ gconstpointer lookup_key,
+ gpointer *orig_key,
+ gpointer *value);
+void g_hash_table_foreach (GHashTable *hash_table,
+ GHFunc func,
+ gpointer user_data);
+guint g_hash_table_foreach_remove (GHashTable *hash_table,
+ GHRFunc func,
+ gpointer user_data);
+guint g_hash_table_foreach_steal (GHashTable *hash_table,
+ GHRFunc func,
+ gpointer user_data);
+guint g_hash_table_size (GHashTable *hash_table);
+
+
+/* --- GScanner --- */
+typedef struct _GScanner GScanner;
+typedef struct _GScannerConfig GScannerConfig;
+typedef union _GTokenValue GTokenValue;
+typedef void (*GScannerMsgFunc) (GScanner *scanner,
+ gchar *message,
+ gint error);
+#define G_CSET_A_2_Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define G_CSET_a_2_z "abcdefghijklmnopqrstuvwxyz"
+#define G_CSET_DIGITS "0123456789"
+#define G_CSET_LATINC "\300\301\302\303\304\305\306"\
+ "\307\310\311\312\313\314\315\316\317\320"\
+ "\321\322\323\324\325\326"\
+ "\330\331\332\333\334\335\336"
+#define G_CSET_LATINS "\337\340\341\342\343\344\345\346"\
+ "\347\350\351\352\353\354\355\356\357\360"\
+ "\361\362\363\364\365\366"\
+ "\370\371\372\373\374\375\376\377"
+typedef enum
+{
+ G_ERR_UNKNOWN,
+ G_ERR_UNEXP_EOF,
+ G_ERR_UNEXP_EOF_IN_STRING,
+ G_ERR_UNEXP_EOF_IN_COMMENT,
+ G_ERR_NON_DIGIT_IN_CONST,
+ G_ERR_DIGIT_RADIX,
+ G_ERR_FLOAT_RADIX,
+ G_ERR_FLOAT_MALFORMED
+} GErrorType;
+typedef enum
+{
+ G_TOKEN_EOF = 0,
+
+ G_TOKEN_LEFT_PAREN = '(',
+ G_TOKEN_RIGHT_PAREN = ')',
+ G_TOKEN_LEFT_CURLY = '{',
+ G_TOKEN_RIGHT_CURLY = '}',
+ G_TOKEN_LEFT_BRACE = '[',
+ G_TOKEN_RIGHT_BRACE = ']',
+ G_TOKEN_EQUAL_SIGN = '=',
+ G_TOKEN_COMMA = ',',
+
+ G_TOKEN_NONE = 256,
+
+ G_TOKEN_ERROR,
+
+ G_TOKEN_CHAR,
+ G_TOKEN_BINARY,
+ G_TOKEN_OCTAL,
+ G_TOKEN_INT,
+ G_TOKEN_HEX,
+ G_TOKEN_FLOAT,
+ G_TOKEN_STRING,
+
+ G_TOKEN_SYMBOL,
+ G_TOKEN_IDENTIFIER,
+ G_TOKEN_IDENTIFIER_NULL,
+
+ G_TOKEN_COMMENT_SINGLE,
+ G_TOKEN_COMMENT_MULTI,
+ G_TOKEN_LAST
+} GTokenType;
+union _GTokenValue
+{
+ gpointer v_symbol;
+ gchar *v_identifier;
+ gulong v_binary;
+ gulong v_octal;
+ gulong v_int;
+ gdouble v_float;
+ gulong v_hex;
+ gchar *v_string;
+ gchar *v_comment;
+ guchar v_char;
+ guint v_error;
+};
+struct _GScannerConfig
+{
+ const gchar *cset_skip_characters; /* default: " \t\n" */
+ const gchar *cset_identifier_first;
+ const gchar *cset_identifier_nth;
+ const gchar *cpair_comment_single; /* default: "#\n" */
+ guint case_sensitive : 1;
+ guint skip_comment_multi : 1; /* C like comment */
+ guint skip_comment_single : 1; /* single line comment */
+ guint scan_comment_multi : 1; /* scan multi line comments? */
+ guint scan_identifier : 1;
+ guint scan_identifier_1char : 1;
+ guint scan_identifier_NULL : 1;
+ guint scan_symbols : 1;
+ guint scan_binary : 1;
+ guint scan_octal : 1;
+ guint scan_float : 1;
+ guint scan_hex : 1; /* `0x0ff0' */
+ guint scan_hex_dollar : 1; /* `$0ff0' */
+ guint scan_string_sq : 1; /* string: 'anything' */
+ guint scan_string_dq : 1; /* string: "\\-escapes!\n" */
+ guint numbers_2_int : 1; /* bin, octal, hex => int */
+ guint int_2_float : 1; /* int => G_TOKEN_FLOAT? */
+ guint identifier_2_string : 1;
+ guint char_2_token : 1; /* return G_TOKEN_CHAR? */
+ guint symbol_2_token : 1;
+ guint scope_0_fallback : 1; /* try scope 0 on lookups? */
+};
+struct _GScanner
+{
+ gpointer user_data;
+ guint max_parse_errors;
+ guint parse_errors;
+ const gchar *input_name;
+ /* GData *qdata; */
+ GScannerConfig *config;
+ GTokenType token;
+ GTokenValue value;
+ guint line;
+ guint position;
+ GTokenType next_token;
+ GTokenValue next_value;
+ guint next_line;
+ guint next_position;
+ GHashTable *symbol_table;
+ gint input_fd;
+ const gchar *text;
+ const gchar *text_end;
+ gchar *buffer;
+ guint scope_id;
+ GScannerMsgFunc msg_handler;
+};
+#define g_scanner_new gsl_g_scanner_new
+#define g_scanner_destroy gsl_g_scanner_destroy
+#define g_scanner_input_file gsl_g_scanner_input_file
+#define g_scanner_sync_file_offset gsl_g_scanner_sync_file_offset
+#define g_scanner_input_text gsl_g_scanner_input_text
+#define g_scanner_get_next_token gsl_g_scanner_get_next_token
+#define g_scanner_peek_next_token gsl_g_scanner_peek_next_token
+#define g_scanner_cur_token gsl_g_scanner_cur_token
+#define g_scanner_cur_value gsl_g_scanner_cur_value
+#define g_scanner_cur_line gsl_g_scanner_cur_line
+#define g_scanner_cur_position gsl_g_scanner_cur_position
+#define g_scanner_eof gsl_g_scanner_eof
+#define g_scanner_set_scope gsl_g_scanner_set_scope
+#define g_scanner_scope_add_symbol gsl_g_scanner_scope_add_symbol
+#define g_scanner_scope_remove_symbol gsl_g_scanner_scope_remove_symbol
+#define g_scanner_scope_lookup_symbol gsl_g_scanner_scope_lookup_symbol
+#define g_scanner_scope_foreach_symbol gsl_g_scanner_scope_foreach_symbol
+#define g_scanner_lookup_symbol gsl_g_scanner_lookup_symbol
+#define g_scanner_unexp_token gsl_g_scanner_unexp_token
+#define g_scanner_error gsl_g_scanner_error
+#define g_scanner_warn gsl_g_scanner_warn
+GScanner* g_scanner_new (const GScannerConfig *config_templ);
+void g_scanner_destroy (GScanner *scanner);
+void g_scanner_input_file (GScanner *scanner,
+ gint input_fd);
+void g_scanner_sync_file_offset (GScanner *scanner);
+void g_scanner_input_text (GScanner *scanner,
+ const gchar *text,
+ guint text_len);
+GTokenType g_scanner_get_next_token (GScanner *scanner);
+GTokenType g_scanner_peek_next_token (GScanner *scanner);
+GTokenType g_scanner_cur_token (GScanner *scanner);
+GTokenValue g_scanner_cur_value (GScanner *scanner);
+guint g_scanner_cur_line (GScanner *scanner);
+guint g_scanner_cur_position (GScanner *scanner);
+gboolean g_scanner_eof (GScanner *scanner);
+guint g_scanner_set_scope (GScanner *scanner,
+ guint scope_id);
+void g_scanner_scope_add_symbol (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol,
+ gpointer value);
+void g_scanner_scope_remove_symbol (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol);
+gpointer g_scanner_scope_lookup_symbol (GScanner *scanner,
+ guint scope_id,
+ const gchar *symbol);
+void g_scanner_scope_foreach_symbol (GScanner *scanner,
+ guint scope_id,
+ GHFunc func,
+ gpointer user_data);
+gpointer g_scanner_lookup_symbol (GScanner *scanner,
+ const gchar *symbol);
+void g_scanner_unexp_token (GScanner *scanner,
+ GTokenType expected_token,
+ const gchar *identifier_spec,
+ const gchar *symbol_spec,
+ const gchar *symbol_name,
+ const gchar *message,
+ gint is_error);
+void g_scanner_error (GScanner *scanner,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (2,3);
+void g_scanner_warn (GScanner *scanner,
+ const gchar *format,
+ ...) G_GNUC_PRINTF (2,3);
+#define g_scanner_add_symbol( scanner, symbol, value ) G_STMT_START { \
+ g_scanner_scope_add_symbol ((scanner), 0, (symbol), (value)); \
+} G_STMT_END
+#define g_scanner_remove_symbol( scanner, symbol ) G_STMT_START { \
+ g_scanner_scope_remove_symbol ((scanner), 0, (symbol)); \
+} G_STMT_END
+#define g_scanner_foreach_symbol( scanner, func, data ) G_STMT_START { \
+ g_scanner_scope_foreach_symbol ((scanner), 0, (func), (data)); \
+} G_STMT_END
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#include <gsl/gslconfig.h>
+#if GSL_USE_ARTS_THREADS
+#include <gsl/gslartsthreads.h>
+#endif
+
+/* if inline is defined in C++ mode, it can cause a lot of grief with C++ */
+/* header files so we need to undefine it here again */
+
+#if defined(__cplusplus) && defined(inline)
+#undef inline
+#endif
+
+#endif /* __GSL_GLIB_H__ */ /* vim: set ts=8 sw=2 sts=2: */
+
diff --git a/flow/gsl/gslglibhash.cc b/flow/gsl/gslglibhash.cc
new file mode 100644
index 0000000..a8c82b0
--- /dev/null
+++ b/flow/gsl/gslglibhash.cc
@@ -0,0 +1,151 @@
+/* GSL Glib Hashtable implementation
+ * Copyright (C) 2001 Stefan Westerfeld
+ *
+ * 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslglib.h"
+#include <list>
+#include <map>
+
+using std::list;
+using std::pair;
+using std::map;
+
+/*
+ * this uses a map of list to emulate somewhat hashtable like behaviour - note
+ * that insert and remove are O(log N) due to the use of a map, instead of
+ * ~ O(1) which they would be for a "real" hashtable
+ */
+struct _GHashTable
+{
+ GHashFunc hashFunc;
+ GEqualFunc equalFunc;
+ map<guint /*hashvalue for key*/, list< pair<gpointer,gpointer> > /*(key,value) pairs*/> nodes;
+
+ /*Con*/ _GHashTable (GHashFunc hf, GEqualFunc ef) :
+ hashFunc(hf), equalFunc(ef) { }
+};
+
+
+GHashTable* g_hash_table_new (GHashFunc hash_func,
+ GEqualFunc key_equal_func)
+{
+ return new GHashTable (hash_func?hash_func:g_direct_hash, key_equal_func?key_equal_func:g_direct_equal);
+}
+void g_hash_table_destroy (GHashTable *hash_table)
+{
+ g_return_if_fail (hash_table != NULL);
+
+ delete hash_table;
+}
+void g_hash_table_insert (GHashTable *hash_table,
+ gpointer key,
+ gpointer value)
+{
+ g_return_if_fail (hash_table != NULL);
+ guint hashvalue = hash_table->hashFunc (key);
+
+ list< pair<gpointer,gpointer> >& bucket = hash_table->nodes[hashvalue];
+ list< pair<gpointer,gpointer> >::iterator i;
+
+ for (i = bucket.begin(); i != bucket.end(); i++)
+ {
+ if (hash_table->equalFunc(i->first, key))
+ {
+ if (value || TRUE)
+ {
+ i->second = value; /* overwrite old hash value */
+ return;
+ }
+ else
+ {
+ bucket.erase(i); /* remove value */
+
+ if (bucket.empty()) /* remove bucket if this was the only value */
+ hash_table->nodes.erase (hashvalue);
+ return;
+ }
+ }
+ }
+
+ if (value)
+ hash_table->nodes[hashvalue].push_back(std::make_pair (key, value));
+}
+
+gpointer g_hash_table_lookup (GHashTable *hash_table,
+ gconstpointer key)
+{
+ g_return_val_if_fail (hash_table != NULL, NULL);
+
+ guint hashvalue = hash_table->hashFunc (key);
+
+ list< pair<gpointer,gpointer> >& bucket = hash_table->nodes[hashvalue];
+ list< pair<gpointer,gpointer> >::iterator i;
+
+ for (i = bucket.begin(); i != bucket.end(); i++)
+ {
+ if (hash_table->equalFunc(i->first, key))
+ return i->second;
+ }
+
+ return 0;
+}
+gboolean g_hash_table_remove (GHashTable *hash_table,
+ gconstpointer key)
+{
+ g_return_val_if_fail (hash_table != NULL, FALSE);
+
+ guint hashvalue = hash_table->hashFunc (key);
+
+ list< pair<gpointer,gpointer> >& bucket = hash_table->nodes[hashvalue];
+ list< pair<gpointer,gpointer> >::iterator i;
+
+ for (i = bucket.begin(); i != bucket.end(); i++)
+ {
+ if (hash_table->equalFunc(i->first, key))
+ {
+ bucket.erase (i);
+
+ if (bucket.empty()) /* remove bucket if this was the only value */
+ hash_table->nodes.erase (hashvalue);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void g_hash_table_foreach (GHashTable *hash_table,
+ GHFunc func,
+ gpointer user_data)
+{
+ map<guint, list< pair<gpointer,gpointer> > >::iterator bi;
+
+ g_return_if_fail (hash_table != NULL);
+
+ /* for all buckets */
+ for (bi = hash_table->nodes.begin (); bi != hash_table->nodes.end (); bi++)
+ {
+ list< pair<gpointer,gpointer> >& bucket = bi->second;
+ list< pair<gpointer,gpointer> >::iterator i;
+
+ /* for each element in the current bucket */
+ for (i = bucket.begin(); i != bucket.end(); i++)
+ func ((void*) i->first, (void*) i->second, user_data);
+ }
+}
+
+/* vim:set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslglibhashtest.cc b/flow/gsl/gslglibhashtest.cc
new file mode 100644
index 0000000..da50c10
--- /dev/null
+++ b/flow/gsl/gslglibhashtest.cc
@@ -0,0 +1,123 @@
+/* GSL Glib Hashtable test
+ * Copyright (C) 2001 Stefan Westerfeld
+ *
+ * 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsldefs.h"
+#include <string.h>
+
+/* cause hashvalue collisions for the test */
+guint g_str_narrow_hash (gconstpointer key) {
+ return g_str_hash (key) & 15;
+}
+
+struct Test {
+ char *key;
+ char *value;
+ int count;
+} test[50];
+
+void print_func (gpointer key, gpointer value, gpointer user_data) {
+#if 0 /* <- enable to get printing of some entries */
+ g_print ("%s: %s = %s\n", user_data, key, value);
+#endif
+}
+
+void fail_func (gpointer key, gpointer value, gpointer user_data) {
+ g_error ("*this* should not have happened");
+}
+
+
+void count_func (gpointer key, gpointer value, gpointer user_data) {
+ g_assert (value != NULL && key != NULL);
+ for(int i=0;i<50;i++)
+ {
+ if(strcmp((char *)key, test[i].key) == 0)
+ {
+ g_assert(strcmp((char *)value, test[i].value) == 0);
+ test[i].count++;
+ }
+ }
+}
+
+
+int main()
+{
+ GHashTable *t = g_hash_table_new (g_str_narrow_hash, g_str_equal);
+
+ for(int i=0;i<50;i++)
+ {
+ test[i].key = g_strdup_printf ("key-%d",i);
+ test[i].value = g_strdup_printf ("value-%d",i);
+ test[i].count = 0;
+
+ g_hash_table_insert (t, test[i].key, test[i].value);
+ }
+
+ g_assert (strcmp ((char *)g_hash_table_lookup (t, "key-24"), "value-24") == 0);
+ g_hash_table_foreach(t, print_func, g_strdup("all-keys-50"));
+ g_hash_table_foreach(t, count_func, 0);
+
+ for(int i=0;i<50;i++)
+ {
+ /* each key should have been found once in the hash table now */
+ g_assert(test[i].count == 1);
+ }
+
+ for(int i=0;i<25;i++)
+ {
+ test[i].key = g_strdup_printf ("key-%d",i);
+ test[i].value = g_strdup_printf ("another-value-%d",i);
+
+ g_hash_table_insert (t, test[i].key, test[i].value);
+ }
+
+ g_assert (strcmp ((char *)g_hash_table_lookup (t, "key-24"), "another-value-24") == 0);
+ g_hash_table_foreach(t, print_func, g_strdup("all-keys-new-25-old-25"));
+ g_hash_table_foreach(t, count_func, 0);
+
+ for(int i=0;i<50;i++)
+ {
+ /* each key should have been found once (with the new value) */
+ g_assert(test[i].count == 2);
+ }
+
+ for(int i=0;i<50;i+=2)
+ {
+ /* remove even valued keys */
+ g_hash_table_remove (t, test[i].key);
+ }
+
+ g_assert (g_hash_table_lookup (t, "key-24") == 0);
+ g_hash_table_foreach(t, print_func, g_strdup("only-odd-keys-25"));
+ g_hash_table_foreach(t, count_func, 0);
+
+ for(int i=0;i<50;i++)
+ {
+ /* only odd keys should be there */
+ g_assert((test[i].count == 3 && (i & 1))
+ || (test[i].count == 2 && !(i & 1)));
+ }
+
+ for(int i=1;i<50;i+=2)
+ {
+ /* remove odd valued keys */
+ g_hash_table_remove (t, g_strdup(test[i].key));
+ }
+
+ g_hash_table_foreach(t, fail_func, 0);
+ return 0;
+}
diff --git a/flow/gsl/gslieee754.h b/flow/gsl/gslieee754.h
new file mode 100644
index 0000000..48ea0ee
--- /dev/null
+++ b/flow/gsl/gslieee754.h
@@ -0,0 +1,246 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 1999, 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_IEEE754_H__
+#define __GSL_IEEE754_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* IEEE 754 single precision floating point layout:
+ * 31 30 23 22 0
+ * +--------+---------------+---------------+
+ * | s 1bit | e[30:23] 8bit | f[22:0] 23bit |
+ * +--------+---------------+---------------+
+ * B0------------------->B1------->B2-->B3-->
+ *
+ * IEEE 754 double precision floating point layout:
+ * 63 62 52 51 32 31 0
+ * +--------+----------------+----------------+ +---------------+
+ * | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit |
+ * +--------+----------------+----------------+ +---------------+
+ * B0--------------->B1---------->B2--->B3----> B4->B5->B6->B7->
+ */
+
+/* floating point type related constants */
+#define GSL_FLOAT_BIAS (127)
+#define GSL_FLOAT_MAX_NORMAL (3.40282347e+38) /* 7f7fffff */
+#define GSL_FLOAT_MIN_NORMAL (1.17549435e-38) /* 00800000 */
+#define GSL_FLOAT_MAX_SUBNORMAL (1.17549421e-38) /* 007fffff */
+#define GSL_FLOAT_MIN_SUBNORMAL (1.40129846e-45) /* 00000001 */
+#define GSL_DOUBLE_BIAS (1023)
+#define GSL_DOUBLE_MAX_NORMAL (1.7976931348623157e+308) /* 7fefffff ffffffff */
+#define GSL_DOUBLE_MIN_NORMAL (2.2250738585072014e-308) /* 00100000 00000000 */
+#define GSL_DOUBLE_MAX_SUBNORMAL (2.2250738585072009e-308) /* 000fffff ffffffff */
+#define GSL_DOUBLE_MIN_SUBNORMAL (4.9406564584124654e-324) /* 00000000 00000001 */
+#define GSL_DOUBLE_INF (_gsl_dinf_union.d)
+#define GSL_DOUBLE_NAN (_gsl_dnan_union.d)
+#define GSL_FLOAT_INF (_gsl_finf_union.f)
+#define GSL_FLOAT_NAN (_gsl_fnan_union.f)
+
+/* multiply with base2 exponent to get base10 exponent (for nomal numbers) */
+#define GSL_LOG_2_BASE_10 (0.30102999566398119521)
+
+/* the following macros work only on variables
+ * and evaluate arguments multiple times
+ */
+
+/* single precision value checks */
+#define GSL_FLOAT_IS_ZERO(f) ((f) == 0.0) /* compiler knows this one */
+#define GSL_FLOAT_IS_NORMAL(f) (GSL_FLOAT_PARTS (f).mpn.biased_exponent > 0 && \
+ GSL_FLOAT_PARTS (f).mpn.biased_exponent < 255)
+#define GSL_FLOAT_IS_SUBNORMAL(f) (GSL_FLOAT_PARTS (f).mpn.biased_exponent == 0 && \
+ GSL_FLOAT_PARTS (f).mpn.mantissa != 0)
+#define GSL_FLOAT_IS_NANINF(f) (GSL_FLOAT_PARTS (f).mpn.biased_exponent == 255)
+#define GSL_FLOAT_IS_NAN(f) (GSL_FLOAT_IS_NANINF (f) && GSL_FLOAT_PARTS (f).mpn.mantissa != 0)
+#define GSL_FLOAT_IS_INF(f) (GSL_FLOAT_IS_NANINF (f) && GSL_FLOAT_PARTS (f).mpn.mantissa == 0)
+#define GSL_FLOAT_IS_INF_POSITIVE(f) (GSL_FLOAT_IS_INF (f) && GSL_FLOAT_PARTS (f).mpn.sign == 0)
+#define GSL_FLOAT_IS_INF_NEGATIVE(f) (GSL_FLOAT_IS_INF (f) && GSL_FLOAT_PARTS (f).mpn.sign == 1)
+#define GSL_FLOAT_SIGN(f) (GSL_FLOAT_PARTS (f).mpn.sign)
+
+/* double precision value checks */
+#define GSL_DOUBLE_IS_ZERO(d) ((d) == 0.0) /* compiler knows this one */
+#define GSL_DOUBLE_IS_NORMAL(d) (GSL_DOUBLE_PARTS (d).mpn.biased_exponent > 0 && \
+ GSL_DOUBLE_PARTS (d).mpn.biased_exponent < 2047)
+#define GSL_DOUBLE_IS_SUBNORMAL(d) (GSL_DOUBLE_PARTS (d).mpn.biased_exponent == 0 && \
+ (GSL_DOUBLE_PARTS (d).mpn.mantissa_low != 0 || \
+ GSL_DOUBLE_PARTS (d).mpn.mantissa_high != 0))
+#define GSL_DOUBLE_IS_NANINF(d) (GSL_DOUBLE_PARTS (d).mpn.biased_exponent == 2047)
+#define GSL_DOUBLE_IS_NAN(d) (GSL_DOUBLE_IS_NANINF (d) && \
+ (GSL_DOUBLE_PARTS (d).mpn.mantissa_low != 0 || \
+ GSL_DOUBLE_PARTS (d).mpn.mantissa_high != 0))
+#define GSL_DOUBLE_IS_INF(d) (GSL_DOUBLE_IS_NANINF (d) && \
+ GSL_DOUBLE_PARTS (d).mpn.mantissa_low == 0 && \
+ GSL_DOUBLE_PARTS (d).mpn.mantissa_high == 0)
+#define GSL_DOUBLE_IS_INF_POSITIVE(d) (GSL_DOUBLE_IS_INF (d) && GSL_DOUBLE_PARTS (d).mpn.sign == 0)
+#define GSL_DOUBLE_IS_INF_NEGATIVE(d) (GSL_DOUBLE_IS_INF (d) && GSL_DOUBLE_PARTS (d).mpn.sign == 1)
+#define GSL_DOUBLE_SIGN(d) (GSL_DOUBLE_PARTS (d).mpn.sign)
+
+/* get structured parts of floating point numbers */
+#define GSL_FLOAT_PARTS(f) (*((GslFloatIEEE754*) &(f)))
+#define GSL_DOUBLE_PARTS(d) (*((GslDoubleIEEE754*) &(d)))
+
+/* --- rounding --- */
+typedef unsigned short int GslFpuState;
+#if defined (__i386__) && defined (__GNUC__)
+/* setting/restoring rounding mode shouldn't actually
+ * be necessary as round-to-nearest is the hardware
+ * default (can be checked with gsl_fpu_okround()).
+ */
+static inline void gsl_fpu_setround (GslFpuState *cw);
+static inline int gsl_fpu_okround (void);
+static inline void gsl_fpu_restore (GslFpuState cv);
+static inline int gsl_ftoi /* nearest */ (register float f) G_GNUC_CONST;
+static inline int gsl_dtoi /* nearest */ (register double f) G_GNUC_CONST;
+/* fallbacks for the !386 case are below */
+#endif
+
+
+/* --- implementation bits --- */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+typedef union
+{
+ float v_float;
+ struct {
+ unsigned int mantissa : 23;
+ unsigned int biased_exponent : 8;
+ unsigned int sign : 1;
+ } mpn;
+} GslFloatIEEE754;
+typedef union
+{
+ double v_double;
+ struct {
+ unsigned int mantissa_low : 32;
+ unsigned int mantissa_high : 20;
+ unsigned int biased_exponent : 11;
+ unsigned int sign : 1;
+ } mpn;
+} GslDoubleIEEE754;
+#define _GSL_DOUBLE_INF_BYTES { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f }
+#define _GSL_DOUBLE_NAN_BYTES { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f }
+#define _GSL_FLOAT_INF_BYTES { 0x00, 0x00, 0x80, 0x7f }
+#define _GSL_FLOAT_NAN_BYTES { 0x00, 0x00, 0xc0, 0x7f }
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+typedef union
+{
+ float v_float;
+ struct {
+ unsigned int sign : 1;
+ unsigned int biased_exponent : 8;
+ unsigned int mantissa : 23;
+ } mpn;
+} GslFloatIEEE754;
+typedef union
+{
+ double v_double;
+ struct {
+ unsigned int sign : 1;
+ unsigned int biased_exponent : 11;
+ unsigned int mantissa_high : 20;
+ unsigned int mantissa_low : 32;
+ } mpn;
+} GslDoubleIEEE754;
+#define _GSL_DOUBLE_INF_BYTES { 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+#define _GSL_DOUBLE_NAN_BYTES { 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+#define _GSL_FLOAT_INF_BYTES { 0x7f, 0x80, 0x00, 0x00 }
+#define _GSL_FLOAT_NAN_BYTES { 0x7f, 0xc0, 0x00, 0x00 }
+#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+#error unknown ENDIAN type
+#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+
+static const union { unsigned char c[8]; double d; } _gsl_dnan_union = { _GSL_DOUBLE_NAN_BYTES };
+static const union { unsigned char c[8]; double d; } _gsl_dinf_union = { _GSL_DOUBLE_INF_BYTES };
+static const union { unsigned char c[4]; float f; } _gsl_fnan_union = { _GSL_FLOAT_NAN_BYTES };
+static const union { unsigned char c[4]; float f; } _gsl_finf_union = { _GSL_FLOAT_INF_BYTES };
+
+#if defined (__i386__) && defined (__GNUC__)
+static inline void
+gsl_fpu_setround (GslFpuState *cw)
+{
+ GslFpuState cv;
+
+ __asm__ ("fnstcw %0"
+ : "=m" (*&cv));
+ *cw = cv;
+ cv &= ~0x0c00;
+ __asm__ ("fldcw %0"
+ :
+ : "m" (*&cv));
+}
+static inline int
+gsl_fpu_okround (void)
+{
+ GslFpuState cv;
+
+ __asm__ ("fnstcw %0"
+ : "=m" (*&cv));
+ return !(cv & 0x0c00);
+}
+static inline void
+gsl_fpu_restore (GslFpuState cv)
+{
+ __asm__ ("fldcw %0"
+ :
+ : "m" (*&cv));
+}
+static inline int G_GNUC_CONST
+gsl_ftoi (register float f)
+{
+ int r;
+
+ __asm__ ("fistl %0"
+ : "=m" (r)
+ : "t" (f));
+ return r;
+}
+static inline int G_GNUC_CONST
+gsl_dtoi (register double f)
+{
+ int r;
+
+ __asm__ ("fistl %0"
+ : "=m" (r)
+ : "t" (f));
+ return r;
+}
+#else /* !386 */
+# define gsl_fpu_setround(p) ((void) (p));
+# define gsl_fpu_okround() (1)
+# define gsl_fpu_restore(x) /* nop */
+static inline int G_GNUC_CONST
+gsl_ftoi (register float v)
+{
+ return v < -0.0 ? v - 0.5 : v + 0.5;
+}
+static inline int G_GNUC_CONST
+gsl_dtoi (register double v)
+{
+ return v < -0.0 ? v - 0.5 : v + 0.5;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_IEEE754_H__ */ /* vim: set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslincluder.c b/flow/gsl/gslincluder.c
new file mode 100644
index 0000000..4ed4e85
--- /dev/null
+++ b/flow/gsl/gslincluder.c
@@ -0,0 +1,13420 @@
+/* GSL - Generic Sound Layer
+ *
+ * This file 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 Library General Public License for more details.
+ */
+
+#if 0
+/* script, used to create this file's contents:
+ */
+{
+ my $first_case = 0;
+ my $last_case = 1024;
+ my $i;
+
+ print "#define GSL_INCLUDER_MAKE_FUNC(name,case) GSL_INCLUDER_CONCAT3 (name, __, case)\n";
+ print "#define GSL_INCLUDER_CONCAT3(x,y,z) x ## y ## z\n";
+ print "#define GSL_INCLUDER_FUNC GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, GSL_INCLUDER_CASE)\n";
+ print "#ifndef GSL_INCLUDER_REJECT\n";
+ print "#define GSL_INCLUDER_REJECT(icase) 0\n";
+ print "#endif\n";
+ print "\n";
+ print "/* check range: $first_case .. $last_case */\n";
+ print "#if (GSL_INCLUDER_FIRST_CASE < $first_case)\n";
+ print "#error GSL_INCLUDER_FIRST_CASE < $first_case is not supported\n";
+ print "#endif\n";
+ print "#if (GSL_INCLUDER_LAST_CASE > $last_case)\n";
+ print "#error GSL_INCLUDER_LAST_CASE > $last_case is not supported\n";
+ print "#endif\n";
+ print "\n";
+ for ($i = $first_case; $i <= $last_case; $i++)
+ {
+ print "/* $i */\n";
+ print "#if (($i >= GSL_INCLUDER_FIRST_CASE) && ($i <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT ($i)))\n";
+ print "#define GSL_INCLUDER_CASE $i\n";
+ print "#include GSL_INCLUDER_FILE\n";
+ print "#undef GSL_INCLUDER_CASE\n";
+ print "#endif\n";
+ }
+ print "\n";
+ print "GSL_INCLUDER_TABLE = {\n";
+ for ($i = $first_case; $i <= $last_case; $i++)
+ {
+ print "#if (($i >= GSL_INCLUDER_FIRST_CASE) && ($i <= GSL_INCLUDER_LAST_CASE))\n";
+ print "#if (GSL_INCLUDER_REJECT ($i))\n";
+ print " NULL,\n";
+ print "#else\n";
+ print " GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, $i),\n";
+ print "#endif\n";
+ print "#endif\n";
+ }
+ print "};\n";
+ print "\n";
+ print "#undef GSL_INCLUDER_REJECT\n";
+ print "#undef GSL_INCLUDER_FUNC\n";
+ print "#undef GSL_INCLUDER_CONCAT3\n";
+ print "#undef GSL_INCLUDER_MAKE_FUNC\n";
+ print "#undef GSL_INCLUDER_FIRST_CASE\n";
+ print "#undef GSL_INCLUDER_LAST_CASE\n";
+ print "#undef GSL_INCLUDER_NAME\n";
+ print "#undef GSL_INCLUDER_TABLE\n";
+ print "#undef GSL_INCLUDER_FILE\n";
+}
+#endif
+
+
+#define GSL_INCLUDER_MAKE_FUNC(name,case) GSL_INCLUDER_CONCAT3 (name, __, case)
+#define GSL_INCLUDER_CONCAT3(x,y,z) x ## y ## z
+#define GSL_INCLUDER_FUNC GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, GSL_INCLUDER_CASE)
+#ifndef GSL_INCLUDER_REJECT
+#define GSL_INCLUDER_REJECT(icase) 0
+#endif
+
+/* check range: 0 .. 1024 */
+#if (GSL_INCLUDER_FIRST_CASE < 0)
+#error GSL_INCLUDER_FIRST_CASE < 0 is not supported
+#endif
+#if (GSL_INCLUDER_LAST_CASE > 1024)
+#error GSL_INCLUDER_LAST_CASE > 1024 is not supported
+#endif
+
+/* 0 */
+#if ((0 >= GSL_INCLUDER_FIRST_CASE) && (0 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (0)))
+#define GSL_INCLUDER_CASE 0
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1 */
+#if ((1 >= GSL_INCLUDER_FIRST_CASE) && (1 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1)))
+#define GSL_INCLUDER_CASE 1
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 2 */
+#if ((2 >= GSL_INCLUDER_FIRST_CASE) && (2 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (2)))
+#define GSL_INCLUDER_CASE 2
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 3 */
+#if ((3 >= GSL_INCLUDER_FIRST_CASE) && (3 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (3)))
+#define GSL_INCLUDER_CASE 3
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 4 */
+#if ((4 >= GSL_INCLUDER_FIRST_CASE) && (4 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (4)))
+#define GSL_INCLUDER_CASE 4
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 5 */
+#if ((5 >= GSL_INCLUDER_FIRST_CASE) && (5 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (5)))
+#define GSL_INCLUDER_CASE 5
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 6 */
+#if ((6 >= GSL_INCLUDER_FIRST_CASE) && (6 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (6)))
+#define GSL_INCLUDER_CASE 6
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 7 */
+#if ((7 >= GSL_INCLUDER_FIRST_CASE) && (7 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (7)))
+#define GSL_INCLUDER_CASE 7
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 8 */
+#if ((8 >= GSL_INCLUDER_FIRST_CASE) && (8 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (8)))
+#define GSL_INCLUDER_CASE 8
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 9 */
+#if ((9 >= GSL_INCLUDER_FIRST_CASE) && (9 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (9)))
+#define GSL_INCLUDER_CASE 9
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 10 */
+#if ((10 >= GSL_INCLUDER_FIRST_CASE) && (10 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (10)))
+#define GSL_INCLUDER_CASE 10
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 11 */
+#if ((11 >= GSL_INCLUDER_FIRST_CASE) && (11 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (11)))
+#define GSL_INCLUDER_CASE 11
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 12 */
+#if ((12 >= GSL_INCLUDER_FIRST_CASE) && (12 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (12)))
+#define GSL_INCLUDER_CASE 12
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 13 */
+#if ((13 >= GSL_INCLUDER_FIRST_CASE) && (13 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (13)))
+#define GSL_INCLUDER_CASE 13
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 14 */
+#if ((14 >= GSL_INCLUDER_FIRST_CASE) && (14 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (14)))
+#define GSL_INCLUDER_CASE 14
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 15 */
+#if ((15 >= GSL_INCLUDER_FIRST_CASE) && (15 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (15)))
+#define GSL_INCLUDER_CASE 15
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 16 */
+#if ((16 >= GSL_INCLUDER_FIRST_CASE) && (16 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (16)))
+#define GSL_INCLUDER_CASE 16
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 17 */
+#if ((17 >= GSL_INCLUDER_FIRST_CASE) && (17 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (17)))
+#define GSL_INCLUDER_CASE 17
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 18 */
+#if ((18 >= GSL_INCLUDER_FIRST_CASE) && (18 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (18)))
+#define GSL_INCLUDER_CASE 18
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 19 */
+#if ((19 >= GSL_INCLUDER_FIRST_CASE) && (19 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (19)))
+#define GSL_INCLUDER_CASE 19
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 20 */
+#if ((20 >= GSL_INCLUDER_FIRST_CASE) && (20 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (20)))
+#define GSL_INCLUDER_CASE 20
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 21 */
+#if ((21 >= GSL_INCLUDER_FIRST_CASE) && (21 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (21)))
+#define GSL_INCLUDER_CASE 21
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 22 */
+#if ((22 >= GSL_INCLUDER_FIRST_CASE) && (22 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (22)))
+#define GSL_INCLUDER_CASE 22
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 23 */
+#if ((23 >= GSL_INCLUDER_FIRST_CASE) && (23 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (23)))
+#define GSL_INCLUDER_CASE 23
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 24 */
+#if ((24 >= GSL_INCLUDER_FIRST_CASE) && (24 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (24)))
+#define GSL_INCLUDER_CASE 24
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 25 */
+#if ((25 >= GSL_INCLUDER_FIRST_CASE) && (25 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (25)))
+#define GSL_INCLUDER_CASE 25
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 26 */
+#if ((26 >= GSL_INCLUDER_FIRST_CASE) && (26 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (26)))
+#define GSL_INCLUDER_CASE 26
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 27 */
+#if ((27 >= GSL_INCLUDER_FIRST_CASE) && (27 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (27)))
+#define GSL_INCLUDER_CASE 27
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 28 */
+#if ((28 >= GSL_INCLUDER_FIRST_CASE) && (28 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (28)))
+#define GSL_INCLUDER_CASE 28
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 29 */
+#if ((29 >= GSL_INCLUDER_FIRST_CASE) && (29 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (29)))
+#define GSL_INCLUDER_CASE 29
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 30 */
+#if ((30 >= GSL_INCLUDER_FIRST_CASE) && (30 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (30)))
+#define GSL_INCLUDER_CASE 30
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 31 */
+#if ((31 >= GSL_INCLUDER_FIRST_CASE) && (31 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (31)))
+#define GSL_INCLUDER_CASE 31
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 32 */
+#if ((32 >= GSL_INCLUDER_FIRST_CASE) && (32 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (32)))
+#define GSL_INCLUDER_CASE 32
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 33 */
+#if ((33 >= GSL_INCLUDER_FIRST_CASE) && (33 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (33)))
+#define GSL_INCLUDER_CASE 33
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 34 */
+#if ((34 >= GSL_INCLUDER_FIRST_CASE) && (34 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (34)))
+#define GSL_INCLUDER_CASE 34
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 35 */
+#if ((35 >= GSL_INCLUDER_FIRST_CASE) && (35 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (35)))
+#define GSL_INCLUDER_CASE 35
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 36 */
+#if ((36 >= GSL_INCLUDER_FIRST_CASE) && (36 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (36)))
+#define GSL_INCLUDER_CASE 36
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 37 */
+#if ((37 >= GSL_INCLUDER_FIRST_CASE) && (37 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (37)))
+#define GSL_INCLUDER_CASE 37
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 38 */
+#if ((38 >= GSL_INCLUDER_FIRST_CASE) && (38 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (38)))
+#define GSL_INCLUDER_CASE 38
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 39 */
+#if ((39 >= GSL_INCLUDER_FIRST_CASE) && (39 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (39)))
+#define GSL_INCLUDER_CASE 39
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 40 */
+#if ((40 >= GSL_INCLUDER_FIRST_CASE) && (40 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (40)))
+#define GSL_INCLUDER_CASE 40
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 41 */
+#if ((41 >= GSL_INCLUDER_FIRST_CASE) && (41 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (41)))
+#define GSL_INCLUDER_CASE 41
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 42 */
+#if ((42 >= GSL_INCLUDER_FIRST_CASE) && (42 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (42)))
+#define GSL_INCLUDER_CASE 42
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 43 */
+#if ((43 >= GSL_INCLUDER_FIRST_CASE) && (43 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (43)))
+#define GSL_INCLUDER_CASE 43
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 44 */
+#if ((44 >= GSL_INCLUDER_FIRST_CASE) && (44 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (44)))
+#define GSL_INCLUDER_CASE 44
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 45 */
+#if ((45 >= GSL_INCLUDER_FIRST_CASE) && (45 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (45)))
+#define GSL_INCLUDER_CASE 45
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 46 */
+#if ((46 >= GSL_INCLUDER_FIRST_CASE) && (46 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (46)))
+#define GSL_INCLUDER_CASE 46
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 47 */
+#if ((47 >= GSL_INCLUDER_FIRST_CASE) && (47 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (47)))
+#define GSL_INCLUDER_CASE 47
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 48 */
+#if ((48 >= GSL_INCLUDER_FIRST_CASE) && (48 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (48)))
+#define GSL_INCLUDER_CASE 48
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 49 */
+#if ((49 >= GSL_INCLUDER_FIRST_CASE) && (49 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (49)))
+#define GSL_INCLUDER_CASE 49
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 50 */
+#if ((50 >= GSL_INCLUDER_FIRST_CASE) && (50 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (50)))
+#define GSL_INCLUDER_CASE 50
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 51 */
+#if ((51 >= GSL_INCLUDER_FIRST_CASE) && (51 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (51)))
+#define GSL_INCLUDER_CASE 51
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 52 */
+#if ((52 >= GSL_INCLUDER_FIRST_CASE) && (52 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (52)))
+#define GSL_INCLUDER_CASE 52
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 53 */
+#if ((53 >= GSL_INCLUDER_FIRST_CASE) && (53 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (53)))
+#define GSL_INCLUDER_CASE 53
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 54 */
+#if ((54 >= GSL_INCLUDER_FIRST_CASE) && (54 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (54)))
+#define GSL_INCLUDER_CASE 54
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 55 */
+#if ((55 >= GSL_INCLUDER_FIRST_CASE) && (55 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (55)))
+#define GSL_INCLUDER_CASE 55
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 56 */
+#if ((56 >= GSL_INCLUDER_FIRST_CASE) && (56 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (56)))
+#define GSL_INCLUDER_CASE 56
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 57 */
+#if ((57 >= GSL_INCLUDER_FIRST_CASE) && (57 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (57)))
+#define GSL_INCLUDER_CASE 57
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 58 */
+#if ((58 >= GSL_INCLUDER_FIRST_CASE) && (58 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (58)))
+#define GSL_INCLUDER_CASE 58
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 59 */
+#if ((59 >= GSL_INCLUDER_FIRST_CASE) && (59 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (59)))
+#define GSL_INCLUDER_CASE 59
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 60 */
+#if ((60 >= GSL_INCLUDER_FIRST_CASE) && (60 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (60)))
+#define GSL_INCLUDER_CASE 60
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 61 */
+#if ((61 >= GSL_INCLUDER_FIRST_CASE) && (61 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (61)))
+#define GSL_INCLUDER_CASE 61
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 62 */
+#if ((62 >= GSL_INCLUDER_FIRST_CASE) && (62 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (62)))
+#define GSL_INCLUDER_CASE 62
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 63 */
+#if ((63 >= GSL_INCLUDER_FIRST_CASE) && (63 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (63)))
+#define GSL_INCLUDER_CASE 63
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 64 */
+#if ((64 >= GSL_INCLUDER_FIRST_CASE) && (64 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (64)))
+#define GSL_INCLUDER_CASE 64
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 65 */
+#if ((65 >= GSL_INCLUDER_FIRST_CASE) && (65 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (65)))
+#define GSL_INCLUDER_CASE 65
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 66 */
+#if ((66 >= GSL_INCLUDER_FIRST_CASE) && (66 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (66)))
+#define GSL_INCLUDER_CASE 66
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 67 */
+#if ((67 >= GSL_INCLUDER_FIRST_CASE) && (67 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (67)))
+#define GSL_INCLUDER_CASE 67
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 68 */
+#if ((68 >= GSL_INCLUDER_FIRST_CASE) && (68 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (68)))
+#define GSL_INCLUDER_CASE 68
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 69 */
+#if ((69 >= GSL_INCLUDER_FIRST_CASE) && (69 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (69)))
+#define GSL_INCLUDER_CASE 69
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 70 */
+#if ((70 >= GSL_INCLUDER_FIRST_CASE) && (70 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (70)))
+#define GSL_INCLUDER_CASE 70
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 71 */
+#if ((71 >= GSL_INCLUDER_FIRST_CASE) && (71 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (71)))
+#define GSL_INCLUDER_CASE 71
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 72 */
+#if ((72 >= GSL_INCLUDER_FIRST_CASE) && (72 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (72)))
+#define GSL_INCLUDER_CASE 72
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 73 */
+#if ((73 >= GSL_INCLUDER_FIRST_CASE) && (73 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (73)))
+#define GSL_INCLUDER_CASE 73
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 74 */
+#if ((74 >= GSL_INCLUDER_FIRST_CASE) && (74 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (74)))
+#define GSL_INCLUDER_CASE 74
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 75 */
+#if ((75 >= GSL_INCLUDER_FIRST_CASE) && (75 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (75)))
+#define GSL_INCLUDER_CASE 75
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 76 */
+#if ((76 >= GSL_INCLUDER_FIRST_CASE) && (76 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (76)))
+#define GSL_INCLUDER_CASE 76
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 77 */
+#if ((77 >= GSL_INCLUDER_FIRST_CASE) && (77 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (77)))
+#define GSL_INCLUDER_CASE 77
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 78 */
+#if ((78 >= GSL_INCLUDER_FIRST_CASE) && (78 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (78)))
+#define GSL_INCLUDER_CASE 78
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 79 */
+#if ((79 >= GSL_INCLUDER_FIRST_CASE) && (79 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (79)))
+#define GSL_INCLUDER_CASE 79
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 80 */
+#if ((80 >= GSL_INCLUDER_FIRST_CASE) && (80 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (80)))
+#define GSL_INCLUDER_CASE 80
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 81 */
+#if ((81 >= GSL_INCLUDER_FIRST_CASE) && (81 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (81)))
+#define GSL_INCLUDER_CASE 81
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 82 */
+#if ((82 >= GSL_INCLUDER_FIRST_CASE) && (82 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (82)))
+#define GSL_INCLUDER_CASE 82
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 83 */
+#if ((83 >= GSL_INCLUDER_FIRST_CASE) && (83 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (83)))
+#define GSL_INCLUDER_CASE 83
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 84 */
+#if ((84 >= GSL_INCLUDER_FIRST_CASE) && (84 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (84)))
+#define GSL_INCLUDER_CASE 84
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 85 */
+#if ((85 >= GSL_INCLUDER_FIRST_CASE) && (85 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (85)))
+#define GSL_INCLUDER_CASE 85
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 86 */
+#if ((86 >= GSL_INCLUDER_FIRST_CASE) && (86 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (86)))
+#define GSL_INCLUDER_CASE 86
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 87 */
+#if ((87 >= GSL_INCLUDER_FIRST_CASE) && (87 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (87)))
+#define GSL_INCLUDER_CASE 87
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 88 */
+#if ((88 >= GSL_INCLUDER_FIRST_CASE) && (88 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (88)))
+#define GSL_INCLUDER_CASE 88
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 89 */
+#if ((89 >= GSL_INCLUDER_FIRST_CASE) && (89 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (89)))
+#define GSL_INCLUDER_CASE 89
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 90 */
+#if ((90 >= GSL_INCLUDER_FIRST_CASE) && (90 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (90)))
+#define GSL_INCLUDER_CASE 90
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 91 */
+#if ((91 >= GSL_INCLUDER_FIRST_CASE) && (91 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (91)))
+#define GSL_INCLUDER_CASE 91
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 92 */
+#if ((92 >= GSL_INCLUDER_FIRST_CASE) && (92 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (92)))
+#define GSL_INCLUDER_CASE 92
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 93 */
+#if ((93 >= GSL_INCLUDER_FIRST_CASE) && (93 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (93)))
+#define GSL_INCLUDER_CASE 93
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 94 */
+#if ((94 >= GSL_INCLUDER_FIRST_CASE) && (94 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (94)))
+#define GSL_INCLUDER_CASE 94
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 95 */
+#if ((95 >= GSL_INCLUDER_FIRST_CASE) && (95 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (95)))
+#define GSL_INCLUDER_CASE 95
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 96 */
+#if ((96 >= GSL_INCLUDER_FIRST_CASE) && (96 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (96)))
+#define GSL_INCLUDER_CASE 96
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 97 */
+#if ((97 >= GSL_INCLUDER_FIRST_CASE) && (97 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (97)))
+#define GSL_INCLUDER_CASE 97
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 98 */
+#if ((98 >= GSL_INCLUDER_FIRST_CASE) && (98 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (98)))
+#define GSL_INCLUDER_CASE 98
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 99 */
+#if ((99 >= GSL_INCLUDER_FIRST_CASE) && (99 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (99)))
+#define GSL_INCLUDER_CASE 99
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 100 */
+#if ((100 >= GSL_INCLUDER_FIRST_CASE) && (100 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (100)))
+#define GSL_INCLUDER_CASE 100
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 101 */
+#if ((101 >= GSL_INCLUDER_FIRST_CASE) && (101 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (101)))
+#define GSL_INCLUDER_CASE 101
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 102 */
+#if ((102 >= GSL_INCLUDER_FIRST_CASE) && (102 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (102)))
+#define GSL_INCLUDER_CASE 102
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 103 */
+#if ((103 >= GSL_INCLUDER_FIRST_CASE) && (103 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (103)))
+#define GSL_INCLUDER_CASE 103
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 104 */
+#if ((104 >= GSL_INCLUDER_FIRST_CASE) && (104 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (104)))
+#define GSL_INCLUDER_CASE 104
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 105 */
+#if ((105 >= GSL_INCLUDER_FIRST_CASE) && (105 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (105)))
+#define GSL_INCLUDER_CASE 105
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 106 */
+#if ((106 >= GSL_INCLUDER_FIRST_CASE) && (106 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (106)))
+#define GSL_INCLUDER_CASE 106
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 107 */
+#if ((107 >= GSL_INCLUDER_FIRST_CASE) && (107 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (107)))
+#define GSL_INCLUDER_CASE 107
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 108 */
+#if ((108 >= GSL_INCLUDER_FIRST_CASE) && (108 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (108)))
+#define GSL_INCLUDER_CASE 108
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 109 */
+#if ((109 >= GSL_INCLUDER_FIRST_CASE) && (109 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (109)))
+#define GSL_INCLUDER_CASE 109
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 110 */
+#if ((110 >= GSL_INCLUDER_FIRST_CASE) && (110 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (110)))
+#define GSL_INCLUDER_CASE 110
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 111 */
+#if ((111 >= GSL_INCLUDER_FIRST_CASE) && (111 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (111)))
+#define GSL_INCLUDER_CASE 111
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 112 */
+#if ((112 >= GSL_INCLUDER_FIRST_CASE) && (112 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (112)))
+#define GSL_INCLUDER_CASE 112
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 113 */
+#if ((113 >= GSL_INCLUDER_FIRST_CASE) && (113 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (113)))
+#define GSL_INCLUDER_CASE 113
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 114 */
+#if ((114 >= GSL_INCLUDER_FIRST_CASE) && (114 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (114)))
+#define GSL_INCLUDER_CASE 114
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 115 */
+#if ((115 >= GSL_INCLUDER_FIRST_CASE) && (115 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (115)))
+#define GSL_INCLUDER_CASE 115
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 116 */
+#if ((116 >= GSL_INCLUDER_FIRST_CASE) && (116 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (116)))
+#define GSL_INCLUDER_CASE 116
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 117 */
+#if ((117 >= GSL_INCLUDER_FIRST_CASE) && (117 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (117)))
+#define GSL_INCLUDER_CASE 117
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 118 */
+#if ((118 >= GSL_INCLUDER_FIRST_CASE) && (118 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (118)))
+#define GSL_INCLUDER_CASE 118
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 119 */
+#if ((119 >= GSL_INCLUDER_FIRST_CASE) && (119 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (119)))
+#define GSL_INCLUDER_CASE 119
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 120 */
+#if ((120 >= GSL_INCLUDER_FIRST_CASE) && (120 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (120)))
+#define GSL_INCLUDER_CASE 120
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 121 */
+#if ((121 >= GSL_INCLUDER_FIRST_CASE) && (121 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (121)))
+#define GSL_INCLUDER_CASE 121
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 122 */
+#if ((122 >= GSL_INCLUDER_FIRST_CASE) && (122 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (122)))
+#define GSL_INCLUDER_CASE 122
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 123 */
+#if ((123 >= GSL_INCLUDER_FIRST_CASE) && (123 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (123)))
+#define GSL_INCLUDER_CASE 123
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 124 */
+#if ((124 >= GSL_INCLUDER_FIRST_CASE) && (124 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (124)))
+#define GSL_INCLUDER_CASE 124
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 125 */
+#if ((125 >= GSL_INCLUDER_FIRST_CASE) && (125 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (125)))
+#define GSL_INCLUDER_CASE 125
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 126 */
+#if ((126 >= GSL_INCLUDER_FIRST_CASE) && (126 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (126)))
+#define GSL_INCLUDER_CASE 126
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 127 */
+#if ((127 >= GSL_INCLUDER_FIRST_CASE) && (127 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (127)))
+#define GSL_INCLUDER_CASE 127
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 128 */
+#if ((128 >= GSL_INCLUDER_FIRST_CASE) && (128 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (128)))
+#define GSL_INCLUDER_CASE 128
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 129 */
+#if ((129 >= GSL_INCLUDER_FIRST_CASE) && (129 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (129)))
+#define GSL_INCLUDER_CASE 129
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 130 */
+#if ((130 >= GSL_INCLUDER_FIRST_CASE) && (130 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (130)))
+#define GSL_INCLUDER_CASE 130
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 131 */
+#if ((131 >= GSL_INCLUDER_FIRST_CASE) && (131 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (131)))
+#define GSL_INCLUDER_CASE 131
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 132 */
+#if ((132 >= GSL_INCLUDER_FIRST_CASE) && (132 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (132)))
+#define GSL_INCLUDER_CASE 132
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 133 */
+#if ((133 >= GSL_INCLUDER_FIRST_CASE) && (133 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (133)))
+#define GSL_INCLUDER_CASE 133
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 134 */
+#if ((134 >= GSL_INCLUDER_FIRST_CASE) && (134 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (134)))
+#define GSL_INCLUDER_CASE 134
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 135 */
+#if ((135 >= GSL_INCLUDER_FIRST_CASE) && (135 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (135)))
+#define GSL_INCLUDER_CASE 135
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 136 */
+#if ((136 >= GSL_INCLUDER_FIRST_CASE) && (136 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (136)))
+#define GSL_INCLUDER_CASE 136
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 137 */
+#if ((137 >= GSL_INCLUDER_FIRST_CASE) && (137 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (137)))
+#define GSL_INCLUDER_CASE 137
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 138 */
+#if ((138 >= GSL_INCLUDER_FIRST_CASE) && (138 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (138)))
+#define GSL_INCLUDER_CASE 138
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 139 */
+#if ((139 >= GSL_INCLUDER_FIRST_CASE) && (139 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (139)))
+#define GSL_INCLUDER_CASE 139
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 140 */
+#if ((140 >= GSL_INCLUDER_FIRST_CASE) && (140 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (140)))
+#define GSL_INCLUDER_CASE 140
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 141 */
+#if ((141 >= GSL_INCLUDER_FIRST_CASE) && (141 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (141)))
+#define GSL_INCLUDER_CASE 141
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 142 */
+#if ((142 >= GSL_INCLUDER_FIRST_CASE) && (142 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (142)))
+#define GSL_INCLUDER_CASE 142
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 143 */
+#if ((143 >= GSL_INCLUDER_FIRST_CASE) && (143 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (143)))
+#define GSL_INCLUDER_CASE 143
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 144 */
+#if ((144 >= GSL_INCLUDER_FIRST_CASE) && (144 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (144)))
+#define GSL_INCLUDER_CASE 144
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 145 */
+#if ((145 >= GSL_INCLUDER_FIRST_CASE) && (145 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (145)))
+#define GSL_INCLUDER_CASE 145
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 146 */
+#if ((146 >= GSL_INCLUDER_FIRST_CASE) && (146 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (146)))
+#define GSL_INCLUDER_CASE 146
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 147 */
+#if ((147 >= GSL_INCLUDER_FIRST_CASE) && (147 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (147)))
+#define GSL_INCLUDER_CASE 147
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 148 */
+#if ((148 >= GSL_INCLUDER_FIRST_CASE) && (148 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (148)))
+#define GSL_INCLUDER_CASE 148
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 149 */
+#if ((149 >= GSL_INCLUDER_FIRST_CASE) && (149 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (149)))
+#define GSL_INCLUDER_CASE 149
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 150 */
+#if ((150 >= GSL_INCLUDER_FIRST_CASE) && (150 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (150)))
+#define GSL_INCLUDER_CASE 150
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 151 */
+#if ((151 >= GSL_INCLUDER_FIRST_CASE) && (151 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (151)))
+#define GSL_INCLUDER_CASE 151
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 152 */
+#if ((152 >= GSL_INCLUDER_FIRST_CASE) && (152 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (152)))
+#define GSL_INCLUDER_CASE 152
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 153 */
+#if ((153 >= GSL_INCLUDER_FIRST_CASE) && (153 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (153)))
+#define GSL_INCLUDER_CASE 153
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 154 */
+#if ((154 >= GSL_INCLUDER_FIRST_CASE) && (154 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (154)))
+#define GSL_INCLUDER_CASE 154
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 155 */
+#if ((155 >= GSL_INCLUDER_FIRST_CASE) && (155 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (155)))
+#define GSL_INCLUDER_CASE 155
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 156 */
+#if ((156 >= GSL_INCLUDER_FIRST_CASE) && (156 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (156)))
+#define GSL_INCLUDER_CASE 156
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 157 */
+#if ((157 >= GSL_INCLUDER_FIRST_CASE) && (157 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (157)))
+#define GSL_INCLUDER_CASE 157
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 158 */
+#if ((158 >= GSL_INCLUDER_FIRST_CASE) && (158 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (158)))
+#define GSL_INCLUDER_CASE 158
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 159 */
+#if ((159 >= GSL_INCLUDER_FIRST_CASE) && (159 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (159)))
+#define GSL_INCLUDER_CASE 159
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 160 */
+#if ((160 >= GSL_INCLUDER_FIRST_CASE) && (160 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (160)))
+#define GSL_INCLUDER_CASE 160
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 161 */
+#if ((161 >= GSL_INCLUDER_FIRST_CASE) && (161 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (161)))
+#define GSL_INCLUDER_CASE 161
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 162 */
+#if ((162 >= GSL_INCLUDER_FIRST_CASE) && (162 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (162)))
+#define GSL_INCLUDER_CASE 162
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 163 */
+#if ((163 >= GSL_INCLUDER_FIRST_CASE) && (163 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (163)))
+#define GSL_INCLUDER_CASE 163
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 164 */
+#if ((164 >= GSL_INCLUDER_FIRST_CASE) && (164 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (164)))
+#define GSL_INCLUDER_CASE 164
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 165 */
+#if ((165 >= GSL_INCLUDER_FIRST_CASE) && (165 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (165)))
+#define GSL_INCLUDER_CASE 165
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 166 */
+#if ((166 >= GSL_INCLUDER_FIRST_CASE) && (166 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (166)))
+#define GSL_INCLUDER_CASE 166
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 167 */
+#if ((167 >= GSL_INCLUDER_FIRST_CASE) && (167 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (167)))
+#define GSL_INCLUDER_CASE 167
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 168 */
+#if ((168 >= GSL_INCLUDER_FIRST_CASE) && (168 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (168)))
+#define GSL_INCLUDER_CASE 168
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 169 */
+#if ((169 >= GSL_INCLUDER_FIRST_CASE) && (169 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (169)))
+#define GSL_INCLUDER_CASE 169
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 170 */
+#if ((170 >= GSL_INCLUDER_FIRST_CASE) && (170 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (170)))
+#define GSL_INCLUDER_CASE 170
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 171 */
+#if ((171 >= GSL_INCLUDER_FIRST_CASE) && (171 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (171)))
+#define GSL_INCLUDER_CASE 171
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 172 */
+#if ((172 >= GSL_INCLUDER_FIRST_CASE) && (172 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (172)))
+#define GSL_INCLUDER_CASE 172
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 173 */
+#if ((173 >= GSL_INCLUDER_FIRST_CASE) && (173 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (173)))
+#define GSL_INCLUDER_CASE 173
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 174 */
+#if ((174 >= GSL_INCLUDER_FIRST_CASE) && (174 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (174)))
+#define GSL_INCLUDER_CASE 174
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 175 */
+#if ((175 >= GSL_INCLUDER_FIRST_CASE) && (175 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (175)))
+#define GSL_INCLUDER_CASE 175
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 176 */
+#if ((176 >= GSL_INCLUDER_FIRST_CASE) && (176 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (176)))
+#define GSL_INCLUDER_CASE 176
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 177 */
+#if ((177 >= GSL_INCLUDER_FIRST_CASE) && (177 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (177)))
+#define GSL_INCLUDER_CASE 177
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 178 */
+#if ((178 >= GSL_INCLUDER_FIRST_CASE) && (178 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (178)))
+#define GSL_INCLUDER_CASE 178
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 179 */
+#if ((179 >= GSL_INCLUDER_FIRST_CASE) && (179 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (179)))
+#define GSL_INCLUDER_CASE 179
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 180 */
+#if ((180 >= GSL_INCLUDER_FIRST_CASE) && (180 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (180)))
+#define GSL_INCLUDER_CASE 180
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 181 */
+#if ((181 >= GSL_INCLUDER_FIRST_CASE) && (181 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (181)))
+#define GSL_INCLUDER_CASE 181
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 182 */
+#if ((182 >= GSL_INCLUDER_FIRST_CASE) && (182 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (182)))
+#define GSL_INCLUDER_CASE 182
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 183 */
+#if ((183 >= GSL_INCLUDER_FIRST_CASE) && (183 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (183)))
+#define GSL_INCLUDER_CASE 183
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 184 */
+#if ((184 >= GSL_INCLUDER_FIRST_CASE) && (184 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (184)))
+#define GSL_INCLUDER_CASE 184
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 185 */
+#if ((185 >= GSL_INCLUDER_FIRST_CASE) && (185 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (185)))
+#define GSL_INCLUDER_CASE 185
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 186 */
+#if ((186 >= GSL_INCLUDER_FIRST_CASE) && (186 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (186)))
+#define GSL_INCLUDER_CASE 186
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 187 */
+#if ((187 >= GSL_INCLUDER_FIRST_CASE) && (187 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (187)))
+#define GSL_INCLUDER_CASE 187
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 188 */
+#if ((188 >= GSL_INCLUDER_FIRST_CASE) && (188 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (188)))
+#define GSL_INCLUDER_CASE 188
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 189 */
+#if ((189 >= GSL_INCLUDER_FIRST_CASE) && (189 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (189)))
+#define GSL_INCLUDER_CASE 189
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 190 */
+#if ((190 >= GSL_INCLUDER_FIRST_CASE) && (190 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (190)))
+#define GSL_INCLUDER_CASE 190
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 191 */
+#if ((191 >= GSL_INCLUDER_FIRST_CASE) && (191 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (191)))
+#define GSL_INCLUDER_CASE 191
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 192 */
+#if ((192 >= GSL_INCLUDER_FIRST_CASE) && (192 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (192)))
+#define GSL_INCLUDER_CASE 192
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 193 */
+#if ((193 >= GSL_INCLUDER_FIRST_CASE) && (193 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (193)))
+#define GSL_INCLUDER_CASE 193
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 194 */
+#if ((194 >= GSL_INCLUDER_FIRST_CASE) && (194 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (194)))
+#define GSL_INCLUDER_CASE 194
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 195 */
+#if ((195 >= GSL_INCLUDER_FIRST_CASE) && (195 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (195)))
+#define GSL_INCLUDER_CASE 195
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 196 */
+#if ((196 >= GSL_INCLUDER_FIRST_CASE) && (196 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (196)))
+#define GSL_INCLUDER_CASE 196
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 197 */
+#if ((197 >= GSL_INCLUDER_FIRST_CASE) && (197 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (197)))
+#define GSL_INCLUDER_CASE 197
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 198 */
+#if ((198 >= GSL_INCLUDER_FIRST_CASE) && (198 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (198)))
+#define GSL_INCLUDER_CASE 198
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 199 */
+#if ((199 >= GSL_INCLUDER_FIRST_CASE) && (199 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (199)))
+#define GSL_INCLUDER_CASE 199
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 200 */
+#if ((200 >= GSL_INCLUDER_FIRST_CASE) && (200 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (200)))
+#define GSL_INCLUDER_CASE 200
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 201 */
+#if ((201 >= GSL_INCLUDER_FIRST_CASE) && (201 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (201)))
+#define GSL_INCLUDER_CASE 201
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 202 */
+#if ((202 >= GSL_INCLUDER_FIRST_CASE) && (202 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (202)))
+#define GSL_INCLUDER_CASE 202
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 203 */
+#if ((203 >= GSL_INCLUDER_FIRST_CASE) && (203 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (203)))
+#define GSL_INCLUDER_CASE 203
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 204 */
+#if ((204 >= GSL_INCLUDER_FIRST_CASE) && (204 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (204)))
+#define GSL_INCLUDER_CASE 204
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 205 */
+#if ((205 >= GSL_INCLUDER_FIRST_CASE) && (205 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (205)))
+#define GSL_INCLUDER_CASE 205
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 206 */
+#if ((206 >= GSL_INCLUDER_FIRST_CASE) && (206 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (206)))
+#define GSL_INCLUDER_CASE 206
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 207 */
+#if ((207 >= GSL_INCLUDER_FIRST_CASE) && (207 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (207)))
+#define GSL_INCLUDER_CASE 207
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 208 */
+#if ((208 >= GSL_INCLUDER_FIRST_CASE) && (208 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (208)))
+#define GSL_INCLUDER_CASE 208
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 209 */
+#if ((209 >= GSL_INCLUDER_FIRST_CASE) && (209 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (209)))
+#define GSL_INCLUDER_CASE 209
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 210 */
+#if ((210 >= GSL_INCLUDER_FIRST_CASE) && (210 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (210)))
+#define GSL_INCLUDER_CASE 210
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 211 */
+#if ((211 >= GSL_INCLUDER_FIRST_CASE) && (211 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (211)))
+#define GSL_INCLUDER_CASE 211
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 212 */
+#if ((212 >= GSL_INCLUDER_FIRST_CASE) && (212 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (212)))
+#define GSL_INCLUDER_CASE 212
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 213 */
+#if ((213 >= GSL_INCLUDER_FIRST_CASE) && (213 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (213)))
+#define GSL_INCLUDER_CASE 213
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 214 */
+#if ((214 >= GSL_INCLUDER_FIRST_CASE) && (214 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (214)))
+#define GSL_INCLUDER_CASE 214
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 215 */
+#if ((215 >= GSL_INCLUDER_FIRST_CASE) && (215 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (215)))
+#define GSL_INCLUDER_CASE 215
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 216 */
+#if ((216 >= GSL_INCLUDER_FIRST_CASE) && (216 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (216)))
+#define GSL_INCLUDER_CASE 216
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 217 */
+#if ((217 >= GSL_INCLUDER_FIRST_CASE) && (217 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (217)))
+#define GSL_INCLUDER_CASE 217
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 218 */
+#if ((218 >= GSL_INCLUDER_FIRST_CASE) && (218 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (218)))
+#define GSL_INCLUDER_CASE 218
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 219 */
+#if ((219 >= GSL_INCLUDER_FIRST_CASE) && (219 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (219)))
+#define GSL_INCLUDER_CASE 219
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 220 */
+#if ((220 >= GSL_INCLUDER_FIRST_CASE) && (220 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (220)))
+#define GSL_INCLUDER_CASE 220
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 221 */
+#if ((221 >= GSL_INCLUDER_FIRST_CASE) && (221 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (221)))
+#define GSL_INCLUDER_CASE 221
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 222 */
+#if ((222 >= GSL_INCLUDER_FIRST_CASE) && (222 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (222)))
+#define GSL_INCLUDER_CASE 222
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 223 */
+#if ((223 >= GSL_INCLUDER_FIRST_CASE) && (223 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (223)))
+#define GSL_INCLUDER_CASE 223
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 224 */
+#if ((224 >= GSL_INCLUDER_FIRST_CASE) && (224 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (224)))
+#define GSL_INCLUDER_CASE 224
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 225 */
+#if ((225 >= GSL_INCLUDER_FIRST_CASE) && (225 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (225)))
+#define GSL_INCLUDER_CASE 225
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 226 */
+#if ((226 >= GSL_INCLUDER_FIRST_CASE) && (226 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (226)))
+#define GSL_INCLUDER_CASE 226
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 227 */
+#if ((227 >= GSL_INCLUDER_FIRST_CASE) && (227 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (227)))
+#define GSL_INCLUDER_CASE 227
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 228 */
+#if ((228 >= GSL_INCLUDER_FIRST_CASE) && (228 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (228)))
+#define GSL_INCLUDER_CASE 228
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 229 */
+#if ((229 >= GSL_INCLUDER_FIRST_CASE) && (229 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (229)))
+#define GSL_INCLUDER_CASE 229
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 230 */
+#if ((230 >= GSL_INCLUDER_FIRST_CASE) && (230 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (230)))
+#define GSL_INCLUDER_CASE 230
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 231 */
+#if ((231 >= GSL_INCLUDER_FIRST_CASE) && (231 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (231)))
+#define GSL_INCLUDER_CASE 231
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 232 */
+#if ((232 >= GSL_INCLUDER_FIRST_CASE) && (232 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (232)))
+#define GSL_INCLUDER_CASE 232
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 233 */
+#if ((233 >= GSL_INCLUDER_FIRST_CASE) && (233 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (233)))
+#define GSL_INCLUDER_CASE 233
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 234 */
+#if ((234 >= GSL_INCLUDER_FIRST_CASE) && (234 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (234)))
+#define GSL_INCLUDER_CASE 234
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 235 */
+#if ((235 >= GSL_INCLUDER_FIRST_CASE) && (235 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (235)))
+#define GSL_INCLUDER_CASE 235
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 236 */
+#if ((236 >= GSL_INCLUDER_FIRST_CASE) && (236 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (236)))
+#define GSL_INCLUDER_CASE 236
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 237 */
+#if ((237 >= GSL_INCLUDER_FIRST_CASE) && (237 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (237)))
+#define GSL_INCLUDER_CASE 237
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 238 */
+#if ((238 >= GSL_INCLUDER_FIRST_CASE) && (238 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (238)))
+#define GSL_INCLUDER_CASE 238
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 239 */
+#if ((239 >= GSL_INCLUDER_FIRST_CASE) && (239 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (239)))
+#define GSL_INCLUDER_CASE 239
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 240 */
+#if ((240 >= GSL_INCLUDER_FIRST_CASE) && (240 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (240)))
+#define GSL_INCLUDER_CASE 240
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 241 */
+#if ((241 >= GSL_INCLUDER_FIRST_CASE) && (241 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (241)))
+#define GSL_INCLUDER_CASE 241
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 242 */
+#if ((242 >= GSL_INCLUDER_FIRST_CASE) && (242 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (242)))
+#define GSL_INCLUDER_CASE 242
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 243 */
+#if ((243 >= GSL_INCLUDER_FIRST_CASE) && (243 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (243)))
+#define GSL_INCLUDER_CASE 243
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 244 */
+#if ((244 >= GSL_INCLUDER_FIRST_CASE) && (244 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (244)))
+#define GSL_INCLUDER_CASE 244
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 245 */
+#if ((245 >= GSL_INCLUDER_FIRST_CASE) && (245 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (245)))
+#define GSL_INCLUDER_CASE 245
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 246 */
+#if ((246 >= GSL_INCLUDER_FIRST_CASE) && (246 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (246)))
+#define GSL_INCLUDER_CASE 246
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 247 */
+#if ((247 >= GSL_INCLUDER_FIRST_CASE) && (247 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (247)))
+#define GSL_INCLUDER_CASE 247
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 248 */
+#if ((248 >= GSL_INCLUDER_FIRST_CASE) && (248 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (248)))
+#define GSL_INCLUDER_CASE 248
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 249 */
+#if ((249 >= GSL_INCLUDER_FIRST_CASE) && (249 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (249)))
+#define GSL_INCLUDER_CASE 249
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 250 */
+#if ((250 >= GSL_INCLUDER_FIRST_CASE) && (250 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (250)))
+#define GSL_INCLUDER_CASE 250
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 251 */
+#if ((251 >= GSL_INCLUDER_FIRST_CASE) && (251 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (251)))
+#define GSL_INCLUDER_CASE 251
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 252 */
+#if ((252 >= GSL_INCLUDER_FIRST_CASE) && (252 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (252)))
+#define GSL_INCLUDER_CASE 252
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 253 */
+#if ((253 >= GSL_INCLUDER_FIRST_CASE) && (253 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (253)))
+#define GSL_INCLUDER_CASE 253
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 254 */
+#if ((254 >= GSL_INCLUDER_FIRST_CASE) && (254 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (254)))
+#define GSL_INCLUDER_CASE 254
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 255 */
+#if ((255 >= GSL_INCLUDER_FIRST_CASE) && (255 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (255)))
+#define GSL_INCLUDER_CASE 255
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 256 */
+#if ((256 >= GSL_INCLUDER_FIRST_CASE) && (256 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (256)))
+#define GSL_INCLUDER_CASE 256
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 257 */
+#if ((257 >= GSL_INCLUDER_FIRST_CASE) && (257 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (257)))
+#define GSL_INCLUDER_CASE 257
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 258 */
+#if ((258 >= GSL_INCLUDER_FIRST_CASE) && (258 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (258)))
+#define GSL_INCLUDER_CASE 258
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 259 */
+#if ((259 >= GSL_INCLUDER_FIRST_CASE) && (259 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (259)))
+#define GSL_INCLUDER_CASE 259
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 260 */
+#if ((260 >= GSL_INCLUDER_FIRST_CASE) && (260 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (260)))
+#define GSL_INCLUDER_CASE 260
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 261 */
+#if ((261 >= GSL_INCLUDER_FIRST_CASE) && (261 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (261)))
+#define GSL_INCLUDER_CASE 261
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 262 */
+#if ((262 >= GSL_INCLUDER_FIRST_CASE) && (262 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (262)))
+#define GSL_INCLUDER_CASE 262
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 263 */
+#if ((263 >= GSL_INCLUDER_FIRST_CASE) && (263 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (263)))
+#define GSL_INCLUDER_CASE 263
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 264 */
+#if ((264 >= GSL_INCLUDER_FIRST_CASE) && (264 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (264)))
+#define GSL_INCLUDER_CASE 264
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 265 */
+#if ((265 >= GSL_INCLUDER_FIRST_CASE) && (265 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (265)))
+#define GSL_INCLUDER_CASE 265
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 266 */
+#if ((266 >= GSL_INCLUDER_FIRST_CASE) && (266 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (266)))
+#define GSL_INCLUDER_CASE 266
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 267 */
+#if ((267 >= GSL_INCLUDER_FIRST_CASE) && (267 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (267)))
+#define GSL_INCLUDER_CASE 267
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 268 */
+#if ((268 >= GSL_INCLUDER_FIRST_CASE) && (268 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (268)))
+#define GSL_INCLUDER_CASE 268
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 269 */
+#if ((269 >= GSL_INCLUDER_FIRST_CASE) && (269 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (269)))
+#define GSL_INCLUDER_CASE 269
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 270 */
+#if ((270 >= GSL_INCLUDER_FIRST_CASE) && (270 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (270)))
+#define GSL_INCLUDER_CASE 270
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 271 */
+#if ((271 >= GSL_INCLUDER_FIRST_CASE) && (271 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (271)))
+#define GSL_INCLUDER_CASE 271
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 272 */
+#if ((272 >= GSL_INCLUDER_FIRST_CASE) && (272 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (272)))
+#define GSL_INCLUDER_CASE 272
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 273 */
+#if ((273 >= GSL_INCLUDER_FIRST_CASE) && (273 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (273)))
+#define GSL_INCLUDER_CASE 273
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 274 */
+#if ((274 >= GSL_INCLUDER_FIRST_CASE) && (274 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (274)))
+#define GSL_INCLUDER_CASE 274
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 275 */
+#if ((275 >= GSL_INCLUDER_FIRST_CASE) && (275 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (275)))
+#define GSL_INCLUDER_CASE 275
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 276 */
+#if ((276 >= GSL_INCLUDER_FIRST_CASE) && (276 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (276)))
+#define GSL_INCLUDER_CASE 276
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 277 */
+#if ((277 >= GSL_INCLUDER_FIRST_CASE) && (277 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (277)))
+#define GSL_INCLUDER_CASE 277
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 278 */
+#if ((278 >= GSL_INCLUDER_FIRST_CASE) && (278 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (278)))
+#define GSL_INCLUDER_CASE 278
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 279 */
+#if ((279 >= GSL_INCLUDER_FIRST_CASE) && (279 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (279)))
+#define GSL_INCLUDER_CASE 279
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 280 */
+#if ((280 >= GSL_INCLUDER_FIRST_CASE) && (280 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (280)))
+#define GSL_INCLUDER_CASE 280
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 281 */
+#if ((281 >= GSL_INCLUDER_FIRST_CASE) && (281 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (281)))
+#define GSL_INCLUDER_CASE 281
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 282 */
+#if ((282 >= GSL_INCLUDER_FIRST_CASE) && (282 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (282)))
+#define GSL_INCLUDER_CASE 282
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 283 */
+#if ((283 >= GSL_INCLUDER_FIRST_CASE) && (283 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (283)))
+#define GSL_INCLUDER_CASE 283
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 284 */
+#if ((284 >= GSL_INCLUDER_FIRST_CASE) && (284 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (284)))
+#define GSL_INCLUDER_CASE 284
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 285 */
+#if ((285 >= GSL_INCLUDER_FIRST_CASE) && (285 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (285)))
+#define GSL_INCLUDER_CASE 285
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 286 */
+#if ((286 >= GSL_INCLUDER_FIRST_CASE) && (286 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (286)))
+#define GSL_INCLUDER_CASE 286
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 287 */
+#if ((287 >= GSL_INCLUDER_FIRST_CASE) && (287 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (287)))
+#define GSL_INCLUDER_CASE 287
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 288 */
+#if ((288 >= GSL_INCLUDER_FIRST_CASE) && (288 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (288)))
+#define GSL_INCLUDER_CASE 288
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 289 */
+#if ((289 >= GSL_INCLUDER_FIRST_CASE) && (289 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (289)))
+#define GSL_INCLUDER_CASE 289
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 290 */
+#if ((290 >= GSL_INCLUDER_FIRST_CASE) && (290 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (290)))
+#define GSL_INCLUDER_CASE 290
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 291 */
+#if ((291 >= GSL_INCLUDER_FIRST_CASE) && (291 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (291)))
+#define GSL_INCLUDER_CASE 291
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 292 */
+#if ((292 >= GSL_INCLUDER_FIRST_CASE) && (292 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (292)))
+#define GSL_INCLUDER_CASE 292
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 293 */
+#if ((293 >= GSL_INCLUDER_FIRST_CASE) && (293 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (293)))
+#define GSL_INCLUDER_CASE 293
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 294 */
+#if ((294 >= GSL_INCLUDER_FIRST_CASE) && (294 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (294)))
+#define GSL_INCLUDER_CASE 294
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 295 */
+#if ((295 >= GSL_INCLUDER_FIRST_CASE) && (295 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (295)))
+#define GSL_INCLUDER_CASE 295
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 296 */
+#if ((296 >= GSL_INCLUDER_FIRST_CASE) && (296 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (296)))
+#define GSL_INCLUDER_CASE 296
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 297 */
+#if ((297 >= GSL_INCLUDER_FIRST_CASE) && (297 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (297)))
+#define GSL_INCLUDER_CASE 297
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 298 */
+#if ((298 >= GSL_INCLUDER_FIRST_CASE) && (298 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (298)))
+#define GSL_INCLUDER_CASE 298
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 299 */
+#if ((299 >= GSL_INCLUDER_FIRST_CASE) && (299 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (299)))
+#define GSL_INCLUDER_CASE 299
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 300 */
+#if ((300 >= GSL_INCLUDER_FIRST_CASE) && (300 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (300)))
+#define GSL_INCLUDER_CASE 300
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 301 */
+#if ((301 >= GSL_INCLUDER_FIRST_CASE) && (301 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (301)))
+#define GSL_INCLUDER_CASE 301
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 302 */
+#if ((302 >= GSL_INCLUDER_FIRST_CASE) && (302 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (302)))
+#define GSL_INCLUDER_CASE 302
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 303 */
+#if ((303 >= GSL_INCLUDER_FIRST_CASE) && (303 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (303)))
+#define GSL_INCLUDER_CASE 303
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 304 */
+#if ((304 >= GSL_INCLUDER_FIRST_CASE) && (304 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (304)))
+#define GSL_INCLUDER_CASE 304
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 305 */
+#if ((305 >= GSL_INCLUDER_FIRST_CASE) && (305 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (305)))
+#define GSL_INCLUDER_CASE 305
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 306 */
+#if ((306 >= GSL_INCLUDER_FIRST_CASE) && (306 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (306)))
+#define GSL_INCLUDER_CASE 306
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 307 */
+#if ((307 >= GSL_INCLUDER_FIRST_CASE) && (307 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (307)))
+#define GSL_INCLUDER_CASE 307
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 308 */
+#if ((308 >= GSL_INCLUDER_FIRST_CASE) && (308 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (308)))
+#define GSL_INCLUDER_CASE 308
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 309 */
+#if ((309 >= GSL_INCLUDER_FIRST_CASE) && (309 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (309)))
+#define GSL_INCLUDER_CASE 309
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 310 */
+#if ((310 >= GSL_INCLUDER_FIRST_CASE) && (310 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (310)))
+#define GSL_INCLUDER_CASE 310
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 311 */
+#if ((311 >= GSL_INCLUDER_FIRST_CASE) && (311 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (311)))
+#define GSL_INCLUDER_CASE 311
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 312 */
+#if ((312 >= GSL_INCLUDER_FIRST_CASE) && (312 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (312)))
+#define GSL_INCLUDER_CASE 312
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 313 */
+#if ((313 >= GSL_INCLUDER_FIRST_CASE) && (313 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (313)))
+#define GSL_INCLUDER_CASE 313
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 314 */
+#if ((314 >= GSL_INCLUDER_FIRST_CASE) && (314 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (314)))
+#define GSL_INCLUDER_CASE 314
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 315 */
+#if ((315 >= GSL_INCLUDER_FIRST_CASE) && (315 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (315)))
+#define GSL_INCLUDER_CASE 315
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 316 */
+#if ((316 >= GSL_INCLUDER_FIRST_CASE) && (316 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (316)))
+#define GSL_INCLUDER_CASE 316
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 317 */
+#if ((317 >= GSL_INCLUDER_FIRST_CASE) && (317 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (317)))
+#define GSL_INCLUDER_CASE 317
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 318 */
+#if ((318 >= GSL_INCLUDER_FIRST_CASE) && (318 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (318)))
+#define GSL_INCLUDER_CASE 318
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 319 */
+#if ((319 >= GSL_INCLUDER_FIRST_CASE) && (319 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (319)))
+#define GSL_INCLUDER_CASE 319
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 320 */
+#if ((320 >= GSL_INCLUDER_FIRST_CASE) && (320 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (320)))
+#define GSL_INCLUDER_CASE 320
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 321 */
+#if ((321 >= GSL_INCLUDER_FIRST_CASE) && (321 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (321)))
+#define GSL_INCLUDER_CASE 321
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 322 */
+#if ((322 >= GSL_INCLUDER_FIRST_CASE) && (322 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (322)))
+#define GSL_INCLUDER_CASE 322
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 323 */
+#if ((323 >= GSL_INCLUDER_FIRST_CASE) && (323 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (323)))
+#define GSL_INCLUDER_CASE 323
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 324 */
+#if ((324 >= GSL_INCLUDER_FIRST_CASE) && (324 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (324)))
+#define GSL_INCLUDER_CASE 324
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 325 */
+#if ((325 >= GSL_INCLUDER_FIRST_CASE) && (325 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (325)))
+#define GSL_INCLUDER_CASE 325
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 326 */
+#if ((326 >= GSL_INCLUDER_FIRST_CASE) && (326 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (326)))
+#define GSL_INCLUDER_CASE 326
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 327 */
+#if ((327 >= GSL_INCLUDER_FIRST_CASE) && (327 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (327)))
+#define GSL_INCLUDER_CASE 327
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 328 */
+#if ((328 >= GSL_INCLUDER_FIRST_CASE) && (328 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (328)))
+#define GSL_INCLUDER_CASE 328
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 329 */
+#if ((329 >= GSL_INCLUDER_FIRST_CASE) && (329 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (329)))
+#define GSL_INCLUDER_CASE 329
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 330 */
+#if ((330 >= GSL_INCLUDER_FIRST_CASE) && (330 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (330)))
+#define GSL_INCLUDER_CASE 330
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 331 */
+#if ((331 >= GSL_INCLUDER_FIRST_CASE) && (331 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (331)))
+#define GSL_INCLUDER_CASE 331
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 332 */
+#if ((332 >= GSL_INCLUDER_FIRST_CASE) && (332 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (332)))
+#define GSL_INCLUDER_CASE 332
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 333 */
+#if ((333 >= GSL_INCLUDER_FIRST_CASE) && (333 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (333)))
+#define GSL_INCLUDER_CASE 333
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 334 */
+#if ((334 >= GSL_INCLUDER_FIRST_CASE) && (334 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (334)))
+#define GSL_INCLUDER_CASE 334
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 335 */
+#if ((335 >= GSL_INCLUDER_FIRST_CASE) && (335 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (335)))
+#define GSL_INCLUDER_CASE 335
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 336 */
+#if ((336 >= GSL_INCLUDER_FIRST_CASE) && (336 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (336)))
+#define GSL_INCLUDER_CASE 336
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 337 */
+#if ((337 >= GSL_INCLUDER_FIRST_CASE) && (337 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (337)))
+#define GSL_INCLUDER_CASE 337
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 338 */
+#if ((338 >= GSL_INCLUDER_FIRST_CASE) && (338 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (338)))
+#define GSL_INCLUDER_CASE 338
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 339 */
+#if ((339 >= GSL_INCLUDER_FIRST_CASE) && (339 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (339)))
+#define GSL_INCLUDER_CASE 339
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 340 */
+#if ((340 >= GSL_INCLUDER_FIRST_CASE) && (340 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (340)))
+#define GSL_INCLUDER_CASE 340
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 341 */
+#if ((341 >= GSL_INCLUDER_FIRST_CASE) && (341 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (341)))
+#define GSL_INCLUDER_CASE 341
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 342 */
+#if ((342 >= GSL_INCLUDER_FIRST_CASE) && (342 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (342)))
+#define GSL_INCLUDER_CASE 342
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 343 */
+#if ((343 >= GSL_INCLUDER_FIRST_CASE) && (343 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (343)))
+#define GSL_INCLUDER_CASE 343
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 344 */
+#if ((344 >= GSL_INCLUDER_FIRST_CASE) && (344 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (344)))
+#define GSL_INCLUDER_CASE 344
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 345 */
+#if ((345 >= GSL_INCLUDER_FIRST_CASE) && (345 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (345)))
+#define GSL_INCLUDER_CASE 345
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 346 */
+#if ((346 >= GSL_INCLUDER_FIRST_CASE) && (346 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (346)))
+#define GSL_INCLUDER_CASE 346
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 347 */
+#if ((347 >= GSL_INCLUDER_FIRST_CASE) && (347 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (347)))
+#define GSL_INCLUDER_CASE 347
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 348 */
+#if ((348 >= GSL_INCLUDER_FIRST_CASE) && (348 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (348)))
+#define GSL_INCLUDER_CASE 348
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 349 */
+#if ((349 >= GSL_INCLUDER_FIRST_CASE) && (349 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (349)))
+#define GSL_INCLUDER_CASE 349
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 350 */
+#if ((350 >= GSL_INCLUDER_FIRST_CASE) && (350 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (350)))
+#define GSL_INCLUDER_CASE 350
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 351 */
+#if ((351 >= GSL_INCLUDER_FIRST_CASE) && (351 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (351)))
+#define GSL_INCLUDER_CASE 351
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 352 */
+#if ((352 >= GSL_INCLUDER_FIRST_CASE) && (352 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (352)))
+#define GSL_INCLUDER_CASE 352
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 353 */
+#if ((353 >= GSL_INCLUDER_FIRST_CASE) && (353 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (353)))
+#define GSL_INCLUDER_CASE 353
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 354 */
+#if ((354 >= GSL_INCLUDER_FIRST_CASE) && (354 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (354)))
+#define GSL_INCLUDER_CASE 354
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 355 */
+#if ((355 >= GSL_INCLUDER_FIRST_CASE) && (355 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (355)))
+#define GSL_INCLUDER_CASE 355
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 356 */
+#if ((356 >= GSL_INCLUDER_FIRST_CASE) && (356 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (356)))
+#define GSL_INCLUDER_CASE 356
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 357 */
+#if ((357 >= GSL_INCLUDER_FIRST_CASE) && (357 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (357)))
+#define GSL_INCLUDER_CASE 357
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 358 */
+#if ((358 >= GSL_INCLUDER_FIRST_CASE) && (358 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (358)))
+#define GSL_INCLUDER_CASE 358
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 359 */
+#if ((359 >= GSL_INCLUDER_FIRST_CASE) && (359 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (359)))
+#define GSL_INCLUDER_CASE 359
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 360 */
+#if ((360 >= GSL_INCLUDER_FIRST_CASE) && (360 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (360)))
+#define GSL_INCLUDER_CASE 360
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 361 */
+#if ((361 >= GSL_INCLUDER_FIRST_CASE) && (361 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (361)))
+#define GSL_INCLUDER_CASE 361
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 362 */
+#if ((362 >= GSL_INCLUDER_FIRST_CASE) && (362 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (362)))
+#define GSL_INCLUDER_CASE 362
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 363 */
+#if ((363 >= GSL_INCLUDER_FIRST_CASE) && (363 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (363)))
+#define GSL_INCLUDER_CASE 363
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 364 */
+#if ((364 >= GSL_INCLUDER_FIRST_CASE) && (364 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (364)))
+#define GSL_INCLUDER_CASE 364
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 365 */
+#if ((365 >= GSL_INCLUDER_FIRST_CASE) && (365 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (365)))
+#define GSL_INCLUDER_CASE 365
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 366 */
+#if ((366 >= GSL_INCLUDER_FIRST_CASE) && (366 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (366)))
+#define GSL_INCLUDER_CASE 366
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 367 */
+#if ((367 >= GSL_INCLUDER_FIRST_CASE) && (367 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (367)))
+#define GSL_INCLUDER_CASE 367
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 368 */
+#if ((368 >= GSL_INCLUDER_FIRST_CASE) && (368 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (368)))
+#define GSL_INCLUDER_CASE 368
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 369 */
+#if ((369 >= GSL_INCLUDER_FIRST_CASE) && (369 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (369)))
+#define GSL_INCLUDER_CASE 369
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 370 */
+#if ((370 >= GSL_INCLUDER_FIRST_CASE) && (370 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (370)))
+#define GSL_INCLUDER_CASE 370
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 371 */
+#if ((371 >= GSL_INCLUDER_FIRST_CASE) && (371 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (371)))
+#define GSL_INCLUDER_CASE 371
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 372 */
+#if ((372 >= GSL_INCLUDER_FIRST_CASE) && (372 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (372)))
+#define GSL_INCLUDER_CASE 372
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 373 */
+#if ((373 >= GSL_INCLUDER_FIRST_CASE) && (373 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (373)))
+#define GSL_INCLUDER_CASE 373
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 374 */
+#if ((374 >= GSL_INCLUDER_FIRST_CASE) && (374 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (374)))
+#define GSL_INCLUDER_CASE 374
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 375 */
+#if ((375 >= GSL_INCLUDER_FIRST_CASE) && (375 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (375)))
+#define GSL_INCLUDER_CASE 375
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 376 */
+#if ((376 >= GSL_INCLUDER_FIRST_CASE) && (376 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (376)))
+#define GSL_INCLUDER_CASE 376
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 377 */
+#if ((377 >= GSL_INCLUDER_FIRST_CASE) && (377 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (377)))
+#define GSL_INCLUDER_CASE 377
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 378 */
+#if ((378 >= GSL_INCLUDER_FIRST_CASE) && (378 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (378)))
+#define GSL_INCLUDER_CASE 378
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 379 */
+#if ((379 >= GSL_INCLUDER_FIRST_CASE) && (379 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (379)))
+#define GSL_INCLUDER_CASE 379
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 380 */
+#if ((380 >= GSL_INCLUDER_FIRST_CASE) && (380 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (380)))
+#define GSL_INCLUDER_CASE 380
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 381 */
+#if ((381 >= GSL_INCLUDER_FIRST_CASE) && (381 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (381)))
+#define GSL_INCLUDER_CASE 381
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 382 */
+#if ((382 >= GSL_INCLUDER_FIRST_CASE) && (382 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (382)))
+#define GSL_INCLUDER_CASE 382
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 383 */
+#if ((383 >= GSL_INCLUDER_FIRST_CASE) && (383 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (383)))
+#define GSL_INCLUDER_CASE 383
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 384 */
+#if ((384 >= GSL_INCLUDER_FIRST_CASE) && (384 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (384)))
+#define GSL_INCLUDER_CASE 384
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 385 */
+#if ((385 >= GSL_INCLUDER_FIRST_CASE) && (385 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (385)))
+#define GSL_INCLUDER_CASE 385
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 386 */
+#if ((386 >= GSL_INCLUDER_FIRST_CASE) && (386 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (386)))
+#define GSL_INCLUDER_CASE 386
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 387 */
+#if ((387 >= GSL_INCLUDER_FIRST_CASE) && (387 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (387)))
+#define GSL_INCLUDER_CASE 387
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 388 */
+#if ((388 >= GSL_INCLUDER_FIRST_CASE) && (388 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (388)))
+#define GSL_INCLUDER_CASE 388
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 389 */
+#if ((389 >= GSL_INCLUDER_FIRST_CASE) && (389 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (389)))
+#define GSL_INCLUDER_CASE 389
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 390 */
+#if ((390 >= GSL_INCLUDER_FIRST_CASE) && (390 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (390)))
+#define GSL_INCLUDER_CASE 390
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 391 */
+#if ((391 >= GSL_INCLUDER_FIRST_CASE) && (391 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (391)))
+#define GSL_INCLUDER_CASE 391
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 392 */
+#if ((392 >= GSL_INCLUDER_FIRST_CASE) && (392 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (392)))
+#define GSL_INCLUDER_CASE 392
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 393 */
+#if ((393 >= GSL_INCLUDER_FIRST_CASE) && (393 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (393)))
+#define GSL_INCLUDER_CASE 393
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 394 */
+#if ((394 >= GSL_INCLUDER_FIRST_CASE) && (394 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (394)))
+#define GSL_INCLUDER_CASE 394
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 395 */
+#if ((395 >= GSL_INCLUDER_FIRST_CASE) && (395 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (395)))
+#define GSL_INCLUDER_CASE 395
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 396 */
+#if ((396 >= GSL_INCLUDER_FIRST_CASE) && (396 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (396)))
+#define GSL_INCLUDER_CASE 396
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 397 */
+#if ((397 >= GSL_INCLUDER_FIRST_CASE) && (397 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (397)))
+#define GSL_INCLUDER_CASE 397
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 398 */
+#if ((398 >= GSL_INCLUDER_FIRST_CASE) && (398 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (398)))
+#define GSL_INCLUDER_CASE 398
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 399 */
+#if ((399 >= GSL_INCLUDER_FIRST_CASE) && (399 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (399)))
+#define GSL_INCLUDER_CASE 399
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 400 */
+#if ((400 >= GSL_INCLUDER_FIRST_CASE) && (400 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (400)))
+#define GSL_INCLUDER_CASE 400
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 401 */
+#if ((401 >= GSL_INCLUDER_FIRST_CASE) && (401 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (401)))
+#define GSL_INCLUDER_CASE 401
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 402 */
+#if ((402 >= GSL_INCLUDER_FIRST_CASE) && (402 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (402)))
+#define GSL_INCLUDER_CASE 402
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 403 */
+#if ((403 >= GSL_INCLUDER_FIRST_CASE) && (403 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (403)))
+#define GSL_INCLUDER_CASE 403
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 404 */
+#if ((404 >= GSL_INCLUDER_FIRST_CASE) && (404 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (404)))
+#define GSL_INCLUDER_CASE 404
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 405 */
+#if ((405 >= GSL_INCLUDER_FIRST_CASE) && (405 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (405)))
+#define GSL_INCLUDER_CASE 405
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 406 */
+#if ((406 >= GSL_INCLUDER_FIRST_CASE) && (406 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (406)))
+#define GSL_INCLUDER_CASE 406
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 407 */
+#if ((407 >= GSL_INCLUDER_FIRST_CASE) && (407 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (407)))
+#define GSL_INCLUDER_CASE 407
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 408 */
+#if ((408 >= GSL_INCLUDER_FIRST_CASE) && (408 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (408)))
+#define GSL_INCLUDER_CASE 408
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 409 */
+#if ((409 >= GSL_INCLUDER_FIRST_CASE) && (409 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (409)))
+#define GSL_INCLUDER_CASE 409
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 410 */
+#if ((410 >= GSL_INCLUDER_FIRST_CASE) && (410 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (410)))
+#define GSL_INCLUDER_CASE 410
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 411 */
+#if ((411 >= GSL_INCLUDER_FIRST_CASE) && (411 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (411)))
+#define GSL_INCLUDER_CASE 411
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 412 */
+#if ((412 >= GSL_INCLUDER_FIRST_CASE) && (412 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (412)))
+#define GSL_INCLUDER_CASE 412
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 413 */
+#if ((413 >= GSL_INCLUDER_FIRST_CASE) && (413 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (413)))
+#define GSL_INCLUDER_CASE 413
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 414 */
+#if ((414 >= GSL_INCLUDER_FIRST_CASE) && (414 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (414)))
+#define GSL_INCLUDER_CASE 414
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 415 */
+#if ((415 >= GSL_INCLUDER_FIRST_CASE) && (415 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (415)))
+#define GSL_INCLUDER_CASE 415
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 416 */
+#if ((416 >= GSL_INCLUDER_FIRST_CASE) && (416 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (416)))
+#define GSL_INCLUDER_CASE 416
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 417 */
+#if ((417 >= GSL_INCLUDER_FIRST_CASE) && (417 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (417)))
+#define GSL_INCLUDER_CASE 417
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 418 */
+#if ((418 >= GSL_INCLUDER_FIRST_CASE) && (418 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (418)))
+#define GSL_INCLUDER_CASE 418
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 419 */
+#if ((419 >= GSL_INCLUDER_FIRST_CASE) && (419 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (419)))
+#define GSL_INCLUDER_CASE 419
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 420 */
+#if ((420 >= GSL_INCLUDER_FIRST_CASE) && (420 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (420)))
+#define GSL_INCLUDER_CASE 420
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 421 */
+#if ((421 >= GSL_INCLUDER_FIRST_CASE) && (421 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (421)))
+#define GSL_INCLUDER_CASE 421
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 422 */
+#if ((422 >= GSL_INCLUDER_FIRST_CASE) && (422 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (422)))
+#define GSL_INCLUDER_CASE 422
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 423 */
+#if ((423 >= GSL_INCLUDER_FIRST_CASE) && (423 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (423)))
+#define GSL_INCLUDER_CASE 423
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 424 */
+#if ((424 >= GSL_INCLUDER_FIRST_CASE) && (424 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (424)))
+#define GSL_INCLUDER_CASE 424
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 425 */
+#if ((425 >= GSL_INCLUDER_FIRST_CASE) && (425 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (425)))
+#define GSL_INCLUDER_CASE 425
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 426 */
+#if ((426 >= GSL_INCLUDER_FIRST_CASE) && (426 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (426)))
+#define GSL_INCLUDER_CASE 426
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 427 */
+#if ((427 >= GSL_INCLUDER_FIRST_CASE) && (427 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (427)))
+#define GSL_INCLUDER_CASE 427
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 428 */
+#if ((428 >= GSL_INCLUDER_FIRST_CASE) && (428 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (428)))
+#define GSL_INCLUDER_CASE 428
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 429 */
+#if ((429 >= GSL_INCLUDER_FIRST_CASE) && (429 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (429)))
+#define GSL_INCLUDER_CASE 429
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 430 */
+#if ((430 >= GSL_INCLUDER_FIRST_CASE) && (430 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (430)))
+#define GSL_INCLUDER_CASE 430
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 431 */
+#if ((431 >= GSL_INCLUDER_FIRST_CASE) && (431 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (431)))
+#define GSL_INCLUDER_CASE 431
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 432 */
+#if ((432 >= GSL_INCLUDER_FIRST_CASE) && (432 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (432)))
+#define GSL_INCLUDER_CASE 432
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 433 */
+#if ((433 >= GSL_INCLUDER_FIRST_CASE) && (433 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (433)))
+#define GSL_INCLUDER_CASE 433
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 434 */
+#if ((434 >= GSL_INCLUDER_FIRST_CASE) && (434 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (434)))
+#define GSL_INCLUDER_CASE 434
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 435 */
+#if ((435 >= GSL_INCLUDER_FIRST_CASE) && (435 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (435)))
+#define GSL_INCLUDER_CASE 435
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 436 */
+#if ((436 >= GSL_INCLUDER_FIRST_CASE) && (436 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (436)))
+#define GSL_INCLUDER_CASE 436
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 437 */
+#if ((437 >= GSL_INCLUDER_FIRST_CASE) && (437 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (437)))
+#define GSL_INCLUDER_CASE 437
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 438 */
+#if ((438 >= GSL_INCLUDER_FIRST_CASE) && (438 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (438)))
+#define GSL_INCLUDER_CASE 438
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 439 */
+#if ((439 >= GSL_INCLUDER_FIRST_CASE) && (439 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (439)))
+#define GSL_INCLUDER_CASE 439
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 440 */
+#if ((440 >= GSL_INCLUDER_FIRST_CASE) && (440 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (440)))
+#define GSL_INCLUDER_CASE 440
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 441 */
+#if ((441 >= GSL_INCLUDER_FIRST_CASE) && (441 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (441)))
+#define GSL_INCLUDER_CASE 441
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 442 */
+#if ((442 >= GSL_INCLUDER_FIRST_CASE) && (442 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (442)))
+#define GSL_INCLUDER_CASE 442
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 443 */
+#if ((443 >= GSL_INCLUDER_FIRST_CASE) && (443 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (443)))
+#define GSL_INCLUDER_CASE 443
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 444 */
+#if ((444 >= GSL_INCLUDER_FIRST_CASE) && (444 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (444)))
+#define GSL_INCLUDER_CASE 444
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 445 */
+#if ((445 >= GSL_INCLUDER_FIRST_CASE) && (445 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (445)))
+#define GSL_INCLUDER_CASE 445
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 446 */
+#if ((446 >= GSL_INCLUDER_FIRST_CASE) && (446 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (446)))
+#define GSL_INCLUDER_CASE 446
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 447 */
+#if ((447 >= GSL_INCLUDER_FIRST_CASE) && (447 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (447)))
+#define GSL_INCLUDER_CASE 447
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 448 */
+#if ((448 >= GSL_INCLUDER_FIRST_CASE) && (448 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (448)))
+#define GSL_INCLUDER_CASE 448
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 449 */
+#if ((449 >= GSL_INCLUDER_FIRST_CASE) && (449 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (449)))
+#define GSL_INCLUDER_CASE 449
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 450 */
+#if ((450 >= GSL_INCLUDER_FIRST_CASE) && (450 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (450)))
+#define GSL_INCLUDER_CASE 450
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 451 */
+#if ((451 >= GSL_INCLUDER_FIRST_CASE) && (451 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (451)))
+#define GSL_INCLUDER_CASE 451
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 452 */
+#if ((452 >= GSL_INCLUDER_FIRST_CASE) && (452 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (452)))
+#define GSL_INCLUDER_CASE 452
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 453 */
+#if ((453 >= GSL_INCLUDER_FIRST_CASE) && (453 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (453)))
+#define GSL_INCLUDER_CASE 453
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 454 */
+#if ((454 >= GSL_INCLUDER_FIRST_CASE) && (454 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (454)))
+#define GSL_INCLUDER_CASE 454
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 455 */
+#if ((455 >= GSL_INCLUDER_FIRST_CASE) && (455 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (455)))
+#define GSL_INCLUDER_CASE 455
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 456 */
+#if ((456 >= GSL_INCLUDER_FIRST_CASE) && (456 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (456)))
+#define GSL_INCLUDER_CASE 456
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 457 */
+#if ((457 >= GSL_INCLUDER_FIRST_CASE) && (457 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (457)))
+#define GSL_INCLUDER_CASE 457
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 458 */
+#if ((458 >= GSL_INCLUDER_FIRST_CASE) && (458 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (458)))
+#define GSL_INCLUDER_CASE 458
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 459 */
+#if ((459 >= GSL_INCLUDER_FIRST_CASE) && (459 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (459)))
+#define GSL_INCLUDER_CASE 459
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 460 */
+#if ((460 >= GSL_INCLUDER_FIRST_CASE) && (460 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (460)))
+#define GSL_INCLUDER_CASE 460
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 461 */
+#if ((461 >= GSL_INCLUDER_FIRST_CASE) && (461 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (461)))
+#define GSL_INCLUDER_CASE 461
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 462 */
+#if ((462 >= GSL_INCLUDER_FIRST_CASE) && (462 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (462)))
+#define GSL_INCLUDER_CASE 462
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 463 */
+#if ((463 >= GSL_INCLUDER_FIRST_CASE) && (463 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (463)))
+#define GSL_INCLUDER_CASE 463
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 464 */
+#if ((464 >= GSL_INCLUDER_FIRST_CASE) && (464 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (464)))
+#define GSL_INCLUDER_CASE 464
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 465 */
+#if ((465 >= GSL_INCLUDER_FIRST_CASE) && (465 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (465)))
+#define GSL_INCLUDER_CASE 465
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 466 */
+#if ((466 >= GSL_INCLUDER_FIRST_CASE) && (466 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (466)))
+#define GSL_INCLUDER_CASE 466
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 467 */
+#if ((467 >= GSL_INCLUDER_FIRST_CASE) && (467 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (467)))
+#define GSL_INCLUDER_CASE 467
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 468 */
+#if ((468 >= GSL_INCLUDER_FIRST_CASE) && (468 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (468)))
+#define GSL_INCLUDER_CASE 468
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 469 */
+#if ((469 >= GSL_INCLUDER_FIRST_CASE) && (469 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (469)))
+#define GSL_INCLUDER_CASE 469
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 470 */
+#if ((470 >= GSL_INCLUDER_FIRST_CASE) && (470 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (470)))
+#define GSL_INCLUDER_CASE 470
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 471 */
+#if ((471 >= GSL_INCLUDER_FIRST_CASE) && (471 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (471)))
+#define GSL_INCLUDER_CASE 471
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 472 */
+#if ((472 >= GSL_INCLUDER_FIRST_CASE) && (472 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (472)))
+#define GSL_INCLUDER_CASE 472
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 473 */
+#if ((473 >= GSL_INCLUDER_FIRST_CASE) && (473 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (473)))
+#define GSL_INCLUDER_CASE 473
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 474 */
+#if ((474 >= GSL_INCLUDER_FIRST_CASE) && (474 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (474)))
+#define GSL_INCLUDER_CASE 474
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 475 */
+#if ((475 >= GSL_INCLUDER_FIRST_CASE) && (475 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (475)))
+#define GSL_INCLUDER_CASE 475
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 476 */
+#if ((476 >= GSL_INCLUDER_FIRST_CASE) && (476 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (476)))
+#define GSL_INCLUDER_CASE 476
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 477 */
+#if ((477 >= GSL_INCLUDER_FIRST_CASE) && (477 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (477)))
+#define GSL_INCLUDER_CASE 477
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 478 */
+#if ((478 >= GSL_INCLUDER_FIRST_CASE) && (478 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (478)))
+#define GSL_INCLUDER_CASE 478
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 479 */
+#if ((479 >= GSL_INCLUDER_FIRST_CASE) && (479 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (479)))
+#define GSL_INCLUDER_CASE 479
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 480 */
+#if ((480 >= GSL_INCLUDER_FIRST_CASE) && (480 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (480)))
+#define GSL_INCLUDER_CASE 480
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 481 */
+#if ((481 >= GSL_INCLUDER_FIRST_CASE) && (481 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (481)))
+#define GSL_INCLUDER_CASE 481
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 482 */
+#if ((482 >= GSL_INCLUDER_FIRST_CASE) && (482 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (482)))
+#define GSL_INCLUDER_CASE 482
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 483 */
+#if ((483 >= GSL_INCLUDER_FIRST_CASE) && (483 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (483)))
+#define GSL_INCLUDER_CASE 483
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 484 */
+#if ((484 >= GSL_INCLUDER_FIRST_CASE) && (484 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (484)))
+#define GSL_INCLUDER_CASE 484
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 485 */
+#if ((485 >= GSL_INCLUDER_FIRST_CASE) && (485 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (485)))
+#define GSL_INCLUDER_CASE 485
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 486 */
+#if ((486 >= GSL_INCLUDER_FIRST_CASE) && (486 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (486)))
+#define GSL_INCLUDER_CASE 486
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 487 */
+#if ((487 >= GSL_INCLUDER_FIRST_CASE) && (487 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (487)))
+#define GSL_INCLUDER_CASE 487
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 488 */
+#if ((488 >= GSL_INCLUDER_FIRST_CASE) && (488 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (488)))
+#define GSL_INCLUDER_CASE 488
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 489 */
+#if ((489 >= GSL_INCLUDER_FIRST_CASE) && (489 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (489)))
+#define GSL_INCLUDER_CASE 489
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 490 */
+#if ((490 >= GSL_INCLUDER_FIRST_CASE) && (490 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (490)))
+#define GSL_INCLUDER_CASE 490
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 491 */
+#if ((491 >= GSL_INCLUDER_FIRST_CASE) && (491 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (491)))
+#define GSL_INCLUDER_CASE 491
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 492 */
+#if ((492 >= GSL_INCLUDER_FIRST_CASE) && (492 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (492)))
+#define GSL_INCLUDER_CASE 492
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 493 */
+#if ((493 >= GSL_INCLUDER_FIRST_CASE) && (493 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (493)))
+#define GSL_INCLUDER_CASE 493
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 494 */
+#if ((494 >= GSL_INCLUDER_FIRST_CASE) && (494 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (494)))
+#define GSL_INCLUDER_CASE 494
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 495 */
+#if ((495 >= GSL_INCLUDER_FIRST_CASE) && (495 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (495)))
+#define GSL_INCLUDER_CASE 495
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 496 */
+#if ((496 >= GSL_INCLUDER_FIRST_CASE) && (496 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (496)))
+#define GSL_INCLUDER_CASE 496
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 497 */
+#if ((497 >= GSL_INCLUDER_FIRST_CASE) && (497 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (497)))
+#define GSL_INCLUDER_CASE 497
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 498 */
+#if ((498 >= GSL_INCLUDER_FIRST_CASE) && (498 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (498)))
+#define GSL_INCLUDER_CASE 498
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 499 */
+#if ((499 >= GSL_INCLUDER_FIRST_CASE) && (499 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (499)))
+#define GSL_INCLUDER_CASE 499
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 500 */
+#if ((500 >= GSL_INCLUDER_FIRST_CASE) && (500 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (500)))
+#define GSL_INCLUDER_CASE 500
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 501 */
+#if ((501 >= GSL_INCLUDER_FIRST_CASE) && (501 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (501)))
+#define GSL_INCLUDER_CASE 501
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 502 */
+#if ((502 >= GSL_INCLUDER_FIRST_CASE) && (502 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (502)))
+#define GSL_INCLUDER_CASE 502
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 503 */
+#if ((503 >= GSL_INCLUDER_FIRST_CASE) && (503 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (503)))
+#define GSL_INCLUDER_CASE 503
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 504 */
+#if ((504 >= GSL_INCLUDER_FIRST_CASE) && (504 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (504)))
+#define GSL_INCLUDER_CASE 504
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 505 */
+#if ((505 >= GSL_INCLUDER_FIRST_CASE) && (505 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (505)))
+#define GSL_INCLUDER_CASE 505
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 506 */
+#if ((506 >= GSL_INCLUDER_FIRST_CASE) && (506 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (506)))
+#define GSL_INCLUDER_CASE 506
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 507 */
+#if ((507 >= GSL_INCLUDER_FIRST_CASE) && (507 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (507)))
+#define GSL_INCLUDER_CASE 507
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 508 */
+#if ((508 >= GSL_INCLUDER_FIRST_CASE) && (508 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (508)))
+#define GSL_INCLUDER_CASE 508
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 509 */
+#if ((509 >= GSL_INCLUDER_FIRST_CASE) && (509 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (509)))
+#define GSL_INCLUDER_CASE 509
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 510 */
+#if ((510 >= GSL_INCLUDER_FIRST_CASE) && (510 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (510)))
+#define GSL_INCLUDER_CASE 510
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 511 */
+#if ((511 >= GSL_INCLUDER_FIRST_CASE) && (511 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (511)))
+#define GSL_INCLUDER_CASE 511
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 512 */
+#if ((512 >= GSL_INCLUDER_FIRST_CASE) && (512 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (512)))
+#define GSL_INCLUDER_CASE 512
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 513 */
+#if ((513 >= GSL_INCLUDER_FIRST_CASE) && (513 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (513)))
+#define GSL_INCLUDER_CASE 513
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 514 */
+#if ((514 >= GSL_INCLUDER_FIRST_CASE) && (514 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (514)))
+#define GSL_INCLUDER_CASE 514
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 515 */
+#if ((515 >= GSL_INCLUDER_FIRST_CASE) && (515 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (515)))
+#define GSL_INCLUDER_CASE 515
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 516 */
+#if ((516 >= GSL_INCLUDER_FIRST_CASE) && (516 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (516)))
+#define GSL_INCLUDER_CASE 516
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 517 */
+#if ((517 >= GSL_INCLUDER_FIRST_CASE) && (517 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (517)))
+#define GSL_INCLUDER_CASE 517
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 518 */
+#if ((518 >= GSL_INCLUDER_FIRST_CASE) && (518 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (518)))
+#define GSL_INCLUDER_CASE 518
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 519 */
+#if ((519 >= GSL_INCLUDER_FIRST_CASE) && (519 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (519)))
+#define GSL_INCLUDER_CASE 519
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 520 */
+#if ((520 >= GSL_INCLUDER_FIRST_CASE) && (520 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (520)))
+#define GSL_INCLUDER_CASE 520
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 521 */
+#if ((521 >= GSL_INCLUDER_FIRST_CASE) && (521 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (521)))
+#define GSL_INCLUDER_CASE 521
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 522 */
+#if ((522 >= GSL_INCLUDER_FIRST_CASE) && (522 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (522)))
+#define GSL_INCLUDER_CASE 522
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 523 */
+#if ((523 >= GSL_INCLUDER_FIRST_CASE) && (523 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (523)))
+#define GSL_INCLUDER_CASE 523
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 524 */
+#if ((524 >= GSL_INCLUDER_FIRST_CASE) && (524 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (524)))
+#define GSL_INCLUDER_CASE 524
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 525 */
+#if ((525 >= GSL_INCLUDER_FIRST_CASE) && (525 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (525)))
+#define GSL_INCLUDER_CASE 525
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 526 */
+#if ((526 >= GSL_INCLUDER_FIRST_CASE) && (526 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (526)))
+#define GSL_INCLUDER_CASE 526
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 527 */
+#if ((527 >= GSL_INCLUDER_FIRST_CASE) && (527 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (527)))
+#define GSL_INCLUDER_CASE 527
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 528 */
+#if ((528 >= GSL_INCLUDER_FIRST_CASE) && (528 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (528)))
+#define GSL_INCLUDER_CASE 528
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 529 */
+#if ((529 >= GSL_INCLUDER_FIRST_CASE) && (529 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (529)))
+#define GSL_INCLUDER_CASE 529
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 530 */
+#if ((530 >= GSL_INCLUDER_FIRST_CASE) && (530 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (530)))
+#define GSL_INCLUDER_CASE 530
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 531 */
+#if ((531 >= GSL_INCLUDER_FIRST_CASE) && (531 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (531)))
+#define GSL_INCLUDER_CASE 531
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 532 */
+#if ((532 >= GSL_INCLUDER_FIRST_CASE) && (532 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (532)))
+#define GSL_INCLUDER_CASE 532
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 533 */
+#if ((533 >= GSL_INCLUDER_FIRST_CASE) && (533 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (533)))
+#define GSL_INCLUDER_CASE 533
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 534 */
+#if ((534 >= GSL_INCLUDER_FIRST_CASE) && (534 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (534)))
+#define GSL_INCLUDER_CASE 534
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 535 */
+#if ((535 >= GSL_INCLUDER_FIRST_CASE) && (535 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (535)))
+#define GSL_INCLUDER_CASE 535
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 536 */
+#if ((536 >= GSL_INCLUDER_FIRST_CASE) && (536 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (536)))
+#define GSL_INCLUDER_CASE 536
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 537 */
+#if ((537 >= GSL_INCLUDER_FIRST_CASE) && (537 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (537)))
+#define GSL_INCLUDER_CASE 537
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 538 */
+#if ((538 >= GSL_INCLUDER_FIRST_CASE) && (538 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (538)))
+#define GSL_INCLUDER_CASE 538
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 539 */
+#if ((539 >= GSL_INCLUDER_FIRST_CASE) && (539 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (539)))
+#define GSL_INCLUDER_CASE 539
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 540 */
+#if ((540 >= GSL_INCLUDER_FIRST_CASE) && (540 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (540)))
+#define GSL_INCLUDER_CASE 540
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 541 */
+#if ((541 >= GSL_INCLUDER_FIRST_CASE) && (541 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (541)))
+#define GSL_INCLUDER_CASE 541
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 542 */
+#if ((542 >= GSL_INCLUDER_FIRST_CASE) && (542 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (542)))
+#define GSL_INCLUDER_CASE 542
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 543 */
+#if ((543 >= GSL_INCLUDER_FIRST_CASE) && (543 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (543)))
+#define GSL_INCLUDER_CASE 543
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 544 */
+#if ((544 >= GSL_INCLUDER_FIRST_CASE) && (544 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (544)))
+#define GSL_INCLUDER_CASE 544
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 545 */
+#if ((545 >= GSL_INCLUDER_FIRST_CASE) && (545 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (545)))
+#define GSL_INCLUDER_CASE 545
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 546 */
+#if ((546 >= GSL_INCLUDER_FIRST_CASE) && (546 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (546)))
+#define GSL_INCLUDER_CASE 546
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 547 */
+#if ((547 >= GSL_INCLUDER_FIRST_CASE) && (547 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (547)))
+#define GSL_INCLUDER_CASE 547
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 548 */
+#if ((548 >= GSL_INCLUDER_FIRST_CASE) && (548 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (548)))
+#define GSL_INCLUDER_CASE 548
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 549 */
+#if ((549 >= GSL_INCLUDER_FIRST_CASE) && (549 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (549)))
+#define GSL_INCLUDER_CASE 549
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 550 */
+#if ((550 >= GSL_INCLUDER_FIRST_CASE) && (550 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (550)))
+#define GSL_INCLUDER_CASE 550
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 551 */
+#if ((551 >= GSL_INCLUDER_FIRST_CASE) && (551 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (551)))
+#define GSL_INCLUDER_CASE 551
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 552 */
+#if ((552 >= GSL_INCLUDER_FIRST_CASE) && (552 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (552)))
+#define GSL_INCLUDER_CASE 552
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 553 */
+#if ((553 >= GSL_INCLUDER_FIRST_CASE) && (553 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (553)))
+#define GSL_INCLUDER_CASE 553
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 554 */
+#if ((554 >= GSL_INCLUDER_FIRST_CASE) && (554 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (554)))
+#define GSL_INCLUDER_CASE 554
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 555 */
+#if ((555 >= GSL_INCLUDER_FIRST_CASE) && (555 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (555)))
+#define GSL_INCLUDER_CASE 555
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 556 */
+#if ((556 >= GSL_INCLUDER_FIRST_CASE) && (556 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (556)))
+#define GSL_INCLUDER_CASE 556
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 557 */
+#if ((557 >= GSL_INCLUDER_FIRST_CASE) && (557 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (557)))
+#define GSL_INCLUDER_CASE 557
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 558 */
+#if ((558 >= GSL_INCLUDER_FIRST_CASE) && (558 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (558)))
+#define GSL_INCLUDER_CASE 558
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 559 */
+#if ((559 >= GSL_INCLUDER_FIRST_CASE) && (559 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (559)))
+#define GSL_INCLUDER_CASE 559
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 560 */
+#if ((560 >= GSL_INCLUDER_FIRST_CASE) && (560 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (560)))
+#define GSL_INCLUDER_CASE 560
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 561 */
+#if ((561 >= GSL_INCLUDER_FIRST_CASE) && (561 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (561)))
+#define GSL_INCLUDER_CASE 561
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 562 */
+#if ((562 >= GSL_INCLUDER_FIRST_CASE) && (562 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (562)))
+#define GSL_INCLUDER_CASE 562
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 563 */
+#if ((563 >= GSL_INCLUDER_FIRST_CASE) && (563 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (563)))
+#define GSL_INCLUDER_CASE 563
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 564 */
+#if ((564 >= GSL_INCLUDER_FIRST_CASE) && (564 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (564)))
+#define GSL_INCLUDER_CASE 564
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 565 */
+#if ((565 >= GSL_INCLUDER_FIRST_CASE) && (565 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (565)))
+#define GSL_INCLUDER_CASE 565
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 566 */
+#if ((566 >= GSL_INCLUDER_FIRST_CASE) && (566 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (566)))
+#define GSL_INCLUDER_CASE 566
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 567 */
+#if ((567 >= GSL_INCLUDER_FIRST_CASE) && (567 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (567)))
+#define GSL_INCLUDER_CASE 567
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 568 */
+#if ((568 >= GSL_INCLUDER_FIRST_CASE) && (568 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (568)))
+#define GSL_INCLUDER_CASE 568
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 569 */
+#if ((569 >= GSL_INCLUDER_FIRST_CASE) && (569 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (569)))
+#define GSL_INCLUDER_CASE 569
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 570 */
+#if ((570 >= GSL_INCLUDER_FIRST_CASE) && (570 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (570)))
+#define GSL_INCLUDER_CASE 570
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 571 */
+#if ((571 >= GSL_INCLUDER_FIRST_CASE) && (571 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (571)))
+#define GSL_INCLUDER_CASE 571
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 572 */
+#if ((572 >= GSL_INCLUDER_FIRST_CASE) && (572 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (572)))
+#define GSL_INCLUDER_CASE 572
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 573 */
+#if ((573 >= GSL_INCLUDER_FIRST_CASE) && (573 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (573)))
+#define GSL_INCLUDER_CASE 573
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 574 */
+#if ((574 >= GSL_INCLUDER_FIRST_CASE) && (574 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (574)))
+#define GSL_INCLUDER_CASE 574
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 575 */
+#if ((575 >= GSL_INCLUDER_FIRST_CASE) && (575 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (575)))
+#define GSL_INCLUDER_CASE 575
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 576 */
+#if ((576 >= GSL_INCLUDER_FIRST_CASE) && (576 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (576)))
+#define GSL_INCLUDER_CASE 576
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 577 */
+#if ((577 >= GSL_INCLUDER_FIRST_CASE) && (577 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (577)))
+#define GSL_INCLUDER_CASE 577
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 578 */
+#if ((578 >= GSL_INCLUDER_FIRST_CASE) && (578 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (578)))
+#define GSL_INCLUDER_CASE 578
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 579 */
+#if ((579 >= GSL_INCLUDER_FIRST_CASE) && (579 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (579)))
+#define GSL_INCLUDER_CASE 579
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 580 */
+#if ((580 >= GSL_INCLUDER_FIRST_CASE) && (580 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (580)))
+#define GSL_INCLUDER_CASE 580
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 581 */
+#if ((581 >= GSL_INCLUDER_FIRST_CASE) && (581 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (581)))
+#define GSL_INCLUDER_CASE 581
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 582 */
+#if ((582 >= GSL_INCLUDER_FIRST_CASE) && (582 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (582)))
+#define GSL_INCLUDER_CASE 582
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 583 */
+#if ((583 >= GSL_INCLUDER_FIRST_CASE) && (583 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (583)))
+#define GSL_INCLUDER_CASE 583
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 584 */
+#if ((584 >= GSL_INCLUDER_FIRST_CASE) && (584 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (584)))
+#define GSL_INCLUDER_CASE 584
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 585 */
+#if ((585 >= GSL_INCLUDER_FIRST_CASE) && (585 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (585)))
+#define GSL_INCLUDER_CASE 585
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 586 */
+#if ((586 >= GSL_INCLUDER_FIRST_CASE) && (586 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (586)))
+#define GSL_INCLUDER_CASE 586
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 587 */
+#if ((587 >= GSL_INCLUDER_FIRST_CASE) && (587 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (587)))
+#define GSL_INCLUDER_CASE 587
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 588 */
+#if ((588 >= GSL_INCLUDER_FIRST_CASE) && (588 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (588)))
+#define GSL_INCLUDER_CASE 588
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 589 */
+#if ((589 >= GSL_INCLUDER_FIRST_CASE) && (589 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (589)))
+#define GSL_INCLUDER_CASE 589
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 590 */
+#if ((590 >= GSL_INCLUDER_FIRST_CASE) && (590 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (590)))
+#define GSL_INCLUDER_CASE 590
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 591 */
+#if ((591 >= GSL_INCLUDER_FIRST_CASE) && (591 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (591)))
+#define GSL_INCLUDER_CASE 591
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 592 */
+#if ((592 >= GSL_INCLUDER_FIRST_CASE) && (592 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (592)))
+#define GSL_INCLUDER_CASE 592
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 593 */
+#if ((593 >= GSL_INCLUDER_FIRST_CASE) && (593 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (593)))
+#define GSL_INCLUDER_CASE 593
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 594 */
+#if ((594 >= GSL_INCLUDER_FIRST_CASE) && (594 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (594)))
+#define GSL_INCLUDER_CASE 594
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 595 */
+#if ((595 >= GSL_INCLUDER_FIRST_CASE) && (595 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (595)))
+#define GSL_INCLUDER_CASE 595
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 596 */
+#if ((596 >= GSL_INCLUDER_FIRST_CASE) && (596 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (596)))
+#define GSL_INCLUDER_CASE 596
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 597 */
+#if ((597 >= GSL_INCLUDER_FIRST_CASE) && (597 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (597)))
+#define GSL_INCLUDER_CASE 597
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 598 */
+#if ((598 >= GSL_INCLUDER_FIRST_CASE) && (598 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (598)))
+#define GSL_INCLUDER_CASE 598
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 599 */
+#if ((599 >= GSL_INCLUDER_FIRST_CASE) && (599 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (599)))
+#define GSL_INCLUDER_CASE 599
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 600 */
+#if ((600 >= GSL_INCLUDER_FIRST_CASE) && (600 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (600)))
+#define GSL_INCLUDER_CASE 600
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 601 */
+#if ((601 >= GSL_INCLUDER_FIRST_CASE) && (601 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (601)))
+#define GSL_INCLUDER_CASE 601
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 602 */
+#if ((602 >= GSL_INCLUDER_FIRST_CASE) && (602 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (602)))
+#define GSL_INCLUDER_CASE 602
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 603 */
+#if ((603 >= GSL_INCLUDER_FIRST_CASE) && (603 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (603)))
+#define GSL_INCLUDER_CASE 603
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 604 */
+#if ((604 >= GSL_INCLUDER_FIRST_CASE) && (604 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (604)))
+#define GSL_INCLUDER_CASE 604
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 605 */
+#if ((605 >= GSL_INCLUDER_FIRST_CASE) && (605 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (605)))
+#define GSL_INCLUDER_CASE 605
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 606 */
+#if ((606 >= GSL_INCLUDER_FIRST_CASE) && (606 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (606)))
+#define GSL_INCLUDER_CASE 606
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 607 */
+#if ((607 >= GSL_INCLUDER_FIRST_CASE) && (607 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (607)))
+#define GSL_INCLUDER_CASE 607
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 608 */
+#if ((608 >= GSL_INCLUDER_FIRST_CASE) && (608 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (608)))
+#define GSL_INCLUDER_CASE 608
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 609 */
+#if ((609 >= GSL_INCLUDER_FIRST_CASE) && (609 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (609)))
+#define GSL_INCLUDER_CASE 609
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 610 */
+#if ((610 >= GSL_INCLUDER_FIRST_CASE) && (610 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (610)))
+#define GSL_INCLUDER_CASE 610
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 611 */
+#if ((611 >= GSL_INCLUDER_FIRST_CASE) && (611 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (611)))
+#define GSL_INCLUDER_CASE 611
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 612 */
+#if ((612 >= GSL_INCLUDER_FIRST_CASE) && (612 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (612)))
+#define GSL_INCLUDER_CASE 612
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 613 */
+#if ((613 >= GSL_INCLUDER_FIRST_CASE) && (613 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (613)))
+#define GSL_INCLUDER_CASE 613
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 614 */
+#if ((614 >= GSL_INCLUDER_FIRST_CASE) && (614 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (614)))
+#define GSL_INCLUDER_CASE 614
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 615 */
+#if ((615 >= GSL_INCLUDER_FIRST_CASE) && (615 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (615)))
+#define GSL_INCLUDER_CASE 615
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 616 */
+#if ((616 >= GSL_INCLUDER_FIRST_CASE) && (616 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (616)))
+#define GSL_INCLUDER_CASE 616
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 617 */
+#if ((617 >= GSL_INCLUDER_FIRST_CASE) && (617 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (617)))
+#define GSL_INCLUDER_CASE 617
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 618 */
+#if ((618 >= GSL_INCLUDER_FIRST_CASE) && (618 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (618)))
+#define GSL_INCLUDER_CASE 618
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 619 */
+#if ((619 >= GSL_INCLUDER_FIRST_CASE) && (619 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (619)))
+#define GSL_INCLUDER_CASE 619
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 620 */
+#if ((620 >= GSL_INCLUDER_FIRST_CASE) && (620 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (620)))
+#define GSL_INCLUDER_CASE 620
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 621 */
+#if ((621 >= GSL_INCLUDER_FIRST_CASE) && (621 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (621)))
+#define GSL_INCLUDER_CASE 621
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 622 */
+#if ((622 >= GSL_INCLUDER_FIRST_CASE) && (622 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (622)))
+#define GSL_INCLUDER_CASE 622
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 623 */
+#if ((623 >= GSL_INCLUDER_FIRST_CASE) && (623 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (623)))
+#define GSL_INCLUDER_CASE 623
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 624 */
+#if ((624 >= GSL_INCLUDER_FIRST_CASE) && (624 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (624)))
+#define GSL_INCLUDER_CASE 624
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 625 */
+#if ((625 >= GSL_INCLUDER_FIRST_CASE) && (625 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (625)))
+#define GSL_INCLUDER_CASE 625
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 626 */
+#if ((626 >= GSL_INCLUDER_FIRST_CASE) && (626 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (626)))
+#define GSL_INCLUDER_CASE 626
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 627 */
+#if ((627 >= GSL_INCLUDER_FIRST_CASE) && (627 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (627)))
+#define GSL_INCLUDER_CASE 627
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 628 */
+#if ((628 >= GSL_INCLUDER_FIRST_CASE) && (628 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (628)))
+#define GSL_INCLUDER_CASE 628
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 629 */
+#if ((629 >= GSL_INCLUDER_FIRST_CASE) && (629 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (629)))
+#define GSL_INCLUDER_CASE 629
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 630 */
+#if ((630 >= GSL_INCLUDER_FIRST_CASE) && (630 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (630)))
+#define GSL_INCLUDER_CASE 630
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 631 */
+#if ((631 >= GSL_INCLUDER_FIRST_CASE) && (631 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (631)))
+#define GSL_INCLUDER_CASE 631
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 632 */
+#if ((632 >= GSL_INCLUDER_FIRST_CASE) && (632 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (632)))
+#define GSL_INCLUDER_CASE 632
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 633 */
+#if ((633 >= GSL_INCLUDER_FIRST_CASE) && (633 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (633)))
+#define GSL_INCLUDER_CASE 633
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 634 */
+#if ((634 >= GSL_INCLUDER_FIRST_CASE) && (634 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (634)))
+#define GSL_INCLUDER_CASE 634
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 635 */
+#if ((635 >= GSL_INCLUDER_FIRST_CASE) && (635 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (635)))
+#define GSL_INCLUDER_CASE 635
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 636 */
+#if ((636 >= GSL_INCLUDER_FIRST_CASE) && (636 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (636)))
+#define GSL_INCLUDER_CASE 636
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 637 */
+#if ((637 >= GSL_INCLUDER_FIRST_CASE) && (637 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (637)))
+#define GSL_INCLUDER_CASE 637
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 638 */
+#if ((638 >= GSL_INCLUDER_FIRST_CASE) && (638 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (638)))
+#define GSL_INCLUDER_CASE 638
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 639 */
+#if ((639 >= GSL_INCLUDER_FIRST_CASE) && (639 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (639)))
+#define GSL_INCLUDER_CASE 639
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 640 */
+#if ((640 >= GSL_INCLUDER_FIRST_CASE) && (640 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (640)))
+#define GSL_INCLUDER_CASE 640
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 641 */
+#if ((641 >= GSL_INCLUDER_FIRST_CASE) && (641 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (641)))
+#define GSL_INCLUDER_CASE 641
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 642 */
+#if ((642 >= GSL_INCLUDER_FIRST_CASE) && (642 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (642)))
+#define GSL_INCLUDER_CASE 642
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 643 */
+#if ((643 >= GSL_INCLUDER_FIRST_CASE) && (643 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (643)))
+#define GSL_INCLUDER_CASE 643
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 644 */
+#if ((644 >= GSL_INCLUDER_FIRST_CASE) && (644 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (644)))
+#define GSL_INCLUDER_CASE 644
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 645 */
+#if ((645 >= GSL_INCLUDER_FIRST_CASE) && (645 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (645)))
+#define GSL_INCLUDER_CASE 645
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 646 */
+#if ((646 >= GSL_INCLUDER_FIRST_CASE) && (646 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (646)))
+#define GSL_INCLUDER_CASE 646
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 647 */
+#if ((647 >= GSL_INCLUDER_FIRST_CASE) && (647 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (647)))
+#define GSL_INCLUDER_CASE 647
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 648 */
+#if ((648 >= GSL_INCLUDER_FIRST_CASE) && (648 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (648)))
+#define GSL_INCLUDER_CASE 648
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 649 */
+#if ((649 >= GSL_INCLUDER_FIRST_CASE) && (649 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (649)))
+#define GSL_INCLUDER_CASE 649
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 650 */
+#if ((650 >= GSL_INCLUDER_FIRST_CASE) && (650 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (650)))
+#define GSL_INCLUDER_CASE 650
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 651 */
+#if ((651 >= GSL_INCLUDER_FIRST_CASE) && (651 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (651)))
+#define GSL_INCLUDER_CASE 651
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 652 */
+#if ((652 >= GSL_INCLUDER_FIRST_CASE) && (652 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (652)))
+#define GSL_INCLUDER_CASE 652
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 653 */
+#if ((653 >= GSL_INCLUDER_FIRST_CASE) && (653 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (653)))
+#define GSL_INCLUDER_CASE 653
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 654 */
+#if ((654 >= GSL_INCLUDER_FIRST_CASE) && (654 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (654)))
+#define GSL_INCLUDER_CASE 654
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 655 */
+#if ((655 >= GSL_INCLUDER_FIRST_CASE) && (655 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (655)))
+#define GSL_INCLUDER_CASE 655
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 656 */
+#if ((656 >= GSL_INCLUDER_FIRST_CASE) && (656 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (656)))
+#define GSL_INCLUDER_CASE 656
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 657 */
+#if ((657 >= GSL_INCLUDER_FIRST_CASE) && (657 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (657)))
+#define GSL_INCLUDER_CASE 657
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 658 */
+#if ((658 >= GSL_INCLUDER_FIRST_CASE) && (658 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (658)))
+#define GSL_INCLUDER_CASE 658
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 659 */
+#if ((659 >= GSL_INCLUDER_FIRST_CASE) && (659 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (659)))
+#define GSL_INCLUDER_CASE 659
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 660 */
+#if ((660 >= GSL_INCLUDER_FIRST_CASE) && (660 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (660)))
+#define GSL_INCLUDER_CASE 660
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 661 */
+#if ((661 >= GSL_INCLUDER_FIRST_CASE) && (661 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (661)))
+#define GSL_INCLUDER_CASE 661
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 662 */
+#if ((662 >= GSL_INCLUDER_FIRST_CASE) && (662 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (662)))
+#define GSL_INCLUDER_CASE 662
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 663 */
+#if ((663 >= GSL_INCLUDER_FIRST_CASE) && (663 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (663)))
+#define GSL_INCLUDER_CASE 663
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 664 */
+#if ((664 >= GSL_INCLUDER_FIRST_CASE) && (664 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (664)))
+#define GSL_INCLUDER_CASE 664
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 665 */
+#if ((665 >= GSL_INCLUDER_FIRST_CASE) && (665 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (665)))
+#define GSL_INCLUDER_CASE 665
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 666 */
+#if ((666 >= GSL_INCLUDER_FIRST_CASE) && (666 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (666)))
+#define GSL_INCLUDER_CASE 666
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 667 */
+#if ((667 >= GSL_INCLUDER_FIRST_CASE) && (667 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (667)))
+#define GSL_INCLUDER_CASE 667
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 668 */
+#if ((668 >= GSL_INCLUDER_FIRST_CASE) && (668 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (668)))
+#define GSL_INCLUDER_CASE 668
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 669 */
+#if ((669 >= GSL_INCLUDER_FIRST_CASE) && (669 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (669)))
+#define GSL_INCLUDER_CASE 669
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 670 */
+#if ((670 >= GSL_INCLUDER_FIRST_CASE) && (670 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (670)))
+#define GSL_INCLUDER_CASE 670
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 671 */
+#if ((671 >= GSL_INCLUDER_FIRST_CASE) && (671 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (671)))
+#define GSL_INCLUDER_CASE 671
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 672 */
+#if ((672 >= GSL_INCLUDER_FIRST_CASE) && (672 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (672)))
+#define GSL_INCLUDER_CASE 672
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 673 */
+#if ((673 >= GSL_INCLUDER_FIRST_CASE) && (673 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (673)))
+#define GSL_INCLUDER_CASE 673
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 674 */
+#if ((674 >= GSL_INCLUDER_FIRST_CASE) && (674 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (674)))
+#define GSL_INCLUDER_CASE 674
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 675 */
+#if ((675 >= GSL_INCLUDER_FIRST_CASE) && (675 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (675)))
+#define GSL_INCLUDER_CASE 675
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 676 */
+#if ((676 >= GSL_INCLUDER_FIRST_CASE) && (676 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (676)))
+#define GSL_INCLUDER_CASE 676
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 677 */
+#if ((677 >= GSL_INCLUDER_FIRST_CASE) && (677 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (677)))
+#define GSL_INCLUDER_CASE 677
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 678 */
+#if ((678 >= GSL_INCLUDER_FIRST_CASE) && (678 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (678)))
+#define GSL_INCLUDER_CASE 678
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 679 */
+#if ((679 >= GSL_INCLUDER_FIRST_CASE) && (679 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (679)))
+#define GSL_INCLUDER_CASE 679
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 680 */
+#if ((680 >= GSL_INCLUDER_FIRST_CASE) && (680 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (680)))
+#define GSL_INCLUDER_CASE 680
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 681 */
+#if ((681 >= GSL_INCLUDER_FIRST_CASE) && (681 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (681)))
+#define GSL_INCLUDER_CASE 681
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 682 */
+#if ((682 >= GSL_INCLUDER_FIRST_CASE) && (682 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (682)))
+#define GSL_INCLUDER_CASE 682
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 683 */
+#if ((683 >= GSL_INCLUDER_FIRST_CASE) && (683 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (683)))
+#define GSL_INCLUDER_CASE 683
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 684 */
+#if ((684 >= GSL_INCLUDER_FIRST_CASE) && (684 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (684)))
+#define GSL_INCLUDER_CASE 684
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 685 */
+#if ((685 >= GSL_INCLUDER_FIRST_CASE) && (685 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (685)))
+#define GSL_INCLUDER_CASE 685
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 686 */
+#if ((686 >= GSL_INCLUDER_FIRST_CASE) && (686 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (686)))
+#define GSL_INCLUDER_CASE 686
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 687 */
+#if ((687 >= GSL_INCLUDER_FIRST_CASE) && (687 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (687)))
+#define GSL_INCLUDER_CASE 687
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 688 */
+#if ((688 >= GSL_INCLUDER_FIRST_CASE) && (688 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (688)))
+#define GSL_INCLUDER_CASE 688
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 689 */
+#if ((689 >= GSL_INCLUDER_FIRST_CASE) && (689 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (689)))
+#define GSL_INCLUDER_CASE 689
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 690 */
+#if ((690 >= GSL_INCLUDER_FIRST_CASE) && (690 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (690)))
+#define GSL_INCLUDER_CASE 690
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 691 */
+#if ((691 >= GSL_INCLUDER_FIRST_CASE) && (691 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (691)))
+#define GSL_INCLUDER_CASE 691
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 692 */
+#if ((692 >= GSL_INCLUDER_FIRST_CASE) && (692 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (692)))
+#define GSL_INCLUDER_CASE 692
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 693 */
+#if ((693 >= GSL_INCLUDER_FIRST_CASE) && (693 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (693)))
+#define GSL_INCLUDER_CASE 693
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 694 */
+#if ((694 >= GSL_INCLUDER_FIRST_CASE) && (694 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (694)))
+#define GSL_INCLUDER_CASE 694
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 695 */
+#if ((695 >= GSL_INCLUDER_FIRST_CASE) && (695 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (695)))
+#define GSL_INCLUDER_CASE 695
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 696 */
+#if ((696 >= GSL_INCLUDER_FIRST_CASE) && (696 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (696)))
+#define GSL_INCLUDER_CASE 696
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 697 */
+#if ((697 >= GSL_INCLUDER_FIRST_CASE) && (697 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (697)))
+#define GSL_INCLUDER_CASE 697
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 698 */
+#if ((698 >= GSL_INCLUDER_FIRST_CASE) && (698 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (698)))
+#define GSL_INCLUDER_CASE 698
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 699 */
+#if ((699 >= GSL_INCLUDER_FIRST_CASE) && (699 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (699)))
+#define GSL_INCLUDER_CASE 699
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 700 */
+#if ((700 >= GSL_INCLUDER_FIRST_CASE) && (700 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (700)))
+#define GSL_INCLUDER_CASE 700
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 701 */
+#if ((701 >= GSL_INCLUDER_FIRST_CASE) && (701 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (701)))
+#define GSL_INCLUDER_CASE 701
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 702 */
+#if ((702 >= GSL_INCLUDER_FIRST_CASE) && (702 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (702)))
+#define GSL_INCLUDER_CASE 702
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 703 */
+#if ((703 >= GSL_INCLUDER_FIRST_CASE) && (703 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (703)))
+#define GSL_INCLUDER_CASE 703
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 704 */
+#if ((704 >= GSL_INCLUDER_FIRST_CASE) && (704 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (704)))
+#define GSL_INCLUDER_CASE 704
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 705 */
+#if ((705 >= GSL_INCLUDER_FIRST_CASE) && (705 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (705)))
+#define GSL_INCLUDER_CASE 705
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 706 */
+#if ((706 >= GSL_INCLUDER_FIRST_CASE) && (706 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (706)))
+#define GSL_INCLUDER_CASE 706
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 707 */
+#if ((707 >= GSL_INCLUDER_FIRST_CASE) && (707 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (707)))
+#define GSL_INCLUDER_CASE 707
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 708 */
+#if ((708 >= GSL_INCLUDER_FIRST_CASE) && (708 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (708)))
+#define GSL_INCLUDER_CASE 708
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 709 */
+#if ((709 >= GSL_INCLUDER_FIRST_CASE) && (709 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (709)))
+#define GSL_INCLUDER_CASE 709
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 710 */
+#if ((710 >= GSL_INCLUDER_FIRST_CASE) && (710 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (710)))
+#define GSL_INCLUDER_CASE 710
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 711 */
+#if ((711 >= GSL_INCLUDER_FIRST_CASE) && (711 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (711)))
+#define GSL_INCLUDER_CASE 711
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 712 */
+#if ((712 >= GSL_INCLUDER_FIRST_CASE) && (712 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (712)))
+#define GSL_INCLUDER_CASE 712
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 713 */
+#if ((713 >= GSL_INCLUDER_FIRST_CASE) && (713 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (713)))
+#define GSL_INCLUDER_CASE 713
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 714 */
+#if ((714 >= GSL_INCLUDER_FIRST_CASE) && (714 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (714)))
+#define GSL_INCLUDER_CASE 714
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 715 */
+#if ((715 >= GSL_INCLUDER_FIRST_CASE) && (715 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (715)))
+#define GSL_INCLUDER_CASE 715
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 716 */
+#if ((716 >= GSL_INCLUDER_FIRST_CASE) && (716 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (716)))
+#define GSL_INCLUDER_CASE 716
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 717 */
+#if ((717 >= GSL_INCLUDER_FIRST_CASE) && (717 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (717)))
+#define GSL_INCLUDER_CASE 717
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 718 */
+#if ((718 >= GSL_INCLUDER_FIRST_CASE) && (718 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (718)))
+#define GSL_INCLUDER_CASE 718
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 719 */
+#if ((719 >= GSL_INCLUDER_FIRST_CASE) && (719 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (719)))
+#define GSL_INCLUDER_CASE 719
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 720 */
+#if ((720 >= GSL_INCLUDER_FIRST_CASE) && (720 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (720)))
+#define GSL_INCLUDER_CASE 720
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 721 */
+#if ((721 >= GSL_INCLUDER_FIRST_CASE) && (721 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (721)))
+#define GSL_INCLUDER_CASE 721
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 722 */
+#if ((722 >= GSL_INCLUDER_FIRST_CASE) && (722 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (722)))
+#define GSL_INCLUDER_CASE 722
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 723 */
+#if ((723 >= GSL_INCLUDER_FIRST_CASE) && (723 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (723)))
+#define GSL_INCLUDER_CASE 723
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 724 */
+#if ((724 >= GSL_INCLUDER_FIRST_CASE) && (724 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (724)))
+#define GSL_INCLUDER_CASE 724
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 725 */
+#if ((725 >= GSL_INCLUDER_FIRST_CASE) && (725 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (725)))
+#define GSL_INCLUDER_CASE 725
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 726 */
+#if ((726 >= GSL_INCLUDER_FIRST_CASE) && (726 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (726)))
+#define GSL_INCLUDER_CASE 726
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 727 */
+#if ((727 >= GSL_INCLUDER_FIRST_CASE) && (727 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (727)))
+#define GSL_INCLUDER_CASE 727
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 728 */
+#if ((728 >= GSL_INCLUDER_FIRST_CASE) && (728 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (728)))
+#define GSL_INCLUDER_CASE 728
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 729 */
+#if ((729 >= GSL_INCLUDER_FIRST_CASE) && (729 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (729)))
+#define GSL_INCLUDER_CASE 729
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 730 */
+#if ((730 >= GSL_INCLUDER_FIRST_CASE) && (730 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (730)))
+#define GSL_INCLUDER_CASE 730
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 731 */
+#if ((731 >= GSL_INCLUDER_FIRST_CASE) && (731 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (731)))
+#define GSL_INCLUDER_CASE 731
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 732 */
+#if ((732 >= GSL_INCLUDER_FIRST_CASE) && (732 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (732)))
+#define GSL_INCLUDER_CASE 732
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 733 */
+#if ((733 >= GSL_INCLUDER_FIRST_CASE) && (733 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (733)))
+#define GSL_INCLUDER_CASE 733
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 734 */
+#if ((734 >= GSL_INCLUDER_FIRST_CASE) && (734 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (734)))
+#define GSL_INCLUDER_CASE 734
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 735 */
+#if ((735 >= GSL_INCLUDER_FIRST_CASE) && (735 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (735)))
+#define GSL_INCLUDER_CASE 735
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 736 */
+#if ((736 >= GSL_INCLUDER_FIRST_CASE) && (736 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (736)))
+#define GSL_INCLUDER_CASE 736
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 737 */
+#if ((737 >= GSL_INCLUDER_FIRST_CASE) && (737 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (737)))
+#define GSL_INCLUDER_CASE 737
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 738 */
+#if ((738 >= GSL_INCLUDER_FIRST_CASE) && (738 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (738)))
+#define GSL_INCLUDER_CASE 738
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 739 */
+#if ((739 >= GSL_INCLUDER_FIRST_CASE) && (739 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (739)))
+#define GSL_INCLUDER_CASE 739
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 740 */
+#if ((740 >= GSL_INCLUDER_FIRST_CASE) && (740 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (740)))
+#define GSL_INCLUDER_CASE 740
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 741 */
+#if ((741 >= GSL_INCLUDER_FIRST_CASE) && (741 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (741)))
+#define GSL_INCLUDER_CASE 741
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 742 */
+#if ((742 >= GSL_INCLUDER_FIRST_CASE) && (742 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (742)))
+#define GSL_INCLUDER_CASE 742
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 743 */
+#if ((743 >= GSL_INCLUDER_FIRST_CASE) && (743 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (743)))
+#define GSL_INCLUDER_CASE 743
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 744 */
+#if ((744 >= GSL_INCLUDER_FIRST_CASE) && (744 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (744)))
+#define GSL_INCLUDER_CASE 744
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 745 */
+#if ((745 >= GSL_INCLUDER_FIRST_CASE) && (745 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (745)))
+#define GSL_INCLUDER_CASE 745
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 746 */
+#if ((746 >= GSL_INCLUDER_FIRST_CASE) && (746 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (746)))
+#define GSL_INCLUDER_CASE 746
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 747 */
+#if ((747 >= GSL_INCLUDER_FIRST_CASE) && (747 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (747)))
+#define GSL_INCLUDER_CASE 747
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 748 */
+#if ((748 >= GSL_INCLUDER_FIRST_CASE) && (748 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (748)))
+#define GSL_INCLUDER_CASE 748
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 749 */
+#if ((749 >= GSL_INCLUDER_FIRST_CASE) && (749 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (749)))
+#define GSL_INCLUDER_CASE 749
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 750 */
+#if ((750 >= GSL_INCLUDER_FIRST_CASE) && (750 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (750)))
+#define GSL_INCLUDER_CASE 750
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 751 */
+#if ((751 >= GSL_INCLUDER_FIRST_CASE) && (751 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (751)))
+#define GSL_INCLUDER_CASE 751
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 752 */
+#if ((752 >= GSL_INCLUDER_FIRST_CASE) && (752 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (752)))
+#define GSL_INCLUDER_CASE 752
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 753 */
+#if ((753 >= GSL_INCLUDER_FIRST_CASE) && (753 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (753)))
+#define GSL_INCLUDER_CASE 753
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 754 */
+#if ((754 >= GSL_INCLUDER_FIRST_CASE) && (754 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (754)))
+#define GSL_INCLUDER_CASE 754
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 755 */
+#if ((755 >= GSL_INCLUDER_FIRST_CASE) && (755 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (755)))
+#define GSL_INCLUDER_CASE 755
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 756 */
+#if ((756 >= GSL_INCLUDER_FIRST_CASE) && (756 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (756)))
+#define GSL_INCLUDER_CASE 756
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 757 */
+#if ((757 >= GSL_INCLUDER_FIRST_CASE) && (757 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (757)))
+#define GSL_INCLUDER_CASE 757
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 758 */
+#if ((758 >= GSL_INCLUDER_FIRST_CASE) && (758 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (758)))
+#define GSL_INCLUDER_CASE 758
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 759 */
+#if ((759 >= GSL_INCLUDER_FIRST_CASE) && (759 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (759)))
+#define GSL_INCLUDER_CASE 759
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 760 */
+#if ((760 >= GSL_INCLUDER_FIRST_CASE) && (760 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (760)))
+#define GSL_INCLUDER_CASE 760
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 761 */
+#if ((761 >= GSL_INCLUDER_FIRST_CASE) && (761 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (761)))
+#define GSL_INCLUDER_CASE 761
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 762 */
+#if ((762 >= GSL_INCLUDER_FIRST_CASE) && (762 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (762)))
+#define GSL_INCLUDER_CASE 762
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 763 */
+#if ((763 >= GSL_INCLUDER_FIRST_CASE) && (763 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (763)))
+#define GSL_INCLUDER_CASE 763
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 764 */
+#if ((764 >= GSL_INCLUDER_FIRST_CASE) && (764 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (764)))
+#define GSL_INCLUDER_CASE 764
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 765 */
+#if ((765 >= GSL_INCLUDER_FIRST_CASE) && (765 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (765)))
+#define GSL_INCLUDER_CASE 765
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 766 */
+#if ((766 >= GSL_INCLUDER_FIRST_CASE) && (766 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (766)))
+#define GSL_INCLUDER_CASE 766
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 767 */
+#if ((767 >= GSL_INCLUDER_FIRST_CASE) && (767 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (767)))
+#define GSL_INCLUDER_CASE 767
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 768 */
+#if ((768 >= GSL_INCLUDER_FIRST_CASE) && (768 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (768)))
+#define GSL_INCLUDER_CASE 768
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 769 */
+#if ((769 >= GSL_INCLUDER_FIRST_CASE) && (769 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (769)))
+#define GSL_INCLUDER_CASE 769
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 770 */
+#if ((770 >= GSL_INCLUDER_FIRST_CASE) && (770 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (770)))
+#define GSL_INCLUDER_CASE 770
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 771 */
+#if ((771 >= GSL_INCLUDER_FIRST_CASE) && (771 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (771)))
+#define GSL_INCLUDER_CASE 771
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 772 */
+#if ((772 >= GSL_INCLUDER_FIRST_CASE) && (772 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (772)))
+#define GSL_INCLUDER_CASE 772
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 773 */
+#if ((773 >= GSL_INCLUDER_FIRST_CASE) && (773 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (773)))
+#define GSL_INCLUDER_CASE 773
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 774 */
+#if ((774 >= GSL_INCLUDER_FIRST_CASE) && (774 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (774)))
+#define GSL_INCLUDER_CASE 774
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 775 */
+#if ((775 >= GSL_INCLUDER_FIRST_CASE) && (775 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (775)))
+#define GSL_INCLUDER_CASE 775
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 776 */
+#if ((776 >= GSL_INCLUDER_FIRST_CASE) && (776 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (776)))
+#define GSL_INCLUDER_CASE 776
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 777 */
+#if ((777 >= GSL_INCLUDER_FIRST_CASE) && (777 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (777)))
+#define GSL_INCLUDER_CASE 777
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 778 */
+#if ((778 >= GSL_INCLUDER_FIRST_CASE) && (778 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (778)))
+#define GSL_INCLUDER_CASE 778
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 779 */
+#if ((779 >= GSL_INCLUDER_FIRST_CASE) && (779 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (779)))
+#define GSL_INCLUDER_CASE 779
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 780 */
+#if ((780 >= GSL_INCLUDER_FIRST_CASE) && (780 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (780)))
+#define GSL_INCLUDER_CASE 780
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 781 */
+#if ((781 >= GSL_INCLUDER_FIRST_CASE) && (781 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (781)))
+#define GSL_INCLUDER_CASE 781
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 782 */
+#if ((782 >= GSL_INCLUDER_FIRST_CASE) && (782 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (782)))
+#define GSL_INCLUDER_CASE 782
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 783 */
+#if ((783 >= GSL_INCLUDER_FIRST_CASE) && (783 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (783)))
+#define GSL_INCLUDER_CASE 783
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 784 */
+#if ((784 >= GSL_INCLUDER_FIRST_CASE) && (784 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (784)))
+#define GSL_INCLUDER_CASE 784
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 785 */
+#if ((785 >= GSL_INCLUDER_FIRST_CASE) && (785 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (785)))
+#define GSL_INCLUDER_CASE 785
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 786 */
+#if ((786 >= GSL_INCLUDER_FIRST_CASE) && (786 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (786)))
+#define GSL_INCLUDER_CASE 786
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 787 */
+#if ((787 >= GSL_INCLUDER_FIRST_CASE) && (787 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (787)))
+#define GSL_INCLUDER_CASE 787
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 788 */
+#if ((788 >= GSL_INCLUDER_FIRST_CASE) && (788 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (788)))
+#define GSL_INCLUDER_CASE 788
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 789 */
+#if ((789 >= GSL_INCLUDER_FIRST_CASE) && (789 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (789)))
+#define GSL_INCLUDER_CASE 789
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 790 */
+#if ((790 >= GSL_INCLUDER_FIRST_CASE) && (790 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (790)))
+#define GSL_INCLUDER_CASE 790
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 791 */
+#if ((791 >= GSL_INCLUDER_FIRST_CASE) && (791 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (791)))
+#define GSL_INCLUDER_CASE 791
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 792 */
+#if ((792 >= GSL_INCLUDER_FIRST_CASE) && (792 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (792)))
+#define GSL_INCLUDER_CASE 792
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 793 */
+#if ((793 >= GSL_INCLUDER_FIRST_CASE) && (793 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (793)))
+#define GSL_INCLUDER_CASE 793
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 794 */
+#if ((794 >= GSL_INCLUDER_FIRST_CASE) && (794 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (794)))
+#define GSL_INCLUDER_CASE 794
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 795 */
+#if ((795 >= GSL_INCLUDER_FIRST_CASE) && (795 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (795)))
+#define GSL_INCLUDER_CASE 795
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 796 */
+#if ((796 >= GSL_INCLUDER_FIRST_CASE) && (796 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (796)))
+#define GSL_INCLUDER_CASE 796
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 797 */
+#if ((797 >= GSL_INCLUDER_FIRST_CASE) && (797 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (797)))
+#define GSL_INCLUDER_CASE 797
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 798 */
+#if ((798 >= GSL_INCLUDER_FIRST_CASE) && (798 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (798)))
+#define GSL_INCLUDER_CASE 798
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 799 */
+#if ((799 >= GSL_INCLUDER_FIRST_CASE) && (799 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (799)))
+#define GSL_INCLUDER_CASE 799
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 800 */
+#if ((800 >= GSL_INCLUDER_FIRST_CASE) && (800 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (800)))
+#define GSL_INCLUDER_CASE 800
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 801 */
+#if ((801 >= GSL_INCLUDER_FIRST_CASE) && (801 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (801)))
+#define GSL_INCLUDER_CASE 801
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 802 */
+#if ((802 >= GSL_INCLUDER_FIRST_CASE) && (802 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (802)))
+#define GSL_INCLUDER_CASE 802
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 803 */
+#if ((803 >= GSL_INCLUDER_FIRST_CASE) && (803 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (803)))
+#define GSL_INCLUDER_CASE 803
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 804 */
+#if ((804 >= GSL_INCLUDER_FIRST_CASE) && (804 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (804)))
+#define GSL_INCLUDER_CASE 804
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 805 */
+#if ((805 >= GSL_INCLUDER_FIRST_CASE) && (805 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (805)))
+#define GSL_INCLUDER_CASE 805
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 806 */
+#if ((806 >= GSL_INCLUDER_FIRST_CASE) && (806 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (806)))
+#define GSL_INCLUDER_CASE 806
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 807 */
+#if ((807 >= GSL_INCLUDER_FIRST_CASE) && (807 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (807)))
+#define GSL_INCLUDER_CASE 807
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 808 */
+#if ((808 >= GSL_INCLUDER_FIRST_CASE) && (808 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (808)))
+#define GSL_INCLUDER_CASE 808
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 809 */
+#if ((809 >= GSL_INCLUDER_FIRST_CASE) && (809 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (809)))
+#define GSL_INCLUDER_CASE 809
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 810 */
+#if ((810 >= GSL_INCLUDER_FIRST_CASE) && (810 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (810)))
+#define GSL_INCLUDER_CASE 810
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 811 */
+#if ((811 >= GSL_INCLUDER_FIRST_CASE) && (811 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (811)))
+#define GSL_INCLUDER_CASE 811
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 812 */
+#if ((812 >= GSL_INCLUDER_FIRST_CASE) && (812 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (812)))
+#define GSL_INCLUDER_CASE 812
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 813 */
+#if ((813 >= GSL_INCLUDER_FIRST_CASE) && (813 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (813)))
+#define GSL_INCLUDER_CASE 813
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 814 */
+#if ((814 >= GSL_INCLUDER_FIRST_CASE) && (814 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (814)))
+#define GSL_INCLUDER_CASE 814
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 815 */
+#if ((815 >= GSL_INCLUDER_FIRST_CASE) && (815 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (815)))
+#define GSL_INCLUDER_CASE 815
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 816 */
+#if ((816 >= GSL_INCLUDER_FIRST_CASE) && (816 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (816)))
+#define GSL_INCLUDER_CASE 816
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 817 */
+#if ((817 >= GSL_INCLUDER_FIRST_CASE) && (817 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (817)))
+#define GSL_INCLUDER_CASE 817
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 818 */
+#if ((818 >= GSL_INCLUDER_FIRST_CASE) && (818 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (818)))
+#define GSL_INCLUDER_CASE 818
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 819 */
+#if ((819 >= GSL_INCLUDER_FIRST_CASE) && (819 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (819)))
+#define GSL_INCLUDER_CASE 819
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 820 */
+#if ((820 >= GSL_INCLUDER_FIRST_CASE) && (820 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (820)))
+#define GSL_INCLUDER_CASE 820
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 821 */
+#if ((821 >= GSL_INCLUDER_FIRST_CASE) && (821 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (821)))
+#define GSL_INCLUDER_CASE 821
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 822 */
+#if ((822 >= GSL_INCLUDER_FIRST_CASE) && (822 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (822)))
+#define GSL_INCLUDER_CASE 822
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 823 */
+#if ((823 >= GSL_INCLUDER_FIRST_CASE) && (823 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (823)))
+#define GSL_INCLUDER_CASE 823
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 824 */
+#if ((824 >= GSL_INCLUDER_FIRST_CASE) && (824 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (824)))
+#define GSL_INCLUDER_CASE 824
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 825 */
+#if ((825 >= GSL_INCLUDER_FIRST_CASE) && (825 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (825)))
+#define GSL_INCLUDER_CASE 825
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 826 */
+#if ((826 >= GSL_INCLUDER_FIRST_CASE) && (826 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (826)))
+#define GSL_INCLUDER_CASE 826
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 827 */
+#if ((827 >= GSL_INCLUDER_FIRST_CASE) && (827 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (827)))
+#define GSL_INCLUDER_CASE 827
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 828 */
+#if ((828 >= GSL_INCLUDER_FIRST_CASE) && (828 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (828)))
+#define GSL_INCLUDER_CASE 828
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 829 */
+#if ((829 >= GSL_INCLUDER_FIRST_CASE) && (829 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (829)))
+#define GSL_INCLUDER_CASE 829
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 830 */
+#if ((830 >= GSL_INCLUDER_FIRST_CASE) && (830 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (830)))
+#define GSL_INCLUDER_CASE 830
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 831 */
+#if ((831 >= GSL_INCLUDER_FIRST_CASE) && (831 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (831)))
+#define GSL_INCLUDER_CASE 831
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 832 */
+#if ((832 >= GSL_INCLUDER_FIRST_CASE) && (832 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (832)))
+#define GSL_INCLUDER_CASE 832
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 833 */
+#if ((833 >= GSL_INCLUDER_FIRST_CASE) && (833 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (833)))
+#define GSL_INCLUDER_CASE 833
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 834 */
+#if ((834 >= GSL_INCLUDER_FIRST_CASE) && (834 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (834)))
+#define GSL_INCLUDER_CASE 834
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 835 */
+#if ((835 >= GSL_INCLUDER_FIRST_CASE) && (835 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (835)))
+#define GSL_INCLUDER_CASE 835
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 836 */
+#if ((836 >= GSL_INCLUDER_FIRST_CASE) && (836 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (836)))
+#define GSL_INCLUDER_CASE 836
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 837 */
+#if ((837 >= GSL_INCLUDER_FIRST_CASE) && (837 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (837)))
+#define GSL_INCLUDER_CASE 837
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 838 */
+#if ((838 >= GSL_INCLUDER_FIRST_CASE) && (838 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (838)))
+#define GSL_INCLUDER_CASE 838
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 839 */
+#if ((839 >= GSL_INCLUDER_FIRST_CASE) && (839 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (839)))
+#define GSL_INCLUDER_CASE 839
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 840 */
+#if ((840 >= GSL_INCLUDER_FIRST_CASE) && (840 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (840)))
+#define GSL_INCLUDER_CASE 840
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 841 */
+#if ((841 >= GSL_INCLUDER_FIRST_CASE) && (841 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (841)))
+#define GSL_INCLUDER_CASE 841
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 842 */
+#if ((842 >= GSL_INCLUDER_FIRST_CASE) && (842 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (842)))
+#define GSL_INCLUDER_CASE 842
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 843 */
+#if ((843 >= GSL_INCLUDER_FIRST_CASE) && (843 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (843)))
+#define GSL_INCLUDER_CASE 843
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 844 */
+#if ((844 >= GSL_INCLUDER_FIRST_CASE) && (844 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (844)))
+#define GSL_INCLUDER_CASE 844
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 845 */
+#if ((845 >= GSL_INCLUDER_FIRST_CASE) && (845 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (845)))
+#define GSL_INCLUDER_CASE 845
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 846 */
+#if ((846 >= GSL_INCLUDER_FIRST_CASE) && (846 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (846)))
+#define GSL_INCLUDER_CASE 846
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 847 */
+#if ((847 >= GSL_INCLUDER_FIRST_CASE) && (847 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (847)))
+#define GSL_INCLUDER_CASE 847
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 848 */
+#if ((848 >= GSL_INCLUDER_FIRST_CASE) && (848 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (848)))
+#define GSL_INCLUDER_CASE 848
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 849 */
+#if ((849 >= GSL_INCLUDER_FIRST_CASE) && (849 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (849)))
+#define GSL_INCLUDER_CASE 849
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 850 */
+#if ((850 >= GSL_INCLUDER_FIRST_CASE) && (850 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (850)))
+#define GSL_INCLUDER_CASE 850
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 851 */
+#if ((851 >= GSL_INCLUDER_FIRST_CASE) && (851 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (851)))
+#define GSL_INCLUDER_CASE 851
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 852 */
+#if ((852 >= GSL_INCLUDER_FIRST_CASE) && (852 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (852)))
+#define GSL_INCLUDER_CASE 852
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 853 */
+#if ((853 >= GSL_INCLUDER_FIRST_CASE) && (853 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (853)))
+#define GSL_INCLUDER_CASE 853
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 854 */
+#if ((854 >= GSL_INCLUDER_FIRST_CASE) && (854 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (854)))
+#define GSL_INCLUDER_CASE 854
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 855 */
+#if ((855 >= GSL_INCLUDER_FIRST_CASE) && (855 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (855)))
+#define GSL_INCLUDER_CASE 855
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 856 */
+#if ((856 >= GSL_INCLUDER_FIRST_CASE) && (856 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (856)))
+#define GSL_INCLUDER_CASE 856
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 857 */
+#if ((857 >= GSL_INCLUDER_FIRST_CASE) && (857 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (857)))
+#define GSL_INCLUDER_CASE 857
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 858 */
+#if ((858 >= GSL_INCLUDER_FIRST_CASE) && (858 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (858)))
+#define GSL_INCLUDER_CASE 858
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 859 */
+#if ((859 >= GSL_INCLUDER_FIRST_CASE) && (859 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (859)))
+#define GSL_INCLUDER_CASE 859
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 860 */
+#if ((860 >= GSL_INCLUDER_FIRST_CASE) && (860 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (860)))
+#define GSL_INCLUDER_CASE 860
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 861 */
+#if ((861 >= GSL_INCLUDER_FIRST_CASE) && (861 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (861)))
+#define GSL_INCLUDER_CASE 861
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 862 */
+#if ((862 >= GSL_INCLUDER_FIRST_CASE) && (862 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (862)))
+#define GSL_INCLUDER_CASE 862
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 863 */
+#if ((863 >= GSL_INCLUDER_FIRST_CASE) && (863 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (863)))
+#define GSL_INCLUDER_CASE 863
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 864 */
+#if ((864 >= GSL_INCLUDER_FIRST_CASE) && (864 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (864)))
+#define GSL_INCLUDER_CASE 864
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 865 */
+#if ((865 >= GSL_INCLUDER_FIRST_CASE) && (865 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (865)))
+#define GSL_INCLUDER_CASE 865
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 866 */
+#if ((866 >= GSL_INCLUDER_FIRST_CASE) && (866 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (866)))
+#define GSL_INCLUDER_CASE 866
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 867 */
+#if ((867 >= GSL_INCLUDER_FIRST_CASE) && (867 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (867)))
+#define GSL_INCLUDER_CASE 867
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 868 */
+#if ((868 >= GSL_INCLUDER_FIRST_CASE) && (868 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (868)))
+#define GSL_INCLUDER_CASE 868
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 869 */
+#if ((869 >= GSL_INCLUDER_FIRST_CASE) && (869 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (869)))
+#define GSL_INCLUDER_CASE 869
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 870 */
+#if ((870 >= GSL_INCLUDER_FIRST_CASE) && (870 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (870)))
+#define GSL_INCLUDER_CASE 870
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 871 */
+#if ((871 >= GSL_INCLUDER_FIRST_CASE) && (871 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (871)))
+#define GSL_INCLUDER_CASE 871
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 872 */
+#if ((872 >= GSL_INCLUDER_FIRST_CASE) && (872 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (872)))
+#define GSL_INCLUDER_CASE 872
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 873 */
+#if ((873 >= GSL_INCLUDER_FIRST_CASE) && (873 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (873)))
+#define GSL_INCLUDER_CASE 873
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 874 */
+#if ((874 >= GSL_INCLUDER_FIRST_CASE) && (874 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (874)))
+#define GSL_INCLUDER_CASE 874
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 875 */
+#if ((875 >= GSL_INCLUDER_FIRST_CASE) && (875 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (875)))
+#define GSL_INCLUDER_CASE 875
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 876 */
+#if ((876 >= GSL_INCLUDER_FIRST_CASE) && (876 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (876)))
+#define GSL_INCLUDER_CASE 876
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 877 */
+#if ((877 >= GSL_INCLUDER_FIRST_CASE) && (877 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (877)))
+#define GSL_INCLUDER_CASE 877
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 878 */
+#if ((878 >= GSL_INCLUDER_FIRST_CASE) && (878 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (878)))
+#define GSL_INCLUDER_CASE 878
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 879 */
+#if ((879 >= GSL_INCLUDER_FIRST_CASE) && (879 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (879)))
+#define GSL_INCLUDER_CASE 879
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 880 */
+#if ((880 >= GSL_INCLUDER_FIRST_CASE) && (880 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (880)))
+#define GSL_INCLUDER_CASE 880
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 881 */
+#if ((881 >= GSL_INCLUDER_FIRST_CASE) && (881 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (881)))
+#define GSL_INCLUDER_CASE 881
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 882 */
+#if ((882 >= GSL_INCLUDER_FIRST_CASE) && (882 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (882)))
+#define GSL_INCLUDER_CASE 882
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 883 */
+#if ((883 >= GSL_INCLUDER_FIRST_CASE) && (883 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (883)))
+#define GSL_INCLUDER_CASE 883
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 884 */
+#if ((884 >= GSL_INCLUDER_FIRST_CASE) && (884 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (884)))
+#define GSL_INCLUDER_CASE 884
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 885 */
+#if ((885 >= GSL_INCLUDER_FIRST_CASE) && (885 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (885)))
+#define GSL_INCLUDER_CASE 885
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 886 */
+#if ((886 >= GSL_INCLUDER_FIRST_CASE) && (886 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (886)))
+#define GSL_INCLUDER_CASE 886
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 887 */
+#if ((887 >= GSL_INCLUDER_FIRST_CASE) && (887 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (887)))
+#define GSL_INCLUDER_CASE 887
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 888 */
+#if ((888 >= GSL_INCLUDER_FIRST_CASE) && (888 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (888)))
+#define GSL_INCLUDER_CASE 888
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 889 */
+#if ((889 >= GSL_INCLUDER_FIRST_CASE) && (889 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (889)))
+#define GSL_INCLUDER_CASE 889
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 890 */
+#if ((890 >= GSL_INCLUDER_FIRST_CASE) && (890 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (890)))
+#define GSL_INCLUDER_CASE 890
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 891 */
+#if ((891 >= GSL_INCLUDER_FIRST_CASE) && (891 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (891)))
+#define GSL_INCLUDER_CASE 891
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 892 */
+#if ((892 >= GSL_INCLUDER_FIRST_CASE) && (892 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (892)))
+#define GSL_INCLUDER_CASE 892
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 893 */
+#if ((893 >= GSL_INCLUDER_FIRST_CASE) && (893 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (893)))
+#define GSL_INCLUDER_CASE 893
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 894 */
+#if ((894 >= GSL_INCLUDER_FIRST_CASE) && (894 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (894)))
+#define GSL_INCLUDER_CASE 894
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 895 */
+#if ((895 >= GSL_INCLUDER_FIRST_CASE) && (895 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (895)))
+#define GSL_INCLUDER_CASE 895
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 896 */
+#if ((896 >= GSL_INCLUDER_FIRST_CASE) && (896 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (896)))
+#define GSL_INCLUDER_CASE 896
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 897 */
+#if ((897 >= GSL_INCLUDER_FIRST_CASE) && (897 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (897)))
+#define GSL_INCLUDER_CASE 897
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 898 */
+#if ((898 >= GSL_INCLUDER_FIRST_CASE) && (898 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (898)))
+#define GSL_INCLUDER_CASE 898
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 899 */
+#if ((899 >= GSL_INCLUDER_FIRST_CASE) && (899 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (899)))
+#define GSL_INCLUDER_CASE 899
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 900 */
+#if ((900 >= GSL_INCLUDER_FIRST_CASE) && (900 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (900)))
+#define GSL_INCLUDER_CASE 900
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 901 */
+#if ((901 >= GSL_INCLUDER_FIRST_CASE) && (901 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (901)))
+#define GSL_INCLUDER_CASE 901
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 902 */
+#if ((902 >= GSL_INCLUDER_FIRST_CASE) && (902 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (902)))
+#define GSL_INCLUDER_CASE 902
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 903 */
+#if ((903 >= GSL_INCLUDER_FIRST_CASE) && (903 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (903)))
+#define GSL_INCLUDER_CASE 903
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 904 */
+#if ((904 >= GSL_INCLUDER_FIRST_CASE) && (904 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (904)))
+#define GSL_INCLUDER_CASE 904
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 905 */
+#if ((905 >= GSL_INCLUDER_FIRST_CASE) && (905 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (905)))
+#define GSL_INCLUDER_CASE 905
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 906 */
+#if ((906 >= GSL_INCLUDER_FIRST_CASE) && (906 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (906)))
+#define GSL_INCLUDER_CASE 906
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 907 */
+#if ((907 >= GSL_INCLUDER_FIRST_CASE) && (907 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (907)))
+#define GSL_INCLUDER_CASE 907
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 908 */
+#if ((908 >= GSL_INCLUDER_FIRST_CASE) && (908 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (908)))
+#define GSL_INCLUDER_CASE 908
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 909 */
+#if ((909 >= GSL_INCLUDER_FIRST_CASE) && (909 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (909)))
+#define GSL_INCLUDER_CASE 909
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 910 */
+#if ((910 >= GSL_INCLUDER_FIRST_CASE) && (910 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (910)))
+#define GSL_INCLUDER_CASE 910
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 911 */
+#if ((911 >= GSL_INCLUDER_FIRST_CASE) && (911 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (911)))
+#define GSL_INCLUDER_CASE 911
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 912 */
+#if ((912 >= GSL_INCLUDER_FIRST_CASE) && (912 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (912)))
+#define GSL_INCLUDER_CASE 912
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 913 */
+#if ((913 >= GSL_INCLUDER_FIRST_CASE) && (913 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (913)))
+#define GSL_INCLUDER_CASE 913
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 914 */
+#if ((914 >= GSL_INCLUDER_FIRST_CASE) && (914 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (914)))
+#define GSL_INCLUDER_CASE 914
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 915 */
+#if ((915 >= GSL_INCLUDER_FIRST_CASE) && (915 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (915)))
+#define GSL_INCLUDER_CASE 915
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 916 */
+#if ((916 >= GSL_INCLUDER_FIRST_CASE) && (916 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (916)))
+#define GSL_INCLUDER_CASE 916
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 917 */
+#if ((917 >= GSL_INCLUDER_FIRST_CASE) && (917 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (917)))
+#define GSL_INCLUDER_CASE 917
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 918 */
+#if ((918 >= GSL_INCLUDER_FIRST_CASE) && (918 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (918)))
+#define GSL_INCLUDER_CASE 918
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 919 */
+#if ((919 >= GSL_INCLUDER_FIRST_CASE) && (919 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (919)))
+#define GSL_INCLUDER_CASE 919
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 920 */
+#if ((920 >= GSL_INCLUDER_FIRST_CASE) && (920 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (920)))
+#define GSL_INCLUDER_CASE 920
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 921 */
+#if ((921 >= GSL_INCLUDER_FIRST_CASE) && (921 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (921)))
+#define GSL_INCLUDER_CASE 921
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 922 */
+#if ((922 >= GSL_INCLUDER_FIRST_CASE) && (922 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (922)))
+#define GSL_INCLUDER_CASE 922
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 923 */
+#if ((923 >= GSL_INCLUDER_FIRST_CASE) && (923 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (923)))
+#define GSL_INCLUDER_CASE 923
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 924 */
+#if ((924 >= GSL_INCLUDER_FIRST_CASE) && (924 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (924)))
+#define GSL_INCLUDER_CASE 924
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 925 */
+#if ((925 >= GSL_INCLUDER_FIRST_CASE) && (925 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (925)))
+#define GSL_INCLUDER_CASE 925
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 926 */
+#if ((926 >= GSL_INCLUDER_FIRST_CASE) && (926 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (926)))
+#define GSL_INCLUDER_CASE 926
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 927 */
+#if ((927 >= GSL_INCLUDER_FIRST_CASE) && (927 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (927)))
+#define GSL_INCLUDER_CASE 927
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 928 */
+#if ((928 >= GSL_INCLUDER_FIRST_CASE) && (928 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (928)))
+#define GSL_INCLUDER_CASE 928
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 929 */
+#if ((929 >= GSL_INCLUDER_FIRST_CASE) && (929 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (929)))
+#define GSL_INCLUDER_CASE 929
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 930 */
+#if ((930 >= GSL_INCLUDER_FIRST_CASE) && (930 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (930)))
+#define GSL_INCLUDER_CASE 930
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 931 */
+#if ((931 >= GSL_INCLUDER_FIRST_CASE) && (931 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (931)))
+#define GSL_INCLUDER_CASE 931
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 932 */
+#if ((932 >= GSL_INCLUDER_FIRST_CASE) && (932 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (932)))
+#define GSL_INCLUDER_CASE 932
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 933 */
+#if ((933 >= GSL_INCLUDER_FIRST_CASE) && (933 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (933)))
+#define GSL_INCLUDER_CASE 933
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 934 */
+#if ((934 >= GSL_INCLUDER_FIRST_CASE) && (934 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (934)))
+#define GSL_INCLUDER_CASE 934
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 935 */
+#if ((935 >= GSL_INCLUDER_FIRST_CASE) && (935 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (935)))
+#define GSL_INCLUDER_CASE 935
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 936 */
+#if ((936 >= GSL_INCLUDER_FIRST_CASE) && (936 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (936)))
+#define GSL_INCLUDER_CASE 936
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 937 */
+#if ((937 >= GSL_INCLUDER_FIRST_CASE) && (937 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (937)))
+#define GSL_INCLUDER_CASE 937
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 938 */
+#if ((938 >= GSL_INCLUDER_FIRST_CASE) && (938 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (938)))
+#define GSL_INCLUDER_CASE 938
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 939 */
+#if ((939 >= GSL_INCLUDER_FIRST_CASE) && (939 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (939)))
+#define GSL_INCLUDER_CASE 939
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 940 */
+#if ((940 >= GSL_INCLUDER_FIRST_CASE) && (940 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (940)))
+#define GSL_INCLUDER_CASE 940
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 941 */
+#if ((941 >= GSL_INCLUDER_FIRST_CASE) && (941 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (941)))
+#define GSL_INCLUDER_CASE 941
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 942 */
+#if ((942 >= GSL_INCLUDER_FIRST_CASE) && (942 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (942)))
+#define GSL_INCLUDER_CASE 942
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 943 */
+#if ((943 >= GSL_INCLUDER_FIRST_CASE) && (943 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (943)))
+#define GSL_INCLUDER_CASE 943
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 944 */
+#if ((944 >= GSL_INCLUDER_FIRST_CASE) && (944 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (944)))
+#define GSL_INCLUDER_CASE 944
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 945 */
+#if ((945 >= GSL_INCLUDER_FIRST_CASE) && (945 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (945)))
+#define GSL_INCLUDER_CASE 945
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 946 */
+#if ((946 >= GSL_INCLUDER_FIRST_CASE) && (946 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (946)))
+#define GSL_INCLUDER_CASE 946
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 947 */
+#if ((947 >= GSL_INCLUDER_FIRST_CASE) && (947 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (947)))
+#define GSL_INCLUDER_CASE 947
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 948 */
+#if ((948 >= GSL_INCLUDER_FIRST_CASE) && (948 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (948)))
+#define GSL_INCLUDER_CASE 948
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 949 */
+#if ((949 >= GSL_INCLUDER_FIRST_CASE) && (949 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (949)))
+#define GSL_INCLUDER_CASE 949
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 950 */
+#if ((950 >= GSL_INCLUDER_FIRST_CASE) && (950 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (950)))
+#define GSL_INCLUDER_CASE 950
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 951 */
+#if ((951 >= GSL_INCLUDER_FIRST_CASE) && (951 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (951)))
+#define GSL_INCLUDER_CASE 951
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 952 */
+#if ((952 >= GSL_INCLUDER_FIRST_CASE) && (952 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (952)))
+#define GSL_INCLUDER_CASE 952
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 953 */
+#if ((953 >= GSL_INCLUDER_FIRST_CASE) && (953 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (953)))
+#define GSL_INCLUDER_CASE 953
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 954 */
+#if ((954 >= GSL_INCLUDER_FIRST_CASE) && (954 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (954)))
+#define GSL_INCLUDER_CASE 954
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 955 */
+#if ((955 >= GSL_INCLUDER_FIRST_CASE) && (955 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (955)))
+#define GSL_INCLUDER_CASE 955
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 956 */
+#if ((956 >= GSL_INCLUDER_FIRST_CASE) && (956 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (956)))
+#define GSL_INCLUDER_CASE 956
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 957 */
+#if ((957 >= GSL_INCLUDER_FIRST_CASE) && (957 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (957)))
+#define GSL_INCLUDER_CASE 957
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 958 */
+#if ((958 >= GSL_INCLUDER_FIRST_CASE) && (958 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (958)))
+#define GSL_INCLUDER_CASE 958
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 959 */
+#if ((959 >= GSL_INCLUDER_FIRST_CASE) && (959 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (959)))
+#define GSL_INCLUDER_CASE 959
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 960 */
+#if ((960 >= GSL_INCLUDER_FIRST_CASE) && (960 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (960)))
+#define GSL_INCLUDER_CASE 960
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 961 */
+#if ((961 >= GSL_INCLUDER_FIRST_CASE) && (961 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (961)))
+#define GSL_INCLUDER_CASE 961
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 962 */
+#if ((962 >= GSL_INCLUDER_FIRST_CASE) && (962 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (962)))
+#define GSL_INCLUDER_CASE 962
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 963 */
+#if ((963 >= GSL_INCLUDER_FIRST_CASE) && (963 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (963)))
+#define GSL_INCLUDER_CASE 963
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 964 */
+#if ((964 >= GSL_INCLUDER_FIRST_CASE) && (964 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (964)))
+#define GSL_INCLUDER_CASE 964
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 965 */
+#if ((965 >= GSL_INCLUDER_FIRST_CASE) && (965 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (965)))
+#define GSL_INCLUDER_CASE 965
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 966 */
+#if ((966 >= GSL_INCLUDER_FIRST_CASE) && (966 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (966)))
+#define GSL_INCLUDER_CASE 966
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 967 */
+#if ((967 >= GSL_INCLUDER_FIRST_CASE) && (967 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (967)))
+#define GSL_INCLUDER_CASE 967
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 968 */
+#if ((968 >= GSL_INCLUDER_FIRST_CASE) && (968 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (968)))
+#define GSL_INCLUDER_CASE 968
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 969 */
+#if ((969 >= GSL_INCLUDER_FIRST_CASE) && (969 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (969)))
+#define GSL_INCLUDER_CASE 969
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 970 */
+#if ((970 >= GSL_INCLUDER_FIRST_CASE) && (970 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (970)))
+#define GSL_INCLUDER_CASE 970
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 971 */
+#if ((971 >= GSL_INCLUDER_FIRST_CASE) && (971 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (971)))
+#define GSL_INCLUDER_CASE 971
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 972 */
+#if ((972 >= GSL_INCLUDER_FIRST_CASE) && (972 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (972)))
+#define GSL_INCLUDER_CASE 972
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 973 */
+#if ((973 >= GSL_INCLUDER_FIRST_CASE) && (973 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (973)))
+#define GSL_INCLUDER_CASE 973
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 974 */
+#if ((974 >= GSL_INCLUDER_FIRST_CASE) && (974 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (974)))
+#define GSL_INCLUDER_CASE 974
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 975 */
+#if ((975 >= GSL_INCLUDER_FIRST_CASE) && (975 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (975)))
+#define GSL_INCLUDER_CASE 975
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 976 */
+#if ((976 >= GSL_INCLUDER_FIRST_CASE) && (976 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (976)))
+#define GSL_INCLUDER_CASE 976
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 977 */
+#if ((977 >= GSL_INCLUDER_FIRST_CASE) && (977 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (977)))
+#define GSL_INCLUDER_CASE 977
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 978 */
+#if ((978 >= GSL_INCLUDER_FIRST_CASE) && (978 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (978)))
+#define GSL_INCLUDER_CASE 978
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 979 */
+#if ((979 >= GSL_INCLUDER_FIRST_CASE) && (979 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (979)))
+#define GSL_INCLUDER_CASE 979
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 980 */
+#if ((980 >= GSL_INCLUDER_FIRST_CASE) && (980 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (980)))
+#define GSL_INCLUDER_CASE 980
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 981 */
+#if ((981 >= GSL_INCLUDER_FIRST_CASE) && (981 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (981)))
+#define GSL_INCLUDER_CASE 981
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 982 */
+#if ((982 >= GSL_INCLUDER_FIRST_CASE) && (982 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (982)))
+#define GSL_INCLUDER_CASE 982
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 983 */
+#if ((983 >= GSL_INCLUDER_FIRST_CASE) && (983 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (983)))
+#define GSL_INCLUDER_CASE 983
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 984 */
+#if ((984 >= GSL_INCLUDER_FIRST_CASE) && (984 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (984)))
+#define GSL_INCLUDER_CASE 984
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 985 */
+#if ((985 >= GSL_INCLUDER_FIRST_CASE) && (985 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (985)))
+#define GSL_INCLUDER_CASE 985
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 986 */
+#if ((986 >= GSL_INCLUDER_FIRST_CASE) && (986 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (986)))
+#define GSL_INCLUDER_CASE 986
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 987 */
+#if ((987 >= GSL_INCLUDER_FIRST_CASE) && (987 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (987)))
+#define GSL_INCLUDER_CASE 987
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 988 */
+#if ((988 >= GSL_INCLUDER_FIRST_CASE) && (988 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (988)))
+#define GSL_INCLUDER_CASE 988
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 989 */
+#if ((989 >= GSL_INCLUDER_FIRST_CASE) && (989 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (989)))
+#define GSL_INCLUDER_CASE 989
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 990 */
+#if ((990 >= GSL_INCLUDER_FIRST_CASE) && (990 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (990)))
+#define GSL_INCLUDER_CASE 990
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 991 */
+#if ((991 >= GSL_INCLUDER_FIRST_CASE) && (991 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (991)))
+#define GSL_INCLUDER_CASE 991
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 992 */
+#if ((992 >= GSL_INCLUDER_FIRST_CASE) && (992 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (992)))
+#define GSL_INCLUDER_CASE 992
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 993 */
+#if ((993 >= GSL_INCLUDER_FIRST_CASE) && (993 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (993)))
+#define GSL_INCLUDER_CASE 993
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 994 */
+#if ((994 >= GSL_INCLUDER_FIRST_CASE) && (994 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (994)))
+#define GSL_INCLUDER_CASE 994
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 995 */
+#if ((995 >= GSL_INCLUDER_FIRST_CASE) && (995 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (995)))
+#define GSL_INCLUDER_CASE 995
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 996 */
+#if ((996 >= GSL_INCLUDER_FIRST_CASE) && (996 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (996)))
+#define GSL_INCLUDER_CASE 996
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 997 */
+#if ((997 >= GSL_INCLUDER_FIRST_CASE) && (997 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (997)))
+#define GSL_INCLUDER_CASE 997
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 998 */
+#if ((998 >= GSL_INCLUDER_FIRST_CASE) && (998 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (998)))
+#define GSL_INCLUDER_CASE 998
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 999 */
+#if ((999 >= GSL_INCLUDER_FIRST_CASE) && (999 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (999)))
+#define GSL_INCLUDER_CASE 999
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1000 */
+#if ((1000 >= GSL_INCLUDER_FIRST_CASE) && (1000 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1000)))
+#define GSL_INCLUDER_CASE 1000
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1001 */
+#if ((1001 >= GSL_INCLUDER_FIRST_CASE) && (1001 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1001)))
+#define GSL_INCLUDER_CASE 1001
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1002 */
+#if ((1002 >= GSL_INCLUDER_FIRST_CASE) && (1002 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1002)))
+#define GSL_INCLUDER_CASE 1002
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1003 */
+#if ((1003 >= GSL_INCLUDER_FIRST_CASE) && (1003 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1003)))
+#define GSL_INCLUDER_CASE 1003
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1004 */
+#if ((1004 >= GSL_INCLUDER_FIRST_CASE) && (1004 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1004)))
+#define GSL_INCLUDER_CASE 1004
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1005 */
+#if ((1005 >= GSL_INCLUDER_FIRST_CASE) && (1005 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1005)))
+#define GSL_INCLUDER_CASE 1005
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1006 */
+#if ((1006 >= GSL_INCLUDER_FIRST_CASE) && (1006 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1006)))
+#define GSL_INCLUDER_CASE 1006
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1007 */
+#if ((1007 >= GSL_INCLUDER_FIRST_CASE) && (1007 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1007)))
+#define GSL_INCLUDER_CASE 1007
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1008 */
+#if ((1008 >= GSL_INCLUDER_FIRST_CASE) && (1008 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1008)))
+#define GSL_INCLUDER_CASE 1008
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1009 */
+#if ((1009 >= GSL_INCLUDER_FIRST_CASE) && (1009 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1009)))
+#define GSL_INCLUDER_CASE 1009
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1010 */
+#if ((1010 >= GSL_INCLUDER_FIRST_CASE) && (1010 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1010)))
+#define GSL_INCLUDER_CASE 1010
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1011 */
+#if ((1011 >= GSL_INCLUDER_FIRST_CASE) && (1011 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1011)))
+#define GSL_INCLUDER_CASE 1011
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1012 */
+#if ((1012 >= GSL_INCLUDER_FIRST_CASE) && (1012 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1012)))
+#define GSL_INCLUDER_CASE 1012
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1013 */
+#if ((1013 >= GSL_INCLUDER_FIRST_CASE) && (1013 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1013)))
+#define GSL_INCLUDER_CASE 1013
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1014 */
+#if ((1014 >= GSL_INCLUDER_FIRST_CASE) && (1014 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1014)))
+#define GSL_INCLUDER_CASE 1014
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1015 */
+#if ((1015 >= GSL_INCLUDER_FIRST_CASE) && (1015 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1015)))
+#define GSL_INCLUDER_CASE 1015
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1016 */
+#if ((1016 >= GSL_INCLUDER_FIRST_CASE) && (1016 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1016)))
+#define GSL_INCLUDER_CASE 1016
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1017 */
+#if ((1017 >= GSL_INCLUDER_FIRST_CASE) && (1017 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1017)))
+#define GSL_INCLUDER_CASE 1017
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1018 */
+#if ((1018 >= GSL_INCLUDER_FIRST_CASE) && (1018 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1018)))
+#define GSL_INCLUDER_CASE 1018
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1019 */
+#if ((1019 >= GSL_INCLUDER_FIRST_CASE) && (1019 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1019)))
+#define GSL_INCLUDER_CASE 1019
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1020 */
+#if ((1020 >= GSL_INCLUDER_FIRST_CASE) && (1020 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1020)))
+#define GSL_INCLUDER_CASE 1020
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1021 */
+#if ((1021 >= GSL_INCLUDER_FIRST_CASE) && (1021 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1021)))
+#define GSL_INCLUDER_CASE 1021
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1022 */
+#if ((1022 >= GSL_INCLUDER_FIRST_CASE) && (1022 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1022)))
+#define GSL_INCLUDER_CASE 1022
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1023 */
+#if ((1023 >= GSL_INCLUDER_FIRST_CASE) && (1023 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1023)))
+#define GSL_INCLUDER_CASE 1023
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+/* 1024 */
+#if ((1024 >= GSL_INCLUDER_FIRST_CASE) && (1024 <= GSL_INCLUDER_LAST_CASE) && !(GSL_INCLUDER_REJECT (1024)))
+#define GSL_INCLUDER_CASE 1024
+#include GSL_INCLUDER_FILE
+#undef GSL_INCLUDER_CASE
+#endif
+
+GSL_INCLUDER_TABLE = {
+#if ((0 >= GSL_INCLUDER_FIRST_CASE) && (0 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (0))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 0),
+#endif
+#endif
+#if ((1 >= GSL_INCLUDER_FIRST_CASE) && (1 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1),
+#endif
+#endif
+#if ((2 >= GSL_INCLUDER_FIRST_CASE) && (2 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (2))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 2),
+#endif
+#endif
+#if ((3 >= GSL_INCLUDER_FIRST_CASE) && (3 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (3))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 3),
+#endif
+#endif
+#if ((4 >= GSL_INCLUDER_FIRST_CASE) && (4 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (4))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 4),
+#endif
+#endif
+#if ((5 >= GSL_INCLUDER_FIRST_CASE) && (5 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (5))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 5),
+#endif
+#endif
+#if ((6 >= GSL_INCLUDER_FIRST_CASE) && (6 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (6))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 6),
+#endif
+#endif
+#if ((7 >= GSL_INCLUDER_FIRST_CASE) && (7 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (7))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 7),
+#endif
+#endif
+#if ((8 >= GSL_INCLUDER_FIRST_CASE) && (8 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (8))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 8),
+#endif
+#endif
+#if ((9 >= GSL_INCLUDER_FIRST_CASE) && (9 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (9))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 9),
+#endif
+#endif
+#if ((10 >= GSL_INCLUDER_FIRST_CASE) && (10 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (10))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 10),
+#endif
+#endif
+#if ((11 >= GSL_INCLUDER_FIRST_CASE) && (11 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (11))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 11),
+#endif
+#endif
+#if ((12 >= GSL_INCLUDER_FIRST_CASE) && (12 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (12))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 12),
+#endif
+#endif
+#if ((13 >= GSL_INCLUDER_FIRST_CASE) && (13 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (13))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 13),
+#endif
+#endif
+#if ((14 >= GSL_INCLUDER_FIRST_CASE) && (14 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (14))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 14),
+#endif
+#endif
+#if ((15 >= GSL_INCLUDER_FIRST_CASE) && (15 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (15))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 15),
+#endif
+#endif
+#if ((16 >= GSL_INCLUDER_FIRST_CASE) && (16 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (16))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 16),
+#endif
+#endif
+#if ((17 >= GSL_INCLUDER_FIRST_CASE) && (17 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (17))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 17),
+#endif
+#endif
+#if ((18 >= GSL_INCLUDER_FIRST_CASE) && (18 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (18))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 18),
+#endif
+#endif
+#if ((19 >= GSL_INCLUDER_FIRST_CASE) && (19 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (19))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 19),
+#endif
+#endif
+#if ((20 >= GSL_INCLUDER_FIRST_CASE) && (20 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (20))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 20),
+#endif
+#endif
+#if ((21 >= GSL_INCLUDER_FIRST_CASE) && (21 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (21))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 21),
+#endif
+#endif
+#if ((22 >= GSL_INCLUDER_FIRST_CASE) && (22 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (22))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 22),
+#endif
+#endif
+#if ((23 >= GSL_INCLUDER_FIRST_CASE) && (23 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (23))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 23),
+#endif
+#endif
+#if ((24 >= GSL_INCLUDER_FIRST_CASE) && (24 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (24))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 24),
+#endif
+#endif
+#if ((25 >= GSL_INCLUDER_FIRST_CASE) && (25 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (25))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 25),
+#endif
+#endif
+#if ((26 >= GSL_INCLUDER_FIRST_CASE) && (26 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (26))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 26),
+#endif
+#endif
+#if ((27 >= GSL_INCLUDER_FIRST_CASE) && (27 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (27))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 27),
+#endif
+#endif
+#if ((28 >= GSL_INCLUDER_FIRST_CASE) && (28 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (28))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 28),
+#endif
+#endif
+#if ((29 >= GSL_INCLUDER_FIRST_CASE) && (29 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (29))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 29),
+#endif
+#endif
+#if ((30 >= GSL_INCLUDER_FIRST_CASE) && (30 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (30))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 30),
+#endif
+#endif
+#if ((31 >= GSL_INCLUDER_FIRST_CASE) && (31 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (31))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 31),
+#endif
+#endif
+#if ((32 >= GSL_INCLUDER_FIRST_CASE) && (32 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (32))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 32),
+#endif
+#endif
+#if ((33 >= GSL_INCLUDER_FIRST_CASE) && (33 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (33))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 33),
+#endif
+#endif
+#if ((34 >= GSL_INCLUDER_FIRST_CASE) && (34 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (34))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 34),
+#endif
+#endif
+#if ((35 >= GSL_INCLUDER_FIRST_CASE) && (35 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (35))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 35),
+#endif
+#endif
+#if ((36 >= GSL_INCLUDER_FIRST_CASE) && (36 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (36))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 36),
+#endif
+#endif
+#if ((37 >= GSL_INCLUDER_FIRST_CASE) && (37 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (37))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 37),
+#endif
+#endif
+#if ((38 >= GSL_INCLUDER_FIRST_CASE) && (38 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (38))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 38),
+#endif
+#endif
+#if ((39 >= GSL_INCLUDER_FIRST_CASE) && (39 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (39))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 39),
+#endif
+#endif
+#if ((40 >= GSL_INCLUDER_FIRST_CASE) && (40 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (40))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 40),
+#endif
+#endif
+#if ((41 >= GSL_INCLUDER_FIRST_CASE) && (41 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (41))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 41),
+#endif
+#endif
+#if ((42 >= GSL_INCLUDER_FIRST_CASE) && (42 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (42))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 42),
+#endif
+#endif
+#if ((43 >= GSL_INCLUDER_FIRST_CASE) && (43 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (43))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 43),
+#endif
+#endif
+#if ((44 >= GSL_INCLUDER_FIRST_CASE) && (44 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (44))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 44),
+#endif
+#endif
+#if ((45 >= GSL_INCLUDER_FIRST_CASE) && (45 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (45))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 45),
+#endif
+#endif
+#if ((46 >= GSL_INCLUDER_FIRST_CASE) && (46 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (46))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 46),
+#endif
+#endif
+#if ((47 >= GSL_INCLUDER_FIRST_CASE) && (47 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (47))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 47),
+#endif
+#endif
+#if ((48 >= GSL_INCLUDER_FIRST_CASE) && (48 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (48))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 48),
+#endif
+#endif
+#if ((49 >= GSL_INCLUDER_FIRST_CASE) && (49 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (49))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 49),
+#endif
+#endif
+#if ((50 >= GSL_INCLUDER_FIRST_CASE) && (50 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (50))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 50),
+#endif
+#endif
+#if ((51 >= GSL_INCLUDER_FIRST_CASE) && (51 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (51))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 51),
+#endif
+#endif
+#if ((52 >= GSL_INCLUDER_FIRST_CASE) && (52 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (52))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 52),
+#endif
+#endif
+#if ((53 >= GSL_INCLUDER_FIRST_CASE) && (53 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (53))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 53),
+#endif
+#endif
+#if ((54 >= GSL_INCLUDER_FIRST_CASE) && (54 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (54))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 54),
+#endif
+#endif
+#if ((55 >= GSL_INCLUDER_FIRST_CASE) && (55 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (55))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 55),
+#endif
+#endif
+#if ((56 >= GSL_INCLUDER_FIRST_CASE) && (56 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (56))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 56),
+#endif
+#endif
+#if ((57 >= GSL_INCLUDER_FIRST_CASE) && (57 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (57))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 57),
+#endif
+#endif
+#if ((58 >= GSL_INCLUDER_FIRST_CASE) && (58 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (58))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 58),
+#endif
+#endif
+#if ((59 >= GSL_INCLUDER_FIRST_CASE) && (59 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (59))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 59),
+#endif
+#endif
+#if ((60 >= GSL_INCLUDER_FIRST_CASE) && (60 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (60))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 60),
+#endif
+#endif
+#if ((61 >= GSL_INCLUDER_FIRST_CASE) && (61 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (61))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 61),
+#endif
+#endif
+#if ((62 >= GSL_INCLUDER_FIRST_CASE) && (62 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (62))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 62),
+#endif
+#endif
+#if ((63 >= GSL_INCLUDER_FIRST_CASE) && (63 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (63))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 63),
+#endif
+#endif
+#if ((64 >= GSL_INCLUDER_FIRST_CASE) && (64 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (64))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 64),
+#endif
+#endif
+#if ((65 >= GSL_INCLUDER_FIRST_CASE) && (65 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (65))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 65),
+#endif
+#endif
+#if ((66 >= GSL_INCLUDER_FIRST_CASE) && (66 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (66))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 66),
+#endif
+#endif
+#if ((67 >= GSL_INCLUDER_FIRST_CASE) && (67 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (67))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 67),
+#endif
+#endif
+#if ((68 >= GSL_INCLUDER_FIRST_CASE) && (68 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (68))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 68),
+#endif
+#endif
+#if ((69 >= GSL_INCLUDER_FIRST_CASE) && (69 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (69))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 69),
+#endif
+#endif
+#if ((70 >= GSL_INCLUDER_FIRST_CASE) && (70 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (70))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 70),
+#endif
+#endif
+#if ((71 >= GSL_INCLUDER_FIRST_CASE) && (71 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (71))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 71),
+#endif
+#endif
+#if ((72 >= GSL_INCLUDER_FIRST_CASE) && (72 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (72))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 72),
+#endif
+#endif
+#if ((73 >= GSL_INCLUDER_FIRST_CASE) && (73 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (73))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 73),
+#endif
+#endif
+#if ((74 >= GSL_INCLUDER_FIRST_CASE) && (74 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (74))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 74),
+#endif
+#endif
+#if ((75 >= GSL_INCLUDER_FIRST_CASE) && (75 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (75))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 75),
+#endif
+#endif
+#if ((76 >= GSL_INCLUDER_FIRST_CASE) && (76 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (76))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 76),
+#endif
+#endif
+#if ((77 >= GSL_INCLUDER_FIRST_CASE) && (77 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (77))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 77),
+#endif
+#endif
+#if ((78 >= GSL_INCLUDER_FIRST_CASE) && (78 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (78))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 78),
+#endif
+#endif
+#if ((79 >= GSL_INCLUDER_FIRST_CASE) && (79 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (79))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 79),
+#endif
+#endif
+#if ((80 >= GSL_INCLUDER_FIRST_CASE) && (80 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (80))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 80),
+#endif
+#endif
+#if ((81 >= GSL_INCLUDER_FIRST_CASE) && (81 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (81))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 81),
+#endif
+#endif
+#if ((82 >= GSL_INCLUDER_FIRST_CASE) && (82 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (82))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 82),
+#endif
+#endif
+#if ((83 >= GSL_INCLUDER_FIRST_CASE) && (83 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (83))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 83),
+#endif
+#endif
+#if ((84 >= GSL_INCLUDER_FIRST_CASE) && (84 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (84))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 84),
+#endif
+#endif
+#if ((85 >= GSL_INCLUDER_FIRST_CASE) && (85 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (85))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 85),
+#endif
+#endif
+#if ((86 >= GSL_INCLUDER_FIRST_CASE) && (86 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (86))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 86),
+#endif
+#endif
+#if ((87 >= GSL_INCLUDER_FIRST_CASE) && (87 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (87))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 87),
+#endif
+#endif
+#if ((88 >= GSL_INCLUDER_FIRST_CASE) && (88 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (88))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 88),
+#endif
+#endif
+#if ((89 >= GSL_INCLUDER_FIRST_CASE) && (89 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (89))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 89),
+#endif
+#endif
+#if ((90 >= GSL_INCLUDER_FIRST_CASE) && (90 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (90))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 90),
+#endif
+#endif
+#if ((91 >= GSL_INCLUDER_FIRST_CASE) && (91 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (91))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 91),
+#endif
+#endif
+#if ((92 >= GSL_INCLUDER_FIRST_CASE) && (92 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (92))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 92),
+#endif
+#endif
+#if ((93 >= GSL_INCLUDER_FIRST_CASE) && (93 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (93))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 93),
+#endif
+#endif
+#if ((94 >= GSL_INCLUDER_FIRST_CASE) && (94 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (94))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 94),
+#endif
+#endif
+#if ((95 >= GSL_INCLUDER_FIRST_CASE) && (95 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (95))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 95),
+#endif
+#endif
+#if ((96 >= GSL_INCLUDER_FIRST_CASE) && (96 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (96))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 96),
+#endif
+#endif
+#if ((97 >= GSL_INCLUDER_FIRST_CASE) && (97 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (97))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 97),
+#endif
+#endif
+#if ((98 >= GSL_INCLUDER_FIRST_CASE) && (98 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (98))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 98),
+#endif
+#endif
+#if ((99 >= GSL_INCLUDER_FIRST_CASE) && (99 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (99))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 99),
+#endif
+#endif
+#if ((100 >= GSL_INCLUDER_FIRST_CASE) && (100 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (100))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 100),
+#endif
+#endif
+#if ((101 >= GSL_INCLUDER_FIRST_CASE) && (101 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (101))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 101),
+#endif
+#endif
+#if ((102 >= GSL_INCLUDER_FIRST_CASE) && (102 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (102))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 102),
+#endif
+#endif
+#if ((103 >= GSL_INCLUDER_FIRST_CASE) && (103 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (103))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 103),
+#endif
+#endif
+#if ((104 >= GSL_INCLUDER_FIRST_CASE) && (104 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (104))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 104),
+#endif
+#endif
+#if ((105 >= GSL_INCLUDER_FIRST_CASE) && (105 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (105))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 105),
+#endif
+#endif
+#if ((106 >= GSL_INCLUDER_FIRST_CASE) && (106 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (106))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 106),
+#endif
+#endif
+#if ((107 >= GSL_INCLUDER_FIRST_CASE) && (107 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (107))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 107),
+#endif
+#endif
+#if ((108 >= GSL_INCLUDER_FIRST_CASE) && (108 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (108))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 108),
+#endif
+#endif
+#if ((109 >= GSL_INCLUDER_FIRST_CASE) && (109 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (109))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 109),
+#endif
+#endif
+#if ((110 >= GSL_INCLUDER_FIRST_CASE) && (110 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (110))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 110),
+#endif
+#endif
+#if ((111 >= GSL_INCLUDER_FIRST_CASE) && (111 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (111))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 111),
+#endif
+#endif
+#if ((112 >= GSL_INCLUDER_FIRST_CASE) && (112 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (112))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 112),
+#endif
+#endif
+#if ((113 >= GSL_INCLUDER_FIRST_CASE) && (113 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (113))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 113),
+#endif
+#endif
+#if ((114 >= GSL_INCLUDER_FIRST_CASE) && (114 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (114))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 114),
+#endif
+#endif
+#if ((115 >= GSL_INCLUDER_FIRST_CASE) && (115 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (115))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 115),
+#endif
+#endif
+#if ((116 >= GSL_INCLUDER_FIRST_CASE) && (116 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (116))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 116),
+#endif
+#endif
+#if ((117 >= GSL_INCLUDER_FIRST_CASE) && (117 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (117))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 117),
+#endif
+#endif
+#if ((118 >= GSL_INCLUDER_FIRST_CASE) && (118 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (118))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 118),
+#endif
+#endif
+#if ((119 >= GSL_INCLUDER_FIRST_CASE) && (119 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (119))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 119),
+#endif
+#endif
+#if ((120 >= GSL_INCLUDER_FIRST_CASE) && (120 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (120))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 120),
+#endif
+#endif
+#if ((121 >= GSL_INCLUDER_FIRST_CASE) && (121 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (121))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 121),
+#endif
+#endif
+#if ((122 >= GSL_INCLUDER_FIRST_CASE) && (122 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (122))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 122),
+#endif
+#endif
+#if ((123 >= GSL_INCLUDER_FIRST_CASE) && (123 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (123))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 123),
+#endif
+#endif
+#if ((124 >= GSL_INCLUDER_FIRST_CASE) && (124 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (124))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 124),
+#endif
+#endif
+#if ((125 >= GSL_INCLUDER_FIRST_CASE) && (125 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (125))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 125),
+#endif
+#endif
+#if ((126 >= GSL_INCLUDER_FIRST_CASE) && (126 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (126))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 126),
+#endif
+#endif
+#if ((127 >= GSL_INCLUDER_FIRST_CASE) && (127 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (127))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 127),
+#endif
+#endif
+#if ((128 >= GSL_INCLUDER_FIRST_CASE) && (128 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (128))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 128),
+#endif
+#endif
+#if ((129 >= GSL_INCLUDER_FIRST_CASE) && (129 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (129))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 129),
+#endif
+#endif
+#if ((130 >= GSL_INCLUDER_FIRST_CASE) && (130 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (130))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 130),
+#endif
+#endif
+#if ((131 >= GSL_INCLUDER_FIRST_CASE) && (131 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (131))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 131),
+#endif
+#endif
+#if ((132 >= GSL_INCLUDER_FIRST_CASE) && (132 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (132))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 132),
+#endif
+#endif
+#if ((133 >= GSL_INCLUDER_FIRST_CASE) && (133 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (133))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 133),
+#endif
+#endif
+#if ((134 >= GSL_INCLUDER_FIRST_CASE) && (134 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (134))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 134),
+#endif
+#endif
+#if ((135 >= GSL_INCLUDER_FIRST_CASE) && (135 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (135))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 135),
+#endif
+#endif
+#if ((136 >= GSL_INCLUDER_FIRST_CASE) && (136 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (136))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 136),
+#endif
+#endif
+#if ((137 >= GSL_INCLUDER_FIRST_CASE) && (137 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (137))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 137),
+#endif
+#endif
+#if ((138 >= GSL_INCLUDER_FIRST_CASE) && (138 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (138))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 138),
+#endif
+#endif
+#if ((139 >= GSL_INCLUDER_FIRST_CASE) && (139 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (139))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 139),
+#endif
+#endif
+#if ((140 >= GSL_INCLUDER_FIRST_CASE) && (140 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (140))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 140),
+#endif
+#endif
+#if ((141 >= GSL_INCLUDER_FIRST_CASE) && (141 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (141))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 141),
+#endif
+#endif
+#if ((142 >= GSL_INCLUDER_FIRST_CASE) && (142 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (142))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 142),
+#endif
+#endif
+#if ((143 >= GSL_INCLUDER_FIRST_CASE) && (143 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (143))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 143),
+#endif
+#endif
+#if ((144 >= GSL_INCLUDER_FIRST_CASE) && (144 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (144))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 144),
+#endif
+#endif
+#if ((145 >= GSL_INCLUDER_FIRST_CASE) && (145 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (145))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 145),
+#endif
+#endif
+#if ((146 >= GSL_INCLUDER_FIRST_CASE) && (146 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (146))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 146),
+#endif
+#endif
+#if ((147 >= GSL_INCLUDER_FIRST_CASE) && (147 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (147))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 147),
+#endif
+#endif
+#if ((148 >= GSL_INCLUDER_FIRST_CASE) && (148 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (148))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 148),
+#endif
+#endif
+#if ((149 >= GSL_INCLUDER_FIRST_CASE) && (149 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (149))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 149),
+#endif
+#endif
+#if ((150 >= GSL_INCLUDER_FIRST_CASE) && (150 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (150))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 150),
+#endif
+#endif
+#if ((151 >= GSL_INCLUDER_FIRST_CASE) && (151 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (151))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 151),
+#endif
+#endif
+#if ((152 >= GSL_INCLUDER_FIRST_CASE) && (152 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (152))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 152),
+#endif
+#endif
+#if ((153 >= GSL_INCLUDER_FIRST_CASE) && (153 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (153))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 153),
+#endif
+#endif
+#if ((154 >= GSL_INCLUDER_FIRST_CASE) && (154 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (154))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 154),
+#endif
+#endif
+#if ((155 >= GSL_INCLUDER_FIRST_CASE) && (155 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (155))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 155),
+#endif
+#endif
+#if ((156 >= GSL_INCLUDER_FIRST_CASE) && (156 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (156))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 156),
+#endif
+#endif
+#if ((157 >= GSL_INCLUDER_FIRST_CASE) && (157 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (157))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 157),
+#endif
+#endif
+#if ((158 >= GSL_INCLUDER_FIRST_CASE) && (158 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (158))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 158),
+#endif
+#endif
+#if ((159 >= GSL_INCLUDER_FIRST_CASE) && (159 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (159))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 159),
+#endif
+#endif
+#if ((160 >= GSL_INCLUDER_FIRST_CASE) && (160 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (160))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 160),
+#endif
+#endif
+#if ((161 >= GSL_INCLUDER_FIRST_CASE) && (161 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (161))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 161),
+#endif
+#endif
+#if ((162 >= GSL_INCLUDER_FIRST_CASE) && (162 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (162))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 162),
+#endif
+#endif
+#if ((163 >= GSL_INCLUDER_FIRST_CASE) && (163 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (163))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 163),
+#endif
+#endif
+#if ((164 >= GSL_INCLUDER_FIRST_CASE) && (164 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (164))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 164),
+#endif
+#endif
+#if ((165 >= GSL_INCLUDER_FIRST_CASE) && (165 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (165))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 165),
+#endif
+#endif
+#if ((166 >= GSL_INCLUDER_FIRST_CASE) && (166 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (166))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 166),
+#endif
+#endif
+#if ((167 >= GSL_INCLUDER_FIRST_CASE) && (167 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (167))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 167),
+#endif
+#endif
+#if ((168 >= GSL_INCLUDER_FIRST_CASE) && (168 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (168))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 168),
+#endif
+#endif
+#if ((169 >= GSL_INCLUDER_FIRST_CASE) && (169 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (169))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 169),
+#endif
+#endif
+#if ((170 >= GSL_INCLUDER_FIRST_CASE) && (170 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (170))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 170),
+#endif
+#endif
+#if ((171 >= GSL_INCLUDER_FIRST_CASE) && (171 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (171))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 171),
+#endif
+#endif
+#if ((172 >= GSL_INCLUDER_FIRST_CASE) && (172 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (172))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 172),
+#endif
+#endif
+#if ((173 >= GSL_INCLUDER_FIRST_CASE) && (173 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (173))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 173),
+#endif
+#endif
+#if ((174 >= GSL_INCLUDER_FIRST_CASE) && (174 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (174))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 174),
+#endif
+#endif
+#if ((175 >= GSL_INCLUDER_FIRST_CASE) && (175 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (175))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 175),
+#endif
+#endif
+#if ((176 >= GSL_INCLUDER_FIRST_CASE) && (176 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (176))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 176),
+#endif
+#endif
+#if ((177 >= GSL_INCLUDER_FIRST_CASE) && (177 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (177))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 177),
+#endif
+#endif
+#if ((178 >= GSL_INCLUDER_FIRST_CASE) && (178 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (178))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 178),
+#endif
+#endif
+#if ((179 >= GSL_INCLUDER_FIRST_CASE) && (179 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (179))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 179),
+#endif
+#endif
+#if ((180 >= GSL_INCLUDER_FIRST_CASE) && (180 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (180))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 180),
+#endif
+#endif
+#if ((181 >= GSL_INCLUDER_FIRST_CASE) && (181 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (181))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 181),
+#endif
+#endif
+#if ((182 >= GSL_INCLUDER_FIRST_CASE) && (182 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (182))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 182),
+#endif
+#endif
+#if ((183 >= GSL_INCLUDER_FIRST_CASE) && (183 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (183))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 183),
+#endif
+#endif
+#if ((184 >= GSL_INCLUDER_FIRST_CASE) && (184 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (184))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 184),
+#endif
+#endif
+#if ((185 >= GSL_INCLUDER_FIRST_CASE) && (185 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (185))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 185),
+#endif
+#endif
+#if ((186 >= GSL_INCLUDER_FIRST_CASE) && (186 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (186))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 186),
+#endif
+#endif
+#if ((187 >= GSL_INCLUDER_FIRST_CASE) && (187 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (187))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 187),
+#endif
+#endif
+#if ((188 >= GSL_INCLUDER_FIRST_CASE) && (188 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (188))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 188),
+#endif
+#endif
+#if ((189 >= GSL_INCLUDER_FIRST_CASE) && (189 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (189))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 189),
+#endif
+#endif
+#if ((190 >= GSL_INCLUDER_FIRST_CASE) && (190 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (190))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 190),
+#endif
+#endif
+#if ((191 >= GSL_INCLUDER_FIRST_CASE) && (191 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (191))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 191),
+#endif
+#endif
+#if ((192 >= GSL_INCLUDER_FIRST_CASE) && (192 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (192))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 192),
+#endif
+#endif
+#if ((193 >= GSL_INCLUDER_FIRST_CASE) && (193 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (193))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 193),
+#endif
+#endif
+#if ((194 >= GSL_INCLUDER_FIRST_CASE) && (194 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (194))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 194),
+#endif
+#endif
+#if ((195 >= GSL_INCLUDER_FIRST_CASE) && (195 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (195))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 195),
+#endif
+#endif
+#if ((196 >= GSL_INCLUDER_FIRST_CASE) && (196 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (196))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 196),
+#endif
+#endif
+#if ((197 >= GSL_INCLUDER_FIRST_CASE) && (197 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (197))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 197),
+#endif
+#endif
+#if ((198 >= GSL_INCLUDER_FIRST_CASE) && (198 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (198))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 198),
+#endif
+#endif
+#if ((199 >= GSL_INCLUDER_FIRST_CASE) && (199 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (199))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 199),
+#endif
+#endif
+#if ((200 >= GSL_INCLUDER_FIRST_CASE) && (200 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (200))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 200),
+#endif
+#endif
+#if ((201 >= GSL_INCLUDER_FIRST_CASE) && (201 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (201))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 201),
+#endif
+#endif
+#if ((202 >= GSL_INCLUDER_FIRST_CASE) && (202 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (202))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 202),
+#endif
+#endif
+#if ((203 >= GSL_INCLUDER_FIRST_CASE) && (203 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (203))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 203),
+#endif
+#endif
+#if ((204 >= GSL_INCLUDER_FIRST_CASE) && (204 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (204))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 204),
+#endif
+#endif
+#if ((205 >= GSL_INCLUDER_FIRST_CASE) && (205 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (205))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 205),
+#endif
+#endif
+#if ((206 >= GSL_INCLUDER_FIRST_CASE) && (206 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (206))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 206),
+#endif
+#endif
+#if ((207 >= GSL_INCLUDER_FIRST_CASE) && (207 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (207))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 207),
+#endif
+#endif
+#if ((208 >= GSL_INCLUDER_FIRST_CASE) && (208 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (208))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 208),
+#endif
+#endif
+#if ((209 >= GSL_INCLUDER_FIRST_CASE) && (209 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (209))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 209),
+#endif
+#endif
+#if ((210 >= GSL_INCLUDER_FIRST_CASE) && (210 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (210))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 210),
+#endif
+#endif
+#if ((211 >= GSL_INCLUDER_FIRST_CASE) && (211 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (211))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 211),
+#endif
+#endif
+#if ((212 >= GSL_INCLUDER_FIRST_CASE) && (212 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (212))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 212),
+#endif
+#endif
+#if ((213 >= GSL_INCLUDER_FIRST_CASE) && (213 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (213))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 213),
+#endif
+#endif
+#if ((214 >= GSL_INCLUDER_FIRST_CASE) && (214 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (214))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 214),
+#endif
+#endif
+#if ((215 >= GSL_INCLUDER_FIRST_CASE) && (215 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (215))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 215),
+#endif
+#endif
+#if ((216 >= GSL_INCLUDER_FIRST_CASE) && (216 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (216))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 216),
+#endif
+#endif
+#if ((217 >= GSL_INCLUDER_FIRST_CASE) && (217 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (217))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 217),
+#endif
+#endif
+#if ((218 >= GSL_INCLUDER_FIRST_CASE) && (218 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (218))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 218),
+#endif
+#endif
+#if ((219 >= GSL_INCLUDER_FIRST_CASE) && (219 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (219))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 219),
+#endif
+#endif
+#if ((220 >= GSL_INCLUDER_FIRST_CASE) && (220 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (220))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 220),
+#endif
+#endif
+#if ((221 >= GSL_INCLUDER_FIRST_CASE) && (221 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (221))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 221),
+#endif
+#endif
+#if ((222 >= GSL_INCLUDER_FIRST_CASE) && (222 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (222))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 222),
+#endif
+#endif
+#if ((223 >= GSL_INCLUDER_FIRST_CASE) && (223 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (223))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 223),
+#endif
+#endif
+#if ((224 >= GSL_INCLUDER_FIRST_CASE) && (224 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (224))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 224),
+#endif
+#endif
+#if ((225 >= GSL_INCLUDER_FIRST_CASE) && (225 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (225))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 225),
+#endif
+#endif
+#if ((226 >= GSL_INCLUDER_FIRST_CASE) && (226 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (226))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 226),
+#endif
+#endif
+#if ((227 >= GSL_INCLUDER_FIRST_CASE) && (227 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (227))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 227),
+#endif
+#endif
+#if ((228 >= GSL_INCLUDER_FIRST_CASE) && (228 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (228))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 228),
+#endif
+#endif
+#if ((229 >= GSL_INCLUDER_FIRST_CASE) && (229 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (229))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 229),
+#endif
+#endif
+#if ((230 >= GSL_INCLUDER_FIRST_CASE) && (230 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (230))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 230),
+#endif
+#endif
+#if ((231 >= GSL_INCLUDER_FIRST_CASE) && (231 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (231))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 231),
+#endif
+#endif
+#if ((232 >= GSL_INCLUDER_FIRST_CASE) && (232 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (232))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 232),
+#endif
+#endif
+#if ((233 >= GSL_INCLUDER_FIRST_CASE) && (233 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (233))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 233),
+#endif
+#endif
+#if ((234 >= GSL_INCLUDER_FIRST_CASE) && (234 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (234))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 234),
+#endif
+#endif
+#if ((235 >= GSL_INCLUDER_FIRST_CASE) && (235 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (235))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 235),
+#endif
+#endif
+#if ((236 >= GSL_INCLUDER_FIRST_CASE) && (236 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (236))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 236),
+#endif
+#endif
+#if ((237 >= GSL_INCLUDER_FIRST_CASE) && (237 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (237))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 237),
+#endif
+#endif
+#if ((238 >= GSL_INCLUDER_FIRST_CASE) && (238 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (238))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 238),
+#endif
+#endif
+#if ((239 >= GSL_INCLUDER_FIRST_CASE) && (239 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (239))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 239),
+#endif
+#endif
+#if ((240 >= GSL_INCLUDER_FIRST_CASE) && (240 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (240))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 240),
+#endif
+#endif
+#if ((241 >= GSL_INCLUDER_FIRST_CASE) && (241 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (241))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 241),
+#endif
+#endif
+#if ((242 >= GSL_INCLUDER_FIRST_CASE) && (242 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (242))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 242),
+#endif
+#endif
+#if ((243 >= GSL_INCLUDER_FIRST_CASE) && (243 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (243))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 243),
+#endif
+#endif
+#if ((244 >= GSL_INCLUDER_FIRST_CASE) && (244 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (244))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 244),
+#endif
+#endif
+#if ((245 >= GSL_INCLUDER_FIRST_CASE) && (245 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (245))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 245),
+#endif
+#endif
+#if ((246 >= GSL_INCLUDER_FIRST_CASE) && (246 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (246))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 246),
+#endif
+#endif
+#if ((247 >= GSL_INCLUDER_FIRST_CASE) && (247 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (247))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 247),
+#endif
+#endif
+#if ((248 >= GSL_INCLUDER_FIRST_CASE) && (248 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (248))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 248),
+#endif
+#endif
+#if ((249 >= GSL_INCLUDER_FIRST_CASE) && (249 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (249))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 249),
+#endif
+#endif
+#if ((250 >= GSL_INCLUDER_FIRST_CASE) && (250 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (250))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 250),
+#endif
+#endif
+#if ((251 >= GSL_INCLUDER_FIRST_CASE) && (251 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (251))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 251),
+#endif
+#endif
+#if ((252 >= GSL_INCLUDER_FIRST_CASE) && (252 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (252))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 252),
+#endif
+#endif
+#if ((253 >= GSL_INCLUDER_FIRST_CASE) && (253 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (253))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 253),
+#endif
+#endif
+#if ((254 >= GSL_INCLUDER_FIRST_CASE) && (254 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (254))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 254),
+#endif
+#endif
+#if ((255 >= GSL_INCLUDER_FIRST_CASE) && (255 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (255))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 255),
+#endif
+#endif
+#if ((256 >= GSL_INCLUDER_FIRST_CASE) && (256 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (256))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 256),
+#endif
+#endif
+#if ((257 >= GSL_INCLUDER_FIRST_CASE) && (257 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (257))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 257),
+#endif
+#endif
+#if ((258 >= GSL_INCLUDER_FIRST_CASE) && (258 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (258))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 258),
+#endif
+#endif
+#if ((259 >= GSL_INCLUDER_FIRST_CASE) && (259 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (259))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 259),
+#endif
+#endif
+#if ((260 >= GSL_INCLUDER_FIRST_CASE) && (260 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (260))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 260),
+#endif
+#endif
+#if ((261 >= GSL_INCLUDER_FIRST_CASE) && (261 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (261))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 261),
+#endif
+#endif
+#if ((262 >= GSL_INCLUDER_FIRST_CASE) && (262 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (262))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 262),
+#endif
+#endif
+#if ((263 >= GSL_INCLUDER_FIRST_CASE) && (263 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (263))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 263),
+#endif
+#endif
+#if ((264 >= GSL_INCLUDER_FIRST_CASE) && (264 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (264))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 264),
+#endif
+#endif
+#if ((265 >= GSL_INCLUDER_FIRST_CASE) && (265 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (265))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 265),
+#endif
+#endif
+#if ((266 >= GSL_INCLUDER_FIRST_CASE) && (266 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (266))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 266),
+#endif
+#endif
+#if ((267 >= GSL_INCLUDER_FIRST_CASE) && (267 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (267))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 267),
+#endif
+#endif
+#if ((268 >= GSL_INCLUDER_FIRST_CASE) && (268 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (268))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 268),
+#endif
+#endif
+#if ((269 >= GSL_INCLUDER_FIRST_CASE) && (269 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (269))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 269),
+#endif
+#endif
+#if ((270 >= GSL_INCLUDER_FIRST_CASE) && (270 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (270))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 270),
+#endif
+#endif
+#if ((271 >= GSL_INCLUDER_FIRST_CASE) && (271 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (271))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 271),
+#endif
+#endif
+#if ((272 >= GSL_INCLUDER_FIRST_CASE) && (272 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (272))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 272),
+#endif
+#endif
+#if ((273 >= GSL_INCLUDER_FIRST_CASE) && (273 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (273))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 273),
+#endif
+#endif
+#if ((274 >= GSL_INCLUDER_FIRST_CASE) && (274 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (274))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 274),
+#endif
+#endif
+#if ((275 >= GSL_INCLUDER_FIRST_CASE) && (275 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (275))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 275),
+#endif
+#endif
+#if ((276 >= GSL_INCLUDER_FIRST_CASE) && (276 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (276))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 276),
+#endif
+#endif
+#if ((277 >= GSL_INCLUDER_FIRST_CASE) && (277 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (277))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 277),
+#endif
+#endif
+#if ((278 >= GSL_INCLUDER_FIRST_CASE) && (278 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (278))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 278),
+#endif
+#endif
+#if ((279 >= GSL_INCLUDER_FIRST_CASE) && (279 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (279))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 279),
+#endif
+#endif
+#if ((280 >= GSL_INCLUDER_FIRST_CASE) && (280 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (280))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 280),
+#endif
+#endif
+#if ((281 >= GSL_INCLUDER_FIRST_CASE) && (281 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (281))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 281),
+#endif
+#endif
+#if ((282 >= GSL_INCLUDER_FIRST_CASE) && (282 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (282))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 282),
+#endif
+#endif
+#if ((283 >= GSL_INCLUDER_FIRST_CASE) && (283 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (283))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 283),
+#endif
+#endif
+#if ((284 >= GSL_INCLUDER_FIRST_CASE) && (284 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (284))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 284),
+#endif
+#endif
+#if ((285 >= GSL_INCLUDER_FIRST_CASE) && (285 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (285))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 285),
+#endif
+#endif
+#if ((286 >= GSL_INCLUDER_FIRST_CASE) && (286 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (286))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 286),
+#endif
+#endif
+#if ((287 >= GSL_INCLUDER_FIRST_CASE) && (287 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (287))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 287),
+#endif
+#endif
+#if ((288 >= GSL_INCLUDER_FIRST_CASE) && (288 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (288))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 288),
+#endif
+#endif
+#if ((289 >= GSL_INCLUDER_FIRST_CASE) && (289 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (289))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 289),
+#endif
+#endif
+#if ((290 >= GSL_INCLUDER_FIRST_CASE) && (290 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (290))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 290),
+#endif
+#endif
+#if ((291 >= GSL_INCLUDER_FIRST_CASE) && (291 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (291))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 291),
+#endif
+#endif
+#if ((292 >= GSL_INCLUDER_FIRST_CASE) && (292 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (292))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 292),
+#endif
+#endif
+#if ((293 >= GSL_INCLUDER_FIRST_CASE) && (293 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (293))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 293),
+#endif
+#endif
+#if ((294 >= GSL_INCLUDER_FIRST_CASE) && (294 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (294))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 294),
+#endif
+#endif
+#if ((295 >= GSL_INCLUDER_FIRST_CASE) && (295 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (295))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 295),
+#endif
+#endif
+#if ((296 >= GSL_INCLUDER_FIRST_CASE) && (296 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (296))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 296),
+#endif
+#endif
+#if ((297 >= GSL_INCLUDER_FIRST_CASE) && (297 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (297))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 297),
+#endif
+#endif
+#if ((298 >= GSL_INCLUDER_FIRST_CASE) && (298 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (298))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 298),
+#endif
+#endif
+#if ((299 >= GSL_INCLUDER_FIRST_CASE) && (299 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (299))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 299),
+#endif
+#endif
+#if ((300 >= GSL_INCLUDER_FIRST_CASE) && (300 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (300))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 300),
+#endif
+#endif
+#if ((301 >= GSL_INCLUDER_FIRST_CASE) && (301 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (301))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 301),
+#endif
+#endif
+#if ((302 >= GSL_INCLUDER_FIRST_CASE) && (302 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (302))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 302),
+#endif
+#endif
+#if ((303 >= GSL_INCLUDER_FIRST_CASE) && (303 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (303))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 303),
+#endif
+#endif
+#if ((304 >= GSL_INCLUDER_FIRST_CASE) && (304 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (304))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 304),
+#endif
+#endif
+#if ((305 >= GSL_INCLUDER_FIRST_CASE) && (305 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (305))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 305),
+#endif
+#endif
+#if ((306 >= GSL_INCLUDER_FIRST_CASE) && (306 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (306))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 306),
+#endif
+#endif
+#if ((307 >= GSL_INCLUDER_FIRST_CASE) && (307 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (307))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 307),
+#endif
+#endif
+#if ((308 >= GSL_INCLUDER_FIRST_CASE) && (308 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (308))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 308),
+#endif
+#endif
+#if ((309 >= GSL_INCLUDER_FIRST_CASE) && (309 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (309))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 309),
+#endif
+#endif
+#if ((310 >= GSL_INCLUDER_FIRST_CASE) && (310 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (310))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 310),
+#endif
+#endif
+#if ((311 >= GSL_INCLUDER_FIRST_CASE) && (311 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (311))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 311),
+#endif
+#endif
+#if ((312 >= GSL_INCLUDER_FIRST_CASE) && (312 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (312))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 312),
+#endif
+#endif
+#if ((313 >= GSL_INCLUDER_FIRST_CASE) && (313 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (313))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 313),
+#endif
+#endif
+#if ((314 >= GSL_INCLUDER_FIRST_CASE) && (314 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (314))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 314),
+#endif
+#endif
+#if ((315 >= GSL_INCLUDER_FIRST_CASE) && (315 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (315))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 315),
+#endif
+#endif
+#if ((316 >= GSL_INCLUDER_FIRST_CASE) && (316 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (316))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 316),
+#endif
+#endif
+#if ((317 >= GSL_INCLUDER_FIRST_CASE) && (317 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (317))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 317),
+#endif
+#endif
+#if ((318 >= GSL_INCLUDER_FIRST_CASE) && (318 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (318))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 318),
+#endif
+#endif
+#if ((319 >= GSL_INCLUDER_FIRST_CASE) && (319 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (319))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 319),
+#endif
+#endif
+#if ((320 >= GSL_INCLUDER_FIRST_CASE) && (320 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (320))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 320),
+#endif
+#endif
+#if ((321 >= GSL_INCLUDER_FIRST_CASE) && (321 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (321))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 321),
+#endif
+#endif
+#if ((322 >= GSL_INCLUDER_FIRST_CASE) && (322 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (322))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 322),
+#endif
+#endif
+#if ((323 >= GSL_INCLUDER_FIRST_CASE) && (323 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (323))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 323),
+#endif
+#endif
+#if ((324 >= GSL_INCLUDER_FIRST_CASE) && (324 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (324))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 324),
+#endif
+#endif
+#if ((325 >= GSL_INCLUDER_FIRST_CASE) && (325 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (325))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 325),
+#endif
+#endif
+#if ((326 >= GSL_INCLUDER_FIRST_CASE) && (326 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (326))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 326),
+#endif
+#endif
+#if ((327 >= GSL_INCLUDER_FIRST_CASE) && (327 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (327))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 327),
+#endif
+#endif
+#if ((328 >= GSL_INCLUDER_FIRST_CASE) && (328 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (328))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 328),
+#endif
+#endif
+#if ((329 >= GSL_INCLUDER_FIRST_CASE) && (329 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (329))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 329),
+#endif
+#endif
+#if ((330 >= GSL_INCLUDER_FIRST_CASE) && (330 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (330))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 330),
+#endif
+#endif
+#if ((331 >= GSL_INCLUDER_FIRST_CASE) && (331 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (331))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 331),
+#endif
+#endif
+#if ((332 >= GSL_INCLUDER_FIRST_CASE) && (332 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (332))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 332),
+#endif
+#endif
+#if ((333 >= GSL_INCLUDER_FIRST_CASE) && (333 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (333))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 333),
+#endif
+#endif
+#if ((334 >= GSL_INCLUDER_FIRST_CASE) && (334 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (334))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 334),
+#endif
+#endif
+#if ((335 >= GSL_INCLUDER_FIRST_CASE) && (335 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (335))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 335),
+#endif
+#endif
+#if ((336 >= GSL_INCLUDER_FIRST_CASE) && (336 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (336))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 336),
+#endif
+#endif
+#if ((337 >= GSL_INCLUDER_FIRST_CASE) && (337 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (337))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 337),
+#endif
+#endif
+#if ((338 >= GSL_INCLUDER_FIRST_CASE) && (338 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (338))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 338),
+#endif
+#endif
+#if ((339 >= GSL_INCLUDER_FIRST_CASE) && (339 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (339))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 339),
+#endif
+#endif
+#if ((340 >= GSL_INCLUDER_FIRST_CASE) && (340 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (340))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 340),
+#endif
+#endif
+#if ((341 >= GSL_INCLUDER_FIRST_CASE) && (341 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (341))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 341),
+#endif
+#endif
+#if ((342 >= GSL_INCLUDER_FIRST_CASE) && (342 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (342))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 342),
+#endif
+#endif
+#if ((343 >= GSL_INCLUDER_FIRST_CASE) && (343 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (343))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 343),
+#endif
+#endif
+#if ((344 >= GSL_INCLUDER_FIRST_CASE) && (344 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (344))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 344),
+#endif
+#endif
+#if ((345 >= GSL_INCLUDER_FIRST_CASE) && (345 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (345))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 345),
+#endif
+#endif
+#if ((346 >= GSL_INCLUDER_FIRST_CASE) && (346 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (346))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 346),
+#endif
+#endif
+#if ((347 >= GSL_INCLUDER_FIRST_CASE) && (347 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (347))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 347),
+#endif
+#endif
+#if ((348 >= GSL_INCLUDER_FIRST_CASE) && (348 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (348))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 348),
+#endif
+#endif
+#if ((349 >= GSL_INCLUDER_FIRST_CASE) && (349 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (349))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 349),
+#endif
+#endif
+#if ((350 >= GSL_INCLUDER_FIRST_CASE) && (350 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (350))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 350),
+#endif
+#endif
+#if ((351 >= GSL_INCLUDER_FIRST_CASE) && (351 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (351))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 351),
+#endif
+#endif
+#if ((352 >= GSL_INCLUDER_FIRST_CASE) && (352 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (352))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 352),
+#endif
+#endif
+#if ((353 >= GSL_INCLUDER_FIRST_CASE) && (353 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (353))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 353),
+#endif
+#endif
+#if ((354 >= GSL_INCLUDER_FIRST_CASE) && (354 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (354))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 354),
+#endif
+#endif
+#if ((355 >= GSL_INCLUDER_FIRST_CASE) && (355 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (355))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 355),
+#endif
+#endif
+#if ((356 >= GSL_INCLUDER_FIRST_CASE) && (356 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (356))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 356),
+#endif
+#endif
+#if ((357 >= GSL_INCLUDER_FIRST_CASE) && (357 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (357))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 357),
+#endif
+#endif
+#if ((358 >= GSL_INCLUDER_FIRST_CASE) && (358 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (358))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 358),
+#endif
+#endif
+#if ((359 >= GSL_INCLUDER_FIRST_CASE) && (359 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (359))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 359),
+#endif
+#endif
+#if ((360 >= GSL_INCLUDER_FIRST_CASE) && (360 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (360))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 360),
+#endif
+#endif
+#if ((361 >= GSL_INCLUDER_FIRST_CASE) && (361 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (361))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 361),
+#endif
+#endif
+#if ((362 >= GSL_INCLUDER_FIRST_CASE) && (362 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (362))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 362),
+#endif
+#endif
+#if ((363 >= GSL_INCLUDER_FIRST_CASE) && (363 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (363))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 363),
+#endif
+#endif
+#if ((364 >= GSL_INCLUDER_FIRST_CASE) && (364 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (364))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 364),
+#endif
+#endif
+#if ((365 >= GSL_INCLUDER_FIRST_CASE) && (365 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (365))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 365),
+#endif
+#endif
+#if ((366 >= GSL_INCLUDER_FIRST_CASE) && (366 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (366))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 366),
+#endif
+#endif
+#if ((367 >= GSL_INCLUDER_FIRST_CASE) && (367 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (367))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 367),
+#endif
+#endif
+#if ((368 >= GSL_INCLUDER_FIRST_CASE) && (368 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (368))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 368),
+#endif
+#endif
+#if ((369 >= GSL_INCLUDER_FIRST_CASE) && (369 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (369))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 369),
+#endif
+#endif
+#if ((370 >= GSL_INCLUDER_FIRST_CASE) && (370 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (370))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 370),
+#endif
+#endif
+#if ((371 >= GSL_INCLUDER_FIRST_CASE) && (371 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (371))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 371),
+#endif
+#endif
+#if ((372 >= GSL_INCLUDER_FIRST_CASE) && (372 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (372))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 372),
+#endif
+#endif
+#if ((373 >= GSL_INCLUDER_FIRST_CASE) && (373 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (373))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 373),
+#endif
+#endif
+#if ((374 >= GSL_INCLUDER_FIRST_CASE) && (374 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (374))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 374),
+#endif
+#endif
+#if ((375 >= GSL_INCLUDER_FIRST_CASE) && (375 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (375))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 375),
+#endif
+#endif
+#if ((376 >= GSL_INCLUDER_FIRST_CASE) && (376 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (376))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 376),
+#endif
+#endif
+#if ((377 >= GSL_INCLUDER_FIRST_CASE) && (377 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (377))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 377),
+#endif
+#endif
+#if ((378 >= GSL_INCLUDER_FIRST_CASE) && (378 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (378))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 378),
+#endif
+#endif
+#if ((379 >= GSL_INCLUDER_FIRST_CASE) && (379 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (379))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 379),
+#endif
+#endif
+#if ((380 >= GSL_INCLUDER_FIRST_CASE) && (380 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (380))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 380),
+#endif
+#endif
+#if ((381 >= GSL_INCLUDER_FIRST_CASE) && (381 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (381))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 381),
+#endif
+#endif
+#if ((382 >= GSL_INCLUDER_FIRST_CASE) && (382 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (382))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 382),
+#endif
+#endif
+#if ((383 >= GSL_INCLUDER_FIRST_CASE) && (383 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (383))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 383),
+#endif
+#endif
+#if ((384 >= GSL_INCLUDER_FIRST_CASE) && (384 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (384))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 384),
+#endif
+#endif
+#if ((385 >= GSL_INCLUDER_FIRST_CASE) && (385 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (385))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 385),
+#endif
+#endif
+#if ((386 >= GSL_INCLUDER_FIRST_CASE) && (386 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (386))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 386),
+#endif
+#endif
+#if ((387 >= GSL_INCLUDER_FIRST_CASE) && (387 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (387))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 387),
+#endif
+#endif
+#if ((388 >= GSL_INCLUDER_FIRST_CASE) && (388 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (388))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 388),
+#endif
+#endif
+#if ((389 >= GSL_INCLUDER_FIRST_CASE) && (389 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (389))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 389),
+#endif
+#endif
+#if ((390 >= GSL_INCLUDER_FIRST_CASE) && (390 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (390))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 390),
+#endif
+#endif
+#if ((391 >= GSL_INCLUDER_FIRST_CASE) && (391 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (391))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 391),
+#endif
+#endif
+#if ((392 >= GSL_INCLUDER_FIRST_CASE) && (392 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (392))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 392),
+#endif
+#endif
+#if ((393 >= GSL_INCLUDER_FIRST_CASE) && (393 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (393))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 393),
+#endif
+#endif
+#if ((394 >= GSL_INCLUDER_FIRST_CASE) && (394 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (394))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 394),
+#endif
+#endif
+#if ((395 >= GSL_INCLUDER_FIRST_CASE) && (395 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (395))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 395),
+#endif
+#endif
+#if ((396 >= GSL_INCLUDER_FIRST_CASE) && (396 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (396))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 396),
+#endif
+#endif
+#if ((397 >= GSL_INCLUDER_FIRST_CASE) && (397 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (397))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 397),
+#endif
+#endif
+#if ((398 >= GSL_INCLUDER_FIRST_CASE) && (398 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (398))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 398),
+#endif
+#endif
+#if ((399 >= GSL_INCLUDER_FIRST_CASE) && (399 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (399))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 399),
+#endif
+#endif
+#if ((400 >= GSL_INCLUDER_FIRST_CASE) && (400 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (400))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 400),
+#endif
+#endif
+#if ((401 >= GSL_INCLUDER_FIRST_CASE) && (401 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (401))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 401),
+#endif
+#endif
+#if ((402 >= GSL_INCLUDER_FIRST_CASE) && (402 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (402))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 402),
+#endif
+#endif
+#if ((403 >= GSL_INCLUDER_FIRST_CASE) && (403 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (403))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 403),
+#endif
+#endif
+#if ((404 >= GSL_INCLUDER_FIRST_CASE) && (404 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (404))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 404),
+#endif
+#endif
+#if ((405 >= GSL_INCLUDER_FIRST_CASE) && (405 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (405))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 405),
+#endif
+#endif
+#if ((406 >= GSL_INCLUDER_FIRST_CASE) && (406 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (406))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 406),
+#endif
+#endif
+#if ((407 >= GSL_INCLUDER_FIRST_CASE) && (407 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (407))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 407),
+#endif
+#endif
+#if ((408 >= GSL_INCLUDER_FIRST_CASE) && (408 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (408))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 408),
+#endif
+#endif
+#if ((409 >= GSL_INCLUDER_FIRST_CASE) && (409 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (409))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 409),
+#endif
+#endif
+#if ((410 >= GSL_INCLUDER_FIRST_CASE) && (410 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (410))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 410),
+#endif
+#endif
+#if ((411 >= GSL_INCLUDER_FIRST_CASE) && (411 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (411))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 411),
+#endif
+#endif
+#if ((412 >= GSL_INCLUDER_FIRST_CASE) && (412 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (412))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 412),
+#endif
+#endif
+#if ((413 >= GSL_INCLUDER_FIRST_CASE) && (413 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (413))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 413),
+#endif
+#endif
+#if ((414 >= GSL_INCLUDER_FIRST_CASE) && (414 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (414))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 414),
+#endif
+#endif
+#if ((415 >= GSL_INCLUDER_FIRST_CASE) && (415 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (415))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 415),
+#endif
+#endif
+#if ((416 >= GSL_INCLUDER_FIRST_CASE) && (416 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (416))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 416),
+#endif
+#endif
+#if ((417 >= GSL_INCLUDER_FIRST_CASE) && (417 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (417))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 417),
+#endif
+#endif
+#if ((418 >= GSL_INCLUDER_FIRST_CASE) && (418 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (418))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 418),
+#endif
+#endif
+#if ((419 >= GSL_INCLUDER_FIRST_CASE) && (419 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (419))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 419),
+#endif
+#endif
+#if ((420 >= GSL_INCLUDER_FIRST_CASE) && (420 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (420))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 420),
+#endif
+#endif
+#if ((421 >= GSL_INCLUDER_FIRST_CASE) && (421 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (421))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 421),
+#endif
+#endif
+#if ((422 >= GSL_INCLUDER_FIRST_CASE) && (422 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (422))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 422),
+#endif
+#endif
+#if ((423 >= GSL_INCLUDER_FIRST_CASE) && (423 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (423))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 423),
+#endif
+#endif
+#if ((424 >= GSL_INCLUDER_FIRST_CASE) && (424 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (424))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 424),
+#endif
+#endif
+#if ((425 >= GSL_INCLUDER_FIRST_CASE) && (425 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (425))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 425),
+#endif
+#endif
+#if ((426 >= GSL_INCLUDER_FIRST_CASE) && (426 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (426))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 426),
+#endif
+#endif
+#if ((427 >= GSL_INCLUDER_FIRST_CASE) && (427 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (427))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 427),
+#endif
+#endif
+#if ((428 >= GSL_INCLUDER_FIRST_CASE) && (428 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (428))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 428),
+#endif
+#endif
+#if ((429 >= GSL_INCLUDER_FIRST_CASE) && (429 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (429))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 429),
+#endif
+#endif
+#if ((430 >= GSL_INCLUDER_FIRST_CASE) && (430 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (430))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 430),
+#endif
+#endif
+#if ((431 >= GSL_INCLUDER_FIRST_CASE) && (431 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (431))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 431),
+#endif
+#endif
+#if ((432 >= GSL_INCLUDER_FIRST_CASE) && (432 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (432))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 432),
+#endif
+#endif
+#if ((433 >= GSL_INCLUDER_FIRST_CASE) && (433 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (433))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 433),
+#endif
+#endif
+#if ((434 >= GSL_INCLUDER_FIRST_CASE) && (434 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (434))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 434),
+#endif
+#endif
+#if ((435 >= GSL_INCLUDER_FIRST_CASE) && (435 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (435))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 435),
+#endif
+#endif
+#if ((436 >= GSL_INCLUDER_FIRST_CASE) && (436 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (436))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 436),
+#endif
+#endif
+#if ((437 >= GSL_INCLUDER_FIRST_CASE) && (437 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (437))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 437),
+#endif
+#endif
+#if ((438 >= GSL_INCLUDER_FIRST_CASE) && (438 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (438))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 438),
+#endif
+#endif
+#if ((439 >= GSL_INCLUDER_FIRST_CASE) && (439 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (439))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 439),
+#endif
+#endif
+#if ((440 >= GSL_INCLUDER_FIRST_CASE) && (440 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (440))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 440),
+#endif
+#endif
+#if ((441 >= GSL_INCLUDER_FIRST_CASE) && (441 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (441))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 441),
+#endif
+#endif
+#if ((442 >= GSL_INCLUDER_FIRST_CASE) && (442 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (442))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 442),
+#endif
+#endif
+#if ((443 >= GSL_INCLUDER_FIRST_CASE) && (443 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (443))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 443),
+#endif
+#endif
+#if ((444 >= GSL_INCLUDER_FIRST_CASE) && (444 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (444))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 444),
+#endif
+#endif
+#if ((445 >= GSL_INCLUDER_FIRST_CASE) && (445 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (445))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 445),
+#endif
+#endif
+#if ((446 >= GSL_INCLUDER_FIRST_CASE) && (446 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (446))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 446),
+#endif
+#endif
+#if ((447 >= GSL_INCLUDER_FIRST_CASE) && (447 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (447))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 447),
+#endif
+#endif
+#if ((448 >= GSL_INCLUDER_FIRST_CASE) && (448 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (448))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 448),
+#endif
+#endif
+#if ((449 >= GSL_INCLUDER_FIRST_CASE) && (449 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (449))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 449),
+#endif
+#endif
+#if ((450 >= GSL_INCLUDER_FIRST_CASE) && (450 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (450))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 450),
+#endif
+#endif
+#if ((451 >= GSL_INCLUDER_FIRST_CASE) && (451 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (451))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 451),
+#endif
+#endif
+#if ((452 >= GSL_INCLUDER_FIRST_CASE) && (452 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (452))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 452),
+#endif
+#endif
+#if ((453 >= GSL_INCLUDER_FIRST_CASE) && (453 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (453))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 453),
+#endif
+#endif
+#if ((454 >= GSL_INCLUDER_FIRST_CASE) && (454 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (454))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 454),
+#endif
+#endif
+#if ((455 >= GSL_INCLUDER_FIRST_CASE) && (455 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (455))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 455),
+#endif
+#endif
+#if ((456 >= GSL_INCLUDER_FIRST_CASE) && (456 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (456))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 456),
+#endif
+#endif
+#if ((457 >= GSL_INCLUDER_FIRST_CASE) && (457 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (457))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 457),
+#endif
+#endif
+#if ((458 >= GSL_INCLUDER_FIRST_CASE) && (458 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (458))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 458),
+#endif
+#endif
+#if ((459 >= GSL_INCLUDER_FIRST_CASE) && (459 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (459))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 459),
+#endif
+#endif
+#if ((460 >= GSL_INCLUDER_FIRST_CASE) && (460 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (460))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 460),
+#endif
+#endif
+#if ((461 >= GSL_INCLUDER_FIRST_CASE) && (461 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (461))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 461),
+#endif
+#endif
+#if ((462 >= GSL_INCLUDER_FIRST_CASE) && (462 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (462))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 462),
+#endif
+#endif
+#if ((463 >= GSL_INCLUDER_FIRST_CASE) && (463 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (463))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 463),
+#endif
+#endif
+#if ((464 >= GSL_INCLUDER_FIRST_CASE) && (464 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (464))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 464),
+#endif
+#endif
+#if ((465 >= GSL_INCLUDER_FIRST_CASE) && (465 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (465))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 465),
+#endif
+#endif
+#if ((466 >= GSL_INCLUDER_FIRST_CASE) && (466 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (466))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 466),
+#endif
+#endif
+#if ((467 >= GSL_INCLUDER_FIRST_CASE) && (467 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (467))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 467),
+#endif
+#endif
+#if ((468 >= GSL_INCLUDER_FIRST_CASE) && (468 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (468))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 468),
+#endif
+#endif
+#if ((469 >= GSL_INCLUDER_FIRST_CASE) && (469 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (469))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 469),
+#endif
+#endif
+#if ((470 >= GSL_INCLUDER_FIRST_CASE) && (470 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (470))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 470),
+#endif
+#endif
+#if ((471 >= GSL_INCLUDER_FIRST_CASE) && (471 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (471))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 471),
+#endif
+#endif
+#if ((472 >= GSL_INCLUDER_FIRST_CASE) && (472 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (472))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 472),
+#endif
+#endif
+#if ((473 >= GSL_INCLUDER_FIRST_CASE) && (473 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (473))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 473),
+#endif
+#endif
+#if ((474 >= GSL_INCLUDER_FIRST_CASE) && (474 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (474))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 474),
+#endif
+#endif
+#if ((475 >= GSL_INCLUDER_FIRST_CASE) && (475 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (475))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 475),
+#endif
+#endif
+#if ((476 >= GSL_INCLUDER_FIRST_CASE) && (476 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (476))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 476),
+#endif
+#endif
+#if ((477 >= GSL_INCLUDER_FIRST_CASE) && (477 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (477))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 477),
+#endif
+#endif
+#if ((478 >= GSL_INCLUDER_FIRST_CASE) && (478 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (478))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 478),
+#endif
+#endif
+#if ((479 >= GSL_INCLUDER_FIRST_CASE) && (479 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (479))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 479),
+#endif
+#endif
+#if ((480 >= GSL_INCLUDER_FIRST_CASE) && (480 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (480))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 480),
+#endif
+#endif
+#if ((481 >= GSL_INCLUDER_FIRST_CASE) && (481 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (481))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 481),
+#endif
+#endif
+#if ((482 >= GSL_INCLUDER_FIRST_CASE) && (482 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (482))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 482),
+#endif
+#endif
+#if ((483 >= GSL_INCLUDER_FIRST_CASE) && (483 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (483))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 483),
+#endif
+#endif
+#if ((484 >= GSL_INCLUDER_FIRST_CASE) && (484 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (484))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 484),
+#endif
+#endif
+#if ((485 >= GSL_INCLUDER_FIRST_CASE) && (485 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (485))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 485),
+#endif
+#endif
+#if ((486 >= GSL_INCLUDER_FIRST_CASE) && (486 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (486))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 486),
+#endif
+#endif
+#if ((487 >= GSL_INCLUDER_FIRST_CASE) && (487 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (487))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 487),
+#endif
+#endif
+#if ((488 >= GSL_INCLUDER_FIRST_CASE) && (488 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (488))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 488),
+#endif
+#endif
+#if ((489 >= GSL_INCLUDER_FIRST_CASE) && (489 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (489))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 489),
+#endif
+#endif
+#if ((490 >= GSL_INCLUDER_FIRST_CASE) && (490 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (490))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 490),
+#endif
+#endif
+#if ((491 >= GSL_INCLUDER_FIRST_CASE) && (491 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (491))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 491),
+#endif
+#endif
+#if ((492 >= GSL_INCLUDER_FIRST_CASE) && (492 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (492))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 492),
+#endif
+#endif
+#if ((493 >= GSL_INCLUDER_FIRST_CASE) && (493 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (493))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 493),
+#endif
+#endif
+#if ((494 >= GSL_INCLUDER_FIRST_CASE) && (494 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (494))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 494),
+#endif
+#endif
+#if ((495 >= GSL_INCLUDER_FIRST_CASE) && (495 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (495))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 495),
+#endif
+#endif
+#if ((496 >= GSL_INCLUDER_FIRST_CASE) && (496 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (496))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 496),
+#endif
+#endif
+#if ((497 >= GSL_INCLUDER_FIRST_CASE) && (497 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (497))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 497),
+#endif
+#endif
+#if ((498 >= GSL_INCLUDER_FIRST_CASE) && (498 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (498))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 498),
+#endif
+#endif
+#if ((499 >= GSL_INCLUDER_FIRST_CASE) && (499 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (499))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 499),
+#endif
+#endif
+#if ((500 >= GSL_INCLUDER_FIRST_CASE) && (500 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (500))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 500),
+#endif
+#endif
+#if ((501 >= GSL_INCLUDER_FIRST_CASE) && (501 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (501))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 501),
+#endif
+#endif
+#if ((502 >= GSL_INCLUDER_FIRST_CASE) && (502 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (502))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 502),
+#endif
+#endif
+#if ((503 >= GSL_INCLUDER_FIRST_CASE) && (503 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (503))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 503),
+#endif
+#endif
+#if ((504 >= GSL_INCLUDER_FIRST_CASE) && (504 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (504))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 504),
+#endif
+#endif
+#if ((505 >= GSL_INCLUDER_FIRST_CASE) && (505 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (505))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 505),
+#endif
+#endif
+#if ((506 >= GSL_INCLUDER_FIRST_CASE) && (506 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (506))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 506),
+#endif
+#endif
+#if ((507 >= GSL_INCLUDER_FIRST_CASE) && (507 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (507))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 507),
+#endif
+#endif
+#if ((508 >= GSL_INCLUDER_FIRST_CASE) && (508 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (508))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 508),
+#endif
+#endif
+#if ((509 >= GSL_INCLUDER_FIRST_CASE) && (509 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (509))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 509),
+#endif
+#endif
+#if ((510 >= GSL_INCLUDER_FIRST_CASE) && (510 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (510))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 510),
+#endif
+#endif
+#if ((511 >= GSL_INCLUDER_FIRST_CASE) && (511 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (511))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 511),
+#endif
+#endif
+#if ((512 >= GSL_INCLUDER_FIRST_CASE) && (512 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (512))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 512),
+#endif
+#endif
+#if ((513 >= GSL_INCLUDER_FIRST_CASE) && (513 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (513))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 513),
+#endif
+#endif
+#if ((514 >= GSL_INCLUDER_FIRST_CASE) && (514 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (514))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 514),
+#endif
+#endif
+#if ((515 >= GSL_INCLUDER_FIRST_CASE) && (515 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (515))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 515),
+#endif
+#endif
+#if ((516 >= GSL_INCLUDER_FIRST_CASE) && (516 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (516))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 516),
+#endif
+#endif
+#if ((517 >= GSL_INCLUDER_FIRST_CASE) && (517 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (517))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 517),
+#endif
+#endif
+#if ((518 >= GSL_INCLUDER_FIRST_CASE) && (518 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (518))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 518),
+#endif
+#endif
+#if ((519 >= GSL_INCLUDER_FIRST_CASE) && (519 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (519))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 519),
+#endif
+#endif
+#if ((520 >= GSL_INCLUDER_FIRST_CASE) && (520 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (520))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 520),
+#endif
+#endif
+#if ((521 >= GSL_INCLUDER_FIRST_CASE) && (521 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (521))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 521),
+#endif
+#endif
+#if ((522 >= GSL_INCLUDER_FIRST_CASE) && (522 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (522))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 522),
+#endif
+#endif
+#if ((523 >= GSL_INCLUDER_FIRST_CASE) && (523 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (523))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 523),
+#endif
+#endif
+#if ((524 >= GSL_INCLUDER_FIRST_CASE) && (524 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (524))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 524),
+#endif
+#endif
+#if ((525 >= GSL_INCLUDER_FIRST_CASE) && (525 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (525))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 525),
+#endif
+#endif
+#if ((526 >= GSL_INCLUDER_FIRST_CASE) && (526 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (526))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 526),
+#endif
+#endif
+#if ((527 >= GSL_INCLUDER_FIRST_CASE) && (527 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (527))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 527),
+#endif
+#endif
+#if ((528 >= GSL_INCLUDER_FIRST_CASE) && (528 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (528))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 528),
+#endif
+#endif
+#if ((529 >= GSL_INCLUDER_FIRST_CASE) && (529 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (529))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 529),
+#endif
+#endif
+#if ((530 >= GSL_INCLUDER_FIRST_CASE) && (530 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (530))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 530),
+#endif
+#endif
+#if ((531 >= GSL_INCLUDER_FIRST_CASE) && (531 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (531))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 531),
+#endif
+#endif
+#if ((532 >= GSL_INCLUDER_FIRST_CASE) && (532 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (532))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 532),
+#endif
+#endif
+#if ((533 >= GSL_INCLUDER_FIRST_CASE) && (533 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (533))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 533),
+#endif
+#endif
+#if ((534 >= GSL_INCLUDER_FIRST_CASE) && (534 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (534))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 534),
+#endif
+#endif
+#if ((535 >= GSL_INCLUDER_FIRST_CASE) && (535 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (535))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 535),
+#endif
+#endif
+#if ((536 >= GSL_INCLUDER_FIRST_CASE) && (536 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (536))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 536),
+#endif
+#endif
+#if ((537 >= GSL_INCLUDER_FIRST_CASE) && (537 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (537))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 537),
+#endif
+#endif
+#if ((538 >= GSL_INCLUDER_FIRST_CASE) && (538 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (538))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 538),
+#endif
+#endif
+#if ((539 >= GSL_INCLUDER_FIRST_CASE) && (539 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (539))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 539),
+#endif
+#endif
+#if ((540 >= GSL_INCLUDER_FIRST_CASE) && (540 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (540))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 540),
+#endif
+#endif
+#if ((541 >= GSL_INCLUDER_FIRST_CASE) && (541 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (541))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 541),
+#endif
+#endif
+#if ((542 >= GSL_INCLUDER_FIRST_CASE) && (542 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (542))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 542),
+#endif
+#endif
+#if ((543 >= GSL_INCLUDER_FIRST_CASE) && (543 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (543))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 543),
+#endif
+#endif
+#if ((544 >= GSL_INCLUDER_FIRST_CASE) && (544 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (544))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 544),
+#endif
+#endif
+#if ((545 >= GSL_INCLUDER_FIRST_CASE) && (545 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (545))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 545),
+#endif
+#endif
+#if ((546 >= GSL_INCLUDER_FIRST_CASE) && (546 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (546))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 546),
+#endif
+#endif
+#if ((547 >= GSL_INCLUDER_FIRST_CASE) && (547 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (547))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 547),
+#endif
+#endif
+#if ((548 >= GSL_INCLUDER_FIRST_CASE) && (548 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (548))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 548),
+#endif
+#endif
+#if ((549 >= GSL_INCLUDER_FIRST_CASE) && (549 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (549))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 549),
+#endif
+#endif
+#if ((550 >= GSL_INCLUDER_FIRST_CASE) && (550 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (550))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 550),
+#endif
+#endif
+#if ((551 >= GSL_INCLUDER_FIRST_CASE) && (551 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (551))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 551),
+#endif
+#endif
+#if ((552 >= GSL_INCLUDER_FIRST_CASE) && (552 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (552))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 552),
+#endif
+#endif
+#if ((553 >= GSL_INCLUDER_FIRST_CASE) && (553 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (553))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 553),
+#endif
+#endif
+#if ((554 >= GSL_INCLUDER_FIRST_CASE) && (554 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (554))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 554),
+#endif
+#endif
+#if ((555 >= GSL_INCLUDER_FIRST_CASE) && (555 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (555))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 555),
+#endif
+#endif
+#if ((556 >= GSL_INCLUDER_FIRST_CASE) && (556 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (556))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 556),
+#endif
+#endif
+#if ((557 >= GSL_INCLUDER_FIRST_CASE) && (557 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (557))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 557),
+#endif
+#endif
+#if ((558 >= GSL_INCLUDER_FIRST_CASE) && (558 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (558))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 558),
+#endif
+#endif
+#if ((559 >= GSL_INCLUDER_FIRST_CASE) && (559 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (559))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 559),
+#endif
+#endif
+#if ((560 >= GSL_INCLUDER_FIRST_CASE) && (560 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (560))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 560),
+#endif
+#endif
+#if ((561 >= GSL_INCLUDER_FIRST_CASE) && (561 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (561))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 561),
+#endif
+#endif
+#if ((562 >= GSL_INCLUDER_FIRST_CASE) && (562 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (562))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 562),
+#endif
+#endif
+#if ((563 >= GSL_INCLUDER_FIRST_CASE) && (563 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (563))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 563),
+#endif
+#endif
+#if ((564 >= GSL_INCLUDER_FIRST_CASE) && (564 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (564))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 564),
+#endif
+#endif
+#if ((565 >= GSL_INCLUDER_FIRST_CASE) && (565 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (565))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 565),
+#endif
+#endif
+#if ((566 >= GSL_INCLUDER_FIRST_CASE) && (566 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (566))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 566),
+#endif
+#endif
+#if ((567 >= GSL_INCLUDER_FIRST_CASE) && (567 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (567))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 567),
+#endif
+#endif
+#if ((568 >= GSL_INCLUDER_FIRST_CASE) && (568 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (568))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 568),
+#endif
+#endif
+#if ((569 >= GSL_INCLUDER_FIRST_CASE) && (569 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (569))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 569),
+#endif
+#endif
+#if ((570 >= GSL_INCLUDER_FIRST_CASE) && (570 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (570))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 570),
+#endif
+#endif
+#if ((571 >= GSL_INCLUDER_FIRST_CASE) && (571 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (571))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 571),
+#endif
+#endif
+#if ((572 >= GSL_INCLUDER_FIRST_CASE) && (572 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (572))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 572),
+#endif
+#endif
+#if ((573 >= GSL_INCLUDER_FIRST_CASE) && (573 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (573))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 573),
+#endif
+#endif
+#if ((574 >= GSL_INCLUDER_FIRST_CASE) && (574 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (574))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 574),
+#endif
+#endif
+#if ((575 >= GSL_INCLUDER_FIRST_CASE) && (575 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (575))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 575),
+#endif
+#endif
+#if ((576 >= GSL_INCLUDER_FIRST_CASE) && (576 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (576))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 576),
+#endif
+#endif
+#if ((577 >= GSL_INCLUDER_FIRST_CASE) && (577 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (577))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 577),
+#endif
+#endif
+#if ((578 >= GSL_INCLUDER_FIRST_CASE) && (578 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (578))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 578),
+#endif
+#endif
+#if ((579 >= GSL_INCLUDER_FIRST_CASE) && (579 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (579))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 579),
+#endif
+#endif
+#if ((580 >= GSL_INCLUDER_FIRST_CASE) && (580 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (580))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 580),
+#endif
+#endif
+#if ((581 >= GSL_INCLUDER_FIRST_CASE) && (581 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (581))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 581),
+#endif
+#endif
+#if ((582 >= GSL_INCLUDER_FIRST_CASE) && (582 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (582))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 582),
+#endif
+#endif
+#if ((583 >= GSL_INCLUDER_FIRST_CASE) && (583 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (583))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 583),
+#endif
+#endif
+#if ((584 >= GSL_INCLUDER_FIRST_CASE) && (584 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (584))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 584),
+#endif
+#endif
+#if ((585 >= GSL_INCLUDER_FIRST_CASE) && (585 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (585))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 585),
+#endif
+#endif
+#if ((586 >= GSL_INCLUDER_FIRST_CASE) && (586 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (586))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 586),
+#endif
+#endif
+#if ((587 >= GSL_INCLUDER_FIRST_CASE) && (587 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (587))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 587),
+#endif
+#endif
+#if ((588 >= GSL_INCLUDER_FIRST_CASE) && (588 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (588))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 588),
+#endif
+#endif
+#if ((589 >= GSL_INCLUDER_FIRST_CASE) && (589 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (589))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 589),
+#endif
+#endif
+#if ((590 >= GSL_INCLUDER_FIRST_CASE) && (590 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (590))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 590),
+#endif
+#endif
+#if ((591 >= GSL_INCLUDER_FIRST_CASE) && (591 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (591))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 591),
+#endif
+#endif
+#if ((592 >= GSL_INCLUDER_FIRST_CASE) && (592 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (592))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 592),
+#endif
+#endif
+#if ((593 >= GSL_INCLUDER_FIRST_CASE) && (593 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (593))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 593),
+#endif
+#endif
+#if ((594 >= GSL_INCLUDER_FIRST_CASE) && (594 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (594))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 594),
+#endif
+#endif
+#if ((595 >= GSL_INCLUDER_FIRST_CASE) && (595 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (595))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 595),
+#endif
+#endif
+#if ((596 >= GSL_INCLUDER_FIRST_CASE) && (596 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (596))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 596),
+#endif
+#endif
+#if ((597 >= GSL_INCLUDER_FIRST_CASE) && (597 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (597))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 597),
+#endif
+#endif
+#if ((598 >= GSL_INCLUDER_FIRST_CASE) && (598 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (598))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 598),
+#endif
+#endif
+#if ((599 >= GSL_INCLUDER_FIRST_CASE) && (599 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (599))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 599),
+#endif
+#endif
+#if ((600 >= GSL_INCLUDER_FIRST_CASE) && (600 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (600))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 600),
+#endif
+#endif
+#if ((601 >= GSL_INCLUDER_FIRST_CASE) && (601 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (601))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 601),
+#endif
+#endif
+#if ((602 >= GSL_INCLUDER_FIRST_CASE) && (602 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (602))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 602),
+#endif
+#endif
+#if ((603 >= GSL_INCLUDER_FIRST_CASE) && (603 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (603))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 603),
+#endif
+#endif
+#if ((604 >= GSL_INCLUDER_FIRST_CASE) && (604 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (604))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 604),
+#endif
+#endif
+#if ((605 >= GSL_INCLUDER_FIRST_CASE) && (605 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (605))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 605),
+#endif
+#endif
+#if ((606 >= GSL_INCLUDER_FIRST_CASE) && (606 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (606))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 606),
+#endif
+#endif
+#if ((607 >= GSL_INCLUDER_FIRST_CASE) && (607 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (607))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 607),
+#endif
+#endif
+#if ((608 >= GSL_INCLUDER_FIRST_CASE) && (608 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (608))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 608),
+#endif
+#endif
+#if ((609 >= GSL_INCLUDER_FIRST_CASE) && (609 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (609))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 609),
+#endif
+#endif
+#if ((610 >= GSL_INCLUDER_FIRST_CASE) && (610 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (610))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 610),
+#endif
+#endif
+#if ((611 >= GSL_INCLUDER_FIRST_CASE) && (611 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (611))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 611),
+#endif
+#endif
+#if ((612 >= GSL_INCLUDER_FIRST_CASE) && (612 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (612))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 612),
+#endif
+#endif
+#if ((613 >= GSL_INCLUDER_FIRST_CASE) && (613 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (613))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 613),
+#endif
+#endif
+#if ((614 >= GSL_INCLUDER_FIRST_CASE) && (614 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (614))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 614),
+#endif
+#endif
+#if ((615 >= GSL_INCLUDER_FIRST_CASE) && (615 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (615))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 615),
+#endif
+#endif
+#if ((616 >= GSL_INCLUDER_FIRST_CASE) && (616 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (616))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 616),
+#endif
+#endif
+#if ((617 >= GSL_INCLUDER_FIRST_CASE) && (617 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (617))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 617),
+#endif
+#endif
+#if ((618 >= GSL_INCLUDER_FIRST_CASE) && (618 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (618))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 618),
+#endif
+#endif
+#if ((619 >= GSL_INCLUDER_FIRST_CASE) && (619 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (619))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 619),
+#endif
+#endif
+#if ((620 >= GSL_INCLUDER_FIRST_CASE) && (620 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (620))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 620),
+#endif
+#endif
+#if ((621 >= GSL_INCLUDER_FIRST_CASE) && (621 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (621))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 621),
+#endif
+#endif
+#if ((622 >= GSL_INCLUDER_FIRST_CASE) && (622 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (622))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 622),
+#endif
+#endif
+#if ((623 >= GSL_INCLUDER_FIRST_CASE) && (623 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (623))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 623),
+#endif
+#endif
+#if ((624 >= GSL_INCLUDER_FIRST_CASE) && (624 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (624))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 624),
+#endif
+#endif
+#if ((625 >= GSL_INCLUDER_FIRST_CASE) && (625 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (625))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 625),
+#endif
+#endif
+#if ((626 >= GSL_INCLUDER_FIRST_CASE) && (626 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (626))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 626),
+#endif
+#endif
+#if ((627 >= GSL_INCLUDER_FIRST_CASE) && (627 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (627))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 627),
+#endif
+#endif
+#if ((628 >= GSL_INCLUDER_FIRST_CASE) && (628 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (628))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 628),
+#endif
+#endif
+#if ((629 >= GSL_INCLUDER_FIRST_CASE) && (629 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (629))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 629),
+#endif
+#endif
+#if ((630 >= GSL_INCLUDER_FIRST_CASE) && (630 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (630))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 630),
+#endif
+#endif
+#if ((631 >= GSL_INCLUDER_FIRST_CASE) && (631 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (631))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 631),
+#endif
+#endif
+#if ((632 >= GSL_INCLUDER_FIRST_CASE) && (632 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (632))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 632),
+#endif
+#endif
+#if ((633 >= GSL_INCLUDER_FIRST_CASE) && (633 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (633))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 633),
+#endif
+#endif
+#if ((634 >= GSL_INCLUDER_FIRST_CASE) && (634 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (634))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 634),
+#endif
+#endif
+#if ((635 >= GSL_INCLUDER_FIRST_CASE) && (635 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (635))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 635),
+#endif
+#endif
+#if ((636 >= GSL_INCLUDER_FIRST_CASE) && (636 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (636))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 636),
+#endif
+#endif
+#if ((637 >= GSL_INCLUDER_FIRST_CASE) && (637 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (637))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 637),
+#endif
+#endif
+#if ((638 >= GSL_INCLUDER_FIRST_CASE) && (638 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (638))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 638),
+#endif
+#endif
+#if ((639 >= GSL_INCLUDER_FIRST_CASE) && (639 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (639))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 639),
+#endif
+#endif
+#if ((640 >= GSL_INCLUDER_FIRST_CASE) && (640 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (640))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 640),
+#endif
+#endif
+#if ((641 >= GSL_INCLUDER_FIRST_CASE) && (641 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (641))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 641),
+#endif
+#endif
+#if ((642 >= GSL_INCLUDER_FIRST_CASE) && (642 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (642))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 642),
+#endif
+#endif
+#if ((643 >= GSL_INCLUDER_FIRST_CASE) && (643 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (643))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 643),
+#endif
+#endif
+#if ((644 >= GSL_INCLUDER_FIRST_CASE) && (644 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (644))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 644),
+#endif
+#endif
+#if ((645 >= GSL_INCLUDER_FIRST_CASE) && (645 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (645))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 645),
+#endif
+#endif
+#if ((646 >= GSL_INCLUDER_FIRST_CASE) && (646 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (646))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 646),
+#endif
+#endif
+#if ((647 >= GSL_INCLUDER_FIRST_CASE) && (647 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (647))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 647),
+#endif
+#endif
+#if ((648 >= GSL_INCLUDER_FIRST_CASE) && (648 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (648))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 648),
+#endif
+#endif
+#if ((649 >= GSL_INCLUDER_FIRST_CASE) && (649 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (649))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 649),
+#endif
+#endif
+#if ((650 >= GSL_INCLUDER_FIRST_CASE) && (650 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (650))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 650),
+#endif
+#endif
+#if ((651 >= GSL_INCLUDER_FIRST_CASE) && (651 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (651))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 651),
+#endif
+#endif
+#if ((652 >= GSL_INCLUDER_FIRST_CASE) && (652 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (652))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 652),
+#endif
+#endif
+#if ((653 >= GSL_INCLUDER_FIRST_CASE) && (653 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (653))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 653),
+#endif
+#endif
+#if ((654 >= GSL_INCLUDER_FIRST_CASE) && (654 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (654))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 654),
+#endif
+#endif
+#if ((655 >= GSL_INCLUDER_FIRST_CASE) && (655 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (655))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 655),
+#endif
+#endif
+#if ((656 >= GSL_INCLUDER_FIRST_CASE) && (656 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (656))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 656),
+#endif
+#endif
+#if ((657 >= GSL_INCLUDER_FIRST_CASE) && (657 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (657))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 657),
+#endif
+#endif
+#if ((658 >= GSL_INCLUDER_FIRST_CASE) && (658 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (658))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 658),
+#endif
+#endif
+#if ((659 >= GSL_INCLUDER_FIRST_CASE) && (659 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (659))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 659),
+#endif
+#endif
+#if ((660 >= GSL_INCLUDER_FIRST_CASE) && (660 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (660))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 660),
+#endif
+#endif
+#if ((661 >= GSL_INCLUDER_FIRST_CASE) && (661 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (661))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 661),
+#endif
+#endif
+#if ((662 >= GSL_INCLUDER_FIRST_CASE) && (662 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (662))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 662),
+#endif
+#endif
+#if ((663 >= GSL_INCLUDER_FIRST_CASE) && (663 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (663))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 663),
+#endif
+#endif
+#if ((664 >= GSL_INCLUDER_FIRST_CASE) && (664 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (664))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 664),
+#endif
+#endif
+#if ((665 >= GSL_INCLUDER_FIRST_CASE) && (665 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (665))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 665),
+#endif
+#endif
+#if ((666 >= GSL_INCLUDER_FIRST_CASE) && (666 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (666))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 666),
+#endif
+#endif
+#if ((667 >= GSL_INCLUDER_FIRST_CASE) && (667 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (667))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 667),
+#endif
+#endif
+#if ((668 >= GSL_INCLUDER_FIRST_CASE) && (668 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (668))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 668),
+#endif
+#endif
+#if ((669 >= GSL_INCLUDER_FIRST_CASE) && (669 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (669))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 669),
+#endif
+#endif
+#if ((670 >= GSL_INCLUDER_FIRST_CASE) && (670 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (670))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 670),
+#endif
+#endif
+#if ((671 >= GSL_INCLUDER_FIRST_CASE) && (671 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (671))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 671),
+#endif
+#endif
+#if ((672 >= GSL_INCLUDER_FIRST_CASE) && (672 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (672))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 672),
+#endif
+#endif
+#if ((673 >= GSL_INCLUDER_FIRST_CASE) && (673 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (673))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 673),
+#endif
+#endif
+#if ((674 >= GSL_INCLUDER_FIRST_CASE) && (674 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (674))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 674),
+#endif
+#endif
+#if ((675 >= GSL_INCLUDER_FIRST_CASE) && (675 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (675))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 675),
+#endif
+#endif
+#if ((676 >= GSL_INCLUDER_FIRST_CASE) && (676 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (676))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 676),
+#endif
+#endif
+#if ((677 >= GSL_INCLUDER_FIRST_CASE) && (677 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (677))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 677),
+#endif
+#endif
+#if ((678 >= GSL_INCLUDER_FIRST_CASE) && (678 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (678))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 678),
+#endif
+#endif
+#if ((679 >= GSL_INCLUDER_FIRST_CASE) && (679 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (679))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 679),
+#endif
+#endif
+#if ((680 >= GSL_INCLUDER_FIRST_CASE) && (680 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (680))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 680),
+#endif
+#endif
+#if ((681 >= GSL_INCLUDER_FIRST_CASE) && (681 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (681))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 681),
+#endif
+#endif
+#if ((682 >= GSL_INCLUDER_FIRST_CASE) && (682 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (682))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 682),
+#endif
+#endif
+#if ((683 >= GSL_INCLUDER_FIRST_CASE) && (683 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (683))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 683),
+#endif
+#endif
+#if ((684 >= GSL_INCLUDER_FIRST_CASE) && (684 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (684))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 684),
+#endif
+#endif
+#if ((685 >= GSL_INCLUDER_FIRST_CASE) && (685 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (685))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 685),
+#endif
+#endif
+#if ((686 >= GSL_INCLUDER_FIRST_CASE) && (686 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (686))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 686),
+#endif
+#endif
+#if ((687 >= GSL_INCLUDER_FIRST_CASE) && (687 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (687))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 687),
+#endif
+#endif
+#if ((688 >= GSL_INCLUDER_FIRST_CASE) && (688 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (688))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 688),
+#endif
+#endif
+#if ((689 >= GSL_INCLUDER_FIRST_CASE) && (689 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (689))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 689),
+#endif
+#endif
+#if ((690 >= GSL_INCLUDER_FIRST_CASE) && (690 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (690))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 690),
+#endif
+#endif
+#if ((691 >= GSL_INCLUDER_FIRST_CASE) && (691 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (691))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 691),
+#endif
+#endif
+#if ((692 >= GSL_INCLUDER_FIRST_CASE) && (692 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (692))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 692),
+#endif
+#endif
+#if ((693 >= GSL_INCLUDER_FIRST_CASE) && (693 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (693))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 693),
+#endif
+#endif
+#if ((694 >= GSL_INCLUDER_FIRST_CASE) && (694 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (694))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 694),
+#endif
+#endif
+#if ((695 >= GSL_INCLUDER_FIRST_CASE) && (695 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (695))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 695),
+#endif
+#endif
+#if ((696 >= GSL_INCLUDER_FIRST_CASE) && (696 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (696))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 696),
+#endif
+#endif
+#if ((697 >= GSL_INCLUDER_FIRST_CASE) && (697 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (697))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 697),
+#endif
+#endif
+#if ((698 >= GSL_INCLUDER_FIRST_CASE) && (698 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (698))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 698),
+#endif
+#endif
+#if ((699 >= GSL_INCLUDER_FIRST_CASE) && (699 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (699))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 699),
+#endif
+#endif
+#if ((700 >= GSL_INCLUDER_FIRST_CASE) && (700 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (700))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 700),
+#endif
+#endif
+#if ((701 >= GSL_INCLUDER_FIRST_CASE) && (701 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (701))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 701),
+#endif
+#endif
+#if ((702 >= GSL_INCLUDER_FIRST_CASE) && (702 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (702))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 702),
+#endif
+#endif
+#if ((703 >= GSL_INCLUDER_FIRST_CASE) && (703 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (703))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 703),
+#endif
+#endif
+#if ((704 >= GSL_INCLUDER_FIRST_CASE) && (704 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (704))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 704),
+#endif
+#endif
+#if ((705 >= GSL_INCLUDER_FIRST_CASE) && (705 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (705))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 705),
+#endif
+#endif
+#if ((706 >= GSL_INCLUDER_FIRST_CASE) && (706 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (706))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 706),
+#endif
+#endif
+#if ((707 >= GSL_INCLUDER_FIRST_CASE) && (707 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (707))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 707),
+#endif
+#endif
+#if ((708 >= GSL_INCLUDER_FIRST_CASE) && (708 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (708))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 708),
+#endif
+#endif
+#if ((709 >= GSL_INCLUDER_FIRST_CASE) && (709 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (709))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 709),
+#endif
+#endif
+#if ((710 >= GSL_INCLUDER_FIRST_CASE) && (710 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (710))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 710),
+#endif
+#endif
+#if ((711 >= GSL_INCLUDER_FIRST_CASE) && (711 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (711))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 711),
+#endif
+#endif
+#if ((712 >= GSL_INCLUDER_FIRST_CASE) && (712 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (712))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 712),
+#endif
+#endif
+#if ((713 >= GSL_INCLUDER_FIRST_CASE) && (713 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (713))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 713),
+#endif
+#endif
+#if ((714 >= GSL_INCLUDER_FIRST_CASE) && (714 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (714))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 714),
+#endif
+#endif
+#if ((715 >= GSL_INCLUDER_FIRST_CASE) && (715 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (715))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 715),
+#endif
+#endif
+#if ((716 >= GSL_INCLUDER_FIRST_CASE) && (716 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (716))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 716),
+#endif
+#endif
+#if ((717 >= GSL_INCLUDER_FIRST_CASE) && (717 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (717))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 717),
+#endif
+#endif
+#if ((718 >= GSL_INCLUDER_FIRST_CASE) && (718 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (718))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 718),
+#endif
+#endif
+#if ((719 >= GSL_INCLUDER_FIRST_CASE) && (719 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (719))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 719),
+#endif
+#endif
+#if ((720 >= GSL_INCLUDER_FIRST_CASE) && (720 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (720))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 720),
+#endif
+#endif
+#if ((721 >= GSL_INCLUDER_FIRST_CASE) && (721 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (721))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 721),
+#endif
+#endif
+#if ((722 >= GSL_INCLUDER_FIRST_CASE) && (722 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (722))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 722),
+#endif
+#endif
+#if ((723 >= GSL_INCLUDER_FIRST_CASE) && (723 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (723))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 723),
+#endif
+#endif
+#if ((724 >= GSL_INCLUDER_FIRST_CASE) && (724 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (724))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 724),
+#endif
+#endif
+#if ((725 >= GSL_INCLUDER_FIRST_CASE) && (725 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (725))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 725),
+#endif
+#endif
+#if ((726 >= GSL_INCLUDER_FIRST_CASE) && (726 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (726))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 726),
+#endif
+#endif
+#if ((727 >= GSL_INCLUDER_FIRST_CASE) && (727 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (727))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 727),
+#endif
+#endif
+#if ((728 >= GSL_INCLUDER_FIRST_CASE) && (728 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (728))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 728),
+#endif
+#endif
+#if ((729 >= GSL_INCLUDER_FIRST_CASE) && (729 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (729))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 729),
+#endif
+#endif
+#if ((730 >= GSL_INCLUDER_FIRST_CASE) && (730 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (730))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 730),
+#endif
+#endif
+#if ((731 >= GSL_INCLUDER_FIRST_CASE) && (731 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (731))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 731),
+#endif
+#endif
+#if ((732 >= GSL_INCLUDER_FIRST_CASE) && (732 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (732))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 732),
+#endif
+#endif
+#if ((733 >= GSL_INCLUDER_FIRST_CASE) && (733 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (733))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 733),
+#endif
+#endif
+#if ((734 >= GSL_INCLUDER_FIRST_CASE) && (734 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (734))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 734),
+#endif
+#endif
+#if ((735 >= GSL_INCLUDER_FIRST_CASE) && (735 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (735))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 735),
+#endif
+#endif
+#if ((736 >= GSL_INCLUDER_FIRST_CASE) && (736 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (736))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 736),
+#endif
+#endif
+#if ((737 >= GSL_INCLUDER_FIRST_CASE) && (737 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (737))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 737),
+#endif
+#endif
+#if ((738 >= GSL_INCLUDER_FIRST_CASE) && (738 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (738))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 738),
+#endif
+#endif
+#if ((739 >= GSL_INCLUDER_FIRST_CASE) && (739 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (739))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 739),
+#endif
+#endif
+#if ((740 >= GSL_INCLUDER_FIRST_CASE) && (740 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (740))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 740),
+#endif
+#endif
+#if ((741 >= GSL_INCLUDER_FIRST_CASE) && (741 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (741))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 741),
+#endif
+#endif
+#if ((742 >= GSL_INCLUDER_FIRST_CASE) && (742 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (742))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 742),
+#endif
+#endif
+#if ((743 >= GSL_INCLUDER_FIRST_CASE) && (743 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (743))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 743),
+#endif
+#endif
+#if ((744 >= GSL_INCLUDER_FIRST_CASE) && (744 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (744))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 744),
+#endif
+#endif
+#if ((745 >= GSL_INCLUDER_FIRST_CASE) && (745 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (745))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 745),
+#endif
+#endif
+#if ((746 >= GSL_INCLUDER_FIRST_CASE) && (746 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (746))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 746),
+#endif
+#endif
+#if ((747 >= GSL_INCLUDER_FIRST_CASE) && (747 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (747))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 747),
+#endif
+#endif
+#if ((748 >= GSL_INCLUDER_FIRST_CASE) && (748 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (748))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 748),
+#endif
+#endif
+#if ((749 >= GSL_INCLUDER_FIRST_CASE) && (749 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (749))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 749),
+#endif
+#endif
+#if ((750 >= GSL_INCLUDER_FIRST_CASE) && (750 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (750))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 750),
+#endif
+#endif
+#if ((751 >= GSL_INCLUDER_FIRST_CASE) && (751 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (751))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 751),
+#endif
+#endif
+#if ((752 >= GSL_INCLUDER_FIRST_CASE) && (752 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (752))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 752),
+#endif
+#endif
+#if ((753 >= GSL_INCLUDER_FIRST_CASE) && (753 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (753))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 753),
+#endif
+#endif
+#if ((754 >= GSL_INCLUDER_FIRST_CASE) && (754 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (754))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 754),
+#endif
+#endif
+#if ((755 >= GSL_INCLUDER_FIRST_CASE) && (755 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (755))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 755),
+#endif
+#endif
+#if ((756 >= GSL_INCLUDER_FIRST_CASE) && (756 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (756))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 756),
+#endif
+#endif
+#if ((757 >= GSL_INCLUDER_FIRST_CASE) && (757 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (757))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 757),
+#endif
+#endif
+#if ((758 >= GSL_INCLUDER_FIRST_CASE) && (758 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (758))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 758),
+#endif
+#endif
+#if ((759 >= GSL_INCLUDER_FIRST_CASE) && (759 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (759))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 759),
+#endif
+#endif
+#if ((760 >= GSL_INCLUDER_FIRST_CASE) && (760 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (760))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 760),
+#endif
+#endif
+#if ((761 >= GSL_INCLUDER_FIRST_CASE) && (761 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (761))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 761),
+#endif
+#endif
+#if ((762 >= GSL_INCLUDER_FIRST_CASE) && (762 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (762))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 762),
+#endif
+#endif
+#if ((763 >= GSL_INCLUDER_FIRST_CASE) && (763 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (763))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 763),
+#endif
+#endif
+#if ((764 >= GSL_INCLUDER_FIRST_CASE) && (764 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (764))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 764),
+#endif
+#endif
+#if ((765 >= GSL_INCLUDER_FIRST_CASE) && (765 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (765))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 765),
+#endif
+#endif
+#if ((766 >= GSL_INCLUDER_FIRST_CASE) && (766 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (766))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 766),
+#endif
+#endif
+#if ((767 >= GSL_INCLUDER_FIRST_CASE) && (767 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (767))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 767),
+#endif
+#endif
+#if ((768 >= GSL_INCLUDER_FIRST_CASE) && (768 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (768))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 768),
+#endif
+#endif
+#if ((769 >= GSL_INCLUDER_FIRST_CASE) && (769 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (769))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 769),
+#endif
+#endif
+#if ((770 >= GSL_INCLUDER_FIRST_CASE) && (770 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (770))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 770),
+#endif
+#endif
+#if ((771 >= GSL_INCLUDER_FIRST_CASE) && (771 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (771))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 771),
+#endif
+#endif
+#if ((772 >= GSL_INCLUDER_FIRST_CASE) && (772 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (772))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 772),
+#endif
+#endif
+#if ((773 >= GSL_INCLUDER_FIRST_CASE) && (773 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (773))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 773),
+#endif
+#endif
+#if ((774 >= GSL_INCLUDER_FIRST_CASE) && (774 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (774))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 774),
+#endif
+#endif
+#if ((775 >= GSL_INCLUDER_FIRST_CASE) && (775 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (775))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 775),
+#endif
+#endif
+#if ((776 >= GSL_INCLUDER_FIRST_CASE) && (776 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (776))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 776),
+#endif
+#endif
+#if ((777 >= GSL_INCLUDER_FIRST_CASE) && (777 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (777))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 777),
+#endif
+#endif
+#if ((778 >= GSL_INCLUDER_FIRST_CASE) && (778 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (778))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 778),
+#endif
+#endif
+#if ((779 >= GSL_INCLUDER_FIRST_CASE) && (779 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (779))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 779),
+#endif
+#endif
+#if ((780 >= GSL_INCLUDER_FIRST_CASE) && (780 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (780))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 780),
+#endif
+#endif
+#if ((781 >= GSL_INCLUDER_FIRST_CASE) && (781 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (781))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 781),
+#endif
+#endif
+#if ((782 >= GSL_INCLUDER_FIRST_CASE) && (782 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (782))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 782),
+#endif
+#endif
+#if ((783 >= GSL_INCLUDER_FIRST_CASE) && (783 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (783))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 783),
+#endif
+#endif
+#if ((784 >= GSL_INCLUDER_FIRST_CASE) && (784 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (784))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 784),
+#endif
+#endif
+#if ((785 >= GSL_INCLUDER_FIRST_CASE) && (785 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (785))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 785),
+#endif
+#endif
+#if ((786 >= GSL_INCLUDER_FIRST_CASE) && (786 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (786))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 786),
+#endif
+#endif
+#if ((787 >= GSL_INCLUDER_FIRST_CASE) && (787 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (787))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 787),
+#endif
+#endif
+#if ((788 >= GSL_INCLUDER_FIRST_CASE) && (788 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (788))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 788),
+#endif
+#endif
+#if ((789 >= GSL_INCLUDER_FIRST_CASE) && (789 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (789))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 789),
+#endif
+#endif
+#if ((790 >= GSL_INCLUDER_FIRST_CASE) && (790 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (790))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 790),
+#endif
+#endif
+#if ((791 >= GSL_INCLUDER_FIRST_CASE) && (791 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (791))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 791),
+#endif
+#endif
+#if ((792 >= GSL_INCLUDER_FIRST_CASE) && (792 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (792))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 792),
+#endif
+#endif
+#if ((793 >= GSL_INCLUDER_FIRST_CASE) && (793 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (793))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 793),
+#endif
+#endif
+#if ((794 >= GSL_INCLUDER_FIRST_CASE) && (794 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (794))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 794),
+#endif
+#endif
+#if ((795 >= GSL_INCLUDER_FIRST_CASE) && (795 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (795))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 795),
+#endif
+#endif
+#if ((796 >= GSL_INCLUDER_FIRST_CASE) && (796 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (796))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 796),
+#endif
+#endif
+#if ((797 >= GSL_INCLUDER_FIRST_CASE) && (797 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (797))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 797),
+#endif
+#endif
+#if ((798 >= GSL_INCLUDER_FIRST_CASE) && (798 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (798))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 798),
+#endif
+#endif
+#if ((799 >= GSL_INCLUDER_FIRST_CASE) && (799 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (799))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 799),
+#endif
+#endif
+#if ((800 >= GSL_INCLUDER_FIRST_CASE) && (800 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (800))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 800),
+#endif
+#endif
+#if ((801 >= GSL_INCLUDER_FIRST_CASE) && (801 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (801))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 801),
+#endif
+#endif
+#if ((802 >= GSL_INCLUDER_FIRST_CASE) && (802 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (802))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 802),
+#endif
+#endif
+#if ((803 >= GSL_INCLUDER_FIRST_CASE) && (803 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (803))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 803),
+#endif
+#endif
+#if ((804 >= GSL_INCLUDER_FIRST_CASE) && (804 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (804))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 804),
+#endif
+#endif
+#if ((805 >= GSL_INCLUDER_FIRST_CASE) && (805 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (805))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 805),
+#endif
+#endif
+#if ((806 >= GSL_INCLUDER_FIRST_CASE) && (806 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (806))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 806),
+#endif
+#endif
+#if ((807 >= GSL_INCLUDER_FIRST_CASE) && (807 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (807))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 807),
+#endif
+#endif
+#if ((808 >= GSL_INCLUDER_FIRST_CASE) && (808 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (808))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 808),
+#endif
+#endif
+#if ((809 >= GSL_INCLUDER_FIRST_CASE) && (809 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (809))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 809),
+#endif
+#endif
+#if ((810 >= GSL_INCLUDER_FIRST_CASE) && (810 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (810))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 810),
+#endif
+#endif
+#if ((811 >= GSL_INCLUDER_FIRST_CASE) && (811 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (811))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 811),
+#endif
+#endif
+#if ((812 >= GSL_INCLUDER_FIRST_CASE) && (812 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (812))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 812),
+#endif
+#endif
+#if ((813 >= GSL_INCLUDER_FIRST_CASE) && (813 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (813))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 813),
+#endif
+#endif
+#if ((814 >= GSL_INCLUDER_FIRST_CASE) && (814 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (814))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 814),
+#endif
+#endif
+#if ((815 >= GSL_INCLUDER_FIRST_CASE) && (815 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (815))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 815),
+#endif
+#endif
+#if ((816 >= GSL_INCLUDER_FIRST_CASE) && (816 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (816))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 816),
+#endif
+#endif
+#if ((817 >= GSL_INCLUDER_FIRST_CASE) && (817 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (817))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 817),
+#endif
+#endif
+#if ((818 >= GSL_INCLUDER_FIRST_CASE) && (818 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (818))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 818),
+#endif
+#endif
+#if ((819 >= GSL_INCLUDER_FIRST_CASE) && (819 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (819))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 819),
+#endif
+#endif
+#if ((820 >= GSL_INCLUDER_FIRST_CASE) && (820 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (820))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 820),
+#endif
+#endif
+#if ((821 >= GSL_INCLUDER_FIRST_CASE) && (821 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (821))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 821),
+#endif
+#endif
+#if ((822 >= GSL_INCLUDER_FIRST_CASE) && (822 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (822))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 822),
+#endif
+#endif
+#if ((823 >= GSL_INCLUDER_FIRST_CASE) && (823 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (823))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 823),
+#endif
+#endif
+#if ((824 >= GSL_INCLUDER_FIRST_CASE) && (824 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (824))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 824),
+#endif
+#endif
+#if ((825 >= GSL_INCLUDER_FIRST_CASE) && (825 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (825))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 825),
+#endif
+#endif
+#if ((826 >= GSL_INCLUDER_FIRST_CASE) && (826 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (826))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 826),
+#endif
+#endif
+#if ((827 >= GSL_INCLUDER_FIRST_CASE) && (827 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (827))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 827),
+#endif
+#endif
+#if ((828 >= GSL_INCLUDER_FIRST_CASE) && (828 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (828))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 828),
+#endif
+#endif
+#if ((829 >= GSL_INCLUDER_FIRST_CASE) && (829 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (829))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 829),
+#endif
+#endif
+#if ((830 >= GSL_INCLUDER_FIRST_CASE) && (830 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (830))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 830),
+#endif
+#endif
+#if ((831 >= GSL_INCLUDER_FIRST_CASE) && (831 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (831))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 831),
+#endif
+#endif
+#if ((832 >= GSL_INCLUDER_FIRST_CASE) && (832 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (832))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 832),
+#endif
+#endif
+#if ((833 >= GSL_INCLUDER_FIRST_CASE) && (833 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (833))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 833),
+#endif
+#endif
+#if ((834 >= GSL_INCLUDER_FIRST_CASE) && (834 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (834))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 834),
+#endif
+#endif
+#if ((835 >= GSL_INCLUDER_FIRST_CASE) && (835 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (835))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 835),
+#endif
+#endif
+#if ((836 >= GSL_INCLUDER_FIRST_CASE) && (836 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (836))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 836),
+#endif
+#endif
+#if ((837 >= GSL_INCLUDER_FIRST_CASE) && (837 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (837))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 837),
+#endif
+#endif
+#if ((838 >= GSL_INCLUDER_FIRST_CASE) && (838 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (838))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 838),
+#endif
+#endif
+#if ((839 >= GSL_INCLUDER_FIRST_CASE) && (839 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (839))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 839),
+#endif
+#endif
+#if ((840 >= GSL_INCLUDER_FIRST_CASE) && (840 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (840))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 840),
+#endif
+#endif
+#if ((841 >= GSL_INCLUDER_FIRST_CASE) && (841 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (841))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 841),
+#endif
+#endif
+#if ((842 >= GSL_INCLUDER_FIRST_CASE) && (842 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (842))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 842),
+#endif
+#endif
+#if ((843 >= GSL_INCLUDER_FIRST_CASE) && (843 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (843))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 843),
+#endif
+#endif
+#if ((844 >= GSL_INCLUDER_FIRST_CASE) && (844 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (844))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 844),
+#endif
+#endif
+#if ((845 >= GSL_INCLUDER_FIRST_CASE) && (845 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (845))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 845),
+#endif
+#endif
+#if ((846 >= GSL_INCLUDER_FIRST_CASE) && (846 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (846))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 846),
+#endif
+#endif
+#if ((847 >= GSL_INCLUDER_FIRST_CASE) && (847 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (847))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 847),
+#endif
+#endif
+#if ((848 >= GSL_INCLUDER_FIRST_CASE) && (848 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (848))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 848),
+#endif
+#endif
+#if ((849 >= GSL_INCLUDER_FIRST_CASE) && (849 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (849))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 849),
+#endif
+#endif
+#if ((850 >= GSL_INCLUDER_FIRST_CASE) && (850 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (850))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 850),
+#endif
+#endif
+#if ((851 >= GSL_INCLUDER_FIRST_CASE) && (851 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (851))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 851),
+#endif
+#endif
+#if ((852 >= GSL_INCLUDER_FIRST_CASE) && (852 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (852))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 852),
+#endif
+#endif
+#if ((853 >= GSL_INCLUDER_FIRST_CASE) && (853 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (853))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 853),
+#endif
+#endif
+#if ((854 >= GSL_INCLUDER_FIRST_CASE) && (854 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (854))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 854),
+#endif
+#endif
+#if ((855 >= GSL_INCLUDER_FIRST_CASE) && (855 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (855))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 855),
+#endif
+#endif
+#if ((856 >= GSL_INCLUDER_FIRST_CASE) && (856 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (856))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 856),
+#endif
+#endif
+#if ((857 >= GSL_INCLUDER_FIRST_CASE) && (857 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (857))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 857),
+#endif
+#endif
+#if ((858 >= GSL_INCLUDER_FIRST_CASE) && (858 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (858))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 858),
+#endif
+#endif
+#if ((859 >= GSL_INCLUDER_FIRST_CASE) && (859 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (859))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 859),
+#endif
+#endif
+#if ((860 >= GSL_INCLUDER_FIRST_CASE) && (860 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (860))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 860),
+#endif
+#endif
+#if ((861 >= GSL_INCLUDER_FIRST_CASE) && (861 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (861))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 861),
+#endif
+#endif
+#if ((862 >= GSL_INCLUDER_FIRST_CASE) && (862 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (862))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 862),
+#endif
+#endif
+#if ((863 >= GSL_INCLUDER_FIRST_CASE) && (863 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (863))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 863),
+#endif
+#endif
+#if ((864 >= GSL_INCLUDER_FIRST_CASE) && (864 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (864))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 864),
+#endif
+#endif
+#if ((865 >= GSL_INCLUDER_FIRST_CASE) && (865 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (865))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 865),
+#endif
+#endif
+#if ((866 >= GSL_INCLUDER_FIRST_CASE) && (866 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (866))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 866),
+#endif
+#endif
+#if ((867 >= GSL_INCLUDER_FIRST_CASE) && (867 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (867))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 867),
+#endif
+#endif
+#if ((868 >= GSL_INCLUDER_FIRST_CASE) && (868 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (868))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 868),
+#endif
+#endif
+#if ((869 >= GSL_INCLUDER_FIRST_CASE) && (869 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (869))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 869),
+#endif
+#endif
+#if ((870 >= GSL_INCLUDER_FIRST_CASE) && (870 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (870))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 870),
+#endif
+#endif
+#if ((871 >= GSL_INCLUDER_FIRST_CASE) && (871 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (871))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 871),
+#endif
+#endif
+#if ((872 >= GSL_INCLUDER_FIRST_CASE) && (872 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (872))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 872),
+#endif
+#endif
+#if ((873 >= GSL_INCLUDER_FIRST_CASE) && (873 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (873))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 873),
+#endif
+#endif
+#if ((874 >= GSL_INCLUDER_FIRST_CASE) && (874 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (874))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 874),
+#endif
+#endif
+#if ((875 >= GSL_INCLUDER_FIRST_CASE) && (875 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (875))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 875),
+#endif
+#endif
+#if ((876 >= GSL_INCLUDER_FIRST_CASE) && (876 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (876))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 876),
+#endif
+#endif
+#if ((877 >= GSL_INCLUDER_FIRST_CASE) && (877 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (877))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 877),
+#endif
+#endif
+#if ((878 >= GSL_INCLUDER_FIRST_CASE) && (878 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (878))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 878),
+#endif
+#endif
+#if ((879 >= GSL_INCLUDER_FIRST_CASE) && (879 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (879))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 879),
+#endif
+#endif
+#if ((880 >= GSL_INCLUDER_FIRST_CASE) && (880 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (880))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 880),
+#endif
+#endif
+#if ((881 >= GSL_INCLUDER_FIRST_CASE) && (881 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (881))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 881),
+#endif
+#endif
+#if ((882 >= GSL_INCLUDER_FIRST_CASE) && (882 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (882))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 882),
+#endif
+#endif
+#if ((883 >= GSL_INCLUDER_FIRST_CASE) && (883 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (883))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 883),
+#endif
+#endif
+#if ((884 >= GSL_INCLUDER_FIRST_CASE) && (884 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (884))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 884),
+#endif
+#endif
+#if ((885 >= GSL_INCLUDER_FIRST_CASE) && (885 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (885))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 885),
+#endif
+#endif
+#if ((886 >= GSL_INCLUDER_FIRST_CASE) && (886 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (886))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 886),
+#endif
+#endif
+#if ((887 >= GSL_INCLUDER_FIRST_CASE) && (887 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (887))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 887),
+#endif
+#endif
+#if ((888 >= GSL_INCLUDER_FIRST_CASE) && (888 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (888))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 888),
+#endif
+#endif
+#if ((889 >= GSL_INCLUDER_FIRST_CASE) && (889 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (889))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 889),
+#endif
+#endif
+#if ((890 >= GSL_INCLUDER_FIRST_CASE) && (890 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (890))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 890),
+#endif
+#endif
+#if ((891 >= GSL_INCLUDER_FIRST_CASE) && (891 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (891))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 891),
+#endif
+#endif
+#if ((892 >= GSL_INCLUDER_FIRST_CASE) && (892 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (892))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 892),
+#endif
+#endif
+#if ((893 >= GSL_INCLUDER_FIRST_CASE) && (893 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (893))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 893),
+#endif
+#endif
+#if ((894 >= GSL_INCLUDER_FIRST_CASE) && (894 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (894))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 894),
+#endif
+#endif
+#if ((895 >= GSL_INCLUDER_FIRST_CASE) && (895 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (895))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 895),
+#endif
+#endif
+#if ((896 >= GSL_INCLUDER_FIRST_CASE) && (896 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (896))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 896),
+#endif
+#endif
+#if ((897 >= GSL_INCLUDER_FIRST_CASE) && (897 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (897))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 897),
+#endif
+#endif
+#if ((898 >= GSL_INCLUDER_FIRST_CASE) && (898 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (898))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 898),
+#endif
+#endif
+#if ((899 >= GSL_INCLUDER_FIRST_CASE) && (899 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (899))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 899),
+#endif
+#endif
+#if ((900 >= GSL_INCLUDER_FIRST_CASE) && (900 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (900))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 900),
+#endif
+#endif
+#if ((901 >= GSL_INCLUDER_FIRST_CASE) && (901 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (901))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 901),
+#endif
+#endif
+#if ((902 >= GSL_INCLUDER_FIRST_CASE) && (902 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (902))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 902),
+#endif
+#endif
+#if ((903 >= GSL_INCLUDER_FIRST_CASE) && (903 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (903))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 903),
+#endif
+#endif
+#if ((904 >= GSL_INCLUDER_FIRST_CASE) && (904 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (904))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 904),
+#endif
+#endif
+#if ((905 >= GSL_INCLUDER_FIRST_CASE) && (905 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (905))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 905),
+#endif
+#endif
+#if ((906 >= GSL_INCLUDER_FIRST_CASE) && (906 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (906))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 906),
+#endif
+#endif
+#if ((907 >= GSL_INCLUDER_FIRST_CASE) && (907 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (907))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 907),
+#endif
+#endif
+#if ((908 >= GSL_INCLUDER_FIRST_CASE) && (908 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (908))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 908),
+#endif
+#endif
+#if ((909 >= GSL_INCLUDER_FIRST_CASE) && (909 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (909))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 909),
+#endif
+#endif
+#if ((910 >= GSL_INCLUDER_FIRST_CASE) && (910 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (910))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 910),
+#endif
+#endif
+#if ((911 >= GSL_INCLUDER_FIRST_CASE) && (911 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (911))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 911),
+#endif
+#endif
+#if ((912 >= GSL_INCLUDER_FIRST_CASE) && (912 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (912))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 912),
+#endif
+#endif
+#if ((913 >= GSL_INCLUDER_FIRST_CASE) && (913 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (913))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 913),
+#endif
+#endif
+#if ((914 >= GSL_INCLUDER_FIRST_CASE) && (914 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (914))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 914),
+#endif
+#endif
+#if ((915 >= GSL_INCLUDER_FIRST_CASE) && (915 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (915))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 915),
+#endif
+#endif
+#if ((916 >= GSL_INCLUDER_FIRST_CASE) && (916 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (916))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 916),
+#endif
+#endif
+#if ((917 >= GSL_INCLUDER_FIRST_CASE) && (917 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (917))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 917),
+#endif
+#endif
+#if ((918 >= GSL_INCLUDER_FIRST_CASE) && (918 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (918))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 918),
+#endif
+#endif
+#if ((919 >= GSL_INCLUDER_FIRST_CASE) && (919 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (919))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 919),
+#endif
+#endif
+#if ((920 >= GSL_INCLUDER_FIRST_CASE) && (920 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (920))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 920),
+#endif
+#endif
+#if ((921 >= GSL_INCLUDER_FIRST_CASE) && (921 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (921))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 921),
+#endif
+#endif
+#if ((922 >= GSL_INCLUDER_FIRST_CASE) && (922 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (922))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 922),
+#endif
+#endif
+#if ((923 >= GSL_INCLUDER_FIRST_CASE) && (923 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (923))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 923),
+#endif
+#endif
+#if ((924 >= GSL_INCLUDER_FIRST_CASE) && (924 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (924))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 924),
+#endif
+#endif
+#if ((925 >= GSL_INCLUDER_FIRST_CASE) && (925 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (925))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 925),
+#endif
+#endif
+#if ((926 >= GSL_INCLUDER_FIRST_CASE) && (926 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (926))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 926),
+#endif
+#endif
+#if ((927 >= GSL_INCLUDER_FIRST_CASE) && (927 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (927))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 927),
+#endif
+#endif
+#if ((928 >= GSL_INCLUDER_FIRST_CASE) && (928 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (928))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 928),
+#endif
+#endif
+#if ((929 >= GSL_INCLUDER_FIRST_CASE) && (929 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (929))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 929),
+#endif
+#endif
+#if ((930 >= GSL_INCLUDER_FIRST_CASE) && (930 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (930))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 930),
+#endif
+#endif
+#if ((931 >= GSL_INCLUDER_FIRST_CASE) && (931 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (931))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 931),
+#endif
+#endif
+#if ((932 >= GSL_INCLUDER_FIRST_CASE) && (932 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (932))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 932),
+#endif
+#endif
+#if ((933 >= GSL_INCLUDER_FIRST_CASE) && (933 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (933))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 933),
+#endif
+#endif
+#if ((934 >= GSL_INCLUDER_FIRST_CASE) && (934 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (934))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 934),
+#endif
+#endif
+#if ((935 >= GSL_INCLUDER_FIRST_CASE) && (935 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (935))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 935),
+#endif
+#endif
+#if ((936 >= GSL_INCLUDER_FIRST_CASE) && (936 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (936))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 936),
+#endif
+#endif
+#if ((937 >= GSL_INCLUDER_FIRST_CASE) && (937 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (937))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 937),
+#endif
+#endif
+#if ((938 >= GSL_INCLUDER_FIRST_CASE) && (938 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (938))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 938),
+#endif
+#endif
+#if ((939 >= GSL_INCLUDER_FIRST_CASE) && (939 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (939))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 939),
+#endif
+#endif
+#if ((940 >= GSL_INCLUDER_FIRST_CASE) && (940 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (940))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 940),
+#endif
+#endif
+#if ((941 >= GSL_INCLUDER_FIRST_CASE) && (941 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (941))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 941),
+#endif
+#endif
+#if ((942 >= GSL_INCLUDER_FIRST_CASE) && (942 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (942))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 942),
+#endif
+#endif
+#if ((943 >= GSL_INCLUDER_FIRST_CASE) && (943 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (943))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 943),
+#endif
+#endif
+#if ((944 >= GSL_INCLUDER_FIRST_CASE) && (944 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (944))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 944),
+#endif
+#endif
+#if ((945 >= GSL_INCLUDER_FIRST_CASE) && (945 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (945))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 945),
+#endif
+#endif
+#if ((946 >= GSL_INCLUDER_FIRST_CASE) && (946 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (946))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 946),
+#endif
+#endif
+#if ((947 >= GSL_INCLUDER_FIRST_CASE) && (947 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (947))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 947),
+#endif
+#endif
+#if ((948 >= GSL_INCLUDER_FIRST_CASE) && (948 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (948))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 948),
+#endif
+#endif
+#if ((949 >= GSL_INCLUDER_FIRST_CASE) && (949 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (949))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 949),
+#endif
+#endif
+#if ((950 >= GSL_INCLUDER_FIRST_CASE) && (950 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (950))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 950),
+#endif
+#endif
+#if ((951 >= GSL_INCLUDER_FIRST_CASE) && (951 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (951))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 951),
+#endif
+#endif
+#if ((952 >= GSL_INCLUDER_FIRST_CASE) && (952 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (952))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 952),
+#endif
+#endif
+#if ((953 >= GSL_INCLUDER_FIRST_CASE) && (953 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (953))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 953),
+#endif
+#endif
+#if ((954 >= GSL_INCLUDER_FIRST_CASE) && (954 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (954))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 954),
+#endif
+#endif
+#if ((955 >= GSL_INCLUDER_FIRST_CASE) && (955 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (955))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 955),
+#endif
+#endif
+#if ((956 >= GSL_INCLUDER_FIRST_CASE) && (956 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (956))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 956),
+#endif
+#endif
+#if ((957 >= GSL_INCLUDER_FIRST_CASE) && (957 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (957))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 957),
+#endif
+#endif
+#if ((958 >= GSL_INCLUDER_FIRST_CASE) && (958 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (958))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 958),
+#endif
+#endif
+#if ((959 >= GSL_INCLUDER_FIRST_CASE) && (959 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (959))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 959),
+#endif
+#endif
+#if ((960 >= GSL_INCLUDER_FIRST_CASE) && (960 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (960))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 960),
+#endif
+#endif
+#if ((961 >= GSL_INCLUDER_FIRST_CASE) && (961 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (961))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 961),
+#endif
+#endif
+#if ((962 >= GSL_INCLUDER_FIRST_CASE) && (962 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (962))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 962),
+#endif
+#endif
+#if ((963 >= GSL_INCLUDER_FIRST_CASE) && (963 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (963))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 963),
+#endif
+#endif
+#if ((964 >= GSL_INCLUDER_FIRST_CASE) && (964 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (964))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 964),
+#endif
+#endif
+#if ((965 >= GSL_INCLUDER_FIRST_CASE) && (965 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (965))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 965),
+#endif
+#endif
+#if ((966 >= GSL_INCLUDER_FIRST_CASE) && (966 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (966))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 966),
+#endif
+#endif
+#if ((967 >= GSL_INCLUDER_FIRST_CASE) && (967 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (967))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 967),
+#endif
+#endif
+#if ((968 >= GSL_INCLUDER_FIRST_CASE) && (968 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (968))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 968),
+#endif
+#endif
+#if ((969 >= GSL_INCLUDER_FIRST_CASE) && (969 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (969))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 969),
+#endif
+#endif
+#if ((970 >= GSL_INCLUDER_FIRST_CASE) && (970 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (970))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 970),
+#endif
+#endif
+#if ((971 >= GSL_INCLUDER_FIRST_CASE) && (971 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (971))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 971),
+#endif
+#endif
+#if ((972 >= GSL_INCLUDER_FIRST_CASE) && (972 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (972))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 972),
+#endif
+#endif
+#if ((973 >= GSL_INCLUDER_FIRST_CASE) && (973 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (973))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 973),
+#endif
+#endif
+#if ((974 >= GSL_INCLUDER_FIRST_CASE) && (974 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (974))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 974),
+#endif
+#endif
+#if ((975 >= GSL_INCLUDER_FIRST_CASE) && (975 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (975))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 975),
+#endif
+#endif
+#if ((976 >= GSL_INCLUDER_FIRST_CASE) && (976 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (976))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 976),
+#endif
+#endif
+#if ((977 >= GSL_INCLUDER_FIRST_CASE) && (977 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (977))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 977),
+#endif
+#endif
+#if ((978 >= GSL_INCLUDER_FIRST_CASE) && (978 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (978))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 978),
+#endif
+#endif
+#if ((979 >= GSL_INCLUDER_FIRST_CASE) && (979 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (979))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 979),
+#endif
+#endif
+#if ((980 >= GSL_INCLUDER_FIRST_CASE) && (980 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (980))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 980),
+#endif
+#endif
+#if ((981 >= GSL_INCLUDER_FIRST_CASE) && (981 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (981))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 981),
+#endif
+#endif
+#if ((982 >= GSL_INCLUDER_FIRST_CASE) && (982 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (982))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 982),
+#endif
+#endif
+#if ((983 >= GSL_INCLUDER_FIRST_CASE) && (983 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (983))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 983),
+#endif
+#endif
+#if ((984 >= GSL_INCLUDER_FIRST_CASE) && (984 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (984))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 984),
+#endif
+#endif
+#if ((985 >= GSL_INCLUDER_FIRST_CASE) && (985 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (985))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 985),
+#endif
+#endif
+#if ((986 >= GSL_INCLUDER_FIRST_CASE) && (986 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (986))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 986),
+#endif
+#endif
+#if ((987 >= GSL_INCLUDER_FIRST_CASE) && (987 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (987))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 987),
+#endif
+#endif
+#if ((988 >= GSL_INCLUDER_FIRST_CASE) && (988 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (988))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 988),
+#endif
+#endif
+#if ((989 >= GSL_INCLUDER_FIRST_CASE) && (989 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (989))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 989),
+#endif
+#endif
+#if ((990 >= GSL_INCLUDER_FIRST_CASE) && (990 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (990))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 990),
+#endif
+#endif
+#if ((991 >= GSL_INCLUDER_FIRST_CASE) && (991 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (991))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 991),
+#endif
+#endif
+#if ((992 >= GSL_INCLUDER_FIRST_CASE) && (992 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (992))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 992),
+#endif
+#endif
+#if ((993 >= GSL_INCLUDER_FIRST_CASE) && (993 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (993))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 993),
+#endif
+#endif
+#if ((994 >= GSL_INCLUDER_FIRST_CASE) && (994 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (994))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 994),
+#endif
+#endif
+#if ((995 >= GSL_INCLUDER_FIRST_CASE) && (995 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (995))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 995),
+#endif
+#endif
+#if ((996 >= GSL_INCLUDER_FIRST_CASE) && (996 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (996))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 996),
+#endif
+#endif
+#if ((997 >= GSL_INCLUDER_FIRST_CASE) && (997 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (997))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 997),
+#endif
+#endif
+#if ((998 >= GSL_INCLUDER_FIRST_CASE) && (998 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (998))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 998),
+#endif
+#endif
+#if ((999 >= GSL_INCLUDER_FIRST_CASE) && (999 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (999))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 999),
+#endif
+#endif
+#if ((1000 >= GSL_INCLUDER_FIRST_CASE) && (1000 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1000))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1000),
+#endif
+#endif
+#if ((1001 >= GSL_INCLUDER_FIRST_CASE) && (1001 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1001))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1001),
+#endif
+#endif
+#if ((1002 >= GSL_INCLUDER_FIRST_CASE) && (1002 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1002))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1002),
+#endif
+#endif
+#if ((1003 >= GSL_INCLUDER_FIRST_CASE) && (1003 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1003))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1003),
+#endif
+#endif
+#if ((1004 >= GSL_INCLUDER_FIRST_CASE) && (1004 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1004))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1004),
+#endif
+#endif
+#if ((1005 >= GSL_INCLUDER_FIRST_CASE) && (1005 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1005))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1005),
+#endif
+#endif
+#if ((1006 >= GSL_INCLUDER_FIRST_CASE) && (1006 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1006))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1006),
+#endif
+#endif
+#if ((1007 >= GSL_INCLUDER_FIRST_CASE) && (1007 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1007))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1007),
+#endif
+#endif
+#if ((1008 >= GSL_INCLUDER_FIRST_CASE) && (1008 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1008))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1008),
+#endif
+#endif
+#if ((1009 >= GSL_INCLUDER_FIRST_CASE) && (1009 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1009))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1009),
+#endif
+#endif
+#if ((1010 >= GSL_INCLUDER_FIRST_CASE) && (1010 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1010))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1010),
+#endif
+#endif
+#if ((1011 >= GSL_INCLUDER_FIRST_CASE) && (1011 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1011))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1011),
+#endif
+#endif
+#if ((1012 >= GSL_INCLUDER_FIRST_CASE) && (1012 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1012))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1012),
+#endif
+#endif
+#if ((1013 >= GSL_INCLUDER_FIRST_CASE) && (1013 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1013))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1013),
+#endif
+#endif
+#if ((1014 >= GSL_INCLUDER_FIRST_CASE) && (1014 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1014))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1014),
+#endif
+#endif
+#if ((1015 >= GSL_INCLUDER_FIRST_CASE) && (1015 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1015))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1015),
+#endif
+#endif
+#if ((1016 >= GSL_INCLUDER_FIRST_CASE) && (1016 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1016))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1016),
+#endif
+#endif
+#if ((1017 >= GSL_INCLUDER_FIRST_CASE) && (1017 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1017))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1017),
+#endif
+#endif
+#if ((1018 >= GSL_INCLUDER_FIRST_CASE) && (1018 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1018))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1018),
+#endif
+#endif
+#if ((1019 >= GSL_INCLUDER_FIRST_CASE) && (1019 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1019))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1019),
+#endif
+#endif
+#if ((1020 >= GSL_INCLUDER_FIRST_CASE) && (1020 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1020))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1020),
+#endif
+#endif
+#if ((1021 >= GSL_INCLUDER_FIRST_CASE) && (1021 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1021))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1021),
+#endif
+#endif
+#if ((1022 >= GSL_INCLUDER_FIRST_CASE) && (1022 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1022))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1022),
+#endif
+#endif
+#if ((1023 >= GSL_INCLUDER_FIRST_CASE) && (1023 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1023))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1023),
+#endif
+#endif
+#if ((1024 >= GSL_INCLUDER_FIRST_CASE) && (1024 <= GSL_INCLUDER_LAST_CASE))
+#if (GSL_INCLUDER_REJECT (1024))
+ NULL,
+#else
+ GSL_INCLUDER_MAKE_FUNC (GSL_INCLUDER_NAME, 1024),
+#endif
+#endif
+};
+
+#undef GSL_INCLUDER_REJECT
+#undef GSL_INCLUDER_FUNC
+#undef GSL_INCLUDER_CONCAT3
+#undef GSL_INCLUDER_MAKE_FUNC
+#undef GSL_INCLUDER_FIRST_CASE
+#undef GSL_INCLUDER_LAST_CASE
+#undef GSL_INCLUDER_NAME
+#undef GSL_INCLUDER_TABLE
+#undef GSL_INCLUDER_FILE
diff --git a/flow/gsl/gslloader-gslwave.c b/flow/gsl/gslloader-gslwave.c
new file mode 100644
index 0000000..e851a12
--- /dev/null
+++ b/flow/gsl/gslloader-gslwave.c
@@ -0,0 +1,701 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001, 2002 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslloader.h"
+
+#include "gsldatahandle.h"
+#include "gslmath.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+
+#define GSL_DEBUG_LOADER g_message
+
+#define parse_or_return(scanner, token) { guint _t = (token); \
+ if (g_scanner_get_next_token (scanner) != _t) \
+ return _t; \
+ }
+
+
+/* --- token types --- */
+typedef enum
+{
+ /* wave tokens */
+ GSL_WAVE_TOKEN_WAVE = 512,
+ GSL_WAVE_TOKEN_CHUNK,
+ GSL_WAVE_TOKEN_NAME,
+ GSL_WAVE_TOKEN_BYTE_ORDER,
+ GSL_WAVE_TOKEN_FORMAT,
+ GSL_WAVE_TOKEN_N_CHANNELS,
+ GSL_WAVE_TOKEN_MIX_FREQ,
+ GSL_WAVE_TOKEN_OSC_FREQ,
+ GSL_WAVE_TOKEN_MIDI_NOTE,
+ GSL_WAVE_TOKEN_FILE,
+ GSL_WAVE_TOKEN_INDEX,
+ GSL_WAVE_TOKEN_BOFFSET,
+ GSL_WAVE_TOKEN_N_VALUES,
+ GSL_WAVE_TOKEN_LOOP_TYPE,
+ GSL_WAVE_TOKEN_LOOP_START,
+ GSL_WAVE_TOKEN_LOOP_END,
+ GSL_WAVE_TOKEN_LOOP_COUNT,
+ GSL_WAVE_TOKEN_LAST_FIELD,
+ /* data tokens */
+ GSL_WAVE_TOKEN_BIG_ENDIAN = 768,
+ GSL_WAVE_TOKEN_BIG,
+ GSL_WAVE_TOKEN_LITTLE_ENDIAN,
+ GSL_WAVE_TOKEN_LITTLE,
+ GSL_WAVE_TOKEN_SIGNED_8,
+ GSL_WAVE_TOKEN_SIGNED_12,
+ GSL_WAVE_TOKEN_SIGNED_16,
+ GSL_WAVE_TOKEN_UNSIGNED_8,
+ GSL_WAVE_TOKEN_UNSIGNED_12,
+ GSL_WAVE_TOKEN_UNSIGNED_16,
+ GSL_WAVE_TOKEN_FLOAT,
+ GSL_WAVE_TOKEN_NONE,
+ GSL_WAVE_TOKEN_JUMP,
+ GSL_WAVE_TOKEN_PINGPONG,
+ GSL_WAVE_TOKEN_LAST_DATA
+} GslWaveTokenType;
+
+
+/* --- structures --- */
+typedef struct
+{
+ GslWaveFileInfo wfi;
+ gchar *cwd;
+} FileInfo;
+
+typedef struct
+{
+ GslWaveDsc wdsc;
+ GslWaveFormatType format;
+ guint byte_order;
+ gfloat dfl_mix_freq;
+} WaveDsc;
+
+
+/* --- tokens --- */
+static const char *wave_tokens_512[] = {
+ "wave", "chunk", "name", "byte_order",
+ "format", "n_channels", "mix_freq", "osc_freq",
+ "midi_note", "file", "index", "boffset",
+ "n_values", "loop_type", "loop_start", "loop_end",
+ "loop_count",
+};
+static const char *wave_tokens_768[] = {
+ "big_endian", "big", "little_endian", "little",
+ "signed_8", "signed_12", "signed_16",
+ "unsigned_8", "unsigned_12", "unsigned_16",
+ "float", "none", "jump", "pingpong",
+};
+
+
+/* --- functions --- */
+static const gchar*
+gsl_wave_token (GslWaveTokenType token)
+{
+ if (token >= 768)
+ {
+ token -= 768;
+ return token > sizeof (wave_tokens_768) / sizeof (wave_tokens_768[0]) ? NULL : wave_tokens_768[token];
+ }
+ else
+ {
+ token -= 512;
+ return token > sizeof (wave_tokens_512) / sizeof (wave_tokens_512[0]) ? NULL : wave_tokens_512[token];
+ }
+}
+
+static GTokenType
+gslwave_skip_rest_statement (GScanner *scanner,
+ guint level)
+{
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+
+ while (level)
+ {
+ g_scanner_get_next_token (scanner);
+ switch (scanner->token)
+ {
+ case G_TOKEN_EOF: case G_TOKEN_ERROR: return '}';
+ case '(': case '{': case '[': level++; break;
+ case ')': case '}': case ']': level--; break;
+ default: break;
+ }
+ }
+
+ return G_TOKEN_NONE;
+}
+
+static GslWaveFileInfo*
+gslwave_load_file_info (gpointer data,
+ const gchar *_file_name,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = NULL;
+ gboolean in_wave = FALSE, abort = FALSE;
+ GslRing *wave_names = NULL;
+ GScanner *scanner;
+ gchar *cwd, *file_name;
+ gint fd;
+ guint i;
+
+ if (g_path_is_absolute (_file_name))
+ {
+ gchar *p = strrchr (_file_name, G_DIR_SEPARATOR);
+
+ g_assert (p != NULL);
+ cwd = g_strndup (_file_name, p - _file_name + 1);
+ file_name = g_strdup (_file_name);
+ }
+ else
+ {
+ cwd = g_get_current_dir ();
+ file_name = g_strdup_printf ("%s%c%s", cwd, G_DIR_SEPARATOR, _file_name);
+ }
+
+ fd = open (file_name, O_RDONLY);
+ if (fd < 0)
+ {
+ *error_p = GSL_ERROR_OPEN_FAILED;
+ g_free (cwd);
+ g_free (file_name);
+ return NULL;
+ }
+
+ scanner = g_scanner_new (NULL);
+ scanner->config->symbol_2_token = TRUE;
+ g_scanner_scope_add_symbol (scanner, 0, "wave", GUINT_TO_POINTER (GSL_WAVE_TOKEN_WAVE));
+ g_scanner_scope_add_symbol (scanner, 0, "name", GUINT_TO_POINTER (GSL_WAVE_TOKEN_NAME));
+ g_scanner_input_file (scanner, fd);
+ while (!abort)
+ {
+ g_scanner_get_next_token (scanner);
+ switch (scanner->token)
+ {
+ case GSL_WAVE_TOKEN_WAVE:
+ if (g_scanner_peek_next_token (scanner) == '{')
+ {
+ g_scanner_get_next_token (scanner); /* eat '{' */
+ in_wave = TRUE;
+ }
+ break;
+ case '{':
+ if (gslwave_skip_rest_statement (scanner, 1) != G_TOKEN_NONE)
+ abort = TRUE;
+ break;
+ case GSL_WAVE_TOKEN_NAME:
+ if (in_wave && g_scanner_peek_next_token (scanner) == '=')
+ {
+ g_scanner_get_next_token (scanner); /* eat '=' */
+ if (g_scanner_peek_next_token (scanner) == G_TOKEN_STRING)
+ {
+ gchar *wave_name;
+
+ g_scanner_get_next_token (scanner); /* eat string */
+ wave_name = g_strdup (scanner->value.v_string);
+ if (gslwave_skip_rest_statement (scanner, 1) == G_TOKEN_NONE)
+ {
+ in_wave = FALSE;
+ wave_names = gsl_ring_append (wave_names, wave_name);
+ }
+ else
+ {
+ g_free (wave_name);
+ abort = TRUE;
+ }
+ }
+ }
+ break;
+ default:
+ if (scanner->token == G_TOKEN_EOF || scanner->token == G_TOKEN_ERROR)
+ abort = TRUE;
+ break;
+ }
+ }
+ g_scanner_destroy (scanner);
+ close (fd);
+
+ if (wave_names)
+ {
+ GslRing *ring;
+
+ fi = gsl_new_struct0 (FileInfo, 1);
+ fi->wfi.n_waves = gsl_ring_length (wave_names);
+ fi->wfi.waves = g_malloc0 (sizeof (fi->wfi.waves[0]) * fi->wfi.n_waves);
+ for (i = 0, ring = wave_names; i < fi->wfi.n_waves; i++, ring = ring->next)
+ fi->wfi.waves[i].name = ring->data;
+ gsl_ring_free (wave_names);
+ fi->cwd = cwd;
+ }
+ else
+ g_free (cwd);
+ g_free (file_name);
+
+ /* FIXME: empty wave error? */
+
+ return fi ? &fi->wfi : NULL;
+}
+
+static void
+gslwave_free_file_info (gpointer data,
+ GslWaveFileInfo *file_info)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+ guint i;
+
+ for (i = 0; i < fi->wfi.n_waves; i++)
+ g_free (fi->wfi.waves[i].name);
+ g_free (fi->wfi.waves);
+ g_free (fi->cwd);
+ gsl_delete_struct (FileInfo, fi);
+}
+
+static guint
+gslwave_parse_chunk_dsc (GScanner *scanner,
+ GslWaveChunkDsc *chunk)
+{
+ parse_or_return (scanner, '{');
+ do
+ switch (g_scanner_get_next_token (scanner))
+ {
+ case '}':
+ return G_TOKEN_NONE;
+ default:
+ return '}';
+ case GSL_WAVE_TOKEN_FILE:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_STRING);
+ g_free (chunk->loader_data1); /* file_name */
+ chunk->loader_data1 = g_strdup (scanner->value.v_string);
+ break;
+ case GSL_WAVE_TOKEN_INDEX:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_STRING);
+ g_free (chunk->loader_data2); /* wave_name */
+ chunk->loader_data2 = g_strdup (scanner->value.v_string);
+ break;
+ case GSL_WAVE_TOKEN_MIX_FREQ:
+ parse_or_return (scanner, '=');
+ switch (g_scanner_get_next_token (scanner))
+ {
+ case G_TOKEN_FLOAT: chunk->mix_freq = scanner->value.v_float; break;
+ case G_TOKEN_INT: chunk->mix_freq = scanner->value.v_int; break;
+ default: return G_TOKEN_FLOAT;
+ }
+ break;
+ case GSL_WAVE_TOKEN_OSC_FREQ:
+ parse_or_return (scanner, '=');
+ switch (g_scanner_get_next_token (scanner))
+ {
+ case G_TOKEN_FLOAT: chunk->osc_freq = scanner->value.v_float; break;
+ case G_TOKEN_INT: chunk->osc_freq = scanner->value.v_int; break;
+ default: return G_TOKEN_FLOAT;
+ }
+ break;
+ case GSL_WAVE_TOKEN_MIDI_NOTE:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ chunk->osc_freq = gsl_temp_freq (gsl_get_config ()->kammer_freq,
+ scanner->value.v_int - gsl_get_config ()->midi_kammer_note);
+ break;
+ case GSL_WAVE_TOKEN_BOFFSET:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ chunk->loader_offset = scanner->value.v_int; /* byte_offset */
+ break;
+ case GSL_WAVE_TOKEN_N_VALUES:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ chunk->loader_length = scanner->value.v_int; /* n_values */
+ break;
+ case GSL_WAVE_TOKEN_LOOP_TYPE:
+ parse_or_return (scanner, '=');
+ switch (g_scanner_get_next_token (scanner))
+ {
+ case GSL_WAVE_TOKEN_NONE: chunk->loop_type = GSL_WAVE_LOOP_NONE; break;
+ case GSL_WAVE_TOKEN_JUMP: chunk->loop_type = GSL_WAVE_LOOP_JUMP; break;
+ case GSL_WAVE_TOKEN_PINGPONG: chunk->loop_type = GSL_WAVE_LOOP_PINGPONG; break;
+ default: return GSL_WAVE_TOKEN_JUMP;
+ }
+ break;
+ case GSL_WAVE_TOKEN_LOOP_START:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ chunk->loop_start = scanner->value.v_int;
+ break;
+ case GSL_WAVE_TOKEN_LOOP_END:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ chunk->loop_end = scanner->value.v_int;
+ break;
+ case GSL_WAVE_TOKEN_LOOP_COUNT:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ chunk->loop_count = scanner->value.v_int;
+ break;
+ }
+ while (TRUE);
+}
+
+static guint
+gslwave_parse_wave_dsc (GScanner *scanner,
+ WaveDsc *dsc,
+ const gchar *wave_name)
+{
+ parse_or_return (scanner, '{');
+ do
+ switch (g_scanner_get_next_token (scanner))
+ {
+ guint i, token;
+ case '}':
+ return G_TOKEN_NONE;
+ default:
+ return '}';
+ case GSL_WAVE_TOKEN_NAME:
+ if (dsc->wdsc.name)
+ return '}';
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_STRING);
+ if (wave_name)
+ {
+ if (strcmp (wave_name, scanner->value.v_string) == 0)
+ dsc->wdsc.name = g_strdup (scanner->value.v_string);
+ else
+ return gslwave_skip_rest_statement (scanner, 1);
+ }
+ else
+ dsc->wdsc.name = g_strdup (scanner->value.v_string);
+ break;
+ case GSL_WAVE_TOKEN_CHUNK:
+ if (g_scanner_peek_next_token (scanner) != '{')
+ parse_or_return (scanner, '{');
+ i = dsc->wdsc.n_chunks++;
+ dsc->wdsc.chunks = g_realloc (dsc->wdsc.chunks, sizeof (dsc->wdsc.chunks[0]) * dsc->wdsc.n_chunks);
+ memset (dsc->wdsc.chunks + i, 0, sizeof (dsc->wdsc.chunks[0]) * 1);
+ dsc->wdsc.chunks[i].mix_freq = dsc->dfl_mix_freq;
+ dsc->wdsc.chunks[i].osc_freq = dsc->dfl_mix_freq; /* we check this later */
+ dsc->wdsc.chunks[i].loop_type = GSL_WAVE_LOOP_JUMP;
+ dsc->wdsc.chunks[i].loop_start = GSL_MAXLONG;
+ dsc->wdsc.chunks[i].loop_end = -1;
+ dsc->wdsc.chunks[i].loop_count = 1000000; /* FIXME */
+ dsc->wdsc.chunks[i].loader_offset = 0; /* offset in bytes */
+ dsc->wdsc.chunks[i].loader_length = 0; /* length in n_values */
+ dsc->wdsc.chunks[i].loader_data1 = NULL; /* file_name */
+ dsc->wdsc.chunks[i].loader_data2 = NULL; /* wave_name */
+ token = gslwave_parse_chunk_dsc (scanner, dsc->wdsc.chunks + i);
+ if (token != G_TOKEN_NONE)
+ return token;
+ if (dsc->wdsc.chunks[i].loop_end < dsc->wdsc.chunks[i].loop_start)
+ {
+ dsc->wdsc.chunks[i].loop_type = GSL_WAVE_LOOP_NONE;
+ dsc->wdsc.chunks[i].loop_start = 0;
+ dsc->wdsc.chunks[i].loop_end = 0;
+ dsc->wdsc.chunks[i].loop_count = 0;
+ }
+ if (dsc->wdsc.chunks[i].osc_freq >= dsc->wdsc.chunks[i].mix_freq / 2.)
+ g_scanner_error (scanner, "wave chunk \"%s\" mixing frequency is invalid: mix_freq=%f osc_freq=%f",
+ dsc->wdsc.chunks[i].loader_data1 ? (gchar*) dsc->wdsc.chunks[i].loader_data1 : "",
+ dsc->wdsc.chunks[i].mix_freq,
+ dsc->wdsc.chunks[i].osc_freq);
+ break;
+ case GSL_WAVE_TOKEN_BYTE_ORDER:
+ parse_or_return (scanner, '=');
+ token = g_scanner_get_next_token (scanner);
+ switch (token)
+ {
+ case GSL_WAVE_TOKEN_LITTLE_ENDIAN:
+ case GSL_WAVE_TOKEN_LITTLE: dsc->byte_order = G_LITTLE_ENDIAN; break;
+ case GSL_WAVE_TOKEN_BIG_ENDIAN:
+ case GSL_WAVE_TOKEN_BIG: dsc->byte_order = G_BIG_ENDIAN; break;
+ default: return GSL_WAVE_TOKEN_LITTLE_ENDIAN;
+ }
+ break;
+ case GSL_WAVE_TOKEN_FORMAT:
+ parse_or_return (scanner, '=');
+ token = g_scanner_get_next_token (scanner);
+ switch (token)
+ {
+ case GSL_WAVE_TOKEN_SIGNED_8: dsc->format = GSL_WAVE_FORMAT_SIGNED_8; break;
+ case GSL_WAVE_TOKEN_SIGNED_12: dsc->format = GSL_WAVE_FORMAT_SIGNED_12; break;
+ case GSL_WAVE_TOKEN_SIGNED_16: dsc->format = GSL_WAVE_FORMAT_SIGNED_16; break;
+ case GSL_WAVE_TOKEN_UNSIGNED_8: dsc->format = GSL_WAVE_FORMAT_UNSIGNED_8; break;
+ case GSL_WAVE_TOKEN_UNSIGNED_12: dsc->format = GSL_WAVE_FORMAT_UNSIGNED_12; break;
+ case GSL_WAVE_TOKEN_UNSIGNED_16: dsc->format = GSL_WAVE_FORMAT_UNSIGNED_16; break;
+ case GSL_WAVE_TOKEN_FLOAT: dsc->format = GSL_WAVE_FORMAT_FLOAT; break;
+ default: return GSL_WAVE_TOKEN_SIGNED_16;
+ }
+ break;
+ case GSL_WAVE_TOKEN_N_CHANNELS:
+ parse_or_return (scanner, '=');
+ parse_or_return (scanner, G_TOKEN_INT);
+ dsc->wdsc.n_channels = scanner->value.v_int;
+ if (dsc->wdsc.n_channels < 1)
+ return G_TOKEN_INT;
+ break;
+ case GSL_WAVE_TOKEN_MIX_FREQ:
+ parse_or_return (scanner, '=');
+ switch (g_scanner_get_next_token (scanner))
+ {
+ case G_TOKEN_FLOAT: dsc->dfl_mix_freq = scanner->value.v_float; break;
+ case G_TOKEN_INT: dsc->dfl_mix_freq = scanner->value.v_int; break;
+ default: return G_TOKEN_FLOAT;
+ }
+ break;
+ }
+ while (TRUE);
+}
+
+static void
+gslwave_wave_dsc_free (WaveDsc *dsc)
+{
+ guint i;
+
+ for (i = 0; i < dsc->wdsc.n_chunks; i++)
+ {
+ g_free (dsc->wdsc.chunks[i].loader_data1); /* file_name */
+ g_free (dsc->wdsc.chunks[i].loader_data2); /* wave_name */
+ }
+ g_free (dsc->wdsc.chunks);
+ g_free (dsc->wdsc.name);
+ gsl_delete_struct (WaveDsc, dsc);
+}
+
+static GslWaveDsc*
+gslwave_load_wave_dsc (gpointer data,
+ GslWaveFileInfo *file_info,
+ guint nth_wave,
+ GslErrorType *error_p)
+{
+ GScanner *scanner;
+ WaveDsc *dsc;
+ guint token, i;
+ gint fd;
+
+ fd = open (file_info->file_name, O_RDONLY);
+ if (fd < 0)
+ {
+ *error_p = GSL_ERROR_OPEN_FAILED;
+ return NULL;
+ }
+
+ scanner = g_scanner_new (NULL);
+ scanner->config->symbol_2_token = TRUE;
+ scanner->input_name = file_info->file_name;
+ g_scanner_input_file (scanner, fd);
+ for (i = GSL_WAVE_TOKEN_WAVE; i < GSL_WAVE_TOKEN_LAST_FIELD; i++)
+ g_scanner_scope_add_symbol (scanner, 0, gsl_wave_token (i), GUINT_TO_POINTER (i));
+ for (i = GSL_WAVE_TOKEN_BIG_ENDIAN; i < GSL_WAVE_TOKEN_LAST_DATA; i++)
+ g_scanner_scope_add_symbol (scanner, 0, gsl_wave_token (i), GUINT_TO_POINTER (i));
+
+ continue_scanning:
+ dsc = gsl_new_struct0 (WaveDsc, 1);
+ dsc->wdsc.name = NULL;
+ dsc->wdsc.n_chunks = 0;
+ dsc->wdsc.chunks = NULL;
+ dsc->wdsc.n_channels = 1;
+ dsc->format = GSL_WAVE_FORMAT_SIGNED_16;
+ dsc->byte_order = G_LITTLE_ENDIAN;
+ dsc->dfl_mix_freq = 44100;
+ if (g_scanner_get_next_token (scanner) != GSL_WAVE_TOKEN_WAVE)
+ token = GSL_WAVE_TOKEN_WAVE;
+ else
+ token = gslwave_parse_wave_dsc (scanner, dsc, file_info->waves[nth_wave].name);
+ if (token != G_TOKEN_NONE || scanner->parse_errors)
+ {
+ gslwave_wave_dsc_free (dsc);
+ dsc = NULL;
+ if (!scanner->parse_errors)
+ g_scanner_unexp_token (scanner, token, "identifier", "keyword", NULL, "discarding wave", TRUE); /* FIXME */
+ }
+ else
+ {
+ if (dsc->wdsc.n_chunks && dsc->wdsc.name)
+ {
+ /* found the correctly named wave and parsed it */
+ }
+ else
+ {
+ /* got invalid/wrong wave */
+ gslwave_wave_dsc_free (dsc);
+ dsc = NULL;
+ goto continue_scanning; /* next attempt */
+ }
+ }
+ g_scanner_destroy (scanner);
+ close (fd);
+
+ return dsc ? &dsc->wdsc : NULL;
+}
+
+static void
+gslwave_free_wave_dsc (gpointer data,
+ GslWaveDsc *wave_dsc)
+{
+ WaveDsc *dsc = (WaveDsc*) wave_dsc;
+
+ gslwave_wave_dsc_free (dsc);
+}
+
+static GslDataHandle*
+gslwave_load_singlechunk_wave (GslWaveFileInfo *fi,
+ const gchar *wave_name,
+ GslErrorType *error_p)
+{
+ GslWaveDsc *wdsc;
+ guint i;
+
+ if (fi->n_waves == 1 && !wave_name)
+ i = 0;
+ else if (!wave_name)
+ {
+ /* don't know which wave to pick */
+ *error_p = GSL_ERROR_FORMAT_INVALID;
+ return NULL;
+ }
+ else /* find named wave */
+ for (i = 0; i < fi->n_waves; i++)
+ if (strcmp (fi->waves[i].name, wave_name) == 0)
+ break;
+ if (i >= fi->n_waves)
+ {
+ *error_p = GSL_ERROR_NOT_FOUND;
+ return NULL;
+ }
+
+ wdsc = gsl_wave_dsc_load (fi, i, error_p);
+ if (!wdsc)
+ return NULL;
+
+ if (wdsc->n_chunks == 1)
+ {
+ GslDataHandle *dhandle = gsl_wave_handle_create (wdsc, 0, error_p);
+
+ gsl_wave_dsc_free (wdsc);
+ return dhandle;
+ }
+
+ /* this is ridiculous, letting the chunk of a wave
+ * point to a wave with multiple chunks...
+ */
+ gsl_wave_dsc_free (wdsc);
+ *error_p = GSL_ERROR_FORMAT_INVALID;
+ return NULL;
+}
+
+static GslDataHandle*
+gslwave_create_chunk_handle (gpointer data,
+ GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error_p)
+{
+ WaveDsc *dsc = (WaveDsc*) wave_dsc;
+ FileInfo *fi = (FileInfo*) dsc->wdsc.file_info;
+ GslWaveChunkDsc *chunk = wave_dsc->chunks + nth_chunk;
+
+ if (chunk->loader_data1) /* file_name */
+ {
+ GslDataHandle *dhandle;
+ GslWaveFileInfo *cfi;
+ gchar *string;
+
+
+ /* construct chunk file name from (hopefully) relative path
+ */
+ if (g_path_is_absolute (chunk->loader_data1))
+ string = g_strdup (chunk->loader_data1);
+ else
+ string = g_strdup_printf ("%s%c%s", fi->cwd, G_DIR_SEPARATOR, (char*) chunk->loader_data1);
+
+
+ /* first, try to load the chunk via registered loaders
+ */
+ cfi = gsl_wave_file_info_load (string, error_p);
+ if (cfi)
+ {
+ /* FIXME: there's a potential attack here, in letting a single chunk
+ * wave's chunk point to its own wave. this'll trigger recursions until
+ * stack overflow
+ */
+ dhandle = gslwave_load_singlechunk_wave (cfi,
+ chunk->loader_data2, /* wave_name */
+ error_p);
+ gsl_wave_file_info_unref (cfi);
+ g_free (string);
+ return dhandle;
+ }
+
+
+ /* didn't work, assume it's a raw sample
+ */
+ if (chunk->loader_data2) /* wave_name */
+ {
+ /* raw samples don't give names to their data */
+ *error_p = GSL_ERROR_NOT_FOUND;
+ g_free (string);
+ return NULL;
+ }
+ dhandle = gsl_wave_handle_new (string, /* file_name */
+ dsc->wdsc.n_channels,
+ dsc->format,
+ dsc->byte_order,
+ chunk->loader_offset, /* byte_offset */
+ chunk->loader_length > 0 /* n_values */
+ ? chunk->loader_length
+ : -1);
+ *error_p = dhandle ? GSL_ERROR_NONE : GSL_ERROR_IO;
+ g_free (string);
+ return dhandle;
+ }
+ else
+ {
+ /* no file_name specified */
+ *error_p = GSL_ERROR_NOT_FOUND;
+ return NULL;
+ }
+}
+
+void
+_gsl_init_loader_gslwave (void)
+{
+ static const gchar *file_exts[] = { "gslwave", NULL, };
+ static const gchar *mime_types[] = { "audio/x-gslwave", NULL, };
+ static const gchar *magics[] = { "0 string #GslWave", NULL, };
+ static GslLoader loader = {
+ "GslWave",
+ file_exts,
+ mime_types,
+ magics,
+ 0, /* priority */
+ NULL,
+ gslwave_load_file_info,
+ gslwave_free_file_info,
+ gslwave_load_wave_dsc,
+ gslwave_free_wave_dsc,
+ gslwave_create_chunk_handle,
+ };
+ static gboolean initialized = FALSE;
+
+ g_assert (initialized == FALSE);
+ initialized = TRUE;
+
+ gsl_loader_register (&loader);
+}
diff --git a/flow/gsl/gslloader-mad.c b/flow/gsl/gslloader-mad.c
new file mode 100644
index 0000000..984aa39
--- /dev/null
+++ b/flow/gsl/gslloader-mad.c
@@ -0,0 +1,210 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2002 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsl/gslloader.h"
+
+#include <gsl/gsldatahandle.h>
+#include "gsldatahandle-mad.h"
+
+#include <unistd.h>
+
+
+/* --- structures --- */
+typedef struct
+{
+ GslWaveFileInfo wfi;
+ guint n_channels;
+ gfloat mix_freq;
+ gfloat osc_freq;
+} FileInfo;
+
+
+/* --- functions --- */
+static GslWaveFileInfo*
+mad_load_file_info (gpointer data,
+ const gchar *file_name,
+ GslErrorType *error_p)
+{
+ FileInfo *fi;
+ guint n_channels;
+ gfloat mix_freq;
+ GslErrorType error;
+
+ error = gsl_data_handle_mad_testopen (file_name, &n_channels, &mix_freq);
+ if (error)
+ {
+ *error_p = error;
+ return NULL;
+ }
+
+ fi = gsl_new_struct0 (FileInfo, 1);
+ fi->wfi.n_waves = 1; /* we support only a single MPEG stream */
+ fi->wfi.waves = g_malloc0 (sizeof (fi->wfi.waves[0]) * fi->wfi.n_waves);
+ fi->wfi.waves[0].name = g_strdup (file_name);
+ fi->n_channels = n_channels;
+ fi->mix_freq = mix_freq;
+ fi->osc_freq = 440.0; /* FIXME */
+
+ return &fi->wfi;
+}
+
+static void
+mad_free_file_info (gpointer data,
+ GslWaveFileInfo *file_info)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+ guint i;
+
+ for (i = 0; i < fi->wfi.n_waves; i++)
+ g_free (fi->wfi.waves[i].name);
+ g_free (fi->wfi.waves);
+ gsl_delete_struct (FileInfo, fi);
+}
+
+static GslWaveDsc*
+mad_load_wave_dsc (gpointer data,
+ GslWaveFileInfo *file_info,
+ guint nth_wave,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+ GslWaveDsc *wdsc = gsl_new_struct0 (GslWaveDsc, 1);
+
+ wdsc->name = g_strdup (fi->wfi.waves[0].name);
+ wdsc->n_channels = fi->n_channels;
+ wdsc->n_chunks = 1;
+ wdsc->chunks = g_new0 (GslWaveChunkDsc, 1);
+ wdsc->chunks[0].osc_freq = fi->osc_freq;
+ wdsc->chunks[0].mix_freq = fi->mix_freq;
+
+ return wdsc;
+}
+
+static void
+mad_free_wave_dsc (gpointer data,
+ GslWaveDsc *wdsc)
+{
+ g_free (wdsc->name);
+ g_free (wdsc->chunks);
+ gsl_delete_struct (GslWaveDsc, wdsc);
+}
+
+static GslDataHandle*
+mad_create_chunk_handle (gpointer data,
+ GslWaveDsc *wdsc,
+ guint nth_chunk,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = (FileInfo*) wdsc->file_info;
+ GslDataHandle *dhandle;
+
+ g_return_val_if_fail (nth_chunk == 0, NULL);
+
+ dhandle = gsl_data_handle_new_mad (fi->wfi.file_name);
+
+ if (!dhandle)
+ *error_p = GSL_ERROR_OPEN_FAILED;
+ return dhandle;
+}
+
+
+#define MAGIC_MPEG_HEADER "0 beshort &0xffe0\n" /* MPEG */ \
+ "2 ubyte&0x0c <0x0c\n" /* valid samplefreq */ \
+ "2 ubyte&0xf0 <0xf0\n" /* valid bitrate */
+#define MAGIC_MPEG10_I (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x18\n" /* 1.0 */ \
+ "1 byte&0x06 =0x06\n" /* I */)
+#define MAGIC_MPEG10_II (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x18\n" /* 1.0 */ \
+ "1 byte&0x06 =0x04\n" /* II */)
+#define MAGIC_MPEG10_III (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x18\n" /* 1.0 */ \
+ "1 byte&0x06 =0x02\n" /* III */)
+#define MAGIC_MPEG20_I (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x10\n" /* 2.0 */ \
+ "1 byte&0x06 =0x06\n" /* I */)
+#define MAGIC_MPEG20_II (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x10\n" /* 2.0 */ \
+ "1 byte&0x06 =0x04\n" /* II */)
+#define MAGIC_MPEG20_III (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x10\n" /* 2.0 */ \
+ "1 byte&0x06 =0x02\n" /* III */)
+#define MAGIC_MPEG25_I (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x00\n" /* 2.5 */ \
+ "1 byte&0x06 =0x06\n" /* I */)
+#define MAGIC_MPEG25_II (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x00\n" /* 2.5 */ \
+ "1 byte&0x06 =0x04\n" /* II */)
+#define MAGIC_MPEG25_III (MAGIC_MPEG_HEADER \
+ "1 byte&0x18 =0x00\n" /* 2.5 */ \
+ "1 byte&0x06 =0x02\n" /* III */)
+#define MAGIC_RIFF_MPEG ("0 string RIFF\n" \
+ "8 string WAVE\n" \
+ "12 string fmt\\s\n" /* "fmt " */ \
+ "20 leshort 80\n" /* format: MPEG */)
+#define MAGIC_RIFF_MPEG_III ("0 string RIFF\n" \
+ "8 string WAVE\n" \
+ "12 string fmt\\s\n" /* "fmt " */ \
+ "20 leshort 85\n" /* format: MPEG III */)
+#define MAGIC_MPEG_ID3 ("0 string ID3\n" /* ID3v2 tag for mp3 */ \
+ "3 ubyte <0xff\n" /* major version */ \
+ "4 ubyte <0xff\n" /* revision */)
+
+void
+_gsl_init_loader_mad (void)
+{
+ static const gchar *file_exts[] = {
+ "mp1", "mp2", "mp3",
+ NULL,
+ };
+ static const gchar *mime_types[] = {
+ "audio/mp3", "audio/x-mp3", "audio/mpg3", "audio/x-mpg3", "audio/mpeg3", "audio/x-mpeg3",
+ "audio/mp2", "audio/x-mp2", "audio/mpg2", "audio/x-mpg2", "audio/mpeg2", "audio/x-mpeg2",
+ "audio/mp1", "audio/x-mp1", "audio/mpg1", "audio/x-mpg1", "audio/mpeg1", "audio/x-mpeg1",
+ "audio/mpeg", "audio/x-mpeg",
+ NULL,
+ };
+ static const gchar *magics[] = {
+ MAGIC_MPEG10_I, MAGIC_MPEG10_II, MAGIC_MPEG10_III,
+ MAGIC_MPEG20_I, MAGIC_MPEG20_II, MAGIC_MPEG20_III,
+ MAGIC_MPEG25_I, MAGIC_MPEG25_II, MAGIC_MPEG25_III,
+ MAGIC_RIFF_MPEG, MAGIC_RIFF_MPEG_III,
+ MAGIC_MPEG_ID3,
+ NULL,
+ };
+ static GslLoader loader = {
+ "MPEG Audio (MAD: MPEG 1.0/2.0/2.5 Layer III/II/I Decoder)",
+ file_exts,
+ mime_types,
+ magics,
+ 0, /* priority */
+ NULL,
+ mad_load_file_info,
+ mad_free_file_info,
+ mad_load_wave_dsc,
+ mad_free_wave_dsc,
+ mad_create_chunk_handle,
+ };
+ static gboolean initialized = FALSE;
+
+ g_assert (initialized == FALSE);
+ initialized = TRUE;
+
+ if (GSL_HAVE_LIBMAD)
+ gsl_loader_register (&loader);
+}
diff --git a/flow/gsl/gslloader-oggvorbis.c b/flow/gsl/gslloader-oggvorbis.c
new file mode 100644
index 0000000..3ec3d88
--- /dev/null
+++ b/flow/gsl/gslloader-oggvorbis.c
@@ -0,0 +1,178 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 1998, 2000, 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsl/gslloader.h"
+
+#if GSL_HAVE_OGGVORBIS
+#include <gsl/gsldatahandle.h>
+#include "gsldatahandle-vorbis.h"
+
+#include <vorbis/vorbisfile.h>
+#include <string.h>
+#include <unistd.h>
+
+
+/* --- structures --- */
+typedef struct
+{
+ GslWaveFileInfo wfi;
+ OggVorbis_File ofile;
+} FileInfo;
+
+
+/* --- functions --- */
+static GslWaveFileInfo*
+oggv_load_file_info (gpointer data,
+ const gchar *file_name,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = gsl_new_struct0 (FileInfo, 1);
+ FILE *file;
+ gint err, i;
+
+ file = fopen (file_name, "r");
+ if (!file)
+ {
+ *error_p = GSL_ERROR_OPEN_FAILED;
+ return NULL;
+ }
+
+ fi = gsl_new_struct0 (FileInfo, 1);
+ err = ov_open (file, &fi->ofile, NULL, 0);
+ if (err)
+ {
+ fclose (file);
+ gsl_delete_struct (FileInfo, fi);
+ *error_p = GSL_ERROR_CODEC_FAILURE;
+ return NULL;
+ }
+
+ fi->wfi.n_waves = ov_streams (&fi->ofile);
+ fi->wfi.waves = g_malloc0 (sizeof (fi->wfi.waves[0]) * fi->wfi.n_waves);
+ for (i = 0; i < fi->wfi.n_waves; i++)
+ {
+ vorbis_comment *vc = ov_comment (&fi->ofile, i);
+ guint n;
+
+ for (n = 0; n < vc->comments; n++)
+ if (strcmp (vc->user_comments[n], "title=") == 0)
+ break;
+ if (n < vc->comments)
+ fi->wfi.waves[i].name = g_strdup (vc->user_comments[n] + 6);
+ else
+ fi->wfi.waves[i].name = g_strdup_printf ("Unnamed-%u", i);
+ }
+
+ return &fi->wfi;
+}
+
+static void
+oggv_free_file_info (gpointer data,
+ GslWaveFileInfo *file_info)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+ guint i;
+
+ for (i = 0; i < fi->wfi.n_waves; i++)
+ g_free (fi->wfi.waves[i].name);
+ g_free (fi->wfi.waves);
+ ov_clear (&fi->ofile);
+ gsl_delete_struct (FileInfo, fi);
+}
+
+static GslWaveDsc*
+oggv_load_wave_dsc (gpointer data,
+ GslWaveFileInfo *file_info,
+ guint nth_wave,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+ GslWaveDsc *wdsc = gsl_new_struct0 (GslWaveDsc, 1);
+ vorbis_info *vi = ov_info (&fi->ofile, nth_wave);
+
+ wdsc->name = g_strdup (fi->wfi.waves[nth_wave].name);
+ wdsc->n_channels = vi->channels;
+ wdsc->n_chunks = 1;
+ wdsc->chunks = g_new0 (GslWaveChunkDsc, 1);
+ wdsc->chunks[0].osc_freq = 440.0; /* FIXME */
+ wdsc->chunks[0].mix_freq = vi->rate;
+ wdsc->chunks[0].loader_offset = nth_wave; /* lbitstream */
+
+ return wdsc;
+}
+
+static void
+oggv_free_wave_dsc (gpointer data,
+ GslWaveDsc *wdsc)
+{
+ g_free (wdsc->name);
+ g_free (wdsc->chunks);
+ gsl_delete_struct (GslWaveDsc, wdsc);
+}
+
+static GslDataHandle*
+oggv_create_chunk_handle (gpointer data,
+ GslWaveDsc *wdsc,
+ guint nth_chunk,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = (FileInfo*) wdsc->file_info;
+ GslDataHandle *dhandle;
+
+ g_return_val_if_fail (nth_chunk == 0, NULL);
+
+ dhandle = gsl_data_handle_new_ogg_vorbis (fi->wfi.file_name,
+ wdsc->chunks[0].loader_offset); /* lbitstream */
+ if (!dhandle)
+ *error_p = GSL_ERROR_OPEN_FAILED;
+ return dhandle;
+}
+
+void
+_gsl_init_loader_oggvorbis (void)
+{
+ static const gchar *file_exts[] = { "ogg", NULL, };
+ static const gchar *mime_types[] = { "application/x-ogg", "audio/x-vorbis", "audio/x-ogg", NULL, };
+ static const gchar *magics[] = { "0 string OggS\n" "29 string vorbis", NULL, };
+ static GslLoader loader = {
+ "Ogg/Vorbis",
+ file_exts,
+ mime_types,
+ magics,
+ 0, /* priority */
+ NULL,
+ oggv_load_file_info,
+ oggv_free_file_info,
+ oggv_load_wave_dsc,
+ oggv_free_wave_dsc,
+ oggv_create_chunk_handle,
+ };
+ static gboolean initialized = FALSE;
+
+ g_assert (initialized == FALSE);
+ initialized = TRUE;
+
+ gsl_loader_register (&loader);
+}
+#else
+void
+_gsl_init_loader_oggvorbis (void)
+{
+ /* dummy */
+}
+#endif /* GSL_HAVE_OGGVORBIS */
diff --git a/flow/gsl/gslloader-wav.c b/flow/gsl/gslloader-wav.c
new file mode 100644
index 0000000..d0a1c1e
--- /dev/null
+++ b/flow/gsl/gslloader-wav.c
@@ -0,0 +1,442 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 1998, 2000, 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslloader.h"
+
+#include "gsldatahandle.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+
+/* load routine for the RIFF/WAVE sample format
+ * ref.: C't 01/1993 pp. 213
+ */
+
+typedef guint32 DWord;
+typedef guint16 Word;
+#define DWORD_FROM_BE GUINT32_FROM_BE
+#define DWORD_FROM_LE GUINT32_FROM_LE
+#define WORD_FROM_LE GUINT16_FROM_LE
+
+
+/* --- debugging and errors --- */
+#define WAV_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_DATA_HANDLE, "WAV")
+#define WAV_MSG GSL_MESSAGE_FUNCTION (GSL_MSG_DATA_HANDLE, "WAV")
+
+
+/* --- functions --- */
+typedef struct
+{
+ DWord main_chunk; /* 'RIFF', big endian as int */
+ DWord file_length; /* file length */
+ DWord chunk_type; /* 'WAVE', big endian as int */
+} WavHeader;
+static GslErrorType
+wav_read_header (gint fd,
+ WavHeader *header)
+{
+ guint n_bytes;
+
+ memset (header, 0, sizeof (*header));
+
+ /* read header contents */
+ n_bytes = 4 + 4 + 4;
+ g_assert (n_bytes == sizeof (*header));
+ if (read (fd, header, n_bytes) != n_bytes)
+ {
+ WAV_DEBUG ("failed to read WavHeader");
+ return GSL_ERROR_IO;
+ }
+
+ /* endianess corrections */
+ header->main_chunk = DWORD_FROM_BE (header->main_chunk);
+ header->file_length = DWORD_FROM_LE (header->file_length);
+ header->chunk_type = DWORD_FROM_BE (header->chunk_type);
+
+ /* validation */
+ if (header->main_chunk != ('R' << 24 | 'I' << 16 | 'F' << 8 | 'F'))
+ {
+ WAV_DEBUG ("unmatched token 'RIFF'");
+ return GSL_ERROR_FORMAT_INVALID;
+ }
+ if (header->file_length < 40)
+ {
+ WAV_DEBUG ("file length (%u) too small", header->file_length);
+ return GSL_ERROR_FORMAT_INVALID;
+ }
+ if (header->chunk_type != ('W' << 24 | 'A' << 16 | 'V' << 8 | 'E'))
+ {
+ WAV_DEBUG ("unmatched token 'WAVE'");
+ return GSL_ERROR_FORMAT_INVALID;
+ }
+
+ return GSL_ERROR_NONE;
+}
+
+typedef struct
+{
+ DWord sub_chunk; /* 'fmt ', big endian as int */
+ DWord length; /* sub chunk length, must be 16 */
+ Word format; /* 1 for PCM */
+ Word n_channels; /* 1 = Mono, 2 = Stereo */
+ DWord sample_freq;
+ DWord byte_per_second;
+ Word byte_per_sample; /* 1 = 8bit, 2 = 16bit */
+ Word bit_per_sample; /* 8, 12 or 16 */
+} FmtHeader;
+static GslErrorType
+wav_read_fmt_header (gint fd,
+ FmtHeader *header)
+{
+ guint n_bytes;
+
+ memset (header, 0, sizeof (*header));
+
+ /* read header contents */
+ n_bytes = 4 + 4 + 2 + 2 + 4 + 4 + 2 + 2;
+ g_assert (n_bytes == sizeof (*header));
+ if (read (fd, header, n_bytes) != n_bytes)
+ {
+ WAV_DEBUG ("failed to read FmtHeader");
+ return GSL_ERROR_IO;
+ }
+
+ /* endianess corrections */
+ header->sub_chunk = DWORD_FROM_BE (header->sub_chunk);
+ header->length = DWORD_FROM_LE (header->length);
+ header->format = WORD_FROM_LE (header->format);
+ header->n_channels = WORD_FROM_LE (header->n_channels);
+ header->sample_freq = DWORD_FROM_LE (header->sample_freq);
+ header->byte_per_second = DWORD_FROM_LE (header->byte_per_second);
+ header->byte_per_sample = WORD_FROM_LE (header->byte_per_sample);
+ header->bit_per_sample = WORD_FROM_LE (header->bit_per_sample);
+
+ /* validation */
+ if (header->sub_chunk != ('f' << 24 | 'm' << 16 | 't' << 8 | ' '))
+ {
+ WAV_DEBUG ("unmatched token 'fmt '");
+ return GSL_ERROR_FORMAT_UNKNOWN;
+ }
+ if (header->format != 1 /* PCM */ ||
+ header->n_channels > 2 || header->n_channels < 1)
+ {
+ WAV_DEBUG ("invalid format (%u) or n_channels (%u)", header->format, header->n_channels);
+ return GSL_ERROR_FORMAT_UNKNOWN;
+ }
+ if (header->length < 16)
+ {
+ WAV_DEBUG ("WAVE header too short (%u)", header->length);
+ return GSL_ERROR_FORMAT_INVALID;
+ }
+ if (header->sample_freq < 1378 || header->sample_freq > 96000)
+ {
+ WAV_DEBUG ("invalid sample_freq (%u)", header->sample_freq);
+ return GSL_ERROR_FORMAT_UNKNOWN;
+ }
+ if (header->byte_per_sample < 1 || header->byte_per_sample > 4 ||
+ (header->bit_per_sample != 8 && header->bit_per_sample != 12 && header->bit_per_sample != 16))
+ {
+ WAV_DEBUG ("invalid byte_per_sample (%u) or bit_per_sample (%u)", header->byte_per_sample, header->bit_per_sample);
+ return GSL_ERROR_FORMAT_UNKNOWN;
+ }
+ if (header->byte_per_second != header->sample_freq * header->byte_per_sample ||
+ header->byte_per_sample != (header->bit_per_sample + 7) / 8 * header->n_channels)
+ {
+ WAV_DEBUG ("invalid byte_per_second (%u!=%u) or byte_per_sample (%u!=%u)",
+ header->byte_per_second, header->sample_freq * header->byte_per_sample,
+ header->byte_per_sample, (header->bit_per_sample + 7) / 8 * header->n_channels);
+ return GSL_ERROR_FORMAT_INVALID;
+ }
+ if (header->length > 16)
+ {
+ guint n;
+
+ WAV_DEBUG ("WAVE header too long (%u)", header->length);
+
+ n = header->length - 16;
+ while (n)
+ {
+ guint8 junk[64];
+ guint l = MIN (n, 64);
+
+ l = read (fd, junk, l);
+ if (l < 1 || l > n)
+ {
+ WAV_DEBUG ("failed to read FmtHeader");
+ return GSL_ERROR_IO;
+ }
+ n -= l;
+ }
+
+ WAV_MSG (GSL_ERROR_CONTENT_GLITCH, "skipping %u bytes of junk in WAVE header", header->length - 16);
+ }
+
+ return GSL_ERROR_NONE;
+}
+
+typedef struct
+{
+ DWord data_chunk; /* 'data', big endian as int */
+ DWord data_length;
+} DataHeader;
+static GslErrorType
+wav_read_data_header (gint fd,
+ DataHeader *header,
+ guint byte_alignment)
+{
+ guint n_bytes;
+
+ memset (header, 0, sizeof (*header));
+
+ /* read header contents */
+ n_bytes = 4 + 4;
+ g_assert (n_bytes == sizeof (*header));
+ if (read (fd, header, n_bytes) != n_bytes)
+ {
+ WAV_DEBUG ("failed to read DataHeader");
+ return GSL_ERROR_IO;
+ }
+
+ /* endianess corrections */
+ header->data_chunk = DWORD_FROM_BE (header->data_chunk);
+ header->data_length = DWORD_FROM_LE (header->data_length);
+
+ /* validation */
+ if (header->data_chunk != ('d' << 24 | 'a' << 16 | 't' << 8 | 'a'))
+ {
+ guchar chunk[5];
+ gchar *esc;
+
+ chunk[0] = header->data_chunk >> 24;
+ chunk[1] = (header->data_chunk >> 16) & 0xff;
+ chunk[2] = (header->data_chunk >> 8) & 0xff;
+ chunk[3] = header->data_chunk & 0xff;
+ chunk[4] = 0;
+ esc = g_strescape (chunk, NULL);
+
+ /* skip chunk and retry */
+ WAV_DEBUG ("ignoring sub-chunk '%s'", esc);
+ g_free (esc);
+ if (lseek (fd, header->data_length, SEEK_CUR) < 0)
+ {
+ WAV_DEBUG ("failed to seek while skipping sub-chunk");
+ return GSL_ERROR_IO;
+ }
+ return wav_read_data_header (fd, header, byte_alignment);
+ }
+ if (header->data_length < 1 || header->data_length % byte_alignment != 0)
+ {
+ WAV_DEBUG ("invalid data length (%u) or alignment (%u)",
+ header->data_length, header->data_length % byte_alignment);
+ return GSL_ERROR_FORMAT_INVALID;
+ }
+
+ return GSL_ERROR_NONE;
+}
+
+typedef struct
+{
+ GslWaveFileInfo wfi;
+ gint fd;
+} FileInfo;
+
+static GslWaveFileInfo*
+wav_load_file_info (gpointer data,
+ const gchar *file_name,
+ GslErrorType *error_p)
+{
+ WavHeader wav_header;
+ FileInfo *fi;
+ gint fd;
+
+ fd = open (file_name, O_RDONLY);
+ if (fd < 0)
+ {
+ *error_p = GSL_ERROR_OPEN_FAILED;
+ return NULL;
+ }
+
+ *error_p = wav_read_header (fd, &wav_header);
+ if (*error_p)
+ {
+ close (fd);
+ return NULL;
+ }
+
+ fi = gsl_new_struct0 (FileInfo, 1);
+ fi->wfi.n_waves = 1;
+ fi->wfi.waves = g_malloc0 (sizeof (fi->wfi.waves[0]) * fi->wfi.n_waves);
+ fi->wfi.waves[0].name = g_strdup (file_name);
+ fi->fd = fd;
+
+ return &fi->wfi;
+}
+
+static void
+wav_free_file_info (gpointer data,
+ GslWaveFileInfo *file_info)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+
+ g_free (fi->wfi.waves[0].name);
+ g_free (fi->wfi.waves);
+ close (fi->fd);
+ gsl_delete_struct (FileInfo, fi);
+}
+
+typedef struct
+{
+ GslWaveDsc wdsc;
+ GslLong data_offset;
+ GslLong n_values;
+ GslWaveFormatType format;
+} WaveDsc;
+
+static GslWaveDsc*
+wav_load_wave_dsc (gpointer data,
+ GslWaveFileInfo *file_info,
+ guint nth_wave,
+ GslErrorType *error_p)
+{
+ FileInfo *fi = (FileInfo*) file_info;
+ DataHeader data_header;
+ FmtHeader fmt_header;
+ WaveDsc *dsc;
+ GslWaveFormatType format;
+ GslLong data_offset, data_width;
+
+ g_return_val_if_fail (nth_wave == 0, NULL);
+
+ if (lseek (fi->fd, sizeof (WavHeader), SEEK_SET) != sizeof (WavHeader))
+ {
+ WAV_DEBUG ("failed to seek to end of WavHeader");
+ *error_p = GSL_ERROR_IO;
+ return NULL;
+ }
+
+ *error_p = wav_read_fmt_header (fi->fd, &fmt_header);
+ if (*error_p)
+ return NULL;
+
+ data_width = (fmt_header.bit_per_sample + 7) / 8;
+ *error_p = wav_read_data_header (fi->fd, &data_header, data_width * fmt_header.n_channels);
+ data_offset = lseek (fi->fd, 0, SEEK_CUR);
+ if (data_offset < sizeof (WavHeader) && !*error_p)
+ {
+ WAV_DEBUG ("failed to seek to start of data");
+ *error_p = GSL_ERROR_IO;
+ }
+ if (*error_p)
+ return NULL;
+
+ switch (fmt_header.bit_per_sample)
+ {
+ case 8: format = GSL_WAVE_FORMAT_UNSIGNED_8; break;
+ case 12: format = GSL_WAVE_FORMAT_SIGNED_12; break;
+ case 16: format = GSL_WAVE_FORMAT_SIGNED_16; break;
+ default:
+ WAV_DEBUG ("unrecognized sample width (%u)", fmt_header.bit_per_sample);
+ *error_p = GSL_ERROR_FORMAT_UNKNOWN;
+ return NULL;
+ }
+ if (0)
+ WAV_DEBUG ("n_channels: %d sample_freq: %d bit_width: %u",
+ fmt_header.n_channels, fmt_header.sample_freq, fmt_header.bit_per_sample);
+
+ dsc = gsl_new_struct0 (WaveDsc, 1);
+ dsc->wdsc.name = g_strdup (fi->wfi.waves[0].name);
+ dsc->wdsc.n_channels = fmt_header.n_channels;
+ dsc->wdsc.n_chunks = 1;
+ dsc->wdsc.chunks = g_malloc0 (sizeof (dsc->wdsc.chunks[0]) * dsc->wdsc.n_chunks);
+ dsc->wdsc.chunks[0].mix_freq = fmt_header.sample_freq;
+ dsc->wdsc.chunks[0].osc_freq = 440.0; /* FIXME */
+ dsc->data_offset = data_offset;
+ dsc->n_values = data_header.data_length / data_width;
+ dsc->format = format;
+
+ return &dsc->wdsc;
+}
+
+static void
+wav_free_wave_dsc (gpointer data,
+ GslWaveDsc *wave_dsc)
+{
+ WaveDsc *dsc = (WaveDsc*) wave_dsc;
+
+ g_free (dsc->wdsc.name);
+ g_free (dsc->wdsc.chunks);
+ gsl_delete_struct (WaveDsc, dsc);
+}
+
+static GslDataHandle*
+wav_create_chunk_handle (gpointer data,
+ GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error_p)
+{
+ WaveDsc *dsc = (WaveDsc*) wave_dsc;
+ GslDataHandle *dhandle;
+
+ g_return_val_if_fail (nth_chunk == 0, NULL);
+
+ dhandle = gsl_wave_handle_new (dsc->wdsc.file_info->file_name,
+ dsc->wdsc.n_channels,
+ dsc->format, G_LITTLE_ENDIAN,
+ dsc->data_offset, dsc->n_values);
+ return dhandle;
+}
+
+void
+_gsl_init_loader_wav (void)
+{
+ static const gchar *file_exts[] = { "wav", NULL, };
+ static const gchar *mime_types[] = { "audio/wav", "audio/x-wav", NULL, };
+ static const gchar *magics[] = {
+ (
+ "0 string RIFF\n"
+ "8 string WAVE\n"
+ "12 string fmt\\s\n" /* expect "fmt " */
+ "16 lelong >15\n" /* expect valid sub chunk length */
+ "20 leshort =1\n" /* expect PCM format */
+ ),
+ NULL,
+ };
+ static GslLoader loader = {
+ "RIFF, WAVE audio, PCM",
+ file_exts,
+ mime_types,
+ magics,
+ 0, /* priority */
+ NULL,
+ wav_load_file_info,
+ wav_free_file_info,
+ wav_load_wave_dsc,
+ wav_free_wave_dsc,
+ wav_create_chunk_handle,
+ };
+ static gboolean initialized = FALSE;
+
+ g_assert (initialized == FALSE);
+ initialized = TRUE;
+
+ gsl_loader_register (&loader);
+}
diff --git a/flow/gsl/gslloader.c b/flow/gsl/gslloader.c
new file mode 100644
index 0000000..002e39f
--- /dev/null
+++ b/flow/gsl/gslloader.c
@@ -0,0 +1,335 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslloader.h"
+
+#include "gslcommon.h"
+#include "gsldatahandle.h"
+#include "gslmagic.h"
+#include <string.h>
+
+
+/* --- variables --- */
+static GslLoader *gsl_loader_list = NULL;
+static GslRing *gsl_magic_list = NULL;
+
+
+/* --- functions --- */
+static GslLoader*
+loader_find_by_name (const gchar *name)
+{
+ GslLoader *loader;
+
+ for (loader = gsl_loader_list; loader != NULL; loader = loader->next)
+ if (strcmp (name, loader->name) == 0)
+ return loader;
+ return NULL;
+}
+
+void
+gsl_loader_register (GslLoader *loader)
+{
+ g_return_if_fail (loader != NULL);
+ g_return_if_fail (loader->name != NULL);
+ g_return_if_fail (loader->extensions || loader->mime_types || loader->magic_specs);
+ g_return_if_fail (loader_find_by_name (loader->name) == NULL);
+ g_return_if_fail (loader->next == NULL);
+ g_return_if_fail (loader->load_file_info != NULL);
+ g_return_if_fail (loader->free_file_info != NULL);
+ g_return_if_fail (loader->load_wave_dsc != NULL);
+ g_return_if_fail (loader->free_wave_dsc != NULL);
+ g_return_if_fail (loader->create_chunk_handle != NULL);
+
+ loader->next = gsl_loader_list;
+ gsl_loader_list = loader;
+
+ if (loader->magic_specs)
+ {
+ GslMagic *magic;
+ guint i, j;
+
+ for (i = 0; loader->magic_specs[i]; i++)
+ {
+ if (loader->extensions)
+ for (j = 0; loader->extensions[j]; j++)
+ {
+ magic = gsl_magic_create (loader, loader->priority,
+ loader->extensions[j], loader->magic_specs[i]);
+ gsl_magic_list = gsl_ring_append (gsl_magic_list, magic);
+ }
+ else
+ {
+ magic = gsl_magic_create (loader, loader->priority,
+ NULL, loader->magic_specs[i]);
+ gsl_magic_list = gsl_ring_append (gsl_magic_list, magic);
+ }
+ }
+ }
+}
+
+GslLoader*
+gsl_loader_match (const gchar *file_name)
+{
+ GslMagic *magic;
+
+ g_return_val_if_fail (file_name != NULL, NULL);
+
+ magic = gsl_magic_list_match_file (gsl_magic_list, file_name);
+ if (magic)
+ return magic->data;
+
+ return NULL;
+}
+
+GslWaveFileInfo*
+gsl_wave_file_info_load (const gchar *file_name,
+ GslErrorType *error_p)
+{
+ GslWaveFileInfo *finfo = NULL;
+ GslErrorType error = GSL_ERROR_NONE;
+ GslLoader *loader;
+
+ if (error_p)
+ *error_p = GSL_ERROR_INTERNAL;
+ g_return_val_if_fail (file_name != NULL, NULL);
+
+ loader = gsl_loader_match (file_name);
+ if (loader)
+ {
+ finfo = loader->load_file_info (loader->data, file_name, &error);
+ if (error && finfo)
+ {
+ /* loaders shouldn't do this */
+ loader->free_file_info (loader->data, finfo);
+ finfo = NULL;
+ }
+ if (!finfo && !error)
+ error = GSL_ERROR_FILE_EMPTY; /* FIXME: try next loader */
+ if (finfo)
+ {
+ if (finfo->n_waves > 0)
+ {
+ guint i;
+
+ g_return_val_if_fail (finfo->loader == NULL, NULL);
+ g_return_val_if_fail (finfo->file_name == NULL, NULL);
+
+ for (i = 0; i < finfo->n_waves; i++)
+ g_return_val_if_fail (finfo->waves[i].name != NULL, NULL);
+
+ finfo->file_name = g_strdup (file_name);
+ finfo->loader = loader;
+ finfo->ref_count = 1;
+ }
+ else
+ {
+ loader->free_file_info (loader->data, finfo);
+ finfo = NULL;
+ error = GSL_ERROR_FILE_EMPTY; /* FIXME: try next loader */
+ }
+ }
+ }
+ else /* no loader match */
+ {
+ /* try to provide appropriate error code */
+ error = gsl_check_file (file_name, "rf");
+ if (!error)
+ error = GSL_ERROR_FORMAT_UNKNOWN;
+ }
+
+ if (error_p)
+ *error_p = error;
+
+ return finfo;
+}
+
+void
+gsl_wave_file_info_unref (GslWaveFileInfo *wave_file_info)
+{
+ g_return_if_fail (wave_file_info != NULL);
+ g_return_if_fail (wave_file_info->ref_count > 0);
+
+ wave_file_info->ref_count--;
+ if (!wave_file_info->ref_count)
+ {
+ GslLoader *loader = wave_file_info->loader;
+
+ g_free (wave_file_info->file_name);
+ wave_file_info->file_name = NULL;
+ wave_file_info->loader = NULL;
+
+ loader->free_file_info (loader->data, wave_file_info);
+ }
+}
+
+GslWaveFileInfo*
+gsl_wave_file_info_ref (GslWaveFileInfo *wave_file_info)
+{
+ g_return_val_if_fail (wave_file_info != NULL, NULL);
+ g_return_val_if_fail (wave_file_info->ref_count > 0, NULL);
+
+ wave_file_info->ref_count++;
+
+ return wave_file_info;
+}
+
+GslWaveDsc*
+gsl_wave_dsc_load (GslWaveFileInfo *wave_file_info,
+ guint nth_wave,
+ GslErrorType *error_p)
+{
+ GslErrorType error = GSL_ERROR_NONE;
+ GslWaveDsc *wdsc;
+ GslLoader *loader;
+
+ if (error_p)
+ *error_p = GSL_ERROR_INTERNAL;
+ g_return_val_if_fail (wave_file_info != NULL, NULL);
+ g_return_val_if_fail (wave_file_info->loader != NULL, NULL);
+ g_return_val_if_fail (nth_wave < wave_file_info->n_waves, NULL);
+
+ loader = wave_file_info->loader;
+ wdsc = loader->load_wave_dsc (loader->data, wave_file_info, nth_wave,&error);
+
+ if (error && wdsc)
+ {
+ /* loaders shouldn't do this */
+ loader->free_wave_dsc (loader->data, wdsc);
+ wdsc = NULL;
+ }
+ if (!wdsc && !error)
+ error = GSL_ERROR_FILE_EMPTY;
+ if (wdsc)
+ {
+ if (wdsc->n_chunks > 0)
+ {
+ g_return_val_if_fail (wdsc->file_info == NULL, NULL);
+ g_return_val_if_fail (wdsc->name && strcmp (wdsc->name, wave_file_info->waves[nth_wave].name) == 0, NULL);
+
+ wdsc->file_info = wave_file_info;
+ gsl_wave_file_info_ref (wave_file_info);
+ }
+ else
+ {
+ loader->free_wave_dsc (loader->data, wdsc);
+ wdsc = NULL;
+ error = GSL_ERROR_FILE_EMPTY;
+ }
+ }
+
+ if (error_p)
+ *error_p = error;
+
+ return wdsc;
+}
+
+void
+gsl_wave_dsc_free (GslWaveDsc *wave_dsc)
+{
+ GslWaveFileInfo *file_info;
+
+ g_return_if_fail (wave_dsc != NULL);
+ g_return_if_fail (wave_dsc->file_info != NULL);
+
+ file_info = wave_dsc->file_info;
+ wave_dsc->file_info = NULL;
+
+ file_info->loader->free_wave_dsc (file_info->loader->data, wave_dsc);
+
+ gsl_wave_file_info_unref (file_info);
+}
+
+GslDataHandle*
+gsl_wave_handle_create (GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error_p)
+{
+ GslErrorType error = GSL_ERROR_NONE;
+ GslDataHandle *dhandle;
+ GslLoader *loader;
+
+ if (error_p)
+ *error_p = GSL_ERROR_INTERNAL;
+ g_return_val_if_fail (wave_dsc != NULL, NULL);
+ g_return_val_if_fail (wave_dsc->file_info != NULL, NULL);
+ g_return_val_if_fail (nth_chunk < wave_dsc->n_chunks, NULL);
+
+ loader = wave_dsc->file_info->loader;
+
+ dhandle = loader->create_chunk_handle (loader->data,
+ wave_dsc,
+ nth_chunk,
+ &error);
+ if (error && dhandle)
+ {
+ /* loaders shouldn't do this */
+ gsl_data_handle_unref (dhandle);
+ dhandle = NULL;
+ }
+ if (!dhandle && !error)
+ error = GSL_ERROR_FORMAT_INVALID;
+
+ if (error_p)
+ *error_p = error;
+
+ return dhandle;
+}
+
+GslWaveChunk*
+gsl_wave_chunk_create (GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error_p)
+{
+ GslDataHandle *dhandle;
+ GslDataCache *dcache;
+ GslWaveChunk *wchunk;
+
+ if (error_p)
+ *error_p = GSL_ERROR_INTERNAL;
+ g_return_val_if_fail (wave_dsc != NULL, NULL);
+ g_return_val_if_fail (nth_chunk < wave_dsc->n_chunks, NULL);
+
+ dhandle = gsl_wave_handle_create (wave_dsc, nth_chunk, error_p);
+ if (!dhandle)
+ return NULL;
+
+ if (error_p)
+ *error_p = GSL_ERROR_IO;
+
+ /* FIXME: we essentially create a dcache for each wchunk here ;( */
+
+ dcache = gsl_data_cache_from_dhandle (dhandle, gsl_get_config ()->wave_chunk_padding * wave_dsc->n_channels);
+ gsl_data_handle_unref (dhandle);
+ if (!dcache)
+ return NULL;
+ /* dcache keeps dhandle alive */
+
+ wchunk = gsl_wave_chunk_new (dcache,
+ wave_dsc->chunks[nth_chunk].osc_freq,
+ wave_dsc->chunks[nth_chunk].mix_freq,
+ wave_dsc->chunks[nth_chunk].loop_type,
+ wave_dsc->chunks[nth_chunk].loop_start,
+ wave_dsc->chunks[nth_chunk].loop_end,
+ wave_dsc->chunks[nth_chunk].loop_count);
+ gsl_data_cache_unref (dcache);
+
+ if (error_p && wchunk)
+ *error_p = GSL_ERROR_NONE;
+
+ return wchunk;
+}
diff --git a/flow/gsl/gslloader.h b/flow/gsl/gslloader.h
new file mode 100644
index 0000000..e4b391c
--- /dev/null
+++ b/flow/gsl/gslloader.h
@@ -0,0 +1,136 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_LOADER_H__
+#define __GSL_LOADER_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gslcommon.h>
+#include <gsl/gslwavechunk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+typedef struct _GslWaveFileInfo GslWaveFileInfo;
+typedef struct _GslWaveDsc GslWaveDsc;
+typedef struct _GslWaveChunkDsc GslWaveChunkDsc;
+
+/* --- structures --- */
+struct _GslWaveFileInfo
+{
+ guint n_waves;
+ struct {
+ gchar *name;
+ } *waves;
+
+ /*< private >*/
+ gchar *file_name;
+ GslLoader *loader;
+ guint ref_count;
+};
+struct _GslWaveDsc
+{
+ gchar *name;
+ guint n_chunks;
+ GslWaveChunkDsc *chunks;
+ guint n_channels;
+ /*< private >*/
+ GslWaveFileInfo *file_info;
+};
+struct _GslWaveChunkDsc
+{
+ gfloat osc_freq;
+ gfloat mix_freq;
+ GslWaveLoopType loop_type;
+ GslLong loop_start; /* sample offset */
+ GslLong loop_end; /* sample offset */
+ guint loop_count;
+ /* loader-specific */
+ GslLong loader_offset;
+ GslLong loader_length;
+ gpointer loader_data1; /* generic pointers for more data */
+ gpointer loader_data2;
+};
+
+
+/* --- functions --- */
+GslWaveFileInfo* gsl_wave_file_info_load (const gchar *file_name,
+ GslErrorType *error);
+GslWaveFileInfo* gsl_wave_file_info_ref (GslWaveFileInfo *wave_file_info);
+void gsl_wave_file_info_unref (GslWaveFileInfo *wave_file_info);
+GslWaveDsc* gsl_wave_dsc_load (GslWaveFileInfo *wave_file_info,
+ guint nth_wave,
+ GslErrorType *error);
+void gsl_wave_dsc_free (GslWaveDsc *wave_dsc);
+GslDataHandle* gsl_wave_handle_create (GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error);
+GslWaveChunk* gsl_wave_chunk_create (GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error);
+
+
+/* --- loader impl --- */
+struct _GslLoader
+{
+ const gchar *name; /* format/loader name, e.g. "GslWave" or "WAVE audio, RIFF (little-endian)" */
+
+ /* at least one of the
+ * following three must
+ * be non-NULL
+ */
+ const gchar **extensions; /* e.g.: "mp3", "ogg" or "gslwave" */
+ const gchar **mime_types; /* e.g.: "audio/x-mpg3" or "audio/x-wav" */
+ const gchar **magic_specs; /* e.g.: "0 string RIFF\n8 string WAVE\n" or "0 string #GslWave\n" */
+
+ gint priority; /* -100=high, +100=low, 0=default */
+
+ /*< private >*/
+ gpointer data;
+ GslWaveFileInfo* (*load_file_info) (gpointer data,
+ const gchar *file_name,
+ GslErrorType *error);
+ void (*free_file_info) (gpointer data,
+ GslWaveFileInfo *file_info);
+ GslWaveDsc* (*load_wave_dsc) (gpointer data,
+ GslWaveFileInfo *file_info,
+ guint nth_wave,
+ GslErrorType *error);
+ void (*free_wave_dsc) (gpointer data,
+ GslWaveDsc *wave_dsc);
+ GslDataHandle* (*create_chunk_handle) (gpointer data,
+ GslWaveDsc *wave_dsc,
+ guint nth_chunk,
+ GslErrorType *error);
+ GslLoader *next; /* must be NULL */
+};
+
+void gsl_loader_register (GslLoader *loader);
+GslLoader* gsl_loader_match (const gchar *file_name);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_LOADER_H__ */
diff --git a/flow/gsl/gslmagic.c b/flow/gsl/gslmagic.c
new file mode 100644
index 0000000..29486e3
--- /dev/null
+++ b/flow/gsl/gslmagic.c
@@ -0,0 +1,711 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2000-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslmagic.h"
+
+#include "gslcommon.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+/* --- defines --- */
+#define BFILE_BSIZE (768) /* amount of buffering */
+#define MAX_MAGIC_STRING (256) /* must be < BFILE_BSIZE / 2 */
+
+
+/* --- typedefs & structures --- */
+typedef struct _Magic Magic;
+typedef struct _BFile BFile;
+struct _BFile
+{
+ gint fd;
+ guint file_size;
+ guint8 header[BFILE_BSIZE];
+ guint offset;
+ guint8 buffer[BFILE_BSIZE];
+};
+
+
+/* --- prototypes --- */
+static Magic* magic_create (gchar *magic_string,
+ const gchar *original);
+static gboolean magic_match_file (BFile *bfile,
+ Magic *magics);
+static gboolean bfile_open (BFile *bfile,
+ const gchar *file_name);
+static gboolean bfile_read (BFile *bfile,
+ guint offset,
+ void *mem,
+ guint n_bytes);
+static void bfile_close (BFile *bfile);
+static guint bfile_get_size (BFile *bfile);
+
+
+/* --- functions --- */
+GslMagic*
+gsl_magic_list_match_file (GslRing *magic_list,
+ const gchar *file_name)
+{
+ GslMagic *rmagic = NULL;
+ BFile bfile = { -1, };
+
+ g_return_val_if_fail (file_name != NULL, NULL);
+
+ if (bfile_open (&bfile, file_name))
+ {
+ gchar *extension = strrchr (file_name, '.');
+ gint rpriority = G_MAXINT;
+ GslRing *node;
+
+ /* we do a quick scan by extension first */
+ if (!rmagic && extension)
+ for (node = magic_list; node; node = gsl_ring_walk (magic_list, node))
+ {
+ GslMagic *magic = node->data;
+
+ if (!magic->extension
+ || strcmp (magic->extension, extension) != 0
+ || rpriority < magic->priority
+ || (rmagic && rpriority == magic->priority))
+ continue;
+ if (magic_match_file (&bfile, magic->match_list))
+ {
+ rmagic = magic;
+ rpriority = rmagic->priority;
+ }
+ }
+ /* then we do a normal walk but skip extension matches */
+ if (!rmagic && extension)
+ for (node = magic_list; node; node = gsl_ring_walk (magic_list, node))
+ {
+ GslMagic *magic = node->data;
+
+ if ((magic->extension && strcmp (magic->extension, extension) == 0)
+ || rpriority < magic->priority
+ || (rmagic && rpriority == magic->priority))
+ continue;
+ if (magic_match_file (&bfile, magic->match_list))
+ {
+ rmagic = magic;
+ rpriority = rmagic->priority;
+ }
+ }
+ /* for no extension, we do a full walk */
+ if (!rmagic && !extension)
+ for (node = magic_list; node; node = gsl_ring_walk (magic_list, node))
+ {
+ GslMagic *magic = node->data;
+
+ if (rpriority < magic->priority ||
+ (rmagic && rpriority == magic->priority))
+ continue;
+ if (magic_match_file (&bfile, magic->match_list))
+ {
+ rmagic = magic;
+ rpriority = rmagic->priority;
+ }
+ }
+ bfile_close (&bfile);
+ }
+
+ return rmagic;
+}
+
+GslMagic*
+gsl_magic_create (gpointer data,
+ gint priority,
+ const gchar *extension,
+ const gchar *magic_spec)
+{
+ GslMagic *magic;
+ Magic *match_list;
+ gchar *magic_string;
+
+ g_return_val_if_fail (magic_spec != NULL, NULL);
+
+ magic_string = g_strdup (magic_spec);
+ match_list = magic_create (magic_string, magic_spec);
+ g_free (magic_string);
+ if (!match_list)
+ return NULL;
+
+ magic = g_new (GslMagic, 1);
+ magic->data = data;
+ magic->extension = g_strdup (extension);
+ magic->priority = priority;
+ magic->match_list = match_list;
+
+ return magic;
+}
+
+
+/* --- Magic creation/checking --- */
+typedef enum
+{
+ MAGIC_CHECK_ANY,
+ MAGIC_CHECK_INT_EQUAL,
+ MAGIC_CHECK_INT_GREATER,
+ MAGIC_CHECK_INT_SMALLER,
+ MAGIC_CHECK_UINT_GREATER,
+ MAGIC_CHECK_UINT_SMALLER,
+ MAGIC_CHECK_UINT_ZEROS,
+ MAGIC_CHECK_UINT_ONES,
+ MAGIC_CHECK_STRING_EQUAL,
+ MAGIC_CHECK_STRING_GREATER,
+ MAGIC_CHECK_STRING_SMALLER
+} MagicCheckType;
+typedef union
+{
+ gint32 v_int32;
+ guint32 v_uint32;
+ gchar *v_string;
+} MagicData;
+struct _Magic
+{
+ Magic *next;
+ gulong offset;
+ guint data_size;
+ MagicCheckType magic_check;
+ guint32 data_mask;
+ MagicData value;
+ guint read_string : 1;
+ guint read_size : 1;
+ guint need_swap : 1;
+ guint cmp_unsigned : 1;
+};
+static const gchar *magic_field_delims = " \t,";
+static const gchar *magic_string_delims = " \t\n\r";
+
+static gboolean
+magic_parse_test (Magic *magic,
+ const gchar *string)
+{
+ if (!magic->read_string)
+ {
+ gchar *f = NULL;
+
+ if (string[0] == '<' || string[0] == '>')
+ {
+ if (magic->cmp_unsigned)
+ magic->magic_check = string[0] == '<' ? MAGIC_CHECK_UINT_SMALLER : MAGIC_CHECK_UINT_GREATER;
+ else
+ magic->magic_check = string[0] == '<' ? MAGIC_CHECK_INT_SMALLER : MAGIC_CHECK_INT_GREATER;
+ string += 1;
+ }
+ else if (string[0] == '^' || string[0] == '&')
+ {
+ magic->magic_check = string[0] == '&' ? MAGIC_CHECK_UINT_ONES : MAGIC_CHECK_UINT_ZEROS;
+ string += 1;
+ }
+ else if (string[0] == 'x')
+ {
+ magic->magic_check = MAGIC_CHECK_ANY;
+ string += 1;
+ }
+ else
+ {
+ string += string[0] == '=';
+ magic->magic_check = MAGIC_CHECK_INT_EQUAL;
+ }
+ if (string[0] == '0')
+ magic->value.v_int32 = strtol (string, &f, string[1] == 'x' ? 16 : 8);
+ else
+ magic->value.v_int32 = strtol (string, &f, 10);
+
+ return *string == 0 || !f || *f == 0;
+ }
+ else
+ {
+ gchar tmp_string[MAX_MAGIC_STRING + 1];
+ guint n = 0;
+
+ if (string[0] == '<' || string[0] == '>')
+ {
+ magic->magic_check = string[0] == '<' ? MAGIC_CHECK_STRING_SMALLER : MAGIC_CHECK_STRING_GREATER;
+ string += 1;
+ }
+ else
+ {
+ string += string[0] == '=';
+ magic->magic_check = MAGIC_CHECK_STRING_EQUAL;
+ }
+ while (n < MAX_MAGIC_STRING && string[n] && !strchr (magic_string_delims, string[n]))
+ {
+ if (string[n] != '\\')
+ tmp_string[n] = string[n];
+ else switch ((++string)[n])
+ {
+ case '\\': tmp_string[n] = '\\'; break;
+ case 't': tmp_string[n] = '\t'; break;
+ case 'n': tmp_string[n] = '\n'; break;
+ case 'r': tmp_string[n] = '\r'; break;
+ case 'b': tmp_string[n] = '\b'; break;
+ case 'f': tmp_string[n] = '\f'; break;
+ case 's': tmp_string[n] = ' '; break;
+ case 'e': tmp_string[n] = 27; break;
+ default:
+ if (string[n] >= '0' && string[n] <= '7')
+ {
+ tmp_string[n] = string[n] - '0';
+ if (string[n + 1] >= '0' && string[n + 1] <= '7')
+ {
+ string += 1;
+ tmp_string[n] *= 8;
+ tmp_string[n] += string[n] - '0';
+ if (string[n + 1] >= '0' && string[n + 1] <= '7')
+ {
+ string += 1;
+ tmp_string[n] *= 8;
+ tmp_string[n] += string[n] - '0';
+ }
+ }
+ }
+ else
+ tmp_string[n] = string[n];
+ break;
+ }
+ n++;
+ }
+ tmp_string[n] = 0;
+ magic->data_size = n;
+ magic->value.v_string = g_strdup (tmp_string);
+
+ return TRUE;
+ }
+}
+
+static gboolean
+magic_parse_type (Magic *magic,
+ const gchar *string)
+{
+ gchar *f = NULL;
+
+ if (string[0] == 'u')
+ {
+ string += 1;
+ magic->cmp_unsigned = TRUE;
+ }
+ if (strncmp (string, "byte", 4) == 0)
+ {
+ string += 4;
+ magic->data_size = 1;
+ }
+ else if (strncmp (string, "short", 5) == 0)
+ {
+ string += 5;
+ magic->data_size = 2;
+ }
+ else if (strncmp (string, "leshort", 7) == 0)
+ {
+ string += 7;
+ magic->data_size = 2;
+ magic->need_swap = G_BYTE_ORDER != G_LITTLE_ENDIAN;
+ }
+ else if (strncmp (string, "beshort", 7) == 0)
+ {
+ string += 7;
+ magic->data_size = 2;
+ magic->need_swap = G_BYTE_ORDER != G_BIG_ENDIAN;
+ }
+ else if (strncmp (string, "long", 4) == 0)
+ {
+ string += 4;
+ magic->data_size = 4;
+ }
+ else if (strncmp (string, "lelong", 6) == 0)
+ {
+ string += 6;
+ magic->data_size = 4;
+ magic->need_swap = G_BYTE_ORDER != G_LITTLE_ENDIAN;
+ }
+ else if (strncmp (string, "belong", 6) == 0)
+ {
+ string += 6;
+ magic->data_size = 4;
+ magic->need_swap = G_BYTE_ORDER != G_BIG_ENDIAN;
+ }
+#if 0
+ else if (strncmp (string, "size", 4) == 0)
+ {
+ string += 4;
+ magic->data_size = 4;
+ magic->read_size = TRUE;
+ magic->cmp_unsigned = TRUE;
+ }
+#endif
+ else if (strncmp (string, "string", 6) == 0)
+ {
+ string += 6;
+ magic->data_size = 0;
+ magic->read_string = TRUE;
+ }
+ if (string[0] == '&')
+ {
+ string += 1;
+ if (string[0] == '0')
+ magic->data_mask = strtol (string, &f, string[1] == 'x' ? 16 : 8);
+ else
+ magic->data_mask = strtol (string, &f, 10);
+ if (f && *f != 0)
+ return FALSE;
+ while (*string)
+ string++;
+ }
+ else
+ magic->data_mask = 0xffffffff;
+
+ return *string == 0;
+}
+
+static gboolean
+magic_parse_offset (Magic *magic,
+ gchar *string)
+{
+ gchar *f = NULL;
+
+ if (string[0] == '0')
+ magic->offset = strtol (string, &f, string[1] == 'x' ? 16 : 8);
+ else
+ magic->offset = strtol (string, &f, 10);
+
+ return !f || *f == 0;
+}
+
+static Magic*
+magic_create (gchar *magic_string,
+ const gchar *original)
+#define SKIP_CLEAN(s) { while (*s && !strchr(magic_field_delims, *s)) s++; \
+ while (*s && strchr(magic_field_delims, *s)) \
+ *(s++)=0;}
+{
+ Magic *magics = NULL;
+ gchar *p = magic_string;
+
+ while (p && *p)
+ {
+ gchar *next_line;
+
+ if (*p == '#' || *p == '\n')
+ {
+ next_line = strchr (p, '\n');
+ if (next_line)
+ next_line++;
+ }
+ else
+ {
+ Magic *tmp = magics;
+
+ magics = g_new0 (Magic, 1);
+ magics->next = tmp;
+
+ magic_string = p;
+ SKIP_CLEAN (p);
+ if (!magic_parse_offset (magics, magic_string))
+ {
+ g_warning ("unable to parse magic offset \"%s\" from \"%s\"", magic_string, original);
+ return NULL;
+ }
+ magic_string = p;
+ SKIP_CLEAN (p);
+ if (!magic_parse_type (magics, magic_string))
+ {
+ g_warning ("unable to parse magic type \"%s\" from \"%s\"", magic_string, original);
+ return NULL;
+ }
+ magic_string = p;
+ next_line = strchr (magic_string, '\n');
+ if (next_line)
+ *(next_line++) = 0;
+ if (!magics->read_string)
+ SKIP_CLEAN (p);
+ if (!magic_parse_test (magics, magic_string))
+ {
+ g_warning ("unable to parse magic test \"%s\" from \"%s\"", magic_string, original);
+ return NULL;
+ }
+ }
+ p = next_line;
+ }
+
+ return magics;
+}
+
+static gboolean
+magic_check_data (Magic *magic,
+ MagicData *data)
+{
+ gint cmp = 0;
+
+ switch (magic->magic_check)
+ {
+ guint l;
+ case MAGIC_CHECK_ANY:
+ cmp = 1;
+ break;
+ case MAGIC_CHECK_INT_EQUAL:
+ data->v_int32 &= magic->data_mask;
+ cmp = data->v_int32 == magic->value.v_int32;
+ break;
+ case MAGIC_CHECK_INT_GREATER:
+ data->v_int32 &= magic->data_mask;
+ cmp = data->v_int32 > magic->value.v_int32;
+ break;
+ case MAGIC_CHECK_INT_SMALLER:
+ data->v_int32 &= magic->data_mask;
+ cmp = data->v_int32 < magic->value.v_int32;
+ break;
+ case MAGIC_CHECK_UINT_GREATER:
+ data->v_uint32 &= magic->data_mask;
+ cmp = data->v_uint32 > magic->value.v_uint32;
+ break;
+ case MAGIC_CHECK_UINT_SMALLER:
+ data->v_uint32 &= magic->data_mask;
+ cmp = data->v_uint32 < magic->value.v_uint32;
+ break;
+ case MAGIC_CHECK_UINT_ZEROS:
+ data->v_uint32 &= magic->data_mask;
+ cmp = (data->v_int32 & magic->value.v_int32) == 0;
+ break;
+ case MAGIC_CHECK_UINT_ONES:
+ data->v_uint32 &= magic->data_mask;
+ cmp = (data->v_int32 & magic->value.v_int32) == magic->value.v_int32;
+ break;
+ case MAGIC_CHECK_STRING_EQUAL:
+ l = magic->data_size < 1 ? strlen (data->v_string) : magic->data_size;
+ cmp = strncmp (data->v_string, magic->value.v_string, l) == 0;
+ break;
+ case MAGIC_CHECK_STRING_GREATER:
+ l = magic->data_size < 1 ? strlen (data->v_string) : magic->data_size;
+ cmp = strncmp (data->v_string, magic->value.v_string, l) > 0;
+ break;
+ case MAGIC_CHECK_STRING_SMALLER:
+ l = magic->data_size < 1 ? strlen (data->v_string) : magic->data_size;
+ cmp = strncmp (data->v_string, magic->value.v_string, l) < 0;
+ break;
+ }
+
+ return cmp > 0;
+}
+
+static inline gboolean
+magic_read_data (BFile *bfile,
+ Magic *magic,
+ MagicData *data)
+{
+ guint file_size = bfile_get_size (bfile);
+
+ if (magic->read_size)
+ data->v_uint32 = file_size;
+ else if (magic->read_string)
+ {
+ guint l = magic->data_size;
+
+ if (l < 1 || l > MAX_MAGIC_STRING)
+ l = MIN (MAX_MAGIC_STRING, file_size - magic->offset);
+ if (!bfile_read (bfile, magic->offset, data->v_string, l))
+ return FALSE;
+ data->v_string[MAX (l, 0)] = 0;
+ }
+ else
+ {
+ if (magic->data_size == 4)
+ {
+ guint32 uint32 = 0;
+
+ if (!bfile_read (bfile, magic->offset, &uint32, 4))
+ return FALSE;
+ if (magic->need_swap)
+ data->v_uint32 = GUINT32_SWAP_LE_BE (uint32);
+ else
+ data->v_uint32 = uint32;
+ }
+ else if (magic->data_size == 2)
+ {
+ guint16 uint16 = 0;
+
+ if (!bfile_read (bfile, magic->offset, &uint16, 2))
+ return FALSE;
+ if (magic->need_swap)
+ uint16 = GUINT16_SWAP_LE_BE (uint16);
+ if (magic->cmp_unsigned)
+ data->v_uint32 = uint16;
+ else
+ data->v_int32 = (signed) uint16;
+ }
+ else if (magic->data_size == 1)
+ {
+ guint8 uint8;
+
+ if (!bfile_read (bfile, magic->offset, &uint8, 1))
+ return FALSE;
+ if (magic->cmp_unsigned)
+ data->v_uint32 = uint8;
+ else
+ data->v_int32 = (signed) uint8;
+ }
+ else
+ g_assert_not_reached ();
+ }
+
+ return TRUE;
+}
+
+static gboolean
+magic_match_file (BFile *bfile,
+ Magic *magics)
+{
+ g_return_val_if_fail (bfile != NULL, FALSE);
+ g_return_val_if_fail (magics != NULL, FALSE);
+
+ do
+ {
+ gchar data_string[MAX_MAGIC_STRING + 1];
+ MagicData data;
+
+ if (magics->read_string)
+ data.v_string = data_string;
+ else
+ data.v_uint32 = 0;
+
+ if (!magic_read_data (bfile, magics, &data) ||
+ !magic_check_data (magics, &data))
+ return FALSE;
+ magics = magics->next;
+ }
+ while (magics);
+
+ return TRUE;
+}
+
+
+/* --- buffered file, optimized for magic checks --- */
+static gboolean
+bfile_open (BFile *bfile,
+ const gchar *file_name)
+{
+ struct stat buf = { 0, };
+ gint ret;
+
+ g_return_val_if_fail (bfile != NULL, FALSE);
+ g_return_val_if_fail (bfile->fd < 0, FALSE);
+ g_return_val_if_fail (file_name != NULL, FALSE);
+
+ bfile->fd = open (file_name, O_RDONLY);
+ if (bfile->fd < 0)
+ return FALSE;
+
+ do
+ ret = fstat (bfile->fd, &buf);
+ while (ret < 0 && errno == EINTR);
+ if (ret < 0)
+ {
+ bfile_close (bfile);
+ return FALSE;
+ }
+ bfile->file_size = buf.st_size;
+
+ do
+ ret = read (bfile->fd, bfile->header, BFILE_BSIZE);
+ while (ret < 0 && errno == EINTR);
+ if (ret < 0)
+ {
+ bfile_close (bfile);
+ return FALSE;
+ }
+
+ bfile->offset = 0;
+ memcpy (bfile->buffer, bfile->header, BFILE_BSIZE);
+
+ return TRUE;
+}
+
+static gboolean
+bfile_read (BFile *bfile,
+ guint offset,
+ void *mem,
+ guint n_bytes)
+{
+ guint end = offset + n_bytes;
+ gint ret;
+
+ g_return_val_if_fail (bfile != NULL, FALSE);
+ g_return_val_if_fail (n_bytes < BFILE_BSIZE / 2, FALSE);
+
+ if (end > bfile->file_size || bfile->fd < 0)
+ return FALSE;
+
+ if (end < BFILE_BSIZE)
+ {
+ memcpy (mem, bfile->header + offset, n_bytes);
+ return TRUE;
+ }
+ if (offset >= bfile->offset && end < bfile->offset + BFILE_BSIZE)
+ {
+ memcpy (mem, bfile->buffer + offset - bfile->offset, n_bytes);
+ return TRUE;
+ }
+
+ bfile->offset = offset - BFILE_BSIZE / 8;
+ do
+ ret = lseek (bfile->fd, bfile->offset, SEEK_SET);
+ while (ret < 0 && errno == EINTR);
+ if (ret < 0)
+ {
+ bfile_close (bfile);
+ return FALSE;
+ }
+ do
+ ret = read (bfile->fd, bfile->buffer, BFILE_BSIZE);
+ while (ret < 0 && errno == EINTR);
+ if (ret < 0)
+ {
+ bfile_close (bfile);
+ return FALSE;
+ }
+ if (offset >= bfile->offset && end < bfile->offset + BFILE_BSIZE)
+ {
+ memcpy (mem, bfile->buffer + offset - bfile->offset, n_bytes);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static guint
+bfile_get_size (BFile *bfile)
+{
+ g_return_val_if_fail (bfile != NULL, 0);
+
+ return bfile->fd >= 0 ? bfile->file_size : 0;
+}
+
+static void
+bfile_close (BFile *bfile)
+{
+ g_return_if_fail (bfile != NULL);
+
+ if (bfile->fd >= 0)
+ close (bfile->fd);
+ bfile->fd = -1;
+}
diff --git a/flow/gsl/gslmagic.h b/flow/gsl/gslmagic.h
new file mode 100644
index 0000000..41961bd
--- /dev/null
+++ b/flow/gsl/gslmagic.h
@@ -0,0 +1,72 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2000-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_MAGIC_H__
+#define __GSL_MAGIC_H__
+
+#include <gsl/gsldefs.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+/* --- structures --- */
+struct _GslMagic
+{
+ gpointer data;
+ gchar *extension;
+
+ /*< private >*/
+ gint priority;
+ gpointer match_list;
+};
+
+
+/* match entity with:
+ * prefix,
+ * extension,
+ * magic_spec
+ *
+ * where prefix has absolute preference, and extension is just
+ * a _hint_ for magic_spec match order, unless magic_spec==NULL
+ *
+ * no prefix for save handlers. (?) just extension matches.
+ *
+ * need pre-parse functionality, to figure name and type of a
+ * file's contents.
+ */
+
+
+/* --- prototypes --- */
+GslMagic* gsl_magic_create (gpointer data,
+ gint priority,
+ const gchar *extension,
+ const gchar *magic_spec);
+GslMagic* gsl_magic_list_match_file (GslRing *magic_list,
+ const gchar *file_name);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_MAGIC_H__ */
diff --git a/flow/gsl/gslmakefile.inc b/flow/gsl/gslmakefile.inc
new file mode 100644
index 0000000..9787b7d
--- /dev/null
+++ b/flow/gsl/gslmakefile.inc
@@ -0,0 +1,87 @@
+# this makefile defines:
+#
+# GSL_C_SRC C source files which need to be added to *_SOURCES
+# GSL_NOINST_PROGS GSL test programs, needs to be added to noinst_PROGRAMS
+#
+# this makefile supports:
+#
+# GSL_progs_ldadd add link options to this varibale, which are required
+# to link GSL_NOINST_PROGS targets
+# gslincludedir directory to install public headers into if not empty
+#
+# this makefile introduces:
+#
+# gsltestoutput: make target to generate a sample set of test data
+
+# make sure gslincludedir= is defined
+# GSL targets
+GSL_H_SRC = gslcommon.h gsldatacache.h gsldatahandle.h gsldefs.h \
+ gslloader.h gslmath.h gslfilter.h gsldatautils.h gsldatahandle-vorbis.h \
+ gslconvert.h gslfft.h gslieee754.h gslsignal.h gslmagic.h \
+ gslengine.h gslwaveosc.h gslwavechunk.h gsldatahandle-mad.h \
+ gslosctable.h gsloscillator.h
+GSL_C_SRC = gsldatacache.c gsldatahandle.c gslwavechunk.c gsldatahandle-vorbis.c \
+ gslmath.c gslfilter.c gslcommon.c gsldatautils.c gslmagic.c \
+ gslloader-wav.c gslloader-gslwave.c gslloader-mad.c gslloader-oggvorbis.c \
+ gslconvert.c gslfft.c gslsignal.c gslloader.c gslwaveosc.c \
+ gslengine.c gsloputil.c gslopmaster.c gslopschedule.c gsldatahandle-mad.c \
+ gslosctable.c gsloscillator.c
+GSL_EXTRA_SRC = gslconfig.h gsloputil.h gslopmaster.h gslopnode.h \
+ gslopschedule.h gslincluder.c gslwaveosc-aux.c gsloscillator-aux.c
+GSL_EXTRA_DAT = gsl.gnuplot gsl-mplan.txt gslarrows gslwave.header gslglib.c gslglib.h gsl-fftgen.pl
+EXTRA_DIST += $(GSL_H_SRC) $(GSL_EXTRA_SRC) $(GSL_EXTRA_DAT)
+
+GSL_NOINST_PROGS = gslwchunk gsltests gslffttest
+gslwchunk_SOURCES = gslwchunk.c
+gslwchunk_LDADD = $(GSL_progs_ldadd)
+gslwchunk_LDFLAGS = $(USE_THREADS)
+gsltests_SOURCES = gsltests.c
+gsltests_LDADD = $(GSL_progs_ldadd)
+gsltests_LDFLAGS = $(USE_THREADS)
+gslffttest_SOURCES = gslffttest.c
+gslffttest_LDADD = $(GSL_progs_ldadd)
+gslffttest_LDFLAGS = $(USE_THREADS)
+
+$(srcdir)/gslfft.c: $(srcdir)/gsl-fftgen.pl $(srcdir)/gsl-fftconf.sh
+ cd $(srcdir) && ./gsl-fftconf.sh 'perl ./gsl-fftgen.pl' \"gslfft.h\" >gslfft.c
+MAINTAINERCLEANFILES += gslfft.c
+
+$(srcdir)/gslwchunk.c: gslconfig.h
+$(srcdir)/gsltests.c: gslconfig.h
+$(srcdir)/gslffttest.c: gslconfig.h
+# $(OBJECTS): gslconfig.h
+
+gsl_public_HEADERS = $(GSL_H_SRC) gslconfig.h
+gsl_publicdir = $(gslincludedir)
+
+.PHONY: gsltestoutput
+
+gsltestoutput:
+ @./gsltests blp 7 0.3 0.1211
+ @./gsltests bhp 12 1.8332 0.1033
+ @./gsltests bbp 14 0.5 0.6 0.1033
+ @./gsltests bbs 12 1.5 1.6 0.2
+ @./gsltests t1l 7 0.3 0.0125
+ @./gsltests t1h 8 1.8332 0.1033
+ @./gsltests t1p 6 0.5 0.6 0.1033
+ @./gsltests t1s 8 1.4 1.5 0.25
+ @./gsltests t2l 13 0.1 1.1 0.176
+ @./gsltests t2h 10 1.14 1.2 0.0763
+ @./gsltests t2p 14 0.7 0.8 1.3 0.0763
+ @./gsltests t2p 10 0.9 1.2 1.4 0.15
+ @./gsltests t2s 10 0.9 1.2 1.1 0.15
+ @echo -n "plot [0:pi] [-96:1]"
+ @echo -n " dB(BL7(Z(x))),"
+ @echo -n " dB(BH12(Z(x))),"
+ @echo -n " dB(BP14(Z(x))),"
+ @echo -n " dB(BS12(Z(x))),"
+ @echo -n " dB(T1L7(Z(x))),"
+ @echo -n " dB(T1H8(Z(x))),"
+ @echo -n " dB(T1P6(Z(x))),"
+ @echo -n " dB(T1S8(Z(x))),"
+ @echo -n " dB(T2L13(Z(x))),"
+ @echo -n " dB(T2H10(Z(x))),"
+ @echo -n " dB(T2P14(Z(x))),"
+ @echo -n " dB(T2P10(Z(x))),"
+ @echo -n " dB(T2S10(Z(x))),"
+ @echo " -3"
diff --git a/flow/gsl/gslmath.c b/flow/gsl/gslmath.c
new file mode 100644
index 0000000..97ac675
--- /dev/null
+++ b/flow/gsl/gslmath.c
@@ -0,0 +1,1085 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslmath.h"
+
+#include <string.h>
+#include <stdio.h>
+
+
+#define RING_BUFFER_LENGTH (16)
+#define PRINTF_DIGITS "1270"
+#define FLOAT_STRING_SIZE (2048)
+
+
+/* factorization constants: 2^(1/12), ln(2^(1/12)) and 2^(1/(12*6))
+ * retrived with:
+ #include <stl.h>
+ #include <complex.h>
+ typedef long double ld;
+
+ int main (void)
+ {
+ ld r, l;
+
+ cout.precision(256);
+
+ r = pow ((ld) 2, (ld) 1 / (ld) 12);
+ cout << "2^(1/12) =\n";
+ cout << "2^" << (ld) 1 / (ld) 12 << " =\n";
+ cout << r << "\n";
+
+ l = log (r);
+ cout << "ln(2^(1/12)) =\n";
+ cout << "ln(" << r << ") =\n";
+ cout << l << "\n";
+
+ r = pow ((ld) 2, (ld) 1 / (ld) 72);
+ cout << "2^(1/72) =\n";
+ cout << "2^" << (ld) 1 / (ld) 72 << " =\n";
+ cout << r << "\n";
+
+ return 0;
+ }
+*/
+
+
+/* --- prototypes --- */
+static void zrhqr (double a[], int m, double rtr[], double rti[]);
+static double rf (double x, double y, double z);
+static double ellf (double phi, double ak);
+static void sncndn (double uu, double emmc, double *sn_p, double *cn_p, double *dn_p);
+static void sncndnC (GslComplex uu, GslComplex emmc, GslComplex *sn_p, GslComplex *cn_p, GslComplex *dn_p);
+static GslComplex rfC (GslComplex x, GslComplex y, GslComplex z);
+
+
+/* --- functions --- */
+static inline char*
+pretty_print_double (char *str,
+ double d)
+{
+ char *s= str;
+
+ sprintf (s, "%."PRINTF_DIGITS"f", d);
+ while (*s) s++;
+ while (s[-1] == '0' && s[-2] != '.')
+ s--;
+ *s = 0;
+ return s;
+}
+
+char*
+gsl_complex_list (unsigned int n_points,
+ GslComplex *points,
+ const char *indent)
+{
+ static unsigned int rbi = 0;
+ static char* rbuffer[RING_BUFFER_LENGTH] = { NULL, };
+ char *s, *tbuffer = g_newa (char, (FLOAT_STRING_SIZE * 2 * n_points));
+ unsigned int i;
+
+ rbi++; if (rbi >= RING_BUFFER_LENGTH) rbi -= RING_BUFFER_LENGTH;
+ if (rbuffer[rbi] != NULL)
+ g_free (rbuffer[rbi]);
+ s = tbuffer;
+ for (i = 0; i < n_points; i++)
+ {
+ *s = 0;
+ if (indent)
+ strcat (s, indent);
+ while (*s) s++;
+ s = pretty_print_double (s, points[i].re);
+ *s++ = ' ';
+ s = pretty_print_double (s, points[i].im);
+ *s++ = '\n';
+ }
+ *s++ = 0;
+ rbuffer[rbi] = g_strdup (tbuffer);
+ return rbuffer[rbi];
+}
+
+char*
+gsl_complex_str (GslComplex c)
+{
+ static unsigned int rbi = 0;
+ static char* rbuffer[RING_BUFFER_LENGTH] = { NULL, };
+ char *s, tbuffer[FLOAT_STRING_SIZE * 2];
+
+ rbi++; if (rbi >= RING_BUFFER_LENGTH) rbi -= RING_BUFFER_LENGTH;
+ if (rbuffer[rbi] != NULL)
+ g_free (rbuffer[rbi]);
+ s = tbuffer;
+ *s++ = '{';
+ s = pretty_print_double (s, c.re);
+ *s++ = ',';
+ *s++ = ' ';
+ s = pretty_print_double (s, c.im);
+ *s++ = '}';
+ *s++ = 0;
+ rbuffer[rbi] = g_strdup (tbuffer);
+ return rbuffer[rbi];
+}
+
+char*
+gsl_poly_str (unsigned int degree,
+ double *a,
+ const char *var)
+{
+ static unsigned int rbi = 0;
+ static char* rbuffer[RING_BUFFER_LENGTH] = { NULL, };
+ char *s, *tbuffer = g_newa (char, degree * FLOAT_STRING_SIZE);
+ unsigned int i;
+
+ if (!var)
+ var = "x";
+ rbi++; if (rbi >= RING_BUFFER_LENGTH) rbi -= RING_BUFFER_LENGTH;
+ if (rbuffer[rbi] != NULL)
+ g_free (rbuffer[rbi]);
+ s = tbuffer;
+ *s++ = '(';
+ s = pretty_print_double (s, a[0]);
+ for (i = 1; i <= degree; i++)
+ {
+ *s++ = '+';
+ *s = 0; strcat (s, var); while (*s) s++;
+ *s++ = '*';
+ *s++ = '(';
+ s = pretty_print_double (s, a[i]);
+ }
+ while (i--)
+ *s++ = ')';
+ *s++ = 0;
+ rbuffer[rbi] = g_strdup (tbuffer);
+ return rbuffer[rbi];
+}
+
+char*
+gsl_poly_str1 (unsigned int degree,
+ double *a,
+ const char *var)
+{
+ static unsigned int rbi = 0;
+ static char* rbuffer[RING_BUFFER_LENGTH] = { NULL, };
+ char *s, *tbuffer = g_newa (char, degree * FLOAT_STRING_SIZE);
+ unsigned int i, need_plus = 0;
+
+ if (!var)
+ var = "x";
+ rbi++; if (rbi >= RING_BUFFER_LENGTH) rbi -= RING_BUFFER_LENGTH;
+ if (rbuffer[rbi] != NULL)
+ g_free (rbuffer[rbi]);
+ s = tbuffer;
+ *s++ = '(';
+ if (a[0] != 0.0)
+ {
+ s = pretty_print_double (s, a[0]);
+ need_plus = 1;
+ }
+ for (i = 1; i <= degree; i++)
+ {
+ if (a[i] == 0.0)
+ continue;
+ if (need_plus)
+ {
+ *s++ = ' ';
+ *s++ = '+';
+ *s++ = ' ';
+ }
+ if (a[i] != 1.0)
+ {
+ s = pretty_print_double (s, a[i]);
+ *s++ = '*';
+ }
+ *s = 0;
+ strcat (s, var);
+ while (*s) s++;
+ if (i > 1)
+ {
+ *s++ = '*';
+ *s++ = '*';
+ sprintf (s, "%u", i);
+ while (*s) s++;
+ }
+ need_plus = 1;
+ }
+ *s++ = ')';
+ *s++ = 0;
+ rbuffer[rbi] = g_strdup (tbuffer);
+ return rbuffer[rbi];
+}
+
+void
+gsl_complex_gnuplot (const char *file_name,
+ unsigned int n_points,
+ GslComplex *points)
+{
+ FILE *fout = fopen (file_name, "w");
+
+ fputs (gsl_complex_list (n_points, points, ""), fout);
+ fclose (fout);
+}
+
+double
+gsl_temp_freq (double kammer_freq,
+ int halftone_delta)
+{
+ double factor;
+
+ factor = pow (GSL_2_POW_1_DIV_12, halftone_delta);
+
+ return kammer_freq * factor;
+}
+
+void
+gsl_poly_from_re_roots (unsigned int degree,
+ double *a,
+ GslComplex *roots)
+{
+ unsigned int i;
+
+ /* initialize polynomial */
+ a[1] = 1;
+ a[0] = -roots[0].re;
+ /* monomial factor multiplication */
+ for (i = 1; i < degree; i++)
+ {
+ unsigned int j;
+
+ a[i + 1] = a[i];
+ for (j = i; j >= 1; j--)
+ a[j] = a[j - 1] - a[j] * roots[i].re;
+ a[0] *= -roots[i].re;
+ }
+}
+
+void
+gsl_cpoly_from_roots (unsigned int degree,
+ GslComplex *c,
+ GslComplex *roots)
+{
+ unsigned int i;
+
+ /* initialize polynomial */
+ c[1].re = 1;
+ c[1].im = 0;
+ c[0].re = -roots[0].re;
+ c[0].im = -roots[0].im;
+ /* monomial factor multiplication */
+ for (i = 1; i < degree; i++)
+ {
+ GslComplex r = gsl_complex (-roots[i].re, -roots[i].im);
+ unsigned int j;
+
+ c[i + 1] = c[i];
+ for (j = i; j >= 1; j--)
+ c[j] = gsl_complex_add (c[j - 1], gsl_complex_mul (c[j], r));
+ c[0] = gsl_complex_mul (c[0], r);
+ }
+}
+
+void
+gsl_poly_complex_roots (unsigned int degree,
+ double *a, /* [0..degree] (degree+1 elements) */
+ GslComplex *roots) /* [degree] */
+{
+ double *roots_re = g_newa (double, 1 + degree);
+ double *roots_im = g_newa (double, 1 + degree);
+ unsigned int i;
+
+ zrhqr (a, degree, roots_re, roots_im);
+ for (i = 0; i < degree; i++)
+ {
+ roots[i].re = roots_re[1 + i];
+ roots[i].im = roots_im[1 + i];
+ }
+}
+
+double
+gsl_ellip_rf (double x,
+ double y,
+ double z)
+{
+ return rf (x, y, z);
+}
+
+double
+gsl_ellip_F (double phi,
+ double ak)
+{
+ return ellf (phi, ak);
+}
+
+double
+gsl_ellip_sn (double u,
+ double emmc)
+{
+ double sn;
+
+ sncndn (u, emmc, &sn, NULL, NULL);
+ return sn;
+}
+
+double
+gsl_ellip_asn (double y,
+ double emmc)
+{
+ return y * rf (1.0 - y * y, 1.0 - y * y * (1.0 - emmc), 1.0);
+}
+
+GslComplex
+gsl_complex_ellip_asn (GslComplex y,
+ GslComplex emmc)
+{
+ return gsl_complex_mul (y,
+ rfC (gsl_complex_sub (gsl_complex (1.0, 0),
+ gsl_complex_mul (y, y)),
+ gsl_complex_sub (gsl_complex (1.0, 0),
+ gsl_complex_mul3 (y, y, gsl_complex_sub (gsl_complex (1.0, 0),
+ emmc))),
+ gsl_complex (1.0, 0)));
+}
+
+GslComplex
+gsl_complex_ellip_sn (GslComplex u,
+ GslComplex emmc)
+{
+ GslComplex sn;
+
+ sncndnC (u, emmc, &sn, NULL, NULL);
+ return sn;
+}
+
+double
+gsl_bit_depth_epsilon (guint n_bits)
+{
+ /* epsilon for various bit depths, based on significance of one bit,
+ * minus fudge. created with:
+ * { echo "scale=40"; for i in `seq 1 32` ; do echo "1/2^$i - 10^-($i+1)" ; done } | bc | sed 's/$/,/'
+ */
+ static const double bit_epsilons[] = {
+ .4900000000000000000000000000000000000000,
+ .2490000000000000000000000000000000000000,
+ .1249000000000000000000000000000000000000,
+ .0624900000000000000000000000000000000000,
+ .0312490000000000000000000000000000000000,
+ .0156249000000000000000000000000000000000,
+ .0078124900000000000000000000000000000000,
+ .0039062490000000000000000000000000000000,
+ .0019531249000000000000000000000000000000,
+ .0009765624900000000000000000000000000000,
+ .0004882812490000000000000000000000000000,
+ .0002441406249000000000000000000000000000,
+ .0001220703124900000000000000000000000000,
+ .0000610351562490000000000000000000000000,
+ .0000305175781249000000000000000000000000,
+ .0000152587890624900000000000000000000000,
+ .0000076293945312490000000000000000000000,
+ .0000038146972656249000000000000000000000,
+ .0000019073486328124900000000000000000000,
+ .0000009536743164062490000000000000000000,
+ .0000004768371582031249000000000000000000,
+ .0000002384185791015624900000000000000000,
+ .0000001192092895507812490000000000000000,
+ .0000000596046447753906249000000000000000,
+ .0000000298023223876953124900000000000000,
+ .0000000149011611938476562490000000000000,
+ .0000000074505805969238281249000000000000,
+ .0000000037252902984619140624900000000000,
+ .0000000018626451492309570312490000000000,
+ .0000000009313225746154785156249000000000,
+ .0000000004656612873077392578124900000000,
+ .0000000002328306436538696289062490000000,
+ };
+
+ return bit_epsilons[CLAMP (n_bits, 1, 32) - 1];
+}
+
+
+/* --- Numerical Receipes --- */
+#define gsl_complex_rmul(scale, c) gsl_complex_scale (c, scale)
+#define ONE gsl_complex (1.0, 0)
+#define SIGN(a,b) ((b) >= 0.0 ? fabs (a) : -fabs(a))
+static inline int IMAX (int i1, int i2) { return i1 > i2 ? i1 : i2; }
+static inline double DMIN (double d1, double d2) { return d1 < d2 ? d1 : d2; }
+static inline double DMAX (double d1, double d2) { return d1 > d2 ? d1 : d2; }
+static inline double DSQR (double d) { return d == 0.0 ? 0.0 : d * d; }
+#define nrerror(error) g_error ("NR-ERROR: %s", (error))
+static inline double* vector (long nl, long nh)
+ /* allocate a vector with subscript range v[nl..nh] */
+{
+ double *v = g_new (double, nh - nl + 1 + 1);
+ return v - nl + 1;
+}
+static inline void free_vector (double *v, long nl, long nh)
+{
+ g_free (v + nl - 1);
+}
+static inline double** matrix (long nrl, long nrh, long ncl, long nch)
+ /* allocate a matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+ long i, nrow = nrh - nrl + 1, ncol = nch - ncl + 1;
+ double **m = g_new (double*, nrow + 1);
+ m += 1;
+ m -= nrl;
+ m[nrl] = g_new (double, nrow * ncol + 1);
+ m[nrl] += 1;
+ m[nrl] -= ncl;
+ for (i = nrl + 1; i <= nrh; i++)
+ m[i] = m[i - 1] + ncol;
+ return m;
+}
+static inline void free_matrix (double **m, long nrl, long nrh, long ncl, long nch)
+{
+ g_free (m[nrl] + ncl - 1);
+ g_free (m + nrl - 1);
+}
+
+static void
+poldiv (double u[], int n, double v[], int nv, double q[], double r[])
+ /* Given the n+1 coefficients of a polynomial of degree n in u[0..n], and the nv+1 coefficients
+ of another polynomial of degree nv in v[0..nv], divide the polynomial u by the polynomial
+ v ("u"/"v") giving a quotient polynomial whose coefficients are returned in q[0..n], and a
+ remainder polynomial whose coefficients are returned in r[0..n]. The elements r[nv..n]
+ and q[n-nv+1..n] are returned as zero. */
+{
+ int k,j;
+
+ for (j=0;j<=n;j++) {
+ r[j]=u[j];
+ q[j]=0.0;
+ }for (k=n-nv;k>=0;k--) {
+ q[k]=r[nv+k]/v[nv];
+ for (j=nv+k-1;j>=k;j--) r[j] -= q[k]*v[j-k];
+ }for (j=nv;j<=n;j++) r[j]=0.0;
+}
+
+#define MAX_ITER_BASE 9 /* TIMJ: was 3 */
+#define MAX_ITER_FAC 20 /* TIMJ: was 10 */
+static void
+hqr (double **a, int n, double wr[], double wi[])
+ /* Finds all eigenvalues of an upper Hessenberg matrix a[1..n][1..n]. On input a can be
+ exactly as output from elmhes §11.5; on output it is destroyed. The real and imaginary parts
+ of the eigenvalues are returned in wr[1..n] and wi[1..n], respectively. */
+{
+ int nn,m,l,k,j,its,i,mmin;
+ double z,y,x,w,v,u,t,s,r,q,p,anorm;
+ r=q=p=0; /* TIMJ: silence compiler */
+
+ anorm=0.0; /* Compute matrix norm for possible use in lo- */
+ for (i=1;i<=n;i++) /* cating single small subdiagonal element. */
+ for (j=IMAX (i-1,1);j<=n;j++)
+ anorm += fabs (a[i][j]);
+ nn=n;
+ t=0.0; /* Gets changed only by an exceptional shift. */
+ while (nn >= 1) { /* Begin search for next eigenvalue. */
+ its=0;
+ do {for (l=nn;l>=2;l--) { /* Begin iteration: look for single small subdi- */
+ s=fabs (a[l-1][l-1])+fabs (a[l][l]); /* agonal element. */
+ if (s == 0.0) s=anorm;
+ if ((double)(fabs (a[l][l-1]) + s) == s) break;
+ }
+ x=a[nn][nn];
+ if (l == nn) { /* One root found. */
+ wr[nn]=x+t;
+ wi[nn--]=0.0;
+ } else {
+ y=a[nn-1][nn-1];
+ w=a[nn][nn-1]*a[nn-1][nn];
+ if (l == (nn-1)) { /* Two roots found... */
+ p=0.5*(y-x);
+ q=p*p+w;
+ z=sqrt (fabs (q));
+ x += t;
+ if (q >= 0.0) { /* ...a real pair. */
+ z=p+SIGN (z,p);
+ wr[nn-1]=wr[nn]=x+z;
+ if (z) wr[nn]=x-w/z;
+ wi[nn-1]=wi[nn]=0.0;
+ } else { /* ...a complex pair. */
+ wr[nn-1]=wr[nn]=x+p;
+ wi[nn-1]= -(wi[nn]=z);
+ }
+ nn -= 2;
+ } else { /* No roots found. Continue iteration. */
+ if (its == MAX_ITER_BASE * MAX_ITER_FAC)
+ nrerror ("Too many iterations in hqr");
+ if (its && !(its%MAX_ITER_FAC)) { /* Form exceptional shift. */
+ t += x;
+ for (i=1;i<=nn;i++) a[i][i] -= x;
+ s=fabs (a[nn][nn-1])+fabs (a[nn-1][nn-2]);
+ y=x=0.75*s;
+ w = -0.4375*s*s;
+ }
+ ++its;
+ for (m=(nn-2);m>=l;m--) { /* Form shift and then look for */
+ z=a[m][m]; /* 2 consecutive small sub- */
+ r=x-z; /* diagonal elements. */
+ s=y-z;
+ p=(r*s-w)/a[m+1][m]+a[m][m+1]; /* Equation (11.6.23). */
+ q=a[m+1][m+1]-z-r-s;
+ r=a[m+2][m+1];
+ s=fabs (p)+fabs (q)+fabs (r); /* Scale to prevent overflow or */
+ p /= s; /* underflow. */
+ q /= s;
+ r /= s;
+ if (m == l) break;
+ u=fabs (a[m][m-1])*(fabs (q)+fabs (r));
+ v=fabs (p)*(fabs (a[m-1][m-1])+fabs (z)+fabs (a[m+1][m+1]));
+ if ((double)(u+v) == v)
+ break; /* Equation (11.6.26). */
+ }
+ for (i=m+2;i<=nn;i++) {
+ a[i][i-2]=0.0;
+ if (i != (m+2))
+ a[i][i-3]=0.0;
+ }
+ for (k=m;k<=nn-1;k++) {
+ /* Double QR step on rows l to nn and columns m to nn. */
+ if (k != m) {
+ p=a[k][k-1]; /* Begin setup of Householder */
+ q=a[k+1][k-1]; /* vector. */
+ r=0.0;
+ if (k != (nn-1)) r=a[k+2][k-1];
+ if ((x=fabs (p)+fabs (q)+fabs (r)) != 0.0) {
+ p /= x; /* Scale to prevent overflow or */
+ q /= x; /* underflow. */
+ r /= x;
+ }
+ }
+ if ((s=SIGN (sqrt (p*p+q*q+r*r),p)) != 0.0) {
+ if (k == m) {
+ if (l != m)
+ a[k][k-1] = -a[k][k-1];
+ } else
+ a[k][k-1] = -s*x;
+ p += s; /* Equations (11.6.24). */
+ x=p/s;
+ y=q/s;
+ z=r/s;
+ q /= p;
+ r /= p;
+ for (j=k;j<=nn;j++) { /* Row modification. */
+ p=a[k][j]+q*a[k+1][j];
+ if (k != (nn-1)) {
+ p += r*a[k+2][j];
+ a[k+2][j] -= p*z;
+ }
+ a[k+1][j] -= p*y;
+ a[k][j] -= p*x;
+ }
+ mmin = nn<k+3 ? nn : k+3;
+ for (i=l;i<=mmin;i++) { /* Column modification. */
+ p=x*a[i][k]+y*a[i][k+1];
+ if (k != (nn-1)) {
+ p += z*a[i][k+2];
+ a[i][k+2] -= p*r;
+ }a[i][k+1] -= p*q;
+ a[i][k] -= p;
+ }
+ }
+ }
+ }
+ }
+ } while (l < nn-1);
+ }
+}
+
+#define RADIX 2.0
+static void
+balanc (double **a, int n)
+ /* Given a matrix a[1..n][1..n], this routine replaces it by a balanced matrix with identical
+ eigenvalues. A symmetric matrix is already balanced and is unaffected by this procedure. The
+ parameter RADIX should be the machine's floating-point radix. */
+{
+ int last,j,i;
+ double s,r,g,f,c,sqrdx;
+
+ sqrdx=RADIX*RADIX;
+ last=0;
+ while (last == 0) {
+ last=1;
+ for (i=1;i<=n;i++) { /* Calculate row and column norms. */
+ r=c=0.0;
+ for (j=1;j<=n;j++)
+ if (j != i) {
+ c += fabs (a[j][i]);
+ r += fabs (a[i][j]);
+ }
+ if (c && r) { /* If both are nonzero, */
+ g=r/RADIX;
+ f=1.0;
+ s=c+r;
+ while (c<g) { /* find the integer power of the machine radix that */
+ f *= RADIX; /* comes closest to balancing the matrix. */
+ c *= sqrdx;
+ }
+ g=r*RADIX;
+ while (c>g) {
+ f /= RADIX;
+ c /= sqrdx;
+ }
+ if ((c+r)/f < 0.95*s) {
+ last=0;
+ g=1.0/f;
+ for (j=1;j<=n;j++)
+ a[i][j] *= g; /* Apply similarity transformation */
+ for (j=1;j<=n;j++) a[j][i] *= f;
+ }
+ }
+ }
+ }
+}
+
+#define MAX_DEGREE 50
+
+static void
+zrhqr (double a[], int m, double rtr[], double rti[])
+ /* Find all the roots of a polynomial with real coefficients, E(i=0..m) a(i)x^i, given the degree m
+ and the coefficients a[0..m]. The method is to construct an upper Hessenberg matrix whose
+ eigenvalues are the desired roots, and then use the routines balanc and hqr. The real and
+ imaginary parts of the roots are returned in rtr[1..m] and rti[1..m], respectively. */
+{
+ int j,k;
+ double **hess,xr,xi;
+
+ hess=matrix (1,MAX_DEGREE,1,MAX_DEGREE);
+ if (m > MAX_DEGREE || a[m] == 0.0 || /* TIMJ: */ fabs (a[m]) < 1e-15 )
+ nrerror ("bad args in zrhqr");
+ for (k=1;k<=m;k++) /* Construct the matrix. */
+ {
+ hess[1][k] = -a[m-k]/a[m];
+ for (j=2;j<=m;j++)
+ hess[j][k]=0.0;
+ if (k != m)
+ hess[k+1][k]=1.0;
+ }
+ balanc (hess,m); /* Find its eigenvalues. */
+ hqr (hess,m,rtr,rti);
+ if (0) /* TIMJ: don't need sorting */
+ for (j=2;j<=m;j++)
+ { /* Sort roots by their real parts by straight insertion. */
+ xr=rtr[j];
+ xi=rti[j];
+ for (k=j-1;k>=1;k--)
+ {
+ if (rtr[k] <= xr)
+ break;
+ rtr[k+1]=rtr[k];
+ rti[k+1]=rti[k];
+ }
+ rtr[k+1]=xr;
+ rti[k+1]=xi;
+ }
+ free_matrix (hess,1,MAX_DEGREE,1,MAX_DEGREE);
+}
+
+
+#define EPSS 2.0e-16 /* TIMJ, was(float): 1.0e-7 */
+#define MR 8
+#define MT 100 /* TIMJ: was: 10 */
+#define MAXIT (MT*MR)
+/* Here EPSS is the estimated fractional roundoff error. We try to break (rare) limit cycles with
+ MR different fractional values, once every MT steps, for MAXIT total allowed iterations. */
+
+static void
+laguer (GslComplex a[], int m, GslComplex *x, int *its)
+ /* Given the degree m and the m+1 complex coefficients a[0..m] of the polynomial mi=0 a[i]xi,
+ and given a complex value x, this routine improves x by Laguerre's method until it converges,
+ within the achievable roundoff limit, to a root of the given polynomial. The number of iterations
+ taken is returned as its. */
+{
+ int iter,j;
+ double abx,abp,abm,err;
+ GslComplex dx,x1,b,d,f,g,h,sq,gp,gm,g2;
+ static double frac[MR+1] = {0.0,0.5,0.25,0.75,0.13,0.38,0.62,0.88,1.0};
+ /* Fractions used to break a limit cycle. */
+
+ for (iter=1;iter<=MAXIT;iter++)
+ { /* Loop over iterations up to allowed maximum. */
+ *its=iter;
+ b=a[m];
+ err=gsl_complex_abs (b);
+ d=f=gsl_complex (0.0,0.0);
+ abx=gsl_complex_abs (*x);
+ for (j=m-1;j>=0;j--)
+ { /* Efficient computation of the polynomial and */
+ f=gsl_complex_add (gsl_complex_mul (*x,f),d); /* its first two derivatives. */
+ d=gsl_complex_add (gsl_complex_mul (*x,d),b);
+ b=gsl_complex_add (gsl_complex_mul (*x,b),a[j]);
+ err=gsl_complex_abs (b)+abx*err;
+ }
+ err *= EPSS;
+ /* Estimate of roundoff error in evaluating polynomial. */
+ if (gsl_complex_abs (b) <= err)
+ return; /* We are on the root. */
+ g=gsl_complex_div (d,b); /* The generic case: use Laguerre's formula. */
+ g2=gsl_complex_mul (g,g);
+ h=gsl_complex_sub (g2,gsl_complex_rmul (2.0,gsl_complex_div (f,b)));
+ sq=gsl_complex_sqrt (gsl_complex_rmul ((double) (m-1),gsl_complex_sub (gsl_complex_rmul ((double) m,h),g2)));
+ gp=gsl_complex_add (g,sq);
+ gm=gsl_complex_sub (g,sq);
+ abp=gsl_complex_abs (gp);
+ abm=gsl_complex_abs (gm);
+ if (abp < abm)
+ gp=gm;
+ dx=((DMAX (abp,abm) > 0.0 ? gsl_complex_div (gsl_complex ((double) m,0.0),gp)
+ : gsl_complex_rmul (1+abx,gsl_complex (cos ((double)iter),sin ((double)iter)))));
+ x1=gsl_complex_sub (*x,dx);
+ if (x->re == x1.re && x->im == x1.im)
+ return; /* Converged. */
+ if (iter % MT) *x=x1;
+ else *x=gsl_complex_sub (*x,gsl_complex_rmul (frac[iter/MT],dx));
+ /* Every so often we take a fractional step, to break any limit cycle (itself a rare occurrence). */
+ }
+ nrerror ("too many iterations in laguer");
+ /* Very unusual - can occur only for complex roots. Try a different starting guess for the root. */
+}
+
+/* Here is a driver routine that calls laguer in succession for each root, performs
+ the deflation, optionally polishes the roots by the same Laguerre method - if you
+ are not going to polish in some other way - and finally sorts the roots by their real
+ parts. (We will use this routine in Chapter 13.) */
+
+#define EPS 4.0e-15 /* TIMJ, was(float): 2.0e-6 */
+#define MAXM 100
+/* A small number, and maximum anticipated value of m. */
+
+static void
+zroots (GslComplex a[], int m, GslComplex roots[], int polish)
+ /* Given the degree m and the m+1 complex coefficients a[0..m] of the polynomial mi=0 a (i)xi,
+ this routine successively calls laguer and finds all m complex roots in roots[1..m]. The
+ boolean variable polish should be input as true (1) if polishing (also by Laguerre's method)
+ is desired, false (0) if the roots will be subsequently polished by other means. */
+{
+ int i,its,j,jj;
+ GslComplex x,b,c,ad[MAXM];
+
+ for (j=0;j<=m;j++) ad[j]=a[j]; /* Copy of coefficients for successive deflation. */
+ for (j=m;j>=1;j--) /* Loop over each root to be found. */
+ {
+ x=gsl_complex (0.0,0.0); /* Start at zero to favor convergence to small- */
+ laguer (ad,j,&x,&its); /* est remaining root, and find the root. */
+ if (fabs (x.im) <= 2.0*EPS*fabs (x.re))
+ x.im=0.0;
+ roots[j]=x;
+ b=ad[j]; /* Forward deflation. */
+ for (jj=j-1;jj>=0;jj--)
+ {
+ c=ad[jj];
+ ad[jj]=b;
+ b=gsl_complex_add (gsl_complex_mul (x,b),c);
+ }
+ }
+ if (polish)
+ for (j=1;j<=m;j++) /* Polish the roots using the undeflated coeffi- */
+ laguer (a,m,&roots[j],&its); /* cients. */
+ for (j=2;j<=m;j++) /* Sort roots by their real parts by straight insertion */
+ {
+ x=roots[j];
+ for (i=j-1;i>=1;i--) {
+ if (roots[i].re <= x.re)
+ break;
+ roots[i+1]=roots[i];
+ }
+ roots[i+1]=x;
+ }
+}
+
+#define ITMAX 20 /* At most ITMAX iterations. */
+#define TINY 2.0-15 /* TIMJ, was (float): 1.0e-6 */
+
+static void
+qroot (double p[], int n, double *b, double *c, double eps)
+ /* Given n+1 coefficients p[0..n] of a polynomial of degree n, and trial values for the coefficients
+ of a quadratic factor x*x+b*x+c, improve the solution until the coefficients b,c change by less
+ than eps. The routine poldiv §5.3 is used. */
+{
+ int iter;
+ double sc,sb,s,rc,rb,r,dv,delc,delb;
+ double *q,*qq,*rem;
+ double d[3];
+
+ q=vector (0,n);
+ qq=vector (0,n);
+ rem=vector (0,n);
+ d[2]=1.0;
+ for (iter=1;iter<=ITMAX;iter++)
+ {
+ d[1]=(*b);
+ d[0]=(*c);
+ poldiv (p,n,d,2,q,rem);
+ s=rem[0]; /* First division r,s. */
+ r=rem[1];
+ poldiv (q,(n-1),d,2,qq,rem);
+ sb = -(*c)*(rc = -rem[1]); /* Second division partial r,s with respect to */
+ rb = -(*b)*rc+(sc = -rem[0]); /* c. */
+ dv=1.0/(sb*rc-sc*rb); /* Solve 2x2 equation. */
+ delb=(r*sc-s*rc)*dv;
+ delc=(-r*sb+s*rb)*dv;
+ *b += (delb=(r*sc-s*rc)*dv);
+ *c += (delc=(-r*sb+s*rb)*dv);
+ if ((fabs (delb) <= eps*fabs (*b) || fabs (*b) < TINY)
+ && (fabs (delc) <= eps*fabs (*c) || fabs (*c) < TINY))
+ {
+ free_vector (rem,0,n); /* Coefficients converged. */
+ free_vector (qq,0,n);
+ free_vector (q,0,n);
+ return;
+ }
+ }
+ nrerror ("Too many iterations in routine qroot");
+}
+
+#define SNCNDN_CA 0.0003 /* The accuracy is the square of SNCNDN_CA. */
+static void
+sncndn (double uu, double emmc, double *sn_p, double *cn_p, double *dn_p)
+ /* Returns the Jacobian elliptic functions sn(u, kc), cn(u, kc), and dn(u, kc). Here uu = u, while
+ emmc = k2c. */
+{
+ double a,b,c,d,emc,u,sn,cn,dn;
+ double em[14],en[14];
+ int i,ii,l,bo;
+ d=0; /* TIMJ: shutup compiler */
+
+ emc=emmc;
+ u=uu;
+ if (emc) {
+ bo=(emc < 0.0);
+ if (bo) {
+ d=1.0-emc;
+ emc /= -1.0/d;
+ u *= (d=sqrt(d));
+ }a=1.0;
+ dn=1.0;
+ for (i=1;i<=13;i++) {
+ l=i;
+ em[i]=a;
+ en[i]=(emc=sqrt(emc));
+ c=0.5*(a+emc);
+ if (fabs(a-emc) <= SNCNDN_CA*a) break;
+ emc *= a;
+ a=c;
+ }u *= c;
+ sn=sin(u);
+ cn=cos(u);
+ if (sn) {
+ a=cn/sn;
+ c *= a;
+ for (ii=l;ii>=1;ii--) {
+ b=em[ii];
+ a *= c;
+ c *= dn;
+ dn=(en[ii]+a)/(b+a);
+ a=c/b;
+ }a=1.0/sqrt(c*c+1.0);
+ sn=(sn >= 0.0 ? a : -a);
+ cn=c*sn;
+ }if (bo) {
+ a=dn;
+ dn=cn;
+ cn=a;
+ sn /= d;
+ }
+ } else {
+ cn=1.0/cosh(u);
+ dn=cn;
+ sn=tanh(u);
+ }
+ if (sn_p)
+ *sn_p = sn;
+ if (cn_p)
+ *cn_p = cn;
+ if (dn_p)
+ *dn_p = dn;
+}
+
+static void
+sncndnC (GslComplex uu, GslComplex emmc, GslComplex *sn_p, GslComplex *cn_p, GslComplex *dn_p)
+{
+ GslComplex a,b,c,d,emc,u,sn,cn,dn;
+ GslComplex em[14],en[14];
+ int i,ii,l,bo;
+
+ emc=emmc;
+ u=uu;
+ if (emc.re || emc.im) /* gsl_complex_abs (emc)) */
+ {
+ /* bo=gsl_complex_abs (emc) < 0.0; */
+ bo=emc.re < 0.0;
+ if (bo) {
+ d=gsl_complex_sub (ONE, emc);
+ emc = gsl_complex_div (emc, gsl_complex_div (gsl_complex (-1.0, 0), d));
+ d = gsl_complex_sqrt (d);
+ u = gsl_complex_mul (u, d);
+ }
+ a=ONE; dn=ONE;
+ for (i=1;i<=13;i++) {
+ l=i;
+ em[i]=a;
+ emc = gsl_complex_sqrt (emc);
+ en[i]=emc;
+ c = gsl_complex_mul (gsl_complex (0.5, 0), gsl_complex_add (a, emc));
+ if (gsl_complex_abs (gsl_complex_sub (a, emc)) <=
+ gsl_complex_abs (gsl_complex_mul (gsl_complex (SNCNDN_CA, 0), a)))
+ break;
+ emc = gsl_complex_mul (emc, a);
+ a=c;
+ }
+ u = gsl_complex_mul (u, c);
+ sn = gsl_complex_sin (u);
+ cn = gsl_complex_cos (u);
+ if (sn.re) /* gsl_complex_abs (sn)) */
+ {
+ a= gsl_complex_div (cn, sn);
+ c = gsl_complex_mul (c, a);
+ for (ii=l;ii>=1;ii--) {
+ b = em[ii];
+ a = gsl_complex_mul (a, c);
+ c = gsl_complex_mul (c, dn);
+ dn = gsl_complex_div (gsl_complex_add (en[ii], a), gsl_complex_add (b, a));
+ a = gsl_complex_div (c, b);
+ }
+ a = gsl_complex_div (ONE, gsl_complex_sqrt (gsl_complex_add (ONE, gsl_complex_mul (c, c))));
+ if (sn.re >= 0.0) /* gsl_complex_arg (sn) >= 0.0) */
+ sn = a;
+ else
+ {
+ sn.re = -a.re;
+ sn.im = a.im;
+ }
+ cn = gsl_complex_mul (c, sn);
+ }
+ if (bo) {
+ a=dn;
+ dn=cn;
+ cn=a;
+ sn = gsl_complex_div (sn, d);
+ }
+ } else {
+ cn=gsl_complex_div (ONE, gsl_complex_cosh (u));
+ dn=cn;
+ sn=gsl_complex_tanh (u);
+ }
+ if (sn_p)
+ *sn_p = sn;
+ if (cn_p)
+ *cn_p = cn;
+ if (dn_p)
+ *dn_p = dn;
+}
+
+#define RF_ERRTOL 0.0025 /* TIMJ, was(float): 0.08 */
+#define RF_TINY 2.2e-307 /* TIMJ, was(float): 1.5e-38 */
+#define RF_BIG 1.5e+307 /* TIMJ, was(float): 3.0e37 */
+#define RF_THIRD (1.0/3.0)
+#define RF_C1 (1.0/24.0)
+#define RF_C2 0.1
+#define RF_C3 (3.0/44.0)
+#define RF_C4 (1.0/14.0)
+
+static double
+rf (double x, double y, double z)
+ /* Computes Carlson's elliptic integral of the first kind, RF (x, y, z). x, y, and z must be nonneg-
+ ative, and at most one can be zero. RF_TINY must be at least 5 times the machine underflow limit,
+ RF_BIG at most one fifth the machine overflow limit. */
+{
+ double alamb,ave,delx,dely,delz,e2,e3,sqrtx,sqrty,sqrtz,xt,yt,zt;
+
+ if (1 /* TIMJ: add verbose checks */)
+ {
+ if (DMIN (DMIN (x, y), z) < 0.0)
+ nrerror ("rf: x,y,z have to be positive");
+ if (DMIN (DMIN (x + y, x + z), y + z) < RF_TINY)
+ nrerror ("rf: only one of x,y,z may be 0");
+ if (DMAX (DMAX (x, y), z) > RF_BIG)
+ nrerror ("rf: at least one of x,y,z is too big");
+ }
+ if (DMIN(DMIN(x,y),z) < 0.0 || DMIN(DMIN(x+y,x+z),y+z) < RF_TINY ||
+ DMAX(DMAX(x,y),z) > RF_BIG)
+ nrerror("invalid arguments in rf");
+ xt=x;
+ yt=y;
+ zt=z;
+ do {
+ sqrtx=sqrt(xt);
+ sqrty=sqrt(yt);
+ sqrtz=sqrt(zt);
+ alamb=sqrtx*(sqrty+sqrtz)+sqrty*sqrtz;
+ xt=0.25*(xt+alamb);
+ yt=0.25*(yt+alamb);
+ zt=0.25*(zt+alamb);
+ ave=RF_THIRD*(xt+yt+zt);
+ delx=(ave-xt)/ave;
+ dely=(ave-yt)/ave;
+ delz=(ave-zt)/ave;
+ } while (DMAX(DMAX(fabs(delx),fabs(dely)),fabs(delz)) > RF_ERRTOL);
+ e2=delx*dely-delz*delz;
+ e3=delx*dely*delz;
+ return (1.0+(RF_C1*e2-RF_C2-RF_C3*e3)*e2+RF_C4*e3)/sqrt(ave);
+}
+
+static GslComplex
+rfC (GslComplex x, GslComplex y, GslComplex z)
+{
+ GslComplex alamb,ave,delx,dely,delz,e2,e3,sqrtx,sqrty,sqrtz,xt,yt,zt;
+ GslComplex RFC_C1 = {1.0/24.0, 0}, RFC_C2 = {0.1, 0}, RFC_C3 = {3.0/44.0, 0}, RFC_C4 = {1.0/14.0, 0};
+
+ if (DMIN (DMIN (gsl_complex_abs (x), gsl_complex_abs (y)), gsl_complex_abs (z)) < 0.0)
+ nrerror ("rf: x,y,z have to be positive");
+ if (DMIN (DMIN (gsl_complex_abs (x) + gsl_complex_abs (y), gsl_complex_abs (x) + gsl_complex_abs (z)),
+ gsl_complex_abs (y) + gsl_complex_abs (z)) < RF_TINY)
+ nrerror ("rf: only one of x,y,z may be 0");
+ if (DMAX (DMAX (gsl_complex_abs (x), gsl_complex_abs (y)), gsl_complex_abs (z)) > RF_BIG)
+ nrerror ("rf: at least one of x,y,z is too big");
+ xt=x;
+ yt=y;
+ zt=z;
+ do {
+ sqrtx = gsl_complex_sqrt (xt);
+ sqrty = gsl_complex_sqrt (yt);
+ sqrtz = gsl_complex_sqrt (zt);
+ alamb = gsl_complex_add (gsl_complex_mul (sqrtx, gsl_complex_add (sqrty, sqrtz)), gsl_complex_mul (sqrty, sqrtz));
+ xt = gsl_complex_mul (gsl_complex (0.25, 0), gsl_complex_add (xt, alamb));
+ yt = gsl_complex_mul (gsl_complex (0.25, 0), gsl_complex_add (yt, alamb));
+ zt = gsl_complex_mul (gsl_complex (0.25, 0), gsl_complex_add (zt, alamb));
+ ave = gsl_complex_mul (gsl_complex (RF_THIRD, 0), gsl_complex_add3 (xt, yt, zt));
+ delx = gsl_complex_div (gsl_complex_sub (ave, xt), ave);
+ dely = gsl_complex_div (gsl_complex_sub (ave, yt), ave);
+ delz = gsl_complex_div (gsl_complex_sub (ave, zt), ave);
+ /* } while (DMAX (DMAX (fabs (delx.re), fabs (dely.re)), fabs (delz.re)) > RF_ERRTOL); */
+ } while (DMAX (DMAX (gsl_complex_abs (delx), gsl_complex_abs (dely)), gsl_complex_abs (delz)) > RF_ERRTOL);
+ e2 = gsl_complex_sub (gsl_complex_mul (delx, dely), gsl_complex_mul (delz, delz));
+ e3 = gsl_complex_mul3 (delx, dely, delz);
+ return gsl_complex_div (gsl_complex_add3 (gsl_complex (1.0, 0),
+ gsl_complex_mul (e2,
+ gsl_complex_sub3 (gsl_complex_mul (RFC_C1, e2),
+ RFC_C2,
+ gsl_complex_mul (RFC_C3, e3))),
+ gsl_complex_mul (RFC_C4, e3)),
+ gsl_complex_sqrt (ave));
+}
+
+
+static double
+ellf (double phi, double ak)
+ /* Legendre elliptic integral of the 1st kind F(phi, k), evaluated using Carlson's function RF.
+ The argument ranges are 0 <= phi <= pi/2, 0 <= k*sin(phi) <= 1. */
+{
+ double s=sin(phi);
+ return s*rf(DSQR(cos(phi)),(1.0-s*ak)*(1.0+s*ak),1.0);
+}
diff --git a/flow/gsl/gslmath.h b/flow/gsl/gslmath.h
new file mode 100644
index 0000000..b690a54
--- /dev/null
+++ b/flow/gsl/gslmath.h
@@ -0,0 +1,518 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_MATH_H__
+#define __GSL_MATH_H__
+
+#include <gsl/gslieee754.h>
+#include <gsl/gsldefs.h>
+#include <math.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- constants --- */
+#define GSL_PI (3.1415926535897932384626433832795029 /* pi */)
+#define GSL_PI_DIV_2 (1.5707963267948966192313216916397514 /* pi/2 */)
+#define GSL_PI_DIV_4 (0.7853981633974483096156608458198757 /* pi/4 */)
+#define GSL_1_DIV_PI (0.3183098861837906715377675267450287 /* 1/pi */)
+#define GSL_2_DIV_PI (0.6366197723675813430755350534900574 /* 2/pi */)
+#define GSL_2_DIV_SQRT_PI (1.1283791670955125738961589031215452 /* 2/sqrt(pi) */)
+#define GSL_SQRT2 (1.4142135623730950488016887242096981 /* sqrt(2) */)
+#define GSL_1_DIV_SQRT2 (0.7071067811865475244008443621048490 /* 1/sqrt(2) */)
+#define GSL_E (2.7182818284590452353602874713526625 /* e */)
+#define GSL_LOG2E (1.4426950408889634073599246810018922 /* log_2(e) */)
+#define GSL_LOG10E (0.4342944819032518276511289189166051 /* log_10(e) */)
+#define GSL_LN2 (0.6931471805599453094172321214581766 /* ln(2) */)
+#define GSL_LN10 (2.3025850929940456840179914546843642 /* ln(10) */)
+#define GSL_2_POW_1_DIV_12 (1.0594630943592952645618252949463417 /* 2^(1/12) */)
+#define GSL_2_POW_1_DIV_72 (1.0096735332285108621925214011186051 /* 2^(1/72) */)
+#define GSL_LN_2_POW_1_DIV_12 (0.0577622650466621091181026767881814 /* ln(2^(1/12)) */)
+#define GSL_LN_2_POW_1_DIV_72 (0.0096270441744436848530171127980302 /* ln(2^(1/72)) */)
+#define GSL_LOG2_10 (3.3219280948873623478703194294893902 /* log_2(10) */)
+#define GSL_LOG2POW20_10 (0.1660964047443681173935159714744695 /* log_2(10)/20 */)
+
+
+/* --- structures --- */
+struct _GslComplex
+{
+ double re;
+ double im;
+};
+
+
+/* --- float/double signbit extraction --- */
+#ifdef signbit
+# define gsl_float_sign(dblflt) (signbit (dblflt))
+#else
+# define gsl_float_sign(dblflt) ((dblflt) < -0.0) /* good enough for us */
+#endif
+
+
+/* --- complex numbers --- */
+static inline GslComplex gsl_complex (double re,
+ double im);
+static inline GslComplex gsl_complex_polar (double abs,
+ double arg);
+static inline GslComplex gsl_complex_add (GslComplex c1,
+ GslComplex c2);
+static inline GslComplex gsl_complex_add3 (GslComplex c1,
+ GslComplex c2,
+ GslComplex c3);
+static inline GslComplex gsl_complex_sub (GslComplex c1,
+ GslComplex c2);
+static inline GslComplex gsl_complex_sub3 (GslComplex c1,
+ GslComplex c2,
+ GslComplex c3);
+static inline GslComplex gsl_complex_scale (GslComplex c1,
+ double scale);
+static inline GslComplex gsl_complex_mul (GslComplex c1,
+ GslComplex c2);
+static inline GslComplex gsl_complex_mul3 (GslComplex c1,
+ GslComplex c2,
+ GslComplex c3);
+static inline GslComplex gsl_complex_div (GslComplex a,
+ GslComplex b);
+static inline GslComplex gsl_complex_reciprocal (GslComplex c);
+static inline GslComplex gsl_complex_sqrt (GslComplex z);
+static inline GslComplex gsl_complex_conj (GslComplex c); /* {re, -im} */
+static inline GslComplex gsl_complex_id (GslComplex c);
+static inline GslComplex gsl_complex_inv (GslComplex c); /* {-re, -im} */
+static inline double gsl_complex_abs (GslComplex c);
+static inline double gsl_complex_arg (GslComplex c);
+static inline GslComplex gsl_complex_sin (GslComplex c);
+static inline GslComplex gsl_complex_cos (GslComplex c);
+static inline GslComplex gsl_complex_tan (GslComplex c);
+static inline GslComplex gsl_complex_sinh (GslComplex c);
+static inline GslComplex gsl_complex_cosh (GslComplex c);
+static inline GslComplex gsl_complex_tanh (GslComplex c);
+char* gsl_complex_str (GslComplex c);
+char* gsl_complex_list (unsigned int n_points,
+ GslComplex *points,
+ const char *indent);
+void gsl_complex_gnuplot (const char *file_name,
+ unsigned int n_points,
+ GslComplex *points);
+
+
+/* --- polynomials --- */
+/* example, degree=2: 5+2x+7x^2 => a[0..degree] = { 5, 2, 7 } */
+static inline void gsl_poly_add (unsigned int degree,
+ double *a, /* a[0..degree] */
+ double *b);
+static inline void gsl_poly_sub (unsigned int order,
+ double *a, /* [0..degree] */
+ double *b);
+static inline void gsl_poly_mul (double *p, /* out:[0..aorder+border] */
+ unsigned int aorder,
+ const double *a, /* in:[0..aorder] */
+ unsigned int border,
+ const double *b); /* in:[0..border] */
+static inline void gsl_poly_scale (unsigned int order,
+ double *a, /* [0..degree] */
+ double scale);
+static inline void gsl_poly_xscale (unsigned int order,
+ double *a, /* [0..degree] */
+ double xscale);
+static inline double gsl_poly_eval (unsigned int degree,
+ double *a, /* [0..degree] */
+ double x);
+void gsl_poly_complex_roots (unsigned int poly_degree,
+ double *a, /* [0..degree] (degree+1 elements) */
+ GslComplex *roots); /* [degree] */
+void gsl_poly_from_re_roots (unsigned int poly_degree,
+ double *a, /* [0..degree] */
+ GslComplex *roots);
+void gsl_cpoly_from_roots (unsigned int poly_degree,
+ GslComplex *c, /* [0..degree] */
+ GslComplex *roots);
+static inline void gsl_cpoly_mul_monomial (unsigned int degree, /* _new_ degree */
+ GslComplex *c, /* in:[0..degree-1] out:[0..degree] */
+ GslComplex root); /* c(x) *= (x^1 - root) */
+static inline void gsl_cpoly_mul_reciprocal (unsigned int degree, /* _new_ degree */
+ GslComplex *c, /* in:[0..degree-1] out:[0..degree] */
+ GslComplex root); /* c(x) *= (1 - root * x^-1) */
+static inline void gsl_cpoly_mul (GslComplex *p, /* out:[0..aorder+border] */
+ unsigned int aorder,
+ GslComplex *a, /* in:[0..aorder] */
+ unsigned int border,
+ GslComplex *b); /* in:[0..border] */
+
+char* gsl_poly_str (unsigned int degree,
+ double *a,
+ const char *var);
+char* gsl_poly_str1 (unsigned int degree,
+ double *a,
+ const char *var);
+
+
+/* --- transformations --- */
+double gsl_temp_freq (double kammer_freq,
+ int halftone_delta);
+
+
+/* --- miscellaneous --- */
+double gsl_bit_depth_epsilon (guint n_bits); /* 1..32 */
+
+
+/* --- ellipses --- */
+double gsl_ellip_rf (double x,
+ double y,
+ double z);
+double gsl_ellip_F (double phi,
+ double ak);
+double gsl_ellip_sn (double u,
+ double emmc);
+double gsl_ellip_asn (double y,
+ double emmc);
+GslComplex gsl_complex_ellip_asn (GslComplex y,
+ GslComplex emmc);
+GslComplex gsl_complex_ellip_sn (GslComplex u,
+ GslComplex emmc);
+
+
+/* --- implementations --- */
+static inline GslComplex
+gsl_complex (double re,
+ double im)
+{
+ GslComplex r;
+ r.re = re;
+ r.im = im;
+ return r;
+}
+static inline GslComplex
+gsl_complex_polar (double abs,
+ double arg)
+{
+ return gsl_complex (abs * cos (arg), abs * sin (arg));
+}
+static inline GslComplex
+gsl_complex_add (GslComplex c1,
+ GslComplex c2)
+{
+ return gsl_complex (c1.re + c2.re, c1.im + c2.im);
+}
+static inline GslComplex
+gsl_complex_add3 (GslComplex c1,
+ GslComplex c2,
+ GslComplex c3)
+{
+ return gsl_complex (c1.re + c2.re + c3.re, c1.im + c2.im + c3.im);
+}
+static inline GslComplex
+gsl_complex_sub (GslComplex c1,
+ GslComplex c2)
+{
+ return gsl_complex (c1.re - c2.re, c1.im - c2.im);
+}
+static inline GslComplex
+gsl_complex_sub3 (GslComplex c1,
+ GslComplex c2,
+ GslComplex c3)
+{
+ return gsl_complex (c1.re - c2.re - c3.re, c1.im - c2.im - c3.im);
+}
+static inline GslComplex
+gsl_complex_scale (GslComplex c1,
+ double scale)
+{
+ return gsl_complex (c1.re * scale, c1.im * scale);
+}
+static inline GslComplex
+gsl_complex_mul (GslComplex c1,
+ GslComplex c2)
+{
+ return gsl_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
+}
+static inline GslComplex
+gsl_complex_mul3 (GslComplex c1,
+ GslComplex c2,
+ GslComplex c3)
+{
+ double aec = c1.re * c2.re * c3.re;
+ double bde = c1.im * c2.im * c3.re;
+ double adf = c1.re * c2.im * c3.im;
+ double bcf = c1.im * c2.re * c3.im;
+ double ade = c1.re * c2.im * c3.re;
+ double bce = c1.im * c2.re * c3.re;
+ double acf = c1.re * c2.re * c3.im;
+ double bdf = c1.im * c2.im * c3.im;
+
+ return gsl_complex (aec - bde - adf - bcf, ade + bce + acf - bdf);
+}
+static inline GslComplex
+gsl_complex_div (GslComplex a,
+ GslComplex b)
+{
+ GslComplex c;
+ if (fabs (b.re) >= fabs (b.im))
+ {
+ double r = b.im / b.re, den = b.re + r * b.im;
+ c.re = (a.re + r * a.im) / den;
+ c.im = (a.im - r * a.re) / den;
+ }
+ else
+ {
+ double r = b.re / b.im, den = b.im + r * b.re;
+ c.re = (a.re * r + a.im) / den;
+ c.im = (a.im * r - a.re) / den;
+ }
+ return c;
+}
+static inline GslComplex
+gsl_complex_reciprocal (GslComplex c)
+{
+ if (fabs (c.re) >= fabs (c.im))
+ {
+ double r = c.im / c.re, den = c.re + r * c.im;
+ c.re = 1. / den;
+ c.im = - r / den;
+ }
+ else
+ {
+ double r = c.re / c.im, den = c.im + r * c.re;
+ c.re = r / den;
+ c.im = - 1. / den;
+ }
+ return c;
+}
+static inline GslComplex
+gsl_complex_sqrt (GslComplex z)
+{
+ if (z.re == 0.0 && z.im == 0.0)
+ return z;
+ else
+ {
+ GslComplex c;
+ double w, x = fabs (z.re), y = fabs (z.im);
+ if (x >= y)
+ {
+ double r = y / x;
+ w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + r * r)));
+ }
+ else
+ {
+ double r = x / y;
+ w = sqrt (y) * sqrt (0.5 * (r + sqrt (1.0 + r * r)));
+ }
+ if (z.re >= 0.0)
+ {
+ c.re = w;
+ c.im = z.im / (2.0 * w);
+ }
+ else
+ {
+ c.im = z.im >= 0 ? w : -w;
+ c.re = z.im / (2.0 * c.im);
+ }
+ return c;
+ }
+}
+static inline GslComplex
+gsl_complex_conj (GslComplex c)
+{
+ return gsl_complex (c.re, -c.im);
+}
+static inline GslComplex
+gsl_complex_inv (GslComplex c)
+{
+ return gsl_complex (-c.re, -c.im);
+}
+static inline GslComplex
+gsl_complex_id (GslComplex c)
+{
+ return c;
+}
+static inline double
+gsl_complex_abs (GslComplex c)
+{
+ /* compute (a^2 + b^2)^(1/2) without destructive underflow or overflow */
+ double absa = fabs (c.re), absb = fabs (c.im);
+ return (absa > absb ?
+ absb == 0.0 ? absa :
+ absa * sqrt (1.0 + (absb / absa) * (absb / absa)) :
+ absb == 0.0 ? 0.0 :
+ absb * sqrt (1.0 + (absa / absb) * (absa / absb)));
+}
+static inline double
+gsl_complex_arg (GslComplex c)
+{
+ double a = atan2 (c.im, c.re);
+ return a;
+}
+static inline GslComplex
+gsl_complex_sin (GslComplex c)
+{
+ return gsl_complex (sin (c.re) * cosh (c.im), cos (c.re) * sinh (c.im));
+}
+static inline GslComplex
+gsl_complex_cos (GslComplex c)
+{
+ return gsl_complex (cos (c.re) * cosh (c.im), - sin (c.re) * sinh (c.im));
+}
+static inline GslComplex
+gsl_complex_tan (GslComplex c)
+{
+ return gsl_complex_div (gsl_complex (tan (c.re), tanh (c.im)),
+ gsl_complex (1.0, -tan (c.re) * tanh (c.im)));
+}
+static inline GslComplex
+gsl_complex_sinh (GslComplex c)
+{
+ return gsl_complex (sinh (c.re) * cos (c.im), cosh (c.re) * sin (c.im));
+}
+static inline GslComplex
+gsl_complex_cosh (GslComplex c)
+{
+ return gsl_complex (cosh (c.re) * cos (c.im), sinh (c.re) * sin (c.im));
+}
+static inline GslComplex
+gsl_complex_tanh (GslComplex c)
+{
+ return gsl_complex_div (gsl_complex_sinh (c),
+ gsl_complex_cosh (c));
+}
+static inline void
+gsl_poly_add (unsigned int degree,
+ double *a,
+ double *b)
+{
+ unsigned int i;
+
+ for (i = 0; i <= degree; i++)
+ a[i] += b[i];
+}
+static inline void
+gsl_poly_sub (unsigned int degree,
+ double *a,
+ double *b)
+{
+ unsigned int i;
+
+ for (i = 0; i <= degree; i++)
+ a[i] -= b[i];
+}
+static inline void
+gsl_poly_mul (double *p, /* out:[0..aorder+border] */
+ unsigned int aorder,
+ const double *a, /* in:[0..aorder] */
+ unsigned int border,
+ const double *b) /* in:[0..border] */
+{
+ unsigned int i;
+
+ for (i = aorder + border; i > 0; i--)
+ {
+ unsigned int j;
+ double t = 0;
+
+ for (j = i - MIN (border, i); j <= MIN (aorder, i); j++)
+ t += a[j] * b[i - j];
+ p[i] = t;
+ }
+ p[0] = a[0] * b[0];
+}
+static inline void
+gsl_cpoly_mul_monomial (unsigned int degree,
+ GslComplex *c,
+ GslComplex root)
+{
+ unsigned int j;
+
+ c[degree] = c[degree - 1];
+ for (j = degree - 1; j >= 1; j--)
+ c[j] = gsl_complex_sub (c[j - 1], gsl_complex_mul (c[j], root));
+ c[0] = gsl_complex_mul (c[0], gsl_complex_inv (root));
+}
+static inline void
+gsl_cpoly_mul_reciprocal (unsigned int degree,
+ GslComplex *c,
+ GslComplex root)
+{
+ unsigned int j;
+
+ c[degree] = gsl_complex_mul (c[degree - 1], gsl_complex_inv (root));
+ for (j = degree - 1; j >= 1; j--)
+ c[j] = gsl_complex_sub (c[j], gsl_complex_mul (c[j - 1], root));
+ /* c[0] = c[0]; */
+}
+static inline void
+gsl_cpoly_mul (GslComplex *p, /* [0..aorder+border] */
+ unsigned int aorder,
+ GslComplex *a,
+ unsigned int border,
+ GslComplex *b)
+{
+ unsigned int i;
+
+ for (i = aorder + border; i > 0; i--)
+ {
+ GslComplex t;
+ unsigned int j;
+
+ t = gsl_complex (0, 0);
+ for (j = i - MIN (i, border); j <= MIN (aorder, i); j++)
+ t = gsl_complex_add (t, gsl_complex_mul (a[j], b[i - j]));
+ p[i] = t;
+ }
+ p[0] = gsl_complex_mul (a[0], b[0]);
+}
+static inline void
+gsl_poly_scale (unsigned int degree,
+ double *a,
+ double scale)
+{
+ unsigned int i;
+
+ for (i = 0; i <= degree; i++)
+ a[i] *= scale;
+}
+static inline void
+gsl_poly_xscale (unsigned int degree,
+ double *a,
+ double xscale)
+{
+ double scale = xscale;
+ unsigned int i;
+
+ for (i = 1; i <= degree; i++)
+ {
+ a[i] *= scale;
+ scale *= xscale;
+ }
+}
+static inline double
+gsl_poly_eval (unsigned int degree,
+ double *a,
+ double x)
+{
+ double sum = a[degree];
+
+ while (degree--)
+ sum = sum * x + a[degree];
+ return sum;
+}
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_MATH_H__ */ /* vim: set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslmathtest.c b/flow/gsl/gslmathtest.c
new file mode 100644
index 0000000..55130aa
--- /dev/null
+++ b/flow/gsl/gslmathtest.c
@@ -0,0 +1,334 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 Stefan Westerfeld and Tim Janik
+ *
+ * This program 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 of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <gsl/gslmath.h>
+#include <gsl/gslfilter.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define PREC "15"
+
+static void
+usage (char *s)
+{
+ printf ("usage: gslmathtest %s\n", s);
+ exit (1);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ gchar *arg;
+
+ if (argc < 2)
+ goto abort;
+
+ if (strcmp (argv[1], "rf") == 0)
+ {
+ double x, y, z;
+ if (argc != 5)
+ usage ("rf <x> <y> <z>");
+ x = atof (argv[2]);
+ y = atof (argv[3]);
+ z = atof (argv[4]);
+
+ printf ("rf(%f, %f, %f) = %."PREC"f\n", x, y, z, gsl_ellip_rf (x, y, z));
+ }
+ else if (strcmp (argv[1], "F") == 0)
+ {
+ double phi, ak;
+ if (argc != 4)
+ usage ("F <phi> <ak>");
+ phi = atof (argv[2]);
+ ak = atof (argv[3]);
+
+ printf ("F(%f, %f) = %."PREC"f\n", phi, ak, gsl_ellip_F (phi, ak));
+ }
+ else if (strcmp (argv[1], "sn") == 0)
+ {
+ double u, emmc;
+ if (argc != 4)
+ usage ("sn <u> <emmc>");
+ u = atof (argv[2]);
+ emmc = atof (argv[3]);
+
+ printf ("sn(%f, %f) = %."PREC"f\n", u, emmc, gsl_ellip_sn (u, emmc));
+ }
+ else if (strcmp (argv[1], "snc") == 0)
+ {
+ GslComplex u, emmc;
+ if (argc != 6)
+ usage ("sn <u.re> <u.im> <emmc.re> <emmc.im>");
+ u.re = atof (argv[2]);
+ u.im = atof (argv[3]);
+ emmc.re = atof (argv[4]);
+ emmc.im = atof (argv[5]);
+
+ printf ("snc(%s, %s) = %s\n",
+ gsl_complex_str (u),
+ gsl_complex_str (emmc),
+ gsl_complex_str (gsl_complex_ellip_sn (u, emmc)));
+ }
+ else if (strcmp (argv[1], "sci_snc") == 0)
+ {
+ GslComplex u, k2;
+ if (argc != 6)
+ usage ("sci_sn <u.re> <u.im> <k2.re> <k2.im>");
+ u.re = atof (argv[2]);
+ u.im = atof (argv[3]);
+ k2.re = atof (argv[4]);
+ k2.im = atof (argv[5]);
+
+ printf ("sci_snc(%s, %s) = %s\n",
+ gsl_complex_str (u),
+ gsl_complex_str (k2),
+ gsl_complex_str (gsl_complex_ellip_sn (u, gsl_complex_sub (gsl_complex (1.0, 0), k2))));
+ }
+ else if (strcmp (argv[1], "asn") == 0)
+ {
+ double y, emmc;
+ if (argc != 4)
+ usage ("asn <y> <emmc>");
+ y = atof (argv[2]);
+ emmc = atof (argv[3]);
+
+ printf ("asn(%f, %f) = %."PREC"f\n", y, emmc, gsl_ellip_asn (y, emmc));
+ }
+ else if (strcmp (argv[1], "asnc") == 0)
+ {
+ GslComplex y, emmc;
+ if (argc != 6)
+ usage ("asnc <y.re> <y.im> <emmc.re> <emmc.im>");
+ y.re = atof (argv[2]);
+ y.im = atof (argv[3]);
+ emmc.re = atof (argv[4]);
+ emmc.im = atof (argv[5]);
+
+ printf ("asnc(%s, %s) = %s\n",
+ gsl_complex_str (y), gsl_complex_str (emmc),
+ gsl_complex_str (gsl_complex_ellip_asn (y, emmc)));
+ printf ("asn(%f, %f = %."PREC"f\n",
+ y.re, emmc.re, gsl_ellip_asn (y.re, emmc.re));
+ }
+ else if (strcmp (argv[1], "sci_sn") == 0)
+ {
+ double u, k2;
+ if (argc != 4)
+ usage ("sci_sn <u> <k2>");
+ u = atof (argv[2]);
+ k2 = atof (argv[3]);
+
+ printf ("sci_sn(%f, %f) = %."PREC"f\n", u, k2, gsl_ellip_sn (u, 1.0 - k2));
+ }
+ else if (strcmp (argv[1], "sci_asn") == 0)
+ {
+ double y, k2;
+ if (argc != 4)
+ usage ("sci_asn <y> <k2>");
+ y = atof (argv[2]);
+ k2 = atof (argv[3]);
+
+ printf ("sci_asn(%f, %f) = %."PREC"f\n", y, k2, gsl_ellip_asn (y, 1.0 - k2));
+ }
+ else if (strcmp (argv[1], "sci_asnc") == 0)
+ {
+ GslComplex y, k2;
+ if (argc != 6)
+ usage ("sci_asnc <y.re> <y.im> <k2.re> <k2.im>");
+ y.re = atof (argv[2]);
+ y.im = atof (argv[3]);
+ k2.re = atof (argv[4]);
+ k2.im = atof (argv[5]);
+
+ printf ("sci_asnc(%s, %s) = %s\n",
+ gsl_complex_str (y), gsl_complex_str (k2),
+ gsl_complex_str (gsl_complex_ellip_asn (y, gsl_complex_sub (gsl_complex (1.0, 0), k2))));
+ printf ("asn(%f, %f = %."PREC"f\n",
+ y.re, k2.re, gsl_ellip_asn (y.re, 1.0 - k2.re));
+ }
+ else if (strcmp (argv[1], "sin") == 0)
+ {
+ GslComplex phi;
+ if (argc != 4)
+ usage ("sin <phi.re> <phi.im>");
+ phi.re = atof (argv[2]);
+ phi.im = atof (argv[3]);
+
+ printf ("sin(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_sin (phi)));
+ }
+ else if (strcmp (argv[1], "cos") == 0)
+ {
+ GslComplex phi;
+ if (argc != 4)
+ usage ("cos <phi.re> <phi.im>");
+ phi.re = atof (argv[2]);
+ phi.im = atof (argv[3]);
+
+ printf ("cos(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_cos (phi)));
+ }
+ else if (strcmp (argv[1], "tan") == 0)
+ {
+ GslComplex phi;
+ if (argc != 4)
+ usage ("tan <phi.re> <phi.im>");
+ phi.re = atof (argv[2]);
+ phi.im = atof (argv[3]);
+
+ printf ("tan(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_tan (phi)));
+ }
+ else if (strcmp (argv[1], "sinh") == 0)
+ {
+ GslComplex phi;
+ if (argc != 4)
+ usage ("sinh <phi.re> <phi.im>");
+ phi.re = atof (argv[2]);
+ phi.im = atof (argv[3]);
+
+ printf ("sinh(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_sinh (phi)));
+ }
+ else if (strcmp (argv[1], "cosh") == 0)
+ {
+ GslComplex phi;
+ if (argc != 4)
+ usage ("cosh <phi.re> <phi.im>");
+ phi.re = atof (argv[2]);
+ phi.im = atof (argv[3]);
+
+ printf ("cosh(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_cosh (phi)));
+ }
+ else if (strcmp (argv[1], "tanh") == 0)
+ {
+ GslComplex phi;
+ if (argc != 4)
+ usage ("tanh <phi.re> <phi.im>");
+ phi.re = atof (argv[2]);
+ phi.im = atof (argv[3]);
+
+ printf ("tanh(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_tanh (phi)));
+ }
+ else if (strcmp (argv[1], "t1") == 0)
+ {
+ guint order;
+ double f, e;
+ if (argc != 5)
+ usage ("t1 <order> <freq> <epsilon>");
+ order = atoi (argv[2]);
+ f = atof (argv[3]);
+ e = atof (argv[4]);
+ f *= GSL_PI / 2.;
+ e = gsl_trans_zepsilon2ss (e);
+ {
+ double a[order + 1], b[order + 1];
+ gsl_filter_tscheb1 (order, f, e, a, b);
+ g_print ("# Tschebyscheff Type1 order=%u freq=%f s^2epsilon=%f norm0=%f:\n",
+ order, f, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ g_print ("H%u(z)=%s/%s\n", order,
+ gsl_poly_str (order, a, "z"),
+ gsl_poly_str (order, b, "z"));
+ }
+ }
+ else if (strcmp (argv[1], "t2") == 0)
+ {
+ guint order;
+ double fc, fr, e;
+ if (argc != 6)
+ usage ("t1 <order> <freqc> <freqr> <epsilon>");
+ order = atoi (argv[2]);
+ fc = atof (argv[3]);
+ fr = atof (argv[4]);
+ e = atof (argv[5]);
+ fc *= GSL_PI / 2.;
+ fr *= GSL_PI / 2.;
+ e = gsl_trans_zepsilon2ss (e);
+ {
+ double a[order + 1], b[order + 1];
+ gsl_filter_tscheb2 (order, fc, fr, e, a, b);
+ g_print ("# Tschebyscheff Type2 order=%u freq_c=%f freq_r=%f s^2epsilon=%f norm=%f:\n",
+ order, fc, fr, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ g_print ("H%u(z)=%s/%s\n", order,
+ gsl_poly_str (order, a, "z"),
+ gsl_poly_str (order, b, "z"));
+ }
+ }
+ else if (strncmp (argv[1], "test", 4) == 0)
+ {
+ guint order;
+ arg = argv[1] + 4;
+ if (argc != argc)
+ usage ("test");
+ order = 2;
+ {
+ double a[100] = { 1, 2, 1 }, b[100] = { 1, -3./2., 0.5 };
+ g_print ("# Test order=%u norm=%f:\n",
+ order,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ g_print ("H%u(z)=%s/%s\n", order,
+ gsl_poly_str (order, a, "z"),
+ gsl_poly_str (order, b, "z"));
+ if (*arg)
+ {
+ GslComplex root, roots[100];
+ guint i;
+
+ if (*arg == 'r')
+ {
+ g_print ("#roots:\n");
+ gsl_poly_complex_roots (order, a, roots);
+ for (i = 0; i < order; i++)
+ {
+ root = gsl_complex_div (gsl_complex (1, 0), roots[i]);
+ g_print ("%+.14f %+.14f # %.14f\n", root.re, root.im, gsl_complex_abs (root));
+ }
+ }
+ if (*arg == 'p')
+ {
+ g_print ("#poles:\n");
+ gsl_poly_complex_roots (order, b, roots);
+ for (i = 0; i < order; i++)
+ {
+ root = gsl_complex_div (gsl_complex (1, 0), roots[i]);
+ g_print ("%+.14f %+.14f # %.14f\n", root.re, root.im, gsl_complex_abs (root));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ abort:
+ usage ("{rf|F|sn|snc|sci_sn|sci_snc|asn|asnc|sci_asn|sci_asnc|sin(h)|cos(h)|tan(h)|t1|t2} ...");
+ }
+
+ return 0;
+}
diff --git a/flow/gsl/gslopmaster.c b/flow/gsl/gslopmaster.c
new file mode 100644
index 0000000..f71ec3d
--- /dev/null
+++ b/flow/gsl/gslopmaster.c
@@ -0,0 +1,783 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include "gslopmaster.h"
+
+#include "gslcommon.h"
+#include "gslopnode.h"
+#include "gsloputil.h"
+#include "gslopschedule.h"
+#include "gslieee754.h"
+
+
+
+#define NODE_FLAG_RECONNECT(node) G_STMT_START { (node)->reconnected = (node)->module.klass->reconnect != NULL; } G_STMT_END
+
+
+/* --- time stamping (debugging) --- */
+#define ToyprofStamp struct timeval
+#define toyprof_clock_name() ("Glibc gettimeofday(2)")
+#define toyprof_stampinit() /* nothing */
+#define toyprof_stamp(st) gettimeofday (&(st), 0)
+#define toyprof_stamp_ticks() (1000000)
+static inline guint64
+toyprof_elapsed (ToyprofStamp fstamp,
+ ToyprofStamp lstamp)
+{
+ guint64 first = fstamp.tv_sec * toyprof_stamp_ticks () + fstamp.tv_usec;
+ guint64 last = lstamp.tv_sec * toyprof_stamp_ticks () + lstamp.tv_usec;
+ return last - first;
+}
+
+
+/* --- typedefs & structures --- */
+typedef struct _Poll Poll;
+struct _Poll
+{
+ Poll *next;
+ GslPollFunc poll_func;
+ gpointer data;
+ guint n_fds;
+ GPollFD *fds;
+ GslFreeFunc free_func;
+};
+
+
+/* --- prototypes --- */
+static void master_schedule_discard (void);
+
+
+/* --- variables --- */
+static gboolean master_need_reflow = FALSE;
+static gboolean master_need_process = FALSE;
+static EngineNode *master_consumer_list = NULL;
+const gfloat gsl_engine_master_zero_block[GSL_STREAM_MAX_VALUES] = { 0, }; /* FIXME */
+static Poll *master_poll_list = NULL;
+static guint master_n_pollfds = 0;
+static guint master_pollfds_changed = FALSE;
+static GPollFD master_pollfds[GSL_ENGINE_MAX_POLLFDS];
+static EngineSchedule *master_schedule = NULL;
+
+
+/* --- functions --- */
+static void
+add_consumer (EngineNode *node)
+{
+ g_return_if_fail (ENGINE_NODE_IS_CONSUMER (node) && node->toplevel_next == NULL && node->integrated);
+
+ node->toplevel_next = master_consumer_list;
+ master_consumer_list = node;
+}
+
+static void
+remove_consumer (EngineNode *node)
+{
+ EngineNode *tmp, *last = NULL;
+
+ g_return_if_fail (!ENGINE_NODE_IS_CONSUMER (node) || !node->integrated);
+
+ for (tmp = master_consumer_list; tmp; last = tmp, tmp = last->toplevel_next)
+ if (tmp == node)
+ break;
+ g_return_if_fail (tmp != NULL);
+ if (last)
+ last->toplevel_next = node->toplevel_next;
+ else
+ master_consumer_list = node->toplevel_next;
+ node->toplevel_next = NULL;
+}
+
+static void
+master_idisconnect_node (EngineNode *node,
+ guint istream)
+{
+ EngineNode *src_node = node->inputs[istream].src_node;
+ guint ostream = node->inputs[istream].src_stream;
+ gboolean was_consumer;
+
+ g_assert (ostream < ENGINE_NODE_N_OSTREAMS (src_node) &&
+ src_node->outputs[ostream].n_outputs > 0); /* these checks better pass */
+
+ node->inputs[istream].src_node = NULL;
+ node->inputs[istream].src_stream = ~0;
+ node->module.istreams[istream].connected = FALSE;
+ was_consumer = ENGINE_NODE_IS_CONSUMER (src_node);
+ src_node->outputs[ostream].n_outputs -= 1;
+ src_node->module.ostreams[ostream].connected = src_node->outputs[ostream].n_outputs > 0;
+ src_node->output_nodes = gsl_ring_remove (src_node->output_nodes, node);
+ NODE_FLAG_RECONNECT (node);
+ NODE_FLAG_RECONNECT (src_node);
+ /* add to consumer list */
+ if (!was_consumer && ENGINE_NODE_IS_CONSUMER (src_node))
+ add_consumer (src_node);
+}
+
+static void
+master_jdisconnect_node (EngineNode *node,
+ guint jstream,
+ guint con)
+{
+ EngineNode *src_node = node->jinputs[jstream][con].src_node;
+ guint i, ostream = node->jinputs[jstream][con].src_stream;
+ gboolean was_consumer;
+
+ g_assert (ostream < ENGINE_NODE_N_OSTREAMS (src_node) &&
+ node->module.jstreams[jstream].n_connections > 0 &&
+ src_node->outputs[ostream].n_outputs > 0); /* these checks better pass */
+
+ i = --node->module.jstreams[jstream].n_connections;
+ node->jinputs[jstream][con] = node->jinputs[jstream][i];
+ node->module.jstreams[jstream].values[i] = NULL; /* float**values 0-termination */
+ was_consumer = ENGINE_NODE_IS_CONSUMER (src_node);
+ src_node->outputs[ostream].n_outputs -= 1;
+ src_node->module.ostreams[ostream].connected = src_node->outputs[ostream].n_outputs > 0;
+ src_node->output_nodes = gsl_ring_remove (src_node->output_nodes, node);
+ NODE_FLAG_RECONNECT (node);
+ NODE_FLAG_RECONNECT (src_node);
+ /* add to consumer list */
+ if (!was_consumer && ENGINE_NODE_IS_CONSUMER (src_node))
+ add_consumer (src_node);
+}
+
+static void
+master_disconnect_node_outputs (EngineNode *src_node,
+ EngineNode *dest_node)
+{
+ gint i, j;
+
+ for (i = 0; i < ENGINE_NODE_N_ISTREAMS (dest_node); i++)
+ if (dest_node->inputs[i].src_node == src_node)
+ master_idisconnect_node (dest_node, i);
+ for (j = 0; j < ENGINE_NODE_N_JSTREAMS (dest_node); j++)
+ for (i = 0; i < dest_node->module.jstreams[j].n_connections; i++)
+ if (dest_node->jinputs[j][i].src_node == src_node)
+ master_jdisconnect_node (dest_node, j, i--);
+}
+
+static void
+master_process_job (GslJob *job)
+{
+ switch (job->job_id)
+ {
+ EngineNode *node, *src_node;
+ Poll *poll, *poll_last;
+ guint istream, jstream, ostream, con;
+ EngineFlowJob *fjob;
+ gboolean was_consumer;
+ case ENGINE_JOB_INTEGRATE:
+ node = job->data.node;
+ JOB_DEBUG ("integrate(%p)", node);
+ g_return_if_fail (node->integrated == FALSE);
+ g_return_if_fail (node->sched_tag == FALSE);
+ _engine_mnl_integrate (node);
+ if (ENGINE_NODE_IS_CONSUMER (node))
+ add_consumer (node);
+ node->counter = 0;
+ NODE_FLAG_RECONNECT (node);
+ master_need_reflow |= TRUE;
+ break;
+ case ENGINE_JOB_DISCARD:
+ /* FIXME: free pending flow jobs */
+ node = job->data.node;
+ JOB_DEBUG ("discard(%p)", node);
+ g_return_if_fail (node->integrated == TRUE);
+ /* disconnect inputs */
+ for (istream = 0; istream < ENGINE_NODE_N_ISTREAMS (node); istream++)
+ if (node->inputs[istream].src_node)
+ master_idisconnect_node (node, istream);
+ for (jstream = 0; jstream < ENGINE_NODE_N_JSTREAMS (node); jstream++)
+ while (node->module.jstreams[jstream].n_connections)
+ master_jdisconnect_node (node, jstream, node->module.jstreams[jstream].n_connections - 1);
+ /* disconnect outputs */
+ while (node->output_nodes)
+ master_disconnect_node_outputs (node, node->output_nodes->data);
+ /* remove from consumer list */
+ if (ENGINE_NODE_IS_CONSUMER (node))
+ {
+ _engine_mnl_remove (node);
+ remove_consumer (node);
+ }
+ else
+ _engine_mnl_remove (node);
+ node->counter = 0;
+ master_need_reflow |= TRUE;
+ master_schedule_discard (); /* discard schedule so node may be freed */
+ break;
+ case ENGINE_JOB_SET_CONSUMER:
+ case ENGINE_JOB_UNSET_CONSUMER:
+ node = job->data.node;
+ JOB_DEBUG ("toggle_consumer(%p)", node);
+ was_consumer = ENGINE_NODE_IS_CONSUMER (node);
+ node->is_consumer = job->job_id == ENGINE_JOB_SET_CONSUMER;
+ if (was_consumer != ENGINE_NODE_IS_CONSUMER (node))
+ {
+ if (ENGINE_NODE_IS_CONSUMER (node))
+ add_consumer (node);
+ else
+ remove_consumer (node);
+ master_need_reflow |= TRUE;
+ }
+ break;
+ case ENGINE_JOB_ICONNECT:
+ node = job->data.connection.dest_node;
+ src_node = job->data.connection.src_node;
+ istream = job->data.connection.dest_ijstream;
+ ostream = job->data.connection.src_ostream;
+ JOB_DEBUG ("connect(%p,%u,%p,%u)", node, istream, src_node, ostream);
+ g_return_if_fail (node->integrated == TRUE);
+ g_return_if_fail (src_node->integrated == TRUE);
+ g_return_if_fail (node->inputs[istream].src_node == NULL);
+ node->inputs[istream].src_node = src_node;
+ node->inputs[istream].src_stream = ostream;
+ node->module.istreams[istream].connected = TRUE;
+ /* remove from consumer list */
+ was_consumer = ENGINE_NODE_IS_CONSUMER (src_node);
+ src_node->outputs[ostream].n_outputs += 1;
+ src_node->module.ostreams[ostream].connected = TRUE;
+ src_node->output_nodes = gsl_ring_append (src_node->output_nodes, node);
+ NODE_FLAG_RECONNECT (node);
+ NODE_FLAG_RECONNECT (src_node);
+ src_node->counter = 0; /* FIXME: counter reset? */
+ if (was_consumer && !ENGINE_NODE_IS_CONSUMER (src_node))
+ remove_consumer (src_node);
+ master_need_reflow |= TRUE;
+ break;
+ case ENGINE_JOB_JCONNECT:
+ node = job->data.connection.dest_node;
+ src_node = job->data.connection.src_node;
+ jstream = job->data.connection.dest_ijstream;
+ ostream = job->data.connection.src_ostream;
+ JOB_DEBUG ("jconnect(%p,%u,%p,%u)", node, jstream, src_node, ostream);
+ g_return_if_fail (node->integrated == TRUE);
+ g_return_if_fail (src_node->integrated == TRUE);
+ con = node->module.jstreams[jstream].n_connections++;
+ node->jinputs[jstream] = g_renew (EngineJInput, node->jinputs[jstream], node->module.jstreams[jstream].n_connections);
+ node->module.jstreams[jstream].values = g_renew (const gfloat*, node->module.jstreams[jstream].values, node->module.jstreams[jstream].n_connections + 1);
+ node->module.jstreams[jstream].values[node->module.jstreams[jstream].n_connections] = NULL; /* float**values 0-termination */
+ node->jinputs[jstream][con].src_node = src_node;
+ node->jinputs[jstream][con].src_stream = ostream;
+ /* remove from consumer list */
+ was_consumer = ENGINE_NODE_IS_CONSUMER (src_node);
+ src_node->outputs[ostream].n_outputs += 1;
+ src_node->module.ostreams[ostream].connected = TRUE;
+ src_node->output_nodes = gsl_ring_append (src_node->output_nodes, node);
+ NODE_FLAG_RECONNECT (node);
+ NODE_FLAG_RECONNECT (src_node);
+ src_node->counter = 0; /* FIXME: counter reset? */
+ if (was_consumer && !ENGINE_NODE_IS_CONSUMER (src_node))
+ remove_consumer (src_node);
+ master_need_reflow |= TRUE;
+ break;
+ case ENGINE_JOB_IDISCONNECT:
+ node = job->data.connection.dest_node;
+ JOB_DEBUG ("idisconnect(%p,%u)", node, job->data.connection.dest_ijstream);
+ g_return_if_fail (node->integrated == TRUE);
+ g_return_if_fail (node->inputs[job->data.connection.dest_ijstream].src_node != NULL);
+ master_idisconnect_node (node, job->data.connection.dest_ijstream);
+ master_need_reflow |= TRUE;
+ break;
+ case ENGINE_JOB_JDISCONNECT:
+ node = job->data.connection.dest_node;
+ jstream = job->data.connection.dest_ijstream;
+ src_node = job->data.connection.src_node;
+ ostream = job->data.connection.src_ostream;
+ JOB_DEBUG ("jdisconnect(%p,%u,%p,%u)", node, jstream, src_node, ostream);
+ g_return_if_fail (node->integrated == TRUE);
+ g_return_if_fail (node->module.jstreams[jstream].n_connections > 0);
+ for (con = 0; con < node->module.jstreams[jstream].n_connections; con++)
+ if (node->jinputs[jstream][con].src_node == src_node &&
+ node->jinputs[jstream][con].src_stream == ostream)
+ break;
+ if (con < node->module.jstreams[jstream].n_connections)
+ {
+ master_jdisconnect_node (node, jstream, con);
+ master_need_reflow |= TRUE;
+ }
+ else
+ g_warning ("jdisconnect(dest:%p,%u,src:%p,%u): no such connection", node, jstream, src_node, ostream);
+ break;
+ case ENGINE_JOB_ACCESS:
+ node = job->data.access.node;
+ JOB_DEBUG ("access node(%p): %p(%p)", node, job->data.access.access_func, job->data.access.data);
+ g_return_if_fail (node->integrated == TRUE);
+ job->data.access.access_func (&node->module, job->data.access.data);
+ break;
+ case ENGINE_JOB_FLOW_JOB:
+ node = job->data.flow_job.node;
+ fjob = job->data.flow_job.fjob;
+ JOB_DEBUG ("add flow_job(%p,%p)", node, fjob);
+ g_return_if_fail (node->integrated == TRUE);
+ job->data.flow_job.fjob = NULL; /* ownership taken over */
+ _engine_node_insert_flow_job (node, fjob);
+ _engine_mnl_reorder (node);
+ break;
+ case ENGINE_JOB_DEBUG:
+ JOB_DEBUG ("debug");
+ g_printerr ("JOB-DEBUG: %s\n", job->data.debug);
+ break;
+ case ENGINE_JOB_ADD_POLL:
+ JOB_DEBUG ("add poll %p(%p,%u)", job->data.poll.poll_func, job->data.poll.data, job->data.poll.n_fds);
+ if (job->data.poll.n_fds + master_n_pollfds > GSL_ENGINE_MAX_POLLFDS)
+ g_error ("adding poll job exceeds maximum number of poll-fds (%u > %u)",
+ job->data.poll.n_fds + master_n_pollfds, GSL_ENGINE_MAX_POLLFDS);
+ poll = gsl_new_struct0 (Poll, 1);
+ poll->poll_func = job->data.poll.poll_func;
+ poll->data = job->data.poll.data;
+ poll->free_func = job->data.poll.free_func;
+ job->data.poll.free_func = NULL; /* don't free data this round */
+ poll->n_fds = job->data.poll.n_fds;
+ poll->fds = poll->n_fds ? master_pollfds + master_n_pollfds : master_pollfds;
+ master_n_pollfds += poll->n_fds;
+ if (poll->n_fds)
+ master_pollfds_changed = TRUE;
+ memcpy (poll->fds, job->data.poll.fds, sizeof (poll->fds[0]) * poll->n_fds);
+ poll->next = master_poll_list;
+ master_poll_list = poll;
+ break;
+ case ENGINE_JOB_REMOVE_POLL:
+ JOB_DEBUG ("remove poll %p(%p)", job->data.poll.poll_func, job->data.poll.data);
+ for (poll = master_poll_list, poll_last = NULL; poll; poll_last = poll, poll = poll_last->next)
+ if (poll->poll_func == job->data.poll.poll_func && poll->data == job->data.poll.data)
+ {
+ if (poll_last)
+ poll_last->next = poll->next;
+ else
+ master_poll_list = poll->next;
+ break;
+ }
+ if (poll)
+ {
+ job->data.poll.free_func = poll->free_func; /* free data with job */
+ poll_last = poll;
+ if (poll_last->n_fds)
+ {
+ for (poll = master_poll_list; poll; poll = poll->next)
+ if (poll->fds > poll_last->fds)
+ poll->fds -= poll_last->n_fds;
+ g_memmove (poll_last->fds, poll_last->fds + poll_last->n_fds,
+ ((guint8*) (master_pollfds + master_n_pollfds)) -
+ ((guint8*) (poll_last->fds + poll_last->n_fds)));
+ master_n_pollfds -= poll_last->n_fds;
+ master_pollfds_changed = TRUE;
+ }
+ gsl_delete_struct (Poll, poll_last);
+ }
+ else
+ g_warning (G_STRLOC ": failed to remove unknown poll function %p(%p)",
+ job->data.poll.poll_func, job->data.poll.data);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ JOB_DEBUG ("done");
+}
+
+static void
+master_poll_check (glong *timeout_p,
+ gboolean check_with_revents)
+{
+ gboolean need_processing = FALSE;
+ Poll *poll;
+
+ if (master_need_process || *timeout_p == 0)
+ {
+ master_need_process = TRUE;
+ return;
+ }
+ for (poll = master_poll_list; poll; poll = poll->next)
+ {
+ glong timeout = -1;
+
+ if (poll->poll_func (poll->data, gsl_engine_block_size (), &timeout,
+ poll->n_fds, poll->n_fds ? poll->fds : NULL, check_with_revents)
+ || timeout == 0)
+ {
+ need_processing |= TRUE;
+ *timeout_p = 0;
+ break;
+ }
+ else if (timeout > 0)
+ *timeout_p = *timeout_p < 0 ? timeout : MIN (*timeout_p, timeout);
+ }
+ master_need_process = need_processing;
+}
+
+static inline guint64
+master_handle_flow_jobs (EngineNode *node,
+ guint64 max_tick)
+{
+ EngineFlowJob *fjob = _engine_node_pop_flow_job (node, max_tick);
+
+ if_reject (fjob)
+ do
+ {
+ g_printerr ("FJob: at:%lld from:%lld \n", node->counter, fjob->any.tick_stamp);
+ switch (fjob->fjob_id)
+ {
+ case ENGINE_FLOW_JOB_ACCESS:
+ fjob->access.access_func (&node->module, fjob->access.data);
+ break;
+ default:
+ g_assert_not_reached (); /* FIXME */
+ }
+ fjob = _engine_node_pop_flow_job (node, max_tick);
+ }
+ while (fjob);
+
+ return _engine_node_peek_flow_job_stamp (node);
+}
+
+static void
+master_process_locked_node (EngineNode *node,
+ guint n_values)
+{
+ guint64 final_counter = GSL_TICK_STAMP + n_values;
+
+ while (node->counter < final_counter)
+ {
+ guint64 next_counter = master_handle_flow_jobs (node, node->counter);
+ guint64 new_counter = MIN (next_counter, final_counter);
+ guint i, j, diff = node->counter - GSL_TICK_STAMP;
+
+ for (i = 0; i < ENGINE_NODE_N_ISTREAMS (node); i++)
+ {
+ EngineNode *inode = node->inputs[i].src_node;
+
+ if (inode)
+ {
+ ENGINE_NODE_LOCK (inode);
+ if (inode->counter < final_counter)
+ master_process_locked_node (inode, final_counter - node->counter);
+ node->module.istreams[i].values = inode->outputs[node->inputs[i].src_stream].buffer;
+ node->module.istreams[i].values += diff;
+ ENGINE_NODE_UNLOCK (inode);
+ }
+ else
+ node->module.istreams[i].values = gsl_engine_master_zero_block;
+ }
+ for (j = 0; j < ENGINE_NODE_N_JSTREAMS (node); j++)
+ for (i = 0; i < node->module.jstreams[j].n_connections; i++)
+ {
+ EngineNode *inode = node->jinputs[j][i].src_node;
+
+ ENGINE_NODE_LOCK (inode);
+ if (inode->counter < final_counter)
+ master_process_locked_node (inode, final_counter - node->counter);
+ node->module.jstreams[j].values[i] = inode->outputs[node->jinputs[j][i].src_stream].buffer;
+ node->module.jstreams[j].values[i] += diff;
+ ENGINE_NODE_UNLOCK (inode);
+ }
+ for (i = 0; i < ENGINE_NODE_N_OSTREAMS (node); i++)
+ node->module.ostreams[i].values = node->outputs[i].buffer + diff;
+ if_reject (node->reconnected)
+ {
+ node->module.klass->reconnect (&node->module);
+ node->reconnected = FALSE;
+ }
+ node->module.klass->process (&node->module, new_counter - node->counter);
+ for (i = 0; i < ENGINE_NODE_N_OSTREAMS (node); i++)
+ {
+ /* FIXME: this takes the worst possible performance hit to support virtualization */
+ if (node->module.ostreams[i].values != node->outputs[i].buffer + diff)
+ memcpy (node->outputs[i].buffer + diff, node->module.ostreams[i].values,
+ (new_counter - node->counter) * sizeof (gfloat));
+ }
+ node->counter = new_counter;
+ }
+}
+
+static GslLong gsl_profile_modules = 0; /* set to 1 in gdb to get profile output */
+
+static void
+master_process_flow (void)
+{
+ guint64 new_counter = GSL_TICK_STAMP + gsl_engine_block_size ();
+ GslLong profile_maxtime = 0;
+ GslLong profile_modules = gsl_profile_modules;
+ EngineNode *profile_node = NULL;
+
+ g_return_if_fail (master_need_process == TRUE);
+
+ g_assert (gsl_fpu_okround () == TRUE);
+
+ MAS_DEBUG ("process_flow");
+ if (master_schedule)
+ {
+ EngineNode *node;
+
+ _engine_schedule_restart (master_schedule);
+ _engine_set_schedule (master_schedule);
+
+ node = _engine_pop_unprocessed_node ();
+ while (node)
+ {
+ ToyprofStamp profile_stamp1, profile_stamp2;
+
+ if_reject (profile_modules)
+ toyprof_stamp (profile_stamp1);
+
+ master_process_locked_node (node, gsl_engine_block_size ());
+
+ if_reject (profile_modules)
+ {
+ GslLong duration;
+
+ toyprof_stamp (profile_stamp2);
+ duration = toyprof_elapsed (profile_stamp1, profile_stamp2);
+ if (duration > profile_maxtime)
+ {
+ profile_maxtime = duration;
+ profile_node = node;
+ }
+ }
+
+ _engine_push_processed_node (node);
+ node = _engine_pop_unprocessed_node ();
+ }
+
+ if_reject (profile_modules)
+ {
+ if (profile_node)
+ {
+ if (profile_maxtime > profile_modules)
+ g_print ("Excess Node: %p Duration: %lu usecs ((void(*)())%p) \n",
+ profile_node, profile_maxtime, profile_node->module.klass->process);
+ else
+ g_print ("Slowest Node: %p Duration: %lu usecs ((void(*)())%p) \r",
+ profile_node, profile_maxtime, profile_node->module.klass->process);
+ }
+ }
+
+ /* walk unscheduled nodes which have flow jobs */
+ node = _engine_mnl_head ();
+ while (node && GSL_MNL_HEAD_NODE (node))
+ {
+ EngineNode *tmp = node->mnl_next;
+ EngineFlowJob *fjob = _engine_node_pop_flow_job (node, new_counter);
+
+ if (fjob)
+ {
+ while (fjob)
+ {
+ g_printerr ("ignoring flow_job %p\n", fjob);
+ fjob = _engine_node_pop_flow_job (node, new_counter);
+ }
+ _engine_mnl_reorder (node);
+ }
+ node = tmp;
+ }
+
+ /* nothing new to process, wait on slaves */
+ _engine_wait_on_unprocessed ();
+
+ _engine_unset_schedule (master_schedule);
+ _gsl_tick_stamp_inc ();
+ _engine_recycle_const_values ();
+ }
+ master_need_process = FALSE;
+}
+
+static void
+master_reschedule_flow (void)
+{
+ EngineNode *node;
+
+ g_return_if_fail (master_need_reflow == TRUE);
+
+ MAS_DEBUG ("flow_reschedule");
+ if (!master_schedule)
+ master_schedule = _engine_schedule_new ();
+ else
+ {
+ _engine_schedule_unsecure (master_schedule);
+ _engine_schedule_clear (master_schedule);
+ }
+ for (node = master_consumer_list; node; node = node->toplevel_next)
+ _engine_schedule_consumer_node (master_schedule, node);
+ _engine_schedule_secure (master_schedule);
+ master_need_reflow = FALSE;
+}
+
+static void
+master_schedule_discard (void)
+{
+ g_return_if_fail (master_need_reflow == TRUE);
+
+ if (master_schedule)
+ {
+ _engine_schedule_unsecure (master_schedule);
+ _engine_schedule_destroy (master_schedule);
+ master_schedule = NULL;
+ }
+}
+
+
+/* --- MasterThread main loop --- */
+gboolean
+_engine_master_prepare (GslEngineLoop *loop)
+{
+ gboolean need_dispatch;
+ guint i;
+
+ g_return_val_if_fail (loop != NULL, FALSE);
+
+ /* setup and clear pollfds here already, so master_poll_check() gets no junk (and IRIX can't handle non-0 revents) */
+ loop->fds_changed = master_pollfds_changed;
+ master_pollfds_changed = FALSE;
+ loop->n_fds = master_n_pollfds;
+ loop->fds = master_pollfds;
+ for (i = 0; i < loop->n_fds; i++)
+ loop->fds[i].revents = 0;
+ loop->revents_filled = FALSE;
+
+ loop->timeout = -1;
+ /* cached checks first */
+ need_dispatch = master_need_reflow || master_need_process;
+ /* lengthy query */
+ if (!need_dispatch)
+ need_dispatch = _engine_job_pending ();
+ /* invoke custom poll checks */
+ if (!need_dispatch)
+ {
+ master_poll_check (&loop->timeout, FALSE);
+ need_dispatch = master_need_process;
+ }
+ if (need_dispatch)
+ loop->timeout = 0;
+
+ MAS_DEBUG ("PREPARE: need_dispatch=%u timeout=%6ld n_fds=%u",
+ need_dispatch,
+ loop->timeout, loop->n_fds);
+
+ return need_dispatch;
+}
+
+gboolean
+_engine_master_check (const GslEngineLoop *loop)
+{
+ gboolean need_dispatch;
+
+ g_return_val_if_fail (loop != NULL, FALSE);
+ g_return_val_if_fail (loop->n_fds == master_n_pollfds, FALSE);
+ g_return_val_if_fail (loop->fds == master_pollfds, FALSE);
+ if (loop->n_fds)
+ g_return_val_if_fail (loop->revents_filled == TRUE, FALSE);
+
+ /* cached checks first */
+ need_dispatch = master_need_reflow || master_need_process;
+ /* lengthy query */
+ if (!need_dispatch)
+ need_dispatch = _engine_job_pending ();
+ /* invoke custom poll checks */
+ if (!need_dispatch)
+ {
+ glong dummy = -1;
+
+ master_poll_check (&dummy, TRUE);
+ need_dispatch = master_need_process;
+ }
+
+ MAS_DEBUG ("CHECK: need_dispatch=%u", need_dispatch);
+
+ return need_dispatch;
+}
+
+void
+_engine_master_dispatch_jobs (void)
+{
+ GslJob *job;
+
+ job = _engine_pop_job ();
+ while (job)
+ {
+ master_process_job (job);
+ job = _engine_pop_job (); /* have to process _all_ jobs */
+ }
+}
+
+void
+_engine_master_dispatch (void)
+{
+ /* processing has prime priority, but we can't process the
+ * network, until all jobs have been handled and if necessary
+ * rescheduled the network.
+ * that's why we have to handle everything at once and can't
+ * preliminarily return after just handling jobs or rescheduling.
+ */
+ _engine_master_dispatch_jobs ();
+ if (master_need_reflow)
+ master_reschedule_flow ();
+ if (master_need_process)
+ master_process_flow ();
+}
+
+void
+_engine_master_thread (gpointer data)
+{
+ gboolean run = TRUE;
+
+ /* assert sane configuration checks, since we're simply casting structures */
+ g_assert (sizeof (struct pollfd) == sizeof (GPollFD) &&
+ G_STRUCT_OFFSET (GPollFD, fd) == G_STRUCT_OFFSET (struct pollfd, fd) &&
+ G_STRUCT_OFFSET (GPollFD, events) == G_STRUCT_OFFSET (struct pollfd, events) &&
+ G_STRUCT_OFFSET (GPollFD, revents) == G_STRUCT_OFFSET (struct pollfd, revents));
+
+ /* add the thread wakeup pipe to master pollfds, so we get woken
+ * up in time (even though we evaluate the pipe contents later)
+ */
+ gsl_thread_get_pollfd (master_pollfds);
+ master_n_pollfds += 1;
+ master_pollfds_changed = TRUE;
+
+ toyprof_stampinit ();
+
+ while (run)
+ {
+ GslEngineLoop loop;
+ gboolean need_dispatch;
+
+ need_dispatch = _engine_master_prepare (&loop);
+
+ if (!need_dispatch)
+ {
+ gint err;
+
+ err = poll ((struct pollfd*) loop.fds, loop.n_fds, loop.timeout);
+
+ if (err >= 0)
+ loop.revents_filled = TRUE;
+ else
+ g_printerr (G_STRLOC ": poll() error: %s\n", g_strerror (errno));
+
+ if (loop.revents_filled)
+ need_dispatch = _engine_master_check (&loop);
+ }
+
+ if (need_dispatch)
+ _engine_master_dispatch ();
+
+ /* handle thread pollfd messages */
+ run = gsl_thread_sleep (0);
+ }
+}
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gslopmaster.h b/flow/gsl/gslopmaster.h
new file mode 100644
index 0000000..69cc3f8
--- /dev/null
+++ b/flow/gsl/gslopmaster.h
@@ -0,0 +1,42 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_ENGINE_MASTER_H__
+#define __GSL_ENGINE_MASTER_H__
+
+#include <gsl/gslengine.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- internal (EngineThread) --- */
+gboolean _engine_master_prepare (GslEngineLoop *loop);
+gboolean _engine_master_check (const GslEngineLoop *loop);
+void _engine_master_dispatch_jobs (void);
+void _engine_master_dispatch (void);
+void _engine_master_thread (gpointer data);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_ENGINE_MASTER_H__ */
diff --git a/flow/gsl/gslopnode.h b/flow/gsl/gslopnode.h
new file mode 100644
index 0000000..3e236e5
--- /dev/null
+++ b/flow/gsl/gslopnode.h
@@ -0,0 +1,247 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_ENGINE_NODE_H__
+#define __GSL_ENGINE_NODE_H__
+
+#include "gslengine.h"
+#include "gsloputil.h"
+#include "gslcommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+#define ENGINE_NODE(module) ((EngineNode*) (module))
+#define ENGINE_NODE_N_OSTREAMS(node) ((node)->module.klass->n_ostreams)
+#define ENGINE_NODE_N_ISTREAMS(node) ((node)->module.klass->n_istreams)
+#define ENGINE_NODE_N_JSTREAMS(node) ((node)->module.klass->n_jstreams)
+#define ENGINE_NODE_IS_CONSUMER(node) ((node)->is_consumer && \
+ (node)->output_nodes == NULL)
+#define ENGINE_NODE_IS_DEFERRED(node) (FALSE)
+#define ENGINE_NODE_IS_SCHEDULED(node) (ENGINE_NODE (node)->sched_tag)
+#define ENGINE_NODE_IS_CHEAP(node) (((node)->module.klass->mflags & GSL_COST_CHEAP) != 0)
+#define ENGINE_NODE_IS_EXPENSIVE(node) (((node)->module.klass->mflags & GSL_COST_EXPENSIVE) != 0)
+#define ENGINE_NODE_LOCK(node) gsl_rec_mutex_lock (&(node)->rec_mutex)
+#define ENGINE_NODE_UNLOCK(node) gsl_rec_mutex_unlock (&(node)->rec_mutex)
+
+
+/* --- debugging and messages --- */
+#define ENG_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_ENGINE, NULL)
+#define MAS_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_MASTER, NULL)
+#define JOB_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_JOBS, NULL)
+#define SCHED_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_SCHED, NULL)
+
+
+/* --- transactions --- */
+typedef union _EngineFlowJob EngineFlowJob;
+typedef enum {
+ ENGINE_JOB_NOP,
+ ENGINE_JOB_INTEGRATE,
+ ENGINE_JOB_DISCARD,
+ ENGINE_JOB_ICONNECT,
+ ENGINE_JOB_JCONNECT,
+ ENGINE_JOB_IDISCONNECT,
+ ENGINE_JOB_JDISCONNECT,
+ ENGINE_JOB_SET_CONSUMER,
+ ENGINE_JOB_UNSET_CONSUMER,
+ ENGINE_JOB_ACCESS,
+ ENGINE_JOB_ADD_POLL,
+ ENGINE_JOB_REMOVE_POLL,
+ ENGINE_JOB_FLOW_JOB,
+ ENGINE_JOB_DEBUG,
+ ENGINE_JOB_LAST
+} EngineJobType;
+struct _GslJob
+{
+ EngineJobType job_id;
+ GslJob *next;
+ union {
+ EngineNode *node;
+ struct {
+ EngineNode *dest_node;
+ guint dest_ijstream;
+ EngineNode *src_node;
+ guint src_ostream;
+ } connection;
+ struct {
+ EngineNode *node;
+ GslAccessFunc access_func;
+ gpointer data;
+ GslFreeFunc free_func;
+ } access;
+ struct {
+ GslPollFunc poll_func;
+ gpointer data;
+ GslFreeFunc free_func;
+ guint n_fds;
+ GPollFD *fds;
+ } poll;
+ struct {
+ EngineNode *node;
+ EngineFlowJob *fjob;
+ } flow_job;
+ gchar *debug;
+ } data;
+};
+struct _GslTrans
+{
+ GslJob *jobs_head;
+ GslJob *jobs_tail;
+ guint comitted : 1;
+ GslTrans *cqt_next; /* com-thread-queue */
+};
+typedef enum {
+ ENGINE_FLOW_JOB_NOP,
+ ENGINE_FLOW_JOB_SUSPEND,
+ ENGINE_FLOW_JOB_RESUME,
+ ENGINE_FLOW_JOB_ACCESS,
+ ENGINE_FLOW_JOB_LAST
+} EngineFlowJobType;
+typedef struct
+{
+ EngineFlowJobType fjob_id;
+ EngineFlowJob *next;
+ guint64 tick_stamp;
+} EngineFlowJobAny;
+typedef struct
+{
+ EngineFlowJobType fjob_id;
+ EngineFlowJob *next;
+ guint64 tick_stamp;
+ GslAccessFunc access_func;
+ gpointer data;
+ GslFreeFunc free_func;
+} EngineFlowJobAccess;
+union _EngineFlowJob
+{
+ EngineFlowJobType fjob_id;
+ EngineFlowJobAny any;
+ EngineFlowJobAccess access;
+};
+
+
+/* --- module nodes --- */
+typedef struct
+{
+ EngineNode *src_node;
+ guint src_stream; /* ostream of src_node */
+} EngineInput;
+typedef struct
+{
+ EngineNode *src_node;
+ guint src_stream; /* ostream of src_node */
+} EngineJInput;
+typedef struct
+{
+ gfloat *buffer;
+ guint n_outputs;
+} EngineOutput;
+struct _EngineNode /* fields sorted by order of processing access */
+{
+ GslModule module;
+
+ GslRecMutex rec_mutex; /* processing lock */
+ guint64 counter; /* <= GSL_TICK_STAMP */
+ EngineInput *inputs; /* [ENGINE_NODE_N_ISTREAMS()] */
+ EngineJInput **jinputs; /* [ENGINE_NODE_N_JSTREAMS()] */
+ EngineOutput *outputs; /* [ENGINE_NODE_N_OSTREAMS()] */
+
+ /* flow jobs */
+ EngineFlowJob *flow_jobs; /* active jobs */
+ EngineFlowJob *fjob_first, *fjob_last; /* trash list */
+
+ /* master-node-list */
+ EngineNode *mnl_next;
+ EngineNode *mnl_prev;
+ guint integrated : 1;
+ guint reconnected : 1;
+
+ guint is_consumer : 1;
+
+ /* scheduler */
+ guint sched_tag : 1;
+ guint sched_router_tag : 1;
+ guint sched_leaf_level;
+ EngineNode *toplevel_next; /* master-consumer-list, FIXME: overkill, using a GslRing is good enough */
+ GslRing *output_nodes; /* EngineNode* ring of nodes in ->outputs[] */
+};
+
+static void
+_engine_node_insert_flow_job (EngineNode *node,
+ EngineFlowJob *fjob)
+{
+ EngineFlowJob *last = NULL, *tmp = node->flow_jobs;
+
+ /* find next position */
+ while (tmp && tmp->any.tick_stamp <= fjob->any.tick_stamp)
+ {
+ last = tmp;
+ tmp = last->any.next;
+ }
+ /* insert before */
+ fjob->any.next = tmp;
+ if (last)
+ last->any.next = fjob;
+ else
+ node->flow_jobs = fjob;
+}
+
+static inline EngineFlowJob*
+_engine_node_pop_flow_job (EngineNode *node,
+ guint64 tick_stamp)
+{
+ EngineFlowJob *fjob = node->flow_jobs;
+
+ if_reject (fjob)
+ {
+ if (fjob->any.tick_stamp <= tick_stamp)
+ {
+ node->flow_jobs = fjob->any.next;
+
+ fjob->any.next = node->fjob_first;
+ node->fjob_first = fjob;
+ if (!node->fjob_last)
+ node->fjob_last = node->fjob_first;
+ }
+ else
+ fjob = NULL;
+ }
+
+ return fjob;
+}
+
+static inline guint64
+_engine_node_peek_flow_job_stamp (EngineNode *node)
+{
+ EngineFlowJob *fjob = node->flow_jobs;
+
+ if_reject (fjob)
+ return fjob->any.tick_stamp;
+
+ return GSL_MAX_TICK_STAMP;
+}
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_ENGINE_NODE_H__ */
diff --git a/flow/gsl/gslopschedule.c b/flow/gsl/gslopschedule.c
new file mode 100644
index 0000000..9102a41
--- /dev/null
+++ b/flow/gsl/gslopschedule.c
@@ -0,0 +1,582 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslopschedule.h"
+
+
+#include "gslcommon.h"
+
+
+/* --- functions --- */
+EngineSchedule*
+_engine_schedule_new (void)
+{
+ EngineSchedule *sched = gsl_new_struct0 (EngineSchedule, 1);
+
+ sched->n_items = 0;
+ sched->leaf_levels = 0;
+ sched->nodes = NULL;
+ sched->cycles = NULL;
+ sched->secured = FALSE;
+ sched->in_pqueue = FALSE;
+ sched->cur_leaf_level = ~0;
+ sched->cur_node = NULL;
+ sched->cur_cycle = NULL;
+
+ return sched;
+}
+
+static inline void
+unschedule_node (EngineSchedule *sched,
+ EngineNode *node)
+{
+ guint leaf_level;
+
+ g_return_if_fail (ENGINE_NODE_IS_SCHEDULED (node) == TRUE);
+ leaf_level = node->sched_leaf_level;
+ g_return_if_fail (leaf_level <= sched->leaf_levels);
+ g_return_if_fail (sched->n_items > 0);
+
+ SCHED_DEBUG ("unschedule_node(%p,%u)", node, leaf_level);
+ sched->nodes[leaf_level] = gsl_ring_remove (sched->nodes[leaf_level], node);
+ node->sched_leaf_level = 0;
+ node->sched_tag = FALSE;
+ if (node->flow_jobs)
+ _engine_mnl_reorder (node);
+ sched->n_items--;
+}
+
+static inline void
+unschedule_cycle (EngineSchedule *sched,
+ GslRing *ring)
+{
+ guint leaf_level;
+ GslRing *walk;
+
+ g_return_if_fail (ENGINE_NODE_IS_SCHEDULED (ENGINE_NODE (ring->data)) == TRUE);
+ leaf_level = ENGINE_NODE (ring->data)->sched_leaf_level;
+ g_return_if_fail (leaf_level <= sched->leaf_levels);
+ g_return_if_fail (sched->n_items > 0);
+
+ SCHED_DEBUG ("unschedule_cycle(%p,%u,%p)", ring->data, leaf_level, ring);
+ sched->nodes[leaf_level] = gsl_ring_remove (sched->nodes[leaf_level], ring);
+ for (walk = ring; walk; walk = gsl_ring_walk (ring, walk))
+ {
+ EngineNode *node = walk->data;
+
+ if (!ENGINE_NODE_IS_SCHEDULED (node))
+ g_warning ("node(%p) in schedule ring(%p) is untagged", node, ring);
+ node->sched_leaf_level = 0;
+ node->sched_tag = FALSE;
+ if (node->flow_jobs)
+ _engine_mnl_reorder (node);
+ }
+ sched->n_items--;
+}
+
+static void
+_engine_schedule_debug_dump (EngineSchedule *sched)
+{
+ g_printerr ("sched(%p) = {\n", sched);
+ if (sched)
+ {
+ guint i;
+
+ g_printerr (" n_items=%u, leaf_levels=%u, secured=%u,\n",
+ sched->n_items, sched->leaf_levels, sched->secured);
+ g_printerr (" in_pqueue=%u, cur_leaf_level=%u,\n",
+ sched->in_pqueue, sched->cur_leaf_level);
+ g_printerr (" cur_node=%p, cur_cycle=%p,\n",
+ sched->cur_node, sched->cur_cycle);
+ for (i = 0; i < sched->leaf_levels; i++)
+ {
+ GslRing *ring, *head = sched->nodes[i];
+
+ if (!head)
+ continue;
+ g_printerr (" { leaf_level=%u:", i);
+ for (ring = head; ring; ring = gsl_ring_walk (head, ring))
+ g_printerr (" node(%p(tag:%u))", ring->data, ((EngineNode*) ring->data)->sched_tag);
+ g_printerr (" },\n");
+ }
+ }
+ g_printerr ("};\n");
+}
+
+
+void
+_engine_schedule_clear (EngineSchedule *sched)
+{
+ guint i;
+
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == FALSE);
+ g_return_if_fail (sched->in_pqueue == FALSE);
+
+ for (i = 0; i < sched->leaf_levels; i++)
+ {
+ /* FIXME: each unschedule operation is a list walk, while we
+ * could easily leave the rings alone and free them as a whole
+ */
+ while (sched->nodes[i])
+ unschedule_node (sched, sched->nodes[i]->data);
+ while (sched->cycles[i])
+ unschedule_cycle (sched, sched->cycles[i]->data);
+ }
+ g_return_if_fail (sched->n_items == 0);
+}
+
+void
+_engine_schedule_destroy (EngineSchedule *sched)
+{
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == FALSE);
+ g_return_if_fail (sched->in_pqueue == FALSE);
+
+ _engine_schedule_clear (sched);
+ g_free (sched->nodes);
+ g_free (sched->cycles);
+ gsl_delete_struct (EngineSchedule, sched);
+}
+
+static void
+_engine_schedule_grow (EngineSchedule *sched,
+ guint leaf_level)
+{
+ guint ll = 1 << g_bit_storage (leaf_level); /* power2 growth alignment, ll >= leaf_level+1 */
+
+ if (sched->leaf_levels < ll)
+ {
+ guint i = sched->leaf_levels;
+
+ sched->leaf_levels = ll;
+ sched->nodes = g_renew (GslRing*, sched->nodes, sched->leaf_levels);
+ sched->cycles = g_renew (GslRing*, sched->cycles, sched->leaf_levels);
+ for (; i < sched->leaf_levels; i++)
+ {
+ sched->nodes[i] = NULL;
+ sched->cycles[i] = NULL;
+ }
+ }
+}
+
+void
+_engine_schedule_node (EngineSchedule *sched,
+ EngineNode *node,
+ guint leaf_level)
+{
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == FALSE);
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (!ENGINE_NODE_IS_SCHEDULED (node));
+
+ SCHED_DEBUG ("schedule_node(%p,%u)", node, leaf_level);
+ node->sched_leaf_level = leaf_level;
+ node->sched_tag = TRUE;
+ if (node->flow_jobs)
+ _engine_mnl_reorder (node);
+ _engine_schedule_grow (sched, leaf_level);
+ /* could do 3-stage scheduling by expensiveness */
+ sched->nodes[leaf_level] = (ENGINE_NODE_IS_EXPENSIVE (node) ? gsl_ring_prepend : gsl_ring_append) (sched->nodes[leaf_level], node);
+ sched->n_items++;
+}
+
+void
+_engine_schedule_cycle (EngineSchedule *sched,
+ GslRing *cycle_nodes,
+ guint leaf_level)
+{
+ GslRing *walk;
+
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == FALSE);
+ g_return_if_fail (cycle_nodes != NULL);
+
+ for (walk = cycle_nodes; walk; walk = gsl_ring_walk (cycle_nodes, walk))
+ {
+ EngineNode *node = walk->data;
+
+ g_return_if_fail (!ENGINE_NODE_IS_SCHEDULED (node));
+ node->sched_leaf_level = leaf_level;
+ node->sched_tag = TRUE;
+ if (node->flow_jobs)
+ _engine_mnl_reorder (node);
+ }
+ _engine_schedule_grow (sched, leaf_level);
+ sched->cycles[leaf_level] = gsl_ring_prepend (sched->cycles[leaf_level], cycle_nodes);
+ sched->n_items++;
+}
+
+void
+_engine_schedule_restart (EngineSchedule *sched)
+{
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == TRUE);
+ g_return_if_fail (sched->cur_leaf_level == sched->leaf_levels);
+ g_return_if_fail (sched->cur_node == NULL);
+ g_return_if_fail (sched->cur_cycle == NULL);
+
+ sched->cur_leaf_level = 0;
+ if (sched->leaf_levels > 0)
+ {
+ sched->cur_node = sched->nodes[0];
+ sched->cur_cycle = sched->cycles[0];
+ }
+}
+
+void
+_engine_schedule_secure (EngineSchedule *sched)
+{
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == FALSE);
+
+ sched->secured = TRUE;
+ sched->cur_leaf_level = sched->leaf_levels;
+
+ if (gsl_debug_check (GSL_MSG_SCHED))
+ _engine_schedule_debug_dump (sched);
+}
+
+static void
+schedule_advance (EngineSchedule *sched)
+{
+ while (!sched->cur_node && !sched->cur_cycle && sched->cur_leaf_level < sched->leaf_levels)
+ {
+ sched->cur_leaf_level += 1;
+ if (sched->cur_leaf_level < sched->leaf_levels)
+ {
+ sched->cur_node = sched->nodes[sched->cur_leaf_level];
+ sched->cur_cycle = sched->cycles[sched->cur_leaf_level];
+ }
+ }
+}
+
+EngineNode*
+_engine_schedule_pop_node (EngineSchedule *sched)
+{
+ g_return_val_if_fail (sched != NULL, NULL);
+ g_return_val_if_fail (sched->secured == TRUE, NULL);
+ g_return_val_if_fail (sched->cur_leaf_level <= sched->leaf_levels, NULL);
+
+ do
+ {
+ guint leaf_level = sched->cur_leaf_level;
+
+ if (sched->cur_node)
+ {
+ EngineNode *node = sched->cur_node->data;
+
+ sched->cur_node = gsl_ring_walk (sched->nodes[leaf_level], sched->cur_node);
+ return node;
+ }
+ schedule_advance (sched);
+ }
+ while (sched->cur_node);
+
+ /* nothing to hand out, either we're empty or still have cycles pending */
+ return NULL;
+}
+
+GslRing*
+_engine_schedule_pop_cycle (EngineSchedule *sched)
+{
+ g_return_val_if_fail (sched != NULL, NULL);
+ g_return_val_if_fail (sched->secured == TRUE, NULL);
+ g_return_val_if_fail (sched->cur_leaf_level <= sched->leaf_levels, NULL);
+
+ do
+ {
+ guint leaf_level = sched->cur_leaf_level;
+
+ if (sched->cur_cycle)
+ {
+ GslRing *cycle = sched->cur_cycle->data;
+
+ sched->cur_cycle = gsl_ring_walk (sched->cycles[leaf_level], sched->cur_cycle);
+ return cycle;
+ }
+ schedule_advance (sched);
+ }
+ while (sched->cur_cycle);
+
+ /* nothing to hand out, either we're empty or still have nodes pending */
+ return NULL;
+}
+
+void
+_engine_schedule_unsecure (EngineSchedule *sched)
+{
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == TRUE);
+ g_return_if_fail (sched->in_pqueue == FALSE);
+ g_return_if_fail (sched->cur_leaf_level == sched->leaf_levels);
+ g_return_if_fail (sched->cur_node == NULL);
+ g_return_if_fail (sched->cur_cycle == NULL);
+
+ sched->secured = FALSE;
+ sched->cur_leaf_level = ~0;
+}
+
+
+/* --- depth scheduling --- */
+static GslRing*
+merge_untagged_node_lists_uniq (GslRing *ring1,
+ GslRing *ring2)
+{
+ GslRing *walk;
+
+ /* paranoid, ensure all nodes are untagged */
+ for (walk = ring2; walk; walk = gsl_ring_walk (ring2, walk))
+ {
+ EngineNode *node = walk->data;
+
+ g_assert (node->sched_router_tag == FALSE);
+ }
+
+ /* tag all nodes in list first */
+ for (walk = ring1; walk; walk = gsl_ring_walk (ring1, walk))
+ {
+ EngineNode *node = walk->data;
+
+ g_assert (node->sched_router_tag == FALSE); /* paranoid check */
+ node->sched_router_tag = TRUE;
+ }
+
+ /* merge list with missing (untagged) nodes */
+ for (walk = ring2; walk; walk = gsl_ring_walk (ring2, walk))
+ {
+ EngineNode *node = walk->data;
+
+ if (node->sched_router_tag == FALSE)
+ ring1 = gsl_ring_append (ring1, node);
+ }
+
+ /* untag all nodes */
+ for (walk = ring1; walk; walk = gsl_ring_walk (ring1, walk))
+ {
+ EngineNode *node = walk->data;
+
+ node->sched_router_tag = FALSE;
+ }
+ for (walk = ring2; walk; walk = gsl_ring_walk (ring2, walk))
+ {
+ EngineNode *node = walk->data;
+
+ node->sched_router_tag = FALSE;
+ }
+ gsl_ring_free (ring2);
+ return ring1;
+}
+
+static gboolean
+resolve_cycle (EngineCycle *cycle,
+ EngineNode *node,
+ GslRing **cycle_nodes_p)
+{
+ if (node != cycle->last)
+ return FALSE;
+ if (!cycle->seen_deferred_node)
+ {
+ g_error ("cycle without delay module: (%p)", cycle);
+ }
+ *cycle_nodes_p = merge_untagged_node_lists_uniq (*cycle_nodes_p, cycle->nodes);
+ cycle->nodes = NULL;
+ cycle->last = NULL;
+ return TRUE;
+}
+
+static gboolean
+master_resolve_cycles (EngineQuery *query,
+ EngineNode *node)
+{
+ GslRing *walk;
+ gboolean all_resolved = TRUE;
+
+ g_assert (query->cycles != NULL); /* paranoid */
+
+ walk = query->cycles;
+ while (walk)
+ {
+ GslRing *next = gsl_ring_walk (query->cycles, walk);
+ EngineCycle *cycle = walk->data;
+
+ if (resolve_cycle (cycle, node, &query->cycle_nodes))
+ {
+ g_assert (cycle->last == NULL); /* paranoid */
+ g_assert (cycle->nodes == NULL); /* paranoid */
+
+ gsl_delete_struct (EngineCycle, cycle);
+ query->cycles = gsl_ring_remove_node (query->cycles, walk);
+ }
+ else
+ all_resolved = FALSE;
+ walk = next;
+ }
+ if (all_resolved)
+ g_assert (query->cycles == NULL); /* paranoid */
+ return all_resolved;
+}
+
+static void
+query_add_cycle (EngineQuery *query,
+ EngineNode *dep,
+ EngineNode *node)
+{
+ EngineCycle *cycle = gsl_new_struct0 (EngineCycle, 1);
+
+ cycle->last = dep;
+ cycle->nodes = gsl_ring_prepend (NULL, node);
+ cycle->seen_deferred_node = ENGINE_NODE_IS_DEFERRED (node); /* dep will be checked when added to nodes */
+ query->cycles = gsl_ring_append (query->cycles, cycle);
+}
+
+static void
+query_merge_cycles (EngineQuery *query,
+ EngineQuery *child_query,
+ EngineNode *node)
+{
+ GslRing *walk;
+
+ g_assert (child_query->cycles != NULL); /* paranoid */
+
+ /* add node to all child cycles */
+ for (walk = child_query->cycles; walk; walk = gsl_ring_walk (child_query->cycles, walk))
+ {
+ EngineCycle *cycle = walk->data;
+
+ cycle->nodes = gsl_ring_prepend (cycle->nodes, node);
+ cycle->seen_deferred_node |= ENGINE_NODE_IS_DEFERRED (node);
+ }
+
+ /* merge child cycles into ours */
+ query->cycles = gsl_ring_concat (query->cycles, child_query->cycles);
+ child_query->cycles = NULL;
+
+ /* merge childs cycle nodes from resolved cycles into ours */
+ query->cycle_nodes = merge_untagged_node_lists_uniq (query->cycle_nodes, child_query->cycle_nodes);
+ child_query->cycle_nodes = NULL;
+}
+
+static void
+subschedule_query_node (EngineSchedule *schedule,
+ EngineNode *node,
+ EngineQuery *query)
+{
+ guint i, j, leaf_level = 0;
+
+ g_return_if_fail (node->sched_router_tag == FALSE);
+
+ SCHED_DEBUG ("start_query(%p)", node);
+ node->sched_router_tag = TRUE;
+ for (i = 0; i < ENGINE_NODE_N_ISTREAMS (node); i++)
+ {
+ EngineNode *child = node->inputs[i].src_node;
+
+ if (!child)
+ continue;
+ else if (ENGINE_NODE_IS_SCHEDULED (child))
+ {
+ leaf_level = MAX (leaf_level, child->sched_leaf_level + 1);
+ continue;
+ }
+ else if (child->sched_router_tag) /* cycle */
+ {
+ query_add_cycle (query, child, node);
+ }
+ else /* nice boy ;) */
+ {
+ EngineQuery child_query = { 0, };
+
+ subschedule_query_node (schedule, child, &child_query);
+ leaf_level = MAX (leaf_level, child_query.leaf_level + 1);
+ if (!child_query.cycles)
+ {
+ g_assert (child_query.cycle_nodes == NULL); /* paranoid */
+ _engine_schedule_node (schedule, child, child_query.leaf_level);
+ }
+ else if (master_resolve_cycles (&child_query, child))
+ {
+ g_assert (child == child_query.cycle_nodes->data); /* paranoid */
+ _engine_schedule_cycle (schedule, child_query.cycle_nodes, child_query.leaf_level);
+ child_query.cycle_nodes = NULL;
+ }
+ else
+ query_merge_cycles (query, &child_query, node);
+ g_assert (child_query.cycles == NULL); /* paranoid */
+ g_assert (child_query.cycle_nodes == NULL); /* paranoid */
+ }
+ }
+ for (j = 0; j < ENGINE_NODE_N_JSTREAMS (node); j++)
+ for (i = 0; i < node->module.jstreams[j].n_connections; i++)
+ {
+ EngineNode *child = node->jinputs[j][i].src_node;
+
+ if (ENGINE_NODE_IS_SCHEDULED (child))
+ {
+ leaf_level = MAX (leaf_level, child->sched_leaf_level + 1);
+ continue;
+ }
+ else if (child->sched_router_tag) /* cycle */
+ {
+ query_add_cycle (query, child, node);
+ }
+ else /* nice boy ;) */
+ {
+ EngineQuery child_query = { 0, };
+
+ subschedule_query_node (schedule, child, &child_query);
+ leaf_level = MAX (leaf_level, child_query.leaf_level + 1);
+ if (!child_query.cycles)
+ {
+ g_assert (child_query.cycle_nodes == NULL); /* paranoid */
+ _engine_schedule_node (schedule, child, child_query.leaf_level);
+ }
+ else if (master_resolve_cycles (&child_query, child))
+ {
+ g_assert (child == child_query.cycle_nodes->data); /* paranoid */
+ _engine_schedule_cycle (schedule, child_query.cycle_nodes, child_query.leaf_level);
+ child_query.cycle_nodes = NULL;
+ }
+ else
+ query_merge_cycles (query, &child_query, node);
+ g_assert (child_query.cycles == NULL); /* paranoid */
+ g_assert (child_query.cycle_nodes == NULL); /* paranoid */
+ }
+ }
+ query->leaf_level = leaf_level;
+ node->counter = GSL_TICK_STAMP;
+ node->sched_router_tag = FALSE;
+ SCHED_DEBUG ("end_query(%p)", node);
+}
+
+void
+_engine_schedule_consumer_node (EngineSchedule *schedule,
+ EngineNode *node)
+{
+ EngineQuery query = { 0, };
+
+ g_return_if_fail (schedule != NULL);
+ g_return_if_fail (schedule->secured == FALSE);
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (ENGINE_NODE_IS_CONSUMER (node));
+
+ subschedule_query_node (schedule, node, &query);
+ g_assert (query.cycles == NULL); /* paranoid */
+ g_assert (query.cycle_nodes == NULL); /* paranoid */
+ _engine_schedule_node (schedule, node, query.leaf_level);
+}
diff --git a/flow/gsl/gslopschedule.h b/flow/gsl/gslopschedule.h
new file mode 100644
index 0000000..a2b5281
--- /dev/null
+++ b/flow/gsl/gslopschedule.h
@@ -0,0 +1,79 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_ENGINE_SCHEDULE_H__
+#define __GSL_ENGINE_SCHEDULE_H__
+
+#include <gsl/gslopnode.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct
+{
+ EngineNode *last; /* resolve node */
+ GslRing *nodes; /* of type EngineNode* */
+ guint seen_deferred_node : 1;
+} EngineCycle;
+typedef struct
+{
+ guint leaf_level;
+ GslRing *cycles; /* of type Cycle* */
+ GslRing *cycle_nodes; /* of type EngineNode* */
+} EngineQuery;
+struct _EngineSchedule
+{
+ guint n_items;
+ guint leaf_levels;
+ GslRing **nodes; /* EngineNode* */
+ GslRing **cycles; /* GslRing* */
+ guint secured : 1;
+ guint in_pqueue : 1;
+ guint cur_leaf_level;
+ GslRing *cur_node;
+ GslRing *cur_cycle;
+};
+#define GSL_SCHEDULE_NONPOPABLE(schedule) ((schedule)->cur_leaf_level >= (schedule)->leaf_levels)
+
+
+/* --- MasterThread --- */
+EngineSchedule* _engine_schedule_new (void);
+void _engine_schedule_clear (EngineSchedule *schedule);
+void _engine_schedule_destroy (EngineSchedule *schedule);
+void _engine_schedule_consumer_node (EngineSchedule *schedule,
+ EngineNode *node);
+void _engine_schedule_node (EngineSchedule *schedule,
+ EngineNode *node,
+ guint leaf_level);
+void _engine_schedule_cycle (EngineSchedule *schedule,
+ GslRing *cycle_nodes,
+ guint leaf_level);
+void _engine_schedule_secure (EngineSchedule *schedule);
+EngineNode* _engine_schedule_pop_node (EngineSchedule *schedule);
+GslRing* _engine_schedule_pop_cycle (EngineSchedule *schedule);
+void _engine_schedule_restart (EngineSchedule *schedule);
+void _engine_schedule_unsecure (EngineSchedule *schedule);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_ENGINE_SCHEDULE_H__ */
diff --git a/flow/gsl/gsloputil.c b/flow/gsl/gsloputil.c
new file mode 100644
index 0000000..9adce89
--- /dev/null
+++ b/flow/gsl/gsloputil.c
@@ -0,0 +1,721 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsloputil.h"
+
+#include "gslcommon.h"
+#include "gslopnode.h"
+#include "gslopschedule.h"
+#include "gslsignal.h"
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+
+
+/* --- UserThread --- */
+GslOStream*
+_engine_alloc_ostreams (guint n)
+{
+ if (n)
+ {
+ guint i = sizeof (GslOStream) * n + sizeof (gfloat) * gsl_engine_block_size () * n;
+ GslOStream *streams = gsl_alloc_memblock0 (i);
+ gfloat *buffers = (gfloat*) (streams + n);
+
+ for (i = 0; i < n; i++)
+ {
+ streams[i].values = buffers;
+ buffers += gsl_engine_block_size ();
+ }
+ return streams;
+ }
+ else
+ return NULL;
+}
+
+static void
+free_node (EngineNode *node)
+{
+ guint j;
+
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (node->output_nodes == NULL);
+ g_return_if_fail (node->integrated == FALSE);
+ g_return_if_fail (node->sched_tag == FALSE);
+ g_return_if_fail (node->sched_router_tag == FALSE);
+
+ if (node->module.klass->free)
+ node->module.klass->free (node->module.user_data, node->module.klass);
+ gsl_rec_mutex_destroy (&node->rec_mutex);
+ if (node->module.ostreams)
+ {
+ guint n = ENGINE_NODE_N_OSTREAMS (node);
+ guint i = sizeof (GslOStream) * n + sizeof (gfloat) * gsl_engine_block_size () * n;
+
+ gsl_free_memblock (i, node->module.ostreams);
+ gsl_delete_structs (EngineOutput, ENGINE_NODE_N_OSTREAMS (node), node->outputs);
+ }
+ if (node->module.istreams)
+ {
+ gsl_delete_structs (GslIStream, ENGINE_NODE_N_ISTREAMS (node), node->module.istreams);
+ gsl_delete_structs (EngineInput, ENGINE_NODE_N_ISTREAMS (node), node->inputs);
+ }
+ for (j = 0; j < ENGINE_NODE_N_JSTREAMS (node); j++)
+ {
+ g_free (node->jinputs[j]);
+ g_free (node->module.jstreams[j].values);
+ }
+ if (node->module.jstreams)
+ {
+ gsl_delete_structs (GslJStream, ENGINE_NODE_N_JSTREAMS (node), node->module.jstreams);
+ gsl_delete_structs (EngineJInput*, ENGINE_NODE_N_JSTREAMS (node), node->jinputs);
+ }
+ gsl_delete_struct (EngineNode, node);
+}
+
+static void
+free_job (GslJob *job)
+{
+ g_return_if_fail (job != NULL);
+
+ switch (job->job_id)
+ {
+ case ENGINE_JOB_ACCESS:
+ if (job->data.access.free_func)
+ job->data.access.free_func (job->data.access.data);
+ break;
+ case ENGINE_JOB_DEBUG:
+ g_free (job->data.debug);
+ break;
+ case ENGINE_JOB_ADD_POLL:
+ case ENGINE_JOB_REMOVE_POLL:
+ g_free (job->data.poll.fds);
+ if (job->data.poll.free_func)
+ job->data.poll.free_func (job->data.poll.data);
+ break;
+ case ENGINE_JOB_DISCARD:
+ free_node (job->data.node);
+ break;
+ default: ;
+ }
+ gsl_delete_struct (GslJob, job);
+}
+
+static void
+free_flow_job (EngineFlowJob *fjob)
+{
+ switch (fjob->fjob_id)
+ {
+ case ENGINE_FLOW_JOB_SUSPEND:
+ case ENGINE_FLOW_JOB_RESUME:
+ gsl_delete_struct (EngineFlowJobAny, &fjob->any);
+ break;
+ case ENGINE_FLOW_JOB_ACCESS:
+ if (fjob->access.free_func)
+ fjob->access.free_func (fjob->access.data);
+ gsl_delete_struct (EngineFlowJobAccess, &fjob->access);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+void
+_engine_free_trans (GslTrans *trans)
+{
+ GslJob *job;
+
+ g_return_if_fail (trans != NULL);
+ g_return_if_fail (trans->comitted == FALSE);
+ if (trans->jobs_tail)
+ g_return_if_fail (trans->jobs_tail->next == NULL); /* paranoid */
+
+ job = trans->jobs_head;
+ while (job)
+ {
+ GslJob *tmp = job->next;
+
+ free_job (job);
+ job = tmp;
+ }
+ gsl_delete_struct (GslTrans, trans);
+}
+
+
+/* -- master node list --- */
+static EngineNode *master_node_list_head = NULL;
+static EngineNode *master_node_list_tail = NULL;
+
+EngineNode*
+_engine_mnl_head (void)
+{
+ return master_node_list_head;
+}
+
+void
+_engine_mnl_remove (EngineNode *node)
+{
+ g_return_if_fail (node->integrated == TRUE);
+
+ node->integrated = FALSE;
+ /* remove */
+ if (node->mnl_prev)
+ node->mnl_prev->mnl_next = node->mnl_next;
+ else
+ master_node_list_head = node->mnl_next;
+ if (node->mnl_next)
+ node->mnl_next->mnl_prev = node->mnl_prev;
+ else
+ master_node_list_tail = node->mnl_prev;
+ node->mnl_prev = NULL;
+ node->mnl_next = NULL;
+}
+
+void
+_engine_mnl_integrate (EngineNode *node)
+{
+ g_return_if_fail (node->integrated == FALSE);
+ g_return_if_fail (node->flow_jobs == NULL);
+
+ node->integrated = TRUE;
+ /* append */
+ if (master_node_list_tail)
+ master_node_list_tail->mnl_next = node;
+ node->mnl_prev = master_node_list_tail;
+ master_node_list_tail = node;
+ if (!master_node_list_head)
+ master_node_list_head = master_node_list_tail;
+ g_assert (node->mnl_next == NULL);
+}
+
+void
+_engine_mnl_reorder (EngineNode *node)
+{
+ EngineNode *sibling;
+
+ g_return_if_fail (node->integrated == TRUE);
+
+ /* the master node list is partially sorted. that is, all
+ * nodes which are not scheduled and have pending flow_jobs
+ * are agglomerated at the head.
+ */
+ sibling = node->mnl_prev ? node->mnl_prev : node->mnl_next;
+ if (sibling && GSL_MNL_HEAD_NODE (node) != GSL_MNL_HEAD_NODE (sibling))
+ {
+ /* remove */
+ if (node->mnl_prev)
+ node->mnl_prev->mnl_next = node->mnl_next;
+ else
+ master_node_list_head = node->mnl_next;
+ if (node->mnl_next)
+ node->mnl_next->mnl_prev = node->mnl_prev;
+ else
+ master_node_list_tail = node->mnl_prev;
+ if (GSL_MNL_HEAD_NODE (node)) /* move towards head */
+ {
+ /* prepend to non-NULL list */
+ master_node_list_head->mnl_prev = node;
+ node->mnl_next = master_node_list_head;
+ master_node_list_head = node;
+ node->mnl_prev = NULL;
+ }
+ else /* move towards tail */
+ {
+ /* append to non-NULL list */
+ master_node_list_tail->mnl_next = node;
+ node->mnl_prev = master_node_list_tail;
+ master_node_list_tail = node;
+ node->mnl_next = NULL;
+ }
+ }
+}
+
+
+/* --- const value blocks --- */
+typedef struct
+{
+ guint n_nodes;
+ gfloat **nodes;
+ guint8 *nodes_used;
+} ConstValuesArray;
+
+static const guint8 CONST_VALUES_EXPIRE = 16; /* expire value after being unused for 16 times */
+
+static inline gfloat**
+const_values_lookup_nextmost (ConstValuesArray *array,
+ gfloat key_value)
+{
+ guint n_nodes = array->n_nodes;
+
+ if (n_nodes > 0)
+ {
+ gfloat **nodes = array->nodes;
+ gfloat **check;
+
+ nodes -= 1;
+ do
+ {
+ guint i;
+ register gfloat cmp;
+
+ i = (n_nodes + 1) >> 1;
+ check = nodes + i;
+ cmp = key_value - **check;
+ if (cmp > GSL_SIGNAL_EPSILON)
+ {
+ n_nodes -= i;
+ nodes = check;
+ }
+ else if (cmp < -GSL_SIGNAL_EPSILON)
+ n_nodes = i - 1;
+ else /* cmp ~==~ 0.0 */
+ return check; /* matched */
+ }
+ while (n_nodes);
+
+ return check; /* nextmost */
+ }
+
+ return NULL;
+}
+
+static inline guint
+upper_power2 (guint number)
+{
+ return gsl_alloc_upper_power2 (MAX (number, 8));
+}
+
+static inline void
+const_values_insert (ConstValuesArray *array,
+ guint index,
+ gfloat *value_block)
+{
+ if (array->n_nodes == 0)
+ {
+ guint new_size = upper_power2 (sizeof (gfloat*));
+
+ array->nodes = g_realloc (array->nodes, new_size);
+ array->nodes_used = g_realloc (array->nodes_used, new_size / sizeof (gfloat*));
+ array->n_nodes = 1;
+
+ g_assert (index == 0);
+ }
+ else
+ {
+ guint n_nodes = array->n_nodes++;
+
+ if (*array->nodes[index] < *value_block)
+ index++;
+
+ if (1)
+ {
+ guint new_size = upper_power2 (array->n_nodes * sizeof (gfloat*));
+ guint old_size = upper_power2 (n_nodes * sizeof (gfloat*));
+
+ if (new_size != old_size)
+ {
+ array->nodes = g_realloc (array->nodes, new_size);
+ array->nodes_used = g_realloc (array->nodes_used, new_size / sizeof(gfloat*));
+ }
+ }
+ g_memmove (array->nodes + index + 1, array->nodes + index, (n_nodes - index) * sizeof (array->nodes[0]));
+ g_memmove (array->nodes_used + index + 1, array->nodes_used + index, (n_nodes - index) * sizeof (array->nodes_used[0]));
+ }
+
+ array->nodes[index] = value_block;
+ array->nodes_used[index] = CONST_VALUES_EXPIRE;
+}
+
+static ConstValuesArray cvalue_array = { 0, NULL, NULL };
+
+gfloat*
+gsl_engine_const_values (gfloat value)
+{
+ extern const gfloat gsl_engine_master_zero_block[];
+ gfloat **block;
+
+ if (fabs (value) < GSL_SIGNAL_EPSILON)
+ return (gfloat*) gsl_engine_master_zero_block;
+
+ block = const_values_lookup_nextmost (&cvalue_array, value);
+
+ /* found correct match? */
+ if (block && fabs (**block - value) < GSL_SIGNAL_EPSILON)
+ {
+ cvalue_array.nodes_used[block - cvalue_array.nodes] = CONST_VALUES_EXPIRE;
+ return *block;
+ }
+ else
+ {
+ /* create new value block */
+ gfloat *values = g_new (gfloat, gsl_engine_block_size ());
+ guint i;
+
+ for (i = 0; i < gsl_engine_block_size (); i++)
+ values[i] = value;
+
+ if (block)
+ const_values_insert (&cvalue_array, block - cvalue_array.nodes, values);
+ else
+ const_values_insert (&cvalue_array, 0, values);
+
+ return values;
+ }
+}
+
+void
+_engine_recycle_const_values (void)
+{
+ gfloat **nodes = cvalue_array.nodes;
+ guint8 *used = cvalue_array.nodes_used;
+ guint count = cvalue_array.n_nodes, e = 0, i;
+
+ for (i = 0; i < count; i++)
+ {
+ used[i]--; /* invariant: use counts are never 0 */
+
+ if (used[i] == 0)
+ g_free (nodes[i]);
+ else /* preserve node */
+ {
+ if (e < i)
+ {
+ nodes[e] = nodes[i];
+ used[e] = used[i];
+ }
+ e++;
+ }
+ }
+ cvalue_array.n_nodes = e;
+}
+
+/* --- job transactions --- */
+static GslMutex cqueue_trans = { 0, };
+static GslTrans *cqueue_trans_pending_head = NULL;
+static GslTrans *cqueue_trans_pending_tail = NULL;
+static GslCond cqueue_trans_cond = { 0, };
+static GslTrans *cqueue_trans_trash = NULL;
+static GslTrans *cqueue_trans_active_head = NULL;
+static GslTrans *cqueue_trans_active_tail = NULL;
+static EngineFlowJob *cqueue_trash_fjobs = NULL;
+static GslJob *cqueue_trans_job = NULL;
+
+void
+_engine_enqueue_trans (GslTrans *trans)
+{
+ g_return_if_fail (trans != NULL);
+ g_return_if_fail (trans->comitted == TRUE);
+ g_return_if_fail (trans->jobs_head != NULL);
+ g_return_if_fail (trans->cqt_next == NULL);
+
+ GSL_SPIN_LOCK (&cqueue_trans);
+ if (cqueue_trans_pending_tail)
+ {
+ cqueue_trans_pending_tail->cqt_next = trans;
+ cqueue_trans_pending_tail->jobs_tail->next = trans->jobs_head;
+ }
+ else
+ cqueue_trans_pending_head = trans;
+ cqueue_trans_pending_tail = trans;
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+ gsl_cond_signal (&cqueue_trans_cond);
+}
+
+void
+_engine_wait_on_trans (void)
+{
+ GSL_SPIN_LOCK (&cqueue_trans);
+ while (cqueue_trans_pending_head || cqueue_trans_active_head)
+ gsl_cond_wait (&cqueue_trans_cond, &cqueue_trans);
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+}
+
+gboolean
+_engine_job_pending (void)
+{
+ gboolean pending = cqueue_trans_job != NULL;
+
+ if (!pending)
+ {
+ GSL_SPIN_LOCK (&cqueue_trans);
+ pending = cqueue_trans_pending_head != NULL;
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+ }
+ return pending;
+}
+
+GslJob*
+_engine_pop_job (void) /* (glong max_useconds) */
+{
+ /* clean up if necessary and try fetching new jobs */
+ if (!cqueue_trans_job)
+ {
+ if (cqueue_trans_active_head)
+ {
+ GSL_SPIN_LOCK (&cqueue_trans);
+ /* get rid of processed transaction and
+ * signal UserThread which might be in
+ * op_com_wait_on_trans()
+ */
+ cqueue_trans_active_tail->cqt_next = cqueue_trans_trash;
+ cqueue_trans_trash = cqueue_trans_active_head;
+ /* fetch new transaction */
+ cqueue_trans_active_head = cqueue_trans_pending_head;
+ cqueue_trans_active_tail = cqueue_trans_pending_tail;
+ cqueue_trans_pending_head = NULL;
+ cqueue_trans_pending_tail = NULL;
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+ gsl_cond_signal (&cqueue_trans_cond);
+ }
+ else
+ {
+ GSL_SPIN_LOCK (&cqueue_trans);
+ /* fetch new transaction */
+ cqueue_trans_active_head = cqueue_trans_pending_head;
+ cqueue_trans_active_tail = cqueue_trans_pending_tail;
+ cqueue_trans_pending_head = NULL;
+ cqueue_trans_pending_tail = NULL;
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+ }
+ cqueue_trans_job = cqueue_trans_active_head ? cqueue_trans_active_head->jobs_head : NULL;
+ }
+
+ /* pick new job and out of here */
+ if (cqueue_trans_job)
+ {
+ GslJob *job = cqueue_trans_job;
+
+ cqueue_trans_job = job->next;
+ return job;
+ }
+
+#if 0
+ /* wait until jobs are present */
+ if (max_useconds != 0)
+ {
+ GSL_SPIN_LOCK (&cqueue_trans);
+ if (!cqueue_trans_pending_head)
+ gsl_cond_wait_timed (&cqueue_trans_cond,
+ &cqueue_trans,
+ max_useconds);
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+
+ /* there may be jobs now, start from scratch */
+ return op_com_pop_job_timed (max_useconds < 0 ? -1 : 0);
+ }
+#endif
+
+ /* time expired, no jobs... */
+ return NULL;
+}
+
+
+/* --- user thread garbage collection --- */
+/**
+ * gsl_engine_garbage_collect
+ *
+ * GSL Engine user thread function. Collects processed jobs
+ * and transactions from the engine and frees them, this
+ * involves callback invocation of GslFreeFunc() functions,
+ * e.g. from gsl_job_access() or gsl_flow_job_access()
+ * jobs.
+ * This function may only be called from the user thread,
+ * as GslFreeFunc() functions are guranteed to be executed
+ * in the user thread.
+ */
+void
+gsl_engine_garbage_collect (void)
+{
+ GslTrans *trans;
+ EngineFlowJob *fjobs;
+
+ GSL_SPIN_LOCK (&cqueue_trans);
+ trans = cqueue_trans_trash;
+ cqueue_trans_trash = NULL;
+ fjobs = cqueue_trash_fjobs;
+ cqueue_trash_fjobs = NULL;
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+
+ while (trans)
+ {
+ GslTrans *t = trans;
+
+ trans = t->cqt_next;
+ t->cqt_next = NULL;
+ t->jobs_tail->next = NULL;
+ t->comitted = FALSE;
+ _engine_free_trans (t);
+ }
+
+ while (fjobs)
+ {
+ EngineFlowJob *j = fjobs;
+
+ fjobs = j->any.next;
+ j->any.next = NULL;
+ free_flow_job (j);
+ }
+}
+
+
+/* --- node processing queue --- */
+static GslMutex pqueue_mutex = { 0, };
+static EngineSchedule *pqueue_schedule = NULL;
+static guint pqueue_n_nodes = 0;
+static guint pqueue_n_cycles = 0;
+static GslCond pqueue_done_cond = { 0, };
+static EngineFlowJob *pqueue_trash_fjobs_first = NULL;
+static EngineFlowJob *pqueue_trash_fjobs_last = NULL;
+
+void
+_engine_set_schedule (EngineSchedule *sched)
+{
+ g_return_if_fail (sched != NULL);
+ g_return_if_fail (sched->secured == TRUE);
+
+ GSL_SPIN_LOCK (&pqueue_mutex);
+ if_reject (pqueue_schedule)
+ {
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+ g_warning (G_STRLOC ": schedule already set");
+ return;
+ }
+ pqueue_schedule = sched;
+ sched->in_pqueue = TRUE;
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+}
+
+void
+_engine_unset_schedule (EngineSchedule *sched)
+{
+ EngineFlowJob *trash_fjobs_first, *trash_fjobs_last;
+
+ g_return_if_fail (sched != NULL);
+
+ GSL_SPIN_LOCK (&pqueue_mutex);
+ if_reject (pqueue_schedule != sched)
+ {
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+ g_warning (G_STRLOC ": schedule(%p) not currently set", sched);
+ return;
+ }
+ if_reject (pqueue_n_nodes || pqueue_n_cycles)
+ g_warning (G_STRLOC ": schedule(%p) still busy", sched);
+
+ sched->in_pqueue = FALSE;
+ pqueue_schedule = NULL;
+ trash_fjobs_first = pqueue_trash_fjobs_first;
+ trash_fjobs_last = pqueue_trash_fjobs_last;
+ pqueue_trash_fjobs_first = NULL;
+ pqueue_trash_fjobs_last = NULL;
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+
+ if (trash_fjobs_first) /* move trash flow jobs */
+ {
+ GSL_SPIN_LOCK (&cqueue_trans);
+ trash_fjobs_last->any.next = cqueue_trash_fjobs;
+ cqueue_trash_fjobs = trash_fjobs_first;
+ GSL_SPIN_UNLOCK (&cqueue_trans);
+ }
+}
+
+EngineNode*
+_engine_pop_unprocessed_node (void)
+{
+ EngineNode *node;
+
+ GSL_SPIN_LOCK (&pqueue_mutex);
+ node = pqueue_schedule ? _engine_schedule_pop_node (pqueue_schedule) : NULL;
+ if (node)
+ pqueue_n_nodes += 1;
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+
+ if (node)
+ ENGINE_NODE_LOCK (node);
+
+ return node;
+}
+
+void
+_engine_push_processed_node (EngineNode *node)
+{
+ g_return_if_fail (node != NULL);
+ g_return_if_fail (pqueue_n_nodes > 0);
+ g_return_if_fail (ENGINE_NODE_IS_SCHEDULED (node));
+
+ GSL_SPIN_LOCK (&pqueue_mutex);
+ g_assert (pqueue_n_nodes > 0); /* paranoid */
+ if (node->fjob_first) /* collect trash flow jobs */
+ {
+ node->fjob_last->any.next = pqueue_trash_fjobs_first;
+ pqueue_trash_fjobs_first = node->fjob_first;
+ if (!pqueue_trash_fjobs_last)
+ pqueue_trash_fjobs_last = node->fjob_last;
+ node->fjob_first = NULL;
+ node->fjob_last = NULL;
+ }
+ pqueue_n_nodes -= 1;
+ ENGINE_NODE_UNLOCK (node);
+ if (!pqueue_n_nodes && !pqueue_n_cycles && GSL_SCHEDULE_NONPOPABLE (pqueue_schedule))
+ gsl_cond_signal (&pqueue_done_cond);
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+}
+
+GslRing*
+_engine_pop_unprocessed_cycle (void)
+{
+ return NULL;
+}
+
+void
+_engine_push_processed_cycle (GslRing *cycle)
+{
+ g_return_if_fail (cycle != NULL);
+ g_return_if_fail (pqueue_n_cycles > 0);
+ g_return_if_fail (ENGINE_NODE_IS_SCHEDULED (cycle->data));
+}
+
+void
+_engine_wait_on_unprocessed (void)
+{
+ GSL_SPIN_LOCK (&pqueue_mutex);
+ while (pqueue_n_nodes || pqueue_n_cycles || !GSL_SCHEDULE_NONPOPABLE (pqueue_schedule))
+ gsl_cond_wait (&pqueue_done_cond, &pqueue_mutex);
+ GSL_SPIN_UNLOCK (&pqueue_mutex);
+}
+
+
+/* --- initialization --- */
+void
+_gsl_init_engine_utils (void)
+{
+ static gboolean initialized = FALSE;
+
+ g_assert (initialized == FALSE); /* single invocation */
+ initialized++;
+
+ gsl_mutex_init (&cqueue_trans);
+ gsl_cond_init (&cqueue_trans_cond);
+ gsl_mutex_init (&pqueue_mutex);
+ gsl_cond_init (&pqueue_done_cond);
+}
+
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gsloputil.h b/flow/gsl/gsloputil.h
new file mode 100644
index 0000000..9089770
--- /dev/null
+++ b/flow/gsl/gsloputil.h
@@ -0,0 +1,86 @@
+/* GSL Engine - Flow module operation engine
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_ENGINE_UTIL_H__
+#define __GSL_ENGINE_UTIL_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- typedefs --- */
+typedef struct _EngineNode EngineNode;
+typedef struct _EngineSchedule EngineSchedule;
+
+
+/* --- UserThread --- */
+void _engine_free_trans (GslTrans *trans);
+GslOStream* _engine_alloc_ostreams (guint n);
+#if 0 /* gslengine.h: */
+void gsl_engine_garbage_collect (void);
+gfloat* gsl_engine_const_values (gfloat value);
+#endif
+
+
+/* --- MasterThread --- */
+void _engine_recycle_const_values (void);
+/* master node list */
+void _engine_mnl_remove (EngineNode *node);
+void _engine_mnl_reorder (EngineNode *node);
+void _engine_mnl_integrate (EngineNode *node);
+#define GSL_MNL_HEAD_NODE(node) ((node)->flow_jobs && !(node)->sched_tag)
+EngineNode* _engine_mnl_head (void);
+
+/* communication routines for threads:
+ * UserThread - main application
+ * MasterThread - op engine control thread
+ * SlaveThread - op engine calculation threads
+ *
+ * these functions are for _internal_ use of gslop*.c implementations
+ */
+
+/* --- job transactions --- */
+/* UserThread */
+void _engine_enqueue_trans (GslTrans *trans);
+GslTrans* _engine_collect_trans (void);
+void _engine_wait_on_trans (void);
+/* MasterThread */
+/* GslJob* _engine_pop_job_timed (glong max_useconds); */
+GslJob* _engine_pop_job (void);
+gboolean _engine_job_pending (void);
+
+
+/* --- node processing queue --- */
+void _engine_set_schedule (EngineSchedule *schedule);
+void _engine_unset_schedule (EngineSchedule *schedule);
+EngineNode* _engine_pop_unprocessed_node (void);
+void _engine_push_processed_node (EngineNode *node);
+GslRing* _engine_pop_unprocessed_cycle (void);
+void _engine_push_processed_cycle (GslRing *cycle);
+void _engine_wait_on_unprocessed (void);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_ENGINE_UTIL_H__ */
diff --git a/flow/gsl/gsloscillator-aux.c b/flow/gsl/gsloscillator-aux.c
new file mode 100644
index 0000000..d755bc5
--- /dev/null
+++ b/flow/gsl/gsloscillator-aux.c
@@ -0,0 +1,214 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 1999, 2000-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#define OSC_FLAGS (GSL_INCLUDER_CASE | OSC_INCLUDER_FLAGS)
+#define ISYNC1_OSYNC0 ((OSC_FLAGS & OSC_FLAG_ISYNC) && !(OSC_FLAGS & OSC_FLAG_OSYNC))
+#define ISYNC1_OSYNC1 ((OSC_FLAGS & OSC_FLAG_ISYNC) && (OSC_FLAGS & OSC_FLAG_OSYNC))
+#define ISYNC0_OSYNC1 ((OSC_FLAGS & OSC_FLAG_OSYNC) && !(OSC_FLAGS & OSC_FLAG_ISYNC))
+#define WITH_OSYNC (OSC_FLAGS & OSC_FLAG_OSYNC)
+#define WITH_FREQ (OSC_FLAGS & OSC_FLAG_FREQ)
+#define WITH_SMOD (OSC_FLAGS & OSC_FLAG_SELF_MOD)
+#define WITH_LMOD (OSC_FLAGS & OSC_FLAG_LINEAR_MOD)
+#define WITH_EMOD (OSC_FLAGS & OSC_FLAG_EXP_MOD)
+#define WITH_PWM_MOD (OSC_FLAGS & OSC_FLAG_PWM_MOD)
+#define PULSE_OSC (OSC_FLAGS & OSC_FLAG_PULSE_OSC)
+
+
+static void
+GSL_INCLUDER_FUNC (GslOscData *osc,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *mod_in,
+ const gfloat *sync_in,
+ const gfloat *pwm_in,
+ gfloat *mono_out,
+ gfloat *sync_out)
+{
+ gfloat last_sync_level = osc->last_sync_level;
+ gfloat last_pwm_level = osc->last_pwm_level;
+ gdouble last_freq_level = osc->last_freq_level;
+ guint32 cur_pos = osc->cur_pos;
+ guint32 last_pos = osc->last_pos;
+ guint32 sync_pos, pos_inc;
+ gfloat posm_strength, self_posm_strength;
+ gfloat *boundary = mono_out + n_values;
+ GslOscWave *wave = &osc->wave;
+
+ /* FIXME: should we do gsl_fpu_setround() here? */
+
+ pos_inc = gsl_dtoi (osc->last_freq_level * gsl_cent_factor (osc->config.fine_tune) * wave->freq_to_step);
+ sync_pos = osc->config.phase * wave->phase_to_pos;
+ posm_strength = pos_inc * osc->config.fm_strength;
+ self_posm_strength = pos_inc * osc->config.self_fm_strength;
+
+ /* do the mixing */
+ do
+ {
+ gfloat v;
+
+ /* handle syncs
+ */
+#if (ISYNC1_OSYNC0) /* input sync only */
+ {
+ gfloat sync_level = *sync_in++;
+ if_reject (GSL_SIGNAL_RAISING_EDGE (last_sync_level, sync_level))
+ cur_pos = sync_pos;
+ last_sync_level = sync_level;
+ }
+#elif (ISYNC1_OSYNC1) /* input and output sync */
+ {
+ gfloat sync_level = *sync_in++;
+ if_reject (GSL_SIGNAL_RAISING_EDGE (last_sync_level, sync_level))
+ {
+ cur_pos = sync_pos;
+ *sync_out++ = 1.0;
+ }
+ else /* figure output sync position */
+ {
+ guint is_sync = (sync_pos <= cur_pos) + (last_pos < sync_pos) + (cur_pos < last_pos);
+ *sync_out++ = is_sync >= 2 ? 1.0 : 0.0;
+ }
+ last_sync_level = sync_level;
+ }
+#elif (ISYNC0_OSYNC1) /* output sync only */
+ {
+ /* figure output sync position */
+ guint is_sync = (sync_pos <= cur_pos) + (last_pos < sync_pos) + (cur_pos < last_pos);
+ *sync_out++ = is_sync >= 2 ? 1.0 : 0.0;
+ }
+#endif
+
+ /* track frequency changes
+ */
+#if (WITH_FREQ)
+ {
+ gdouble freq_level = *ifreq++;
+ freq_level = GSL_SIGNAL_TO_FREQ (freq_level);
+ if (GSL_SIGNAL_FREQ_CHANGED (last_freq_level, freq_level))
+ {
+ if_reject (freq_level <= wave->min_freq || freq_level > wave->max_freq)
+ {
+ gdouble fcpos, flpos;
+ const gfloat *orig_values = wave->values;
+
+ fcpos = cur_pos * wave->ifrac_to_float;
+ flpos = last_pos * wave->ifrac_to_float;
+ gsl_osc_table_lookup (osc->config.table, freq_level, wave);
+ if (orig_values != wave->values) /* catch non-changes */
+ {
+ last_pos = flpos / wave->ifrac_to_float;
+ cur_pos = fcpos / wave->ifrac_to_float;
+ sync_pos = osc->config.phase * wave->phase_to_pos;
+ pos_inc = gsl_dtoi (freq_level * gsl_cent_factor (osc->config.fine_tune) * wave->freq_to_step);
+#if (PULSE_OSC)
+ osc->last_pwm_level = 0;
+ osc_update_pwm_offset (osc, osc->last_pwm_level);
+ last_pwm_level = osc->last_pwm_level;
+#endif
+ }
+ }
+ else
+ pos_inc = gsl_dtoi (freq_level * gsl_cent_factor (osc->config.fine_tune) * wave->freq_to_step);
+ posm_strength = pos_inc * osc->config.fm_strength;
+ self_posm_strength = pos_inc * osc->config.self_fm_strength;
+ last_freq_level = freq_level;
+ }
+ }
+#endif
+
+ /* track pulse witdh modulation
+ */
+#if (WITH_PWM_MOD)
+ {
+ gfloat pwm_level = *pwm_in++;
+ if (fabs (last_pwm_level - pwm_level) > 1.0 / 65536.0)
+ {
+ last_pwm_level = pwm_level;
+ osc_update_pwm_offset (osc, pwm_level);
+ }
+ }
+#endif
+
+ /* output signal calculation
+ */
+#if (PULSE_OSC) /* pulse width modulation oscillator */
+ {
+ guint32 tpos, ipos;
+ tpos = cur_pos >> wave->n_frac_bits;
+ ipos = (cur_pos - osc->pwm_offset) >> wave->n_frac_bits;
+ v = wave->values[tpos] - wave->values[ipos];
+ v = (v + osc->pwm_center) * osc->pwm_max;
+ }
+#else /* table read out and linear ipol */
+ {
+ guint32 tpos, ifrac;
+ gfloat ffrac, w;
+ tpos = cur_pos >> wave->n_frac_bits;
+ ifrac = cur_pos & wave->frac_bitmask;
+ ffrac = ifrac * wave->ifrac_to_float;
+ v = wave->values[tpos];
+ w = wave->values[tpos + 1];
+ v *= 1.0 - ffrac;
+ w *= ffrac;
+ v += w;
+ }
+#endif /* v = value_out done */
+ *mono_out++ = v;
+
+ /* position increment
+ */
+#if (WITH_OSYNC)
+ last_pos = cur_pos;
+#endif
+#if (WITH_SMOD) /* self modulation */
+ cur_pos += self_posm_strength * v;
+#endif
+#if (WITH_LMOD) /* linear fm */
+ {
+ gfloat mod_level = *mod_in++;
+ cur_pos += pos_inc + posm_strength * mod_level;
+ }
+#elif (WITH_EMOD) /* exponential fm */
+ {
+ gfloat mod_level = *mod_in++;
+ cur_pos += pos_inc * gsl_signal_exp2 (osc->config.fm_strength * mod_level);
+ }
+#else /* no modulation */
+ cur_pos += pos_inc;
+#endif
+ }
+ while (mono_out < boundary);
+
+ osc->last_pos = WITH_OSYNC ? last_pos : cur_pos;
+ osc->cur_pos = cur_pos;
+ osc->last_sync_level = last_sync_level;
+ osc->last_freq_level = last_freq_level;
+ osc->last_pwm_level = last_pwm_level;
+}
+
+#undef ISYNC1_OSYNC0
+#undef ISYNC1_OSYNC1
+#undef ISYNC0_OSYNC1
+#undef WITH_OSYNC
+#undef WITH_FREQ
+#undef WITH_SMOD
+#undef WITH_LMOD
+#undef WITH_EMOD
+#undef OSC_FLAGS
diff --git a/flow/gsl/gsloscillator.c b/flow/gsl/gsloscillator.c
new file mode 100644
index 0000000..0747cff
--- /dev/null
+++ b/flow/gsl/gsloscillator.c
@@ -0,0 +1,219 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 1999, 2000-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gsloscillator.h"
+
+#include "gslsignal.h"
+
+#define SIGNAL_LEVEL_INVAL (-2.0) /* trigger level-changed checks */
+
+
+/* --- functions --- */
+static inline void
+osc_update_pwm_offset (GslOscData *osc,
+ gfloat pulse_mod) /* -1..+1 */
+{
+ guint32 maxp_offs, minp_offs, mpos, tpos;
+ gfloat min, max, foffset;
+
+ /* figure actual pulse width (0..1) */
+ foffset = osc->config.pulse_width; /* 0..1 */
+ foffset += pulse_mod * osc->config.pulse_mod_strength;
+ foffset = CLAMP (foffset, 0.0, 1.0);
+
+ /* calculate pulse scaling range for this offset */
+ osc->pwm_offset = foffset * osc->wave.n_values;
+ osc->pwm_offset <<= osc->wave.n_frac_bits;
+
+ maxp_offs = (osc->wave.min_pos + osc->wave.n_values + osc->wave.max_pos) << (osc->wave.n_frac_bits - 1);
+ minp_offs = (osc->wave.max_pos + osc->wave.min_pos) << (osc->wave.n_frac_bits - 1);
+
+ mpos = maxp_offs + (osc->pwm_offset >> 1);
+ tpos = mpos >> osc->wave.n_frac_bits;
+ max = osc->wave.values[tpos];
+ mpos -= osc->pwm_offset;
+ tpos = mpos >> osc->wave.n_frac_bits;
+ max -= osc->wave.values[tpos];
+ mpos = minp_offs + (osc->pwm_offset >> 1);
+ tpos = mpos >> osc->wave.n_frac_bits;
+ min = osc->wave.values[tpos];
+ mpos -= osc->pwm_offset;
+ tpos = mpos >> osc->wave.n_frac_bits;
+ min -= osc->wave.values[tpos];
+ osc->pwm_center = (min + max) / -2.0;
+ min = fabs (min + osc->pwm_center);
+ max = fabs (max + osc->pwm_center);
+ max = MAX (max, min);
+ if_reject (max < GSL_FLOAT_MIN_NORMAL)
+ {
+ osc->pwm_center = foffset < 0.5 ? -1.0 : +1.0;
+ osc->pwm_max = 1.0;
+ }
+ else
+ osc->pwm_max = 1.0 / max;
+}
+
+
+/* --- generate processing function variants --- */
+#define OSC_FLAG_INVAL (0xffffffff)
+#define OSC_FLAG_ISYNC (1)
+#define OSC_FLAG_OSYNC (2)
+#define OSC_FLAG_FREQ (4)
+#define OSC_FLAG_SELF_MOD (8)
+#define OSC_FLAG_LINEAR_MOD (16)
+#define OSC_FLAG_EXP_MOD (32)
+#define OSC_FLAG_PWM_MOD (64)
+#define OSC_FLAG_PULSE_OSC (128)
+
+/* normal oscillator variants */
+#define OSC_INCLUDER_FLAGS 0
+#define GSL_INCLUDER_FIRST_CASE 0
+#define GSL_INCLUDER_LAST_CASE 63
+#define GSL_INCLUDER_NAME oscillator_process_normal
+#define GSL_INCLUDER_TABLE static void (*osc_process_table[]) (GslOscData*,guint, \
+ const gfloat*,const gfloat*,const gfloat*, \
+ const gfloat*,gfloat*,gfloat*)
+#define GSL_INCLUDER_FILE "gsloscillator-aux.c"
+#include "gslincluder.c"
+#undef OSC_INCLUDER_FLAGS
+
+/* pulse width modulation oscillator variants */
+#define OSC_INCLUDER_FLAGS OSC_FLAG_PULSE_OSC
+#define GSL_INCLUDER_FIRST_CASE 0
+#define GSL_INCLUDER_LAST_CASE 127
+#define GSL_INCLUDER_NAME oscillator_process_pulse
+#define GSL_INCLUDER_TABLE static void (*osc_process_pulse_table[]) (GslOscData*,guint, \
+ const gfloat*,const gfloat*,const gfloat*, \
+ const gfloat*,gfloat*,gfloat*)
+#define GSL_INCLUDER_FILE "gsloscillator-aux.c"
+#include "gslincluder.c"
+#undef OSC_INCLUDER_FLAGS
+
+
+/* --- functions --- */
+static inline void
+osc_process (GslOscData *osc,
+ guint n_values,
+ guint mode,
+ const gfloat *ifreq,
+ const gfloat *imod,
+ const gfloat *isync,
+ const gfloat *ipwm,
+ gfloat *mono_out,
+ gfloat *sync_out)
+{
+ mode |= isync ? OSC_FLAG_ISYNC : 0;
+ mode |= sync_out ? OSC_FLAG_OSYNC : 0;
+ mode |= ifreq ? OSC_FLAG_FREQ : 0;
+ if (osc->config.pulse_mod_strength > GSL_FLOAT_MIN_NORMAL)
+ mode |= ipwm ? OSC_FLAG_PWM_MOD : 0;
+ if (osc->config.self_fm_strength > GSL_FLOAT_MIN_NORMAL)
+ mode |= OSC_FLAG_SELF_MOD;
+ if (imod && osc->config.exponential_fm)
+ mode |= OSC_FLAG_EXP_MOD;
+ else if (imod)
+ mode |= OSC_FLAG_LINEAR_MOD;
+
+ if_reject (mode != osc->last_mode)
+ {
+ guint change_mask = osc->last_mode >= OSC_FLAG_INVAL ? OSC_FLAG_INVAL : osc->last_mode ^ mode;
+
+ if (change_mask & OSC_FLAG_FREQ)
+ {
+ gdouble fcpos, flpos;
+
+ fcpos = osc->cur_pos * osc->wave.ifrac_to_float;
+ flpos = osc->last_pos * osc->wave.ifrac_to_float;
+ osc->last_freq_level = osc->config.cfreq;
+ gsl_osc_table_lookup (osc->config.table, osc->last_freq_level, &osc->wave);
+ osc->last_pos = flpos / osc->wave.ifrac_to_float;
+ osc->cur_pos = fcpos / osc->wave.ifrac_to_float;
+ }
+ if (!(mode & OSC_FLAG_ISYNC))
+ osc->last_sync_level = 0;
+ if (mode & OSC_FLAG_PULSE_OSC)
+ {
+ osc->last_pwm_level = 0;
+ osc_update_pwm_offset (osc, osc->last_pwm_level);
+ }
+ osc->last_mode = mode;
+ }
+
+ /* invoke generated function variant */
+ if (mode & OSC_FLAG_PULSE_OSC)
+ osc_process_pulse_table[mode & ~OSC_FLAG_PULSE_OSC] (osc, n_values,
+ ifreq, imod, isync, ipwm,
+ mono_out, sync_out);
+ else
+ osc_process_table[mode] (osc, n_values,
+ ifreq, imod, isync, NULL,
+ mono_out, sync_out);
+}
+
+void
+gsl_osc_process (GslOscData *osc,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *imod,
+ const gfloat *isync,
+ gfloat *mono_out,
+ gfloat *sync_out)
+{
+ g_return_if_fail (osc != NULL);
+ g_return_if_fail (n_values > 0);
+ g_return_if_fail (mono_out != NULL);
+
+ if (osc->last_mode & OSC_FLAG_PULSE_OSC)
+ osc->last_mode = OSC_FLAG_INVAL;
+ osc_process (osc, n_values, 0,
+ ifreq, imod, isync, NULL,
+ mono_out, sync_out);
+}
+
+void
+gsl_osc_process_pulse (GslOscData *osc,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *imod,
+ const gfloat *isync,
+ const gfloat *ipwm,
+ gfloat *mono_out,
+ gfloat *sync_out)
+{
+ g_return_if_fail (osc != NULL);
+ g_return_if_fail (n_values > 0);
+ g_return_if_fail (mono_out != NULL);
+
+ if (!(osc->last_mode & OSC_FLAG_PULSE_OSC))
+ osc->last_mode = OSC_FLAG_INVAL;
+ osc_process (osc, n_values, OSC_FLAG_PULSE_OSC,
+ ifreq, imod, isync, ipwm,
+ mono_out, sync_out);
+}
+
+void
+gsl_osc_config (GslOscData *osc,
+ GslOscConfig *config)
+{
+ g_return_if_fail (osc != NULL);
+ g_return_if_fail (config != NULL);
+ g_return_if_fail (config->table != NULL);
+
+ osc->config = *config;
+ osc->last_mode = OSC_FLAG_INVAL;
+}
diff --git a/flow/gsl/gsloscillator.h b/flow/gsl/gsloscillator.h
new file mode 100644
index 0000000..24223fc
--- /dev/null
+++ b/flow/gsl/gsloscillator.h
@@ -0,0 +1,84 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 1999, 2000-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_OSCILLATOR_H__
+#define __GSL_OSCILLATOR_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gslosctable.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- structures --- */
+typedef struct
+{
+ GslOscTable *table;
+ guint exponential_fm : 1;
+ gfloat fm_strength; /* linear: 0..1, exponential: n_octaves */
+ gfloat self_fm_strength; /* 0..1 */
+ gfloat phase; /* -0.5..+0.5 */
+ gfloat cfreq; /* for ifreq == NULL */
+ gfloat pulse_width; /* 0..1 */
+ gfloat pulse_mod_strength; /* 0..0.5 */
+ gint fine_tune; /* -100..+100 */
+} GslOscConfig;
+typedef struct
+{
+ GslOscConfig config;
+ guint last_mode;
+ guint32 cur_pos, last_pos;
+ gfloat last_sync_level;
+ gdouble last_freq_level;
+ gfloat last_pwm_level;
+ GslOscWave wave;
+ /* pwm */
+ guint32 pwm_offset;
+ gfloat pwm_max, pwm_center;
+} GslOscData;
+
+
+/* --- Oscillator --- */
+void gsl_osc_config (GslOscData *osc,
+ GslOscConfig *config);
+void gsl_osc_process (GslOscData *osc,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *imod,
+ const gfloat *isync,
+ gfloat *mono_out,
+ gfloat *sync_out);
+void gsl_osc_process_pulse (GslOscData *osc,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *imod,
+ const gfloat *isync,
+ const gfloat *ipwm,
+ gfloat *mono_out,
+ gfloat *sync_out);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_OSCILLATOR_H__ */
diff --git a/flow/gsl/gslosctable.c b/flow/gsl/gslosctable.c
new file mode 100644
index 0000000..f3e096d
--- /dev/null
+++ b/flow/gsl/gslosctable.c
@@ -0,0 +1,626 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslosctable.h"
+
+#include <string.h>
+#include "gbsearcharray.h"
+#include "gslcommon.h"
+#include "gslmath.h"
+#include "gslfft.h"
+
+
+#define OSC_DEBUG GSL_DEBUG_FUNCTION (GSL_MSG_OSC, G_STRLOC)
+
+#define OSC_FREQ_EPSILON (1e-3) /* range within which frequencies are "equal" */
+
+/* compare mfreqs against each other, use an arbitrary sample rate
+ * for which OSC_FREQ_EPSILON makes sense
+ */
+#define CACHE_MATCH_FREQ(usr_mfreq, cache_mfreq) \
+ (fabs ((cache_mfreq) * 44107 - (usr_mfreq) * 44107) < OSC_FREQ_EPSILON)
+
+
+/* --- structures --- */
+typedef struct
+{
+ /* main key (osc and cache tables) */
+ gfloat mfreq; /* [0..0.5], mix_freq relative */
+ /* secondary key (cache tables) */
+ GslOscWaveForm wave_form;
+ guint8 *filter_func; /* just here for key indexing */
+ /* data */
+ guint ref_count;
+ guint min_pos, max_pos; /* pulse extension */
+ guint n_values;
+ const gfloat values[1]; /* flexible array */
+} OscTableEntry;
+
+
+/* --- prototypes --- */
+static gint cache_table_entry_locs_cmp (gconstpointer bsearch_node1, /* key */
+ gconstpointer bsearch_node2);
+static gint osc_table_entry_locs_cmp (gconstpointer bsearch_node1, /* key */
+ gconstpointer bsearch_node2);
+static void osc_wave_extrema_pos (guint n_values,
+ const gfloat *values,
+ guint *minp_p,
+ guint *maxp_p);
+void gsl_osc_cache_debug_dump (void);
+
+
+/* --- variables --- */
+static GBSearchArray *cache_entries = NULL;
+static const GBSearchConfig cache_taconfig = {
+ sizeof (OscTableEntry*),
+ cache_table_entry_locs_cmp,
+ 0
+};
+static const GBSearchConfig osc_taconfig = {
+ sizeof (OscTableEntry*),
+ osc_table_entry_locs_cmp,
+ 0
+};
+
+
+/* --- functions --- */
+static gint
+cache_table_entry_locs_cmp (gconstpointer bsearch_node1, /* key */
+ gconstpointer bsearch_node2)
+{
+ const OscTableEntry * const *ep1 = bsearch_node1;
+ const OscTableEntry * const *ep2 = bsearch_node2;
+ const OscTableEntry *e1 = *ep1;
+ const OscTableEntry *e2 = *ep2;
+
+ if (e1->wave_form == e2->wave_form)
+ {
+ if (e1->filter_func == e2->filter_func)
+ return G_BSEARCH_ARRAY_CMP (e1->mfreq, e2->mfreq);
+ else
+ return e1->filter_func > e2->filter_func ? 1 : -1;
+ }
+ else
+ return e1->wave_form > e2->wave_form ? 1 : -1;
+}
+
+static gint
+osc_table_entry_locs_cmp (gconstpointer bsearch_node1, /* key */
+ gconstpointer bsearch_node2)
+{
+ const OscTableEntry * const *ep1 = bsearch_node1;
+ const OscTableEntry * const *ep2 = bsearch_node2;
+ const OscTableEntry *e1 = *ep1;
+ const OscTableEntry *e2 = *ep2;
+
+ return G_BSEARCH_ARRAY_CMP (e1->mfreq, e2->mfreq);
+}
+
+static OscTableEntry*
+cache_table_entry_lookup_best (GslOscWaveForm wave_form,
+ guint8* filter_func,
+ gfloat mfreq)
+{
+ OscTableEntry key, *k = &key, **ep1 = NULL, **ep2, **ep3 = NULL;
+
+ key.mfreq = mfreq;
+ key.wave_form = wave_form;
+ key.filter_func = filter_func;
+
+ /* get exact match or a match which is one off into either direction */
+ ep2 = g_bsearch_array_lookup_sibling (cache_entries, &cache_taconfig, &k);
+ if (ep2)
+ {
+ guint i = g_bsearch_array_get_index (cache_entries, &cache_taconfig, ep2);
+
+ /* get siblings */
+ if (i > 0)
+ ep1 = g_bsearch_array_get_nth (cache_entries, &cache_taconfig, i - 1);
+ if (i + 1 < g_bsearch_array_get_n_nodes (cache_entries))
+ ep3 = g_bsearch_array_get_nth (cache_entries, &cache_taconfig, i + 1);
+
+ /* get rid of invalid matches, i.e. ones with:
+ * - a different wave
+ * - a different filter
+ * - a filter wider than required
+ */
+ if (ep1 && ((*ep1)->wave_form != wave_form ||
+ (*ep1)->filter_func != filter_func ||
+ (*ep1)->mfreq < mfreq))
+ ep1 = NULL;
+ if (ep3 && ((*ep3)->wave_form != wave_form ||
+ (*ep3)->filter_func != filter_func ||
+ (*ep3)->mfreq < mfreq))
+ ep3 = NULL;
+ if ((*ep2)->wave_form != wave_form ||
+ (*ep2)->filter_func != filter_func ||
+ (*ep2)->mfreq < mfreq)
+ {
+ /* collapse siblings, so that, if we have valid matches, ep2 is amongst them */
+ if (ep1)
+ {
+ ep2 = ep1;
+ ep1 = NULL;
+ }
+ else if (ep3)
+ {
+ ep2 = ep3;
+ ep3 = NULL;
+ }
+ else
+ ep2 = NULL; /* no valid match at all */
+ }
+ }
+
+ /* now figure best out of valid siblings */
+ if (ep2)
+ {
+ if (ep1 && fabs ((*ep1)->mfreq - mfreq) < fabs ((*ep2)->mfreq - mfreq))
+ ep2 = ep1;
+ if (ep3 && fabs ((*ep3)->mfreq - mfreq) < fabs ((*ep2)->mfreq - mfreq))
+ ep2 = ep3;
+ }
+ return ep2 ? *ep2 : NULL;
+}
+
+static OscTableEntry*
+osc_table_entry_lookup_best (const GslOscTable *table,
+ gfloat mfreq,
+ gfloat *min_mfreq)
+{
+ OscTableEntry key, *k = &key, **ep;
+ guint i;
+
+ /* get exact match or a match which is one off into either direction */
+ key.mfreq = mfreq;
+ ep = g_bsearch_array_lookup_sibling (table->entry_array, &osc_taconfig, &k);
+ if_reject (!ep)
+ return NULL; /* ugh, bad */
+
+ if (mfreq > (*ep)->mfreq) /* need better filter */
+ {
+ i = g_bsearch_array_get_index (table->entry_array, &osc_taconfig, ep);
+ if (i + 1 < g_bsearch_array_get_n_nodes (table->entry_array))
+ ep = g_bsearch_array_get_nth (table->entry_array, &osc_taconfig, i + 1);
+ else /* bad, might cause aliasing */
+ OSC_DEBUG ("lookup mismatch, aliasing possible: want_freq=%f got_freq=%f",
+ mfreq * table->mix_freq, (*ep)->mfreq * table->mix_freq);
+ }
+
+ if (min_mfreq)
+ {
+ /* fetch mfreq from previous */
+ i = g_bsearch_array_get_index (table->entry_array, &osc_taconfig, ep);
+ if (i > 0)
+ {
+ OscTableEntry **tp = g_bsearch_array_get_nth (table->entry_array, &osc_taconfig, i - 1);
+
+ *min_mfreq = (*tp)->mfreq;
+ }
+ else
+ *min_mfreq = 0;
+ }
+
+ return *ep;
+}
+
+static guint
+wave_table_size (GslOscWaveForm wave_form,
+ gfloat mfreq)
+{
+ /* have to return power of 2, and honour 8 <= size */
+
+ /* FIXME: decide on other table sizes
+ 10000: 256
+ 5000: 512
+ 2500: 1024
+ 1250: 2048
+ GSL_OSC_WAVE_SAW_FALL always huge buffers to guarantee pulse width stepping granularity
+ */
+
+ if (wave_form == GSL_OSC_WAVE_SAW_FALL)
+ return 8192;
+
+ return 2048;
+}
+
+static void
+fft_filter (guint n_values,
+ gfloat *values, /* [0..n_values], n_values/2 complex values */
+ gdouble scale_window,
+ double (*window) (double))
+{
+ guint i;
+
+ n_values >>= 1;
+ scale_window /= (gdouble) n_values;
+ for (i = 0; i <= n_values; i++)
+ {
+ gdouble w = window (i * scale_window);
+ values[i * 2] *= w;
+ values[i * 2 + 1] *= w;
+ }
+}
+
+static OscTableEntry*
+cache_table_ref_entry (GslOscWaveForm wave_form,
+ double (*filter_func) (double),
+ gfloat mfreq)
+{
+ OscTableEntry *e = cache_table_entry_lookup_best (wave_form, (guint8*) filter_func, mfreq);
+
+ if (e && !CACHE_MATCH_FREQ (mfreq, e->mfreq))
+ e = NULL;
+ if (!e)
+ {
+ guint size = wave_table_size (wave_form, mfreq);
+ gfloat *values, *fft, step, min, max;
+
+ /* size:
+ * - OscTableEntry already contains the first float values
+ * - we need n_values+1 adressable floats to provide values[0] == values[n_values]
+ */
+ e = g_malloc (sizeof (OscTableEntry) + sizeof (gfloat) * size);
+ values = (gfloat*) &e->values[0];
+ e->wave_form = wave_form;
+ e->filter_func = (guint8*) filter_func;
+ e->mfreq = mfreq;
+ e->ref_count = 1;
+ e->n_values = size;
+ gsl_osc_wave_fill_buffer (e->wave_form, e->n_values, values);
+
+ /* filter wave accordingly */
+ gsl_osc_wave_extrema (e->n_values, values, &min, &max);
+ fft = g_new (gfloat, e->n_values + 2); /* [0..n_values] for n_values/2 complex freqs */
+ gsl_power2_fftar_simple (e->n_values, values, fft);
+ step = e->mfreq * (gdouble) e->n_values;
+ fft_filter (e->n_values, fft, step, filter_func);
+ gsl_power2_fftsr_simple (e->n_values, fft, values);
+ g_free (fft);
+ gsl_osc_wave_normalize (e->n_values, values, (min + max) / 2, max);
+
+ /* provide values[0]==values[n_values] */
+ values[e->n_values] = values[0];
+
+ /* pulse min/max pos extension */
+ osc_wave_extrema_pos (e->n_values, values, &e->min_pos, &e->max_pos);
+
+ /* insert into cache */
+ cache_entries = g_bsearch_array_insert (cache_entries, &cache_taconfig, &e);
+ }
+ else
+ e->ref_count++;
+ return e;
+}
+
+static void
+cache_table_unref_entry (OscTableEntry *e)
+{
+ g_return_if_fail (e->ref_count > 0);
+
+ e->ref_count -= 1;
+ if (e->ref_count == 0)
+ {
+ OscTableEntry **ep;
+ guint i;
+
+ ep = g_bsearch_array_lookup (cache_entries, &cache_taconfig, &e);
+ i = g_bsearch_array_get_index (cache_entries, &cache_taconfig, ep);
+ cache_entries = g_bsearch_array_remove (cache_entries, &cache_taconfig, i);
+ }
+}
+
+GslOscTable*
+gsl_osc_table_create (gfloat mix_freq,
+ GslOscWaveForm wave_form,
+ double (*filter_func) (double),
+ guint n_freqs,
+ const gfloat *freqs)
+{
+ GslOscTable *table;
+ gfloat nyquist;
+ guint i;
+
+ g_return_val_if_fail (mix_freq > 0, NULL);
+ g_return_val_if_fail (n_freqs > 0, NULL);
+ g_return_val_if_fail (freqs != NULL, NULL);
+
+ if (!cache_entries)
+ cache_entries = g_bsearch_array_create (&cache_taconfig);
+
+ table = gsl_new_struct (GslOscTable, 1);
+ table->mix_freq = mix_freq;
+ table->wave_form = wave_form;
+ table->entry_array = g_bsearch_array_create (&osc_taconfig);
+ nyquist = table->mix_freq * 0.5;
+ if (wave_form == GSL_OSC_WAVE_PULSE_SAW)
+ wave_form = GSL_OSC_WAVE_SAW_FALL;
+ for (i = 0; i < n_freqs; i++)
+ {
+ OscTableEntry *e;
+ gdouble mfreq = MIN (nyquist, freqs[i]);
+
+ mfreq /= table->mix_freq;
+ e = osc_table_entry_lookup_best (table, mfreq, NULL);
+ if (!e || fabs (e->mfreq * table->mix_freq - mfreq * table->mix_freq) > OSC_FREQ_EPSILON)
+ {
+ e = cache_table_ref_entry (wave_form, filter_func, mfreq);
+ table->entry_array = g_bsearch_array_insert (table->entry_array, &osc_taconfig, &e);
+ }
+ else if (e)
+ OSC_DEBUG ("not inserting existing entry (freq=%f) for freq %f (nyquist=%f)",
+ e->mfreq * table->mix_freq, mfreq * table->mix_freq, nyquist);
+ }
+
+ return table;
+}
+
+void
+gsl_osc_table_lookup (const GslOscTable *table,
+ gfloat freq,
+ GslOscWave *wave)
+{
+ OscTableEntry *e;
+ gfloat mfreq, min_mfreq;
+
+ g_return_if_fail (table != NULL);
+ g_return_if_fail (wave != NULL);
+
+ mfreq = freq / table->mix_freq;
+ e = osc_table_entry_lookup_best (table, mfreq, &min_mfreq);
+ if (e)
+ {
+ guint32 int_one;
+ gfloat float_one;
+
+ wave->min_freq = min_mfreq * table->mix_freq;
+ wave->max_freq = e->mfreq * table->mix_freq;
+ wave->n_values = e->n_values;
+ wave->values = e->values;
+ wave->n_frac_bits = g_bit_storage (wave->n_values - 1);
+ wave->n_frac_bits = 32 - wave->n_frac_bits;
+ int_one = 1 << wave->n_frac_bits;
+ wave->frac_bitmask = int_one - 1;
+ float_one = int_one;
+ wave->freq_to_step = float_one * wave->n_values / table->mix_freq;
+ wave->phase_to_pos = wave->n_values * float_one;
+ wave->ifrac_to_float = 1.0 / float_one;
+ /* pulse min/max pos extension */
+ wave->min_pos = e->min_pos;
+ wave->max_pos = e->max_pos;
+ }
+ else
+ {
+ /* shouldn't happen */
+ OSC_DEBUG ("table lookup revealed NULL, empty table?");
+ memset (wave, 0, sizeof (*wave));
+ }
+}
+
+void
+gsl_osc_table_free (GslOscTable *table)
+{
+ guint n;
+
+ g_return_if_fail (table != NULL);
+
+ n = g_bsearch_array_get_n_nodes (table->entry_array);
+ while (n--)
+ {
+ OscTableEntry **ep;
+
+ ep = g_bsearch_array_get_nth (table->entry_array, &osc_taconfig, n);
+ cache_table_unref_entry (*ep);
+ table->entry_array = g_bsearch_array_remove (table->entry_array, &osc_taconfig, n);
+ }
+ g_bsearch_array_free (table->entry_array, &osc_taconfig);
+ gsl_delete_struct (GslOscTable, table);
+}
+
+void
+gsl_osc_cache_debug_dump (void)
+{
+ OSC_DEBUG ("left in cache: %u", g_bsearch_array_get_n_nodes (cache_entries));
+}
+
+void
+gsl_osc_wave_fill_buffer (GslOscWaveForm type,
+ guint n_values,
+ gfloat *values)
+{
+ gdouble max = n_values, hmax = max * 0.5, qmax = n_values * 0.25;
+ gint i, half = n_values / 2, quarter = half / 2;
+
+ switch (type)
+ {
+ gdouble frac, pos;
+ case GSL_OSC_WAVE_SINE:
+ for (i = 0; i < n_values; i++)
+ {
+ frac = ((gdouble) i) / max; /* [0..1[ */
+ pos = frac * 2. * GSL_PI;
+ values[i] = sin (pos);
+ }
+ break;
+ case GSL_OSC_WAVE_SAW_RISE:
+ for (i = 0; i < n_values; i++)
+ {
+ frac = ((gdouble) i) / max; /* [0..1[ */
+ values[i] = 2.0 * frac - 1.0;
+ }
+ break;
+ case GSL_OSC_WAVE_SAW_FALL:
+ for (i = 0; i < n_values; i++)
+ {
+ frac = ((gdouble) i) / max; /* [0..1[ */
+ values[i] = 1.0 - 2.0 * frac;
+ }
+ break;
+ case GSL_OSC_WAVE_PEAK_RISE: /* spaced saw */
+ for (i = 0; i < half; i++)
+ {
+ frac = ((gdouble) i) / hmax;
+ values[i] = 2.0 * frac - 1.0;
+ }
+ for (; i < n_values; i++)
+ values[i] = -1.0;
+ break;
+ case GSL_OSC_WAVE_PEAK_FALL: /* spaced saw */
+ for (i = 0; i < half; i++)
+ {
+ frac = ((gdouble) i) / hmax;
+ values[i] = 1.0 - 2.0 * frac;
+ }
+ for (; i < n_values; i++)
+ values[i] = -1.0;
+ break;
+ case GSL_OSC_WAVE_TRIANGLE:
+ for (i = 0; i < quarter; i++)
+ {
+ frac = ((gdouble) i) / qmax;
+ values[i] = frac;
+ }
+ for (; i < half + quarter; i++)
+ {
+ frac = ((gdouble) i - quarter) / hmax;
+ values[i] = 1.0 - 2.0 * frac;
+ }
+ for (; i < n_values; i++)
+ {
+ frac = ((gdouble) i - half - quarter) / qmax;
+ values[i] = frac - 1.0;
+ }
+ break;
+ case GSL_OSC_WAVE_MOOG_SAW:
+ for (i = 0; i < half; i++)
+ {
+ frac = ((gdouble) i) / hmax;
+ values[i] = 2.0 * frac - 1.0;
+ }
+ for (; i < n_values; i++)
+ {
+ frac = ((gdouble) i) / max;
+ values[i] = 1.0 - 2.0 * frac;
+ }
+ break;
+ case GSL_OSC_WAVE_SQUARE:
+ for (i = 0; i < half; i++)
+ values[i] = 1.0;
+ for (; i < n_values; i++)
+ values[i] = -1.0;
+ break;
+ default:
+ g_critical ("%s: invalid wave form id (%u)", G_STRLOC, type);
+ case GSL_OSC_WAVE_NONE:
+ for (i = 0; i < n_values; i++)
+ values[i] = 0;
+ break;
+ }
+}
+
+static void
+osc_wave_extrema_pos (guint n_values,
+ const gfloat *values,
+ guint *minp_p,
+ guint *maxp_p)
+{
+ guint i, minp = 0, maxp = 0;
+ gfloat min = values[0], max = min;
+
+ for (i = 1; i < n_values; i++)
+ {
+ if (values[i] > max)
+ {
+ max = values[i];
+ maxp = i;
+ }
+ else if (values[i] < min)
+ {
+ min = values[i];
+ minp = i;
+ }
+ }
+ *minp_p = minp;
+ *maxp_p = maxp;
+}
+
+void
+gsl_osc_wave_extrema (guint n_values,
+ const gfloat *values,
+ gfloat *min_p,
+ gfloat *max_p)
+{
+ guint minp, maxp;
+
+ g_return_if_fail (n_values > 0 && values != NULL && min_p != NULL && max_p != NULL);
+
+ osc_wave_extrema_pos (n_values, values, &minp, &maxp);
+ *min_p = values[minp];
+ *max_p = values[maxp];
+}
+
+void
+gsl_osc_wave_adjust_range (guint n_values,
+ gfloat *values,
+ gfloat min,
+ gfloat max,
+ gfloat new_center,
+ gfloat new_max)
+{
+ gfloat center;
+ guint i;
+
+ g_return_if_fail (n_values > 0 && values != NULL);
+
+ center = (min + max) / 2;
+ center = new_center - center;
+ min = fabs (min + center);
+ max = fabs (max + center);
+ if (min > max)
+ max = min;
+ if (max > GSL_FLOAT_MIN_NORMAL)
+ max = new_max / max;
+ else
+ max = 0;
+ for (i = 0; i < n_values; i++)
+ values[i] = (values[i] + center) * max;
+}
+
+void
+gsl_osc_wave_normalize (guint n_values,
+ gfloat *values,
+ gfloat new_center,
+ gfloat new_max)
+{
+ gfloat min, max;
+ guint i;
+
+ g_return_if_fail (n_values > 0 && values != NULL);
+
+ min = values[0];
+ max = min;
+ for (i = 1; i < n_values; i++)
+ {
+ register gfloat v = values[i];
+
+ max = MAX (max, v);
+ min = MIN (min, v);
+ }
+
+ gsl_osc_wave_adjust_range (n_values, values, min, max, new_center, new_max);
+}
diff --git a/flow/gsl/gslosctable.h b/flow/gsl/gslosctable.h
new file mode 100644
index 0000000..021e5b9
--- /dev/null
+++ b/flow/gsl/gslosctable.h
@@ -0,0 +1,104 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_OSC_TABLE_H__
+#define __GSL_OSC_TABLE_H__
+
+#include <gsl/gsldefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- structures & enums --- */
+typedef enum /*< skip >*/
+{
+ GSL_OSC_WAVE_NONE,
+ GSL_OSC_WAVE_SINE,
+ GSL_OSC_WAVE_TRIANGLE,
+ GSL_OSC_WAVE_SAW_RISE,
+ GSL_OSC_WAVE_SAW_FALL,
+ GSL_OSC_WAVE_PEAK_RISE,
+ GSL_OSC_WAVE_PEAK_FALL,
+ GSL_OSC_WAVE_MOOG_SAW,
+ GSL_OSC_WAVE_SQUARE,
+ GSL_OSC_WAVE_PULSE_SAW
+} GslOscWaveForm;
+
+typedef struct
+{
+ gfloat mix_freq;
+ GslOscWaveForm wave_form;
+ gpointer entry_array;
+} GslOscTable;
+
+typedef struct
+{
+ gfloat min_freq;
+ gfloat max_freq;
+ guint n_values;
+ const gfloat *values; /* contains n_values+1 values with values[0]==values[n_values] */
+ /* integer stepping (block size dependant) */
+ guint32 n_frac_bits;
+ guint32 frac_bitmask;
+ gfloat freq_to_step; /* freq -> int.frac */
+ gfloat phase_to_pos; /* 0..1 -> int.frac */
+ gfloat ifrac_to_float; /* frac -> 0..1 float */
+ guint min_pos, max_pos; /* pulse extension */
+} GslOscWave;
+
+
+/* --- oscillator table --- */
+GslOscTable* gsl_osc_table_create (gfloat mix_freq,
+ GslOscWaveForm wave_form,
+ double (*filter_func) (double),
+ guint n_freqs,
+ const gfloat *freqs);
+void gsl_osc_table_lookup (const GslOscTable *table,
+ gfloat freq,
+ GslOscWave *wave);
+void gsl_osc_table_free (GslOscTable *table);
+
+
+/* --- oscillator wave utils --- */
+void gsl_osc_wave_fill_buffer (GslOscWaveForm type,
+ guint n_values,
+ gfloat *values);
+void gsl_osc_wave_extrema (guint n_values,
+ const gfloat *values,
+ gfloat *min,
+ gfloat *max);
+void gsl_osc_wave_normalize (guint n_values,
+ gfloat *values,
+ gfloat new_center,
+ gfloat new_max);
+void gsl_osc_wave_adjust_range (guint n_values,
+ gfloat *values,
+ gfloat min,
+ gfloat max,
+ gfloat new_center,
+ gfloat new_max);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_OSC_TABLE_H__ */
diff --git a/flow/gsl/gslsignal.c b/flow/gsl/gslsignal.c
new file mode 100644
index 0000000..9afc5bb
--- /dev/null
+++ b/flow/gsl/gslsignal.c
@@ -0,0 +1,258 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslsignal.h"
+
+#include "gslcommon.h"
+
+
+/* --- frequency modulation --- */
+void
+gsl_frequency_modulator (const GslFrequencyModulator *fm,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *ifmod,
+ gfloat *fm_buffer)
+{
+ gfloat *bound, fine_tune, fm_strength;
+ gboolean with_fine_tune;
+
+ fine_tune = gsl_cent_factor (fm->fine_tune);
+ with_fine_tune = fm->fine_tune != 0;
+ fm_strength = fm->fm_strength;
+
+ bound = fm_buffer + n_values;
+ if (ifreq && ifmod)
+ {
+ if (fm->exponential_fm)
+ {
+ if (with_fine_tune)
+ do {
+ *fm_buffer++ = *ifreq++ * gsl_approx_exp2 (fm_strength * *ifmod++) * fine_tune;
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = *ifreq++ * gsl_approx_exp2 (fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ }
+ else
+ {
+ if (with_fine_tune)
+ do {
+ *fm_buffer++ = *ifreq++ * (1 + fm_strength * *ifmod++) * fine_tune;
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = *ifreq++ * (1 + fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ }
+ }
+ else if (ifmod)
+ {
+ gfloat signal_freq = fm->signal_freq * fine_tune;
+
+ if (fm->exponential_fm)
+ do {
+ *fm_buffer++ = signal_freq * gsl_approx_exp2 (fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = signal_freq * (1 + fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ }
+ else if (ifreq)
+ {
+ if (with_fine_tune)
+ do {
+ *fm_buffer++ = *ifreq++ * fine_tune;
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = *ifreq++;
+ } while (fm_buffer < bound);
+ }
+ else
+ {
+ gfloat signal_freq = fm->signal_freq * fine_tune;
+
+ do {
+ *fm_buffer++ = signal_freq;
+ } while (fm_buffer < bound);
+ }
+}
+
+
+/* --- windows --- */
+double
+gsl_window_bartlett (double x) /* triangle */
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 1.0 - fabs (x);
+}
+
+double
+gsl_window_blackman (double x)
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 0.42 + 0.5 * cos (GSL_PI * x) + 0.08 * cos (2.0 * GSL_PI * x);
+}
+
+double
+gsl_window_cos (double x) /* von Hann window */
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 0.5 * cos (x * GSL_PI) + 0.5;
+}
+
+double
+gsl_window_hamming (double x) /* sharp (rectangle) cutoffs at boundaries */
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 0.54 + 0.46 * cos (GSL_PI * x);
+}
+
+double
+gsl_window_sinc (double x) /* noramlied C. Lanczos window */
+{
+ if (fabs (x) > 1)
+ return 0;
+ x = x * GSL_PI;
+ if (fabs (x) < 1e-12)
+ return 1.0;
+ else
+ return sin (x) / x;
+}
+
+double
+gsl_window_rect (double x) /* a square */
+{
+ if (fabs (x) > 1)
+ return 0;
+ return 1.0;
+}
+
+/*
+cos_roll_off(x)= x>fh?0:x<fl?1:cos(pi/2.*((fl-x)/(fh-fl)))
+*/
+
+
+/* --- cents & init --- */
+const gdouble *gsl_cent_table = NULL;
+#define GSL_2_RAISED_TO_1_OVER_1200_d ( /* 2^(1/1200) */ \
+ 1.0005777895065548488418016859213821589946746826171875)
+void
+_gsl_init_signal (void)
+{
+ static gdouble cent_table_space[201];
+ gint i;
+
+ /* cent table initialization,
+ * allow negative indexing within [-100..+100]
+ */
+ gsl_cent_table = cent_table_space + 100;
+ for (i = -100; i <= 100; i++)
+ cent_table_space[100 + i] = pow (GSL_2_RAISED_TO_1_OVER_1200_d, i);
+}
+
+
+/* --- gsl_approx_atan1() --- */
+double
+gsl_approx_atan1_prescale (double boost_amount)
+{
+ double max_boost_factor = 100; /* atan1(x*100) gets pretty close to 1 for x=1 */
+ double recip_tan_1_div_0_75 = 0.24202942695518667705824990442766; /* 1/tan(1/0.75) */
+ double scale;
+
+ g_return_val_if_fail (boost_amount >= 0 && boost_amount <= 1.0, 1.0);
+
+ /* scale boost_amount from [0..1] to -1..1 */
+ boost_amount = boost_amount * 2 - 1.0;
+
+ /* prescale factor for atan1(x*prescale), ranges from 1/max_boost_factor..max_boost_factor */
+ scale = pow (max_boost_factor, tan (boost_amount / 0.75) * recip_tan_1_div_0_75);
+
+ return scale;
+}
+
+
+/* --- exp2f() approximation taylor coefficients finder --- */
+#if 0
+#include <stdio.h>
+double
+exp2coeff (int n)
+{
+ double r = 1;
+ int i;
+
+ for (i = 1; i <= n; i++)
+ {
+ r *= GSL_LN2;
+ r /= i;
+ }
+ return r;
+}
+/* generate taylor coefficients */
+int
+main (int argc,
+ char *argv[])
+{
+ int i;
+
+ for (i = 0; i < 20; i++)
+ printf ("#define EXP2_TAYLOR_COEFF_%u\t(%.40f)\n", i, exp2coeff (i));
+
+ return 0;
+}
+/* test/bench program */
+#define _GNU_SOURCE
+#include <math.h>
+int
+main (int argc,
+ char *argv[])
+{
+ double x, dummy = 0, l = 4;
+
+ if (1) /* print errors */
+ for (x = -3; x < 3.01; x += 0.1)
+ {
+ g_print ("%+f %+1.20f \t (%.20f - %.20f)\n",
+ x, exp (x * GSL_LN2) - gsl_signal_exp2 (x),
+ exp (x * GSL_LN2), gsl_signal_exp2 (x));
+ }
+
+ if (0) /* bench test */
+ for (x = -l; x < l; x += 0.000001)
+ {
+ dummy += gsl_signal_exp2 (x);
+ // dummy += exp2f (x);
+ }
+
+ g_print ("%f\r \n", dummy);
+
+ return 0;
+}
+#endif /* coeff generation */
+
diff --git a/flow/gsl/gslsignal.h b/flow/gsl/gslsignal.h
new file mode 100644
index 0000000..aa92f32
--- /dev/null
+++ b/flow/gsl/gslsignal.h
@@ -0,0 +1,343 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_SIGNAL_H__
+#define __GSL_SIGNAL_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gslieee754.h>
+#include <gsl/gslmath.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* smallest value of a signal sample, greater than zero
+ */
+#define GSL_SIGNAL_EPSILON (1.15e-14) /* 1.16415321826934814453125e-9 ~= 1/2^33 */
+
+/* maximum value of a signal sample
+ */
+#define GSL_SIGNAL_KAPPA (1.5)
+
+/* catch edges in sync signals.
+ * sync signals should be constant, do comparing against
+ * an epsilon just hurts speed in the common case
+ */
+#define GSL_SIGNAL_RAISING_EDGE(v1,v2) ((v1) < (v2))
+#define GSL_SIGNAL_FALLING_EDGE(v1,v2) ((v1) > (v2))
+
+/* value changes in signals which represent frequencies
+ */
+#define GSL_SIGNAL_FREQ_CHANGED(v1,v2) (fabs ((v1) - (v2)) > 1e-7)
+
+/* value changes in signals which represent modulation
+ */
+#define GSL_SIGNAL_MOD_CHANGED(v1,v2) (fabs ((v1) - (v2)) > 1e-8)
+
+/* value changes in signals which represent dB ranges
+ */
+#define GSL_SIGNAL_GAIN_CHANGED(v1,v2) (fabs ((v1) - (v2)) > 1e-8)
+
+/* convert between literal frequencies and signal values
+ */
+#if defined (BSE_COMPILATION) || defined (BSE_PLUGIN_FALLBACK)
+#include <bse/bseglobals.h>
+# define GSL_SIGNAL_TO_FREQ_FACTOR (BSE_MAX_FREQUENCY_f)
+# define GSL_SIGNAL_FROM_FREQ_FACTOR (1.0 / BSE_MAX_FREQUENCY_f)
+# define GSL_SIGNAL_TO_FREQ(value) (((gfloat) (value)) * GSL_SIGNAL_TO_FREQ_FACTOR)
+# define GSL_SIGNAL_FROM_FREQ(freq) (((gfloat) (freq)) * GSL_SIGNAL_FROM_FREQ_FACTOR)
+#elif defined (GSL_USE_ARTS_THREADS) /* must be aRts */
+# define GSL_SIGNAL_TO_FREQ(x) (x)
+# define GSL_SIGNAL_FROM_FREQ(x) (x)
+#endif
+
+
+/* --- frequency modulation --- */
+typedef struct {
+ gfloat fm_strength; /* linear: 0..1, exponential: n_octaves */
+ guint exponential_fm : 1;
+ gfloat signal_freq; /* for ifreq == NULL (as GSL_SIGNAL_FROM_FREQ) */
+ gint fine_tune; /* -100..+100 */
+} GslFrequencyModulator;
+
+void gsl_frequency_modulator (const GslFrequencyModulator *fm,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *ifmod,
+ gfloat *fm_buffer);
+
+
+/* --- function approximations --- */
+
+/**
+ * gsl_signal_exp2
+ * Deprecated in favour of gsl_approx_exp2().
+ */
+static inline float gsl_signal_exp2 (float x) G_GNUC_CONST;
+
+/**
+ * gsl_approx_exp2
+ * @ex: exponent within [-127..127]
+ * @RETURNS: y approximating 2^x
+ * Fast approximation of 2 raised to the power of x.
+ * Multiplicative error stays below 8e-6 and aproaches zero
+ * for integer values of x (i.e. x - floor (x) = 0).
+ */
+static inline double gsl_approx_exp2 (float ex) G_GNUC_CONST;
+
+
+/**
+ * gsl_approx_atan1
+ * Fast atan(x)/(PI/2) approximation, with maximum error < 0.01 and
+ * gsl_approx_atan1(0)==0, according to the formula:
+ * n1 = -0.41156875521951602506487246309908;
+ * n2 = -1.0091272542790025586079663559158;
+ * d1 = 0.81901156857081841441890603235599;
+ * d2 = 1.0091272542790025586079663559158;
+ * positive_atan1(x) = 1 + (n1 * x + n2) / ((1 + d1 * x) * x + d2);
+ */
+static inline double gsl_approx_atan1 (register double x) G_GNUC_CONST;
+
+/**
+ * gsl_approx_atan1_prescale
+ * @boost_amount: boost amount between [0..1]
+ * @RETURNS: prescale factor for gsl_approx_atan1()
+ * Calculate the prescale factor for gsl_approx_atan1(x*prescale) from
+ * a linear boost factor, where 0.5 amounts to prescale=1.0, 1.0 results
+ * in maximum boost and 0.0 results in maximum attenuation.
+ */
+double gsl_approx_atan1_prescale (double boost_amount);
+
+/**
+ * gsl_approx_qcircle1
+ * @x: x within [0..1]
+ * @RETURNS: y for circle approximation within [0..1]
+ * Fast approximation of the upper right quadrant of a circle.
+ * Errors at x=0 and x=1 are zero, for the rest of the curve, the error
+ * wasn't minimized, but distributed to best fit the curverture of a
+ * quarter circle. The maximum error is below 0.092.
+ */
+static inline double gsl_approx_qcircle1 (register double x) G_GNUC_CONST;
+
+/**
+ * gsl_approx_qcircle2
+ * @x: x within [0..1]
+ * @RETURNS: y for circle approximation within [0..1]
+ * Fast approximation of the upper left quadrant of a circle.
+ * Errors at x=0 and x=1 are zero, for the rest of the curve, the error
+ * wasn't minimized, but distributed to best fit the curverture of a
+ * quarter circle. The maximum error is below 0.092.
+ */
+static inline double gsl_approx_qcircle2 (register double x) G_GNUC_CONST;
+
+/**
+ * gsl_approx_qcircle3
+ * @x: x within [0..1]
+ * @RETURNS: y for circle approximation within [0..1]
+ * Fast approximation of the lower left quadrant of a circle.
+ * Errors at x=0 and x=1 are zero, for the rest of the curve, the error
+ * wasn't minimized, but distributed to best fit the curverture of a
+ * quarter circle. The maximum error is below 0.092.
+ */
+static inline double gsl_approx_qcircle3 (register double x) G_GNUC_CONST;
+
+/**
+ * gsl_approx_qcircle4
+ * @x: x within [0..1]
+ * @RETURNS: y for circle approximation within [0..1]
+ * Fast approximation of the lower right quadrant of a circle.
+ * Errors at x=0 and x=1 are zero, for the rest of the curve, the error
+ * wasn't minimized, but distributed to best fit the curverture of a
+ * quarter circle. The maximum error is below 0.092.
+ */
+static inline double gsl_approx_qcircle4 (register double x) G_GNUC_CONST;
+
+
+/* --- windows --- */
+double gsl_window_bartlett (double x); /* narrowest */
+double gsl_window_blackman (double x);
+double gsl_window_cos (double x);
+double gsl_window_hamming (double x);
+double gsl_window_sinc (double x);
+double gsl_window_rect (double x); /* widest */
+
+
+/* --- cents (1/100th of a semitone) --- */
+#define gsl_cent_factor(index /* -100..100 */) (gsl_cent_table[index])
+extern const gdouble *gsl_cent_table;
+
+
+/* --- implementation details --- */
+static inline double G_GNUC_CONST
+gsl_approx_atan1 (register double x)
+{
+ if (x < 0) /* make use of -atan(-x)==atan(x) */
+ {
+ register double numerator, denominator = -1.0;
+
+ denominator += x * 0.81901156857081841441890603235599; /* d1 */
+ numerator = x * 0.41156875521951602506487246309908; /* -n1 */
+ denominator *= x;
+ numerator += -1.0091272542790025586079663559158; /* n2 */
+ denominator += 1.0091272542790025586079663559158; /* d2 */
+
+ return -1.0 - numerator / denominator;
+ }
+ else
+ {
+ register double numerator, denominator = 1.0;
+
+ denominator += x * 0.81901156857081841441890603235599; /* d1 */
+ numerator = x * -0.41156875521951602506487246309908; /* n1 */
+ denominator *= x;
+ numerator += -1.0091272542790025586079663559158; /* n2 */
+ denominator += 1.0091272542790025586079663559158; /* d2 */
+
+ return 1.0 + numerator / denominator;
+ }
+}
+
+static inline double G_GNUC_CONST
+gsl_approx_qcircle1 (register double x)
+{
+ double numerator = 1.20460124790369468987715633298929 * x - 1.20460124790369468987715633298929;
+ double denominator = x - 1.20460124790369468987715633298929;
+ /* R1(x)=(1.2046012479036946898771563 * x - 1.2046012479036946898771563) / (x - 1.2046012479036946898771563) */
+ return numerator / denominator;
+}
+
+static inline double G_GNUC_CONST
+gsl_approx_qcircle2 (register double x)
+{
+ double numerator = 1.20460124790369468987715633298929*x;
+ double denominator = x + 0.20460124790369468987715633298929;
+ /* R2(x)=1.2046012479036946898771563*x/(x + 0.2046012479036946898771563) */
+ return numerator / denominator;
+}
+
+static inline double G_GNUC_CONST
+gsl_approx_qcircle3 (register double x)
+{
+ double numerator = 0.20460124790369468987715633298929 - 0.20460124790369468987715633298929 * x;
+ double denominator = x + 0.20460124790369468987715633298929;
+ /* R3(x)=(0.2046012479036946898771563 - 0.2046012479036946898771563 * x) / (x + 0.2046012479036946898771563) */
+ return numerator / denominator;
+}
+
+static inline double G_GNUC_CONST
+gsl_approx_qcircle4 (register double x)
+{
+ double numerator = -0.20460124790369468987715633298929 * x;
+ double denominator = x - 1.20460124790369468987715633298929;
+ /* R4(x)=-0.2046012479036946898771563 * x / (x - 1.2046012479036946898771563) */
+ return numerator / denominator;
+}
+
+static inline double G_GNUC_CONST
+gsl_approx_exp2 (float ex)
+{
+ register GslFloatIEEE754 fp = { 0, };
+ register double numer, denom, x;
+ gint i;
+
+ i = gsl_ftoi (ex);
+ fp.mpn.biased_exponent = GSL_FLOAT_BIAS + i;
+ x = ex - i;
+ numer = x * 1.022782938747283388104723674300322141276;
+ denom = x - 8.72117024533378044415954808601135282456;
+ numer += 8.786902350800703562041965087953613538091;
+ denom *= x;
+ numer *= x;
+ denom += 25.25880955504064143887016455761526606757;
+ numer += 25.2588095552441757401874424757283407864;
+
+ return numer / denom * fp.v_float;
+}
+
+static inline float G_GNUC_CONST
+_gsl_signal_exp2_fraction (float x) /* 2^x, -0.5 <= x <= 0.5 */
+{
+ static const float exp2taylorC0 = 1.0000000000000000000000000000000000000000;
+ static const float exp2taylorC1 = 0.6931471805599452862267639829951804131269;
+ static const float exp2taylorC2 = 0.2402265069591006940719069007172947749496;
+ static const float exp2taylorC3 = 0.0555041086648215761800706502526736585423;
+ static const float exp2taylorC4 = 0.0096181291076284768787330037298488605302;
+ static const float exp2taylorC5 = 0.0013333558146428443284131626356270317046;
+#if 0
+ static const float exp2taylorC6 = 0.0001540353039338160877607525334198612654;
+ static const float exp2taylorC7 = 0.0000152527338040598393887042200089965149;
+ static const float exp2taylorC8 = 0.0000013215486790144307390984122416166535;
+ static const float exp2taylorC9 = 0.0000001017808600923969859895309888857262;
+#endif
+ float r = 0.0;
+
+ /* order 5 taylor series aproximation */
+ r += exp2taylorC5;
+ r *= x;
+ r += exp2taylorC4;
+ r *= x;
+ r += exp2taylorC3;
+ r *= x;
+ r += exp2taylorC2;
+ r *= x;
+ r += exp2taylorC1;
+ r *= x;
+ r += exp2taylorC0;
+
+ return r;
+}
+static inline float G_GNUC_CONST
+gsl_signal_exp2 (float x) /* 2^x, -3.5 <= x <= 3.5, prec>16bit */
+{
+ if_reject (x < -0.5)
+ {
+ if_reject (x < -1.5)
+ {
+ if (x < -2.5)
+ return 0.125 * _gsl_signal_exp2_fraction (x + 3);
+ else /* -2.5 <= x < -1.5 */
+ return 0.25 * _gsl_signal_exp2_fraction (x + 2);
+ }
+ else /* -1.5 <= x < -0.5 */
+ return 0.5 * _gsl_signal_exp2_fraction (x + 1);
+ }
+ else if_reject (x > 0.5)
+ {
+ if_reject (x > 1.5)
+ {
+ if (x > 2.5)
+ return 8 * _gsl_signal_exp2_fraction (x - 3);
+ else /* 1.5 < x <= 2.5 */
+ return 4 * _gsl_signal_exp2_fraction (x - 2);
+ }
+ else /* 0.5 < x <= 1.5 */
+ return 2 * _gsl_signal_exp2_fraction (x - 1);
+ }
+ else
+ return _gsl_signal_exp2_fraction (x);
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_SIGNAL_H__ */
diff --git a/flow/gsl/gsltests.c b/flow/gsl/gsltests.c
new file mode 100644
index 0000000..12a1664
--- /dev/null
+++ b/flow/gsl/gsltests.c
@@ -0,0 +1,650 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This program 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 of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <gsl/gslmath.h>
+#include <gsl/gslcommon.h>
+#include <gsl/gslmath.h>
+#include <gsl/gslfilter.h>
+#include <gsl/gslloader.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PREC "15"
+
+
+static void usage (void) G_GNUC_NORETURN;
+
+
+static guint shift_argc = 0;
+static const gchar **shift_argv = NULL;
+
+static const gchar*
+shift (void)
+{
+ const gchar *arg;
+
+ if (shift_argc > 1)
+ {
+ shift_argc--;
+ arg = shift_argv++[1];
+ if (!arg)
+ arg = "";
+ }
+ else
+ arg = NULL;
+ return arg;
+}
+static const gchar*
+pshift (void)
+{
+ const gchar *arg = shift ();
+
+ return arg ? arg : "";
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ const gchar *arg;
+
+ /* iir filter parameters */
+ enum { FILTER_GNUPLOT, FILTER_SCAN } filter_mode = FILTER_GNUPLOT;
+ const gchar *filter_label = 0;
+ gdouble *a, *b;
+ guint order = 0;
+
+ shift_argc = argc;
+ shift_argv = (gchar **)argv;
+
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+ gsl_init (NULL, NULL);
+
+ arg = shift ();
+ if (!arg)
+ usage ();
+
+ restart:
+ a = b = 0;
+
+ if (strcmp (arg, "wave-scan") == 0)
+ {
+ const gchar *file = pshift ();
+
+ while (file)
+ {
+ GslWaveFileInfo *fi;
+ GslErrorType error;
+
+ fi = gsl_wave_file_info_load (file, &error);
+ if (fi)
+ {
+ guint i;
+
+ g_print ("Loader \"%s\" found %u waves in \"%s\":\n", fi->loader->name, fi->n_waves, file);
+ for (i = 0; i < fi->n_waves; i++)
+ g_print ("%u) %s\n", i + 1, fi->waves[i].name);
+ gsl_wave_file_info_unref (fi);
+ }
+ else
+ g_print ("Failed to scan \"%s\": %s\n", file, gsl_strerror (error));
+ file = pshift ();
+ if (!file[0])
+ break;
+ }
+ }
+ else if (strcmp (arg, "file-test") == 0)
+ {
+ const gchar *file = pshift ();
+
+ g_print ("file test for \"%s\":\n", file);
+ g_print (" is readable : %s\n", gsl_strerror (gsl_check_file (file, "r")));
+ g_print (" is writable : %s\n", gsl_strerror (gsl_check_file (file, "w")));
+ g_print (" is executable : %s\n", gsl_strerror (gsl_check_file (file, "x")));
+ g_print (" is file : %s\n", gsl_strerror (gsl_check_file (file, "f")));
+ g_print (" is directory : %s\n", gsl_strerror (gsl_check_file (file, "d")));
+ g_print (" is link : %s\n", gsl_strerror (gsl_check_file (file, "l")));
+ }
+ else if (strcmp (arg, "rf") == 0)
+ {
+ double x, y, z;
+ x = atof (pshift ());
+ y = atof (pshift ());
+ z = atof (pshift ());
+
+ g_print ("rf(%f, %f, %f) = %."PREC"f\n", x, y, z, gsl_ellip_rf (x, y, z));
+ }
+ else if (strcmp (arg, "F") == 0)
+ {
+ double phi, ak;
+ phi = atof (pshift ());
+ ak = atof (pshift ());
+
+ g_print ("F(%f, %f) = %."PREC"f\n", phi, ak, gsl_ellip_F (phi, ak));
+ }
+ else if (strcmp (arg, "sn") == 0)
+ {
+ double u, emmc;
+ u = atof (pshift ());
+ emmc = atof (pshift ());
+
+ g_print ("sn(%f, %f) = %."PREC"f\n", u, emmc, gsl_ellip_sn (u, emmc));
+ }
+ else if (strcmp (arg, "snc") == 0)
+ {
+ GslComplex u, emmc;
+ u.re = atof (pshift ());
+ u.im = atof (pshift ());
+ emmc.re = atof (pshift ());
+ emmc.im = atof (pshift ());
+
+ g_print ("snc(%s, %s) = %s\n",
+ gsl_complex_str (u),
+ gsl_complex_str (emmc),
+ gsl_complex_str (gsl_complex_ellip_sn (u, emmc)));
+ }
+ else if (strcmp (arg, "sci_snc") == 0)
+ {
+ GslComplex u, k2;
+ u.re = atof (pshift ());
+ u.im = atof (pshift ());
+ k2.re = atof (pshift ());
+ k2.im = atof (pshift ());
+
+ g_print ("sci_snc(%s, %s) = %s\n",
+ gsl_complex_str (u),
+ gsl_complex_str (k2),
+ gsl_complex_str (gsl_complex_ellip_sn (u, gsl_complex_sub (gsl_complex (1.0, 0), k2))));
+ }
+ else if (strcmp (arg, "asn") == 0)
+ {
+ double y, emmc;
+ y = atof (pshift ());
+ emmc = atof (pshift ());
+
+ g_print ("asn(%f, %f) = %."PREC"f\n", y, emmc, gsl_ellip_asn (y, emmc));
+ }
+ else if (strcmp (arg, "asnc") == 0)
+ {
+ GslComplex y, emmc;
+ y.re = atof (pshift ());
+ y.im = atof (pshift ());
+ emmc.re = atof (pshift ());
+ emmc.im = atof (pshift ());
+
+ g_print ("asnc(%s, %s) = %s\n",
+ gsl_complex_str (y), gsl_complex_str (emmc),
+ gsl_complex_str (gsl_complex_ellip_asn (y, emmc)));
+ g_print ("asn(%f, %f = %."PREC"f\n",
+ y.re, emmc.re, gsl_ellip_asn (y.re, emmc.re));
+ }
+ else if (strcmp (arg, "sci_sn") == 0)
+ {
+ double u, k2;
+ u = atof (pshift ());
+ k2 = atof (pshift ());
+ g_print ("sci_sn(%f, %f) = %."PREC"f\n", u, k2, gsl_ellip_sn (u, 1.0 - k2));
+ }
+ else if (strcmp (arg, "sci_asn") == 0)
+ {
+ double y, k2;
+ y = atof (pshift ());
+ k2 = atof (pshift ());
+ g_print ("sci_asn(%f, %f) = %."PREC"f\n", y, k2, gsl_ellip_asn (y, 1.0 - k2));
+ }
+ else if (strcmp (arg, "sci_asnc") == 0)
+ {
+ GslComplex y, k2;
+ y.re = atof (pshift ());
+ y.im = atof (pshift ());
+ k2.re = atof (pshift ());
+ k2.im = atof (pshift ());
+ g_print ("sci_asnc(%s, %s) = %s\n",
+ gsl_complex_str (y), gsl_complex_str (k2),
+ gsl_complex_str (gsl_complex_ellip_asn (y, gsl_complex_sub (gsl_complex (1.0, 0), k2))));
+ g_print ("asn(%f, %f = %."PREC"f\n",
+ y.re, k2.re, gsl_ellip_asn (y.re, 1.0 - k2.re));
+ }
+ else if (strcmp (arg, "sin") == 0)
+ {
+ GslComplex phi;
+ phi.re = atof (pshift ());
+ phi.im = atof (pshift ());
+ g_print ("sin(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_sin (phi)));
+ }
+ else if (strcmp (arg, "cos") == 0)
+ {
+ GslComplex phi;
+ phi.re = atof (pshift ());
+ phi.im = atof (pshift ());
+ g_print ("cos(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_cos (phi)));
+ }
+ else if (strcmp (arg, "tan") == 0)
+ {
+ GslComplex phi;
+ phi.re = atof (pshift ());
+ phi.im = atof (pshift ());
+ g_print ("tan(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_tan (phi)));
+ }
+ else if (strcmp (arg, "sinh") == 0)
+ {
+ GslComplex phi;
+ phi.re = atof (pshift ());
+ phi.im = atof (pshift ());
+ g_print ("sinh(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_sinh (phi)));
+ }
+ else if (strcmp (arg, "cosh") == 0)
+ {
+ GslComplex phi;
+ phi.re = atof (pshift ());
+ phi.im = atof (pshift ());
+ g_print ("cosh(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_cosh (phi)));
+ }
+ else if (strcmp (arg, "tanh") == 0)
+ {
+ GslComplex phi;
+ phi.re = atof (pshift ());
+ phi.im = atof (pshift ());
+ g_print ("tanh(%s) = %s\n",
+ gsl_complex_str (phi),
+ gsl_complex_str (gsl_complex_tanh (phi)));
+ }
+ else if (strcmp (arg, "midi2freq") == 0)
+ {
+ gint note;
+ note = atol (pshift ());
+ note = CLAMP (note, 0, 128);
+ g_print ("midi2freq(%u) = %f\n",
+ note,
+ gsl_temp_freq (gsl_get_config ()->kammer_freq,
+ note - gsl_get_config ()->midi_kammer_note));
+ }
+ else if (strcmp (arg, "blp") == 0)
+ {
+ double f, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f = atof (pshift ());
+ e = atof (pshift ());
+ f *= GSL_PI / 2.;
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+ gsl_filter_butter_lp (order, f, e, a, b);
+ g_print ("# Lowpass Butterworth filter order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n",
+ order, f, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "BL";
+ }
+ else if (strcmp (arg, "bhp") == 0)
+ {
+ double f, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f = atof (pshift ());
+ e = atof (pshift ());
+ f *= GSL_PI / 2.;
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_butter_hp (order, f, e, a, b);
+ g_print ("# Highpass Butterworth filter order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n",
+ order, f, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "BH";
+ }
+ else if (strcmp (arg, "bbp") == 0)
+ {
+ double f1, f2, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f1 = atof (pshift ());
+ f2 = atof (pshift ());
+ e = atof (pshift ());
+ f1 *= GSL_PI / 2.;
+ f2 *= GSL_PI / 2.;
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_butter_bp (order, f1, f2, e, a, b);
+ g_print ("# Bandpass Butterworth filter order=%u freq1=%f freq2=%f epsilon(s^2)=%f norm0=%f:\n",
+ order, f1, f2, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "BP";
+ }
+ else if (strcmp (arg, "bbs") == 0)
+ {
+ double f1, f2, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f1 = atof (pshift ());
+ f2 = atof (pshift ());
+ e = atof (pshift ());
+ f1 *= GSL_PI / 2.;
+ f2 *= GSL_PI / 2.;
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_butter_bs (order, f1, f2, e, a, b);
+ g_print ("# Bandstop Butterworth filter order=%u freq1=%f freq2=%f epsilon(s^2)=%f norm0=%f:\n",
+ order, f1, f2, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "BS";
+ }
+ else if (strcmp (arg, "t1l") == 0)
+ {
+ double f, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f = atof (pshift ());
+ e = atof (pshift ());
+ f *= GSL_PI / 2.;
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb1_lp (order, f, e, a, b);
+ g_print ("# Lowpass Tschebyscheff Type1 order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n",
+ order, f, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T1L";
+ }
+ else if (strcmp (arg, "t1h") == 0)
+ {
+ double f, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f = atof (pshift ());
+ e = atof (pshift ());
+ f *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb1_hp (order, f, e, a, b);
+ g_print ("# Highpass Tschebyscheff Type1 order=%u freq=%f epsilon(s^2)=%f norm0=%f:\n",
+ order, f, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T1H";
+ }
+ else if (strcmp (arg, "t1s") == 0)
+ {
+ double fc, fr, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ fc = atof (pshift ());
+ fr = atof (pshift ());
+ e = atof (pshift ());
+ fc *= GSL_PI / 2.;
+ fr *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb1_bs (order, fc, fr, e, a, b);
+ g_print ("# Bandstop Tschebyscheff Type1 order=%u freq_c=%f freq_r=%f epsilon(s^2)=%f norm=%f:\n",
+ order, fc, fr, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T1S";
+ }
+ else if (strcmp (arg, "t1p") == 0)
+ {
+ double fc, fr, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ fc = atof (pshift ());
+ fr = atof (pshift ());
+ e = atof (pshift ());
+ fc *= GSL_PI / 2.;
+ fr *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb1_bp (order, fc, fr, e, a, b);
+ g_print ("# Bandpass Tschebyscheff Type1 order=%u freq_c=%f freq_r=%f epsilon(s^2)=%f norm=%f:\n",
+ order, fc, fr, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T1P";
+ }
+ else if (strcmp (arg, "t2l") == 0)
+ {
+ double f, st, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f = atof (pshift ());
+ st = atof (pshift ());
+ e = atof (pshift ());
+ f *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb2_lp (order, f, st, e, a, b);
+ g_print ("# Lowpass Tschebyscheff Type2 order=%u freq=%f steepness=%f (%f) epsilon(s^2)=%f norm=%f:\n",
+ order, f, st, f * (1.+st), e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T2L";
+ }
+ else if (strcmp (arg, "t2h") == 0)
+ {
+ double f, st, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f = atof (pshift ());
+ st = atof (pshift ());
+ e = atof (pshift ());
+ f *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb2_hp (order, f, st, e, a, b);
+ g_print ("# Highpass Tschebyscheff Type2 order=%u freq=%f steepness=%f (%f, %f) epsilon(s^2)=%f norm=%f:\n",
+ order, f, st, GSL_PI - f, (GSL_PI - f) * (1.+st), e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T2H";
+ }
+ else if (strcmp (arg, "t2p") == 0)
+ {
+ double f1, f2, st, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f1 = atof (pshift ());
+ f2 = atof (pshift ());
+ st = atof (pshift ());
+ e = atof (pshift ());
+ f1 *= GSL_PI / 2.;
+ f2 *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb2_bp (order, f1, f2, st, e, a, b);
+ g_print ("# Bandpass Tschebyscheff Type2 order=%u freq1=%f freq2=%f steepness=%f epsilon(s^2)=%f norm=%f:\n",
+ order, f1, f2, st, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T2P";
+ }
+ else if (strcmp (arg, "t2s") == 0)
+ {
+ double f1, f2, st, e;
+ order = atoi (pshift ()); order = MAX (order, 1);
+ f1 = atof (pshift ());
+ f2 = atof (pshift ());
+ st = atof (pshift ());
+ e = atof (pshift ());
+ f1 *= GSL_PI / 2.;
+ f2 *= GSL_PI / 2.;
+
+ a = g_new (gdouble, order + 1);
+ b = g_new (gdouble, order + 1);
+
+ gsl_filter_tscheb2_bs (order, f1, f2, st, e, a, b);
+ g_print ("# Bandstop Tschebyscheff Type2 order=%u freq1=%f freq2=%f steepness=%f epsilon(s^2)=%f norm=%f:\n",
+ order, f1, f2, st, e,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ filter_label = "T2S";
+ }
+ else if (strcmp (arg, "scan") == 0)
+ {
+ filter_mode = FILTER_SCAN;
+ }
+ else if (strcmp (arg, "fir") == 0)
+ {
+ unsigned int iorder = atoi (pshift ());
+ unsigned int n_points = 0;
+
+ double *freq = g_newa (double, argc / 2 + 1);
+ double *value = g_newa (double, argc / 2 + 1);
+ double *a = g_newa (double, iorder);
+ const char *f, *v;
+
+ do
+ {
+ f = pshift ();
+ v = pshift ();
+
+ if (f[0] && v[0])
+ {
+ freq[n_points] = atof (f) * GSL_PI;
+ value[n_points] = atof (v);
+ n_points++;
+ }
+ }
+ while (f[0] && v[0]);
+
+ gsl_filter_fir_approx (iorder, a, n_points, freq, value);
+ g_print ("FIR%u(z)=%s\n", iorder, gsl_poly_str (iorder, a, "z"));
+ }
+ else if (strncmp (arg, "poly", 4) == 0)
+ {
+ guint order;
+ arg = arg + 4;
+ order = 2;
+ {
+ double a[100] = { 1, 2, 1 }, b[100] = { 1, -3./2., 0.5 };
+ g_print ("# Test order=%u norm=%f:\n",
+ order,
+ gsl_poly_eval (order, a, 1) / gsl_poly_eval (order, b, 1));
+ g_print ("H%u(z)=%s/%s\n", order,
+ gsl_poly_str (order, a, "z"),
+ gsl_poly_str (order, b, "z"));
+ if (*arg)
+ {
+ GslComplex root, roots[100];
+ guint i;
+
+ if (*arg == 'r')
+ {
+ g_print ("#roots:\n");
+ gsl_poly_complex_roots (order, a, roots);
+ for (i = 0; i < order; i++)
+ {
+ root = gsl_complex_div (gsl_complex (1, 0), roots[i]);
+ g_print ("%+.14f %+.14f # %.14f\n", root.re, root.im, gsl_complex_abs (root));
+ }
+ }
+ if (*arg == 'p')
+ {
+ g_print ("#poles:\n");
+ gsl_poly_complex_roots (order, b, roots);
+ for (i = 0; i < order; i++)
+ {
+ root = gsl_complex_div (gsl_complex (1, 0), roots[i]);
+ g_print ("%+.14f %+.14f # %.14f\n", root.re, root.im, gsl_complex_abs (root));
+ }
+ }
+ }
+ }
+ }
+ else
+ usage ();
+
+ if (a && b)
+ {
+ gdouble freq;
+
+ if (filter_mode == FILTER_SCAN)
+ {
+ freq = 0.001;
+ while (freq < 3.14)
+ {
+ g_print ("%f %.20f\n", freq, gsl_filter_sine_scan (order, a, b, freq, MAX((int)(1000.0/freq),10000)));
+ freq = MIN (freq * 1.1, freq + 0.01);
+ }
+ }
+ else if (filter_mode == FILTER_GNUPLOT)
+ {
+ g_print ("%s%u(z)=%s/%s\n", filter_label, order,
+ gsl_poly_str (order, a, "z"),
+ gsl_poly_str (order, b, "z"));
+ }
+ else
+ g_error ("unknown filter_mode");
+ g_free (a);
+ g_free (b);
+ }
+
+ arg = shift ();
+ if (arg)
+ goto restart;
+
+ return 0;
+}
+
+static void
+usage (void)
+{
+ g_print ("usage: gsltests {test} [args...]\n");
+ g_print ("tests:\n");
+ g_print (" wave-scan <file> scan a wave file for waves\n");
+ g_print (" file-test <file> test file properties\n");
+ g_print (" rf <x> <y> <z> Carlson's elliptic integral of the first kind\n");
+ g_print (" F <phi> <ak> Legendre elliptic integral of the 1st kind\n");
+ g_print (" sn <u> <emmc> Jacobian elliptic function sn()\n");
+ g_print (" asn <y> <emmc> elliptic integral, inverse sn()\n");
+ g_print (" sin <phi.re> <phi.im> complex sine\n");
+ g_print (" cos <phi.re> <phi.im> complex cosine\n");
+ g_print (" tan <phi.re> <phi.im> complex tangent\n");
+ g_print (" sinh <phi.re> <phi.im> complex hyperbolic sine\n");
+ g_print (" cosh <phi.re> <phi.im> complex hyperbolic cosine\n");
+ g_print (" tanh <phi.re> <phi.im> complex hyperbolic tangent\n");
+ g_print (" midi2freq <midinote> convert midinote into oscilaltor frequency\n");
+ g_print (" snc <u.re> <u.im> <emmc.re> <emmc.im> sn() for complex numbers\n");
+ g_print (" asnc <y.re> <y.im> <emmc.re> <emmc.im> asn() for complex numbers\n");
+ g_print (" sci_sn <u> <k2> scilab version of sn()\n");
+ g_print (" sci_asn <y> <k2> scilab version of asn()\n");
+ g_print (" sci_snc <u.re> <u.im> <k2.re> <k2.im> scilab version of snc()\n");
+ g_print (" sci_asnc <y.re> <y.im> <k2.re> <k2.im> scilab version of asnc()\n");
+ g_print (" blp <order> <freq> <epsilon> butterworth lowpass filter\n");
+ g_print (" bhp <order> <freq> <epsilon> butterworth higpass filter\n");
+ g_print (" bbp <order> <freqc> <freqr> <epsilon> butterworth bandpass filter\n");
+ g_print (" t1l <order> <freq> <epsilon> type1 tschebyscheff lowpass filter\n");
+ g_print (" t1h <order> <freq> <epsilon> type1 tschebyscheff highpass filter\n");
+ g_print (" t1s <order> <freqc> <freqr> <epsilon> type1 tschebyscheff bandstop filter\n");
+ g_print (" t1p <order> <freqc> <freqr> <epsilon> type1 tschebyscheff bandpass filter\n");
+ g_print (" t2l <order> <freqc> <steepn> <epsilon> type2 tschebyscheff lowpass filter\n");
+ g_print (" t2h <order> <freqc> <steepn> <epsilon> type2 tschebyscheff highpass filter\n");
+ g_print (" fir <order> <freq1> <value1> ... fir approximation\n");
+ g_print (" scan blp <order> <freq> <epsilon> scan butterworth lowpass filter\n");
+ g_print (" poly | polyr | polyp polynom test (+roots or +poles)\n");
+ exit (1);
+}
+
+
+
+/* vim:set ts=8 sts=2 sw=2: */
diff --git a/flow/gsl/gslwave.header b/flow/gsl/gslwave.header
new file mode 100644
index 0000000..2b0bf5b
--- /dev/null
+++ b/flow/gsl/gslwave.header
Binary files differ
diff --git a/flow/gsl/gslwavechunk.c b/flow/gsl/gslwavechunk.c
new file mode 100644
index 0000000..06a105f
--- /dev/null
+++ b/flow/gsl/gslwavechunk.c
@@ -0,0 +1,812 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslwavechunk.h"
+
+#include "gslcommon.h"
+#include "gsldatahandle.h"
+
+#include <string.h>
+
+
+/* --- macros --- */
+#define PRINT_DEBUG_INFO (0)
+#define STATIC_ZERO_SIZE (4096)
+#define PBLOCK_SIZE(pad, n_channels) (MAX (2 * (pad), (n_channels) * gsl_get_config ()->wave_chunk_big_pad))
+
+#define PHASE_NORM(wchunk) ((GslWaveChunkMem*) (0))
+#define PHASE_NORM_BACKWARD(wchunk) ((GslWaveChunkMem*) (+1))
+#define PHASE_UNDEF(wchunk) ((GslWaveChunkMem*) (+2))
+#define PHASE_HEAD(wchunk) (&(wchunk)->head)
+#define PHASE_ENTER(wchunk) (&(wchunk)->enter)
+#define PHASE_WRAP(wchunk) (&(wchunk)->wrap)
+#define PHASE_PPWRAP(wchunk) (&(wchunk)->ppwrap)
+#define PHASE_LEAVE(wchunk) (&(wchunk)->leave)
+#define PHASE_TAIL(wchunk) (&(wchunk)->tail)
+
+
+/* --- typedefs & structures --- */
+typedef struct {
+ GslLong pos; /* input */
+ GslLong rel_pos;
+ GslLong lbound, ubound; /* PHASE_NORM/_BACKWARD */
+} Iter;
+typedef struct {
+ GslLong dir;
+ GslLong pos;
+ GslLong loop_count;
+} WPos;
+
+
+/* --- variables --- */
+static gfloat static_zero_block[STATIC_ZERO_SIZE] = { 0, }; /* FIXME */
+
+
+/* --- functions --- */
+static inline void
+wpos_step (GslWaveChunk *wchunk,
+ WPos *wpos)
+{
+ wpos->pos += wpos->dir;
+ if (wpos->loop_count)
+ {
+ if (wchunk->loop_type == GSL_WAVE_LOOP_PINGPONG)
+ {
+ if (wpos->dir < 0 &&
+ wpos->pos == wchunk->loop_first + wpos->dir)
+ {
+ wpos->loop_count--;
+ wpos->dir = -wpos->dir;
+ wpos->pos = wchunk->loop_first + wpos->dir;
+ }
+ else if (wpos->pos == wchunk->loop_last + wpos->dir)
+ {
+ wpos->loop_count--;
+ wpos->dir = -wpos->dir;
+ wpos->pos = wchunk->loop_last + wpos->dir;
+ }
+ }
+ else
+ {
+ if (wpos->pos == wchunk->loop_last + wpos->dir && wpos->loop_count)
+ {
+ wpos->loop_count--;
+ wpos->pos = wchunk->loop_first;
+ }
+ }
+ }
+}
+
+static void
+fill_block (GslWaveChunk *wchunk,
+ gfloat *block,
+ GslLong offset,
+ guint length,
+ gboolean backward,
+ guint loop_count)
+{
+ GslLong dcache_length = gsl_data_handle_length (wchunk->dcache->dhandle);
+ guint i, dnode_length = wchunk->dcache->node_size;
+ GslDataCacheNode *dnode;
+ WPos wpos;
+
+ wpos.dir = wchunk->n_channels;
+ if (backward)
+ wpos.dir = -wpos.dir;
+ wpos.pos = offset;
+ wpos.loop_count = loop_count;
+ dnode = gsl_data_cache_ref_node (wchunk->dcache, 0, TRUE);
+ for (i = 0; i < length; i++)
+ {
+ GslLong offset = wpos.pos;
+
+ if (offset < 0 || offset >= dcache_length)
+ block[i] = 0;
+ else
+ {
+ if (offset < dnode->offset || offset >= dnode->offset + dnode_length)
+ {
+ gsl_data_cache_unref_node (wchunk->dcache, dnode);
+ dnode = gsl_data_cache_ref_node (wchunk->dcache, offset, TRUE);
+ }
+ block[i] = dnode->data[offset - dnode->offset];
+ }
+ wpos_step (wchunk, &wpos);
+ }
+ gsl_data_cache_unref_node (wchunk->dcache, dnode);
+}
+
+static gfloat*
+create_block_for_offset (GslWaveChunk *wchunk,
+ GslLong offset,
+ guint length)
+{
+ GslLong padding = wchunk->n_pad_values;
+ GslLong one = wchunk->n_channels;
+ GslLong wave_last = wchunk->length - one;
+ GslLong loop_width = wchunk->loop_last - wchunk->loop_first;
+ gfloat *mem;
+ GslLong l, j, k;
+
+ if (wchunk->loop_type != GSL_WAVE_LOOP_PINGPONG)
+ loop_width += one;
+
+ l = length + 2 * padding;
+ mem = gsl_new_struct (gfloat, l);
+ offset -= padding;
+ j = ((wchunk->wave_length - one - offset) -
+ (wchunk->pploop_ends_backwards ? wchunk->loop_first : wave_last - wchunk->loop_last));
+ if (j >= 0)
+ {
+ k = j / loop_width;
+ /* g_print ("endoffset-setup: j=%ld %%=%ld, k=%ld, k&1=%ld\n", j, j % loop_width, k, k & 1); */
+ j %= loop_width;
+ if (wchunk->loop_type == GSL_WAVE_LOOP_PINGPONG)
+ {
+ if (wchunk->pploop_ends_backwards && (k & 1))
+ fill_block (wchunk, mem, wchunk->loop_last - j, l, FALSE, k);
+ else if (wchunk->pploop_ends_backwards)
+ fill_block (wchunk, mem, wchunk->loop_first + j, l, TRUE, k);
+ else if (k & 1)
+ fill_block (wchunk, mem, wchunk->loop_first + j, l, TRUE, k);
+ else
+ fill_block (wchunk, mem, wchunk->loop_last - j, l, FALSE, k);
+ }
+ else
+ fill_block (wchunk, mem, wchunk->loop_last - j, l, FALSE, k);
+ }
+ else if (wchunk->pploop_ends_backwards)
+ fill_block (wchunk, mem, wchunk->loop_first + j, l, TRUE, 0);
+ else
+ fill_block (wchunk, mem, wchunk->loop_last - j, l, FALSE, 0);
+ return mem + padding;
+}
+
+static void
+setup_pblocks (GslWaveChunk *wchunk)
+{
+ GslLong padding = wchunk->n_pad_values;
+ GslLong big_pad = PBLOCK_SIZE (wchunk->n_pad_values, wchunk->n_channels);
+ GslLong loop_width = wchunk->loop_last - wchunk->loop_first;
+ GslLong one = wchunk->n_channels;
+ GslLong loop_duration, wave_last = wchunk->length - one;
+ gfloat *mem;
+ guint l;
+
+ if (wchunk->loop_type != GSL_WAVE_LOOP_PINGPONG)
+ loop_width += one;
+ loop_duration = loop_width * wchunk->loop_count;
+
+ wchunk->head.start = -padding;
+ wchunk->head.end = big_pad;
+ wchunk->head.length = wchunk->head.end - wchunk->head.start + one;
+ wchunk->tail_start_norm = wave_last - big_pad;
+ wchunk->tail.start = wchunk->tail_start_norm + loop_duration;
+ wchunk->tail.end = wchunk->tail.start + big_pad + padding;
+ wchunk->tail.length = wchunk->tail.end - wchunk->tail.start + one;
+ if (wchunk->loop_type)
+ {
+ wchunk->enter.start = wchunk->loop_last - padding;
+ wchunk->enter.end = wchunk->loop_last + one + big_pad;
+ wchunk->wrap.start = loop_width - padding;
+ wchunk->wrap.end = big_pad;
+ if (wchunk->loop_type == GSL_WAVE_LOOP_PINGPONG)
+ {
+ wchunk->enter.end -= one;
+ wchunk->wrap.end -= one;
+ wchunk->ppwrap.start = wchunk->wrap.start;
+ wchunk->ppwrap.end = wchunk->wrap.end + loop_width;
+ wchunk->ppwrap.length = wchunk->ppwrap.end - wchunk->ppwrap.start + one;
+ wchunk->wrap.length = loop_width - wchunk->wrap.start + wchunk->wrap.end + one;
+ wchunk->wrap.start += loop_width;
+ }
+ else
+ wchunk->wrap.length = loop_width - wchunk->wrap.start + wchunk->wrap.end + one;
+ wchunk->leave_end_norm = wchunk->loop_last + big_pad;
+ wchunk->leave.start = wchunk->loop_last + loop_duration - padding;
+ wchunk->leave.end = wchunk->leave_end_norm + loop_duration;
+ if (wchunk->mini_loop)
+ {
+ wchunk->leave.start -= wchunk->wrap.length + padding;
+ wchunk->enter.end += wchunk->wrap.length + padding;
+ }
+ wchunk->leave.length = wchunk->leave.end - wchunk->leave.start + one;
+ wchunk->enter.length = wchunk->enter.end - wchunk->enter.start + one;
+ if (wchunk->pploop_ends_backwards)
+ {
+ wchunk->tail.start += wchunk->loop_last - wave_last + wchunk->loop_first;
+ wchunk->tail.end += wchunk->loop_last - wave_last + wchunk->loop_first;
+ wchunk->tail_start_norm = 0 + big_pad;
+ wchunk->leave_end_norm = wchunk->loop_first - big_pad;
+ }
+ }
+ else
+ {
+ /*
+ wchunk->enter.start = wchunk->head.end;
+ wchunk->enter.end = wchunk->head.end;
+ wchunk->enter.length = 0;
+ */
+ wchunk->enter.start = wchunk->tail.start;
+ wchunk->enter.end = wchunk->head.end;
+ wchunk->enter.length = 0;
+ wchunk->wrap.start = wchunk->tail.end + 1;
+ wchunk->wrap.end = wchunk->head.start - 1;
+ wchunk->wrap.length = 0;
+ wchunk->ppwrap.start = wchunk->tail.end + 1;
+ wchunk->ppwrap.end = wchunk->head.start - 1;
+ wchunk->ppwrap.length = 0;
+ wchunk->leave.start = wchunk->tail.start;
+ wchunk->leave.end = wchunk->tail.end;
+ wchunk->leave_end_norm = 0;
+ wchunk->leave.length = 0;
+ }
+
+ l = wchunk->head.length + 2 * padding;
+ mem = gsl_new_struct (gfloat, l);
+ fill_block (wchunk, mem, wchunk->head.start - padding, l, FALSE, wchunk->loop_count);
+ wchunk->head.mem = mem + padding;
+ if (wchunk->loop_type)
+ {
+ l = wchunk->enter.length + 2 * padding;
+ mem = gsl_new_struct (gfloat, l);
+ fill_block (wchunk, mem, wchunk->enter.start - padding, l, FALSE, wchunk->loop_count);
+ wchunk->enter.mem = mem + padding;
+ if (wchunk->loop_type == GSL_WAVE_LOOP_PINGPONG)
+ {
+ wchunk->wrap.mem = create_block_for_offset (wchunk, wchunk->loop_last + one + wchunk->wrap.start, wchunk->wrap.length);
+ wchunk->ppwrap.mem = create_block_for_offset (wchunk, wchunk->loop_last + one + wchunk->ppwrap.start, wchunk->ppwrap.length);
+ }
+ else
+ {
+ l = wchunk->wrap.length + 2 * padding;
+ mem = gsl_new_struct (gfloat, l);
+ fill_block (wchunk, mem, wchunk->loop_first + wchunk->wrap.start - padding, l, FALSE, wchunk->loop_count - 1);
+ wchunk->wrap.mem = mem + padding;
+ }
+ wchunk->leave.mem = create_block_for_offset (wchunk, wchunk->leave.start, wchunk->leave.length);
+ }
+ wchunk->tail.mem = create_block_for_offset (wchunk, wchunk->tail.start, wchunk->tail.length);
+}
+
+static inline GslWaveChunkMem*
+wave_identify_offset (GslWaveChunk *wchunk,
+ Iter *iter)
+{
+ GslLong pos = iter->pos;
+ GslLong one = wchunk->n_channels;
+
+ if (pos < wchunk->head.start) /* outside wave boundaries */
+ {
+ iter->lbound = 0;
+ iter->rel_pos = wchunk->n_pad_values;
+ iter->ubound = iter->rel_pos + MIN (STATIC_ZERO_SIZE - 2 * wchunk->n_pad_values, wchunk->head.start - pos);
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_UNDEF, pre-head %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_UNDEF (wchunk);
+ }
+ if (pos > wchunk->tail.end) /* outside wave boundaries */
+ {
+ iter->lbound = 0;
+ iter->rel_pos = wchunk->n_pad_values;
+ iter->ubound = iter->rel_pos + MIN (STATIC_ZERO_SIZE - 2 * wchunk->n_pad_values, pos - wchunk->tail.end);
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_UNDEF, post-tail %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_UNDEF (wchunk);
+ }
+ if (pos <= wchunk->head.end)
+ {
+ iter->rel_pos = pos - wchunk->head.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_HEAD %ld %ld %ld\n", wchunk->head.start, iter->rel_pos, wchunk->head.end);
+ return PHASE_HEAD (wchunk);
+ }
+ else if (pos <= wchunk->enter.end) /* before loop */
+ {
+ if (pos >= wchunk->enter.start)
+ {
+ iter->rel_pos = pos - wchunk->enter.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_ENTER %ld %ld %ld\n", wchunk->enter.start, iter->rel_pos, wchunk->enter.end);
+ return PHASE_ENTER (wchunk);
+ }
+ iter->rel_pos = pos - wchunk->head.end;
+ iter->lbound = wchunk->head.end;
+ iter->ubound = wchunk->enter.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM, pre-enter %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM (wchunk);
+ }
+ else if (pos >= wchunk->tail.start)
+ {
+ iter->rel_pos = pos - wchunk->tail.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_TAIL %ld %ld %ld\n", wchunk->tail.start, iter->rel_pos, wchunk->tail.end);
+ return PHASE_TAIL (wchunk);
+ }
+ else if (pos >= wchunk->leave.start) /* after loop */
+ {
+ if (pos <= wchunk->leave.end)
+ {
+ iter->rel_pos = pos - wchunk->leave.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_LEAVE %ld %ld %ld\n", wchunk->leave.start, iter->rel_pos, wchunk->leave.end);
+ return PHASE_LEAVE (wchunk);
+ }
+ iter->rel_pos = pos - wchunk->leave.end;
+ if (wchunk->pploop_ends_backwards)
+ {
+ iter->lbound = wchunk->tail_start_norm;
+ iter->ubound = wchunk->leave_end_norm;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM_BACKWARD, post-leave %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM_BACKWARD (wchunk);
+ }
+ else
+ {
+ iter->lbound = wchunk->leave_end_norm;
+ iter->ubound = wchunk->tail_start_norm;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM, post-leave %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM (wchunk);
+ }
+ }
+ else if (wchunk->loop_type == GSL_WAVE_LOOP_PINGPONG) /* in ping-pong loop */
+ {
+ guint loop_width = wchunk->loop_last - wchunk->loop_first;
+
+ pos -= wchunk->loop_last + one;
+ pos %= 2 * loop_width;
+ if (pos <= wchunk->ppwrap.end)
+ {
+ if (pos <= wchunk->wrap.end)
+ {
+ iter->rel_pos = wchunk->wrap.length - one - wchunk->wrap.end + pos;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_WRAP %ld %ld %ld\n", wchunk->wrap.start, iter->rel_pos, wchunk->wrap.end);
+ return PHASE_WRAP (wchunk);
+ }
+ if (pos >= wchunk->ppwrap.start)
+ {
+ iter->rel_pos = pos - wchunk->ppwrap.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_PPWRAP %ld %ld %ld\n", wchunk->ppwrap.start, iter->rel_pos, wchunk->ppwrap.end);
+ return PHASE_PPWRAP (wchunk);
+ }
+ iter->ubound = wchunk->loop_last - one - wchunk->wrap.end;
+ iter->lbound = wchunk->loop_last - one - wchunk->ppwrap.start;
+ iter->rel_pos = pos - wchunk->wrap.end;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM_BACKWARD, pploop %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM_BACKWARD (wchunk);
+ }
+ if (pos >= wchunk->wrap.start)
+ {
+ iter->rel_pos = pos - wchunk->wrap.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_WRAP %ld %ld %ld\n", wchunk->wrap.start, iter->rel_pos, wchunk->wrap.end);
+ return PHASE_WRAP (wchunk);
+ }
+ iter->rel_pos = pos - wchunk->ppwrap.end;
+ iter->ubound = wchunk->loop_first + one + wchunk->wrap.start - loop_width;
+ iter->lbound = wchunk->loop_first + one + wchunk->ppwrap.end - loop_width;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM, pploop %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM (wchunk);
+ }
+ else if (wchunk->loop_type == GSL_WAVE_LOOP_JUMP) /* in jump loop */
+ {
+ guint loop_width = wchunk->loop_last - wchunk->loop_first + one;
+
+ pos -= wchunk->loop_last + one;
+ pos %= loop_width;
+ if (pos >= wchunk->wrap.start)
+ {
+ iter->rel_pos = pos - wchunk->wrap.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_WRAP %ld %ld %ld\n", wchunk->wrap.start, iter->rel_pos, wchunk->wrap.end);
+ return PHASE_WRAP (wchunk);
+ }
+ if (pos <= wchunk->wrap.end)
+ {
+ iter->rel_pos = wchunk->wrap.length - one - wchunk->wrap.end + pos;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_WRAP %ld %ld %ld\n", wchunk->wrap.start, iter->rel_pos, wchunk->wrap.end);
+ return PHASE_WRAP (wchunk);
+ }
+ iter->rel_pos = pos - wchunk->wrap.end;
+ iter->lbound = wchunk->loop_first + wchunk->wrap.end;
+ iter->ubound = wchunk->loop_first + wchunk->wrap.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM, jloop %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM (wchunk);
+ }
+ iter->rel_pos = pos - wchunk->head.end;
+ iter->lbound = wchunk->head.end;
+ iter->ubound = wchunk->enter.start;
+ if (PRINT_DEBUG_INFO)
+ g_print ("PHASE_NORM, noloop %ld %ld %ld\n", iter->lbound, iter->rel_pos, iter->ubound);
+ return PHASE_NORM (wchunk);
+}
+
+void
+gsl_wave_chunk_use_block (GslWaveChunk *wchunk,
+ GslWaveChunkBlock *block)
+{
+ GslWaveChunkMem *phase;
+ GslLong one;
+ Iter iter;
+ gboolean reverse;
+
+ g_return_if_fail (wchunk != NULL);
+ g_return_if_fail (wchunk->open_count > 0);
+ g_return_if_fail (block != NULL);
+ g_return_if_fail (wchunk->dcache != NULL);
+ g_return_if_fail (block->node == NULL);
+ g_return_if_fail (block->play_dir == -1 || block->play_dir == +1);
+
+ block->offset /= wchunk->n_channels;
+ block->offset *= wchunk->n_channels;
+
+ one = wchunk->n_channels;
+ reverse = block->play_dir < 0;
+ iter.pos = block->offset;
+ phase = wave_identify_offset (wchunk, &iter);
+
+ block->is_silent = FALSE;
+ if (phase <= PHASE_UNDEF (wchunk))
+ {
+ GslDataCacheNode *dnode;
+ guint offset;
+
+ if (phase == PHASE_UNDEF (wchunk))
+ {
+ block->is_silent = TRUE;
+ reverse = FALSE;
+ block->length = (iter.ubound - iter.rel_pos) / wchunk->n_channels;
+ block->length *= wchunk->n_channels;
+ g_assert (block->length <= STATIC_ZERO_SIZE - 2 * wchunk->n_pad_values);
+ block->start = static_zero_block + iter.rel_pos;
+ }
+ else
+ {
+ GslLong max_length;
+
+ if (phase == PHASE_NORM_BACKWARD (wchunk))
+ {
+ offset = iter.ubound - iter.rel_pos;
+ reverse = !reverse;
+ }
+ else
+ offset = iter.lbound + iter.rel_pos;
+ max_length = reverse ? offset - iter.lbound : iter.ubound - offset;
+ dnode = gsl_data_cache_ref_node (wchunk->dcache, offset, TRUE); /* FIXME: demand_load */
+ offset -= dnode->offset;
+ block->start = dnode->data + offset;
+ if (reverse)
+ {
+ block->length = 1 + offset / wchunk->n_channels;
+ block->length *= wchunk->n_channels;
+ }
+ else
+ {
+ block->length = (wchunk->dcache->node_size - offset) / wchunk->n_channels;
+ block->length *= wchunk->n_channels;
+ }
+ block->length = MIN (block->length, max_length);
+ block->node = dnode;
+ }
+ }
+ else
+ {
+ block->start = phase->mem + iter.rel_pos;
+ if (reverse)
+ block->length = one + iter.rel_pos;
+ else
+ block->length = phase->length - iter.rel_pos;
+ }
+ if (reverse)
+ {
+ block->dirstride = -wchunk->n_channels;
+ block->end = block->start - block->length;
+ }
+ else
+ {
+ block->dirstride = +wchunk->n_channels;
+ block->end = block->start + block->length;
+ }
+ g_assert (block->length > 0);
+ /* we might want to partly reset this at some point to implement
+ * truly infinite loops
+ */
+ block->next_offset = block->offset + (block->play_dir > 0 ? block->length : -block->length);
+}
+
+void
+gsl_wave_chunk_unuse_block (GslWaveChunk *wchunk,
+ GslWaveChunkBlock *block)
+{
+ g_return_if_fail (wchunk != NULL);
+ g_return_if_fail (block != NULL);
+ g_return_if_fail (wchunk->dcache != NULL);
+
+ if (block->node)
+ {
+ gsl_data_cache_unref_node (wchunk->dcache, block->node);
+ block->node = NULL;
+ }
+}
+
+static void
+wave_chunk_setup_loop (GslWaveChunk *wchunk)
+{
+ GslWaveLoopType loop_type = wchunk->requested_loop_type;
+ GslLong loop_first = wchunk->requested_loop_first;
+ GslLong loop_last = wchunk->requested_loop_last;
+ guint loop_count = wchunk->requested_loop_count;
+ GslLong one, padding, big_pad;
+
+ g_return_if_fail (wchunk->open_count > 0);
+
+ one = wchunk->n_channels;
+ padding = wchunk->n_pad_values;
+ big_pad = PBLOCK_SIZE (wchunk->n_pad_values, wchunk->n_channels);
+
+ /* check validity */
+ if (loop_count < 1 || loop_first < 0 || loop_last < 0 || wchunk->length < 1)
+ loop_type = GSL_WAVE_LOOP_NONE;
+
+ /* setup loop types */
+ switch (loop_type)
+ {
+ case GSL_WAVE_LOOP_JUMP:
+ loop_first /= wchunk->n_channels;
+ loop_last /= wchunk->n_channels;
+ if (loop_last >= wchunk->length ||
+ loop_first >= loop_last)
+ goto CASE_DONT_LOOP;
+ wchunk->loop_type = loop_type;
+ wchunk->loop_first = loop_first * wchunk->n_channels;
+ wchunk->loop_last = loop_last * wchunk->n_channels;
+ wchunk->loop_count = (G_MAXINT - wchunk->length) / (wchunk->loop_last - wchunk->loop_first + one);
+ wchunk->loop_count = MIN (wchunk->loop_count, loop_count);
+ wchunk->wave_length = wchunk->length + (wchunk->loop_last - wchunk->loop_first + one) * wchunk->loop_count;
+ break;
+ case GSL_WAVE_LOOP_PINGPONG:
+ loop_first /= wchunk->n_channels;
+ loop_last /= wchunk->n_channels;
+ if (loop_last >= wchunk->length ||
+ loop_first >= loop_last)
+ goto CASE_DONT_LOOP;
+ wchunk->loop_type = loop_type;
+ wchunk->loop_first = loop_first * wchunk->n_channels;
+ wchunk->loop_last = loop_last * wchunk->n_channels;
+ wchunk->loop_count = (G_MAXINT - wchunk->loop_last - one) / (wchunk->loop_last - wchunk->loop_first);
+ wchunk->loop_count = MIN (wchunk->loop_count, loop_count);
+ wchunk->wave_length = wchunk->loop_last + one + (wchunk->loop_last - wchunk->loop_first) * wchunk->loop_count;
+ if (wchunk->loop_count & 1) /* FIXME */
+ wchunk->wave_length += wchunk->loop_first;
+ else
+ wchunk->wave_length += wchunk->length - one - wchunk->loop_last;
+ break;
+ CASE_DONT_LOOP:
+ loop_type = GSL_WAVE_LOOP_NONE;
+ case GSL_WAVE_LOOP_NONE:
+ wchunk->loop_type = loop_type;
+ wchunk->loop_first = wchunk->length + 1;
+ wchunk->loop_last = -1;
+ wchunk->loop_count = 0;
+ wchunk->wave_length = wchunk->length;
+ break;
+ }
+ wchunk->pploop_ends_backwards = wchunk->loop_type == GSL_WAVE_LOOP_PINGPONG && (wchunk->loop_count & 1);
+ wchunk->mini_loop = wchunk->loop_type && wchunk->loop_last - wchunk->loop_first < 2 * big_pad + padding;
+}
+
+GslWaveChunk*
+gsl_wave_chunk_new (GslDataCache *dcache,
+ gfloat osc_freq,
+ gfloat mix_freq,
+ GslWaveLoopType loop_type,
+ GslLong loop_first,
+ GslLong loop_last,
+ guint loop_count)
+{
+ GslWaveChunk *wchunk;
+
+ g_return_val_if_fail (dcache != NULL, NULL);
+ g_return_val_if_fail (osc_freq < mix_freq / 2, NULL);
+ g_return_val_if_fail (loop_type >= GSL_WAVE_LOOP_NONE && loop_type <= GSL_WAVE_LOOP_PINGPONG, NULL);
+
+ wchunk = gsl_new_struct0 (GslWaveChunk, 1);
+ wchunk->dcache = gsl_data_cache_ref (dcache);
+ wchunk->length = 0;
+ wchunk->n_channels = 0;
+ wchunk->n_pad_values = 0;
+ wchunk->wave_length = 0;
+ wchunk->loop_type = GSL_WAVE_LOOP_NONE;
+ wchunk->leave_end_norm = 0;
+ wchunk->tail_start_norm = 0;
+ wchunk->ref_count = 1;
+ wchunk->open_count = 0;
+ wchunk->mix_freq = mix_freq;
+ wchunk->osc_freq = osc_freq;
+ wchunk->requested_loop_type = loop_type;
+ wchunk->requested_loop_first = loop_first;
+ wchunk->requested_loop_last = loop_last;
+ wchunk->requested_loop_count = loop_count;
+
+ return wchunk;
+}
+
+GslWaveChunk*
+gsl_wave_chunk_ref (GslWaveChunk *wchunk)
+{
+ g_return_val_if_fail (wchunk != NULL, NULL);
+ g_return_val_if_fail (wchunk->ref_count > 0, NULL);
+
+ wchunk->ref_count++;
+ return wchunk;
+}
+
+void
+gsl_wave_chunk_unref (GslWaveChunk *wchunk)
+{
+ g_return_if_fail (wchunk != NULL);
+ g_return_if_fail (wchunk->ref_count > 0);
+
+ wchunk->ref_count--;
+ if (wchunk->ref_count == 0)
+ {
+ g_return_if_fail (wchunk->open_count == 0);
+ gsl_data_cache_unref (wchunk->dcache);
+ gsl_delete_struct (GslWaveChunk, wchunk);
+ }
+}
+
+GslErrorType
+gsl_wave_chunk_open (GslWaveChunk *wchunk)
+{
+ g_return_val_if_fail (wchunk != NULL, GSL_ERROR_INTERNAL);
+ g_return_val_if_fail (wchunk->ref_count > 0, GSL_ERROR_INTERNAL);
+
+ if (wchunk->open_count == 0)
+ {
+ GslErrorType error;
+
+ error = gsl_data_handle_open (wchunk->dcache->dhandle);
+ if (error != GSL_ERROR_NONE)
+ return error;
+ if (gsl_data_handle_n_values (wchunk->dcache->dhandle) < gsl_data_handle_n_channels (wchunk->dcache->dhandle))
+ {
+ gsl_data_handle_close (wchunk->dcache->dhandle);
+ return GSL_ERROR_FILE_EMPTY;
+ }
+ wchunk->n_channels = gsl_data_handle_n_channels (wchunk->dcache->dhandle);
+ wchunk->length = gsl_data_handle_n_values (wchunk->dcache->dhandle) / wchunk->n_channels;
+ wchunk->length *= wchunk->n_channels;
+ wchunk->n_pad_values = gsl_get_config ()->wave_chunk_padding * wchunk->n_channels;
+ gsl_data_cache_open (wchunk->dcache);
+ gsl_data_handle_close (wchunk->dcache->dhandle);
+ g_return_val_if_fail (wchunk->dcache->padding >= wchunk->n_pad_values, GSL_ERROR_INTERNAL);
+ wchunk->open_count++;
+ wchunk->ref_count++;
+ wave_chunk_setup_loop (wchunk);
+ setup_pblocks (wchunk);
+ }
+ else
+ wchunk->open_count++;
+ return GSL_ERROR_NONE;
+}
+
+void
+gsl_wave_chunk_close (GslWaveChunk *wchunk)
+{
+ GslLong padding;
+
+ g_return_if_fail (wchunk != NULL);
+ g_return_if_fail (wchunk->open_count > 0);
+ g_return_if_fail (wchunk->ref_count > 0);
+
+ wchunk->open_count--;
+ if (wchunk->open_count)
+ return;
+
+ padding = wchunk->n_pad_values;
+ gsl_data_cache_close (wchunk->dcache);
+ if (wchunk->head.mem)
+ gsl_delete_structs (gfloat, wchunk->head.length + 2 * padding, wchunk->head.mem - padding);
+ memset (&wchunk->head, 0, sizeof (GslWaveChunkMem));
+ if (wchunk->enter.mem)
+ gsl_delete_structs (gfloat, wchunk->enter.length + 2 * padding, wchunk->enter.mem - padding);
+ memset (&wchunk->enter, 0, sizeof (GslWaveChunkMem));
+ if (wchunk->wrap.mem)
+ gsl_delete_structs (gfloat, wchunk->wrap.length + 2 * padding, wchunk->wrap.mem - padding);
+ memset (&wchunk->wrap, 0, sizeof (GslWaveChunkMem));
+ if (wchunk->ppwrap.mem)
+ gsl_delete_structs (gfloat, wchunk->ppwrap.length + 2 * padding, wchunk->ppwrap.mem - padding);
+ memset (&wchunk->ppwrap, 0, sizeof (GslWaveChunkMem));
+ if (wchunk->leave.mem)
+ gsl_delete_structs (gfloat, wchunk->leave.length + 2 * padding, wchunk->leave.mem - padding);
+ memset (&wchunk->leave, 0, sizeof (GslWaveChunkMem));
+ if (wchunk->tail.mem)
+ gsl_delete_structs (gfloat, wchunk->tail.length + 2 * padding, wchunk->tail.mem - padding);
+ memset (&wchunk->tail, 0, sizeof (GslWaveChunkMem));
+ wchunk->length = 0;
+ wchunk->n_channels = 0;
+ wchunk->n_pad_values = 0;
+ wchunk->wave_length = 0;
+ wchunk->loop_type = GSL_WAVE_LOOP_NONE;
+ wchunk->leave_end_norm = 0;
+ wchunk->tail_start_norm = 0;
+ gsl_wave_chunk_unref (wchunk);
+}
+
+void
+gsl_wave_chunk_debug_block (GslWaveChunk *wchunk,
+ GslLong offset,
+ GslLong length,
+ gfloat *block)
+{
+ g_return_if_fail (wchunk != NULL);
+
+ fill_block (wchunk, block, offset, length, FALSE, wchunk->loop_count);
+}
+
+GslWaveChunk*
+_gsl_wave_chunk_copy (GslWaveChunk *wchunk)
+{
+ g_return_val_if_fail (wchunk != NULL, NULL);
+ g_return_val_if_fail (wchunk->ref_count > 0, NULL);
+
+ return gsl_wave_chunk_new (wchunk->dcache,
+ wchunk->osc_freq,
+ wchunk->mix_freq,
+ wchunk->loop_type,
+ wchunk->loop_first,
+ wchunk->loop_last,
+ wchunk->loop_count);
+}
+
+const gchar*
+gsl_wave_loop_type_to_string (GslWaveLoopType wave_loop)
+{
+ g_return_val_if_fail (wave_loop >= GSL_WAVE_LOOP_NONE && wave_loop <= GSL_WAVE_LOOP_PINGPONG, NULL);
+
+ switch (wave_loop)
+ {
+ case GSL_WAVE_LOOP_NONE: return "none";
+ case GSL_WAVE_LOOP_JUMP: return "jump";
+ case GSL_WAVE_LOOP_PINGPONG: return "pingpong";
+ default: return NULL;
+ }
+}
+
+GslWaveLoopType
+gsl_wave_loop_type_from_string (const gchar *string)
+{
+ g_return_val_if_fail (string != NULL, 0);
+
+ while (*string == ' ')
+ string++;
+ if (strncasecmp (string, "jump", 4) == 0)
+ return GSL_WAVE_LOOP_JUMP;
+ if (strncasecmp (string, "pingpong", 8) == 0)
+ return GSL_WAVE_LOOP_PINGPONG;
+ return GSL_WAVE_LOOP_NONE;
+}
diff --git a/flow/gsl/gslwavechunk.h b/flow/gsl/gslwavechunk.h
new file mode 100644
index 0000000..c4deaf5
--- /dev/null
+++ b/flow/gsl/gslwavechunk.h
@@ -0,0 +1,129 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_WAVE_CHUNK_H__
+#define __GSL_WAVE_CHUNK_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gsldatacache.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* --- typedefs & structures --- */
+typedef enum /*< skip >*/
+{
+ GSL_WAVE_LOOP_NONE,
+ GSL_WAVE_LOOP_JUMP,
+ GSL_WAVE_LOOP_PINGPONG
+} GslWaveLoopType;
+typedef struct
+{
+ GslLong start, end, length;
+ gfloat *mem;
+} GslWaveChunkMem;
+struct _GslWaveChunk
+{
+ /* wave chunk data residency */
+ GslDataCache *dcache;
+ GslLong length; /* number of per-channel-values * n-channels */
+
+ /* chunk specific parameters */
+ gint n_channels;
+ GslLong n_pad_values; /* guaranteed pad values around blocks */
+ GslLong wave_length; /* start + loop duration + end (single channel) */
+
+ /* flags */
+ guint pploop_ends_backwards : 1;
+ guint mini_loop : 1;
+
+ /* loop spec */
+ GslWaveLoopType loop_type;
+ GslLong loop_first;
+ GslLong loop_last;
+ guint loop_count;
+
+ /* preformatted blocks */
+ GslWaveChunkMem head;
+ GslWaveChunkMem enter;
+ GslWaveChunkMem wrap;
+ GslWaveChunkMem ppwrap;
+ GslWaveChunkMem leave;
+ GslWaveChunkMem tail;
+ GslLong leave_end_norm;
+ GslLong tail_start_norm;
+
+ GslWaveLoopType requested_loop_type;
+ GslLong requested_loop_first;
+ GslLong requested_loop_last;
+ guint requested_loop_count;
+ guint ref_count;
+ guint open_count;
+ /* legacy */
+ gfloat mix_freq; /* recorded with mix_freq */
+ gfloat osc_freq; /* while oscillating at osc_freq */
+};
+struct _GslWaveChunkBlock
+{
+ /* requisition (in) */
+ gint play_dir; /* usually +1 */
+ GslLong offset; /* requested offset into wave */
+ /* result (out) */
+ GslLong length; /* resulting signed? length of block in # values */
+ gboolean is_silent; /* sample end reached, values are 0 */
+ gint dirstride; /* >0 => increment, <0 => decrement */
+ gfloat *start; /* first data value location */
+ gfloat *end; /* last data value location +1 */
+ GslLong next_offset; /* offset of next adjunct block */
+ /*< private >*/
+ gpointer node;
+};
+
+
+/* --- prototypes --- */
+void gsl_wave_chunk_use_block (GslWaveChunk *wave_chunk,
+ GslWaveChunkBlock *block);
+void gsl_wave_chunk_unuse_block (GslWaveChunk *wave_chunk,
+ GslWaveChunkBlock *block);
+GslWaveChunk* gsl_wave_chunk_new (GslDataCache *dcache,
+ gfloat osc_freq,
+ gfloat mix_freq,
+ GslWaveLoopType loop_type,
+ GslLong loop_first,
+ GslLong loop_end,
+ guint loop_count);
+GslWaveChunk* gsl_wave_chunk_ref (GslWaveChunk *wchunk);
+void gsl_wave_chunk_unref (GslWaveChunk *wchunk);
+GslErrorType gsl_wave_chunk_open (GslWaveChunk *wchunk);
+void gsl_wave_chunk_close (GslWaveChunk *wchunk);
+void gsl_wave_chunk_debug_block (GslWaveChunk *wchunk,
+ GslLong offset,
+ GslLong length,
+ gfloat *block);
+GslWaveChunk* _gsl_wave_chunk_copy (GslWaveChunk *wchunk);
+const gchar* gsl_wave_loop_type_to_string (GslWaveLoopType wave_loop);
+GslWaveLoopType gsl_wave_loop_type_from_string (const gchar *string);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_WAVE_CHUNK_H__ */
diff --git a/flow/gsl/gslwaveloader.c b/flow/gsl/gslwaveloader.c
new file mode 100644
index 0000000..cd097d9
--- /dev/null
+++ b/flow/gsl/gslwaveloader.c
@@ -0,0 +1,2 @@
+#include <gsl/gslwaveloader.h>
+
diff --git a/flow/gsl/gslwaveloader.h b/flow/gsl/gslwaveloader.h
new file mode 100644
index 0000000..7453359
--- /dev/null
+++ b/flow/gsl/gslwaveloader.h
@@ -0,0 +1,6 @@
+
+#ifndef GSLWAVELOADER_H
+#define GSLWAVELOADER_H
+
+#endif // GSLWAVELOADER_H
+
diff --git a/flow/gsl/gslwaveosc-aux.c b/flow/gsl/gslwaveosc-aux.c
new file mode 100644
index 0000000..4485242
--- /dev/null
+++ b/flow/gsl/gslwaveosc-aux.c
@@ -0,0 +1,249 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#define CHECK_SYNC (WOSC_MIX_VARIANT & WOSC_MIX_WITH_SYNC)
+#define CHECK_FREQ (WOSC_MIX_VARIANT & WOSC_MIX_WITH_FREQ)
+#define CHECK_MOD (WOSC_MIX_VARIANT & WOSC_MIX_WITH_MOD)
+#define EXPONENTIAL_FM (WOSC_MIX_VARIANT & WOSC_MIX_WITH_EXP_FM)
+#define DIRSTRIDE(b) (b->dirstride) /* (1) change for n_channel stepping */
+
+
+static void
+WOSC_MIX_VARIANT_NAME (GslWaveOscData *wosc,
+ guint n_values,
+ const gfloat *freq_in,
+ const gfloat *mod_in,
+ const gfloat *sync_in,
+ gfloat *wave_out)
+{
+ gfloat *wave_boundary;
+ gfloat last_sync_level = wosc->last_sync_level;
+ gfloat last_freq_level = wosc->last_freq_level;
+ gfloat last_mod_level = wosc->last_mod_level;
+ GslWaveChunkBlock *block = &wosc->block;
+ gdouble *a = wosc->a, *b = wosc->b, *y = wosc->y;
+ gfloat *boundary = block->end;
+ guint wosc_j = wosc->j;
+
+ /* do the mixing */
+ wave_boundary = wave_out + n_values;
+ do
+ {
+ gfloat ffrac;
+
+ if (CHECK_SYNC)
+ {
+ gfloat sync_level = *sync_in++;
+ if_reject (GSL_SIGNAL_RAISING_EDGE (last_sync_level, sync_level))
+ {
+ wosc->j = wosc_j;
+ gsl_wave_osc_retrigger (wosc, CHECK_FREQ ? GSL_SIGNAL_TO_FREQ (*freq_in) : wosc->config.cfreq);
+ /* retrigger alters last_freq and last_mod */
+ last_freq_level = wosc->last_freq_level;
+ last_mod_level = wosc->last_mod_level;
+ wosc_j = wosc->j;
+ boundary = block->end;
+ /* FIXME: g_assert (ABS (block->dirstride) == 1); */
+ last_sync_level = sync_level;
+ }
+ }
+ if (CHECK_MOD && CHECK_FREQ)
+ {
+ gfloat mod_level = *mod_in++, freq_level = *freq_in++;
+ if_reject (GSL_SIGNAL_FREQ_CHANGED (last_freq_level, freq_level))
+ {
+ last_freq_level = freq_level;
+ if (GSL_SIGNAL_MOD_CHANGED (last_mod_level, mod_level))
+ last_mod_level = mod_level;
+ goto UPDATE_FREQ;
+ }
+ else if_reject (GSL_SIGNAL_MOD_CHANGED (last_mod_level, mod_level))
+ {
+ gfloat new_freq;
+ last_mod_level = mod_level;
+ UPDATE_FREQ:
+ new_freq = GSL_SIGNAL_TO_FREQ (freq_level);
+ if (EXPONENTIAL_FM)
+ new_freq *= gsl_signal_exp2 (wosc->config.fm_strength * mod_level);
+ else /* LINEAR_FM */
+ new_freq *= 1.0 + wosc->config.fm_strength * mod_level;
+ wave_osc_transform_filter (wosc, new_freq);
+ }
+ }
+ else if (CHECK_MOD)
+ {
+ gfloat mod_level = *mod_in++;
+ if (GSL_SIGNAL_MOD_CHANGED (last_mod_level, mod_level))
+ {
+ gfloat new_freq = wosc->config.cfreq;
+ if (EXPONENTIAL_FM)
+ new_freq *= gsl_signal_exp2 (wosc->config.fm_strength * mod_level);
+ else /* LINEAR_FM */
+ new_freq *= 1.0 + wosc->config.fm_strength * mod_level;
+ last_mod_level = mod_level;
+ wave_osc_transform_filter (wosc, new_freq);
+ }
+ }
+ else if (CHECK_FREQ)
+ {
+ gfloat freq_level = *freq_in++;
+ if (GSL_SIGNAL_FREQ_CHANGED (last_freq_level, freq_level))
+ {
+ last_freq_level = freq_level;
+ wave_osc_transform_filter (wosc, GSL_SIGNAL_TO_FREQ (freq_level));
+ }
+ }
+
+ /* process filter while necesary */
+ while (wosc->cur_pos >= (FRAC_MASK + 1) << 1)
+ {
+ gfloat c, c0, c1, c2, c3, c4, c5, c6, c7, c8;
+ gfloat d, d0, d1, d2, d3, d4, d5, d6, d7;
+ gfloat *x;
+
+ if_reject (wosc->x >= boundary) /* wchunk block boundary */
+ {
+ GslLong next_offset = block->next_offset;
+
+ gsl_wave_chunk_unuse_block (wosc->wchunk, block);
+ block->play_dir = wosc->config.play_dir;
+ block->offset = next_offset;
+ gsl_wave_chunk_use_block (wosc->wchunk, block);
+ wosc->x = block->start + wosc->config.channel;
+ boundary = block->end;
+ /* FIXME: g_assert (ABS (block->dirstride) == 1); */
+ }
+
+ if_expect (block->dirstride > 0)
+ {
+ x = wosc->x;
+ d0 = b[0] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d1 = b[1] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d2 = b[2] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d3 = b[3] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d4 = b[4] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d5 = b[5] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d6 = b[6] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d7 = b[7] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ c8 = a[8] * x[-4 * DIRSTRIDE (block)];
+ c6 = a[6] * x[-3 * DIRSTRIDE (block)];
+ c4 = a[4] * x[-2 * DIRSTRIDE (block)];
+ c2 = a[2] * x[-1 * DIRSTRIDE (block)];
+ c0 = a[0] * x[0 * DIRSTRIDE (block)];
+ d = d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7;
+ c = c0 + c2 + c4 + c6 + c8;
+ y[wosc_j] = c - d; wosc_j++; wosc_j &= 0x7;
+ d0 = b[0] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d1 = b[1] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d2 = b[2] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d3 = b[3] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d4 = b[4] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d5 = b[5] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d6 = b[6] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d7 = b[7] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ c7 = a[7] * x[-3 * DIRSTRIDE (block)];
+ c5 = a[5] * x[-2 * DIRSTRIDE (block)];
+ c3 = a[3] * x[-1 * DIRSTRIDE (block)];
+ c1 = a[1] * x[0 * DIRSTRIDE (block)];
+ d = d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7;
+ c = c1 + c3 + c5 + c7;
+ y[wosc_j] = c - d; wosc_j++; wosc_j &= 0x7;
+ wosc->x += DIRSTRIDE (block);
+ }
+ else /* dirstride < 0 */
+ {
+ x = wosc->x;
+ d0 = b[0] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d1 = b[1] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d2 = b[2] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d3 = b[3] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d4 = b[4] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d5 = b[5] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d6 = b[6] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d7 = b[7] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ c8 = a[8] * x[-4 * -DIRSTRIDE (block)];
+ c6 = a[6] * x[-3 * -DIRSTRIDE (block)];
+ c4 = a[4] * x[-2 * -DIRSTRIDE (block)];
+ c2 = a[2] * x[-1 * -DIRSTRIDE (block)];
+ c0 = a[0] * x[0 * -DIRSTRIDE (block)];
+ d = d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7;
+ c = c0 + c2 + c4 + c6 + c8;
+ y[wosc_j] = c - d; wosc_j++; wosc_j &= 0x7;
+ d0 = b[0] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d1 = b[1] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d2 = b[2] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d3 = b[3] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d4 = b[4] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d5 = b[5] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d6 = b[6] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ d7 = b[7] * y[wosc_j]; wosc_j++; wosc_j &= 0x7;
+ c7 = a[7] * x[-3 * -DIRSTRIDE (block)];
+ c5 = a[5] * x[-2 * -DIRSTRIDE (block)];
+ c3 = a[3] * x[-1 * -DIRSTRIDE (block)];
+ c1 = a[1] * x[0 * -DIRSTRIDE (block)];
+ d = d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7;
+ c = c1 + c3 + c5 + c7;
+ y[wosc_j] = c - d; wosc_j++; wosc_j &= 0x7;
+ wosc->x += -DIRSTRIDE (block);
+ }
+
+ wosc->cur_pos -= (FRAC_MASK + 1) << 1;
+ }
+
+ /* interpolate filter output from current pos
+ * wosc->cur_pos >> FRAC_SHIFT is 1 or 0;
+ */
+ if (wosc->cur_pos >> FRAC_SHIFT)
+ {
+ guint k = wosc_j - 2;
+
+ ffrac = wosc->cur_pos & FRAC_MASK; /* int -> float */
+ ffrac *= 1. / (FRAC_MASK + 1.);
+ *wave_out++ = y[k & 0x7] * (1.0 - ffrac) + y[(k + 1) & 0x7] * ffrac;
+ }
+ else
+ {
+ guint k = wosc_j - 3;
+
+ ffrac = wosc->cur_pos; /* int -> float */
+ ffrac *= 1. / (FRAC_MASK + 1.);
+ *wave_out++ = y[k & 0x7] * (1.0 - ffrac) + y[(k + 1) & 0x7] * ffrac;
+ }
+
+ /* increment */
+ wosc->cur_pos += wosc->istep;
+ }
+ while (wave_out < wave_boundary);
+ wosc->j = wosc_j;
+ wosc->last_sync_level = last_sync_level;
+ wosc->last_freq_level = last_freq_level;
+ wosc->last_mod_level = last_mod_level;
+}
+
+#undef CHECK_SYNC
+#undef CHECK_FREQ
+#undef CHECK_MOD
+#undef EXPONENTIAL_FM
+#undef DIRSTRIDE
+
+#undef WOSC_MIX_VARIANT
+#undef WOSC_MIX_VARIANT_NAME
+
+/* vim:set ts=8 sw=2 sts=2: */
diff --git a/flow/gsl/gslwaveosc.c b/flow/gsl/gslwaveosc.c
new file mode 100644
index 0000000..a17c836
--- /dev/null
+++ b/flow/gsl/gslwaveosc.c
@@ -0,0 +1,376 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslwaveosc.h"
+
+#include "gslfilter.h"
+#include "gslsignal.h"
+#include "gslengine.h" /* for gsl_engine_sample_freq() */
+#include <string.h>
+
+
+#define FRAC_SHIFT (16)
+#define FRAC_MASK ((1 << FRAC_SHIFT) - 1)
+#define SIGNAL_LEVEL_INVAL (-2.0) /* trigger level-changed checks */
+
+
+/* --- prototype --- */
+static void wave_osc_transform_filter (GslWaveOscData *wosc,
+ gfloat play_freq);
+
+
+/* --- generated function variants --- */
+#define WOSC_MIX_VARIANT_INVAL (0xffffffff)
+#define WOSC_MIX_WITH_SYNC (1)
+#define WOSC_MIX_WITH_FREQ (2)
+#define WOSC_MIX_WITH_MOD (4)
+#define WOSC_MIX_WITH_EXP_FM (8)
+#define WOSC_MIX_VARIANT_NAME wosc_process_sfme
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process_sfm_
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0 )
+#include "gslwaveosc-aux.c"
+#if 0
+#define WOSC_MIX_VARIANT_NAME wosc_process_sf_e
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#endif
+#define WOSC_MIX_VARIANT_NAME wosc_process_sf__
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | 0 )
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process_s_me
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process_s_m_
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | 0 )
+#include "gslwaveosc-aux.c"
+#if 0
+#define WOSC_MIX_VARIANT_NAME wosc_process_s__e
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | 0 | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#endif
+#define WOSC_MIX_VARIANT_NAME wosc_process_s___
+#define WOSC_MIX_VARIANT (WOSC_MIX_WITH_SYNC | 0 | 0 | 0 )
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process__fme
+#define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process__fm_
+#define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0 )
+#include "gslwaveosc-aux.c"
+#if 0
+#define WOSC_MIX_VARIANT_NAME wosc_process__f_e
+#define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#endif
+#define WOSC_MIX_VARIANT_NAME wosc_process__f__
+#define WOSC_MIX_VARIANT (0 | WOSC_MIX_WITH_FREQ | 0 | 0 )
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process___me
+#define WOSC_MIX_VARIANT (0 | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#define WOSC_MIX_VARIANT_NAME wosc_process___m_
+#define WOSC_MIX_VARIANT (0 | 0 | WOSC_MIX_WITH_MOD | 0 )
+#include "gslwaveosc-aux.c"
+#if 0
+#define WOSC_MIX_VARIANT_NAME wosc_process____e
+#define WOSC_MIX_VARIANT (0 | 0 | 0 | WOSC_MIX_WITH_EXP_FM)
+#include "gslwaveosc-aux.c"
+#endif
+#define WOSC_MIX_VARIANT_NAME wosc_process_____
+#define WOSC_MIX_VARIANT (0 | 0 | 0 | 0 )
+#include "gslwaveosc-aux.c"
+
+
+/* --- functions --- */
+gboolean
+gsl_wave_osc_process (GslWaveOscData *wosc,
+ guint n_values,
+ const gfloat *freq_in,
+ const gfloat *mod_in,
+ const gfloat *sync_in,
+ gfloat *mono_out)
+{
+ guint mode = 0;
+
+ g_return_val_if_fail (wosc != NULL, FALSE);
+ g_return_val_if_fail (n_values > 0, FALSE);
+ g_return_val_if_fail (mono_out != NULL, FALSE);
+
+ if_reject (!wosc->config.wchunk_from_freq)
+ return FALSE;
+
+ /* mode changes:
+ * freq_in: if (freq_in) last_freq=inval else set_filter()
+ * sync_in: last_sync=0
+ * mod_in: if (mod_in) last_mod=0 else if (freq_in) last_freq=inval else transform_filter()
+ * exp_mod: n/a
+ */
+
+ if (sync_in)
+ mode |= WOSC_MIX_WITH_SYNC;
+ if (freq_in)
+ mode |= WOSC_MIX_WITH_FREQ;
+ if (mod_in)
+ mode |= WOSC_MIX_WITH_MOD;
+ if (wosc->config.exponential_fm)
+ mode |= WOSC_MIX_WITH_EXP_FM;
+
+ if_reject (mode != wosc->last_mode)
+ {
+ guint mask = wosc->last_mode ^ mode;
+
+ if (mask & WOSC_MIX_WITH_SYNC)
+ wosc->last_sync_level = 0;
+ if (mask & WOSC_MIX_WITH_FREQ)
+ {
+ if (freq_in)
+ wosc->last_freq_level = SIGNAL_LEVEL_INVAL;
+ else
+ gsl_wave_osc_set_filter (wosc, wosc->config.cfreq, FALSE);
+ }
+ if (mask & WOSC_MIX_WITH_MOD)
+ {
+ if (mod_in)
+ wosc->last_mod_level = 0;
+ else if (freq_in)
+ wosc->last_freq_level = SIGNAL_LEVEL_INVAL;
+ else /* !mod_in && !freq_in */
+ wave_osc_transform_filter (wosc, wosc->config.cfreq);
+ }
+ wosc->last_mode = mode;
+ }
+
+ switch (mode)
+ {
+ case 0 | 0 | 0 | 0:
+ case 0 | 0 | 0 | WOSC_MIX_WITH_EXP_FM:
+ wosc_process_____ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case 0 | 0 | WOSC_MIX_WITH_MOD | 0:
+ wosc_process___m_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case 0 | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
+ wosc_process___me (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case 0 | WOSC_MIX_WITH_FREQ | 0 | 0:
+ case 0 | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM:
+ wosc_process__f__ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case 0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0:
+ wosc_process__fm_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case 0 | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
+ wosc_process__fme (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case WOSC_MIX_WITH_SYNC | 0 | 0 | 0:
+ case WOSC_MIX_WITH_SYNC | 0 | 0 | WOSC_MIX_WITH_EXP_FM:
+ wosc_process_s___ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | 0:
+ wosc_process_s_m_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case WOSC_MIX_WITH_SYNC | 0 | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
+ wosc_process_s_me (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | 0:
+ case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | 0 | WOSC_MIX_WITH_EXP_FM:
+ wosc_process_sf__ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | 0:
+ wosc_process_sfm_ (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ case WOSC_MIX_WITH_SYNC | WOSC_MIX_WITH_FREQ | WOSC_MIX_WITH_MOD | WOSC_MIX_WITH_EXP_FM:
+ wosc_process_sfme (wosc, n_values, freq_in, mod_in, sync_in, mono_out);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (wosc->y[0] != 0.0 &&
+ !(fabs (wosc->y[0]) > GSL_SIGNAL_EPSILON && fabs (wosc->y[0]) < GSL_SIGNAL_KAPPA))
+ {
+ guint i;
+
+ /*g_printerr ("clearing filter state at:\n");*/
+ for (i = 0; i < GSL_WAVE_OSC_FILTER_ORDER; i++)
+ {
+ /*g_printerr ("%u) %+.38f\n", i, wosc->y[i]);*/
+ if (GSL_DOUBLE_IS_INF (wosc->y[0]) || fabs (wosc->y[0]) > GSL_SIGNAL_KAPPA)
+ wosc->y[i] = GSL_DOUBLE_SIGN (wosc->y[0]) ? -1.0 : 1.0;
+ else
+ wosc->y[i] = 0.0;
+ }
+ }
+ g_assert (!GSL_DOUBLE_IS_NANINF (wosc->y[0]));
+ g_assert (!GSL_DOUBLE_IS_SUBNORMAL (wosc->y[0]));
+
+ wosc->done = (wosc->block.is_silent && /* FIXME, let filter state run out? */
+ ((wosc->block.play_dir < 0 && wosc->block.offset < 0) ||
+ (wosc->block.play_dir > 0 && wosc->block.offset > wosc->wchunk->wave_length)));
+
+ return TRUE;
+}
+
+void
+gsl_wave_osc_set_filter (GslWaveOscData *wosc,
+ gfloat play_freq,
+ gboolean clear_state)
+{
+ gfloat zero_padding = 2;
+ gfloat step;
+ guint i, istep;
+
+ g_return_if_fail (play_freq > 0);
+
+ if_reject (!wosc->config.wchunk_from_freq)
+ return;
+
+ wosc->step_factor = zero_padding * wosc->wchunk->mix_freq;
+ wosc->step_factor /= wosc->wchunk->osc_freq * wosc->mix_freq;
+ step = wosc->step_factor * play_freq;
+ istep = step * (FRAC_MASK + 1.) + 0.5;
+
+ if (istep != wosc->istep)
+ {
+ gfloat nyquist_fact = GSL_PI * 2.0 / wosc->mix_freq, cutoff_freq = 18000, stop_freq = 24000;
+ gfloat empiric_filter_stability_limit = 6.;
+ gfloat filt_fact = CLAMP (1. / step,
+ 1. / (empiric_filter_stability_limit * zero_padding),
+ 1. / zero_padding /* spectrum half */);
+ gfloat freq_c = cutoff_freq * nyquist_fact * filt_fact;
+ gfloat freq_r = stop_freq * nyquist_fact * filt_fact;
+
+ /* FIXME: this should store filter roots and poles, so modulation does lp->lp transform */
+
+ wosc->istep = istep;
+ gsl_filter_tscheb2_lp (GSL_WAVE_OSC_FILTER_ORDER, freq_c, freq_r / freq_c, 0.18, wosc->a, wosc->b);
+ for (i = 0; i < GSL_WAVE_OSC_FILTER_ORDER + 1; i++)
+ wosc->a[i] *= zero_padding; /* scale to compensate for zero-padding */
+ for (i = 0; i < (GSL_WAVE_OSC_FILTER_ORDER + 1) / 2; i++) /* reverse bs */
+ {
+ gfloat t = wosc->b[GSL_WAVE_OSC_FILTER_ORDER - i];
+
+ wosc->b[GSL_WAVE_OSC_FILTER_ORDER - i] = wosc->b[i];
+ wosc->b[i] = t;
+ }
+ /*g_printerr ("filter: fc=%f fr=%f st=%f is=%u\n", freq_c/GSL_PI*2, freq_r/GSL_PI*2, step, wosc->istep);*/
+ }
+
+ if (clear_state)
+ {
+ /* clear filter state */
+ memset (wosc->y, 0, sizeof (wosc->y));
+ wosc->j = 0;
+ wosc->cur_pos = 0; /* might want to initialize with istep? */
+ }
+}
+
+static void
+wave_osc_transform_filter (GslWaveOscData *wosc,
+ gfloat play_freq)
+{
+ gfloat step;
+ guint istep;
+
+ step = wosc->step_factor * play_freq;
+ istep = step * (FRAC_MASK + 1.) + 0.5;
+ if (istep != wosc->istep)
+ {
+ wosc->istep = istep;
+ /* transform filter poles and roots, normalize filter, update a[] and b[] */
+ }
+}
+
+void
+gsl_wave_osc_retrigger (GslWaveOscData *wosc,
+ gfloat base_freq)
+{
+ g_return_if_fail (wosc != NULL);
+
+ if_reject (!wosc->config.wchunk_from_freq)
+ return;
+
+ if (wosc->wchunk)
+ gsl_wave_chunk_unuse_block (wosc->wchunk, &wosc->block);
+ wosc->wchunk = wosc->config.wchunk_from_freq (wosc->config.wchunk_data, base_freq);
+ wosc->block.play_dir = wosc->config.play_dir;
+ wosc->block.offset = wosc->config.start_offset;
+ gsl_wave_chunk_use_block (wosc->wchunk, &wosc->block);
+ wosc->x = wosc->block.start + wosc->config.channel;
+
+ /*g_printerr ("wave lookup: want=%f got=%f length=%lu\n",
+ base_freq, wosc->wchunk->osc_freq, wosc->wchunk->wave_length);*/
+
+ wosc->last_freq_level = GSL_SIGNAL_FROM_FREQ (base_freq);
+ wosc->last_mod_level = 0;
+ gsl_wave_osc_set_filter (wosc, base_freq, TRUE);
+}
+
+void
+gsl_wave_osc_config (GslWaveOscData *wosc,
+ GslWaveOscConfig *config)
+{
+ g_return_if_fail (wosc != NULL);
+ g_return_if_fail (config != NULL);
+
+ if (wosc->config.wchunk_data != config->wchunk_data ||
+ wosc->config.wchunk_from_freq != config->wchunk_from_freq ||
+ wosc->config.channel != config->channel)
+ {
+ if (wosc->wchunk)
+ gsl_wave_chunk_unuse_block (wosc->wchunk, &wosc->block);
+ wosc->wchunk = NULL;
+ wosc->config = *config;
+ gsl_wave_osc_retrigger (wosc, wosc->config.cfreq);
+ }
+ else
+ {
+ wosc->config.play_dir = config->play_dir;
+ wosc->config.fm_strength = config->fm_strength;
+ if (wosc->config.cfreq != config->cfreq ||
+ wosc->config.start_offset != config->start_offset)
+ {
+ wosc->config.start_offset = config->start_offset;
+ wosc->config.cfreq = config->cfreq;
+ gsl_wave_osc_retrigger (wosc, wosc->config.cfreq);
+ }
+ }
+}
+
+void
+gsl_wave_osc_init (GslWaveOscData *wosc)
+{
+ g_return_if_fail (wosc != NULL);
+
+ g_assert (GSL_WAVE_OSC_FILTER_ORDER <= gsl_get_config ()->wave_chunk_padding);
+
+ memset (wosc, 0, sizeof (GslWaveOscData));
+ wosc->mix_freq = gsl_engine_sample_freq ();
+}
+
+void
+gsl_wave_osc_shutdown (GslWaveOscData *wosc)
+{
+ g_return_if_fail (wosc != NULL);
+
+ if (wosc->wchunk)
+ gsl_wave_chunk_unuse_block (wosc->wchunk, &wosc->block);
+ memset (wosc, 0xaa, sizeof (GslWaveOscData));
+}
diff --git a/flow/gsl/gslwaveosc.h b/flow/gsl/gslwaveosc.h
new file mode 100644
index 0000000..c41b207
--- /dev/null
+++ b/flow/gsl/gslwaveosc.h
@@ -0,0 +1,96 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __GSL_WAVE_OSC_H__
+#define __GSL_WAVE_OSC_H__
+
+#include <gsl/gsldefs.h>
+#include <gsl/gslwavechunk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GSL_WAVE_OSC_FILTER_ORDER (8) /* <= GslConfig.wave_chunk_padding ! */
+
+typedef struct
+{
+ GslLong start_offset;
+ gint play_dir, channel;
+
+ gpointer wchunk_data;
+ GslWaveChunk* (*wchunk_from_freq) (gpointer wchunk_data,
+ gfloat freq);
+
+ gfloat fm_strength; /* linear: 0..1, exponential: n_octaves */
+ guint exponential_fm : 1;
+ gfloat cfreq; /* for ifreq == NULL */
+} GslWaveOscConfig;
+
+typedef struct
+{
+ GslWaveOscConfig config;
+ guint last_mode;
+ gfloat last_sync_level, last_freq_level, last_mod_level;
+ GslWaveChunkBlock block;
+ gfloat *x; /* pointer into block */
+ guint cur_pos, istep; /* FIXME */
+ gdouble a[GSL_WAVE_OSC_FILTER_ORDER + 1]; /* order */
+ gdouble b[GSL_WAVE_OSC_FILTER_ORDER + 1]; /* reversed order */
+ gdouble y[GSL_WAVE_OSC_FILTER_ORDER + 1];
+ guint j; /* y[] index */
+ GslWaveChunk *wchunk;
+ gfloat mix_freq; /* gsl_engine_sample_freq() */
+ gfloat step_factor;
+ gboolean done; /* FIXME. caution, this is TRUE only if
+ * (play_dir < 0 && cur_pos < 0) ||
+ * (play_dir > 0 && cur_pos > wchunk.length)
+ */
+} GslWaveOscData;
+
+
+void gsl_wave_osc_config (GslWaveOscData *wosc,
+ GslWaveOscConfig *config);
+gboolean gsl_wave_osc_process (GslWaveOscData *wosc,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *mod,
+ const gfloat *sync,
+ gfloat *mono_out);
+void gsl_wave_osc_retrigger (GslWaveOscData *wosc,
+ gfloat freq);
+void gsl_wave_osc_set_filter (GslWaveOscData *wosc,
+ gfloat freq,
+ gboolean clear_state);
+
+void gsl_wave_osc_init (GslWaveOscData *wosc);
+void gsl_wave_osc_shutdown (GslWaveOscData *wosc);
+
+/* setup:
+ * wosc = g_new0 (GslWaveOscData, 1);
+ * wosc->mix_freq = gsl_engine_sample_freq ();
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GSL_WAVE_OSC_H__ */
diff --git a/flow/gsl/gslwchunk.c b/flow/gsl/gslwchunk.c
new file mode 100644
index 0000000..1fa4d74
--- /dev/null
+++ b/flow/gsl/gslwchunk.c
@@ -0,0 +1,279 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik
+ *
+ * This program 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 of the License, or (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslwavechunk.h"
+#include "gsldatahandle.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <math.h>
+
+enum {
+ VERBOSITY_NONE,
+ VERBOSITY_SETUP,
+ VERBOSITY_BLOCKS,
+ VERBOSITY_DATA,
+ VERBOSITY_PADDING,
+ VERBOSITY_CHECKS,
+};
+static guint verbosity = VERBOSITY_SETUP;
+
+static gfloat my_data[] = {
+ 0.555555555,1,2,3,4,5,6,7,8,9,
+ 10,11,12,13,14,15,16,17,18,19,
+ 20,21,22,23,24,25,26,27,28,29,
+ 30,31,32,33,34,35,36,
+};
+static guint my_data_length = sizeof (my_data) / sizeof (my_data[0]);
+
+static void print_block (GslWaveChunk *wchunk,
+ GslWaveChunkBlock *block);
+
+#define DEBUG_SIZE (1024 * 256)
+#define MINI_DEBUG_SIZE (16)
+
+static void
+run_tests (GslWaveLoopType loop_type,
+ gint play_dir,
+ gint loop_first,
+ gint loop_last,
+ gint loop_count)
+{
+ gfloat tmpstorage[DEBUG_SIZE], *cmpblock = tmpstorage + DEBUG_SIZE / 2;
+ GslDataHandle *myhandle;
+ GslDataCache *dcache;
+ GslWaveChunkBlock block = { 0, 0 };
+ GslWaveChunk *wchunk;
+ GslErrorType error;
+
+ myhandle = gsl_data_handle_new_mem (1, 32, my_data_length, my_data, NULL);
+ dcache = gsl_data_cache_new (myhandle, 1);
+ gsl_data_handle_unref (myhandle);
+ wchunk = gsl_wave_chunk_new (dcache,
+ 44.0, 44100.0,
+ loop_type, loop_first, loop_last, loop_count);
+ error = gsl_wave_chunk_open (wchunk);
+ if (error)
+ g_error ("failed to open wave chunk: %s", gsl_strerror (error));
+ gsl_wave_chunk_unref (wchunk);
+ if (verbosity >= VERBOSITY_SETUP)
+ g_print ("SETUP: loop_type=%u loop_first=%ld loop_last=%ld loop_count=%d playdir=%+d\n",
+ wchunk->loop_type, wchunk->loop_first, wchunk->loop_last, wchunk->loop_count, play_dir);
+ gsl_wave_chunk_debug_block (wchunk, - DEBUG_SIZE / 2, DEBUG_SIZE, cmpblock - DEBUG_SIZE / 2);
+
+ block.play_dir = play_dir;
+
+ block.offset = block.play_dir < 0 ? wchunk->wave_length + MINI_DEBUG_SIZE/2 : -MINI_DEBUG_SIZE/2;
+ while (block.offset < wchunk->wave_length + MINI_DEBUG_SIZE &&
+ block.offset > -MINI_DEBUG_SIZE)
+ {
+ gint i, start, end, abort;
+
+ gsl_wave_chunk_use_block (wchunk, &block);
+
+ print_block (wchunk, &block);
+ if (block.play_dir > 0)
+ {
+ start = block.offset - wchunk->n_pad_values;
+ end = block.offset + block.length + wchunk->n_pad_values;
+ }
+ else
+ {
+ start = block.offset + wchunk->n_pad_values;
+ end = block.offset - block.length - wchunk->n_pad_values;
+ }
+ abort = FALSE;
+ for (i = start; i != end; i += block.play_dir)
+ {
+ gfloat v = (block.play_dir < 0) ^ (block.dirstride > 0) ? block.start[i - block.offset] : block.start[block.offset - i];
+
+ if (fabs (cmpblock[i] - v) > 1e-15)
+ {
+ abort = TRUE;
+ verbosity = 99;
+ }
+ if (verbosity >= VERBOSITY_CHECKS)
+ g_print ("%s: offset=%d (block.offset=%ld) value=%.16f found=%.16f\n",
+ fabs (cmpblock[i] - v) > 1e-15 ? "MISMATCH" : "match",
+ i, (i - block.offset), cmpblock[i], v);
+ }
+ if (abort)
+ {
+ g_error ("mismatches occoured, setup: loop_type=%u loop_first=%ld loop_last=%ld loop_count=%d (length=%ld)",
+ wchunk->loop_type, wchunk->loop_first, wchunk->loop_last, wchunk->loop_count,
+ gsl_data_handle_length (wchunk->dcache->dhandle));
+ }
+
+ gsl_wave_chunk_unuse_block (wchunk, &block);
+
+ block.offset = block.next_offset;
+ /* block.offset += block.play_dir; */
+ }
+ gsl_wave_chunk_close (wchunk);
+ gsl_data_cache_unref (dcache);
+}
+
+static void
+print_block (GslWaveChunk *wchunk,
+ GslWaveChunkBlock *block)
+{
+ gfloat *p = NULL;
+ guint i;
+
+ if (verbosity >= VERBOSITY_BLOCKS)
+ {
+ g_print ("BLOCK:");
+ g_print (" offset=%ld", block->offset);
+ g_print (" length=%ld", block->length);
+ g_print (" dirstride=%d", block->dirstride);
+ }
+
+ if (verbosity >= VERBOSITY_PADDING)
+ {
+ g_print (" {prepad:");
+ i = wchunk->n_pad_values;
+ p = block->start - (block->dirstride > 0 ? i : -i);
+ while (i--)
+ {
+ g_print (" %.1f", *p);
+ p += block->dirstride;
+ }
+ g_print ("}");
+ }
+
+ if (verbosity >= VERBOSITY_DATA)
+ {
+ g_print (" {data:");
+ p = block->start;
+ while (p != block->end)
+ {
+ g_print (" %.1f", *p);
+ p += block->dirstride;
+ }
+ g_print ("}");
+ }
+
+ if (verbosity >= VERBOSITY_PADDING)
+ {
+ i = wchunk->n_pad_values;
+ g_print (" {postpad:");
+ while (i--)
+ {
+ g_print (" %.1f", *p);
+ p += block->dirstride;
+ }
+ g_print ("}");
+ }
+
+ if (verbosity >= VERBOSITY_BLOCKS)
+ g_print ("\n");
+}
+
+int
+main (gint argc,
+ gchar *argv[])
+{
+ GslConfigValue gslconfig[] = {
+ { "wave_chunk_padding", 1, },
+ { "wave_chunk_big_pad", 2, },
+ { "dcache_block_size", 16, },
+ { NULL, },
+ };
+ gint i, j, k;
+
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+ gsl_init (gslconfig, NULL);
+
+ if (1)
+ {
+ GslDataHandle *myhandle;
+ GslDataHandle *rhandle1, *rhandle2;
+ GslLong o, l, i, e;
+ GslErrorType error;
+
+ g_print ("reversed datahandle test:...\n");
+
+ myhandle = gsl_data_handle_new_mem (1, 32, my_data_length, my_data, NULL);
+ rhandle1 = gsl_data_handle_new_reverse (myhandle);
+ gsl_data_handle_unref (myhandle);
+ rhandle2 = gsl_data_handle_new_reverse (rhandle1);
+ gsl_data_handle_unref (rhandle1);
+ error = gsl_data_handle_open (rhandle2);
+ if (error)
+ g_error ("failed to open rhandle2: %s", gsl_strerror (error));
+ gsl_data_handle_unref (rhandle2);
+
+ g_assert (gsl_data_handle_length (rhandle2) == gsl_data_handle_length (myhandle));
+
+ for (i = 1; i < 8; i++)
+ {
+ o = 0;
+ l = gsl_data_handle_length (rhandle2);
+ while (l)
+ {
+ gfloat d1[8], d2[8];
+
+ e = gsl_data_handle_read (myhandle, o, MIN (i, l), d1);
+ g_assert (e == MIN (i, l));
+ e = gsl_data_handle_read (rhandle2, o, MIN (i, l), d2);
+ g_assert (e == MIN (i, l));
+ g_assert (memcmp (d1, d2, sizeof (d1[0]) * e) == 0);
+ l -= e;
+ o += e;
+ }
+ }
+ gsl_data_handle_close (rhandle2);
+ g_print ("passed.\n");
+ }
+
+ if (1)
+ {
+ g_print ("primitive loop tests:...\n");
+
+ run_tests (GSL_WAVE_LOOP_NONE, -1, 0, 0, 0);
+
+ run_tests (GSL_WAVE_LOOP_NONE, 1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_NONE, -1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_JUMP, 1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, 1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_JUMP, -1, 0, 0, 0);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, -1, 0, 0, 0);
+ g_print ("passed.\n");
+ }
+
+ if (1)
+ {
+ g_print ("brute loop tests:...\n");
+ for (i = 1; i < 7; i++)
+ for (j = 0; j < my_data_length - 1; j++)
+ for (k = j + 1; k < my_data_length; k++)
+ {
+ run_tests (GSL_WAVE_LOOP_JUMP, 1, j, k, i);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, 1, j, k, i);
+ run_tests (GSL_WAVE_LOOP_JUMP, -1, j, k, i);
+ run_tests (GSL_WAVE_LOOP_PINGPONG, -1, j, k, i);
+ }
+ g_print ("passed.\n");
+ }
+
+ return 0;
+}
diff --git a/flow/gslpp/Makefile.am b/flow/gslpp/Makefile.am
new file mode 100644
index 0000000..11f7407
--- /dev/null
+++ b/flow/gslpp/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_srcdir)/flow -I$(top_srcdir)/flow/gsl -I$(top_builddir)/flow -I$(top_srcdir)/mcop -I$(top_builddir)/mcop -I$(top_builddir) $(all_includes)
+
+noinst_LTLIBRARIES = libgslpp.la
+
+libgslpp_la_SOURCES = datahandle.cpp
+#libgslpp_la_LIBADD = $(top_builddir)/mcop/libmcop.la $(top_builddir)/flow/gsl/libgsl.la -lm $(LIBPOSIX4)
+#libgslpp_la_LDFLAGS = -no-undefined
diff --git a/flow/gslpp/datahandle.cpp b/flow/gslpp/datahandle.cpp
new file mode 100644
index 0000000..963e57e
--- /dev/null
+++ b/flow/gslpp/datahandle.cpp
@@ -0,0 +1,412 @@
+ /*
+
+ Copyright (C) 2002 Hans Meine
+ hans_meine@gmx.net
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "datahandle.h"
+#include "../../mcop/debug.h"
+
+namespace GSL {
+
+void DataHandle::copyFrom(const DataHandle &other)
+{
+ handle_ = other.handle_;
+ if(handle_)
+ gsl_data_handle_ref(handle_);
+}
+
+DataHandle::DataHandle(GslDataHandle *handle)
+ : handle_(handle)
+{
+}
+
+DataHandle::DataHandle(const DataHandle &other) { copyFrom(other); }
+
+DataHandle &DataHandle::operator =(const DataHandle &other)
+{
+ if(!( other == *this )) {
+ if(handle_)
+ gsl_data_handle_unref(handle_);
+ copyFrom(other);
+ }
+ return *this;
+}
+
+bool DataHandle::operator ==(const DataHandle &other) const
+{
+ return handle_ == other.handle_;
+}
+
+bool DataHandle::isNull() const
+{
+ return handle_ == 0;
+}
+
+DataHandle::~DataHandle()
+{
+ if(handle_)
+ gsl_data_handle_unref(handle_);
+}
+
+gint DataHandle::open()
+{
+ arts_return_val_if_fail(handle_ != 0, -1);
+
+ arts_debug("open()ing datahandle (open_count before: %d)..",
+ handle_->open_count);
+
+ return gsl_data_handle_open(handle_);
+}
+
+void DataHandle::close()
+{
+ arts_return_if_fail(handle_ != 0);
+
+ arts_debug("close()ing datahandle (open_count before: %d)..",
+ handle_->open_count);
+
+ gsl_data_handle_close(handle_);
+}
+
+bool DataHandle::isOpen() const
+{
+ if(!handle_)
+ return false;
+
+ return handle_->open_count != 0;
+}
+
+GslLong DataHandle::read(GslLong valueOffset, GslLong valueCount, gfloat *values)
+{
+ arts_return_val_if_fail(handle_ != 0, 0);
+
+ return gsl_data_handle_read(handle_, valueOffset, valueCount, values);
+}
+
+DataHandle DataHandle::createCropped(GslLong headCutValueCount,
+ GslLong tailCutValueCount)
+{
+ arts_return_val_if_fail(handle_ != 0, null());
+
+ return DataHandle(gsl_data_handle_new_crop(handle_,
+ headCutValueCount, tailCutValueCount));
+}
+
+DataHandle DataHandle::createCut(GslLong cutOffset,
+ GslLong cutValueCount)
+{
+ arts_return_val_if_fail(handle_ != 0, null());
+
+ return DataHandle(gsl_data_handle_new_cut(handle_, cutOffset,
+ cutValueCount));
+}
+
+DataHandle DataHandle::createReversed()
+{
+ arts_return_val_if_fail(handle_ != 0, null());
+
+ return DataHandle(gsl_data_handle_new_reverse(handle_));
+}
+
+GslDataCache *DataHandle::createGslDataCache()
+{
+ arts_debug("wanna have cache with padding %d for each of %d channels..",
+ gsl_get_config()->wave_chunk_padding,
+ channelCount());
+ return gsl_data_cache_from_dhandle(handle_,
+ gsl_get_config()->wave_chunk_padding *
+ channelCount());
+}
+
+GslLong DataHandle::valueCount() const
+{
+ arts_return_val_if_fail(handle_ != 0, 0);
+ arts_return_val_if_fail(isOpen(), 0);
+
+ return handle_->setup.n_values;
+}
+
+guint DataHandle::channelCount() const
+{
+ arts_return_val_if_fail(handle_ != 0, 0);
+ arts_return_val_if_fail(isOpen(), 0);
+
+ return handle_->setup.n_channels;
+}
+
+guint DataHandle::bitDepth() const
+{
+ arts_return_val_if_fail(handle_ != 0, 0);
+ arts_return_val_if_fail(isOpen(), 0);
+
+ return handle_->setup.bit_depth;
+}
+
+// ----------------------------------------------------------------------------
+
+WaveChunkDescription::WaveChunkDescription(const GslWaveDsc *parent, guint index)
+ : parent_(parent), parentIndex_(index)
+{
+ if(index>parent->n_chunks)
+ {
+ arts_debug("wrong index given to WaveChunkDescription constructor, "
+ "using 0 instead..");
+ parentIndex_ = 0;
+ }
+}
+
+float WaveChunkDescription::oscillatorFrequency()
+{
+ return parent_->chunks[parentIndex_].osc_freq;
+}
+
+float WaveChunkDescription::mixerFrequency()
+{
+ return parent_->chunks[parentIndex_].mix_freq;
+}
+
+GslWaveLoopType WaveChunkDescription::loopType()
+{
+ return parent_->chunks[parentIndex_].loop_type;
+}
+
+GslLong WaveChunkDescription::loopStart()
+{
+ return parent_->chunks[parentIndex_].loop_start;
+}
+
+GslLong WaveChunkDescription::loopEnd()
+{
+ return parent_->chunks[parentIndex_].loop_end;
+}
+
+guint WaveChunkDescription::loopCount()
+{
+ return parent_->chunks[parentIndex_].loop_count;
+}
+
+WaveDataHandle WaveChunkDescription::createDataHandle()
+{
+ return WaveDataHandle(parent_, parentIndex_);
+}
+
+// ----------------------------------------------------------------------------
+
+/**
+ * We use GslWaveFileInfos' refcounting - probably this lazy
+ * construction happens only once, where the object is used. After
+ * copying it would have to be constructed again, but that's not
+ * likely to happen. (?)
+ */
+void WaveDescription::ensurePointer() const
+{
+ if(!desc_)
+ desc_ = gsl_wave_dsc_load(parentInfo_, parentIndex_, &error_);
+}
+
+void WaveDescription::copyFrom(const WaveDescription &other)
+{
+ parentInfo_ = other.parentInfo_;
+ parentIndex_ = other.parentIndex_;
+ gsl_wave_file_info_ref(other.parentInfo_);
+}
+
+// internal, private
+WaveDescription::WaveDescription(GslWaveFileInfo *parent, guint index,
+ const std::string &name)
+ : parentInfo_(parent), name_(name), parentIndex_(index),
+ desc_(0), error_(GSL_ERROR_NONE)
+{
+ gsl_wave_file_info_ref(parentInfo_);
+}
+
+WaveDescription::~WaveDescription()
+{
+ if(desc_)
+ gsl_wave_dsc_free(desc_);
+ gsl_wave_file_info_unref(parentInfo_);
+}
+
+WaveDescription::WaveDescription(const WaveDescription &other)
+ : desc_(0), error_(GSL_ERROR_NONE)
+{
+ copyFrom(other);
+}
+
+WaveDescription &WaveDescription::operator =(const WaveDescription &other)
+{
+ if(desc_)
+ gsl_wave_dsc_free(desc_);
+ gsl_wave_file_info_unref(parentInfo_);
+ copyFrom(other);
+ return *this;
+}
+
+const std::string &WaveDescription::name() const
+{
+ return name_;
+}
+
+GslErrorType WaveDescription::error() const
+{
+ ensurePointer();
+ return error_;
+}
+
+guint WaveDescription::chunkCount() const
+{
+ ensurePointer();
+ return desc_ ? desc_->n_chunks : 0;
+}
+
+WaveChunkDescription WaveDescription::chunkDescription(guint index) const
+{
+ ensurePointer();
+ return WaveChunkDescription(desc_, index);
+}
+
+guint WaveDescription::channelCount() const
+{
+ ensurePointer();
+ return desc_ ? desc_->n_channels : 0;
+}
+
+// ----------------------------------------------------------------------------
+
+void WaveFileInfo::copyFrom(const WaveFileInfo &other)
+{
+ info_ = other.info_;
+ filename_ = other.filename_;
+ if(info_)
+ gsl_wave_file_info_ref(info_);
+
+ error_ = other.error_;
+}
+
+WaveFileInfo::WaveFileInfo(const std::string &filename)
+ : info_(0), error_(GSL_ERROR_NONE), filename_(filename)
+{
+ info_ = gsl_wave_file_info_load(filename.c_str(), &error_);
+}
+
+WaveFileInfo::~WaveFileInfo()
+{
+ if(info_)
+ gsl_wave_file_info_unref(info_);
+}
+
+WaveFileInfo::WaveFileInfo(const WaveFileInfo &other)
+{
+ copyFrom(other);
+}
+
+WaveFileInfo &WaveFileInfo::operator =(const WaveFileInfo &other)
+{
+ if(info_)
+ gsl_wave_file_info_unref(info_);
+ copyFrom(other);
+ return *this;
+}
+
+guint WaveFileInfo::waveCount() const
+{
+ return info_ ? info_->n_waves : 0;
+}
+
+std::string WaveFileInfo::waveName(guint index) const
+{
+ if(index >= waveCount())
+ return "";
+ return info_->waves[index].name;
+}
+
+WaveDescription WaveFileInfo::waveDescription(guint index)
+{
+ return WaveDescription(info_, index, waveName(index));
+}
+
+GslErrorType WaveFileInfo::error() const
+{
+ return error_;
+}
+
+// ----------------------------------------------------------------------------
+
+WaveDataHandle::WaveDataHandle()
+ : DataHandle(NULL),
+ oscillatorFrequency_(0),
+ mixerFrequency_(0)
+{
+}
+
+WaveDataHandle::WaveDataHandle(const GslWaveDsc *waveDesc, guint chunkIndex)
+ : DataHandle(NULL),
+ oscillatorFrequency_(0),
+ mixerFrequency_(0)
+{
+ handle_ = gsl_wave_handle_create(const_cast<GslWaveDsc *>(waveDesc),
+ chunkIndex, &error_);
+ if(error() == GSL_ERROR_NONE)
+ {
+ oscillatorFrequency_ = waveDesc->chunks[chunkIndex].osc_freq;
+ mixerFrequency_ = waveDesc->chunks[chunkIndex].mix_freq;
+ }
+}
+
+WaveDataHandle::WaveDataHandle(const std::string& filename,
+ guint waveIndex,
+ guint chunkIndex)
+ : DataHandle(NULL),
+ oscillatorFrequency_(0),
+ mixerFrequency_(0)
+{
+ GSL::WaveFileInfo info(filename);
+ error_ = info.error();
+
+ if(!info.error())
+ {
+ GSL::WaveDescription desc= info.waveDescription(waveIndex);
+ error_ = desc.error();
+
+ if(!desc.error() && (desc.chunkCount() > chunkIndex))
+ {
+ GSL::WaveChunkDescription chunkDesc= desc.chunkDescription(chunkIndex);
+
+ (*this) = chunkDesc.createDataHandle();
+ }
+ }
+}
+
+GslErrorType WaveDataHandle::error() const
+{
+ return error_;
+}
+
+float WaveDataHandle::oscillatorFrequency() const
+{
+ return oscillatorFrequency_;
+}
+
+float WaveDataHandle::mixerFrequency() const
+{
+ return mixerFrequency_;
+}
+
+}
diff --git a/flow/gslpp/datahandle.h b/flow/gslpp/datahandle.h
new file mode 100644
index 0000000..7cab930
--- /dev/null
+++ b/flow/gslpp/datahandle.h
@@ -0,0 +1,220 @@
+ /*
+
+ Copyright (C) 2002 Hans Meine
+ hans_meine@gmx.net
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef GSLPP_DATAHANDLE_H
+#define GSLPP_DATAHANDLE_H
+
+#include <gsl/gsldatahandle.h>
+#include <gsl/gslloader.h>
+#include <string>
+
+namespace GSL
+{
+ class WaveFileInfo;
+ class WaveDataHandle;
+ class WaveDescription;
+
+ class DataHandle
+ {
+ protected:
+ GslDataHandle *handle_;
+
+ void clearHandle();
+ void copyFrom(const DataHandle &other);
+
+ DataHandle(GslDataHandle *handle);
+
+ public:
+ static DataHandle null() { return DataHandle(); }
+
+ DataHandle(): handle_(0) {}
+
+ DataHandle(const DataHandle &other);
+
+ DataHandle &operator =(const DataHandle &other);
+
+ bool operator ==(const DataHandle &other) const;
+
+ bool isNull() const;
+
+ virtual ~DataHandle();
+
+ /**
+ * returns error code with errno meaning
+ */
+ virtual gint open();
+
+ virtual void close();
+
+ bool isOpen() const;
+
+ /**
+ * read from this datahandle and fill buffer pointed to by
+ * values with sample data from the range
+ * [valueOffset..valueOffset+valueCount-1]
+ *
+ * returns number of sample values actually read, -1 on error
+ * (errno _may_ be useful then)
+ */
+ virtual GslLong read(GslLong valueOffset, GslLong valueCount, gfloat *values);
+
+ /**
+ * Create a new data handle by chopping off headCutValueCount
+ * values at the start, and tailCutValueCount values at the
+ * end of this data handle.
+ */
+ DataHandle createCropped(GslLong headCutValueCount,
+ GslLong tailCutValueCount);
+
+ /**
+ * Create a new data handle by removing the values
+ * [cutOffset..cutOffset+cutValueCount-1].
+ */
+ DataHandle createCut(GslLong cutOffset,
+ GslLong cutValueCount);
+
+ /**
+ * Create a new data handle which contains the same values as
+ * this one but in reversed order.
+ */
+ DataHandle createReversed();
+
+ // this will maybe be made private in the future, having a
+ // better interface instead
+ GslDataCache *createGslDataCache();
+
+ GslLong valueCount() const;
+
+ guint bitDepth() const;
+
+ guint channelCount() const;
+ };
+
+ class WaveChunkDescription
+ {
+ friend class WaveDescription;
+
+ const GslWaveDsc *parent_;
+ guint parentIndex_;
+
+ WaveChunkDescription(const GslWaveDsc *parent, guint index);
+
+ public:
+ float oscillatorFrequency();
+ float mixerFrequency();
+
+ GslWaveLoopType loopType();
+ GslLong loopStart(); /* sample offset */
+ GslLong loopEnd(); /* sample offset */
+ guint loopCount();
+
+ WaveDataHandle createDataHandle();
+ };
+
+ class WaveDescription
+ {
+ friend class WaveFileInfo; // for construction of WaveDescriptions
+
+ mutable GslWaveFileInfo *parentInfo_; // mutable for ensurePointer()
+ std::string name_;
+ guint parentIndex_;
+ mutable GslWaveDsc *desc_;
+ mutable GslErrorType error_;
+
+ void ensurePointer() const; // lazy construction
+
+ void copyFrom(const WaveDescription &other);
+
+ WaveDescription(GslWaveFileInfo *parent, guint index, const std::string &name);
+
+ public:
+ ~WaveDescription();
+
+ WaveDescription(const WaveDescription &other);
+
+ WaveDescription &operator =(const WaveDescription &other);
+
+ const std::string &name() const;
+
+ GslErrorType error() const;
+
+ guint chunkCount() const;
+
+ WaveChunkDescription chunkDescription(guint index) const;
+
+ guint channelCount() const;
+ };
+
+ class WaveFileInfo
+ {
+ GslWaveFileInfo *info_;
+ GslErrorType error_;
+ std::string filename_;
+
+ void copyFrom(const WaveFileInfo &other);
+
+ public:
+ WaveFileInfo(const std::string &filename);
+
+ ~WaveFileInfo();
+
+ WaveFileInfo(const WaveFileInfo &other);
+
+ WaveFileInfo &operator =(const WaveFileInfo &other);
+
+ guint waveCount() const;
+
+ std::string waveName(guint index) const;
+
+ WaveDescription waveDescription(guint index);
+
+ GslErrorType error() const;
+ };
+
+ class WaveDataHandle: public DataHandle
+ {
+ friend class WaveChunkDescription;
+
+ GslErrorType error_;
+
+ float oscillatorFrequency_;
+ float mixerFrequency_;
+
+ WaveDataHandle();
+ WaveDataHandle(const GslWaveDsc *waveDesc, guint chunkIndex = 0);
+
+ public:
+ WaveDataHandle(const std::string& filename,
+ guint waveIndex = 0,
+ guint chunkIndex = 0);
+
+ static WaveDataHandle null() { return WaveDataHandle(); }
+
+ GslErrorType error() const;
+
+ float oscillatorFrequency() const;
+
+ float mixerFrequency() const;
+ };
+}
+
+#endif // GSLPP_DATAHANDLE_H
diff --git a/flow/gslschedule.cc b/flow/gslschedule.cc
new file mode 100644
index 0000000..370bac1
--- /dev/null
+++ b/flow/gslschedule.cc
@@ -0,0 +1,1195 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "config.h"
+
+#include "virtualports.h"
+#include "startupmanager.h"
+#include "gslschedule.h"
+#include "debug.h"
+#include "asyncschedule.h"
+#include "audiosubsys.h"
+#include <gsl/gslcommon.h>
+#include <gsl/gslengine.h>
+#include <algorithm>
+#include <stdio.h>
+#include <iostream>
+#include <stack>
+
+/* HACK */
+class GslMainLoop {
+protected:
+ std::list<GslClass *> freeClassList;
+
+public:
+ GslEngineLoop loop;
+
+ static bool waitOnTransNeedData;
+ static bool gslDataCalculated;
+
+ /* static check function */
+ static gboolean gslCheck(gpointer /* data */, guint /* n_values */,
+ glong* /* timeout_p */,
+ guint /* n_fds */, const GPollFD* /* fds */,
+ gboolean /* revents_filled */)
+ {
+ return waitOnTransNeedData;
+ }
+ /* mainloop integration: initialize (called to get initial loop setup) */
+ void initialize()
+ {
+ gsl_transact(gsl_job_add_poll (gslCheck, 0, 0, 0, 0), 0);
+ gsl_engine_prepare(&loop);
+
+ for(unsigned int i = 0; i != loop.n_fds; i++)
+ {
+ printf("TODO: engine fd %d\n",i);
+ }
+ }
+ /* mainloop integration: process (TODO - should be called by IOManager) */
+ void process()
+ {
+ printf("TODO: mainloop wrapper for fd watches\n");
+ if(gsl_engine_check(&loop))
+ gsl_engine_dispatch();
+ }
+ /* wait for a transaction */
+ void waitOnTrans()
+ {
+ arts_return_if_fail(waitOnTransNeedData == false);
+ gsl_engine_wait_on_trans();
+ }
+ /* make the engine calculate something */
+ void run()
+ {
+ waitOnTransNeedData = true;
+ gslDataCalculated = false;
+
+ while(!gslDataCalculated && gsl_engine_check(&loop))
+ gsl_engine_dispatch();
+
+ gslDataCalculated = false;
+ waitOnTransNeedData = false;
+
+ if(!freeClassList.empty())
+ {
+ /*
+ * make sure that all transactions that are still pending
+ * get finished (especially important in threaded case,
+ * since an entry in the free list doesn't necessarily
+ * mean that the module has entierly been freed)
+ */
+ waitOnTrans();
+
+ std::list<GslClass *>::iterator fi;
+ for(fi = freeClassList.begin(); fi != freeClassList.end(); fi++)
+ free(*fi);
+
+ freeClassList.clear();
+ }
+ }
+ void freeGslClass(GslClass *klass)
+ {
+ freeClassList.push_back(klass);
+ }
+} gslMainLoop;
+
+bool GslMainLoop::waitOnTransNeedData = false;
+bool GslMainLoop::gslDataCalculated = false;
+namespace Arts { extern void *gslGlobalMutexTable; }
+
+
+using namespace std;
+using namespace Arts;
+
+// ----------- Port -----------
+
+Port::Port(const string& name, void *ptr, long flags, StdScheduleNode* parent)
+ : _name(name), _ptr(ptr), _flags((AttributeType)flags),
+ parent(parent), _dynamicPort(false)
+{
+ _vport = new VPort(this);
+}
+
+Port::~Port()
+{
+ if(_vport)
+ delete _vport;
+}
+
+AttributeType Port::flags()
+{
+ return _flags;
+}
+
+string Port::name()
+{
+ return _name;
+}
+
+ASyncPort *Port::asyncPort()
+{
+ return 0;
+}
+
+AudioPort *Port::audioPort()
+{
+ return 0;
+}
+
+void Port::addAutoDisconnect(Port *source)
+{
+ autoDisconnect.push_back(source);
+ source->autoDisconnect.push_back(this);
+}
+
+void Port::removeAutoDisconnect(Port *source)
+{
+ std::list<Port *>::iterator adi;
+
+ // remove our autodisconnection entry for source port
+ adi = find(autoDisconnect.begin(),autoDisconnect.end(),source);
+ assert(adi != autoDisconnect.end());
+ autoDisconnect.erase(adi);
+
+ // remove the source port autodisconnection entry to us
+ adi=find(source->autoDisconnect.begin(),source->autoDisconnect.end(),this);
+ assert(adi != source->autoDisconnect.end());
+ source->autoDisconnect.erase(adi);
+}
+
+void Port::disconnectAll()
+{
+ if(_vport)
+ delete _vport;
+ _vport = 0;
+ assert(autoDisconnect.empty());
+ while(!autoDisconnect.empty())
+ {
+ Port *other = *autoDisconnect.begin();
+
+ // syntax is disconnect(source)
+ if(_flags & streamIn)
+ // if we're incoming, other port is source
+ vport()->disconnect(other->vport());
+ else
+ // if we're outgoing, we're the source
+ other->vport()->disconnect(this->vport());
+ }
+}
+
+void Port::setPtr(void *ptr)
+{
+ _ptr = ptr;
+}
+
+// ------- AudioPort ---------
+
+AudioPort::AudioPort(const string& name,
+ void *ptr, long flags,StdScheduleNode *parent)
+ : Port(name,ptr,flags,parent)
+{
+ destcount = 0;
+ sourcemodule = 0;
+ source = 0;
+ gslIsConstant = false;
+}
+
+AudioPort::~AudioPort()
+{
+ //
+}
+
+AudioPort *AudioPort::audioPort()
+{
+ return this;
+}
+
+void AudioPort::setFloatValue(float f)
+{
+ gslIsConstant = true;
+ gslConstantValue = f;
+
+ parent->_connectionCountChanged = true;
+}
+
+void AudioPort::connect(Port *psource)
+{
+ if (source) return; // Error, should not happen (See BR70028)
+ source = psource->audioPort();
+ assert(source);
+ addAutoDisconnect(psource);
+
+ source->parent->_connectionCountChanged = parent->_connectionCountChanged = true;
+ source->destcount++;
+ sourcemodule = source->parent;
+
+ // GSL connect
+ GslTrans *trans = gsl_trans_open();
+ gsl_trans_add(trans, gsl_job_connect(source->parent->gslModule,
+ source->gslEngineChannel,
+ parent->gslModule,
+ gslEngineChannel));
+ gsl_trans_commit(trans);
+}
+
+void AudioPort::disconnect(Port *psource)
+{
+ if (!source || source != psource->audioPort()) return; // Error, should not happen (See BR70028)
+ assert(source);
+ assert(source == psource->audioPort());
+ removeAutoDisconnect(psource);
+
+ assert(sourcemodule == source->parent);
+ sourcemodule = 0;
+
+ source->parent->_connectionCountChanged = parent->_connectionCountChanged = true;
+ source->destcount--;
+ source = 0;
+
+ // GSL disconnect
+ GslTrans *trans = gsl_trans_open();
+ gsl_trans_add(trans, gsl_job_disconnect(parent->gslModule,
+ gslEngineChannel));
+ gsl_trans_commit(trans);
+}
+
+// --------- MultiPort ----------
+
+MultiPort::MultiPort(const string& name,
+ void *ptr, long flags,StdScheduleNode *parent)
+ : Port(name,ptr,flags,parent)
+{
+ conns = 0;
+ nextID = 0;
+ initConns();
+}
+
+MultiPort::~MultiPort()
+{
+ if(conns)
+ {
+ delete[] conns;
+ conns = 0;
+ }
+}
+
+void MultiPort::initConns()
+{
+ if(conns != 0) delete[] conns;
+ conns = new float_ptr[parts.size() + 1];
+ conns[parts.size()] = (float *)0;
+
+ *(float ***)_ptr = conns;
+
+ long n = 0;
+ std::list<Part>::iterator i;
+ for(i = parts.begin();i != parts.end(); i++)
+ {
+ AudioPort *p = i->dest;
+ p->setPtr((void *)&conns[n++]);
+ }
+}
+
+void MultiPort::connect(Port *port)
+{
+ AudioPort *dport;
+ char sid[20];
+ sprintf(sid,"%ld",nextID++);
+
+ addAutoDisconnect(port);
+
+ dport = new AudioPort("_"+_name+string(sid),0,streamIn,parent);
+
+ Part part;
+ part.src = (AudioPort *)port;
+ part.dest = dport;
+
+ parts.push_back(part);
+ initConns();
+
+ parent->addDynamicPort(dport);
+ dport->vport()->connect(port->vport());
+}
+
+void MultiPort::disconnect(Port *sport)
+{
+ AudioPort *port = (AudioPort *)sport;
+ removeAutoDisconnect(sport);
+
+ std::list<Part>::iterator i;
+ for(i = parts.begin(); i != parts.end(); i++)
+ {
+ if(i->src == port)
+ {
+ AudioPort *dport = i->dest;
+ parts.erase(i);
+ initConns();
+
+ dport->vport()->disconnect(port->vport());
+ parent->removeDynamicPort(dport);
+
+ delete dport;
+ return;
+ }
+ }
+}
+
+// -------- StdScheduleNode ---------
+
+void StdScheduleNode::freeConn()
+{
+ if(inConn)
+ {
+ delete[] inConn;
+ inConn = 0;
+ }
+ if(outConn)
+ {
+ delete[] outConn;
+ outConn = 0;
+ }
+ inConnCount = outConnCount = 0;
+
+ if(gslModule)
+ {
+ gsl_transact(gsl_job_discard(gslModule),0);
+
+ gslModule = 0;
+ gslRunning = false;
+ }
+}
+
+void StdScheduleNode::gslProcess(GslModule *module, guint n_values)
+{
+ StdScheduleNode *node = (StdScheduleNode *)module->user_data;
+ if(!node->running) /* FIXME: need reasonable suspend in the engine */
+ return;
+
+ arts_return_if_fail(node->module != 0);
+
+ GslMainLoop::gslDataCalculated = true;
+
+ unsigned long j;
+ for(j=0;j<node->inConnCount;j++)
+ {
+ if(node->inConn[j]->gslIsConstant)
+ *((float **)node->inConn[j]->_ptr) =
+ gsl_engine_const_values(node->inConn[j]->gslConstantValue);
+ else
+ *((float **)node->inConn[j]->_ptr) = const_cast<float *>(module->istreams[j].values);
+ }
+
+ for(j=0;j<node->outConnCount;j++)
+ *((float **)node->outConn[j]->_ptr) = module->ostreams[j].values;
+
+ node->module->calculateBlock(n_values);
+}
+
+static void gslModuleFree(gpointer /* data */, const GslClass *klass)
+{
+ gslMainLoop.freeGslClass(const_cast<GslClass *>(klass));
+}
+
+void StdScheduleNode::rebuildConn()
+{
+ std::list<Port *>::iterator i;
+
+ freeConn();
+
+ inConnCount = outConnCount = 0;
+ inConn = new AudioPort_ptr[ports.size()];
+ outConn = new AudioPort_ptr[ports.size()];
+
+ for(i=ports.begin();i != ports.end();i++)
+ {
+ AudioPort *p = (*i)->audioPort();
+ if(p)
+ {
+ if(p->flags() & streamIn)
+ {
+ p->gslEngineChannel = inConnCount;
+ inConn[inConnCount++] = p;
+ }
+ if(p->flags() & streamOut)
+ {
+ p->gslEngineChannel = outConnCount;
+ outConn[outConnCount++] = p;
+ }
+ }
+ }
+
+ /* create GSL node */
+ GslClass *gslClass = (GslClass *)calloc(sizeof(GslClass),1);
+ gslClass->n_istreams = inConnCount;
+ gslClass->n_ostreams = outConnCount;
+ gslClass->process = gslProcess;
+ gslClass->free = gslModuleFree;
+
+ gslModule = gsl_module_new (gslClass, (StdScheduleNode *)this);
+
+ GslTrans *trans = gsl_trans_open();
+ gsl_trans_add(trans,gsl_job_integrate(gslModule));
+ gsl_trans_add(trans,gsl_job_set_consumer(gslModule, running));
+ gslRunning = running;
+
+ /* since destroying the old module and creating a new one will destroy
+ * all the connections, we need to restore them here
+ */
+ unsigned int c;
+ for(c = 0; c < inConnCount; c++)
+ {
+ if(inConn[c]->source)
+ {
+ gsl_trans_add(trans,
+ gsl_job_connect(inConn[c]->source->parent->gslModule,
+ inConn[c]->source->gslEngineChannel,
+ inConn[c]->parent->gslModule,
+ inConn[c]->gslEngineChannel));
+ }
+ }
+ for(c = 0; c < outConnCount; c++)
+ {
+ std::list<Port *>::iterator ci;
+
+ for(ci = outConn[c]->autoDisconnect.begin();
+ ci != outConn[c]->autoDisconnect.end(); ci++)
+ {
+ AudioPort *dest = (*ci)->audioPort();
+ if( dest )
+ {
+ gsl_trans_add(trans,
+ gsl_job_connect(outConn[c]->parent->gslModule,
+ outConn[c]->gslEngineChannel,
+ dest->parent->gslModule,
+ dest->gslEngineChannel));
+ }
+ else
+ {
+ arts_debug( "no audio port: %s for %s", ( *ci )->name().c_str(), _object->_interfaceName().c_str() );
+ }
+ }
+ }
+ gsl_trans_commit(trans);
+}
+
+Object_skel *StdScheduleNode::object()
+{
+ return _object;
+}
+
+void *StdScheduleNode::cast(const string &target)
+{
+ if(target == "StdScheduleNode") return (StdScheduleNode *)this;
+ return 0;
+}
+
+
+void StdScheduleNode::accessModule()
+{
+ if(module) return;
+
+ module = (SynthModule_base *)_object->_cast(Arts::SynthModule_base::_IID);
+ if(!module)
+ arts_warning("Error using interface %s in the flowsystem: only objects"
+ " implementing Arts::SynthModule should carry streams.",
+ _object->_interfaceName().c_str());
+}
+
+StdScheduleNode::StdScheduleNode(Object_skel *object, StdFlowSystem *flowSystem) : ScheduleNode(object)
+{
+ _object = object;
+ this->flowSystem = flowSystem;
+ running = false;
+ suspended = false;
+ module = 0;
+ gslModule = 0;
+ gslRunning = false;
+ queryInitStreamFunc = 0;
+ inConn = outConn = 0;
+ inConnCount = outConnCount = 0;
+}
+
+StdScheduleNode::~StdScheduleNode()
+{
+ /* stop module if still running */
+ if(running) stop();
+ /* disconnect all ports */
+ stack<Port *> disconnect_stack;
+
+ /*
+ * we must be a bit careful here, as dynamic ports (which are created
+ * for connections by MultiPorts) will suddenly start disappearing, so
+ * we better make a copy of those ports that will stay, and disconnect
+ * them then
+ */
+ std::list<Port *>::iterator i;
+ for(i=ports.begin();i != ports.end();i++)
+ {
+ if(!(*i)->dynamicPort()) disconnect_stack.push(*i);
+ }
+
+ while(!disconnect_stack.empty())
+ {
+ disconnect_stack.top()->disconnectAll();
+ disconnect_stack.pop();
+ }
+ /* free them */
+ for(i=ports.begin();i != ports.end();i++)
+ delete (*i);
+ ports.clear();
+
+ freeConn();
+}
+
+void StdScheduleNode::initStream(const string& name, void *ptr, long flags)
+{
+ if(flags == -1)
+ {
+ queryInitStreamFunc = (QueryInitStreamFunc)ptr;
+ }
+ else if(flags & streamAsync)
+ {
+ ports.push_back(new ASyncPort(name,ptr,flags,this));
+ }
+ else if(flags & streamMulti)
+ {
+ ports.push_back(new MultiPort(name,ptr,flags,this));
+ }
+ else
+ {
+ ports.push_back(new AudioPort(name,ptr,flags,this));
+ }
+
+ // TODO: maybe initialize a bit later
+ rebuildConn();
+}
+
+void StdScheduleNode::addDynamicPort(Port *port)
+{
+ port->setDynamicPort();
+ ports.push_back(port);
+ rebuildConn();
+}
+
+void StdScheduleNode::removeDynamicPort(Port *port)
+{
+ std::list<Port *>::iterator i;
+ for(i=ports.begin();i!=ports.end();i++)
+ {
+ Port *p = *i;
+ if(p->name() == port->name())
+ {
+ ports.erase(i);
+ rebuildConn();
+ return;
+ }
+ }
+}
+
+void StdScheduleNode::start()
+{
+ assert(!running);
+ running = true;
+
+ //cout << "start" << endl;
+ accessModule();
+ module->streamInit();
+ module->streamStart();
+ flowSystem->startedChanged();
+}
+
+void StdScheduleNode::stop()
+{
+ assert(running);
+ running = false;
+
+ accessModule();
+ module->streamEnd();
+ flowSystem->startedChanged();
+}
+
+void StdScheduleNode::requireFlow()
+{
+ // cout << "rf" << module->_interfaceName() << endl;
+ flowSystem->updateStarted();
+ gslMainLoop.run();
+}
+
+AutoSuspendState StdScheduleNode::suspendable()
+{
+ if(running) {
+ accessModule();
+ return module->autoSuspend();
+ }
+ // if its not running, who cares?
+ return asSuspend;
+}
+
+void StdScheduleNode::suspend()
+{
+ if(running) {
+ accessModule();
+ suspended = true;
+ if((module->autoSuspend() & asSuspendMask) == asSuspendStop) stop();
+ }
+}
+
+void StdScheduleNode::restart()
+{
+ if(suspended) {
+ accessModule();
+ suspended = false;
+ if(!running && (module->autoSuspend() & asSuspendMask) == asSuspendStop) start();
+ }
+}
+
+Port *StdScheduleNode::findPort(const string& name)
+{
+ std::list<Port *>::iterator i;
+ for(i=ports.begin();i!=ports.end();i++)
+ {
+ Port *p = *i;
+ if(p->name() == name) return p;
+ }
+ if(queryInitStreamFunc)
+ {
+ if(queryInitStreamFunc(_object,name))
+ {
+ for(i=ports.begin();i!=ports.end();i++)
+ {
+ Port *p = *i;
+ if(p->name() == name) return p;
+ }
+ }
+ }
+ return 0;
+}
+
+void StdScheduleNode::virtualize(const std::string& port,
+ ScheduleNode *implNode,
+ const std::string& implPort)
+{
+ StdScheduleNode *impl=(StdScheduleNode *)implNode->cast("StdScheduleNode");
+ if(impl)
+ {
+ Port *p1 = findPort(port);
+ Port *p2 = impl->findPort(implPort);
+
+ assert(p1);
+ assert(p2);
+ p1->vport()->virtualize(p2->vport());
+ }
+}
+
+void StdScheduleNode::devirtualize(const std::string& port,
+ ScheduleNode *implNode,
+ const std::string& implPort)
+{
+ StdScheduleNode *impl=(StdScheduleNode *)implNode->cast("StdScheduleNode");
+ if(impl)
+ {
+ Port *p1 = findPort(port);
+ Port *p2 = impl->findPort(implPort);
+
+ p1->vport()->devirtualize(p2->vport());
+ }
+}
+
+void StdScheduleNode::connect(const string& port, ScheduleNode *dest,
+ const string& destport)
+{
+ RemoteScheduleNode *rsn = dest->remoteScheduleNode();
+ if(rsn)
+ {
+ // RemoteScheduleNodes know better how to connect remotely
+ rsn->connect(destport,this,port);
+ return;
+ }
+
+ flowSystem->restart();
+
+ Port *p1 = findPort(port);
+ Port *p2 = ((StdScheduleNode *)dest)->findPort(destport);
+
+ if(p1 && p2)
+ {
+ if((p1->flags() & streamIn) && (p2->flags() & streamOut))
+ {
+ p1->vport()->connect(p2->vport());
+ }
+ else if((p2->flags() & streamIn) && (p1->flags() & streamOut))
+ {
+ p2->vport()->connect(p1->vport());
+ }
+ }
+}
+
+void StdScheduleNode::disconnect(const string& port, ScheduleNode *dest,
+ const string& destport)
+{
+ RemoteScheduleNode *rsn = dest->remoteScheduleNode();
+ if(rsn)
+ {
+ // RemoteScheduleNodes know better how to disconnect remotely
+ rsn->disconnect(destport,this,port);
+ return;
+ }
+
+ flowSystem->restart();
+
+ Port *p1 = findPort(port);
+ Port *p2 = ((StdScheduleNode *)dest)->findPort(destport);
+
+ if(p1 && p2)
+ {
+ if((p1->flags() & streamIn) && (p2->flags() & streamOut))
+ {
+ p1->vport()->disconnect(p2->vport());
+ }
+ else if((p2->flags() & streamIn) && (p1->flags() & streamOut))
+ {
+ p2->vport()->disconnect(p1->vport());
+ }
+ }
+}
+
+AttributeType StdScheduleNode::queryFlags(const std::string& port)
+{
+ arts_debug("findPort(%s)", port.c_str());
+ arts_debug("have %ld ports", ports.size());
+ Port *p1 = findPort(port);
+ arts_debug("done");
+
+ if(p1)
+ {
+ arts_debug("result %d",(long)p1->flags());
+ return p1->flags();
+ }
+ arts_debug("failed");
+ return (AttributeType)0;
+}
+
+void StdScheduleNode::setFloatValue(const string& port, float value)
+{
+ AudioPort *p = findPort(port)->audioPort();
+
+ if(p) {
+ p->vport()->setFloatValue(value);
+ } else {
+ assert(false);
+ }
+}
+
+unsigned long StdScheduleNode::inputConnectionCount(const string& port)
+{
+ unsigned long result = 0;
+
+ unsigned int c;
+ for(c = 0; c < inConnCount; c++)
+ {
+ if(inConn[c]->name() == port)
+ {
+ if(inConn[c]->source || inConn[c]->gslIsConstant)
+ result++;
+ }
+ }
+
+ return result;
+}
+
+unsigned long StdScheduleNode::outputConnectionCount(const string& port)
+{
+ unsigned long result = 0;
+
+ unsigned int c;
+ for(c = 0; c < outConnCount; c++)
+ {
+ if(outConn[c]->name() == port)
+ result += outConn[c]->destcount;
+ }
+
+ return result;
+}
+
+StdFlowSystem::StdFlowSystem()
+{
+ _suspended = false;
+ needUpdateStarted = false;
+
+ /* TODO: correct parameters */
+ static bool gsl_is_initialized = false;
+ if(!gsl_is_initialized)
+ {
+ GslConfigValue values[3] = {
+ { "wave_chunk_padding", 8 },
+ { "dcache_block_size", 4000, },
+ { 0, 0 }
+ };
+ gsl_is_initialized = true;
+
+ if (!g_thread_supported ())
+ g_thread_init(0);
+ gsl_init(values, (GslMutexTable *)gslGlobalMutexTable);
+
+ /*
+ * FIXME: both of these are really supposed to be tunable
+ * - the 512 because of low-latency apps, where calculating smaller
+ * block sizes might be necessary
+ * - the 44100 because of the obvious reason, that not every artsd
+ * is running at that rate
+ */
+ gsl_engine_init(false, 512, 44100, /* subsamplemask */ 63);
+ if(gslGlobalMutexTable)
+ arts_debug("gsl: using Unix98 pthreads directly for mutexes and conditions");
+ /*gsl_engine_debug_enable(GslEngineDebugLevel(GSL_ENGINE_DEBUG_JOBS | GSL_ENGINE_DEBUG_SCHED));*/
+ }
+ gslMainLoop.initialize();
+}
+
+ScheduleNode *StdFlowSystem::addObject(Object_skel *object)
+{
+ // do not add new modules when being in suspended state
+ restart();
+
+ StdScheduleNode *node = new StdScheduleNode(object,this);
+ nodes.push_back(node);
+ return node;
+}
+
+void StdFlowSystem::removeObject(ScheduleNode *node)
+{
+ StdScheduleNode *xnode = (StdScheduleNode *)node->cast("StdScheduleNode");
+ assert(xnode);
+ nodes.remove(xnode);
+ delete xnode;
+}
+
+bool StdFlowSystem::suspended()
+{
+ return _suspended;
+}
+
+bool StdFlowSystem::suspendable()
+{
+ /*
+ * What it does:
+ * -------------
+ *
+ * The suspension algorithm will first divide the graph of modules into
+ * subgraphs of interconnected modules. A subgraph is suspendable if
+ * all of its modules are suspendable and the subgraph does not contain
+ * producer(s) and consumer(s) at the same time.
+ *
+ * Finally, our module graph is suspendable if all its subgraphs are.
+ *
+ * How it is implemented:
+ * ----------------------
+ *
+ * For efficiency reasons, both steps are merged together. First all
+ * modules will be marked as unseen. Then a module is picked and
+ * all modules that it connects to are recursively added to the
+ * subgraph.
+ */
+
+ /*
+ * initialization: no nodes are seen
+ */
+ std::list<StdScheduleNode *>::iterator i;
+ for (i = nodes.begin(); i != nodes.end(); i++)
+ {
+ StdScheduleNode *node = *i;
+ node->suspendTag = false;
+ }
+
+ stack<StdScheduleNode*> todo;
+ for(i = nodes.begin(); i != nodes.end(); i++)
+ {
+ bool haveConsumer = false;
+ bool haveProducer = false;
+
+ /*
+ * examine the subgraph consisting of all nodes connected to (*i)
+ * (only will do anything if suspendTag is not already set)
+ */
+
+ todo.push(*i);
+ do
+ {
+ StdScheduleNode *node = todo.top();
+ todo.pop();
+
+ if(!node->suspendTag)
+ {
+ node->suspendTag = true; // never examine this node again
+
+ switch (node->suspendable())
+ {
+ case asNoSuspend|asProducer:
+ case asNoSuspend|asConsumer:
+ case asNoSuspend:
+ return false;
+ break;
+ case asSuspend:
+ case asSuspendStop:
+ /* nothing */
+ break;
+ case asSuspend|asProducer:
+ case asSuspendStop|asProducer:
+ if(haveConsumer)
+ return false;
+ else
+ haveProducer = true;
+ break;
+ case asSuspend|asConsumer:
+ case asSuspendStop|asConsumer:
+ if(haveProducer)
+ return false;
+ else
+ haveConsumer = true;
+ break;
+ default:
+ arts_fatal("bad suspend value %d", node->suspendable());
+ }
+
+ unsigned int c;
+ for(c = 0; c < node->inConnCount; c++)
+ {
+ if(node->inConn[c]->source)
+ todo.push(node->inConn[c]->source->parent);
+ }
+
+ for(c = 0; c < node->outConnCount; c++)
+ {
+ std::list<Port *>::iterator ci;
+
+ for(ci = node->outConn[c]->autoDisconnect.begin();
+ ci != node->outConn[c]->autoDisconnect.end(); ci++)
+ {
+ AudioPort *dest = (*ci)->audioPort();
+ if(dest)
+ todo.push(dest->parent);
+ }
+ }
+ }
+ } while(!todo.empty());
+ }
+ return true;
+}
+
+void StdFlowSystem::suspend()
+{
+ if(!_suspended)
+ {
+ std::list<StdScheduleNode *>::iterator i;
+ for(i = nodes.begin();i != nodes.end();i++)
+ {
+ StdScheduleNode *node = *i;
+ node->suspend();
+ }
+ _suspended = true;
+ }
+}
+
+void StdFlowSystem::restart()
+{
+ if(_suspended)
+ {
+ std::list<StdScheduleNode *>::iterator i;
+ for(i = nodes.begin();i != nodes.end();i++)
+ {
+ StdScheduleNode *node = *i;
+ node->restart();
+ }
+ _suspended = false;
+ }
+}
+
+/* remote accessibility */
+
+void StdFlowSystem::startObject(Object node)
+{
+ StdScheduleNode *sn =
+ (StdScheduleNode *)node._node()->cast("StdScheduleNode");
+ sn->start();
+}
+
+void StdFlowSystem::stopObject(Object node)
+{
+ StdScheduleNode *sn =
+ (StdScheduleNode *)node._node()->cast("StdScheduleNode");
+ sn->stop();
+}
+
+void StdFlowSystem::connectObject(Object sourceObject,const string& sourcePort,
+ Object destObject, const std::string& destPort)
+{
+ arts_debug("connect port %s to %s", sourcePort.c_str(), destPort.c_str());
+ StdScheduleNode *sn =
+ (StdScheduleNode *)sourceObject._node()->cast("StdScheduleNode");
+ assert(sn);
+
+ Port *port = sn->findPort(sourcePort);
+ assert(port);
+
+ StdScheduleNode *destsn =
+ (StdScheduleNode *)destObject._node()->cast("StdScheduleNode");
+ if(destsn)
+ {
+ sn->connect(sourcePort,destsn,destPort);
+ return;
+ }
+
+ ASyncPort *ap = port->asyncPort();
+
+ if(ap)
+ {
+ FlowSystemSender sender;
+ FlowSystemReceiver receiver;
+ FlowSystem remoteFs;
+
+ string dest = destObject.toString() + ":" + destPort;
+ ASyncNetSend *netsend = new ASyncNetSend(ap, dest);
+
+ sender = FlowSystemSender::_from_base(netsend); // don't release netsend
+ remoteFs = destObject._flowSystem();
+ receiver = remoteFs.createReceiver(destObject, destPort, sender);
+ netsend->setReceiver(receiver);
+ arts_debug("connected an asyncnetsend");
+ }
+}
+
+void StdFlowSystem::disconnectObject(Object sourceObject,
+ const string& sourcePort, Object destObject, const std::string& destPort)
+{
+ arts_debug("disconnect port %s and %s",sourcePort.c_str(),destPort.c_str());
+ StdScheduleNode *sn =
+ (StdScheduleNode *)sourceObject._node()->cast("StdScheduleNode");
+ assert(sn);
+
+ Port *port = sn->findPort(sourcePort);
+ assert(port);
+
+ StdScheduleNode *destsn =
+ (StdScheduleNode *)destObject._node()->cast("StdScheduleNode");
+ if(destsn)
+ {
+ sn->disconnect(sourcePort,destsn,destPort);
+ return;
+ }
+
+ ASyncPort *ap = port->asyncPort();
+ if(ap)
+ {
+ string dest = destObject.toString() + ":" + destPort;
+ ap->disconnectRemote(dest);
+ arts_debug("disconnected an asyncnetsend");
+ }
+}
+
+AttributeType StdFlowSystem::queryFlags(Object node, const std::string& port)
+{
+ StdScheduleNode *sn =
+ (StdScheduleNode *)node._node()->cast("StdScheduleNode");
+ assert(sn);
+ return sn->queryFlags(port);
+}
+
+void StdFlowSystem::setFloatValue(Object node, const std::string& port,
+ float value)
+{
+ StdScheduleNode *sn =
+ (StdScheduleNode *)node._node()->cast("StdScheduleNode");
+ assert(sn);
+ sn->setFloatValue(port,value);
+}
+
+FlowSystemReceiver StdFlowSystem::createReceiver(Object object,
+ const string &port, FlowSystemSender sender)
+{
+ StdScheduleNode *sn =
+ (StdScheduleNode *)object._node()->cast("StdScheduleNode");
+
+ Port *p = sn->findPort(port);
+ assert(p);
+
+ ASyncPort *ap = p->asyncPort();
+
+ if(ap)
+ {
+ arts_debug("creating packet receiver");
+ return FlowSystemReceiver::_from_base(new ASyncNetReceive(ap, sender));
+ }
+ return FlowSystemReceiver::null();
+}
+
+void StdFlowSystem::updateStarted()
+{
+ if(!needUpdateStarted)
+ return;
+
+ needUpdateStarted = false;
+
+ std::list<StdScheduleNode*>::iterator ni;
+ GslTrans *trans = 0;
+
+ for(ni = nodes.begin(); ni != nodes.end(); ni++)
+ {
+ StdScheduleNode *node = *ni;
+
+ if(node->running != node->gslRunning)
+ {
+ if(!trans)
+ trans = gsl_trans_open();
+ gsl_trans_add(trans, gsl_job_set_consumer(node->gslModule, node->running));
+ node->gslRunning = node->running;
+ }
+ }
+ if(trans)
+ gsl_trans_commit(trans);
+}
+
+void StdFlowSystem::startedChanged()
+{
+ needUpdateStarted = true;
+}
+
+// hacked initialization of Dispatcher::the()->flowSystem ;)
+
+namespace Arts {
+
+static class SetFlowSystem : public StartupClass {
+ FlowSystem_impl *fs;
+public:
+ void startup()
+ {
+ fs = new StdFlowSystem;
+ Dispatcher::the()->setFlowSystem(fs);
+ }
+ void shutdown()
+ {
+ fs->_release();
+ }
+} sfs;
+
+}
+
diff --git a/flow/gslschedule.h b/flow/gslschedule.h
new file mode 100644
index 0000000..4564dfc
--- /dev/null
+++ b/flow/gslschedule.h
@@ -0,0 +1,262 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_GSLSCHEDULE_H
+#define ARTS_GSLSCHEDULE_H
+
+#include "artsflow.h"
+#include "flowsystem.h"
+#include <gsl/gsldefs.h>
+#include <string>
+#include <list>
+
+/*
+ * BC - Status (2002-03-08): Port, AudioPort, MultiPort, StdFlowSystem,
+ * StdScheduleNode
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of libartsflow's
+ * StdFlowSystem, and subject to change with the needs of it.
+ *
+ * If you want to access flowsystem functionality, do so over the core.idl
+ * specified flowsystem interface, (object)->_node() or stuff in mcop/connect.h.
+ */
+
+namespace Arts {
+
+class StdScheduleNode;
+
+class Port {
+ friend class VPort; // TODO: debugging, remove me when it works?
+ friend class VPortConnection; // TODO: debugging, remove me when it works?
+protected:
+ std::string _name;
+public:
+ void *_ptr;
+public: // FIXME: GSL
+ AttributeType _flags;
+ StdScheduleNode *parent;
+
+ // each port has a virtual port, which allows port redirection
+ class VPort *_vport;
+
+ // dynamic ports are created to implement multiports
+ bool _dynamicPort;
+
+ // functionality to remove all connections automatically as soon as
+ // the module gets destroyed
+ std::list<Port *> autoDisconnect;
+
+ /**
+ * call these from your (dis)connect implementation as soon as a the
+ * port gets (dis)connected to some other port (only one call per
+ * connection: destinationport->addAutoDisconnect(sourceport), not
+ * for the other direction)
+ */
+ void addAutoDisconnect(Port *source);
+ void removeAutoDisconnect(Port *source);
+
+public:
+ Port(const std::string& name, void *ptr, long flags,
+ StdScheduleNode* parent);
+ virtual ~Port();
+
+ inline VPort* vport() { assert(_vport); return _vport; }
+ AttributeType flags();
+ std::string name();
+ void setPtr(void *ptr);
+
+ inline bool dynamicPort() { return _dynamicPort; }
+ inline void setDynamicPort() { _dynamicPort = true; }
+
+ virtual class AudioPort *audioPort();
+ virtual class ASyncPort *asyncPort();
+
+ virtual void disconnectAll();
+ virtual void connect(Port *) = 0;
+ virtual void disconnect(Port *) = 0;
+};
+
+class AudioPort : public Port {
+public: // FIXME: GSL
+ AudioPort *source;
+
+public:
+ StdScheduleNode *sourcemodule;
+ unsigned long destcount;
+ unsigned long gslEngineChannel;
+
+ /* GSL */
+ bool gslIsConstant;
+ float gslConstantValue;
+
+ AudioPort(const std::string& name,
+ void *ptr, long flags,StdScheduleNode *parent);
+ ~AudioPort();
+
+ virtual class AudioPort *audioPort();
+
+ void setFloatValue(float f);
+ void connect(Port *psource);
+ void disconnect(Port *psource);
+};
+
+class MultiPort : public Port {
+protected:
+ struct Part {
+ AudioPort *src, *dest;
+ };
+
+ std::list<Part> parts;
+ typedef float *float_ptr;
+ float **conns;
+ long nextID;
+ void initConns();
+
+public:
+ MultiPort(const std::string& name,
+ void *ptr, long flags,StdScheduleNode *parent);
+ ~MultiPort();
+
+ void connect(Port *port);
+ void disconnect(Port *port);
+};
+
+class StdFlowSystem;
+
+class StdScheduleNode :public ScheduleNode
+{
+ friend class StdFlowSystem;
+ bool running;
+ bool suspended;
+
+ Object_skel *_object;
+ SynthModule_base *module;
+ StdFlowSystem *flowSystem;
+ std::list<Port *> ports;
+ AudioPort **inConn;
+ AudioPort **outConn;
+ unsigned long inConnCount, outConnCount;
+ typedef AudioPort *AudioPort_ptr;
+ QueryInitStreamFunc queryInitStreamFunc;
+
+ void freeConn();
+ void rebuildConn();
+ void accessModule();
+
+ static void gslProcess(GslModule *module, guint n_values);
+ public: /* TODO? */
+ Port *findPort(const std::string& name);
+
+public:
+
+ GslModule *gslModule;
+ bool gslRunning;
+
+ /**
+ * this is used by StdFlowSystem::suspend() to mark nodes which
+ * have already been seen by the algorithm
+ */
+ bool suspendTag;
+
+ StdScheduleNode(Object_skel *object, StdFlowSystem *flowSystem);
+ virtual ~StdScheduleNode();
+ void initStream(const std::string& name, void *ptr, long flags);
+ void addDynamicPort(Port *port);
+ void removeDynamicPort(Port *port);
+
+ void start();
+ void stop();
+ void requireFlow();
+ void virtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort);
+ void devirtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort);
+
+ // AutoSuspend stuff
+ AutoSuspendState suspendable();
+ void suspend();
+ void restart();
+
+ void connect(const std::string& port, ScheduleNode *dest,
+ const std::string& destport);
+ void disconnect(const std::string& port, ScheduleNode *dest,
+ const std::string& destport);
+
+ AttributeType queryFlags(const std::string& port);
+ void setFloatValue(const std::string& port, float value);
+
+ Object_skel *object();
+ void *cast(const std::string &target);
+
+ // used by StdSynthModule
+ unsigned long inputConnectionCount(const std::string& port);
+ unsigned long outputConnectionCount(const std::string& port);
+
+ bool _connectionCountChanged;
+ inline bool connectionCountChanged() {
+ bool c = _connectionCountChanged;
+ _connectionCountChanged = false;
+ return c;
+ }
+};
+
+class StdFlowSystem :public FlowSystem_impl
+{
+protected:
+ std::list<StdScheduleNode *> nodes;
+ bool _suspended;
+ bool needUpdateStarted;
+public:
+ StdFlowSystem();
+
+ ScheduleNode *addObject(Object_skel *object);
+ void removeObject(ScheduleNode *node);
+
+ /* AutoSuspend */
+ bool suspendable();
+ bool suspended();
+ void suspend();
+ void restart();
+
+ /* remote accessibility */
+ void startObject(Object node);
+ void stopObject(Object node);
+ void connectObject(Object sourceObject, const std::string& sourcePort,
+ Object destObject, const std::string& destPort);
+ void disconnectObject(Object sourceObject, const std::string& sourcePort,
+ Object destObject, const std::string& destPort);
+ AttributeType queryFlags(Object node, const std::string& port);
+ void setFloatValue(Object node, const std::string& port, float value);
+
+ FlowSystemReceiver createReceiver(Object object, const std::string &port,
+ FlowSystemSender sender);
+
+ /* interface to StdScheduleNode */
+ void schedule(unsigned long samples);
+ void updateStarted();
+ void startedChanged();
+};
+
+}
+
+#endif
diff --git a/flow/mcopclass/DataHandlePlay.mcopclass b/flow/mcopclass/DataHandlePlay.mcopclass
new file mode 100644
index 0000000..cd84c48
--- /dev/null
+++ b/flow/mcopclass/DataHandlePlay.mcopclass
@@ -0,0 +1,2 @@
+Interface=Arts::DataHandlePlay,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Makefile.am b/flow/mcopclass/Makefile.am
new file mode 100644
index 0000000..faf2683
--- /dev/null
+++ b/flow/mcopclass/Makefile.am
@@ -0,0 +1,15 @@
+mcopclassdir = $(libdir)/mcop/Arts
+mcopclass_DATA = Synth_ADD.mcopclass \
+ Synth_FREQUENCY.mcopclass \
+ Synth_MUL.mcopclass \
+ Synth_MULTI_ADD.mcopclass \
+ Synth_PLAY.mcopclass \
+ Synth_RECORD.mcopclass \
+ Synth_PLAY_WAV.mcopclass \
+ Synth_WAVE_SIN.mcopclass \
+ Synth_BUS_DOWNLINK.mcopclass \
+ Synth_BUS_UPLINK.mcopclass \
+ Synth_AMAN_PLAY.mcopclass \
+ Synth_AMAN_RECORD.mcopclass \
+ DataHandlePlay.mcopclass \
+ WaveDataHandle.mcopclass
diff --git a/flow/mcopclass/Synth_ADD.mcopclass b/flow/mcopclass/Synth_ADD.mcopclass
new file mode 100644
index 0000000..0429b3f
--- /dev/null
+++ b/flow/mcopclass/Synth_ADD.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_ADD,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_AMAN_PLAY.mcopclass b/flow/mcopclass/Synth_AMAN_PLAY.mcopclass
new file mode 100644
index 0000000..02f8e99
--- /dev/null
+++ b/flow/mcopclass/Synth_AMAN_PLAY.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_AMAN_PLAY,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_AMAN_RECORD.mcopclass b/flow/mcopclass/Synth_AMAN_RECORD.mcopclass
new file mode 100644
index 0000000..c92cb76
--- /dev/null
+++ b/flow/mcopclass/Synth_AMAN_RECORD.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_AMAN_RECORD,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_BUS_DOWNLINK.mcopclass b/flow/mcopclass/Synth_BUS_DOWNLINK.mcopclass
new file mode 100644
index 0000000..bcc0c2a
--- /dev/null
+++ b/flow/mcopclass/Synth_BUS_DOWNLINK.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_BUS_DOWNLINK,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_BUS_UPLINK.mcopclass b/flow/mcopclass/Synth_BUS_UPLINK.mcopclass
new file mode 100644
index 0000000..d262b1e
--- /dev/null
+++ b/flow/mcopclass/Synth_BUS_UPLINK.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_BUS_UPLINK,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_FREQUENCY.mcopclass b/flow/mcopclass/Synth_FREQUENCY.mcopclass
new file mode 100644
index 0000000..91c5016
--- /dev/null
+++ b/flow/mcopclass/Synth_FREQUENCY.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_FREQUENCY,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_MUL.mcopclass b/flow/mcopclass/Synth_MUL.mcopclass
new file mode 100644
index 0000000..c1087c2
--- /dev/null
+++ b/flow/mcopclass/Synth_MUL.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_MUL,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_MULTI_ADD.mcopclass b/flow/mcopclass/Synth_MULTI_ADD.mcopclass
new file mode 100644
index 0000000..f883f9e
--- /dev/null
+++ b/flow/mcopclass/Synth_MULTI_ADD.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_MULTI_ADD,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_PLAY.mcopclass b/flow/mcopclass/Synth_PLAY.mcopclass
new file mode 100644
index 0000000..35c3ac4
--- /dev/null
+++ b/flow/mcopclass/Synth_PLAY.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_PLAY,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_PLAY_WAV.mcopclass b/flow/mcopclass/Synth_PLAY_WAV.mcopclass
new file mode 100644
index 0000000..8ca8d5c
--- /dev/null
+++ b/flow/mcopclass/Synth_PLAY_WAV.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_PLAY_WAV,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_RECORD.mcopclass b/flow/mcopclass/Synth_RECORD.mcopclass
new file mode 100644
index 0000000..8b69cf7
--- /dev/null
+++ b/flow/mcopclass/Synth_RECORD.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_RECORD,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/Synth_WAVE_SIN.mcopclass b/flow/mcopclass/Synth_WAVE_SIN.mcopclass
new file mode 100644
index 0000000..422d68f
--- /dev/null
+++ b/flow/mcopclass/Synth_WAVE_SIN.mcopclass
@@ -0,0 +1,3 @@
+Buildable=true
+Interface=Arts::Synth_WAVE_SIN,Arts::SynthModule,Arts::Object
+Language=C++
diff --git a/flow/mcopclass/WaveDataHandle.mcopclass b/flow/mcopclass/WaveDataHandle.mcopclass
new file mode 100644
index 0000000..d25effd
--- /dev/null
+++ b/flow/mcopclass/WaveDataHandle.mcopclass
@@ -0,0 +1,2 @@
+Interface=Arts::WaveDataHandle,Arts::Object
+Language=C++
diff --git a/flow/pipebuffer.cc b/flow/pipebuffer.cc
new file mode 100644
index 0000000..bb6073a
--- /dev/null
+++ b/flow/pipebuffer.cc
@@ -0,0 +1,166 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "pipebuffer.h"
+#include <assert.h>
+#include <cstring>
+
+using namespace std;
+using namespace Arts;
+
+PipeSegment::PipeSegment(long size, void *buffer)
+{
+ this->buffer = new char[size];
+ this->currentpos = this->buffer;
+ memcpy(this->buffer,buffer,size);
+
+ _remaining = size;
+}
+
+PipeSegment::~PipeSegment()
+{
+ delete[] buffer;
+}
+
+void *PipeSegment::data()
+{
+ return currentpos;
+}
+
+long PipeSegment::remaining()
+{
+ return _remaining;
+}
+
+void PipeSegment::skip(long count)
+{
+ _remaining -= count;
+ currentpos += count;
+ assert(_remaining >= 0);
+}
+
+PipeBuffer::PipeBuffer()
+{
+ _size = 0;
+}
+
+PipeBuffer::~PipeBuffer()
+{
+ clear();
+}
+
+void PipeBuffer::clear()
+{
+ while(segments.size() != 0)
+ {
+ PipeSegment *first = *segments.begin();
+ delete first;
+
+ segments.pop_front();
+ }
+ _size = 0;
+}
+
+void *PipeBuffer::peek(long size)
+{
+ while(!segments.empty())
+ {
+ PipeSegment *first = *segments.begin();
+ if(size <= first->remaining())
+ return first->data();
+ }
+ return 0;
+}
+
+void PipeBuffer::skip(long size)
+{
+ while(!segments.empty() && size > 0)
+ {
+ PipeSegment *first = *segments.begin();
+
+ // if we have less data to skip than the first segment contains
+ if(size < first->remaining())
+ {
+ // skip the data inside the segment
+
+ _size -= size;
+ first->skip(size);
+ return;
+ }
+ else
+ {
+ // otherwise erase the first segment
+
+ _size -= first->remaining();
+ size -= first->remaining();
+
+ delete first;
+ segments.pop_front();
+ }
+ }
+}
+
+long PipeBuffer::read(long size, void *buffer)
+{
+ long readbytes = 0;
+ char *bptr = (char *)buffer;
+
+ while(!segments.empty() && size > 0)
+ {
+ PipeSegment *first = *segments.begin();
+ long readCnt = size;
+ if(readCnt > first->remaining()) readCnt = first->remaining();
+
+ memcpy(bptr,first->data(),readCnt);
+
+ first->skip(readCnt);
+ size -= readCnt;
+ bptr += readCnt;
+ readbytes += readCnt;
+
+ if(first->remaining() == 0)
+ {
+ delete first;
+ segments.pop_front();
+ }
+ }
+
+ _size -= readbytes;
+ return readbytes;
+}
+
+long PipeBuffer::size()
+{
+ return _size;
+}
+
+void PipeBuffer::write(long size, void *buffer)
+{
+ segments.push_back(new PipeSegment(size,buffer));
+ _size += size;
+}
+
+void PipeBuffer::unRead(long size, void *buffer)
+{
+ segments.push_front(new PipeSegment(size,buffer));
+ _size += size;
+}
diff --git a/flow/pipebuffer.h b/flow/pipebuffer.h
new file mode 100644
index 0000000..c44e16b
--- /dev/null
+++ b/flow/pipebuffer.h
@@ -0,0 +1,75 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef __PIPEBUFFER_H__
+#define __PIPEBUFFER_H__
+
+/*
+ * BC - Status (2002-03-08): PipeSegment, PipeBuffer
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of libartsflow's
+ * AudioSubSystem, and subject to change/disappearing due to optimization
+ * work.
+ */
+
+
+#include <list>
+namespace Arts {
+
+class PipeSegment {
+ long _remaining;
+ char *currentpos, *buffer;
+public:
+ PipeSegment(long size, void *buffer);
+ ~PipeSegment();
+
+ void *data();
+ long remaining();
+ void skip(long count);
+};
+
+class PipeBuffer {
+protected:
+ std::list<PipeSegment *> segments;
+ long _size;
+
+public:
+ PipeBuffer();
+ ~PipeBuffer();
+
+ // reading
+ void *peek(long size);
+ void skip(long size);
+ long read(long size, void *buffer);
+ void unRead(long size, void *buffer);
+
+ // writing
+ void write(long size, void *buffer);
+ void clear();
+
+ // status
+ long size();
+};
+}
+
+#endif
diff --git a/flow/resample.cc b/flow/resample.cc
new file mode 100644
index 0000000..45cd099
--- /dev/null
+++ b/flow/resample.cc
@@ -0,0 +1,305 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "resample.h"
+#include "debug.h"
+#include <math.h>
+#include <assert.h>
+#include <stdio.h>
+
+#define compose_16le(first,second) \
+ (((((second)+128)&0xff) << 8)+(first))
+
+#define compose_16be(first,second) \
+ (((((first)+128)&0xff) << 8)+(second))
+
+#define conv_16_float(x) \
+ ((float)((x)-32768)/32768.0)
+
+#define conv_8_float(x) \
+ ((float)((x)-128)/128.0)
+
+using namespace Arts;
+
+class Arts::ResamplerPrivate {
+public:
+ bool underrun;
+ Resampler::Endianness endianness;
+};
+
+const unsigned int Resampler::bufferSize;
+const unsigned int Resampler::bufferWrap;
+
+Resampler::Resampler(Refiller *refiller) :
+ dropBytes(0), refiller(refiller), pos(0.0), step(1.0), channels(2),
+ bits(16),
+ block(0), haveBlock(-1)
+{
+ d = new ResamplerPrivate();
+ d->underrun = false;
+ d->endianness = littleEndian;
+ updateSampleSize();
+}
+
+Resampler::~Resampler()
+{
+ delete d;
+}
+
+void Resampler::updateSampleSize()
+{
+ sampleSize = channels * bits / 8;
+ bufferSamples = bufferSize / sampleSize;
+}
+
+void Resampler::setStep(double newStep)
+{
+ arts_return_if_fail(newStep > 0);
+
+ step = newStep;
+}
+
+void Resampler::setChannels(int newChannels)
+{
+ arts_return_if_fail(newChannels == 1 || newChannels == 2);
+
+ channels = newChannels;
+ updateSampleSize();
+}
+
+void Resampler::setBits(int newBits)
+{
+ arts_return_if_fail(newBits == 8 || newBits == 16);
+
+ bits = newBits;
+ updateSampleSize();
+}
+
+void Resampler::setEndianness(Endianness newEndianness)
+{
+ arts_return_if_fail(newEndianness == bigEndian || newEndianness == littleEndian);
+
+ d->endianness = newEndianness;
+}
+
+bool Resampler::underrun()
+{
+ return d->underrun;
+}
+
+void Resampler::ensureRefill()
+{
+ if(haveBlock == block) return;
+
+ unsigned long missing;
+ if(block == 0)
+ {
+ missing = bufferSize+sampleSize
+ - refiller->read(buffer,bufferSize+sampleSize);
+
+ d->underrun = (missing == bufferSize+sampleSize);
+ }
+ else
+ {
+ /*
+ * try to drop away "half-sample" reads from the last refill
+ */
+ if(dropBytes > 0)
+ dropBytes -= refiller->read(buffer,dropBytes);
+
+ /*
+ * only if this worked there is hope that we can read sane data
+ */
+ if(dropBytes == 0)
+ {
+ missing = bufferSize
+ - refiller->read(&buffer[sampleSize], bufferSize);
+
+ d->underrun = (missing == bufferSize);
+ }
+ else
+ {
+ missing = bufferSize;
+ d->underrun = true;
+ }
+ }
+ haveBlock++;
+ assert(haveBlock == block);
+
+ /*
+ * If we don't have enough input to fill the block fully, it might be
+ * that the input stall occurred in the middle of a sample. For instance,
+ * if samples are 4 bytes long, it might be that we would have needed
+ * 13 more bytes to do a full refill.
+ *
+ * In this situation, there are four samples and one byte missing to
+ * refill the buffer - the one byte is what we need to care about here:
+ * on the next read, we'll have one byte too much (if we simply ignore
+ * the fact, we end up with misaligned reading, causing noise, or
+ * swapped stereo channels or similar).
+ *
+ * So we set dropBytes here, which is a variable which indicates how
+ * many bytes to drop away upon next refill.
+ */
+ if(missing & (sampleSize - 1))
+ dropBytes = missing & (sampleSize - 1);
+
+ unsigned int i = 0, wrap = (block == 0)?0:sampleSize;
+ if(bits == 16)
+ {
+ // wrap the last part of the buffer back to the beginning (history)
+ while(i<wrap)
+ {
+ fbuffer[i/2] = fbuffer[(bufferSize+i)/2];
+ i += 2;
+ }
+
+ // convert data from incoming
+ if(d->endianness == littleEndian)
+ {
+ while(i<bufferSize+sampleSize-missing)
+ {
+ fbuffer[i/2] = conv_16_float(compose_16le(buffer[i],buffer[i+1]));
+ i += 2;
+ }
+ }
+ else
+ {
+ while(i<bufferSize+sampleSize-missing)
+ {
+ fbuffer[i/2] = conv_16_float(compose_16be(buffer[i],buffer[i+1]));
+ i += 2;
+ }
+ }
+
+ // fill up missing bytes with zero samples
+ while(i<bufferSize+sampleSize)
+ {
+ fbuffer[i/2] = 0.0;
+ i += 2;
+ }
+ }
+ else if(bits == 8)
+ {
+ // wrap the last part of the buffer back to the beginning (history)
+ while(i<wrap)
+ {
+ fbuffer[i] = fbuffer[bufferSize+i];
+ i++;
+ }
+
+ // convert data from incoming
+ while(i<bufferSize+sampleSize-missing)
+ {
+ fbuffer[i] = conv_8_float(buffer[i]);
+ i++;
+ }
+
+ // fill up missing bytes with zero samples
+ while(i<bufferSize+sampleSize)
+ {
+ fbuffer[i++] = 0.0;
+ }
+ }
+ else
+ {
+ assert(false);
+ }
+}
+
+#define RESAMPLER_STEP() \
+ pos += step; \
+ i++; \
+ while(pos >= bufferSamples) \
+ { \
+ pos -= bufferSamples; \
+ block++; \
+ ensureRefill(); \
+ }
+
+void Resampler::run(float *left, float *right, unsigned long samples)
+{
+ ensureRefill();
+ unsigned long i = 0;
+ double delta = step - floor(step);
+ bool interpolate = fabs(delta) > 0.001;
+
+ if(channels == 2 && interpolate)
+ {
+ while(i < samples)
+ {
+ double error = pos - floor(pos);
+ unsigned long offset = 2*(unsigned long)pos;
+
+ left[i] = fbuffer[offset+0]*(1.0-error)+fbuffer[offset+2]*error;
+ right[i] = fbuffer[offset+1]*(1.0-error)+fbuffer[offset+3]*error;
+ RESAMPLER_STEP();
+ }
+ }
+ else if(channels == 1 && interpolate)
+ {
+ while(i < samples)
+ {
+ double error = pos - floor(pos);
+ unsigned long offset = (unsigned long)pos;
+
+ left[i] = right[i] = fbuffer[offset]*(1.0-error)
+ + fbuffer[offset+1]*error;
+ RESAMPLER_STEP();
+ }
+ }
+ else if(channels == 2)
+ {
+ while(i < samples)
+ {
+ unsigned long offset = 2*(unsigned long)pos;
+
+ left[i] = fbuffer[offset+0];
+ right[i] = fbuffer[offset+1];
+ RESAMPLER_STEP();
+ }
+ }
+ else if(channels == 1)
+ {
+ while(i < samples)
+ {
+ unsigned long offset = (unsigned long)pos;
+
+ left[i] = right[i] = fbuffer[offset];
+ RESAMPLER_STEP();
+ }
+ }
+ else
+ {
+ assert(false);
+ }
+}
+
+Refiller::~Refiller()
+{
+}
+
+#undef RESAMPLER_STEP
+#undef compose_16le
+#undef compose_16be
+#undef conv_16_float
+#undef conv_8_float
diff --git a/flow/resample.h b/flow/resample.h
new file mode 100644
index 0000000..3cb99e3
--- /dev/null
+++ b/flow/resample.h
@@ -0,0 +1,167 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+
+#ifndef ARTS_FLOW_RESAMPLE_H
+#define ARTS_FLOW_RESAMPLE_H
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Resampler / Refiller.
+ *
+ * These classes will be kept binary compatible. Resampler has a private
+ * data pointer for this purpose.
+ */
+
+namespace Arts {
+
+/**
+ * Refiller interface
+ *
+ * this is used by the resampler class
+ */
+class ARTS_EXPORT Refiller {
+public:
+ /**
+ * callback method to supply data to the Resampler
+ *
+ * here you supply data in the encoding specified in the Resampler class
+ * (bits, channels, endianness) to the Resampler
+ *
+ * @param buffer a pointer to a buffer where the data can be filled to
+ * @param len the size of the buffer in bytes
+ *
+ * @returns the number of bytes really available
+ */
+ virtual unsigned long read(unsigned char *buffer, unsigned long len) = 0;
+ virtual ~Refiller();
+};
+
+class ResamplerPrivate;
+
+/**
+ * The Resampler class resamples data from an input stream, which is read
+ * through the Refiller interface, and renders it into the float format which
+ * aRts usually uses, converting the sampling rate and format as needed.
+ */
+class ARTS_EXPORT Resampler {
+protected:
+ static const unsigned int bufferSize = 256; // 64 samples in buffer
+ static const unsigned int bufferWrap = 64; // + "wrap around"
+ /*
+ * BC: bufferWrap just needs channels * (filtersize - 1) * bytes per sample
+ * bytes wrap around - this used to be 4: 2 channels, linear interpolation,
+ * 16bit. However, for supporting float resampling and/or better filters,
+ * we'll make this 64 to be safe.
+ */
+
+ int bufferSamples;
+ int sampleSize;
+ int dropBytes;
+
+ Refiller *refiller;
+ double pos, step;
+ int channels,bits;
+
+ unsigned char buffer[bufferSize+bufferWrap];
+ float fbuffer[bufferSize+bufferWrap];
+ long block, haveBlock;
+
+ class ResamplerPrivate *d;
+
+ void updateSampleSize();
+ void ensureRefill();
+public:
+ /**
+ * constructor
+ *
+ */
+ Resampler(Refiller *refiller);
+ ~Resampler();
+
+ /**
+ * sets the resampling step in the input stream
+ *
+ * for instance, settings step to 2.0, the file would be played twice as
+ * fast - you can calculate the resampling step from the sampling rate
+ * the stream you resample was recorded at, and the sampling rate you want
+ * it to be resampled to, using
+ *
+ * step = originalSamplingRate / desiredSamplingRate
+ *
+ * for instance, if a stream recorded at 22050 Hz is to be played at 48000
+ * Hz, step would be
+ *
+ * step = 22050 / 48000 = 0.46
+ */
+ void setStep(double step);
+
+ /**
+ * sets the number of channels in the input stream
+ *
+ * the channels are expected to be interleaved, thus if you have two
+ * channels, you will have one sample for the left stream, one for the
+ * right, one for the left, ... and so on
+ *
+ * currently only either mono (channels = 1) or stereo (channels = 2)
+ * streams are supported
+ */
+ void setChannels(int channels);
+
+ /**
+ * sets the number of bits in the input stream
+ *
+ * currently, only 16 bit and 8 bit streams are supported
+ */
+ void setBits(int bits);
+
+ enum Endianness { bigEndian, littleEndian };
+
+ /**
+ * sets the endianess of the input stream
+ *
+ * supported are bigEndian and littleEndian
+ */
+ void setEndianness(Endianness endianness);
+
+ /**
+ * renders a buffer of float samples from the input stream
+ *
+ * the data is obtained by querying the refiller for data from the
+ * input stream and filling them into the float array pointed to by
+ * left and right - if reading data fails, the underrun flag is set
+ */
+ void run(float *left, float *right, unsigned long samples);
+
+ /**
+ * query the underrun flag
+ *
+ * underruns occur if run is called, but no data is available from the
+ * Refiller object
+ */
+ bool underrun();
+};
+
+}
+
+#endif /* ARTS_FLOW_RESAMPLE_H */
diff --git a/flow/stdsynthmodule.cc b/flow/stdsynthmodule.cc
new file mode 100644
index 0000000..6d1c122
--- /dev/null
+++ b/flow/stdsynthmodule.cc
@@ -0,0 +1,92 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "stdsynthmodule.h"
+#include "gslschedule.h"
+#include "audiosubsys.h"
+#include "flowsystem.h"
+#include "debug.h"
+
+using namespace Arts;
+using namespace std;
+
+StdSynthModule::StdSynthModule()
+{
+ // TODO: maybe this should be handled over some other mechanism
+
+ samplingRate = AudioSubSystem::the()->samplingRate();
+ samplingRateFloat = (float)samplingRate;
+}
+
+void StdSynthModule::streamInit()
+{
+}
+
+void StdSynthModule::streamStart()
+{
+}
+
+void StdSynthModule::streamEnd()
+{
+}
+
+void StdSynthModule::start()
+{
+ _node()->start();
+}
+
+void StdSynthModule::stop()
+{
+ _node()->stop();
+}
+
+AutoSuspendState StdSynthModule::autoSuspend()
+{
+ return asNoSuspend;
+}
+
+unsigned long StdSynthModule::inputConnectionCount(const std::string& port)
+{
+ StdScheduleNode *xnode = (StdScheduleNode *)
+ _node()->cast("StdScheduleNode");
+ arts_return_val_if_fail(xnode, 0);
+
+ return xnode->inputConnectionCount(port);
+}
+
+unsigned long StdSynthModule::outputConnectionCount(const std::string& port)
+{
+ StdScheduleNode *xnode = (StdScheduleNode *)
+ _node()->cast("StdScheduleNode");
+ arts_return_val_if_fail(xnode, 0);
+
+ return xnode->outputConnectionCount(port);
+}
+
+bool StdSynthModule::connectionCountChanged()
+{
+ StdScheduleNode *xnode = (StdScheduleNode *)
+ _node()->cast("StdScheduleNode");
+ arts_return_val_if_fail(xnode, 0);
+
+ return xnode->connectionCountChanged();
+}
diff --git a/flow/stdsynthmodule.h b/flow/stdsynthmodule.h
new file mode 100644
index 0000000..fb1830a
--- /dev/null
+++ b/flow/stdsynthmodule.h
@@ -0,0 +1,65 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef STDSYNTHMODULE_H
+#define STDSYNTHMODULE_H
+
+#include "arts_export.h"
+#include "artsflow.h"
+
+/*
+ * BC - Status (2002-03-08): StdSynthModule
+ *
+ * This class is intended for public use (inheritance) as it supplies a base
+ * for all objects using streams. It will be kept binary compatible.
+ */
+
+namespace Arts {
+
+class StdSynthModulePrivate;
+
+class ARTS_EXPORT StdSynthModule : virtual public SynthModule_base {
+private:
+ StdSynthModulePrivate *d;
+
+protected:
+ long samplingRate;
+ float samplingRateFloat;
+
+public:
+ StdSynthModule();
+
+ void start();
+ void stop();
+
+ void streamInit();
+ void streamStart();
+ void streamEnd();
+
+ AutoSuspendState autoSuspend();
+
+ unsigned long inputConnectionCount(const std::string& portname);
+ unsigned long outputConnectionCount(const std::string& portname);
+ bool connectionCountChanged();
+};
+}
+#endif /* STDSYNTHMODULE_H */
diff --git a/flow/stereoeffectstack_impl.cc b/flow/stereoeffectstack_impl.cc
new file mode 100644
index 0000000..3e82cfb
--- /dev/null
+++ b/flow/stereoeffectstack_impl.cc
@@ -0,0 +1,179 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "flowsystem.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class StereoEffectStack_impl : public StereoEffectStack_skel,
+ public StdSynthModule
+{
+ long nextID;
+
+ struct EffectEntry {
+ StereoEffect effect;
+ string name;
+ long id;
+ };
+ list<EffectEntry *> fx;
+
+ void xconnect(bool connect, Object from, string fromP, Object to, string toP)
+ {
+ if(connect)
+ from._node()->connect(fromP,to._node(),toP);
+ else
+ from._node()->disconnect(fromP,to._node(),toP);
+ }
+ void xvirtualize(bool connect, string myPort, Object impl, string implPort)
+ {
+ if(connect)
+ _node()->virtualize(myPort,impl._node(),implPort);
+ else
+ _node()->devirtualize(myPort,impl._node(),implPort);
+ }
+ void internalconnect(bool c)
+ {
+ if(fx.empty())
+ {
+ /* no effects - forward input through to output */
+ xvirtualize(c,"outleft",Object::_from_base(this->_copy()),"inleft");
+ xvirtualize(c,"outright",Object::_from_base(this->_copy()),"inright");
+ }
+ else
+ {
+ list<EffectEntry *>::iterator ei;
+ EffectEntry *laste = 0;
+
+ long count = 0;
+ for(ei = fx.begin(); ei != fx.end(); ei++, count++)
+ {
+ EffectEntry *e = *ei;
+ if(count == 0) /* top of chain? virtualize to effect */
+ {
+ xvirtualize(c,"inleft",e->effect,"inleft");
+ xvirtualize(c,"inright",e->effect,"inright");
+ }
+ else /* not top? connect last effect to current effect */
+ {
+ xconnect(c,laste->effect,"outleft",e->effect,"inleft");
+ xconnect(c,laste->effect,"outright",e->effect,"inright");
+ }
+ laste = e;
+ }
+ /* end: virtualize effect output to our output */
+ xvirtualize(c,"outleft",laste->effect,"outleft");
+ xvirtualize(c,"outright",laste->effect,"outright");
+ }
+ }
+ void disconnect() { internalconnect(false); }
+ void reconnect() { internalconnect(true); }
+public:
+ StereoEffectStack_impl() : nextID(1)
+ {
+ reconnect();
+ }
+ ~StereoEffectStack_impl()
+ {
+ // disconnect remaining effects
+ EffectEntry *laste = 0;
+ list<EffectEntry *>::iterator ei;
+
+ for(ei = fx.begin(); ei != fx.end(); ei++)
+ {
+ EffectEntry *e = *ei;
+ if(laste)
+ {
+ xconnect(false,laste->effect,"outleft",e->effect,"inleft");
+ xconnect(false,laste->effect,"outright",e->effect,"inright");
+ }
+ laste = e;
+ }
+ // delete remaining effect entries
+ for(ei = fx.begin(); ei != fx.end(); ei++)
+ delete *ei;
+ fx.clear();
+ }
+ long insertTop(StereoEffect effect, const string& name)
+ {
+ arts_return_val_if_fail(!effect.isNull(),0);
+
+ disconnect();
+ EffectEntry *e = new EffectEntry();
+ e->effect = effect;
+ e->name = name;
+ e->id = nextID++;
+ fx.push_front(e);
+ reconnect();
+ return e->id;
+ }
+ long insertBottom(StereoEffect effect, const string& name)
+ {
+ arts_return_val_if_fail(!effect.isNull(),0);
+
+ disconnect();
+ EffectEntry *e = new EffectEntry();
+ e->effect = effect;
+ e->name = name;
+ e->id = nextID++;
+ fx.push_back(e);
+ reconnect();
+ return e->id;
+ }
+
+ void remove(long ID)
+ {
+ arts_return_if_fail(ID != 0);
+
+ bool found = false;
+ disconnect();
+ list<EffectEntry *>::iterator ei = fx.begin();
+
+ while(ei != fx.end())
+ {
+ if((*ei)->id == ID) {
+ found = true;
+ delete (*ei);
+ fx.erase(ei);
+ ei = fx.begin();
+ }
+ else ei++;
+ }
+ if(!found) {
+ arts_warning("StereoEffectStack::remove failed. id %d not found?",
+ ID);
+ }
+ reconnect();
+ }
+
+ AutoSuspendState autoSuspend() { return asSuspend; }
+};
+
+REGISTER_IMPLEMENTATION(StereoEffectStack_impl);
+
+}
diff --git a/flow/stereofftscope_impl.cc b/flow/stereofftscope_impl.cc
new file mode 100644
index 0000000..59ec05a
--- /dev/null
+++ b/flow/stereofftscope_impl.cc
@@ -0,0 +1,131 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "fft.h"
+#include "stdsynthmodule.h"
+#include <math.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class StereoFFTScope_impl : public StereoFFTScope_skel, public StdSynthModule {
+protected:
+ static const unsigned long SAMPLES = 4096;
+ vector<float> _scope;
+ /*
+ * some gcc versions expose ugly behaviour with virtual inheritance:
+ * putting window[4096] & inbuffer[4096] here bloats the vtable then,
+ * and tells you to recompile with -fhuge-objects ... so allocate them
+ * dynamically
+ */
+ float *window;
+ float *inbuffer;
+ unsigned long inbufferpos;
+public:
+ void do_fft()
+ {
+ float out_real[SAMPLES],out_img[SAMPLES];
+ arts_fft_float(SAMPLES,0,inbuffer,0,out_real,out_img);
+
+ _scope.clear();
+ unsigned int i = 3;
+ unsigned int j = 0;
+ for(;;) {
+ float xrange = 0.0;
+ while(j != i)
+ {
+ xrange += (fabs(out_img[j]) + fabs(out_real[j]))/(float)SAMPLES;
+ j++;
+ }
+ _scope.push_back(xrange);
+
+ if(i == SAMPLES/2) return;
+
+ i += i/2;
+ if(i > SAMPLES/2) i = SAMPLES/2;
+ }
+ }
+ void streamInit()
+ {
+ unsigned long i;
+ for(i=0;i<SAMPLES;i++)
+ {
+ float x = (float)i/(float)SAMPLES;
+ window[i] = sin(x*M_PI)*sin(x*M_PI);
+ inbuffer[i] = 0;
+ }
+ do_fft(); // initialize so that we never return an empty scope
+ }
+ void streamStart()
+ {
+ inbufferpos = 0;
+ }
+ vector<float> *scope()
+ {
+ return new vector<float>(_scope);
+ }
+ /*
+ in audio stream inleft, inright;
+ out audio stream outleft, outright;
+ */
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+ for(i=0;i<samples;i++)
+ {
+ inbuffer[inbufferpos] =
+ (inleft[i] + inright[i])*window[inbufferpos];
+ if(++inbufferpos == SAMPLES)
+ {
+ do_fft();
+ inbufferpos = 0;
+ }
+ /*
+ monitoring only tasks can't be done with that StereoEffect
+ interface nicely - copy input to output until there is
+ something better
+ */
+ outleft[i] = inleft[i];
+ outright[i] = inright[i];
+ }
+ }
+
+ /* prevent vtable overflows (see above) */
+ StereoFFTScope_impl() {
+ window = new float[SAMPLES];
+ inbuffer = new float[SAMPLES];
+ }
+ ~StereoFFTScope_impl() {
+ delete [] window;
+ delete [] inbuffer;
+ }
+};
+
+const unsigned long StereoFFTScope_impl::SAMPLES;
+
+REGISTER_IMPLEMENTATION(StereoFFTScope_impl);
+
+}
diff --git a/flow/stereovolumecontrol_impl.cc b/flow/stereovolumecontrol_impl.cc
new file mode 100644
index 0000000..ae90ae6
--- /dev/null
+++ b/flow/stereovolumecontrol_impl.cc
@@ -0,0 +1,197 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <math.h>
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include "flowsystem.h"
+#include <debug.h>
+
+#include <cstring>
+
+using namespace Arts;
+
+namespace Arts {
+
+class StereoVolumeControl_impl : virtual public StereoVolumeControl_skel,
+ virtual public StdSynthModule
+{
+ float _scaleFactor;
+ float _currentVolumeLeft;
+ float _currentVolumeRight;
+ bool _virtualized;
+ bool _calcVolume;
+public:
+ StereoVolumeControl_impl() :_scaleFactor(1.0), _currentVolumeLeft(0.0),
+ _currentVolumeRight(0.0), _virtualized( false ),
+ _calcVolume( false )
+ {
+ virtualize();
+ }
+
+ /*attribute float scaleFactor;*/
+ void scaleFactor(float newFactor) {
+ if(_scaleFactor != newFactor)
+ {
+ _scaleFactor = newFactor;
+ scaleFactor_changed(newFactor);
+ if( _scaleFactor == 1.0 )
+ {
+ if( !_calcVolume && !_virtualized )
+ virtualize();
+ }
+ else if( _virtualized )
+ devirtualize();
+ }
+ }
+ float scaleFactor() { return _scaleFactor; }
+
+ /*
+ readonly attribute float currentVolumeLeft;
+ readonly attribute float currentVolumeRight;
+ */
+ float currentVolumeLeft()
+ {
+ if( _virtualized && !_calcVolume )
+ needVolumeCalculation();
+
+ return _currentVolumeLeft;
+ }
+
+ float currentVolumeRight()
+ {
+ if( _virtualized && !_calcVolume )
+ needVolumeCalculation();
+
+ return _currentVolumeRight;
+ }
+
+ void needVolumeCalculation()
+ {
+ arts_debug( "calculate Volume in StereoVolumeControl" );
+ _calcVolume = true;
+ devirtualize();
+ }
+
+ void virtualize()
+ {
+ arts_debug( "virtualize StereoVolumeControl" );
+ _virtualized = true;
+ _node()->virtualize( "inleft", _node(), "outleft" );
+ _node()->virtualize( "inright", _node(), "outright" );
+ _currentVolumeRight = _currentVolumeLeft = 0.0;
+ }
+ void devirtualize()
+ {
+ arts_debug( "devirtualize StereoVolumeControl" );
+ _virtualized = false;
+ _node()->devirtualize( "inleft", _node(), "outleft" );
+ _node()->devirtualize( "inright", _node(), "outright" );
+ }
+ /*
+ in audio stream inleft, inright;
+ out audio stream outleft, outright;
+ */
+ void calculateBlock(unsigned long samples)
+ {
+ if( _scaleFactor == 1.0 )
+ {
+ if( _calcVolume )
+ {
+ /*
+ * make sure that we reach zero sometimes - otherwise there are
+ * performance issues with calculations close to zero
+ */
+ if(fabs(_currentVolumeLeft) < 0.001) _currentVolumeLeft = 0.0;
+ if(fabs(_currentVolumeRight) < 0.001) _currentVolumeRight = 0.0;
+
+ for( unsigned long i = 0; i < samples; i += 10 )
+ {
+ /* measure volume */
+ float delta;
+
+ // left
+ delta = fabs( outleft[ i ] ) - _currentVolumeLeft;
+ if( delta > 0.0 )
+ _currentVolumeLeft += 0.1 * delta;
+ else
+ _currentVolumeLeft += 0.003 * delta;
+
+ // right
+ delta = fabs( outright[ i ] ) - _currentVolumeRight;
+ if( delta > 0.0 )
+ _currentVolumeRight += 0.1 * delta;
+ else
+ _currentVolumeRight += 0.003 * delta;
+ }
+ memcpy( outleft, inleft, samples * sizeof( float ) );
+ memcpy( outright, inright, samples * sizeof( float ) );
+ }
+ return;
+ }
+
+ unsigned long i;
+
+ /*
+ * make sure that we reach zero sometimes - otherwise there are
+ * performance issues with calculations close to zero
+ */
+ if(fabs(_currentVolumeLeft) < 0.001) _currentVolumeLeft = 0.0;
+ if(fabs(_currentVolumeRight) < 0.001) _currentVolumeRight = 0.0;
+
+ for(i=0;i<samples;i++)
+ {
+ /* scale */
+ outleft[i] = inleft[i] * _scaleFactor;
+ outright[i] = inright[i] * _scaleFactor;
+
+ /* measure volume */
+ float delta;
+
+ // left
+ delta = fabs(outleft[i])-_currentVolumeLeft;
+ if(delta > 0.0)
+ _currentVolumeLeft += 0.01 * delta;
+ else
+ _currentVolumeLeft += 0.0003 * delta;
+
+ // right
+ delta = fabs(outright[i])-_currentVolumeRight;
+ if(delta > 0.0)
+ _currentVolumeRight += 0.01 * delta;
+ else
+ _currentVolumeRight += 0.0003 * delta;
+ }
+ }
+
+ AutoSuspendState autoSuspend() {
+ return (_currentVolumeLeft+_currentVolumeRight<0.001)?
+ asSuspend : asNoSuspend;
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(StereoVolumeControl_impl);
+
+}
+
+// vim: sw=4 ts=4 noet
diff --git a/flow/synth_add_impl.cc b/flow/synth_add_impl.cc
new file mode 100644
index 0000000..1f52a21
--- /dev/null
+++ b/flow/synth_add_impl.cc
@@ -0,0 +1,44 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_ADD_impl :public Synth_ADD_skel, public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+
+ for(i = 0;i < samples; i++)
+ outvalue[i] = invalue1[i] + invalue2[i];
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_ADD_impl);
+
+}
diff --git a/flow/synth_frequency_impl.cc b/flow/synth_frequency_impl.cc
new file mode 100644
index 0000000..1c0bbbe
--- /dev/null
+++ b/flow/synth_frequency_impl.cc
@@ -0,0 +1,70 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include <math.h>
+#include <stdio.h>
+
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_FREQUENCY_impl :public Synth_FREQUENCY_skel, public StdSynthModule
+{
+ float fpos;
+public:
+ void streamInit() {
+ fpos = 0;
+ }
+ void calculateBlock(unsigned long cycles) {
+ float fsample = samplingRateFloat;
+ float finc = *frequency/fsample;
+
+ while(cycles)
+ {
+ if(cycles >= 8 && ((finc*8+fpos) < 0.9))
+ {
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ fpos += finc; *pos++ = fpos;
+ cycles -= 8;
+ }
+ else
+ {
+ fpos += finc;
+ fpos -= floor(fpos);
+ *pos++ = fpos;
+ cycles--;
+ }
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_FREQUENCY_impl);
+
+}
diff --git a/flow/synth_mul_impl.cc b/flow/synth_mul_impl.cc
new file mode 100644
index 0000000..11d97c8
--- /dev/null
+++ b/flow/synth_mul_impl.cc
@@ -0,0 +1,44 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_MUL_impl :public Synth_MUL_skel, public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long samples)
+ {
+ unsigned long i;
+
+ for(i = 0;i < samples; i++)
+ outvalue[i] = invalue1[i] * invalue2[i];
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_MUL_impl);
+
+}
diff --git a/flow/synth_multi_add_impl.cc b/flow/synth_multi_add_impl.cc
new file mode 100644
index 0000000..2bd14dc
--- /dev/null
+++ b/flow/synth_multi_add_impl.cc
@@ -0,0 +1,64 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_MULTI_ADD_impl :public Synth_MULTI_ADD_skel, public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long cycles);
+ AutoSuspendState autoSuspend() { return asSuspend; }
+};
+
+REGISTER_IMPLEMENTATION(Synth_MULTI_ADD_impl);
+
+}
+
+void Synth_MULTI_ADD_impl::calculateBlock(unsigned long cycles)
+{
+ float *outend = outvalue + cycles;
+ float *outp, *inp;
+
+ if(!invalue[0])
+ {
+ // no invalue? zero out the outvalue
+ for(outp = outvalue; outp != outend; outp++) *outp = 0.0;
+ }
+ else
+ {
+ // copy first signal
+ for(outp = outvalue, inp = invalue[0]; outp != outend; outp++, inp++)
+ *outp = *inp;
+
+ // add the others
+ for(int sig=1;(inp = invalue[sig]) != 0;sig++)
+ {
+ for(outp = outvalue; outp != outend;outp++,inp++)
+ *outp += *inp;
+ }
+ }
+}
diff --git a/flow/synth_play_impl.cc b/flow/synth_play_impl.cc
new file mode 100644
index 0000000..c1be750
--- /dev/null
+++ b/flow/synth_play_impl.cc
@@ -0,0 +1,285 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "debug.h"
+#include "convert.h"
+#include "objectmanager.h"
+#include "audiosubsys.h"
+#include "dispatcher.h"
+#include "iomanager.h"
+#include "flowsystem.h"
+#include "stdsynthmodule.h"
+#include <stdio.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_PLAY_impl : virtual public Synth_PLAY_skel,
+ virtual public ASProducer,
+ virtual public StdSynthModule,
+ virtual public IONotify,
+ virtual public TimeNotify
+{
+protected:
+ AudioSubSystem *as;
+ bool haveSubSys;
+ /*
+ * these are to prevent the following situation
+ * 1) audio subsystem needs more data
+ * 2) calculation is started
+ * 3) somehow, some module makes a synchronous invocation to the outside
+ * world and waits for the result
+ * 4) since the audio subsystem still needs data, and since we are in an
+ * idle state now, another calculation will be started, which will of
+ * course fail due to reentrancy
+ * 5) repeat 4) until result is there => lots of wasted CPU cycles (when
+ * running with realtime priority: system freeze)
+ */
+ bool inProgress; // we are just doing some calculations
+ bool restartIOHandling; // I/O handlers removed upon reaching 4: restart
+
+ int audioReadFD;
+ int audioWriteFD;
+ bool audioOpen;
+
+ typedef unsigned char uchar;
+
+ unsigned char *outblock;
+ unsigned long maxsamples;
+ unsigned long channels;
+ int format;
+ int bits;
+
+ bool retryOpen;
+public:
+ /*
+ * functions from the SynthModule interface (which is inherited by
+ * SynthPlay)
+ */
+ void streamInit() {
+ as = AudioSubSystem::the();
+
+ maxsamples = 0;
+ outblock = 0;
+ retryOpen = false;
+ audioOpen = false;
+ inProgress = false;
+
+ haveSubSys = as->attachProducer(this);
+ if(!haveSubSys)
+ {
+ arts_info("Synth_PLAY: audio subsystem is already used");
+ return;
+ }
+
+ audioOpen = as->open();
+ if(!audioOpen)
+ {
+ if(Dispatcher::the()->flowSystem()->suspended())
+ {
+ arts_info("/dev/dsp currently unavailable (retrying)");
+ Dispatcher::the()->ioManager()->addTimer(1000, this);
+ retryOpen = true;
+ }
+ else
+ {
+ arts_info("Synth_PLAY: audio subsystem init failed");
+ arts_info("ASError = %s",as->error());
+ }
+ audioReadFD = audioWriteFD = -1;
+ }
+ else
+ {
+ audioReadFD = as->selectReadFD();
+ audioWriteFD = as->selectWriteFD();
+ }
+
+ channels = as->channels();
+ format = as->format();
+ bits = as->bits();
+ arts_debug("audio format is %d Hz, %d bits, %d channels",
+ as->samplingRate(), bits, channels);
+ }
+
+ void notifyTime() {
+ assert(retryOpen);
+
+ audioOpen = as->open();
+
+ if(audioOpen)
+ {
+ audioReadFD = as->selectReadFD();
+ audioWriteFD = as->selectWriteFD();
+
+ streamStart();
+ arts_info("/dev/dsp ok");
+ Dispatcher::the()->ioManager()->removeTimer(this);
+ retryOpen = false;
+ }
+ }
+
+ void streamStart() {
+ IOManager *iom = Dispatcher::the()->ioManager();
+
+ if(audioReadFD >= 0)
+ iom->watchFD(audioReadFD, IOType::read|IOType::except, this);
+
+ if(audioWriteFD >= 0)
+ iom->watchFD(audioWriteFD, IOType::write|IOType::except, this);
+ }
+
+ void streamEnd() {
+ if(retryOpen)
+ Dispatcher::the()->ioManager()->removeTimer(this);
+
+ arts_debug("Synth_PLAY: closing audio fd");
+ if(audioReadFD >= 0 || audioWriteFD >= 0)
+ {
+ IOManager *iom = Dispatcher::the()->ioManager();
+ iom->remove(this,IOType::all);
+ audioReadFD = audioWriteFD = -1;
+ }
+ AudioSubSystem::the()->detachProducer();
+
+ if(outblock)
+ {
+ delete[] outblock;
+ outblock = 0;
+ }
+ }
+
+ AutoSuspendState autoSuspend()
+ {
+ return static_cast<AutoSuspendState>(asSuspendStop|asConsumer);
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ // no audio subsystem, no play
+ if(!as->running() || !haveSubSys) return;
+
+ if(samples > maxsamples)
+ {
+ maxsamples = samples;
+
+ if(outblock) delete[] outblock;
+ outblock = new uchar[maxsamples * channels * ( format & ( 8 | 16 | 32 ) ) / 8];
+ }
+
+ assert(channels);
+
+ arts_assert(format == 8 || format == 16 || format == 17 || format == 32 );
+ if(channels == 1)
+ {
+ if(format == 8)
+ convert_mono_float_8(samples,invalue_left,outblock);
+ else if(format == 16)
+ convert_mono_float_16le(samples,invalue_left,outblock);
+ else if(format == 17)
+ convert_mono_float_16be(samples,invalue_left,outblock);
+ else if(format == 32)
+ {
+ as->write( invalue_left, samples );
+ return;
+ }
+ }
+ else if(channels == 2)
+ {
+ if(format == 8)
+ convert_stereo_2float_i8(samples,invalue_left,invalue_right,
+ outblock);
+ else if(format == 16)
+ convert_stereo_2float_i16le(samples,invalue_left,invalue_right,
+ outblock);
+ else if(format == 17)
+ convert_stereo_2float_i16be(samples,invalue_left,invalue_right,
+ outblock);
+ else if(format == 32)
+ {
+ float * buffer = ( float* )outblock;
+ float * end = invalue_left + samples;
+ while( invalue_left < end )
+ {
+ *buffer++ = *invalue_left++;
+ *buffer++ = *invalue_right++;
+ }
+ as->write( outblock, 2 * samples * sizeof( float ) );
+ return;
+ }
+ }
+ else arts_warning("channels != 1 && channels != 2?");
+
+ as->write(outblock,channels * (bits / 8) * samples);
+ }
+
+ /**
+ * notifyIO from the IONotify interface (IOManager)
+ */
+ void notifyIO(int fd, int type)
+ {
+ arts_return_if_fail(as->running());
+ assert(fd == audioReadFD || fd == audioWriteFD);
+
+ if(inProgress)
+ {
+ if(!restartIOHandling)
+ {
+ // prevent lots of retries - we just can't do calculations
+ // now, so we need to wait until the situation has resolved
+ Dispatcher::the()->ioManager()->remove(this,IOType::all);
+ restartIOHandling = true;
+ }
+ return;
+ }
+
+ // convert iomanager notification types to audiosubsys notification
+ int asType = 0;
+
+ if(type & IOType::read) asType |= AudioSubSystem::ioRead;
+ if(type & IOType::write) asType |= AudioSubSystem::ioWrite;
+ assert(asType != 0);
+
+ restartIOHandling = false;
+ inProgress = true;
+ as->handleIO(asType);
+ inProgress = false;
+ if(restartIOHandling) streamStart();
+ }
+
+ /**
+ * needmore from the ASProducer interface (AudioSubSystem)
+ */
+ void needMore()
+ {
+ _node()->requireFlow();
+ }
+
+};
+
+REGISTER_IMPLEMENTATION(Synth_PLAY_impl);
+
+}
+// vim: sw=4 ts=4 noet
diff --git a/flow/synth_play_wav_impl.cc b/flow/synth_play_wav_impl.cc
new file mode 100644
index 0000000..d94703c
--- /dev/null
+++ b/flow/synth_play_wav_impl.cc
@@ -0,0 +1,579 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "config.h"
+#ifdef HAVE_LIBAUDIOFILE
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+#include "cachedwav.h"
+#include "convert.h"
+#include <stdio.h>
+#include <iostream>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" {
+/* Some versions of libaudiofile seem to lack the extern "C" declaration,
+ * so you you may need that extra one.
+ *
+ * Other versions of libaudiofile seem to have two closing "}" in aupvlist.h,
+ * so if you can't compile, this, check that /usr/include/aupvlist.h contains
+ * something like that
+ *
+ * #ifdef __cplusplus
+ * }
+ * #endif
+ *
+ * only once not twice.
+ */
+#include "audiofile.h"
+}
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace std;
+using namespace Arts;
+
+
+CachedWav *CachedWav::load(Cache *cache, string filename)
+{
+ CachedWav *wav;
+
+ wav = (CachedWav *)cache->get(string("CachedWav:")+filename);
+ if(!wav) {
+ wav = new CachedWav(cache,filename);
+
+ if(!wav->initOk) // loading failed
+ {
+ wav->decRef();
+ return 0;
+ }
+ }
+
+ return(wav);
+}
+
+bool CachedWav::isValid()
+{
+ if(!initOk)
+ return false;
+
+ struct stat newstat;
+
+ lstat(filename.c_str(),&newstat);
+ return(newstat.st_mtime == oldstat.st_mtime);
+}
+
+int CachedWav::memoryUsage()
+{
+ return(bufferSize);
+}
+
+CachedWav::CachedWav(Cache *cache, string filename) : CachedObject(cache),
+ filename(filename),initOk(false), buffer(0)
+{
+ int sampleFormat;
+ AFframecount frameCount;
+ AFfilehandle file;
+
+ setKey(string("CachedWav:")+filename);
+
+ if(lstat(filename.c_str(),&oldstat) == -1)
+ {
+ arts_info("CachedWav: Can't stat file '%s'", filename.c_str());
+ return;
+ }
+
+ file = afOpenFile(filename.c_str(), "r", NULL);
+ if(!file)
+ {
+ arts_info("CachedWav: Can't read file '%s'", filename.c_str());
+ return;
+ }
+
+ frameCount = afGetFrameCount(file, AF_DEFAULT_TRACK);
+ if(frameCount <= 0 || frameCount >= INT_MAX)
+ {
+ arts_info("CachedWav: Invalid length for '%s'", filename.c_str());
+ afCloseFile(file);
+ return;
+ }
+
+ channelCount = afGetChannels(file, AF_DEFAULT_TRACK);
+ afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);
+
+ // we want everything converted to little endian unconditionally
+ afSetVirtualByteOrder(file,AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN);
+
+ arts_debug("loaded wav %s",filename.c_str());
+ arts_debug(" sample format: %d, sample width: %d",
+ sampleFormat,sampleWidth);
+ arts_debug(" channelCount: %d",channelCount);
+ arts_debug(" frameCount: %d",frameCount);
+
+ // different handling required for other sample widths
+ assert(sampleWidth == 16 || sampleWidth == 8);
+
+ long frameSize = (sampleWidth/8)*channelCount;
+ samplingRate = afGetRate(file, AF_DEFAULT_TRACK);
+
+ /*
+ * if we don't know the track bytes, we'll have to figure out ourselves
+ * how many frames are stored here - it would be nicer if libaudiofile
+ * let us know somehow whether the value returned for getFrameCount
+ * means "don't know" or is really the correct length
+ */
+ int trackBytes = afGetTrackBytes(file, AF_DEFAULT_TRACK);
+ if(trackBytes == -1)
+ {
+ arts_debug("unknown length");
+ long fcount = 0, f = 0;
+
+ list<void *> blocks;
+ do
+ {
+ void *block = malloc(1024 * frameSize);
+
+ f = afReadFrames(file, AF_DEFAULT_TRACK,block,1024);
+ if(f > 0)
+ {
+ fcount += f;
+ blocks.push_back(block);
+ }
+ else
+ {
+ free(block);
+ }
+ } while(f > 0);
+
+ frameCount = fcount;
+ arts_debug("figured out frameCount = %ld", fcount);
+
+ bufferSize = frameCount * frameSize;
+ buffer = new uchar[bufferSize];
+ assert(buffer);
+
+ // reassemble and free the blocks
+ while(!blocks.empty())
+ {
+ void *block = blocks.front();
+ blocks.pop_front();
+
+ f = (fcount>1024)?1024:fcount;
+ memcpy(&buffer[(frameCount-fcount)*frameSize],block,f*frameSize);
+ fcount -= f;
+ }
+ assert(fcount == 0);
+ }
+ else
+ {
+ bufferSize = frameCount * frameSize;
+ buffer = new uchar[bufferSize];
+ assert(buffer);
+
+ afReadFrames(file, AF_DEFAULT_TRACK,buffer,frameCount);
+ }
+
+ afCloseFile(file);
+ initOk = true;
+}
+
+CachedWav::~CachedWav()
+{
+ if(buffer)
+ delete[] buffer;
+}
+
+namespace Arts {
+
+class Synth_PLAY_WAV_impl : public Synth_PLAY_WAV_skel, public StdSynthModule {
+protected:
+ double flpos;
+
+ float _speed;
+ string _filename;
+ bool _finished;
+ CachedWav *cachedwav;
+
+ void unload()
+ {
+ if(cachedwav)
+ {
+ cachedwav->decRef();
+ cachedwav = 0;
+ }
+ }
+
+ void load()
+ {
+ // unload the old file if necessary
+ unload();
+
+ // load the new (which will reset the position)
+ cachedwav = CachedWav::load(Cache::the(), _filename);
+ flpos = 0.0;
+ }
+
+public:
+ float speed() { return _speed; }
+ void speed(float newSpeed) { _speed = newSpeed; }
+
+ string filename() { return _filename; }
+ void filename(const string& filename) { _filename = filename; load(); }
+
+ void finished(bool f)
+ {
+ if(_finished != f)
+ {
+ _finished = f;
+ finished_changed(f);
+ }
+ }
+ bool finished() { return _finished; }
+
+ Synth_PLAY_WAV_impl();
+ ~Synth_PLAY_WAV_impl();
+
+ void streamInit();
+ void calculateBlock(unsigned long samples);
+};
+
+REGISTER_IMPLEMENTATION(Synth_PLAY_WAV_impl);
+
+}
+
+Synth_PLAY_WAV_impl::Synth_PLAY_WAV_impl()
+{
+ cachedwav = 0;
+ _speed = 1.0;
+ _filename = "";
+ _finished = false;
+}
+
+Synth_PLAY_WAV_impl::~Synth_PLAY_WAV_impl()
+{
+ unload();
+}
+
+void Synth_PLAY_WAV_impl::streamInit()
+{
+ finished(false);
+}
+
+void Synth_PLAY_WAV_impl::calculateBlock(unsigned long samples)
+{
+ unsigned long haveSamples = 0;
+
+ if(cachedwav)
+ {
+ double speed = cachedwav->samplingRate / samplingRateFloat * _speed;
+
+ haveSamples = uni_convert_stereo_2float(samples, cachedwav->buffer,
+ cachedwav->bufferSize,cachedwav->channelCount,cachedwav->sampleWidth,
+ left,right,speed,flpos);
+
+ flpos += (double)haveSamples * speed;
+ }
+
+ if(haveSamples != samples)
+ {
+ unsigned long i;
+
+ for(i=haveSamples;i<samples;i++)
+ left[i] = right[i] = 0.0;
+
+ finished(true);
+ }
+
+/*
+ float speed = 0.0;
+ unsigned long haveSamples = 0;
+
+ if(cachedwav)
+ {
+ float allSamples = cachedwav->bufferSize*8 /
+ cachedwav->sampleWidth/cachedwav->channelCount;
+ float fHaveSamples = allSamples - flpos;
+
+ speed = cachedwav->samplingRate / (float)samplingRate * _speed;
+
+ fHaveSamples /= speed;
+ fHaveSamples -= 2.0; // one due to interpolation and another against
+ // rounding errors
+ if(fHaveSamples > 0)
+ {
+ haveSamples = (int)fHaveSamples;
+ if(haveSamples > samples) haveSamples = samples;
+ }
+ }
+
+ if(haveSamples) // something left to play?
+ {
+ if(cachedwav->channelCount == 1)
+ {
+ if(cachedwav->sampleWidth == 16) {
+ interpolate_mono_16le_float(haveSamples,
+ flpos,speed,cachedwav->buffer,left);
+ }
+ else {
+ interpolate_mono_8_float(haveSamples,
+ flpos,speed,cachedwav->buffer,left);
+ }
+ memcpy(right,left,sizeof(float)*haveSamples);
+ }
+ else if(cachedwav->channelCount == 2)
+ {
+ if(cachedwav->sampleWidth == 16) {
+ interpolate_stereo_i16le_2float(haveSamples,
+ flpos,speed,cachedwav->buffer,left,right);
+ }
+ else {
+ interpolate_stereo_i8_2float(haveSamples,
+ flpos,speed,cachedwav->buffer,left,right);
+ }
+ } else {
+ assert(false);
+ }
+
+ flpos += (float)haveSamples * speed;
+ }
+
+ if(haveSamples != samples)
+ {
+ unsigned long i;
+
+ for(i=haveSamples;i<samples;i++)
+ left[i] = right[i] = 0.0;
+
+ _finished = true;
+ }
+*/
+}
+
+
+#if 0
+class Synth_PLAY_WAV :public SynthModule {
+protected:
+ CachedWav *cachedwav;
+
+ unsigned char *buffer;
+ int channelCount;
+ unsigned long bufferSize, position, bytesPerSample;
+
+ // inputs:
+ enum { PROP_FILENAME };
+
+ // outputs:
+ enum { LEFT, RIGHT, DONE };
+
+public:
+ void Initialize();
+ void DeInitialize();
+ void Calculate() { assert(false); }
+ void CalculateBlock(unsigned long samples);
+ string getParams() { return("_filename;left,right,done"); }
+ static void *Creator() { return new Synth_PLAY_WAV; }
+};
+
+ModuleClient MC_Synth_PLAY_WAV(SynthModule::get_MS,"Synth_PLAY_WAV",Synth_PLAY_WAV::Creator);
+
+void Synth_PLAY_WAV::CalculateBlock(unsigned long samples)
+{
+ unsigned long haveSamples = samples;
+ unsigned long remainingSamples;
+
+ remainingSamples = (bufferSize-position)/bytesPerSample;
+ if(haveSamples > remainingSamples) haveSamples = remainingSamples;
+
+ float *left = out[LEFT], *right = out[RIGHT], *done = out[DONE];
+ unsigned long i;
+
+ if(haveSamples)
+ {
+ if(channelCount == 1)
+ {
+ if(bytesPerSample == 2) {
+ convert_mono_16le_float(haveSamples,&buffer[position],left);
+ }
+ else {
+ convert_mono_8_float(haveSamples,&buffer[position],left);
+ }
+ memcpy(right,left,sizeof(float)*haveSamples);
+ }
+ else if(channelCount == 2)
+ {
+ if(bytesPerSample == 2) {
+ convert_stereo_i16le_2float(haveSamples,&buffer[position],
+ left,right);
+ }
+ else {
+ convert_stereo_i8_2float(haveSamples,&buffer[position],
+ left,right);
+ }
+ } else {
+ assert(false);
+ }
+
+ for(i=0;i<haveSamples;i++) done[i] = 0.0;
+
+ position += bytesPerSample*channelCount*haveSamples;
+ }
+
+ for(i=haveSamples;i<samples;i++)
+ {
+ left[i] = right[i] = 0.0; done[i] = 1.0; // ready, kill me ;)
+ }
+}
+
+void Synth_PLAY_WAV::DeInitialize()
+{
+ cachedwav->decRef();
+}
+
+void Synth_PLAY_WAV::Initialize()
+{
+ cachedwav = CachedWav::load(Synthesizer->getCache(),
+ getStringProperty(PROP_FILENAME));
+
+ // may take some speed to access cachedwav every time
+ bufferSize = cachedwav->bufferSize;
+ channelCount = cachedwav->channelCount;
+ buffer = cachedwav->buffer;
+ bytesPerSample = cachedwav->sampleWidth/8;
+
+ haveCalculateBlock = true;
+ position = 0;
+}
+
+class Synth_PLAY_PITCHED_WAV :public SynthModule {
+protected:
+ CachedWav *cachedwav;
+ float flpos;
+
+ // inputs:
+ enum { FREQUENCY,RECFREQUENCY, PROP_FILENAME };
+
+ // outputs:
+ enum { LEFT, RIGHT, DONE };
+
+public:
+ void Initialize();
+ void DeInitialize();
+ void Calculate() { assert(false); }
+ void CalculateBlock(unsigned long samples);
+ string getParams() { return("frequency,recfrequency,_filename;left,right,done"); }
+ static void *Creator() { return new Synth_PLAY_PITCHED_WAV; }
+};
+
+ModuleClient MC_Synth_PLAY_PITCHED_WAV(SynthModule::get_MS,"Synth_PLAY_PITCHED_WAV",Synth_PLAY_PITCHED_WAV::Creator);
+
+void Synth_PLAY_PITCHED_WAV::CalculateBlock(unsigned long samples)
+{
+ float frequency = in[FREQUENCY][0], recfrequency = in[RECFREQUENCY][0];
+ float allSamples = cachedwav->bufferSize*8 /
+ cachedwav->sampleWidth/cachedwav->channelCount;
+ float fHaveSamples = allSamples - flpos;
+ float speed = cachedwav->samplingRate / (float)samplingRate *
+ frequency / recfrequency;
+
+ fHaveSamples /= speed;
+ fHaveSamples -= 2.0; // one due to interpolation and another against
+ // rounding errors
+
+ unsigned long haveSamples;
+
+ if(fHaveSamples < 0)
+ {
+ haveSamples = 0;
+ }
+ else
+ {
+ haveSamples = fHaveSamples;
+ if(haveSamples > samples) haveSamples = samples;
+ }
+
+ float *left = out[LEFT], *right = out[RIGHT], *done = out[DONE];
+ unsigned long i;
+
+ if(haveSamples)
+ {
+ if(cachedwav->channelCount == 1)
+ {
+ if(cachedwav->sampleWidth == 16) {
+ interpolate_mono_16le_float(haveSamples,
+ flpos,speed,cachedwav->buffer,left);
+ }
+ else {
+ interpolate_mono_8_float(haveSamples,
+ flpos,speed,cachedwav->buffer,left);
+ }
+ memcpy(right,left,sizeof(float)*haveSamples);
+ }
+ else if(cachedwav->channelCount == 2)
+ {
+ if(cachedwav->sampleWidth == 16) {
+ interpolate_stereo_i16le_2float(haveSamples,
+ flpos,speed,cachedwav->buffer,left,right);
+ }
+ else {
+ interpolate_stereo_i8_2float(haveSamples,
+ flpos,speed,cachedwav->buffer,left,right);
+ }
+ } else {
+ assert(false);
+ }
+
+ for(i=0;i<haveSamples;i++) done[i] = 0.0;
+
+ flpos += (float)haveSamples * speed;
+ }
+
+ for(i=haveSamples;i<samples;i++)
+ {
+ left[i] = right[i] = 0.0; done[i] = 1.0; // ready, kill me ;)
+ }
+}
+
+void Synth_PLAY_PITCHED_WAV::DeInitialize()
+{
+ cachedwav->decRef();
+}
+
+void Synth_PLAY_PITCHED_WAV::Initialize()
+{
+ cachedwav = CachedWav::load(Synthesizer->getCache(),
+ getStringProperty(PROP_FILENAME));
+
+ haveCalculateBlock = true;
+ flpos = 0.0;
+}
+#endif
+
+#else
+#ifdef __GNUC__
+#warning "No libaudiofile available, that means, you won't be able to play wavs"
+#endif
+#endif
+
diff --git a/flow/synth_record_impl.cc b/flow/synth_record_impl.cc
new file mode 100644
index 0000000..a159bee
--- /dev/null
+++ b/flow/synth_record_impl.cc
@@ -0,0 +1,184 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "debug.h"
+#include "convert.h"
+#include "objectmanager.h"
+#include "audiosubsys.h"
+#include "dispatcher.h"
+#include "iomanager.h"
+#include "flowsystem.h"
+#include "stdsynthmodule.h"
+#include <stdio.h>
+#include <iostream>
+#include <cstring>
+
+#undef DEBUG_WAVEFORM
+#ifdef DEBUG_WAVEFORM
+#include <fstream>
+#endif
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_RECORD_impl : virtual public Synth_RECORD_skel,
+ virtual public ASConsumer,
+ virtual public StdSynthModule
+{
+#ifdef DEBUG_WAVEFORM
+ ofstream plotfile;
+#endif
+protected:
+ AudioSubSystem *as;
+ bool haveSubSys;
+
+ typedef unsigned char uchar;
+
+ unsigned char *inblock;
+ unsigned long maxsamples;
+ unsigned long channels;
+ int format;
+ int bits;
+
+public:
+#ifdef DEBUG_WAVEFORM
+ Synth_RECORD_impl()
+ : plotfile( "/dev/shm/synth_record.plot" )
+ {
+ }
+#endif
+ /*
+ * functions from the SynthModule interface (which is inherited by
+ * SynthPlay)
+ */
+ void streamInit() {
+ as = AudioSubSystem::the();
+
+ channels = as->channels();
+ format = as->format();
+ bits = as->bits();
+ maxsamples = 0;
+ inblock = 0;
+
+ haveSubSys = as->attachConsumer(this);
+ if(!haveSubSys)
+ {
+ arts_info("Synth_RECORD: audio subsystem is already used");
+ return;
+ }
+ }
+
+ void streamEnd() {
+ arts_debug("Synth_RECORD: detaching");
+ if(haveSubSys) as->detachConsumer();
+
+ if(inblock)
+ {
+ delete[] inblock;
+ inblock = 0;
+ }
+ }
+
+ AutoSuspendState autoSuspend()
+ {
+ return static_cast<AutoSuspendState>(asSuspend|asProducer);
+ }
+
+ void calculateBlock(unsigned long samples)
+ {
+ // no audio subsystem, no play
+ if(!as->running() || !haveSubSys) return;
+
+ if(samples > maxsamples)
+ {
+ maxsamples = samples;
+
+ if(inblock) delete[] inblock;
+ inblock = new uchar[maxsamples * channels * bits / 8];
+ }
+
+ assert(channels);
+
+ as->read(inblock,channels * (bits/8) * samples);
+
+ arts_assert(format == 8 || format == 16 || format == 17 || format == 32);
+ if(format == 8)
+ {
+ if(channels == 1)
+ convert_mono_8_float(samples,inblock,left);
+
+ if(channels == 2)
+ convert_stereo_i8_2float(samples,inblock,left,right);
+ }
+ else if(format == 16)
+ {
+ if(channels == 1)
+ convert_mono_16le_float(samples,inblock,left);
+
+ if(channels == 2)
+ convert_stereo_i16le_2float(samples,inblock,left,right);
+ }
+ else if(format == 17)
+ {
+ if(channels == 1)
+ convert_mono_16be_float(samples,inblock,left);
+
+ if(channels == 2)
+ convert_stereo_i16be_2float(samples,inblock,left,right);
+ }
+ else if(format == 32)
+ {
+ if(channels == 2)
+ {
+ float * end = (float *)(inblock + 8 * samples);
+ float * floatbuffer = (float *)inblock;
+ while(floatbuffer < end)
+ {
+#ifdef DEBUG_WAVEFORM
+ plotfile << *floatbuffer << "\n";
+#endif
+ *left++ = *floatbuffer++;
+ *right++ = *floatbuffer++;
+ }
+ }
+ else if(channels == 1)
+ memcpy(left, inblock, samples);
+ }
+ }
+
+ /**
+ * havemore from the ASConsumer interface (AudioSubSystem)
+ */
+ void haveMore()
+ {
+ _node()->requireFlow();
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_RECORD_impl);
+
+}
+
+// vim: sw=4 ts=4
diff --git a/flow/synth_wave_sin_impl.cc b/flow/synth_wave_sin_impl.cc
new file mode 100644
index 0000000..62e2f03
--- /dev/null
+++ b/flow/synth_wave_sin_impl.cc
@@ -0,0 +1,44 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include <math.h>
+
+using namespace Arts;
+
+namespace Arts {
+
+class Synth_WAVE_SIN_impl : virtual public Synth_WAVE_SIN_skel,
+ virtual public StdSynthModule
+{
+public:
+ void calculateBlock(unsigned long cycles)
+ {
+ for(unsigned long i=0; i<cycles; i++)
+ outvalue[i] = sin(pos[i]*2*M_PI);
+ }
+};
+
+REGISTER_IMPLEMENTATION(Synth_WAVE_SIN_impl);
+
+}
diff --git a/flow/synthschedule.h b/flow/synthschedule.h
new file mode 100644
index 0000000..f44667a
--- /dev/null
+++ b/flow/synthschedule.h
@@ -0,0 +1,36 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef SYNTHSCHEDULE_H
+#define SYNTHSCHEDULE_H
+
+#include "config.h"
+
+#ifdef __GNUC__
+#warning " * <synthschedule.h> included! *"
+#warning " * include <gslschedule.h> instead *"
+#endif
+
+#include "gslschedule.h"
+
+#endif // SYNTHSCHEDULE_H
+
diff --git a/flow/virtualports.cc b/flow/virtualports.cc
new file mode 100644
index 0000000..76b5087
--- /dev/null
+++ b/flow/virtualports.cc
@@ -0,0 +1,491 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "virtualports.h"
+#include <algorithm>
+#include <stdio.h>
+
+using namespace Arts;
+using namespace std;
+
+#undef VPORT_DEBUG
+
+/* virtual port connections */
+
+/*
+
+Port virtualization is used in the following case: suppose you have a module
+M which has an input port and an output port like that:
+
+input
+ V
+-----
+ M
+-----
+ V
+output
+
+But suppose the module M is implement as combination of other modules, for
+instance the effect of M is achieved by passing the signal first through an
+A and then through an B module. Clients connecting M should "really" connect
+A,B. For this virtualization is used.
+
+There are two kinds:
+
+- masquerading: which means (like in our case), the input of a module is really
+ implemented with the input of another module. So M's input could be really
+ implemented by A's input
+
+ there is also output masquerading, which would be for instance that M's
+ output is really implemented by B's output
+
+- forwarding: if M in our example would choose to do nothing at all, it could
+ simply forward its input to its output
+
+
+The interface for the user:
+
+MCOP will show the virtualize function to the user, which the user can use
+to delegate the services of a port to another module onto another port.
+
+- masquerading: in our case, for instance the user could call
+
+ m._node()->virtualize("inputport",a._node(),"inputport");
+
+ which would forward all input m gets on "inputport" to a's "inputport"
+
+- forwarding: in the same way, the user could call
+
+ m._node()->virtualize("inputport",m._node(),"outputport");
+
+ which would make m forward its input directly to its output
+
+The implementation:
+
+Virtualization is implemented here, inside the flow system, using a fairly
+complex forwarding strategy, which will have a graph which contains
+
+- "user-made" connections (made with connect())
+- "virtualize-made" connections, which can be either forwarding
+ (input to output port) or masquerading (input to input or output to output)
+
+Out of all these, the algorithm builds "real" connections, which are
+then really performed inside the flow system. If you change the "user-made"
+or "virtualize-made" connections, the "real" connections are recalculated.
+
+The "real" connections are created by the expandHelper function. They are
+called vcTransport here.
+
+The strategy expandHelper uses is to go back to a port which is only output
+port (non forwarded, non masqueraded), and then follow the graph recursively
+over vcMasquerade and vcForward edges until it reaches a port which is only
+input. Then it creates a real connection.
+
+Some tweaks are there which allow that not on any change at the graph, all
+real connections will be removed, but only these that could possibly be
+affected by this change, and then not all real connections are created new,
+but only those that could possibly be created by this virtual connection.
+
+Every VPort contains a pointer to the "real" port, to let the flow system
+know where the "real" connections where real data will flow must be made.
+
+*/
+
+VPortConnection::VPortConnection(VPort *source, VPort *dest, Style style)
+ :source(source),dest(dest),style(style)
+{
+ if(style != vcTransport)
+ {
+ list<VPortConnection *>::iterator i;
+
+ // remove transport connections ending at "source" (they will
+ // probably be forwarded/masqueraded elsewhere by this VPortConnection)
+ i = source->incoming.begin();
+ while(i != source->incoming.end())
+ {
+ if((*i)->style == vcTransport)
+ {
+ delete *i;
+ i = source->incoming.begin();
+ }
+ else i++;
+ }
+
+ // remove transport connections starting at "dest" (they will
+ // probably be forwarded/masqueraded elsewhere by this VPortConnection)
+ i = dest->outgoing.begin();
+ while(i != dest->outgoing.end())
+ {
+ if((*i)->style == vcTransport)
+ {
+ delete *i;
+ i = dest->outgoing.begin();
+ }
+ else i++;
+ }
+ }
+
+ // add to the connection lists
+ source->outgoing.push_back(this);
+ dest->incoming.push_back(this);
+
+ if(style == vcTransport)
+ {
+#ifdef VPORT_DEBUG
+ arts_debug("emit a connection consumer = %s, producer = %s",
+ dest->name(), source->name());
+#endif
+ dest->port->connect(source->port);
+ }
+ else
+ {
+ source->makeTransport(this);
+ }
+}
+
+VPortConnection::~VPortConnection()
+{
+#ifdef VPORT_DEBUG
+ cout << "~VPortConnection" << endl;
+#endif
+
+ if(style != vcTransport)
+ {
+ // remove transport connection which go through this connection
+ source->removeTransport(this);
+ }
+
+ // remove this connection from the lists
+ list<VPortConnection *>::iterator ci;
+
+ ci = find(source->outgoing.begin(),source->outgoing.end(),this);
+ assert(ci != source->outgoing.end());
+ source->outgoing.erase(ci);
+
+ ci = find(dest->incoming.begin(),dest->incoming.end(),this);
+ assert(ci != dest->incoming.end());
+ dest->incoming.erase(ci);
+
+ if(style == vcTransport)
+ {
+#ifdef VPORT_DEBUG
+ arts_debug("delete connection %s -> %s",dest->name(), source->name());
+#endif
+ dest->port->disconnect(source->port);
+ }
+
+ // reestablish all connections which started/ended here before
+ if(style != vcTransport)
+ {
+ list<VPortConnection *>::iterator i;
+ stack<VPortConnection *> todo;
+
+ // reestablish transport connections which were ending at source...
+ for(i = source->incoming.begin(); i != source->incoming.end(); i++)
+ if((*i)->style != vcTransport) todo.push(*i);
+
+ // ... and starting at dest
+ for(i = dest->outgoing.begin(); i != dest->outgoing.end(); i++)
+ if((*i)->style != vcTransport) todo.push(*i);
+
+ // we need to do this with the stack as makeTransport can affect the
+ // incoming/outgoing lists by adding new vcTransport connections
+ while(!todo.empty())
+ {
+ todo.top()->source->makeTransport(todo.top());
+ todo.pop();
+ }
+ }
+
+#ifdef VPORT_DEBUG
+ cout << "~VPortConnection done" << endl;
+#endif
+}
+
+/*---------------------- virtual port implementation ----------------------*/
+
+VPort::VPort(Port *port) :port(port)
+{
+#ifdef VPORT_DEBUG
+ cout << "VPort: " << name() << endl;
+#endif
+}
+
+VPort::~VPort()
+{
+#ifdef VPORT_DEBUG
+ cout << "~VPort: " << name() << endl;
+#endif
+ while(!incoming.empty()) delete *incoming.begin();
+ while(!outgoing.empty()) delete *outgoing.begin();
+#ifdef VPORT_DEBUG
+ cout << "~VPort done" << endl;
+#endif
+}
+
+bool VPort::makeVirtualizeParams(VPort *forward, VPort*& source, VPort*& dest,
+ VPortConnection::Style& style)
+{
+ source = dest = 0;
+ // masquerading
+ if((port->flags() & streamIn) && (forward->port->flags() & streamIn))
+ {
+ // input: data flow direction is from us to the "forward" port
+ // XXX?
+ source = this;
+ dest = forward;
+ style = VPortConnection::vcMasquerade;
+ }
+ else if((port->flags() & streamOut) && (forward->port->flags() & streamOut))
+ {
+ // output: data flow direction is from the "forward" port to us
+ // XXX?
+ source = forward;
+ dest = this;
+ style = VPortConnection::vcMasquerade;
+ }
+ // forwarding
+ else if((port->flags() & streamIn) && (forward->port->flags() & streamOut))
+ {
+ source = this;
+ dest = forward;
+ style = VPortConnection::vcForward;
+ }
+ else if((port->flags() & streamOut) && (forward->port->flags() & streamIn))
+ {
+ source = forward;
+ dest = this;
+ style = VPortConnection::vcForward;
+ }
+ return source != 0;
+}
+
+/**
+ * a->virtualize(b) means, that the functionality that port a should provide
+ * (e.g. produce or consume data) is really provided by port b
+ */
+void VPort::virtualize(VPort *forward)
+{
+ VPort *source, *dest;
+ VPortConnection::Style style;
+
+ if(makeVirtualizeParams(forward,source,dest,style))
+ {
+#ifdef VPORT_DEBUG
+ cout << "virtualize ... source (producer) is " << source->name() <<
+ " dest (consumer) is " << dest->name() << endl;
+#endif
+ new VPortConnection(source,dest,style);
+ }
+}
+
+void VPort::devirtualize(VPort *forward)
+{
+ VPort *source, *dest;
+ VPortConnection::Style style;
+
+ // XXX?
+ if(makeVirtualizeParams(forward,source,dest,style))
+ {
+ list<VPortConnection *>::iterator i;
+ for(i = source->outgoing.begin(); i != source->outgoing.end(); i++)
+ {
+ if((*i)->source == source && (*i)->dest == dest
+ && (*i)->style == style)
+ {
+ delete (*i);
+ return;
+ }
+ }
+ }
+}
+
+void VPort::setFloatValue(float value)
+{
+ if(outgoing.empty())
+ {
+ AudioPort *aport = port->audioPort();
+ assert(aport);
+ aport->setFloatValue(value);
+ }
+ else
+ {
+ list<VPortConnection *>::iterator i;
+ for(i=outgoing.begin();i != outgoing.end(); i++)
+ {
+ VPortConnection *conn = *i;
+ assert(conn->style == VPortConnection::vcMasquerade);
+
+ conn->dest->setFloatValue(value);
+ }
+ }
+}
+
+void VPort::connect(VPort *dest)
+{
+ VPortConnection *conn;
+ if(port->flags() & streamOut)
+ {
+ conn = new VPortConnection(this,dest,VPortConnection::vcConnect);
+ }
+ else
+ {
+ conn = new VPortConnection(dest,this,VPortConnection::vcConnect);
+ }
+}
+
+void VPort::disconnect(VPort *dest)
+{
+ if(port->flags() & streamOut)
+ {
+ list<VPortConnection *>::iterator ci = outgoing.begin();
+ while(ci != outgoing.end())
+ {
+ assert((*ci)->source == this);
+ if((*ci)->dest == dest && (*ci)->style==VPortConnection::vcConnect)
+ {
+ delete (*ci); // will remove itself from the outgoing list
+ return;
+ }
+ ci++;
+ }
+ }
+ else
+ {
+ if(dest->port->flags() & streamOut)
+ {
+ dest->disconnect(this);
+ return;
+ }
+ }
+}
+
+void VPort::expandHelper(VPortConnection *conn, int state, VPort *current,
+ VPort *source, VPort *dest, bool remove)
+{
+ list<VPortConnection *>::iterator ci;
+
+#ifdef VPORT_DEBUG
+ cout << "expandhelper state " << state << " name " << current->name() << endl;
+#endif
+
+ if(state == 1) /* state 1: scan backward for output ports */
+ {
+ if(current->incoming.empty())
+ {
+ if(current->port->flags() & streamOut)
+ expandHelper(conn,2,current,current,dest,remove);
+ }
+ for(ci = current->incoming.begin(); ci != current->incoming.end();ci++)
+ {
+ assert((*ci)->style != VPortConnection::vcTransport);
+ expandHelper(conn,1,(*ci)->source,source,dest,remove);
+ }
+ }
+ else if(state == 2) /* state 2: output port expansion */
+ {
+ assert(current->port->flags() & streamOut);
+
+ for(ci = current->outgoing.begin(); ci != current->outgoing.end();ci++)
+ {
+ /* xconn=0 ensures that only paths are counted which contain conn */
+ VPortConnection *xconn = conn;
+ if(*ci == conn) xconn = 0;
+
+ if((*ci)->style == VPortConnection::vcMasquerade)
+ {
+ expandHelper(xconn,2,(*ci)->dest,source,dest,remove);
+ }
+ else if((*ci)->style == VPortConnection::vcConnect)
+ {
+ expandHelper(xconn,3,(*ci)->dest,source,(*ci)->dest,remove);
+ }
+ }
+ }
+ else if(state == 3) /* state 3: input port expansion */
+ {
+ assert(current->port->flags() & streamIn);
+
+ for(ci = current->outgoing.begin(); ci != current->outgoing.end();ci++)
+ {
+ /* xconn=0 ensures that only paths are counted which contain conn */
+ VPortConnection *xconn = conn;
+ if(*ci == conn) xconn = 0;
+
+ if((*ci)->style == VPortConnection::vcMasquerade)
+ {
+ // XXX ?
+ expandHelper(xconn,3,(*ci)->dest,source,(*ci)->dest,remove);
+ }
+ else if((*ci)->style == VPortConnection::vcForward)
+ {
+ expandHelper(xconn,2,(*ci)->dest,source,dest,remove);
+ }
+ }
+
+ if(current->outgoing.empty() && conn == 0)
+ {
+ if(remove)
+ {
+ // delete exactly one transport connection
+
+ bool removeOk = false;
+ ci = current->incoming.begin();
+ while(ci != current->incoming.end() && !removeOk)
+ {
+ if((*ci)->source == source && (*ci)->dest == dest
+ && (*ci)->style == VPortConnection::vcTransport)
+ {
+ delete (*ci);
+ removeOk = true;
+ }
+ else ci++;
+ }
+ assert(removeOk);
+ }
+ else
+ {
+ new VPortConnection(source,dest,VPortConnection::vcTransport);
+ }
+ }
+ }
+}
+
+void VPort::makeTransport(VPortConnection *conn)
+{
+ expandHelper(conn,1,this,0,0,false);
+}
+
+void VPort::removeTransport(VPortConnection *conn)
+{
+ expandHelper(conn,1,this,0,0,true);
+}
+
+const char *VPort::name()
+{
+ if(_name.empty())
+ {
+ _name = port->parent->object()->_interfaceName() + "." +
+ port->name();
+ }
+ return _name.c_str();
+}
diff --git a/flow/virtualports.h b/flow/virtualports.h
new file mode 100644
index 0000000..5e70fbf
--- /dev/null
+++ b/flow/virtualports.h
@@ -0,0 +1,87 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+
+#ifndef VIRTUALPORTS_H
+#define VIRTUALPORTS_H
+
+#include "gslschedule.h"
+#include <list>
+
+/*
+ * BC - Status (2002-03-08): VPortConnection, VPort.
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of libartsflow's
+ * StdFlowSystem, and subject to change with the needs of it.
+ */
+
+namespace Arts {
+
+class VPortConnection {
+private:
+ friend class VPort;
+ VPort *source;
+ VPort *dest;
+
+public:
+ enum Style { vcForward, vcMasquerade, vcConnect, vcTransport } style;
+ VPortConnection(VPort *source, VPort *dest, Style style);
+ ~VPortConnection();
+};
+
+class VPort {
+private:
+ friend class VPortConnection;
+protected:
+ Port *port;
+ std::string _name;
+ std::list<VPortConnection *> incoming, outgoing;
+
+ void makeTransport(VPortConnection *conn);
+ void removeTransport(VPortConnection *conn);
+ void expandHelper(VPortConnection *conn, int state, VPort *current,
+ VPort *source, VPort *dest, bool remove);
+
+ bool makeVirtualizeParams(VPort *forward, VPort *& source, VPort *& dest,
+ VPortConnection::Style &style);
+
+ const char *name();
+public:
+ VPort(Port *p);
+ ~VPort();
+
+ void setFloatValue(float value);
+
+ void connect(VPort *vport);
+ void disconnect(VPort *port);
+
+ /**
+ * a->virtualize(b) means that the functionality that port a should provide
+ * (produce or consume data) is really provided by port b
+ */
+ void virtualize(VPort *port);
+ void devirtualize(VPort *port);
+};
+}
+
+#endif /* VIRTUALPORTS_H */
diff --git a/gmcop/Makefile.am b/gmcop/Makefile.am
new file mode 100644
index 0000000..2d86b41
--- /dev/null
+++ b/gmcop/Makefile.am
@@ -0,0 +1,10 @@
+lib_LTLIBRARIES = libgmcop.la
+
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop $(GLIB_CFLAGS) $(all_includes)
+
+libgmcop_la_SOURCES = giomanager.cc
+libgmcop_la_LIBADD = $(top_builddir)/mcop/libmcop.la $(GLIB_LIBADD)
+libgmcop_la_LDFLAGS = -no-undefined -version-info 1:0 $(GLIB_LDFLAGS) $(all_libraries)
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = giomanager.h
diff --git a/gmcop/giomanager.cc b/gmcop/giomanager.cc
new file mode 100644
index 0000000..2518008
--- /dev/null
+++ b/gmcop/giomanager.cc
@@ -0,0 +1,506 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+
+#include "giomanager.h"
+#include "notification.h"
+#include "debug.h"
+#include "dispatcher.h"
+#include <glib.h>
+
+using namespace Arts;
+using namespace std;
+
+/*
+ * Fallback for the case where we should perform blocking
+ */
+namespace Arts {
+class GIOManagerBlocking : public StdIOManager {
+public:
+ void setLevel(int newLevel) { level = newLevel; }
+};
+}
+
+namespace Arts {
+ struct GIOManagerSource
+ {
+ GSource source;
+ GIOManager *ioManager;
+ };
+ struct GIOWatch
+ {
+ GPollFD gpollfd; /* <- must be the first data member */
+
+ /* GPollFD =
+ gint fd;
+ gushort events;
+ gushort revents;
+ */
+ GIOWatch(GIOManagerSource *source, int fd, int types, IONotify *notify)
+ : types(types), registered(false), notify(notify), source(source)
+ {
+ gpollfd.fd = fd;
+ setTypes(types);
+ }
+ void setTypes(int types)
+ {
+ this->types = types;
+ gpollfd.events = gpollfd.revents = 0;
+
+ if(types & IOType::read)
+ gpollfd.events |= G_IO_IN | G_IO_HUP;
+ if(types & IOType::write)
+ gpollfd.events |= G_IO_OUT;
+ if(types & IOType::except)
+ gpollfd.events |= G_IO_ERR;
+
+ }
+ /* prepares source for running in event loop level "level"
+ * removes source unconditionally if level == -1
+ */
+ void prepare(int level)
+ {
+ gpollfd.revents = 0;
+
+ bool shouldRegister = true;
+ if(level != 1 && (types & IOType::reentrant) == 0)
+ shouldRegister = false;
+ if(level == -1)
+ shouldRegister = false;
+
+ if(shouldRegister == registered)
+ return;
+
+ if(shouldRegister)
+ {
+ g_source_add_poll(&source->source, &this->gpollfd);
+ }
+ else
+ {
+ g_source_remove_poll(&source->source, &this->gpollfd);
+ }
+
+ registered = shouldRegister;
+ }
+ int check()
+ {
+ int result = 0;
+
+ if(gpollfd.revents & (G_IO_IN | G_IO_HUP))
+ result |= IOType::read;
+ if(gpollfd.revents & G_IO_OUT)
+ result |= IOType::write;
+ if(gpollfd.revents & G_IO_ERR)
+ result |= IOType::except;
+
+ return result;
+ }
+ void destroy()
+ {
+ /* TODO: if active do this, else do that */
+ delete this;
+ }
+ ~GIOWatch()
+ {
+ prepare(-1);
+ }
+
+ int types;
+ bool registered;
+ IONotify *notify;
+ GIOManagerSource *source;
+ };
+
+class GIOTimeWatch {
+ int milliseconds;
+ TimeNotify *_notify;
+ timeval nextNotify;
+ bool active, destroyed;
+public:
+ GIOTimeWatch(int milliseconds, TimeNotify *notify)
+ : milliseconds(milliseconds), _notify(notify),
+ active(false),destroyed(false)
+ {
+ gettimeofday(&nextNotify,0);
+
+ nextNotify.tv_usec += (milliseconds%1000)*1000;
+ nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000);
+ nextNotify.tv_usec %= 1000000;
+ }
+ int msUntilNextNotify(const timeval& now)
+ {
+ int result = (nextNotify.tv_sec - now.tv_sec)*1000
+ + (nextNotify.tv_usec - now.tv_usec)/1000;
+
+ if(result < 0) result = 0;
+ return result;
+ }
+ void advance(const timeval& currentTime)
+ {
+ active = true;
+ while(msUntilNextNotify(currentTime) == 0)
+ {
+ nextNotify.tv_usec += (milliseconds%1000)*1000;
+ nextNotify.tv_sec += (milliseconds/1000)
+ +(nextNotify.tv_usec/1000000);
+ nextNotify.tv_usec %= 1000000;
+
+ _notify->notifyTime();
+
+ if(destroyed)
+ {
+ delete this;
+ return;
+ }
+ }
+ active = false;
+ }
+ void destroy()
+ {
+ if(active)
+ {
+ destroyed = true;
+ }
+ else
+ {
+ delete this;
+ }
+ }
+ TimeNotify *notify()
+ {
+ return _notify;
+ }
+};
+
+static gboolean GIOManager_prepare(GSource *source, gint *timeout)
+{
+ return((GIOManagerSource *)source)->ioManager->prepare(timeout);
+}
+
+static gboolean GIOManager_check(GSource *source)
+{
+ return((GIOManagerSource *)source)->ioManager->check();
+}
+
+static gboolean GIOManager_dispatch(GSource *source, GSourceFunc callback,
+ gpointer user_data)
+{
+ return((GIOManagerSource *)source)->ioManager->dispatch(callback,user_data);
+}
+
+
+}
+
+GIOManager::GIOManager(GMainContext *context)
+ : level(0), context(context)
+{
+ static GSourceFuncs funcs =
+ {
+ GIOManager_prepare,
+ GIOManager_check,
+ GIOManager_dispatch,
+ 0
+ };
+
+ source = (GIOManagerSource *)g_source_new(&funcs, sizeof(GIOManagerSource));
+ source->ioManager = this;
+ g_source_set_can_recurse(&source->source, true);
+ g_source_attach(&source->source, context);
+
+ gioManagerBlocking = new GIOManagerBlocking();
+ _blocking = true;
+ fileDescriptorsNeedRecheck = false;
+}
+
+GIOManager::~GIOManager()
+{
+ g_source_unref(&source->source);
+ delete gioManagerBlocking;
+}
+
+void GIOManager::processOneEvent(bool blocking)
+{
+ if(_blocking)
+ {
+ level++;
+ if(level == 1)
+ Dispatcher::lock();
+
+ /*
+ * we explicitly take the level to gioManagerBlocking, so that it
+ * will process reentrant watchFDs only
+ */
+ fileDescriptorsNeedRecheck = true;
+ gioManagerBlocking->setLevel(level);
+ gioManagerBlocking->processOneEvent(blocking);
+
+ if(level == 1)
+ Dispatcher::unlock();
+ level--;
+ }
+ else
+ {
+ g_main_context_iteration(context, blocking);
+ }
+}
+
+void GIOManager::setBlocking(bool blocking)
+{
+ _blocking = blocking;
+}
+
+void GIOManager::run()
+{
+ arts_warning("GIOManager::run not implemented yet");
+}
+
+void GIOManager::terminate()
+{
+ arts_warning("GIOManager::terminate not implemented yet");
+}
+
+void GIOManager::watchFD(int fd, int types, IONotify * notify)
+{
+ fdList.push_back(new GIOWatch(source, fd, types, notify));
+
+ if(types & IOType::reentrant)
+ gioManagerBlocking->watchFD(fd, types, notify);
+}
+
+void GIOManager::remove(IONotify *notify, int types)
+{
+ list<GIOWatch *>::iterator i;
+
+ i = fdList.begin();
+ while(i != fdList.end())
+ {
+ GIOWatch *w = *i;
+
+ if(w->notify == notify)
+ {
+ int newTypes = w->types & (~types);
+
+ if(newTypes)
+ {
+ w->setTypes(newTypes);
+ }
+ else
+ {
+ w->destroy();
+ fdList.erase(i);
+ i = fdList.begin();
+ }
+ }
+ else i++;
+ }
+ gioManagerBlocking->remove(notify, types);
+}
+
+void GIOManager::addTimer(int milliseconds, TimeNotify *notify)
+{
+ timeList.push_back(new GIOTimeWatch(milliseconds,notify));
+}
+
+void GIOManager::removeTimer(TimeNotify *notify)
+{
+ list<GIOTimeWatch *>::iterator i;
+
+ i = timeList.begin();
+ while(i != timeList.end())
+ {
+ GIOTimeWatch *w = *i;
+
+ if(w->notify() == notify)
+ {
+ w->destroy();
+ timeList.erase(i);
+ i = timeList.begin();
+ }
+ else i++;
+ }
+}
+
+gboolean GIOManager::prepare(gint *timeout)
+{
+ *timeout = 10000;
+
+ level++;
+
+ if(level == 1)
+ Dispatcher::lock();
+
+ /* handle timers - only at level 1 */
+ if(level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<GIOTimeWatch *>::iterator ti;
+
+ ti = timeList.begin();
+ while(ti != timeList.end())
+ {
+ GIOTimeWatch *w = *ti++;
+ int ms = w->msUntilNextNotify(currenttime);
+
+ if(ms < *timeout) *timeout = ms;
+ }
+ }
+
+ list<GIOWatch *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++)
+ {
+ GIOWatch *w = *i;
+ w->prepare(level);
+ }
+ fileDescriptorsNeedRecheck = false;
+
+ if(level == 1 && NotificationManager::the()->pending())
+ *timeout = 0;
+
+ if(level == 1)
+ Dispatcher::unlock();
+
+ level--;
+
+ return (*timeout == 0);
+}
+
+gboolean GIOManager::check()
+{
+ gboolean result = false;
+ level++;
+
+ if(level == 1)
+ Dispatcher::lock();
+
+ /*
+ * handle timers - only at level 1
+ */
+ if(level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<GIOTimeWatch *>::iterator ti;
+
+ ti = timeList.begin();
+ while(ti != timeList.end() && !result)
+ {
+ GIOTimeWatch *w = *ti++;
+ if(w->msUntilNextNotify(currenttime) == 0)
+ result = true;
+ }
+ }
+
+ /*
+ * handle filedescriptors
+ */
+ list<GIOWatch *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++) {
+ GIOWatch *w = *i;
+ int match = w->check();
+
+ if((w->types & IOType::reentrant) == 0 && level != 1)
+ {
+ arts_assert(match == 0);
+ }
+ if(match)
+ {
+ result = true;
+ }
+ }
+ fileDescriptorsNeedRecheck = false;
+
+ /*
+ * check for notifications
+ */
+ if(level == 1 && NotificationManager::the()->pending())
+ result = true;
+
+ if(level == 1)
+ Dispatcher::unlock();
+
+ level--;
+
+ return result;
+}
+
+gboolean GIOManager::dispatch(GSourceFunc /* func */, gpointer /* user_data */)
+{
+ bool done = false;
+
+ level++;
+
+ if(level == 1)
+ Dispatcher::lock();
+
+ // notifications not carried out reentrant
+ if(!done && level == 1 && NotificationManager::the()->pending())
+ {
+ NotificationManager::the()->run();
+ done = true;
+ }
+
+ // handle filedescriptor things
+ if(!done && !fileDescriptorsNeedRecheck)
+ {
+ list<GIOWatch *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++) {
+ GIOWatch *w = *i;
+ int match = w->check();
+
+ if((w->types & IOType::reentrant) == 0 && level != 1)
+ {
+ arts_assert(match == 0);
+ }
+ if(match)
+ {
+ w->notify->notifyIO(w->gpollfd.fd,match);
+ done = true;
+ break;
+ }
+ }
+ }
+
+ // handle timers - only at level 1
+ if(!done && level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<GIOTimeWatch *>::iterator ti;
+
+ ti = timeList.begin();
+ while(ti != timeList.end())
+ {
+ GIOTimeWatch *w = *ti++;
+ w->advance(currenttime);
+ }
+ }
+
+ if(level == 1)
+ Dispatcher::unlock();
+ level--;
+
+ return true;
+}
diff --git a/gmcop/giomanager.h b/gmcop/giomanager.h
new file mode 100644
index 0000000..4a398f8
--- /dev/null
+++ b/gmcop/giomanager.h
@@ -0,0 +1,128 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_GIOMANAGER_H
+#define ARTS_GIOMANAGER_H
+
+#include <glib.h>
+#include <iomanager.h>
+#include <list>
+#include <stack>
+#include <map>
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): GIOManager
+ *
+ * This class will be kept binary compatible (d ptr for extensions).
+ */
+
+namespace Arts {
+
+class GIOWatch;
+class GIOManagerPrivate;
+struct GIOManagerSource;
+class GIOTimeWatch;
+class GIOManagerBlocking;
+
+/**
+ * GIOManager performs MCOP I/O inside the Glib event loop. This way, you will
+ * be able to receive requests and notifications inside Glib application. The
+ * usual way to set it up is:
+ *
+ * <pre>
+ * GMainLoop *main_loop = g_main_new(FALSE); // as usual
+ *
+ * Arts::GIOManager iomanager;
+ * Arts::Dispatcher dispatcher(&iomanager);
+ *
+ * g_main_run(main_loop); // as usual
+ * </pre>
+ */
+class ARTS_EXPORT GIOManager : public IOManager {
+private:
+ GIOManagerPrivate *d;
+
+protected:
+ std::list<GIOWatch *> fdList;
+ std::list<GIOTimeWatch *> timeList;
+ int level;
+ bool _blocking;
+ bool fileDescriptorsNeedRecheck;
+ GMainContext *context;
+ GIOManagerSource *source;
+ GIOManagerBlocking *gioManagerBlocking;
+
+public:
+ GIOManager(GMainContext *context = 0);
+ ~GIOManager();
+
+ void processOneEvent(bool blocking);
+ void run();
+ void terminate();
+ void watchFD(int fd, int types, IONotify *notify);
+ void remove(IONotify *notify, int types);
+ void addTimer(int milliseconds, TimeNotify *notify);
+ void removeTimer(TimeNotify *notify);
+
+ /**
+ * This controls what GIOManager will do while waiting for the result
+ * of an MCOP request, the possibilities are:
+ *
+ * @li block until the request is completed (true)
+ * @li open a local event loop (false)
+ *
+ * It is much easier to write working and reliable code with blocking
+ * enabled, so this is the default. If you disable blocking, you have
+ * to deal with the fact that timers, user interaction and similar
+ * "unpredictable" things will possibly influence your code in all
+ * places where you make a remote MCOP call (which is quite often in
+ * MCOP applications).
+ */
+ void setBlocking(bool blocking);
+
+ /* GSource stuff: */
+
+ /**
+ * - internal -
+ *
+ * (implements the GSource prepare)
+ */
+ gboolean prepare(gint *timeout);
+
+ /**
+ * - internal -
+ *
+ * (implements the GSource check)
+ */
+ gboolean check();
+
+ /**
+ * - internal -
+ *
+ * (implements the GSource dispatch)
+ */
+ gboolean dispatch(GSourceFunc callback, gpointer user_data);
+};
+
+}
+
+#endif /* ARTS_GIOMANAGER_H */
diff --git a/mcop/Makefile.am b/mcop/Makefile.am
new file mode 100644
index 0000000..72fc23b
--- /dev/null
+++ b/mcop/Makefile.am
@@ -0,0 +1,33 @@
+
+AM_CPPFLAGS = -DEXTENSION_DIR='"$(libdir)"' -DTRADER_DIR='"$(libdir)/mcop"'
+##
+lib_LTLIBRARIES = libmcop.la
+#
+# Programs to compile, Manpages to install and Versions
+#
+INCLUDES = -I$(top_srcdir)/libltdl $(all_includes)
+libmcop_la_SOURCES = buffer.cc connection.cc core.cc debug.cc dispatcher.cc \
+ iomanager.cc object.cc socketconnection.cc tcpconnection.cc \
+ unixconnection.cc tcpserver.cc unixserver.cc objectmanager.cc \
+ factory.cc idlfilereg.cc ifacerepo_impl.cc mcoputils.cc \
+ startupmanager.cc md5.c md5auth.cc referenceclean.cc datapacket.cc \
+ asyncstream.cc notification.cc flowsystem.cc extensionloader.cc \
+ tmpglobalcomm.cc mcopconfig.cc connect.cc reference.cc type.cc \
+ trader_impl.cc dynamicrequest.cc anyref.cc loopback.cc \
+ delayedreturn.cc thread.cc dynamicskeleton.cc
+
+libmcop_la_LIBADD = $(LIBSOCKET) $(GLIB_LIBADD) $(top_builddir)/libltdl/libltdlc.la
+libmcop_la_LDFLAGS = -no-undefined -version-info 1:0 $(GLIB_LDFLAGS) $(all_libraries)
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = arts_export.h buffer.h common.h connection.h core.h dispatcher.h \
+ factory.h flowsystem.h idlfilereg.h ifacerepo_impl.h iomanager.h \
+ mcoputils.h object.h objectmanager.h pool.h socketconnection.h \
+ startupmanager.h tcpconnection.h tcpserver.h type.h unixconnection.h \
+ unixserver.h referenceclean.h datapacket.h asyncstream.h notification.h \
+ extensionloader.h mcopconfig.h connect.h reference.h weakreference.h \
+ dynamicrequest.h anyref.h debug.h delayedreturn.h dynamicskeleton.h thread.h \
+ core.idl
+
+core: $(srcdir)/core.idl $(MCOPIDL)
+ $(MCOPIDL) -e Arts::Object -I$(srcdir) $(srcdir)/core.idl
diff --git a/mcop/anyref.cc b/mcop/anyref.cc
new file mode 100644
index 0000000..9ea434b
--- /dev/null
+++ b/mcop/anyref.cc
@@ -0,0 +1,310 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "anyref.h"
+#include "common.h"
+#include "startupmanager.h"
+#include "debug.h"
+#include <assert.h>
+
+using namespace Arts;
+using namespace std;
+
+/*
+ * private utility class to deal with any types
+ */
+namespace Arts {
+ static class AnyRefHelper {
+ private:
+ Arts::InterfaceRepoV2 interfaceRepo;
+
+ public:
+ AnyRefHelper() {
+ interfaceRepo = DynamicCast(Dispatcher::the()->interfaceRepo());
+ }
+ void skipType(Buffer& buffer, const string& type);
+ } *anyRefHelper = 0;
+
+ static class AnyRefHelperStartup : public StartupClass {
+ void startup() {
+ assert(anyRefHelper == 0);
+ anyRefHelper = new AnyRefHelper();
+ }
+ void shutdown() {
+ delete anyRefHelper;
+ anyRefHelper = 0;
+ }
+ } The_AnyRefHelperStartup;
+}
+
+string AnyRefBase::type() const
+{
+/*
+ keep common types here, so that the string constructor doesn't need
+ to get called each and every time
+ */
+ static const string tVoid("void");
+ static const string tByte("byte");
+ static const string tsByte("*byte");
+ static const string tLong("long");
+ static const string tsLong("*long");
+ static const string tFloat("float");
+ static const string tsFloat("*float");
+ static const string tString("string");
+ static const string tsString("*string");
+ static const string tBool("bool");
+ static const string tsBool("*bool");
+
+ switch(rep)
+ {
+ case repVoid: return tVoid;
+
+ // primitive types
+ case repByte: return tByte;
+ case repInt:
+ case repLong: return tLong;
+ case repFloat:
+ case repDouble: return tFloat;
+ case repString:
+ case repCString: return tString;
+ case repBool: return tBool;
+
+ // sequences of primitive types
+ case repByteSeq: return tsByte;
+ case repLongSeq: return tsLong;
+ case repFloatSeq: return tsFloat;
+ case repStringSeq: return tsString;
+ case repBoolSeq: return tsBool;
+
+ case repAny: return ((Any *)data)->type;
+ }
+ assert(false);
+ return tVoid; // silence compiler
+}
+
+void AnyRefBase::_write(Buffer *b) const
+{
+ switch(rep)
+ {
+ case repVoid:
+ break;
+
+ // primitive types
+ case repByte: b->writeByte(*(mcopbyte *)data);
+ break;
+
+ case repInt: b->writeLong(*(int *)data);
+ break;
+
+ case repLong: b->writeLong(*(long *)data);
+ break;
+
+ case repFloat: b->writeFloat(*(float *)data);
+ break;
+
+ case repDouble: b->writeFloat(*(double *)data);
+ break;
+
+ case repString: b->writeString(*(string *)data);
+ break;
+
+ case repCString: b->writeString((const char *)data);
+ break;
+
+ case repBool: b->writeBool(*(bool *)data);
+ break;
+
+ // sequences of primitive types
+ case repByteSeq: b->writeByteSeq(*(vector<mcopbyte> *)data);
+ break;
+
+ case repLongSeq: b->writeLongSeq(*(vector<long> *)data);
+ break;
+
+ case repFloatSeq: b->writeFloatSeq(*(vector<float> *)data);
+ break;
+
+ case repStringSeq: b->writeStringSeq(*(vector<string> *)data);
+ break;
+
+ case repBoolSeq: b->writeBoolSeq(*(vector<bool> *)data);
+ break;
+
+ case repAny: b->write(((Any *)data)->value);
+ break;
+
+ default: assert(false);
+ }
+}
+
+void AnyRefBase::_read(Buffer *b) const
+{
+ switch(rep)
+ {
+ case repVoid:
+ break;
+
+ // primitive types
+ case repByte: *(mcopbyte *)data = b->readByte();
+ break;
+
+ case repInt: *(int *)data = b->readLong();
+ break;
+
+ case repLong: *(long *)data = b->readLong();
+ break;
+
+ case repFloat: *(float *)data = b->readFloat();
+ break;
+
+ case repDouble: *(double *)data = b->readFloat();
+ break;
+
+ case repString: b->readString(*(string *)data);
+ break;
+
+ case repBool: *(bool *)data = b->readBool();
+ break;
+
+ // sequences of primitive types
+ case repByteSeq: b->readByteSeq(*(vector<mcopbyte> *)data);
+ break;
+
+ case repLongSeq: b->readLongSeq(*(vector<long> *)data);
+ break;
+
+ case repFloatSeq: b->readFloatSeq(*(vector<float> *)data);
+ break;
+
+ case repStringSeq: b->readStringSeq(*(vector<string> *)data);
+ break;
+
+ case repBoolSeq: b->readBoolSeq(*(vector<bool> *)data);
+ break;
+
+ case repAny:
+ {
+ // find out the size by skipping over it for the first time
+ long startPos = b->size() - b->remaining();
+ anyRefHelper->skipType(*b, ((Any *)data)->type);
+
+ // if everything went well, read the raw value in one step
+ long size = (b->size() - b->remaining()) - startPos;
+ if(!b->readError())
+ {
+ b->rewind();
+ b->skip(startPos);
+ b->read(((Any *)data)->value, size);
+ }
+ }
+ break;
+
+ default: assert(false);
+ }
+}
+
+/**
+ * correct skipping of an arbitary type not known at compile-time (this is
+ * a problem, since the size of the type will vary, due to the sequence<...>s
+ * contained)
+ */
+void AnyRefHelper::skipType(Buffer& buffer, const string& type)
+{
+ /* sequences */
+ if(type[0] == '*')
+ {
+ long seqlen = buffer.readLong();
+ while(seqlen > 0 && !buffer.readError())
+ {
+ skipType(buffer, type.c_str()+1);
+ seqlen--;
+ }
+ }
+ else
+ {
+ TypeIdentification ti = interfaceRepo.identifyType(type);
+ switch(ti)
+ {
+ case tiString:
+ {
+ string s;
+ buffer.readString(s);
+ }
+ break;
+
+ case tiLong:
+ buffer.readLong();
+ break;
+
+ case tiFloat:
+ buffer.readFloat();
+ break;
+
+ case tiByte:
+ buffer.readByte();
+ break;
+
+ case tiBoolean:
+ buffer.readBool();
+ break;
+
+ case tiVoid:
+ /* nothing to do */
+ break;
+
+ case tiType:
+ {
+ Arts::TypeDef td = interfaceRepo.queryType(type);
+
+ if(td.name == type)
+ {
+ vector<TypeComponent>::iterator tci;
+ for(tci = td.contents.begin(); tci != td.contents.end();
+ tci++)
+ {
+ skipType(buffer,tci->type);
+ }
+ }
+ else
+ {
+ arts_warning("unknown type %s",type.c_str());
+ }
+ }
+ break;
+
+ case tiEnum:
+ buffer.readLong();
+ break;
+
+ case tiInterface:
+ {
+ ObjectReference oref;
+ oref.readType(buffer);
+ }
+ break;
+
+ default:
+ arts_warning("AnyRefHelper: can't read %s",type.c_str());
+ break;
+ }
+ }
+}
diff --git a/mcop/anyref.h b/mcop/anyref.h
new file mode 100644
index 0000000..688f9db
--- /dev/null
+++ b/mcop/anyref.h
@@ -0,0 +1,146 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef MCOP_ANYREF_H
+#define MCOP_ANYREF_H
+
+#include "buffer.h"
+#include <string>
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): AnyRefBase, AnyRef, AnyConstRef
+ *
+ * These classes will be kept binary compatibile. To change it, adding a new
+ * representation is necessary. No private d pointer for this reason.
+ */
+
+namespace Arts {
+
+class Any;
+class ARTS_EXPORT AnyRefBase {
+protected:
+ void *data;
+
+ /*
+ * This is used for specifying which is the content of a sequence or
+ * an enum or similar. For normal types, it remains unset, as their
+ * name can be generated from rep.
+ */
+ std::string _type;
+
+ /*
+ * What representation data is pointing to?
+ *
+ * repInt (int *), repDouble (double *) and repConstChar (const char *)
+ * are no native MCOP types, but alternative ways or representing the
+ * native "int", "float" and "const char *" types
+ */
+
+ // BC: adding new representations and types is possible, however, existing
+ // numbers may not be changed
+ enum Representation {
+ repVoid = 0,
+ repByte = 10,
+ repLong = 20, repInt = 21 /* treated as long */,
+ repFloat = 30, repDouble = 31 /* treated as float */,
+ repString = 40, repCString = 41 /* string */,
+ repBool = 50,
+ repByteSeq = 510,
+ repLongSeq = 520,
+ repFloatSeq = 530,
+ repStringSeq = 540,
+ repBoolSeq = 550,
+ repAny = 1000 /* may hold any type */
+ } rep;
+
+ void _write(Buffer *b) const;
+ void _read(Buffer *b) const;
+
+ AnyRefBase(const void *data, Representation rep)
+ : data(const_cast<void *>(data)), rep(rep) { };
+ AnyRefBase(const void *data, Representation rep, const char *type)
+ : data(const_cast<void *>(data)), _type(type), rep(rep) { };
+ AnyRefBase(const AnyRefBase &copy)
+ : data(copy.data), _type(copy._type), rep(copy.rep) { }
+public:
+ std::string type() const;
+};
+
+class ARTS_EXPORT AnyConstRef : public AnyRefBase {
+public:
+ AnyConstRef() : AnyRefBase(0,repVoid) { };
+ AnyConstRef(const mcopbyte& value) : AnyRefBase(&value,repByte) { };
+ AnyConstRef(const int& value) : AnyRefBase(&value,repInt) { };
+ AnyConstRef(const long& value) : AnyRefBase(&value,repLong) { };
+ AnyConstRef(const float& value) : AnyRefBase(&value,repFloat) { };
+ AnyConstRef(const double& value) : AnyRefBase(&value,repDouble) { };
+ AnyConstRef(const std::string& value) : AnyRefBase(&value,repString) { };
+ AnyConstRef(const char *value) : AnyRefBase(value,repCString) { };
+ AnyConstRef(const bool& value) : AnyRefBase(&value,repBool) { };
+
+ AnyConstRef(const std::vector<mcopbyte>& v)
+ : AnyRefBase(&v,repByteSeq) { };
+ AnyConstRef(const std::vector<long>& v)
+ : AnyRefBase(&v,repLongSeq) { };
+ AnyConstRef(const std::vector<float>& v)
+ : AnyRefBase(&v,repFloatSeq) { };
+ AnyConstRef(const std::vector<std::string>& v)
+ : AnyRefBase(&v,repStringSeq) { };
+ AnyConstRef(const std::vector<bool>& v)
+ : AnyRefBase(&v,repBoolSeq) { };
+
+ AnyConstRef(const Any& value) : AnyRefBase(&value,repAny) { };
+
+ AnyConstRef(const AnyConstRef& ref) : AnyRefBase(ref) { }
+ void write(Buffer *b) const { _write(b); }
+};
+
+class ARTS_EXPORT AnyRef : public AnyRefBase {
+public:
+ AnyRef() : AnyRefBase(0,repVoid) { };
+
+ // primitive types
+ AnyRef(mcopbyte& value) : AnyRefBase(&value,repByte) { };
+ AnyRef(int& value) : AnyRefBase(&value,repInt) { };
+ AnyRef(long& value) : AnyRefBase(&value,repLong) { };
+ AnyRef(float& value) : AnyRefBase(&value,repFloat) { };
+ AnyRef(double& value) : AnyRefBase(&value,repDouble) { };
+ AnyRef(std::string& value) : AnyRefBase(&value,repString) { };
+ AnyRef(bool& value) : AnyRefBase(&value,repBool) { };
+
+ // sequence of primitive types
+ AnyRef(std::vector<mcopbyte>& value) : AnyRefBase(&value,repByteSeq) { };
+ AnyRef(std::vector<long>& value) : AnyRefBase(&value,repLongSeq) { };
+ AnyRef(std::vector<float>& value) : AnyRefBase(&value,repFloatSeq) { };
+ AnyRef(std::vector<std::string>& value) : AnyRefBase(&value,repStringSeq){};
+ AnyRef(std::vector<bool>& value) : AnyRefBase(&value,repBoolSeq){};
+
+ AnyRef(Any& value) : AnyRefBase(&value,repAny) { };
+
+ AnyRef(const AnyRef& ref) : AnyRefBase(ref) { }
+
+ void read(Buffer *b) const { _read(b); }
+ void write(Buffer *b) const { _write(b); }
+};
+
+}
+#endif /* MCOP_ANYREF_H */
diff --git a/mcop/arts_export.h.in b/mcop/arts_export.h.in
new file mode 100644
index 0000000..4de637e
--- /dev/null
+++ b/mcop/arts_export.h.in
@@ -0,0 +1,53 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2002-2003 KDE Team
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef ARTS_EXPORT_H
+#define ARTS_EXPORT_H
+
+#undef __KDE_HAVE_GCC_VISIBILITY
+
+/**
+ * The ARTS_NO_EXPORT macro marks the symbol of the given variable
+ * to be hidden. A hidden symbol is stripped during the linking step,
+ * so it can't be used from outside the resulting library, which is similar
+ * to static. However, static limits the visibility to the current
+ * compilation unit. hidden symbols can still be used in multiple compilation
+ * units.
+ *
+ * \code
+ * int ARTS_NO_EXPORT foo;
+ * int ARTS_EXPORT bar;
+ * \end
+ */
+
+#if defined(__KDE_HAVE_GCC_VISIBILITY)
+/* Visibility is available for GCC newer than 3.4.
+ * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=9283
+ */
+#define ARTS_NO_EXPORT __attribute__ ((visibility("hidden")))
+#define ARTS_EXPORT __attribute__ ((visibility("default")))
+#elif defined(_WIN32)
+#define ARTS_NO_EXPORT
+#define ARTS_EXPORT __declspec(dllexport)
+#else
+#define ARTS_NO_EXPORT
+#define ARTS_EXPORT
+#endif
+
+#endif /* ARTS_EXPORTS */
diff --git a/mcop/asyncstream.cc b/mcop/asyncstream.cc
new file mode 100644
index 0000000..a623353
--- /dev/null
+++ b/mcop/asyncstream.cc
@@ -0,0 +1,46 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "asyncstream.h"
+#include "datapacket.h"
+
+using namespace Arts;
+
+DataPacket<float> *FloatAsyncStream::allocPacket(int capacity)
+{
+ return new FloatDataPacket(capacity,channel);
+}
+
+GenericAsyncStream *FloatAsyncStream::createNewStream()
+{
+ return new FloatAsyncStream();
+}
+
+DataPacket<mcopbyte> *ByteAsyncStream::allocPacket(int capacity)
+{
+ return new ByteDataPacket(capacity,channel);
+}
+
+GenericAsyncStream *ByteAsyncStream::createNewStream()
+{
+ return new ByteAsyncStream();
+}
diff --git a/mcop/asyncstream.h b/mcop/asyncstream.h
new file mode 100644
index 0000000..8d0a603
--- /dev/null
+++ b/mcop/asyncstream.h
@@ -0,0 +1,103 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ASYNCSTREAM_H
+#define ASYNCSTREAM_H
+
+#include "arts_export.h"
+#include "buffer.h"
+#include "datapacket.h"
+
+/*
+ * BC - Status (2002-03-08): GenericAsyncStream, AsyncStream,
+ * FloatAsyncStream/ByteAsyncStream
+ *
+ * These classes are to be treated with extreme care, as they are used in
+ * all kinds of relations with the flow system and the generated code. Do
+ * NOT touch unless you REALLY know what you are doing. For further
+ * extensibility, GenericAsyncStream features a private d pointer.
+ */
+
+namespace Arts {
+
+class GenericAsyncStreamPrivate;
+
+class ARTS_EXPORT GenericAsyncStream {
+private:
+ GenericAsyncStreamPrivate *d; // unused
+public:
+ /**
+ * interface to create packets and to get rid of them
+ */
+ virtual GenericDataPacket *createPacket(int capacity) = 0;
+ virtual void freePacket(GenericDataPacket *packet) = 0;
+
+ virtual GenericAsyncStream *createNewStream() = 0;
+
+ GenericDataChannel *channel;
+ int _notifyID;
+
+ inline int notifyID() { return _notifyID; }
+};
+
+template<class T>
+class AsyncStream : public GenericAsyncStream {
+protected:
+ GenericDataPacket *createPacket(int capacity)
+ {
+ return allocPacket(capacity);
+ }
+ void freePacket(GenericDataPacket *packet)
+ {
+ delete packet;
+ }
+public:
+ // for outgoing streams
+ virtual DataPacket<T> *allocPacket(int capacity) = 0;
+
+ inline void setPull(int packets, int capacity)
+ {
+ channel->setPull(packets,capacity);
+ }
+ inline void endPull()
+ {
+ channel->endPull();
+ }
+};
+
+class ARTS_EXPORT FloatAsyncStream : public AsyncStream<float>
+{
+public:
+ DataPacket<float> *allocPacket(int capacity);
+ GenericAsyncStream *createNewStream();
+};
+
+class ARTS_EXPORT ByteAsyncStream : public AsyncStream<mcopbyte>
+{
+public:
+ DataPacket<mcopbyte> *allocPacket(int capacity);
+ GenericAsyncStream *createNewStream();
+};
+
+}
+
+#endif /* ASYNCSTREAM_H */
diff --git a/mcop/buffer.cc b/mcop/buffer.cc
new file mode 100644
index 0000000..de21b3e
--- /dev/null
+++ b/mcop/buffer.cc
@@ -0,0 +1,386 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "buffer.h"
+#include <assert.h>
+#include <string.h>
+
+using namespace std;
+using namespace Arts;
+
+Buffer::Buffer() : rpos(0), _readError(false),d(0)
+{
+ contents.reserve(128);
+}
+
+Buffer::~Buffer()
+{
+}
+
+long Buffer::size()
+{
+ return contents.size();
+}
+
+long Buffer::remaining()
+{
+ return size()-rpos;
+}
+
+bool Buffer::readError() {
+ return _readError;
+}
+
+void Buffer::writeBool(bool b) {
+ contents.push_back(b?1:0);
+}
+
+void Buffer::writeByte(mcopbyte b) {
+ contents.push_back(b);
+}
+
+void Buffer::writeLong(long l) {
+ contents.push_back((l >> 24) & 0xff);
+ contents.push_back((l >> 16) & 0xff);
+ contents.push_back((l >> 8) & 0xff);
+ contents.push_back(l & 0xff);
+}
+
+void Buffer::writeBoolSeq(const vector<bool>& seq) {
+ writeLong(seq.size());
+
+ vector<bool>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeBool(*i);
+}
+
+void Buffer::writeByteSeq(const vector<mcopbyte>& seq) {
+ writeLong(seq.size()); // bytes are sent raw, so we can call read here
+ write(seq);
+}
+
+void Buffer::writeLongSeq(const vector<long>& seq) {
+ writeLong(seq.size());
+
+ vector<long>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeLong(*i);
+}
+
+void Buffer::writeFloat(float f) {
+ // FIXME: on some machines this may fail badly (there is explicit
+ // float marshalling and demarshalling code in mico/orb/util.cc)
+ union { float f; long l; } u = {f};
+ writeLong(u.l);
+}
+
+void Buffer::writeFloatSeq(const std::vector<float>& seq) {
+ writeLong(seq.size());
+
+ vector<float>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeFloat(*i);
+}
+
+void Buffer::writeString(const string& s) {
+ long len = s.size()+1;
+
+ writeLong(len);
+ contents.insert(contents.end(),reinterpret_cast<const unsigned char*>(s.c_str()),
+ reinterpret_cast<const unsigned char*>(s.c_str()+len));
+}
+
+void Buffer::writeStringSeq(const vector<string>& seq) {
+ writeLong(seq.size());
+
+ vector<string>::const_iterator i;
+ for(i = seq.begin(); i != seq.end(); i++) writeString(*i);
+}
+
+void Buffer::write(void *data, long len) {
+ unsigned char *c = (unsigned char *)data;
+
+ contents.insert(contents.end(),c,c+len);
+}
+
+void Buffer::write(const vector<mcopbyte>& raw)
+{
+ contents.insert(contents.end(), raw.begin(), raw.end());
+}
+
+void Buffer::read(vector<mcopbyte>& raw, long l)
+{
+ if(l >= 0 && remaining() >= l) {
+ raw.clear();
+ raw.insert(raw.end(), contents.begin()+rpos, contents.begin()+rpos+l);
+ rpos += l;
+ } else {
+ _readError = true;
+ }
+}
+
+void *Buffer::read(long l) {
+ void *result = 0;
+
+ if(l >= 0 && remaining() >= l) {
+ result = &contents[rpos];
+ rpos += l;
+ } else {
+ _readError = true;
+ }
+ return result;
+}
+
+void *Buffer::peek(long l) {
+ assert(l >= 0 && remaining() >= l);
+ return &contents[rpos];
+}
+
+void Buffer::skip(long l) {
+ if(l >= 0 && remaining() >= l) {
+ rpos += l;
+ } else {
+ _readError = true;
+ }
+}
+
+void Buffer::rewind() {
+ rpos = 0;
+}
+
+bool Buffer::readBool()
+{
+ long result = false;
+ if(remaining() >= 1) {
+ if(contents[rpos] == 1)
+ result = true;
+ else
+ {
+ assert(contents[rpos] == 0);
+ }
+ rpos += 1;
+ } else {
+ _readError = true;
+ }
+ return result;
+}
+
+void Buffer::readBoolSeq(vector<bool>& result)
+{
+ // might be optimizable a bit
+ long i,seqlen = readLong();
+
+ result.clear();
+ if(seqlen >= 0 && remaining() >= seqlen)
+ {
+ for(i=0;i<seqlen;i++) result.push_back(readBool());
+ }
+ else
+ {
+ _readError = true;
+ }
+}
+
+
+mcopbyte Buffer::readByte()
+{
+ if(remaining() >= 1)
+ {
+ return contents[rpos++];
+ }
+ else
+ {
+ _readError = true;
+ return 0;
+ }
+}
+
+void Buffer::readByteSeq(vector<mcopbyte>& result)
+{
+ long seqlen = readLong(); // bytes are sent raw, so we can call read here
+ read(result, seqlen);
+}
+
+long Buffer::readLong()
+{
+ long result = 0;
+ if(remaining() >= 4) {
+ result = (contents[rpos] << 24)
+ + (contents[rpos+1] << 16)
+ + (contents[rpos+2] << 8)
+ + contents[rpos+3];
+ rpos += 4;
+ } else {
+ _readError = true;
+ }
+ return result;
+}
+
+void Buffer::readLongSeq(vector<long>& result)
+{
+ // might be optimizable a bit
+ long i,seqlen = readLong();
+
+ result.clear();
+ if(seqlen * 4 >= 0 && remaining() >= seqlen * 4)
+ {
+ for(i=0;i<seqlen;i++) result.push_back(readLong());
+ }
+ else
+ {
+ _readError = true;
+ }
+}
+
+float Buffer::readFloat()
+{
+ // FIXME: see writeFloat()
+ union {float f; long l; } u;
+ u.l = readLong();
+
+ if(!_readError) return u.f;
+ return 0.0;
+}
+
+void Buffer::readFloatSeq(vector<float>& result)
+{
+ // might be optimizable a bit
+ long i,seqlen = readLong();
+
+ result.clear();
+ if(seqlen * 4 >= 0 && remaining() >= seqlen * 4)
+ {
+ for(i=0;i<seqlen;i++) result.push_back(readFloat());
+ }
+ else
+ {
+ _readError = true;
+ }
+}
+
+void Buffer::readString(string& result)
+{
+ long len = readLong();
+ char *data = (char *)read(len);
+
+ if(data && len)
+ result.assign(data,len-1);
+ else
+ result = "";
+}
+
+void Buffer::readStringSeq(vector<string>& result)
+{
+ // might be optimizable a bit
+
+ long i,seqlen = readLong();
+
+ result.clear();
+ //result.reserve(seqlen);
+
+ for(i=0;i<seqlen;i++) {
+ string s;
+
+ readString(s);
+ if(_readError) return;
+
+ result.push_back(s);
+ }
+}
+
+
+void Buffer::patchLength()
+{
+ long len = size();
+ assert(len >= 8);
+
+ contents[4] = (len >> 24) & 0xff;
+ contents[5] = (len >> 16) & 0xff;
+ contents[6] = (len >> 8) & 0xff;
+ contents[7] = len & 0xff;
+}
+
+void Buffer::patchLong(long position, long value)
+{
+ long len = size();
+ assert(len >= position+4);
+
+ contents[position] = (value >> 24) & 0xff;
+ contents[position+1] = (value >> 16) & 0xff;
+ contents[position+2] = (value >> 8) & 0xff;
+ contents[position+3] = value & 0xff;
+}
+
+string Buffer::toString(const string& name)
+{
+ string result;
+ char hex[17] = "0123456789abcdef";
+
+ vector<unsigned char>::iterator ci;
+ for(ci = contents.begin(); ci != contents.end(); ci++)
+ {
+ result += hex[(*ci >> 4) & 0xf];
+ result += hex[*ci & 0xf];
+ }
+
+ if(name.empty()) return result;
+ return name + ":" + result;
+}
+
+unsigned char Buffer::fromHexNibble(char c)
+{
+ int uc = (unsigned char)c;
+
+ if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0';
+ if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a';
+ if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A';
+
+ return 16; // error
+}
+
+static int stringncmp(const string& s1, const string& s2, size_t n)
+{
+ // I don't know a way to implement that compliant to all STL string
+ // implementations (compare seems to work differently sometimes)
+ return strncmp(s1.c_str(),s2.c_str(),n);
+}
+
+bool Buffer::fromString(const string& data, const string& name)
+{
+ string start = name+":";
+ if(name.empty()) start = "";
+
+ if(stringncmp(data,start,start.size()) != 0) return false;
+ contents.clear();
+
+ string::const_iterator di = data.begin() + start.size();
+
+ while(di != data.end())
+ {
+ unsigned char h = fromHexNibble(*di++); // high nibble
+ if(di == data.end()) return false;
+
+ unsigned char l = fromHexNibble(*di++); // low nibble
+
+ if(h >= 16 || l >= 16) return false; // no proper hex digit
+ contents.push_back((h << 4) + l);
+ }
+ return true;
+}
+
diff --git a/mcop/buffer.h b/mcop/buffer.h
new file mode 100644
index 0000000..b361092
--- /dev/null
+++ b/mcop/buffer.h
@@ -0,0 +1,104 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include <string>
+#include <vector>
+#include "arts_export.h"
+/*
+ * BC - Status (2002-03-08): Buffer.
+ *
+ * Has to be kept binary compatible. As buffer is speed relevant, currently
+ * there are no private d ptrs, and the idea is to keep this as possible.
+ *
+ * If not, put additional stuff in the d ptr, but keep as much data as
+ * possible in the main items.
+ */
+
+namespace Arts {
+
+#ifndef MCOPBYTE_DEFINED
+#define MCOPBYTE_DEFINED
+typedef unsigned char mcopbyte;
+#endif
+
+class BufferPrivate;
+
+class ARTS_EXPORT Buffer {
+private:
+ long rpos;
+ bool _readError;
+ std::vector<unsigned char> contents;
+
+ BufferPrivate *d; // unused
+ unsigned char fromHexNibble(char c);
+
+public:
+ Buffer();
+ ~Buffer();
+
+ bool readError();
+ void writeBool(bool b);
+ void writeBoolSeq(const std::vector<bool>& seq);
+ void writeByte(mcopbyte b);
+ void writeByteSeq(const std::vector<mcopbyte>& seq);
+ void writeLong(long l);
+ void writeLongSeq(const std::vector<long>& seq);
+ void writeFloat(float f);
+ void writeFloatSeq(const std::vector<float>& seq);
+ void writeString(const std::string& s);
+ void writeStringSeq(const std::vector<std::string>& seq);
+
+ long size();
+ long remaining();
+ void *read(long l);
+ void read(std::vector<mcopbyte>& raw, long l);
+ void *peek(long l);
+ void skip(long l);
+ void rewind();
+
+ void write(void *data, long l);
+ void write(const std::vector<mcopbyte>& raw);
+
+ bool readBool();
+ void readBoolSeq(std::vector<bool>& result);
+ mcopbyte readByte();
+ void readByteSeq(std::vector<mcopbyte>& result);
+ long readLong();
+ void readLongSeq(std::vector<long>& result);
+ float readFloat();
+ void readFloatSeq(std::vector<float>& result);
+ void readString(std::string& result);
+ void readStringSeq(std::vector<std::string>& result);
+
+ void patchLength();
+ void patchLong(long position, long value);
+
+ std::string toString(const std::string& name);
+ bool fromString(const std::string& data, const std::string& name);
+};
+
+}
+
+#endif
diff --git a/mcop/common.h b/mcop/common.h
new file mode 100644
index 0000000..4021fb9
--- /dev/null
+++ b/mcop/common.h
@@ -0,0 +1,141 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "buffer.h"
+#include "type.h"
+#include "dispatcher.h"
+#include "object.h"
+#include "connection.h"
+#include "objectmanager.h"
+#include "idlfilereg.h"
+#include "asyncstream.h"
+#include "mcoputils.h"
+#include "anyref.h"
+#include "connect.h"
+
+/*
+ * BC - Status (2002-03-08): Read/WriteObject(Seq)
+ *
+ * Will be kept binary compatible by NOT TOUCHING AT ALL. Do not change this.
+ * (Interaction with generated code).
+ */
+
+/* define this to see what mcop transfers around */
+#undef DEBUG_IO
+
+/* define this to see what mcop messages are processed */
+#undef DEBUG_MESSAGES
+
+#include "core.h"
+
+namespace Arts {
+/* some marshalling helpers */
+
+template<class T>
+void readTypeSeq(Buffer& stream, std::vector<T>& sequence) {
+ sequence.clear();
+
+ unsigned long l = stream.readLong();
+ while(l--) sequence.push_back(T(stream));
+}
+
+template<class T>
+void writeTypeSeq(Buffer& stream, const std::vector<T>& sequence) {
+ stream.writeLong(sequence.size());
+ for(unsigned long l=0;l<sequence.size();l++)
+ sequence[l].writeType(stream);
+}
+
+template<class T>
+void writeObject(Buffer& stream, T* object) {
+ if(object)
+ {
+ /*
+ * perhaps reimplement directly (without conversion to/from string)
+ * for more speed
+ */
+
+ std::string s = object->_toString();
+
+ Buffer buffer;
+ buffer.fromString(s,"MCOP-Object");
+ ObjectReference reference(buffer);
+
+ object->_copyRemote(); // prevents that the object is freed for a while
+ reference.writeType(stream);
+ }
+ else
+ {
+ ObjectReference null_reference;
+
+ null_reference.serverID = "null";
+ null_reference.objectID = 0;
+ null_reference.writeType(stream);
+ }
+}
+
+template<class T>
+void readObject(Buffer& stream, T*& result) {
+ ObjectReference reference(stream);
+
+ if(reference.serverID == "null")
+ result = 0; // null reference?
+ else
+ result = T::_fromReference(reference,false);
+}
+
+template<class T>
+void readObjectSeq(Buffer& stream, std::vector<T>& sequence)
+{
+ sequence.clear();
+
+ unsigned long l = stream.readLong();
+ while(l--)
+ {
+ typename T::_base_class *temp;
+ readObject(stream, temp);
+ sequence.push_back(T::_from_base(temp));
+ }
+}
+
+template<class T>
+void writeObjectSeq(Buffer& stream, const std::vector<T>& sequence)
+{
+ stream.writeLong(sequence.size());
+
+ for(unsigned long l=0;l<sequence.size();l++)
+ {
+ T object = sequence[l];
+ writeObject(stream,object._base());
+ }
+}
+
+#ifndef MCOPBYTE_DEFINED
+#define MCOPBYTE_DEFINED
+typedef unsigned char mcopbyte;
+#endif
+
+}
+#endif
diff --git a/mcop/connect.cc b/mcop/connect.cc
new file mode 100644
index 0000000..88d5dff
--- /dev/null
+++ b/mcop/connect.cc
@@ -0,0 +1,149 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu
+ nicolas.brodu@free.fr
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "connect.h"
+#include "flowsystem.h"
+#include <assert.h>
+#include "debug.h"
+
+// NDEBUG is the symbol name that can remove the assertions
+#ifdef NDEBUG
+#define mywarning(a,b)
+#else
+#include <iostream>
+#define mywarning(a,b) if (!(a)) arts_warning("MCOP connection warning: %s",b)
+#endif
+
+using namespace std;
+
+namespace Arts {
+
+// Connect function overloaded for objects with default port
+void connect(const Object& src, const std::string& output, const Object& dest, const std::string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ node->connect(output, dest._node(), input);
+}
+
+void connect(const Object& src, const string& output, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsIn.size() == 1, "default input not found in void connect(const Object& src, const string& output, const Object& dest);");
+ node->connect(output, dest._node(), portsIn[0]);
+}
+
+void connect(const Object& src, const Object& dest, const string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ mywarning(portsOut.size() == 1, "default output not found in void connect(const Object& src, const Object& dest, const string& input);");
+ node->connect(portsOut[0], dest._node(), input);
+}
+
+void connect(const Object& src, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsOut.size() == portsIn.size(), "number of defaults for src and dest don't match in void connect(const Object& src, const Object& dest);");
+ mywarning(!portsOut.empty(), "no defaults for src and dest in void connect(const Object& src, const Object& dest);");
+ vector<std::string>::iterator ot = portsOut.begin();
+ vector<std::string>::iterator it = portsIn.begin();
+ for (; ot != portsOut.end(); it++, ot++) {
+ node->connect(*ot, dest._node(), *it);
+ }
+}
+
+void disconnect(const Object& src, const std::string& output, const Object& dest, const std::string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ node->disconnect(output, dest._node(), input);
+}
+
+void disconnect(const Object& src, const string& output, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsIn.size() == 1, "default input not found in void disconnect(const Object& src, const string& output, const Object& dest);");
+ node->disconnect(output, dest._node(), portsIn[0]);
+}
+
+void disconnect(const Object& src, const Object& dest, const string& input)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ mywarning(portsOut.size() == 1, "default output not found in void disconnect(const Object& src, const Object& dest, const string& input);");
+ node->disconnect(portsOut[0], dest._node(), input);
+}
+
+void disconnect(const Object& src, const Object& dest)
+{
+ ScheduleNode *node = src._node();
+ assert(node);
+ vector<std::string> portsOut = src._defaultPortsOut();
+ vector<std::string> portsIn = dest._defaultPortsIn();
+ mywarning(portsOut.size() == portsIn.size(), "number of defaults for src and dest don't match in void disconnect(const Object& src, const Object& dest);");
+ mywarning(!portsOut.empty(), "no defaults for src and dest in void disconnect(const Object& src, const Object& dest);");
+ vector<std::string>::iterator ot = portsOut.begin();
+ vector<std::string>::iterator it = portsIn.begin();
+ for (; ot != portsOut.end(); it++, ot++) {
+ node->disconnect(*ot, dest._node(), *it);
+ }
+}
+
+// setValue function overloaded for objects with default port
+void setValue(const Object& c, const std::string& port, const float fvalue)
+{
+ ScheduleNode *node = c._node();
+ assert(node);
+ node->setFloatValue(port, fvalue);
+}
+
+void setValue(const Object& c, const float fvalue)
+{
+ ScheduleNode *node = c._node();
+ assert(node);
+ vector<std::string> portsIn = c._defaultPortsIn();
+ mywarning(!portsIn.empty(), "c has no default ports in void setValue(const Object& c, const float fvalue);");
+ vector<std::string>::iterator it = portsIn.begin();
+ for (; it != portsIn.end(); it++) {
+ node->setFloatValue(*it, fvalue);
+ }
+}
+
+/* String values???
+void setValue(Object& c, const string& port, const string& svalue)
+{
+}
+
+void setValue(Object& c, const string& svalue)
+{
+}
+*/
+
+}
diff --git a/mcop/connect.h b/mcop/connect.h
new file mode 100644
index 0000000..f9db8b5
--- /dev/null
+++ b/mcop/connect.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu
+ nicolas.brodu@free.fr
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef MCOP_CONNECT_H
+#define MCOP_CONNECT_H
+
+/*
+ * BC - Status (2002-03-08): connect / setValue functions
+ *
+ * Will be kept as they are (binary compatible).
+ */
+
+#include <string>
+#include "arts_export.h"
+
+namespace Arts {
+class Object;
+
+// Connect function overloaded for components with default port
+void ARTS_EXPORT connect(const Object& src, const std::string& output, const Object& dest, const std::string& input);
+void ARTS_EXPORT connect(const Object& src, const std::string& output, const Object& dest);
+void ARTS_EXPORT connect(const Object& src, const Object& dest, const std::string& input);
+void ARTS_EXPORT connect(const Object& src, const Object& dest);
+// Same for disconnect function
+void ARTS_EXPORT disconnect(const Object& src, const std::string& output, const Object& dest, const std::string& input);
+void ARTS_EXPORT disconnect(const Object& src, const std::string& output, const Object& dest);
+void ARTS_EXPORT disconnect(const Object& src, const Object& dest, const std::string& input);
+void ARTS_EXPORT disconnect(const Object& src, const Object& dest);
+
+// setValue function overloaded for components with default port
+void ARTS_EXPORT setValue(const Object& c, const std::string& port, const float fvalue);
+void ARTS_EXPORT setValue(const Object& c, const float fvalue);
+//void setValue(const Object& c, const std::string& port, const std::string& svalue);
+//void setValue(const Object& c, const std::string& svalue);
+
+}
+
+#endif
diff --git a/mcop/connection.cc b/mcop/connection.cc
new file mode 100644
index 0000000..49221f9
--- /dev/null
+++ b/mcop/connection.cc
@@ -0,0 +1,196 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "connection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include <stdio.h>
+#include <string.h> // for Solaris
+#include <queue>
+#include <algorithm>
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+class ConnectionPrivate {
+public:
+ struct Data {
+ Data() : data(0), len(0) { }
+ Data(unsigned char *data, long len) : data(data), len(len) { }
+ Data(const Data& d) : data(d.data), len(d.len) { }
+ unsigned char *data;
+ long len;
+ };
+
+ queue<Data> incoming;
+ map<string,string> hints;
+};
+}
+
+Connection::Connection() :d(new ConnectionPrivate), _refCnt(1)
+{
+ _connState = unknown;
+}
+
+Connection::~Connection()
+{
+ assert(d->incoming.empty());
+ assert(_refCnt == 0);
+
+ delete d;
+}
+
+void Connection::_copy()
+{
+ assert(_refCnt > 0);
+ _refCnt++;
+}
+
+void Connection::_release()
+{
+ assert(_refCnt > 0);
+ _refCnt--;
+ if(_refCnt == 0)
+ delete this;
+}
+
+void Connection::initReceive()
+{
+ rcbuf = 0;
+ receiveHeader = true;
+ remaining = 12;
+}
+
+void Connection::receive(unsigned char *newdata, long newlen)
+{
+ /*
+ * protect against being freed while receive is running, as there are a
+ * few points where reentrant event loops may happen (Dispatcher::handle)
+ */
+ _copy();
+
+ d->incoming.push(ConnectionPrivate::Data(newdata,newlen));
+
+ do
+ {
+ ConnectionPrivate::Data &data = d->incoming.front();
+
+ // get a buffer for the incoming message
+ if(!rcbuf) rcbuf = new Buffer;
+
+ // put a suitable amount of input data into the receive buffer
+ long len = min(remaining, data.len);
+
+ remaining -= len;
+ rcbuf->write(data.data,len);
+
+ data.len -= len;
+ data.data += len;
+
+ if(data.len == 0)
+ d->incoming.pop();
+
+ // look if it was enough to do something useful with it
+ if(remaining == 0)
+ {
+ if(receiveHeader)
+ {
+ long mcopMagic;
+
+ mcopMagic = rcbuf->readLong();
+ remaining = rcbuf->readLong() - 12;
+ messageType = rcbuf->readLong();
+
+ if(_connState != Connection::established
+ && (remaining >= 4096 || remaining < 0))
+ {
+ /*
+ * don't accept large amounts of data on unauthenticated
+ * connections
+ */
+ remaining = 0;
+ }
+
+ if(mcopMagic == MCOP_MAGIC)
+ {
+ // do we need to receive more data (message body?)
+ if(remaining)
+ {
+ receiveHeader = false;
+ }
+ else
+ {
+ Buffer *received = rcbuf;
+ initReceive();
+ Dispatcher::the()->handle(this,received,messageType);
+ }
+ }
+ else
+ {
+ initReceive();
+ Dispatcher::the()->handleCorrupt(this);
+ }
+ }
+ else
+ {
+ Buffer *received = rcbuf;
+
+ /*
+ * it's important to prepare to receive new messages *before*
+ * calling Dispatcher::the()->handle(...), as handle may
+ * get into an I/O situation (e.g. when doing an invocation
+ * itself), and we may receive more messages while handle is
+ * running
+ */
+ initReceive();
+
+ // rcbuf is consumed by the dispatcher
+ Dispatcher::the()->handle(this,received,messageType);
+ }
+ }
+ } while(!d->incoming.empty());
+
+ _release();
+}
+
+void Connection::setHints(const vector<string>& hints)
+{
+ vector<string>::const_iterator i;
+
+ for(i = hints.begin(); i != hints.end(); i++)
+ {
+ string key;
+ vector<string> values;
+
+ if(MCOPUtils::tokenize(*i, key, values))
+ {
+ if(values.size() == 1)
+ d->hints[key] = values[0];
+ }
+ }
+}
+
+string Connection::findHint(const string& hint)
+{
+ return d->hints[hint];
+}
diff --git a/mcop/connection.h b/mcop/connection.h
new file mode 100644
index 0000000..db7edf0
--- /dev/null
+++ b/mcop/connection.h
@@ -0,0 +1,100 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef CONNECTION_H
+#define CONNECTION_H
+
+#include "arts_export.h"
+#include "buffer.h"
+
+/*
+ * BC - Status (2002-03-08): Connection.
+ *
+ * None of these classes is considered part of the public API. However, they
+ * NEED to be kept binary compatible as the DO interact with generated code.
+ *
+ * Especially virtual functions and stuff can't be added, if you need to,
+ * you need to add classes parallel to the Connection hierarchy.
+ */
+
+namespace Arts {
+
+class ConnectionPrivate;
+
+class ARTS_EXPORT Connection {
+private:
+ ConnectionPrivate *d; // unused
+public:
+ enum ConnectionState {
+ unknown = 0,
+ expectServerHello = 1,
+ expectClientHello = 2,
+ expectAuthAccept = 3,
+ established = 4
+ };
+protected:
+ Buffer *rcbuf;
+ bool receiveHeader;
+ long remaining;
+ long messageType;
+ ConnectionState _connState;
+ std::string serverID;
+ std::string _cookie;
+
+ long _refCnt;
+
+ /**
+ * If you don't want to handle message fragmentation yourself:
+ *
+ * Call initReceive in your derived Connection constructor, ald
+ * receive as soon as you receive some data - the connection object
+ * will handle the rest (put the messages into buffers and send them
+ * to the dispatcher)
+ */
+ void initReceive();
+ void receive(unsigned char *data, long len);
+
+ virtual ~Connection();
+public:
+ Connection();
+
+ inline void setServerID(const std::string& _serverID) { serverID = _serverID; }
+ inline bool isConnected(const std::string& s) { return (serverID == s); }
+ inline void setConnState(ConnectionState cs) { _connState = cs; };
+
+ inline std::string cookie() { return _cookie; }
+ void setCookie(const std::string& c) { _cookie = c; }
+ void setHints(const std::vector<std::string>& hints);
+ std::string findHint(const std::string& name);
+
+ inline ConnectionState connState() { return _connState; };
+ virtual void drop() = 0;
+ virtual bool broken() = 0;
+ virtual void qSendBuffer(Buffer *buffer) = 0;
+
+ void _release();
+ void _copy();
+};
+
+}
+
+#endif
diff --git a/mcop/core.cc b/mcop/core.cc
new file mode 100644
index 0000000..b0d48eb
--- /dev/null
+++ b/mcop/core.cc
@@ -0,0 +1,3191 @@
+/* this file was generated by the MCOP idl compiler - DO NOT EDIT */
+
+#include "common.h"
+
+// Implementation
+Arts::Header::Header()
+{
+}
+
+Arts::Header::Header(Arts::HeaderMagic _a_magic, long _a_messageLength, Arts::MessageType _a_messageType)
+{
+ this->magic = _a_magic;
+ this->messageLength = _a_messageLength;
+ this->messageType = _a_messageType;
+}
+
+Arts::Header::Header(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::Header::Header(const Arts::Header& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::Header& Arts::Header::operator=(const Arts::Header& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::Header::readType(Arts::Buffer& stream)
+{
+ magic = (Arts::HeaderMagic)stream.readLong();
+ messageLength = stream.readLong();
+ messageType = (Arts::MessageType)stream.readLong();
+}
+
+void Arts::Header::writeType(Arts::Buffer& stream) const
+{
+ stream.writeLong(magic);
+ stream.writeLong(messageLength);
+ stream.writeLong(messageType);
+}
+
+std::string Arts::Header::_typeName() const
+{
+ return "Arts::Header";
+}
+
+Arts::Invocation::Invocation()
+{
+}
+
+Arts::Invocation::Invocation(long _a_objectID, long _a_methodID, long _a_requestID)
+{
+ this->objectID = _a_objectID;
+ this->methodID = _a_methodID;
+ this->requestID = _a_requestID;
+}
+
+Arts::Invocation::Invocation(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::Invocation::Invocation(const Arts::Invocation& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::Invocation& Arts::Invocation::operator=(const Arts::Invocation& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::Invocation::readType(Arts::Buffer& stream)
+{
+ objectID = stream.readLong();
+ methodID = stream.readLong();
+ requestID = stream.readLong();
+}
+
+void Arts::Invocation::writeType(Arts::Buffer& stream) const
+{
+ stream.writeLong(objectID);
+ stream.writeLong(methodID);
+ stream.writeLong(requestID);
+}
+
+std::string Arts::Invocation::_typeName() const
+{
+ return "Arts::Invocation";
+}
+
+Arts::OnewayInvocation::OnewayInvocation()
+{
+}
+
+Arts::OnewayInvocation::OnewayInvocation(long _a_objectID, long _a_methodID)
+{
+ this->objectID = _a_objectID;
+ this->methodID = _a_methodID;
+}
+
+Arts::OnewayInvocation::OnewayInvocation(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::OnewayInvocation::OnewayInvocation(const Arts::OnewayInvocation& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::OnewayInvocation& Arts::OnewayInvocation::operator=(const Arts::OnewayInvocation& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::OnewayInvocation::readType(Arts::Buffer& stream)
+{
+ objectID = stream.readLong();
+ methodID = stream.readLong();
+}
+
+void Arts::OnewayInvocation::writeType(Arts::Buffer& stream) const
+{
+ stream.writeLong(objectID);
+ stream.writeLong(methodID);
+}
+
+std::string Arts::OnewayInvocation::_typeName() const
+{
+ return "Arts::OnewayInvocation";
+}
+
+Arts::ServerHello::ServerHello()
+{
+}
+
+Arts::ServerHello::ServerHello(const std::string& _a_mcopVersion, const std::string& _a_serverID, const std::vector<std::string>& _a_authProtocols, const std::string& _a_authSeed)
+{
+ this->mcopVersion = _a_mcopVersion;
+ this->serverID = _a_serverID;
+ this->authProtocols = _a_authProtocols;
+ this->authSeed = _a_authSeed;
+}
+
+Arts::ServerHello::ServerHello(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ServerHello::ServerHello(const Arts::ServerHello& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ServerHello& Arts::ServerHello::operator=(const Arts::ServerHello& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ServerHello::readType(Arts::Buffer& stream)
+{
+ stream.readString(mcopVersion);
+ stream.readString(serverID);
+ stream.readStringSeq(authProtocols);
+ stream.readString(authSeed);
+}
+
+void Arts::ServerHello::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(mcopVersion);
+ stream.writeString(serverID);
+ stream.writeStringSeq(authProtocols);
+ stream.writeString(authSeed);
+}
+
+std::string Arts::ServerHello::_typeName() const
+{
+ return "Arts::ServerHello";
+}
+
+Arts::ClientHello::ClientHello()
+{
+}
+
+Arts::ClientHello::ClientHello(const std::string& _a_serverID, const std::string& _a_authProtocol, const std::string& _a_authData)
+{
+ this->serverID = _a_serverID;
+ this->authProtocol = _a_authProtocol;
+ this->authData = _a_authData;
+}
+
+Arts::ClientHello::ClientHello(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ClientHello::ClientHello(const Arts::ClientHello& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ClientHello& Arts::ClientHello::operator=(const Arts::ClientHello& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ClientHello::readType(Arts::Buffer& stream)
+{
+ stream.readString(serverID);
+ stream.readString(authProtocol);
+ stream.readString(authData);
+}
+
+void Arts::ClientHello::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(serverID);
+ stream.writeString(authProtocol);
+ stream.writeString(authData);
+}
+
+std::string Arts::ClientHello::_typeName() const
+{
+ return "Arts::ClientHello";
+}
+
+Arts::AuthAccept::AuthAccept()
+{
+}
+
+Arts::AuthAccept::AuthAccept(const std::vector<std::string>& _a_hints)
+{
+ this->hints = _a_hints;
+}
+
+Arts::AuthAccept::AuthAccept(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::AuthAccept::AuthAccept(const Arts::AuthAccept& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::AuthAccept& Arts::AuthAccept::operator=(const Arts::AuthAccept& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::AuthAccept::readType(Arts::Buffer& stream)
+{
+ stream.readStringSeq(hints);
+}
+
+void Arts::AuthAccept::writeType(Arts::Buffer& stream) const
+{
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::AuthAccept::_typeName() const
+{
+ return "Arts::AuthAccept";
+}
+
+Arts::ObjectReference::ObjectReference()
+{
+}
+
+Arts::ObjectReference::ObjectReference(const std::string& _a_serverID, long _a_objectID, const std::vector<std::string>& _a_urls)
+{
+ this->serverID = _a_serverID;
+ this->objectID = _a_objectID;
+ this->urls = _a_urls;
+}
+
+Arts::ObjectReference::ObjectReference(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ObjectReference::ObjectReference(const Arts::ObjectReference& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ObjectReference& Arts::ObjectReference::operator=(const Arts::ObjectReference& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ObjectReference::readType(Arts::Buffer& stream)
+{
+ stream.readString(serverID);
+ objectID = stream.readLong();
+ stream.readStringSeq(urls);
+}
+
+void Arts::ObjectReference::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(serverID);
+ stream.writeLong(objectID);
+ stream.writeStringSeq(urls);
+}
+
+std::string Arts::ObjectReference::_typeName() const
+{
+ return "Arts::ObjectReference";
+}
+
+Arts::ParamDef::ParamDef()
+{
+}
+
+Arts::ParamDef::ParamDef(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints)
+{
+ this->type = _a_type;
+ this->name = _a_name;
+ this->hints = _a_hints;
+}
+
+Arts::ParamDef::ParamDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ParamDef::ParamDef(const Arts::ParamDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ParamDef& Arts::ParamDef::operator=(const Arts::ParamDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ParamDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(type);
+ stream.readString(name);
+ stream.readStringSeq(hints);
+}
+
+void Arts::ParamDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(type);
+ stream.writeString(name);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::ParamDef::_typeName() const
+{
+ return "Arts::ParamDef";
+}
+
+Arts::MethodDef::MethodDef()
+{
+}
+
+Arts::MethodDef::MethodDef(const std::string& _a_name, const std::string& _a_type, Arts::MethodType _a_flags, const std::vector<Arts::ParamDef>& _a_signature, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->type = _a_type;
+ this->flags = _a_flags;
+ this->signature = _a_signature;
+ this->hints = _a_hints;
+}
+
+Arts::MethodDef::MethodDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::MethodDef::MethodDef(const Arts::MethodDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::MethodDef& Arts::MethodDef::operator=(const Arts::MethodDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::MethodDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ stream.readString(type);
+ flags = (Arts::MethodType)stream.readLong();
+ Arts::readTypeSeq(stream,signature);
+ stream.readStringSeq(hints);
+}
+
+void Arts::MethodDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeString(type);
+ stream.writeLong(flags);
+ Arts::writeTypeSeq(stream,signature);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::MethodDef::_typeName() const
+{
+ return "Arts::MethodDef";
+}
+
+Arts::AttributeDef::AttributeDef()
+{
+}
+
+Arts::AttributeDef::AttributeDef(const std::string& _a_name, const std::string& _a_type, Arts::AttributeType _a_flags, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->type = _a_type;
+ this->flags = _a_flags;
+ this->hints = _a_hints;
+}
+
+Arts::AttributeDef::AttributeDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::AttributeDef::AttributeDef(const Arts::AttributeDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::AttributeDef& Arts::AttributeDef::operator=(const Arts::AttributeDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::AttributeDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ stream.readString(type);
+ flags = (Arts::AttributeType)stream.readLong();
+ stream.readStringSeq(hints);
+}
+
+void Arts::AttributeDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeString(type);
+ stream.writeLong(flags);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::AttributeDef::_typeName() const
+{
+ return "Arts::AttributeDef";
+}
+
+Arts::InterfaceDef::InterfaceDef()
+{
+}
+
+Arts::InterfaceDef::InterfaceDef(const std::string& _a_name, const std::vector<std::string>& _a_inheritedInterfaces, const std::vector<Arts::MethodDef>& _a_methods, const std::vector<Arts::AttributeDef>& _a_attributes, const std::vector<std::string>& _a_defaultPorts, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->inheritedInterfaces = _a_inheritedInterfaces;
+ this->methods = _a_methods;
+ this->attributes = _a_attributes;
+ this->defaultPorts = _a_defaultPorts;
+ this->hints = _a_hints;
+}
+
+Arts::InterfaceDef::InterfaceDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::InterfaceDef::InterfaceDef(const Arts::InterfaceDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::InterfaceDef& Arts::InterfaceDef::operator=(const Arts::InterfaceDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::InterfaceDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ stream.readStringSeq(inheritedInterfaces);
+ Arts::readTypeSeq(stream,methods);
+ Arts::readTypeSeq(stream,attributes);
+ stream.readStringSeq(defaultPorts);
+ stream.readStringSeq(hints);
+}
+
+void Arts::InterfaceDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeStringSeq(inheritedInterfaces);
+ Arts::writeTypeSeq(stream,methods);
+ Arts::writeTypeSeq(stream,attributes);
+ stream.writeStringSeq(defaultPorts);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::InterfaceDef::_typeName() const
+{
+ return "Arts::InterfaceDef";
+}
+
+Arts::TypeComponent::TypeComponent()
+{
+}
+
+Arts::TypeComponent::TypeComponent(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints)
+{
+ this->type = _a_type;
+ this->name = _a_name;
+ this->hints = _a_hints;
+}
+
+Arts::TypeComponent::TypeComponent(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::TypeComponent::TypeComponent(const Arts::TypeComponent& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::TypeComponent& Arts::TypeComponent::operator=(const Arts::TypeComponent& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::TypeComponent::readType(Arts::Buffer& stream)
+{
+ stream.readString(type);
+ stream.readString(name);
+ stream.readStringSeq(hints);
+}
+
+void Arts::TypeComponent::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(type);
+ stream.writeString(name);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::TypeComponent::_typeName() const
+{
+ return "Arts::TypeComponent";
+}
+
+Arts::TypeDef::TypeDef()
+{
+}
+
+Arts::TypeDef::TypeDef(const std::string& _a_name, const std::vector<Arts::TypeComponent>& _a_contents, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->contents = _a_contents;
+ this->hints = _a_hints;
+}
+
+Arts::TypeDef::TypeDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::TypeDef::TypeDef(const Arts::TypeDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::TypeDef& Arts::TypeDef::operator=(const Arts::TypeDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::TypeDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ Arts::readTypeSeq(stream,contents);
+ stream.readStringSeq(hints);
+}
+
+void Arts::TypeDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ Arts::writeTypeSeq(stream,contents);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::TypeDef::_typeName() const
+{
+ return "Arts::TypeDef";
+}
+
+Arts::EnumComponent::EnumComponent()
+{
+}
+
+Arts::EnumComponent::EnumComponent(const std::string& _a_name, long _a_value, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->value = _a_value;
+ this->hints = _a_hints;
+}
+
+Arts::EnumComponent::EnumComponent(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::EnumComponent::EnumComponent(const Arts::EnumComponent& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::EnumComponent& Arts::EnumComponent::operator=(const Arts::EnumComponent& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::EnumComponent::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ value = stream.readLong();
+ stream.readStringSeq(hints);
+}
+
+void Arts::EnumComponent::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ stream.writeLong(value);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::EnumComponent::_typeName() const
+{
+ return "Arts::EnumComponent";
+}
+
+Arts::EnumDef::EnumDef()
+{
+}
+
+Arts::EnumDef::EnumDef(const std::string& _a_name, const std::vector<Arts::EnumComponent>& _a_contents, const std::vector<std::string>& _a_hints)
+{
+ this->name = _a_name;
+ this->contents = _a_contents;
+ this->hints = _a_hints;
+}
+
+Arts::EnumDef::EnumDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::EnumDef::EnumDef(const Arts::EnumDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::EnumDef& Arts::EnumDef::operator=(const Arts::EnumDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::EnumDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(name);
+ Arts::readTypeSeq(stream,contents);
+ stream.readStringSeq(hints);
+}
+
+void Arts::EnumDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(name);
+ Arts::writeTypeSeq(stream,contents);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::EnumDef::_typeName() const
+{
+ return "Arts::EnumDef";
+}
+
+Arts::ModuleDef::ModuleDef()
+{
+}
+
+Arts::ModuleDef::ModuleDef(const std::string& _a_moduleName, const std::vector<Arts::EnumDef>& _a_enums, const std::vector<Arts::TypeDef>& _a_types, const std::vector<Arts::InterfaceDef>& _a_interfaces, const std::vector<std::string>& _a_hints)
+{
+ this->moduleName = _a_moduleName;
+ this->enums = _a_enums;
+ this->types = _a_types;
+ this->interfaces = _a_interfaces;
+ this->hints = _a_hints;
+}
+
+Arts::ModuleDef::ModuleDef(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::ModuleDef::ModuleDef(const Arts::ModuleDef& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::ModuleDef& Arts::ModuleDef::operator=(const Arts::ModuleDef& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::ModuleDef::readType(Arts::Buffer& stream)
+{
+ stream.readString(moduleName);
+ Arts::readTypeSeq(stream,enums);
+ Arts::readTypeSeq(stream,types);
+ Arts::readTypeSeq(stream,interfaces);
+ stream.readStringSeq(hints);
+}
+
+void Arts::ModuleDef::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(moduleName);
+ Arts::writeTypeSeq(stream,enums);
+ Arts::writeTypeSeq(stream,types);
+ Arts::writeTypeSeq(stream,interfaces);
+ stream.writeStringSeq(hints);
+}
+
+std::string Arts::ModuleDef::_typeName() const
+{
+ return "Arts::ModuleDef";
+}
+
+Arts::Any::Any()
+{
+}
+
+Arts::Any::Any(const std::string& _a_type, const std::vector<Arts::mcopbyte>& _a_value)
+{
+ this->type = _a_type;
+ this->value = _a_value;
+}
+
+Arts::Any::Any(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::Any::Any(const Arts::Any& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::Any& Arts::Any::operator=(const Arts::Any& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::Any::readType(Arts::Buffer& stream)
+{
+ stream.readString(type);
+ stream.readByteSeq(value);
+}
+
+void Arts::Any::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(type);
+ stream.writeByteSeq(value);
+}
+
+std::string Arts::Any::_typeName() const
+{
+ return "Arts::Any";
+}
+
+Arts::TraderEntry::TraderEntry()
+{
+}
+
+Arts::TraderEntry::TraderEntry(const std::string& _a_interfaceName, const std::vector<std::string>& _a_lines)
+{
+ this->interfaceName = _a_interfaceName;
+ this->lines = _a_lines;
+}
+
+Arts::TraderEntry::TraderEntry(Arts::Buffer& stream)
+{
+ readType(stream);
+}
+
+Arts::TraderEntry::TraderEntry(const Arts::TraderEntry& copyType) : Arts::Type(copyType)
+{
+ Arts::Buffer buffer;
+ copyType.writeType(buffer);
+ readType(buffer);
+}
+
+Arts::TraderEntry& Arts::TraderEntry::operator=(const Arts::TraderEntry& assignType)
+{
+ Arts::Buffer buffer;
+ assignType.writeType(buffer);
+ readType(buffer);
+ return *this;
+}
+
+void Arts::TraderEntry::readType(Arts::Buffer& stream)
+{
+ stream.readString(interfaceName);
+ stream.readStringSeq(lines);
+}
+
+void Arts::TraderEntry::writeType(Arts::Buffer& stream) const
+{
+ stream.writeString(interfaceName);
+ stream.writeStringSeq(lines);
+}
+
+std::string Arts::TraderEntry::_typeName() const
+{
+ return "Arts::TraderEntry";
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::InterfaceRepo_base *castedObject = (Arts::InterfaceRepo_base *)skel->_cast(Arts::InterfaceRepo_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::InterfaceRepo_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::InterfaceRepo_base *castedObject = (Arts::InterfaceRepo_base *)object._base()->_cast(Arts::InterfaceRepo_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::InterfaceRepo_base *Arts::InterfaceRepo_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::InterfaceRepo_base *result;
+ result = (Arts::InterfaceRepo_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::InterfaceRepo");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::InterfaceRepo_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::InterfaceRepo")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::InterfaceRepo_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::InterfaceRepo_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::InterfaceRepo_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::InterfaceRepo_base::_IID) return (Arts::InterfaceRepo_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::InterfaceRepo_stub::InterfaceRepo_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::InterfaceRepo_stub::InterfaceRepo_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+long Arts::InterfaceRepo_stub::insertModule(const Arts::ModuleDef& newModule)
+{
+ long methodID = _lookupMethodFast("method:0000000d696e736572744d6f64756c6500000000056c6f6e6700000000020000000100000010417274733a3a4d6f64756c65446566000000000a6e65774d6f64756c65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ newModule.writeType(*request);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return 0; // error occurred
+ long returnCode = result->readLong();
+ delete result;
+ return returnCode;
+}
+
+void Arts::InterfaceRepo_stub::removeModule(long moduleID)
+{
+ long methodID = _lookupMethodFast("method:0000000d72656d6f76654d6f64756c650000000005766f6964000000000200000001000000056c6f6e6700000000096d6f64756c654944000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeLong(moduleID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+Arts::InterfaceDef Arts::InterfaceRepo_stub::queryInterface(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000f7175657279496e746572666163650000000013417274733a3a496e7465726661636544656600000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return Arts::InterfaceDef(); // error occurred
+ Arts::InterfaceDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+Arts::TypeDef Arts::InterfaceRepo_stub::queryType(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a717565727954797065000000000e417274733a3a5479706544656600000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return Arts::TypeDef(); // error occurred
+ Arts::TypeDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+Arts::EnumDef Arts::InterfaceRepo_stub::queryEnum(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a7175657279456e756d000000000e417274733a3a456e756d44656600000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return Arts::EnumDef(); // error occurred
+ Arts::EnumDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryChildren(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000e71756572794368696c6472656e00000000082a737472696e6700000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryInterfaces()
+{
+ long methodID = _lookupMethodFast("method:000000107175657279496e746572666163657300000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryTypes()
+{
+ long methodID = _lookupMethodFast("method:0000000b7175657279547970657300000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<std::string> * Arts::InterfaceRepo_stub::queryEnums()
+{
+ long methodID = _lookupMethodFast("method:0000000b7175657279456e756d7300000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::InterfaceRepo_skel::_interfaceName()
+{
+ return "Arts::InterfaceRepo";
+}
+
+bool Arts::InterfaceRepo_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::InterfaceRepo") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::InterfaceRepo_skel::_interfaceNameSkel()
+{
+ return "Arts::InterfaceRepo";
+}
+
+// insertModule
+static void _dispatch_Arts_InterfaceRepo_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::ModuleDef newModule(*request);
+ result->writeLong(((Arts::InterfaceRepo_skel *)object)->insertModule(newModule));
+}
+
+// removeModule
+static void _dispatch_Arts_InterfaceRepo_01(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ long moduleID = request->readLong();
+ ((Arts::InterfaceRepo_skel *)object)->removeModule(moduleID);
+}
+
+// queryInterface
+static void _dispatch_Arts_InterfaceRepo_02(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::InterfaceDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryInterface(name);
+ _returnCode.writeType(*result);
+}
+
+// queryType
+static void _dispatch_Arts_InterfaceRepo_03(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::TypeDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryType(name);
+ _returnCode.writeType(*result);
+}
+
+// queryEnum
+static void _dispatch_Arts_InterfaceRepo_04(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::EnumDef _returnCode = ((Arts::InterfaceRepo_skel *)object)->queryEnum(name);
+ _returnCode.writeType(*result);
+}
+
+// queryChildren
+static void _dispatch_Arts_InterfaceRepo_05(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryChildren(name);
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// queryInterfaces
+static void _dispatch_Arts_InterfaceRepo_06(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryInterfaces();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// queryTypes
+static void _dispatch_Arts_InterfaceRepo_07(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryTypes();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// queryEnums
+static void _dispatch_Arts_InterfaceRepo_08(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::InterfaceRepo_skel *)object)->queryEnums();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+void Arts::InterfaceRepo_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000d696e736572744d6f64756c6500000000056c6f6e670000"
+ "0000020000000100000010417274733a3a4d6f64756c65446566000000000a6e65"
+ "774d6f64756c650000000000000000000000000d72656d6f76654d6f64756c6500"
+ "00000005766f6964000000000200000001000000056c6f6e6700000000096d6f64"
+ "756c6549440000000000000000000000000f7175657279496e7465726661636500"
+ "00000013417274733a3a496e746572666163654465660000000002000000010000"
+ "0007737472696e6700000000056e616d650000000000000000000000000a717565"
+ "727954797065000000000e417274733a3a54797065446566000000000200000001"
+ "00000007737472696e6700000000056e616d650000000000000000000000000a71"
+ "75657279456e756d000000000e417274733a3a456e756d44656600000000020000"
+ "000100000007737472696e6700000000056e616d65000000000000000000000000"
+ "0e71756572794368696c6472656e00000000082a737472696e6700000000020000"
+ "000100000007737472696e6700000000056e616d65000000000000000000000000"
+ "107175657279496e746572666163657300000000082a737472696e670000000002"
+ "00000000000000000000000b7175657279547970657300000000082a737472696e"
+ "67000000000200000000000000000000000b7175657279456e756d730000000008"
+ "2a737472696e6700000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_InterfaceRepo_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_03,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_04,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_05,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_06,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_07,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_InterfaceRepo_08,this,Arts::MethodDef(m));
+}
+
+Arts::InterfaceRepo_skel::InterfaceRepo_skel()
+{
+}
+
+Arts::Object_base* Arts::InterfaceRepo::_Creator() {
+ return Arts::InterfaceRepo_base::_create();
+}
+
+unsigned long Arts::InterfaceRepo_base::_IID = Arts::MCOPUtils::makeIID("Arts::InterfaceRepo");
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::InterfaceRepoV2_base *castedObject = (Arts::InterfaceRepoV2_base *)skel->_cast(Arts::InterfaceRepoV2_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::InterfaceRepoV2_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::InterfaceRepoV2_base *castedObject = (Arts::InterfaceRepoV2_base *)object._base()->_cast(Arts::InterfaceRepoV2_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::InterfaceRepoV2_base *Arts::InterfaceRepoV2_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::InterfaceRepoV2_base *result;
+ result = (Arts::InterfaceRepoV2_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::InterfaceRepoV2");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::InterfaceRepoV2_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::InterfaceRepoV2")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::InterfaceRepoV2_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::InterfaceRepoV2_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::InterfaceRepoV2_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::InterfaceRepoV2_base::_IID) return (Arts::InterfaceRepoV2_base *)this;
+ if(iid == Arts::InterfaceRepo_base::_IID) return (Arts::InterfaceRepo_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::InterfaceRepoV2_stub::InterfaceRepoV2_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::InterfaceRepoV2_stub::InterfaceRepoV2_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+Arts::TypeIdentification Arts::InterfaceRepoV2_stub::identifyType(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000d6964656e74696679547970650000000019417274733a3a547970654964656e74696669636174696f6e00000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return (Arts::TypeIdentification)0; // error occurred
+ Arts::TypeIdentification returnCode = (Arts::TypeIdentification)result->readLong();
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::InterfaceRepoV2_skel::_interfaceName()
+{
+ return "Arts::InterfaceRepoV2";
+}
+
+bool Arts::InterfaceRepoV2_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::InterfaceRepoV2") return true;
+ if (interfacename == "Arts::InterfaceRepo") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::InterfaceRepoV2_skel::_interfaceNameSkel()
+{
+ return "Arts::InterfaceRepoV2";
+}
+
+// identifyType
+static void _dispatch_Arts_InterfaceRepoV2_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ result->writeLong(((Arts::InterfaceRepoV2_skel *)object)->identifyType(name));
+}
+
+void Arts::InterfaceRepoV2_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000d6964656e74696679547970650000000019417274733a3a"
+ "547970654964656e74696669636174696f6e000000000200000001000000077374"
+ "72696e6700000000056e616d65000000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_InterfaceRepoV2_00,this,Arts::MethodDef(m));
+ Arts::InterfaceRepo_skel::_buildMethodTable();
+}
+
+Arts::InterfaceRepoV2_skel::InterfaceRepoV2_skel()
+{
+}
+
+Arts::Object_base* Arts::InterfaceRepoV2::_Creator() {
+ return Arts::InterfaceRepoV2_base::_create();
+}
+
+unsigned long Arts::InterfaceRepoV2_base::_IID = Arts::MCOPUtils::makeIID("Arts::InterfaceRepoV2");
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::FlowSystemSender_base *castedObject = (Arts::FlowSystemSender_base *)skel->_cast(Arts::FlowSystemSender_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::FlowSystemSender_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::FlowSystemSender_base *castedObject = (Arts::FlowSystemSender_base *)object._base()->_cast(Arts::FlowSystemSender_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::FlowSystemSender_base *Arts::FlowSystemSender_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::FlowSystemSender_base *result;
+ result = (Arts::FlowSystemSender_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystemSender");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::FlowSystemSender_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::FlowSystemSender")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::FlowSystemSender_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::FlowSystemSender_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::FlowSystemSender_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::FlowSystemSender_base::_IID) return (Arts::FlowSystemSender_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::FlowSystemSender_stub::FlowSystemSender_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::FlowSystemSender_stub::FlowSystemSender_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::FlowSystemSender_stub::processed()
+{
+ long methodID = _lookupMethodFast("method:0000000a70726f6365737365640000000005766f696400000000010000000000000000");
+ Arts::Buffer *request = Arts::Dispatcher::the()->createOnewayRequest(_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+}
+
+void Arts::FlowSystemSender_stub::disconnect()
+{
+ long methodID = _lookupMethodFast("method:0000000b646973636f6e6e6563740000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::string Arts::FlowSystemSender_skel::_interfaceName()
+{
+ return "Arts::FlowSystemSender";
+}
+
+bool Arts::FlowSystemSender_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::FlowSystemSender") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::FlowSystemSender_skel::_interfaceNameSkel()
+{
+ return "Arts::FlowSystemSender";
+}
+
+// processed
+static void _dispatch_Arts_FlowSystemSender_00(void *object, Arts::Buffer *)
+{
+ ((Arts::FlowSystemSender_skel *)object)->processed();
+}
+
+// disconnect
+static void _dispatch_Arts_FlowSystemSender_01(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::FlowSystemSender_skel *)object)->disconnect();
+}
+
+void Arts::FlowSystemSender_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000a70726f6365737365640000000005766f69640000000001"
+ "00000000000000000000000b646973636f6e6e6563740000000005766f69640000"
+ "0000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_FlowSystemSender_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystemSender_01,this,Arts::MethodDef(m));
+}
+
+Arts::FlowSystemSender_skel::FlowSystemSender_skel()
+{
+}
+
+Arts::Object_base* Arts::FlowSystemSender::_Creator() {
+ return Arts::FlowSystemSender_base::_create();
+}
+
+unsigned long Arts::FlowSystemSender_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystemSender");
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::FlowSystemReceiver_base *castedObject = (Arts::FlowSystemReceiver_base *)skel->_cast(Arts::FlowSystemReceiver_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::FlowSystemReceiver_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::FlowSystemReceiver_base *castedObject = (Arts::FlowSystemReceiver_base *)object._base()->_cast(Arts::FlowSystemReceiver_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::FlowSystemReceiver_base *Arts::FlowSystemReceiver_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::FlowSystemReceiver_base *result;
+ result = (Arts::FlowSystemReceiver_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystemReceiver");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::FlowSystemReceiver_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::FlowSystemReceiver")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::FlowSystemReceiver_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::FlowSystemReceiver_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::FlowSystemReceiver_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::FlowSystemReceiver_base::_IID) return (Arts::FlowSystemReceiver_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::FlowSystemReceiver_stub::FlowSystemReceiver_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::FlowSystemReceiver_stub::FlowSystemReceiver_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::FlowSystemReceiver_stub::disconnect()
+{
+ long methodID = _lookupMethodFast("method:0000000b646973636f6e6e6563740000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+long Arts::FlowSystemReceiver_stub::receiveHandlerID()
+{
+ long methodID = _lookupMethodFast("method:000000165f6765745f7265636569766548616e646c6572494400000000056c6f6e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return 0; // error occurred
+ long returnCode = result->readLong();
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::FlowSystemReceiver_skel::_interfaceName()
+{
+ return "Arts::FlowSystemReceiver";
+}
+
+bool Arts::FlowSystemReceiver_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::FlowSystemReceiver") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::FlowSystemReceiver_skel::_interfaceNameSkel()
+{
+ return "Arts::FlowSystemReceiver";
+}
+
+// disconnect
+static void _dispatch_Arts_FlowSystemReceiver_00(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::FlowSystemReceiver_skel *)object)->disconnect();
+}
+
+// _get_receiveHandlerID
+static void _dispatch_Arts_FlowSystemReceiver_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeLong(((Arts::FlowSystemReceiver_skel *)object)->receiveHandlerID());
+}
+
+void Arts::FlowSystemReceiver_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000b646973636f6e6e6563740000000005766f696400000000"
+ "020000000000000000000000165f6765745f7265636569766548616e646c657249"
+ "4400000000056c6f6e6700000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_FlowSystemReceiver_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystemReceiver_01,this,Arts::MethodDef(m));
+}
+
+Arts::FlowSystemReceiver_skel::FlowSystemReceiver_skel()
+{
+}
+
+Arts::Object_base* Arts::FlowSystemReceiver::_Creator() {
+ return Arts::FlowSystemReceiver_base::_create();
+}
+
+unsigned long Arts::FlowSystemReceiver_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystemReceiver");
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::FlowSystem_base *castedObject = (Arts::FlowSystem_base *)skel->_cast(Arts::FlowSystem_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::FlowSystem_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::FlowSystem_base *castedObject = (Arts::FlowSystem_base *)object._base()->_cast(Arts::FlowSystem_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::FlowSystem_base *Arts::FlowSystem_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::FlowSystem_base *result;
+ result = (Arts::FlowSystem_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::FlowSystem");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::FlowSystem_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::FlowSystem")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::FlowSystem_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::FlowSystem_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::FlowSystem_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::FlowSystem_base::_IID) return (Arts::FlowSystem_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::FlowSystem_stub::FlowSystem_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::FlowSystem_stub::FlowSystem_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::FlowSystem_stub::startObject(Arts::Object node)
+{
+ long methodID = _lookupMethodFast("method:0000000c73746172744f626a6563740000000005766f6964000000000200000001000000076f626a65637400000000056e6f6465000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::FlowSystem_stub::stopObject(Arts::Object node)
+{
+ long methodID = _lookupMethodFast("method:0000000b73746f704f626a6563740000000005766f6964000000000200000001000000076f626a65637400000000056e6f6465000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::FlowSystem_stub::connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ long methodID = _lookupMethodFast("method:0000000e636f6e6e6563744f626a6563740000000005766f6964000000000200000004000000076f626a656374000000000d736f757263654f626a656374000000000000000007737472696e67000000000b736f75726365506f72740000000000000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,sourceObject._base());
+ request->writeString(sourcePort);
+ Arts::writeObject(*request,destObject._base());
+ request->writeString(destPort);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::FlowSystem_stub::disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ long methodID = _lookupMethodFast("method:00000011646973636f6e6e6563744f626a6563740000000005766f6964000000000200000004000000076f626a656374000000000d736f757263654f626a656374000000000000000007737472696e67000000000b736f75726365506f72740000000000000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,sourceObject._base());
+ request->writeString(sourcePort);
+ Arts::writeObject(*request,destObject._base());
+ request->writeString(destPort);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+Arts::AttributeType Arts::FlowSystem_stub::queryFlags(Arts::Object node, const std::string& port)
+{
+ long methodID = _lookupMethodFast("method:0000000b7175657279466c6167730000000014417274733a3a41747472696275746554797065000000000200000002000000076f626a65637400000000056e6f6465000000000000000007737472696e670000000005706f7274000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->writeString(port);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return (Arts::AttributeType)0; // error occurred
+ Arts::AttributeType returnCode = (Arts::AttributeType)result->readLong();
+ delete result;
+ return returnCode;
+}
+
+void Arts::FlowSystem_stub::setFloatValue(Arts::Object node, const std::string& port, float value)
+{
+ long methodID = _lookupMethodFast("method:0000000e736574466c6f617456616c75650000000005766f6964000000000200000003000000076f626a65637400000000056e6f6465000000000000000007737472696e670000000005706f7274000000000000000006666c6f6174000000000676616c7565000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,node._base());
+ request->writeString(port);
+ request->writeFloat(value);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+Arts::FlowSystemReceiver Arts::FlowSystem_stub::createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender)
+{
+ long methodID = _lookupMethodFast("method:0000000f63726561746552656365697665720000000019417274733a3a466c6f7753797374656d5265636569766572000000000200000003000000076f626a656374000000000b646573744f626a656374000000000000000007737472696e67000000000964657374506f7274000000000000000017417274733a3a466c6f7753797374656d53656e646572000000000773656e646572000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,destObject._base());
+ request->writeString(destPort);
+ Arts::writeObject(*request,sender._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::FlowSystemReceiver::null();
+ Arts::FlowSystemReceiver_base* returnCode;
+ Arts::readObject(*result,returnCode);
+ delete result;
+ return Arts::FlowSystemReceiver::_from_base(returnCode);
+}
+
+std::string Arts::FlowSystem_skel::_interfaceName()
+{
+ return "Arts::FlowSystem";
+}
+
+bool Arts::FlowSystem_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::FlowSystem") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::FlowSystem_skel::_interfaceNameSkel()
+{
+ return "Arts::FlowSystem";
+}
+
+// startObject
+static void _dispatch_Arts_FlowSystem_00(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ ((Arts::FlowSystem_skel *)object)->startObject(node);
+}
+
+// stopObject
+static void _dispatch_Arts_FlowSystem_01(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ ((Arts::FlowSystem_skel *)object)->stopObject(node);
+}
+
+// connectObject
+static void _dispatch_Arts_FlowSystem_02(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_sourceObject;
+ Arts::readObject(*request,_temp_sourceObject);
+ Arts::Object sourceObject = Arts::Object::_from_base(_temp_sourceObject);
+ std::string sourcePort;
+ request->readString(sourcePort);
+ Arts::Object_base* _temp_destObject;
+ Arts::readObject(*request,_temp_destObject);
+ Arts::Object destObject = Arts::Object::_from_base(_temp_destObject);
+ std::string destPort;
+ request->readString(destPort);
+ ((Arts::FlowSystem_skel *)object)->connectObject(sourceObject,sourcePort,destObject,destPort);
+}
+
+// disconnectObject
+static void _dispatch_Arts_FlowSystem_03(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_sourceObject;
+ Arts::readObject(*request,_temp_sourceObject);
+ Arts::Object sourceObject = Arts::Object::_from_base(_temp_sourceObject);
+ std::string sourcePort;
+ request->readString(sourcePort);
+ Arts::Object_base* _temp_destObject;
+ Arts::readObject(*request,_temp_destObject);
+ Arts::Object destObject = Arts::Object::_from_base(_temp_destObject);
+ std::string destPort;
+ request->readString(destPort);
+ ((Arts::FlowSystem_skel *)object)->disconnectObject(sourceObject,sourcePort,destObject,destPort);
+}
+
+// queryFlags
+static void _dispatch_Arts_FlowSystem_04(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ std::string port;
+ request->readString(port);
+ result->writeLong(((Arts::FlowSystem_skel *)object)->queryFlags(node,port));
+}
+
+// setFloatValue
+static void _dispatch_Arts_FlowSystem_05(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ Arts::Object_base* _temp_node;
+ Arts::readObject(*request,_temp_node);
+ Arts::Object node = Arts::Object::_from_base(_temp_node);
+ std::string port;
+ request->readString(port);
+ float value = request->readFloat();
+ ((Arts::FlowSystem_skel *)object)->setFloatValue(node,port,value);
+}
+
+// createReceiver
+static void _dispatch_Arts_FlowSystem_06(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::Object_base* _temp_destObject;
+ Arts::readObject(*request,_temp_destObject);
+ Arts::Object destObject = Arts::Object::_from_base(_temp_destObject);
+ std::string destPort;
+ request->readString(destPort);
+ Arts::FlowSystemSender_base* _temp_sender;
+ Arts::readObject(*request,_temp_sender);
+ Arts::FlowSystemSender sender = Arts::FlowSystemSender::_from_base(_temp_sender);
+ Arts::FlowSystemReceiver returnCode = ((Arts::FlowSystem_skel *)object)->createReceiver(destObject,destPort,sender);
+ Arts::writeObject(*result,returnCode._base());
+}
+
+void Arts::FlowSystem_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000c73746172744f626a6563740000000005766f6964000000"
+ "000200000001000000076f626a65637400000000056e6f64650000000000000000"
+ "000000000b73746f704f626a6563740000000005766f6964000000000200000001"
+ "000000076f626a65637400000000056e6f64650000000000000000000000000e63"
+ "6f6e6e6563744f626a6563740000000005766f6964000000000200000004000000"
+ "076f626a656374000000000d736f757263654f626a656374000000000000000007"
+ "737472696e67000000000b736f75726365506f72740000000000000000076f626a"
+ "656374000000000b646573744f626a656374000000000000000007737472696e67"
+ "000000000964657374506f727400000000000000000000000011646973636f6e6e"
+ "6563744f626a6563740000000005766f6964000000000200000004000000076f62"
+ "6a656374000000000d736f757263654f626a656374000000000000000007737472"
+ "696e67000000000b736f75726365506f72740000000000000000076f626a656374"
+ "000000000b646573744f626a656374000000000000000007737472696e67000000"
+ "000964657374506f72740000000000000000000000000b7175657279466c616773"
+ "0000000014417274733a3a41747472696275746554797065000000000200000002"
+ "000000076f626a65637400000000056e6f6465000000000000000007737472696e"
+ "670000000005706f72740000000000000000000000000e736574466c6f61745661"
+ "6c75650000000005766f6964000000000200000003000000076f626a6563740000"
+ "0000056e6f6465000000000000000007737472696e670000000005706f72740000"
+ "00000000000006666c6f6174000000000676616c75650000000000000000000000"
+ "000f63726561746552656365697665720000000019417274733a3a466c6f775379"
+ "7374656d5265636569766572000000000200000003000000076f626a6563740000"
+ "00000b646573744f626a656374000000000000000007737472696e670000000009"
+ "64657374506f7274000000000000000017417274733a3a466c6f7753797374656d"
+ "53656e646572000000000773656e646572000000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_FlowSystem_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_03,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_04,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_05,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_FlowSystem_06,this,Arts::MethodDef(m));
+}
+
+Arts::FlowSystem_skel::FlowSystem_skel()
+{
+}
+
+Arts::Object_base* Arts::FlowSystem::_Creator() {
+ return Arts::FlowSystem_base::_create();
+}
+
+unsigned long Arts::FlowSystem_base::_IID = Arts::MCOPUtils::makeIID("Arts::FlowSystem");
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::GlobalComm_base *castedObject = (Arts::GlobalComm_base *)skel->_cast(Arts::GlobalComm_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::GlobalComm_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::GlobalComm_base *castedObject = (Arts::GlobalComm_base *)object._base()->_cast(Arts::GlobalComm_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::GlobalComm_base *Arts::GlobalComm_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::GlobalComm_base *result;
+ result = (Arts::GlobalComm_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::GlobalComm");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::GlobalComm_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::GlobalComm")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::GlobalComm_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::GlobalComm_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::GlobalComm_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::GlobalComm_base::_IID) return (Arts::GlobalComm_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::GlobalComm_stub::GlobalComm_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::GlobalComm_stub::GlobalComm_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+bool Arts::GlobalComm_stub::put(const std::string& variable, const std::string& value)
+{
+ long methodID = _lookupMethodFast("method:000000047075740000000008626f6f6c65616e00000000020000000200000007737472696e6700000000097661726961626c65000000000000000007737472696e67000000000676616c7565000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(variable);
+ request->writeString(value);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return false; // error occurred
+ bool returnCode = result->readBool();
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::GlobalComm_stub::get(const std::string& variable)
+{
+ long methodID = _lookupMethodFast("method:000000046765740000000007737472696e6700000000020000000100000007737472696e6700000000097661726961626c65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(variable);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+void Arts::GlobalComm_stub::erase(const std::string& variable)
+{
+ long methodID = _lookupMethodFast("method:0000000665726173650000000005766f696400000000020000000100000007737472696e6700000000097661726961626c65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(variable);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::string Arts::GlobalComm_skel::_interfaceName()
+{
+ return "Arts::GlobalComm";
+}
+
+bool Arts::GlobalComm_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::GlobalComm") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::GlobalComm_skel::_interfaceNameSkel()
+{
+ return "Arts::GlobalComm";
+}
+
+// put
+static void _dispatch_Arts_GlobalComm_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string variable;
+ request->readString(variable);
+ std::string value;
+ request->readString(value);
+ result->writeBool(((Arts::GlobalComm_skel *)object)->put(variable,value));
+}
+
+// get
+static void _dispatch_Arts_GlobalComm_01(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string variable;
+ request->readString(variable);
+ result->writeString(((Arts::GlobalComm_skel *)object)->get(variable));
+}
+
+// erase
+static void _dispatch_Arts_GlobalComm_02(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ std::string variable;
+ request->readString(variable);
+ ((Arts::GlobalComm_skel *)object)->erase(variable);
+}
+
+void Arts::GlobalComm_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:000000047075740000000008626f6f6c65616e0000000002000000"
+ "0200000007737472696e6700000000097661726961626c65000000000000000007"
+ "737472696e67000000000676616c75650000000000000000000000000467657400"
+ "00000007737472696e6700000000020000000100000007737472696e6700000000"
+ "097661726961626c65000000000000000000000000066572617365000000000576"
+ "6f696400000000020000000100000007737472696e670000000009766172696162"
+ "6c65000000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_GlobalComm_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_GlobalComm_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_GlobalComm_02,this,Arts::MethodDef(m));
+}
+
+Arts::GlobalComm_skel::GlobalComm_skel()
+{
+}
+
+Arts::Object_base* Arts::GlobalComm::_Creator() {
+ return Arts::GlobalComm_base::_create();
+}
+
+unsigned long Arts::GlobalComm_base::_IID = Arts::MCOPUtils::makeIID("Arts::GlobalComm");
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::TmpGlobalComm_base *castedObject = (Arts::TmpGlobalComm_base *)skel->_cast(Arts::TmpGlobalComm_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::TmpGlobalComm_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::TmpGlobalComm_base *castedObject = (Arts::TmpGlobalComm_base *)object._base()->_cast(Arts::TmpGlobalComm_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::TmpGlobalComm_base *Arts::TmpGlobalComm_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::TmpGlobalComm_base *result;
+ result = (Arts::TmpGlobalComm_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TmpGlobalComm");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::TmpGlobalComm_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::TmpGlobalComm")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::TmpGlobalComm_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::TmpGlobalComm_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::TmpGlobalComm_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::TmpGlobalComm_base::_IID) return (Arts::TmpGlobalComm_base *)this;
+ if(iid == Arts::GlobalComm_base::_IID) return (Arts::GlobalComm_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::TmpGlobalComm_stub::TmpGlobalComm_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::TmpGlobalComm_stub::TmpGlobalComm_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+std::string Arts::TmpGlobalComm_skel::_interfaceName()
+{
+ return "Arts::TmpGlobalComm";
+}
+
+bool Arts::TmpGlobalComm_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::TmpGlobalComm") return true;
+ if (interfacename == "Arts::GlobalComm") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::TmpGlobalComm_skel::_interfaceNameSkel()
+{
+ return "Arts::TmpGlobalComm";
+}
+
+void Arts::TmpGlobalComm_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:",
+ "MethodTable"
+ );
+ Arts::GlobalComm_skel::_buildMethodTable();
+}
+
+Arts::TmpGlobalComm_skel::TmpGlobalComm_skel()
+{
+}
+
+Arts::Object_base* Arts::TmpGlobalComm::_Creator() {
+ return Arts::TmpGlobalComm_base::_create();
+}
+
+unsigned long Arts::TmpGlobalComm_base::_IID = Arts::MCOPUtils::makeIID("Arts::TmpGlobalComm");
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::TraderOffer_base *castedObject = (Arts::TraderOffer_base *)skel->_cast(Arts::TraderOffer_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::TraderOffer_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::TraderOffer_base *castedObject = (Arts::TraderOffer_base *)object._base()->_cast(Arts::TraderOffer_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::TraderOffer_base *Arts::TraderOffer_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::TraderOffer_base *result;
+ result = (Arts::TraderOffer_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TraderOffer");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::TraderOffer_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::TraderOffer")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::TraderOffer_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::TraderOffer_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::TraderOffer_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::TraderOffer_base::_IID) return (Arts::TraderOffer_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::TraderOffer_stub::TraderOffer_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::TraderOffer_stub::TraderOffer_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+std::vector<std::string> * Arts::TraderOffer_stub::getProperty(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000c67657450726f706572747900000000082a737472696e6700000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::TraderOffer_stub::interfaceName()
+{
+ long methodID = _lookupMethodFast("method:000000135f6765745f696e746572666163654e616d650000000007737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+std::string Arts::TraderOffer_skel::_interfaceName()
+{
+ return "Arts::TraderOffer";
+}
+
+bool Arts::TraderOffer_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::TraderOffer") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::TraderOffer_skel::_interfaceNameSkel()
+{
+ return "Arts::TraderOffer";
+}
+
+// getProperty
+static void _dispatch_Arts_TraderOffer_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ std::vector<std::string> *_returnCode = ((Arts::TraderOffer_skel *)object)->getProperty(name);
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// _get_interfaceName
+static void _dispatch_Arts_TraderOffer_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::TraderOffer_skel *)object)->interfaceName());
+}
+
+void Arts::TraderOffer_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000c67657450726f706572747900000000082a737472696e67"
+ "00000000020000000100000007737472696e6700000000056e616d650000000000"
+ "00000000000000135f6765745f696e746572666163654e616d6500000000077374"
+ "72696e6700000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_TraderOffer_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_TraderOffer_01,this,Arts::MethodDef(m));
+}
+
+Arts::TraderOffer_skel::TraderOffer_skel()
+{
+}
+
+Arts::Object_base* Arts::TraderOffer::_Creator() {
+ return Arts::TraderOffer_base::_create();
+}
+
+unsigned long Arts::TraderOffer_base::_IID = Arts::MCOPUtils::makeIID("Arts::TraderOffer");
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::TraderQuery_base *castedObject = (Arts::TraderQuery_base *)skel->_cast(Arts::TraderQuery_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::TraderQuery_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::TraderQuery_base *castedObject = (Arts::TraderQuery_base *)object._base()->_cast(Arts::TraderQuery_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::TraderQuery_base *Arts::TraderQuery_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::TraderQuery_base *result;
+ result = (Arts::TraderQuery_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::TraderQuery");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::TraderQuery_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::TraderQuery")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::TraderQuery_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::TraderQuery_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::TraderQuery_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::TraderQuery_base::_IID) return (Arts::TraderQuery_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::TraderQuery_stub::TraderQuery_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::TraderQuery_stub::TraderQuery_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+void Arts::TraderQuery_stub::supports(const std::string& property, const std::string& value)
+{
+ long methodID = _lookupMethodFast("method:00000009737570706f7274730000000005766f696400000000020000000200000007737472696e67000000000970726f7065727479000000000000000007737472696e67000000000676616c7565000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(property);
+ request->writeString(value);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::vector<Arts::TraderOffer> * Arts::TraderQuery_stub::query()
+{
+ long methodID = _lookupMethodFast("method:00000006717565727900000000132a417274733a3a5472616465724f6666657200000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<Arts::TraderOffer> *_returnCode = new std::vector<Arts::TraderOffer>;
+ if(!result) return _returnCode; // error occurred
+ Arts::readObjectSeq(*result,*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::TraderQuery_skel::_interfaceName()
+{
+ return "Arts::TraderQuery";
+}
+
+bool Arts::TraderQuery_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::TraderQuery") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::TraderQuery_skel::_interfaceNameSkel()
+{
+ return "Arts::TraderQuery";
+}
+
+// supports
+static void _dispatch_Arts_TraderQuery_00(void *object, Arts::Buffer *request, Arts::Buffer *)
+{
+ std::string property;
+ request->readString(property);
+ std::string value;
+ request->readString(value);
+ ((Arts::TraderQuery_skel *)object)->supports(property,value);
+}
+
+// query
+static void _dispatch_Arts_TraderQuery_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<Arts::TraderOffer> *_returnCode = ((Arts::TraderQuery_skel *)object)->query();
+ Arts::writeObjectSeq(*result,*_returnCode);
+ delete _returnCode;
+}
+
+void Arts::TraderQuery_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:00000009737570706f7274730000000005766f6964000000000200"
+ "00000200000007737472696e67000000000970726f706572747900000000000000"
+ "0007737472696e67000000000676616c7565000000000000000000000000067175"
+ "65727900000000132a417274733a3a5472616465724f6666657200000000020000"
+ "000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_TraderQuery_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_TraderQuery_01,this,Arts::MethodDef(m));
+}
+
+Arts::TraderQuery_skel::TraderQuery_skel()
+{
+}
+
+Arts::Object_base* Arts::TraderQuery::_Creator() {
+ return Arts::TraderQuery_base::_create();
+}
+
+unsigned long Arts::TraderQuery_base::_IID = Arts::MCOPUtils::makeIID("Arts::TraderQuery");
+
+Arts::Loader_base *Arts::Loader_base::_create(const std::string& subClass)
+{
+ Arts::Object_skel *skel = Arts::ObjectManager::the()->create(subClass);
+ assert(skel);
+ Arts::Loader_base *castedObject = (Arts::Loader_base *)skel->_cast(Arts::Loader_base::_IID);
+ assert(castedObject);
+ return castedObject;
+}
+
+Arts::Loader_base *Arts::Loader_base::_fromString(std::string objectref)
+{
+ Arts::ObjectReference r;
+
+ if(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))
+ return Arts::Loader_base::_fromReference(r,true);
+ return 0;
+}
+
+Arts::Loader_base *Arts::Loader_base::_fromDynamicCast(const Arts::Object& object)
+{
+ if(object.isNull()) return 0;
+
+ Arts::Loader_base *castedObject = (Arts::Loader_base *)object._base()->_cast(Arts::Loader_base::_IID);
+ if(castedObject) return castedObject->_copy();
+
+ return _fromString(object._toString());
+}
+
+Arts::Loader_base *Arts::Loader_base::_fromReference(Arts::ObjectReference r, bool needcopy)
+{
+ Arts::Loader_base *result;
+ result = (Arts::Loader_base *)Arts::Dispatcher::the()->connectObjectLocal(r,"Arts::Loader");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Arts::Connection *conn = Arts::Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Arts::Loader_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ if (!result->_isCompatibleWith("Arts::Loader")) {
+ result->_release();
+ return 0;
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<std::string> Arts::Loader_base::_defaultPortsIn() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+std::vector<std::string> Arts::Loader_base::_defaultPortsOut() const {
+ std::vector<std::string> ret;
+ return ret;
+}
+
+void *Arts::Loader_base::_cast(unsigned long iid)
+{
+ if(iid == Arts::Loader_base::_IID) return (Arts::Loader_base *)this;
+ if(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;
+ return 0;
+}
+
+Arts::Loader_stub::Loader_stub()
+{
+ // constructor for subclasses (don't use directly)
+}
+
+Arts::Loader_stub::Loader_stub(Arts::Connection *connection, long objectID)
+ : Arts::Object_stub(connection, objectID)
+{
+ // constructor to create a stub for an object
+}
+
+Arts::Object Arts::Loader_stub::loadObject(Arts::TraderOffer offer)
+{
+ long methodID = _lookupMethodFast("method:0000000b6c6f61644f626a65637400000000076f626a65637400000000020000000100000012417274733a3a5472616465724f6666657200000000066f66666572000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ Arts::writeObject(*request,offer._base());
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::Object::null();
+ Arts::Object_base* returnCode;
+ Arts::readObject(*result,returnCode);
+ delete result;
+ return Arts::Object::_from_base(returnCode);
+}
+
+std::string Arts::Loader_stub::dataVersion()
+{
+ long methodID = _lookupMethodFast("method:000000115f6765745f6461746156657273696f6e0000000007737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+std::vector<Arts::TraderEntry> * Arts::Loader_stub::traderEntries()
+{
+ long methodID = _lookupMethodFast("method:000000135f6765745f747261646572456e747269657300000000132a417274733a3a547261646572456e74727900000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<Arts::TraderEntry> *_returnCode = new std::vector<Arts::TraderEntry>;
+ if(!result) return _returnCode; // error occurred
+ Arts::readTypeSeq(*result,*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::vector<Arts::ModuleDef> * Arts::Loader_stub::modules()
+{
+ long methodID = _lookupMethodFast("method:0000000d5f6765745f6d6f64756c657300000000112a417274733a3a4d6f64756c6544656600000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<Arts::ModuleDef> *_returnCode = new std::vector<Arts::ModuleDef>;
+ if(!result) return _returnCode; // error occurred
+ Arts::readTypeSeq(*result,*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+std::string Arts::Loader_skel::_interfaceName()
+{
+ return "Arts::Loader";
+}
+
+bool Arts::Loader_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename == "Arts::Loader") return true;
+ if (interfacename == "Arts::Object") return true;
+ return false;
+}
+
+std::string Arts::Loader_skel::_interfaceNameSkel()
+{
+ return "Arts::Loader";
+}
+
+// loadObject
+static void _dispatch_Arts_Loader_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::TraderOffer_base* _temp_offer;
+ Arts::readObject(*request,_temp_offer);
+ Arts::TraderOffer offer = Arts::TraderOffer::_from_base(_temp_offer);
+ Arts::Object returnCode = ((Arts::Loader_skel *)object)->loadObject(offer);
+ Arts::writeObject(*result,returnCode._base());
+}
+
+// _get_dataVersion
+static void _dispatch_Arts_Loader_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::Loader_skel *)object)->dataVersion());
+}
+
+// _get_traderEntries
+static void _dispatch_Arts_Loader_02(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<Arts::TraderEntry> *_returnCode = ((Arts::Loader_skel *)object)->traderEntries();
+ Arts::writeTypeSeq(*result,*_returnCode);
+ delete _returnCode;
+}
+
+// _get_modules
+static void _dispatch_Arts_Loader_03(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<Arts::ModuleDef> *_returnCode = ((Arts::Loader_skel *)object)->modules();
+ Arts::writeTypeSeq(*result,*_returnCode);
+ delete _returnCode;
+}
+
+void Arts::Loader_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000b6c6f61644f626a65637400000000076f626a6563740000"
+ "0000020000000100000012417274733a3a5472616465724f666665720000000006"
+ "6f66666572000000000000000000000000115f6765745f6461746156657273696f"
+ "6e0000000007737472696e6700000000020000000000000000000000135f676574"
+ "5f747261646572456e747269657300000000132a417274733a3a54726164657245"
+ "6e747279000000000200000000000000000000000d5f6765745f6d6f64756c6573"
+ "00000000112a417274733a3a4d6f64756c65446566000000000200000000000000"
+ "00",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_Loader_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Loader_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Loader_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Loader_03,this,Arts::MethodDef(m));
+}
+
+Arts::Loader_skel::Loader_skel()
+{
+}
+
+Arts::Object_base* Arts::Loader::_Creator() {
+ return Arts::Loader_base::_create();
+}
+
+unsigned long Arts::Loader_base::_IID = Arts::MCOPUtils::makeIID("Arts::Loader");
+
+static Arts::IDLFileReg IDLFileReg_core("core",
+ "IDLFile:00000001000000000500000012417274733a3a4865616465724d6167696300"
+ "000000010000000b4d434f505f4d41474943004d434f50000000000000000000000012"
+ "417274733a3a4d657373616765547970650000000007000000136d636f704d65737361"
+ "6765496e76616c6964000000000000000000000000106d636f7053657276657248656c"
+ "6c6f000000000100000000000000106d636f70436c69656e7448656c6c6f0000000002"
+ "000000000000000f6d636f70417574684163636570740000000003000000000000000f"
+ "6d636f70496e766f636174696f6e0000000004000000000000000b6d636f7052657475"
+ "726e000000000500000000000000156d636f704f6e65776179496e766f636174696f6e"
+ "0000000006000000000000000000000011417274733a3a4d6574686f64547970650000"
+ "0000020000000d6d6574686f644f6e657761790000000001000000000000000d6d6574"
+ "686f6454776f7761790000000002000000000000000000000014417274733a3a417474"
+ "7269627574655479706500000000070000000973747265616d496e0000000001000000"
+ "000000000a73747265616d4f75740000000002000000000000000c73747265616d4d75"
+ "6c74690000000004000000000000001061747472696275746553747265616d00000000"
+ "0800000000000000136174747269627574654174747269627574650000000010000000"
+ "000000000c73747265616d4173796e630000000020000000000000000e73747265616d"
+ "44656661756c740000000040000000000000000000000019417274733a3a5479706549"
+ "64656e74696669636174696f6e000000000a0000000a7469556e6b6e6f776e00000000"
+ "0000000000000000077469566f69640000000001000000000000000774694c6f6e6700"
+ "0000000200000000000000077469427974650000000003000000000000000974695374"
+ "72696e670000000004000000000000000a7469426f6f6c65616e000000000500000000"
+ "000000087469466c6f6174000000000600000000000000077469456e756d0000000080"
+ "00000000000000077469547970650000000081000000000000000c7469496e74657266"
+ "61636500000000820000000000000000000000120000000d417274733a3a4865616465"
+ "72000000000300000012417274733a3a4865616465724d6167696300000000066d6167"
+ "69630000000000000000056c6f6e67000000000e6d6573736167654c656e6774680000"
+ "00000000000012417274733a3a4d65737361676554797065000000000c6d6573736167"
+ "655479706500000000000000000000000011417274733a3a496e766f636174696f6e00"
+ "00000003000000056c6f6e6700000000096f626a65637449440000000000000000056c"
+ "6f6e6700000000096d6574686f6449440000000000000000056c6f6e67000000000a72"
+ "657175657374494400000000000000000000000017417274733a3a4f6e65776179496e"
+ "766f636174696f6e0000000002000000056c6f6e6700000000096f626a656374494400"
+ "00000000000000056c6f6e6700000000096d6574686f64494400000000000000000000"
+ "000012417274733a3a53657276657248656c6c6f000000000400000007737472696e67"
+ "000000000c6d636f7056657273696f6e000000000000000007737472696e6700000000"
+ "0973657276657249440000000000000000082a737472696e67000000000e6175746850"
+ "726f746f636f6c73000000000000000007737472696e67000000000961757468536565"
+ "6400000000000000000000000012417274733a3a436c69656e7448656c6c6f00000000"
+ "0300000007737472696e67000000000973657276657249440000000000000000077374"
+ "72696e67000000000d6175746850726f746f636f6c000000000000000007737472696e"
+ "670000000009617574684461746100000000000000000000000011417274733a3a4175"
+ "74684163636570740000000001000000082a737472696e67000000000668696e747300"
+ "000000000000000000000016417274733a3a4f626a6563745265666572656e63650000"
+ "00000300000007737472696e6700000000097365727665724944000000000000000005"
+ "6c6f6e6700000000096f626a65637449440000000000000000082a737472696e670000"
+ "00000575726c730000000000000000000000000f417274733a3a506172616d44656600"
+ "0000000300000007737472696e67000000000574797065000000000000000007737472"
+ "696e6700000000056e616d650000000000000000082a737472696e6700000000066869"
+ "6e747300000000000000000000000010417274733a3a4d6574686f6444656600000000"
+ "0500000007737472696e6700000000056e616d65000000000000000007737472696e67"
+ "000000000574797065000000000000000011417274733a3a4d6574686f645479706500"
+ "00000006666c6167730000000000000000102a417274733a3a506172616d4465660000"
+ "00000a7369676e61747572650000000000000000082a737472696e6700000000066869"
+ "6e747300000000000000000000000013417274733a3a41747472696275746544656600"
+ "0000000400000007737472696e6700000000056e616d65000000000000000007737472"
+ "696e67000000000574797065000000000000000014417274733a3a4174747269627574"
+ "65547970650000000006666c6167730000000000000000082a737472696e6700000000"
+ "0668696e747300000000000000000000000013417274733a3a496e7465726661636544"
+ "6566000000000600000007737472696e6700000000056e616d65000000000000000008"
+ "2a737472696e670000000014696e68657269746564496e746572666163657300000000"
+ "00000000112a417274733a3a4d6574686f6444656600000000086d6574686f64730000"
+ "000000000000142a417274733a3a417474726962757465446566000000000b61747472"
+ "6962757465730000000000000000082a737472696e67000000000d64656661756c7450"
+ "6f7274730000000000000000082a737472696e67000000000668696e74730000000000"
+ "0000000000000014417274733a3a54797065436f6d706f6e656e740000000003000000"
+ "07737472696e67000000000574797065000000000000000007737472696e6700000000"
+ "056e616d650000000000000000082a737472696e67000000000668696e747300000000"
+ "00000000000000000e417274733a3a5479706544656600000000030000000773747269"
+ "6e6700000000056e616d650000000000000000152a417274733a3a54797065436f6d70"
+ "6f6e656e740000000009636f6e74656e74730000000000000000082a737472696e6700"
+ "0000000668696e747300000000000000000000000014417274733a3a456e756d436f6d"
+ "706f6e656e74000000000300000007737472696e6700000000056e616d650000000000"
+ "000000056c6f6e67000000000676616c75650000000000000000082a737472696e6700"
+ "0000000668696e74730000000000000000000000000e417274733a3a456e756d446566"
+ "000000000300000007737472696e6700000000056e616d650000000000000000152a41"
+ "7274733a3a456e756d436f6d706f6e656e740000000009636f6e74656e747300000000"
+ "00000000082a737472696e67000000000668696e747300000000000000000000000010"
+ "417274733a3a4d6f64756c65446566000000000500000007737472696e67000000000b"
+ "6d6f64756c654e616d6500000000000000000f2a417274733a3a456e756d4465660000"
+ "000006656e756d7300000000000000000f2a417274733a3a5479706544656600000000"
+ "0674797065730000000000000000142a417274733a3a496e7465726661636544656600"
+ "0000000b696e74657266616365730000000000000000082a737472696e670000000006"
+ "68696e74730000000000000000000000000a417274733a3a416e790000000002000000"
+ "07737472696e670000000005747970650000000000000000062a627974650000000006"
+ "76616c756500000000000000000000000012417274733a3a547261646572456e747279"
+ "000000000200000007737472696e67000000000e696e746572666163654e616d650000"
+ "000000000000082a737472696e6700000000066c696e65730000000000000000000000"
+ "000b00000014417274733a3a496e746572666163655265706f00000000000000000900"
+ "00000d696e736572744d6f64756c6500000000056c6f6e670000000002000000010000"
+ "0010417274733a3a4d6f64756c65446566000000000a6e65774d6f64756c6500000000"
+ "00000000000000000d72656d6f76654d6f64756c650000000005766f69640000000002"
+ "00000001000000056c6f6e6700000000096d6f64756c65494400000000000000000000"
+ "00000f7175657279496e746572666163650000000013417274733a3a496e7465726661"
+ "636544656600000000020000000100000007737472696e6700000000056e616d650000"
+ "000000000000000000000a717565727954797065000000000e417274733a3a54797065"
+ "44656600000000020000000100000007737472696e6700000000056e616d6500000000"
+ "00000000000000000a7175657279456e756d000000000e417274733a3a456e756d4465"
+ "6600000000020000000100000007737472696e6700000000056e616d65000000000000"
+ "0000000000000e71756572794368696c6472656e00000000082a737472696e67000000"
+ "00020000000100000007737472696e6700000000056e616d6500000000000000000000"
+ "0000107175657279496e746572666163657300000000082a737472696e670000000002"
+ "00000000000000000000000b7175657279547970657300000000082a737472696e6700"
+ "0000000200000000000000000000000b7175657279456e756d7300000000082a737472"
+ "696e670000000002000000000000000000000000000000000000000000000016417274"
+ "733a3a496e746572666163655265706f5632000000000100000014417274733a3a496e"
+ "746572666163655265706f00000000010000000d6964656e7469667954797065000000"
+ "0019417274733a3a547970654964656e74696669636174696f6e000000000200000001"
+ "00000007737472696e6700000000056e616d6500000000000000000000000000000000"
+ "000000000000000017417274733a3a466c6f7753797374656d53656e64657200000000"
+ "00000000020000000a70726f6365737365640000000005766f69640000000001000000"
+ "00000000000000000b646973636f6e6e6563740000000005766f696400000000020000"
+ "00000000000000000000000000000000000000000019417274733a3a466c6f77537973"
+ "74656d52656365697665720000000000000000010000000b646973636f6e6e65637400"
+ "00000005766f6964000000000200000000000000000000000100000011726563656976"
+ "6548616e646c6572494400000000056c6f6e6700000000120000000000000000000000"
+ "0000000011417274733a3a466c6f7753797374656d0000000000000000070000000c73"
+ "746172744f626a6563740000000005766f6964000000000200000001000000076f626a"
+ "65637400000000056e6f64650000000000000000000000000b73746f704f626a656374"
+ "0000000005766f6964000000000200000001000000076f626a65637400000000056e6f"
+ "64650000000000000000000000000e636f6e6e6563744f626a6563740000000005766f"
+ "6964000000000200000004000000076f626a656374000000000d736f757263654f626a"
+ "656374000000000000000007737472696e67000000000b736f75726365506f72740000"
+ "000000000000076f626a656374000000000b646573744f626a65637400000000000000"
+ "0007737472696e67000000000964657374506f72740000000000000000000000001164"
+ "6973636f6e6e6563744f626a6563740000000005766f69640000000002000000040000"
+ "00076f626a656374000000000d736f757263654f626a65637400000000000000000773"
+ "7472696e67000000000b736f75726365506f72740000000000000000076f626a656374"
+ "000000000b646573744f626a656374000000000000000007737472696e670000000009"
+ "64657374506f72740000000000000000000000000b7175657279466c61677300000000"
+ "14417274733a3a41747472696275746554797065000000000200000002000000076f62"
+ "6a65637400000000056e6f6465000000000000000007737472696e670000000005706f"
+ "72740000000000000000000000000e736574466c6f617456616c75650000000005766f"
+ "6964000000000200000003000000076f626a65637400000000056e6f64650000000000"
+ "00000007737472696e670000000005706f7274000000000000000006666c6f61740000"
+ "00000676616c75650000000000000000000000000f6372656174655265636569766572"
+ "0000000019417274733a3a466c6f7753797374656d5265636569766572000000000200"
+ "000003000000076f626a656374000000000b646573744f626a65637400000000000000"
+ "0007737472696e67000000000964657374506f7274000000000000000017417274733a"
+ "3a466c6f7753797374656d53656e646572000000000773656e64657200000000000000"
+ "000000000000000000000000000000000011417274733a3a476c6f62616c436f6d6d00"
+ "0000000000000003000000047075740000000008626f6f6c65616e0000000002000000"
+ "0200000007737472696e6700000000097661726961626c650000000000000000077374"
+ "72696e67000000000676616c7565000000000000000000000000046765740000000007"
+ "737472696e6700000000020000000100000007737472696e6700000000097661726961"
+ "626c650000000000000000000000000665726173650000000005766f69640000000002"
+ "0000000100000007737472696e6700000000097661726961626c650000000000000000"
+ "0000000000000000000000000000000014417274733a3a546d70476c6f62616c436f6d"
+ "6d000000000100000011417274733a3a476c6f62616c436f6d6d000000000000000000"
+ "000000000000000000000012417274733a3a5472616465724f66666572000000000000"
+ "0000010000000c67657450726f706572747900000000082a737472696e670000000002"
+ "0000000100000007737472696e6700000000056e616d65000000000000000000000000"
+ "010000000e696e746572666163654e616d650000000007737472696e67000000001200"
+ "000000000000000000000000000012417274733a3a5472616465725175657279000000"
+ "00000000000200000009737570706f7274730000000005766f69640000000002000000"
+ "0200000007737472696e67000000000970726f70657274790000000000000000077374"
+ "72696e67000000000676616c7565000000000000000000000000067175657279000000"
+ "00132a417274733a3a5472616465724f66666572000000000200000000000000000000"
+ "000000000000000000000000000d417274733a3a4f626a65637400000000000000000e"
+ "0000000e5f6c6f6f6b75704d6574686f6400000000056c6f6e67000000000200000001"
+ "00000010417274733a3a4d6574686f64446566000000000a6d6574686f644465660000"
+ "000000000000000000000f5f696e746572666163654e616d650000000007737472696e"
+ "6700000000020000000000000000000000105f7175657279496e746572666163650000"
+ "000013417274733a3a496e746572666163654465660000000002000000010000000773"
+ "7472696e6700000000056e616d650000000000000000000000000b5f71756572795479"
+ "7065000000000e417274733a3a54797065446566000000000200000001000000077374"
+ "72696e6700000000056e616d650000000000000000000000000b5f7175657279456e75"
+ "6d000000000e417274733a3a456e756d44656600000000020000000100000007737472"
+ "696e6700000000056e616d650000000000000000000000000a5f746f537472696e6700"
+ "00000007737472696e6700000000020000000000000000000000125f6973436f6d7061"
+ "7469626c65576974680000000008626f6f6c65616e0000000002000000010000000773"
+ "7472696e67000000000e696e746572666163656e616d65000000000000000000000000"
+ "0c5f636f707952656d6f74650000000005766f69640000000002000000000000000000"
+ "00000b5f75736552656d6f74650000000005766f696400000000020000000000000000"
+ "0000000f5f72656c6561736552656d6f74650000000005766f69640000000002000000"
+ "00000000000000000a5f6164644368696c640000000007737472696e67000000000200"
+ "000002000000076f626a65637400000000066368696c64000000000000000007737472"
+ "696e6700000000056e616d650000000000000000000000000d5f72656d6f7665436869"
+ "6c640000000008626f6f6c65616e00000000020000000100000007737472696e670000"
+ "0000056e616d650000000000000000000000000a5f6765744368696c6400000000076f"
+ "626a65637400000000020000000100000007737472696e6700000000056e616d650000"
+ "000000000000000000000f5f71756572794368696c6472656e00000000082a73747269"
+ "6e6700000000020000000000000000000000010000000c5f666c6f7753797374656d00"
+ "00000011417274733a3a466c6f7753797374656d000000001200000000000000000000"
+ "00000000000d417274733a3a4c6f616465720000000000000000010000000b6c6f6164"
+ "4f626a65637400000000076f626a65637400000000020000000100000012417274733a"
+ "3a5472616465724f6666657200000000066f6666657200000000000000000000000003"
+ "0000000c6461746156657273696f6e0000000007737472696e67000000001200000000"
+ "0000000e747261646572456e747269657300000000132a417274733a3a547261646572"
+ "456e747279000000001200000000000000086d6f64756c657300000000112a41727473"
+ "3a3a4d6f64756c65446566000000001200000000000000000000000000000000"
+);
diff --git a/mcop/core.h b/mcop/core.h
new file mode 100644
index 0000000..5ab73e1
--- /dev/null
+++ b/mcop/core.h
@@ -0,0 +1,1561 @@
+/* this file was generated by the MCOP idl compiler - DO NOT EDIT */
+
+#ifndef CORE_H
+#define CORE_H
+
+#include "common.h"
+#include "arts_export.h"
+
+namespace Arts {
+enum HeaderMagic {MCOP_MAGIC = 1296256848};
+enum MessageType {mcopMessageInvalid = 0, mcopServerHello = 1, mcopClientHello = 2, mcopAuthAccept = 3, mcopInvocation = 4, mcopReturn = 5, mcopOnewayInvocation = 6};
+enum MethodType {methodOneway = 1, methodTwoway = 2, methodMax = 0xffffffff};
+enum AttributeType {streamIn = 1, streamOut = 2, streamMulti = 4, attributeStream = 8, attributeAttribute = 16, streamAsync = 32, streamDefault = 64};
+enum TypeIdentification {tiUnknown = 0, tiVoid = 1, tiLong = 2, tiByte = 3, tiString = 4, tiBoolean = 5, tiFloat = 6, tiEnum = 128, tiType = 129, tiInterface = 130};
+}
+namespace Arts {
+class ARTS_EXPORT Header : public Arts::Type {
+public:
+ Header();
+ Header(Arts::HeaderMagic _a_magic, long _a_messageLength, Arts::MessageType _a_messageType);
+ Header(Arts::Buffer& stream);
+ Header(const Header& copyType);
+ Header& operator=(const Header& assignType);
+ Arts::HeaderMagic magic;
+ long messageLength;
+ Arts::MessageType messageType;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT Invocation : public Arts::Type {
+public:
+ Invocation();
+ Invocation(long _a_objectID, long _a_methodID, long _a_requestID);
+ Invocation(Arts::Buffer& stream);
+ Invocation(const Invocation& copyType);
+ Invocation& operator=(const Invocation& assignType);
+ long objectID;
+ long methodID;
+ long requestID;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT OnewayInvocation : public Arts::Type {
+public:
+ OnewayInvocation();
+ OnewayInvocation(long _a_objectID, long _a_methodID);
+ OnewayInvocation(Arts::Buffer& stream);
+ OnewayInvocation(const OnewayInvocation& copyType);
+ OnewayInvocation& operator=(const OnewayInvocation& assignType);
+ long objectID;
+ long methodID;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ServerHello : public Arts::Type {
+public:
+ ServerHello();
+ ServerHello(const std::string& _a_mcopVersion, const std::string& _a_serverID, const std::vector<std::string>& _a_authProtocols, const std::string& _a_authSeed);
+ ServerHello(Arts::Buffer& stream);
+ ServerHello(const ServerHello& copyType);
+ ServerHello& operator=(const ServerHello& assignType);
+ std::string mcopVersion;
+ std::string serverID;
+ std::vector<std::string> authProtocols;
+ std::string authSeed;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ClientHello : public Arts::Type {
+public:
+ ClientHello();
+ ClientHello(const std::string& _a_serverID, const std::string& _a_authProtocol, const std::string& _a_authData);
+ ClientHello(Arts::Buffer& stream);
+ ClientHello(const ClientHello& copyType);
+ ClientHello& operator=(const ClientHello& assignType);
+ std::string serverID;
+ std::string authProtocol;
+ std::string authData;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT AuthAccept : public Arts::Type {
+public:
+ AuthAccept();
+ AuthAccept(const std::vector<std::string>& _a_hints);
+ AuthAccept(Arts::Buffer& stream);
+ AuthAccept(const AuthAccept& copyType);
+ AuthAccept& operator=(const AuthAccept& assignType);
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ObjectReference : public Arts::Type {
+public:
+ ObjectReference();
+ ObjectReference(const std::string& _a_serverID, long _a_objectID, const std::vector<std::string>& _a_urls);
+ ObjectReference(Arts::Buffer& stream);
+ ObjectReference(const ObjectReference& copyType);
+ ObjectReference& operator=(const ObjectReference& assignType);
+ std::string serverID;
+ long objectID;
+ std::vector<std::string> urls;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ParamDef : public Arts::Type {
+public:
+ ParamDef();
+ ParamDef(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints);
+ ParamDef(Arts::Buffer& stream);
+ ParamDef(const ParamDef& copyType);
+ ParamDef& operator=(const ParamDef& assignType);
+ std::string type;
+ std::string name;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT MethodDef : public Arts::Type {
+public:
+ MethodDef();
+ MethodDef(const std::string& _a_name, const std::string& _a_type, Arts::MethodType _a_flags, const std::vector<Arts::ParamDef>& _a_signature, const std::vector<std::string>& _a_hints);
+ MethodDef(Arts::Buffer& stream);
+ MethodDef(const MethodDef& copyType);
+ MethodDef& operator=(const MethodDef& assignType);
+ std::string name;
+ std::string type;
+ Arts::MethodType flags;
+ std::vector<Arts::ParamDef> signature;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT AttributeDef : public Arts::Type {
+public:
+ AttributeDef();
+ AttributeDef(const std::string& _a_name, const std::string& _a_type, Arts::AttributeType _a_flags, const std::vector<std::string>& _a_hints);
+ AttributeDef(Arts::Buffer& stream);
+ AttributeDef(const AttributeDef& copyType);
+ AttributeDef& operator=(const AttributeDef& assignType);
+ std::string name;
+ std::string type;
+ Arts::AttributeType flags;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT InterfaceDef : public Arts::Type {
+public:
+ InterfaceDef();
+ InterfaceDef(const std::string& _a_name, const std::vector<std::string>& _a_inheritedInterfaces, const std::vector<Arts::MethodDef>& _a_methods, const std::vector<Arts::AttributeDef>& _a_attributes, const std::vector<std::string>& _a_defaultPorts, const std::vector<std::string>& _a_hints);
+ InterfaceDef(Arts::Buffer& stream);
+ InterfaceDef(const InterfaceDef& copyType);
+ InterfaceDef& operator=(const InterfaceDef& assignType);
+ std::string name;
+ std::vector<std::string> inheritedInterfaces;
+ std::vector<Arts::MethodDef> methods;
+ std::vector<Arts::AttributeDef> attributes;
+ std::vector<std::string> defaultPorts;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT TypeComponent : public Arts::Type {
+public:
+ TypeComponent();
+ TypeComponent(const std::string& _a_type, const std::string& _a_name, const std::vector<std::string>& _a_hints);
+ TypeComponent(Arts::Buffer& stream);
+ TypeComponent(const TypeComponent& copyType);
+ TypeComponent& operator=(const TypeComponent& assignType);
+ std::string type;
+ std::string name;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT TypeDef : public Arts::Type {
+public:
+ TypeDef();
+ TypeDef(const std::string& _a_name, const std::vector<Arts::TypeComponent>& _a_contents, const std::vector<std::string>& _a_hints);
+ TypeDef(Arts::Buffer& stream);
+ TypeDef(const TypeDef& copyType);
+ TypeDef& operator=(const TypeDef& assignType);
+ std::string name;
+ std::vector<Arts::TypeComponent> contents;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT EnumComponent : public Arts::Type {
+public:
+ EnumComponent();
+ EnumComponent(const std::string& _a_name, long _a_value, const std::vector<std::string>& _a_hints);
+ EnumComponent(Arts::Buffer& stream);
+ EnumComponent(const EnumComponent& copyType);
+ EnumComponent& operator=(const EnumComponent& assignType);
+ std::string name;
+ long value;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT EnumDef : public Arts::Type {
+public:
+ EnumDef();
+ EnumDef(const std::string& _a_name, const std::vector<Arts::EnumComponent>& _a_contents, const std::vector<std::string>& _a_hints);
+ EnumDef(Arts::Buffer& stream);
+ EnumDef(const EnumDef& copyType);
+ EnumDef& operator=(const EnumDef& assignType);
+ std::string name;
+ std::vector<Arts::EnumComponent> contents;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT ModuleDef : public Arts::Type {
+public:
+ ModuleDef();
+ ModuleDef(const std::string& _a_moduleName, const std::vector<Arts::EnumDef>& _a_enums, const std::vector<Arts::TypeDef>& _a_types, const std::vector<Arts::InterfaceDef>& _a_interfaces, const std::vector<std::string>& _a_hints);
+ ModuleDef(Arts::Buffer& stream);
+ ModuleDef(const ModuleDef& copyType);
+ ModuleDef& operator=(const ModuleDef& assignType);
+ std::string moduleName;
+ std::vector<Arts::EnumDef> enums;
+ std::vector<Arts::TypeDef> types;
+ std::vector<Arts::InterfaceDef> interfaces;
+ std::vector<std::string> hints;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT Any : public Arts::Type {
+public:
+ Any();
+ Any(const std::string& _a_type, const std::vector<Arts::mcopbyte>& _a_value);
+ Any(Arts::Buffer& stream);
+ Any(const Any& copyType);
+ Any& operator=(const Any& assignType);
+ std::string type;
+ std::vector<Arts::mcopbyte> value;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+class ARTS_EXPORT TraderEntry : public Arts::Type {
+public:
+ TraderEntry();
+ TraderEntry(const std::string& _a_interfaceName, const std::vector<std::string>& _a_lines);
+ TraderEntry(Arts::Buffer& stream);
+ TraderEntry(const TraderEntry& copyType);
+ TraderEntry& operator=(const TraderEntry& assignType);
+ std::string interfaceName;
+ std::vector<std::string> lines;
+
+// marshalling functions
+ void readType(Arts::Buffer& stream);
+ void writeType(Arts::Buffer& stream) const;
+ std::string _typeName() const;
+};
+
+}
+namespace Arts {
+class InterfaceRepo;
+class InterfaceRepoV2;
+class FlowSystemSender;
+class FlowSystemReceiver;
+class FlowSystem;
+class GlobalComm;
+class TmpGlobalComm;
+class TraderOffer;
+class TraderQuery;
+class Loader;
+
+class ARTS_EXPORT InterfaceRepo_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static InterfaceRepo_base *_create(const std::string& subClass = "Arts::InterfaceRepo");
+ static InterfaceRepo_base *_fromString(std::string objectref);
+ static InterfaceRepo_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static InterfaceRepo_base *_fromDynamicCast(const Arts::Object& object);
+ inline InterfaceRepo_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual long insertModule(const Arts::ModuleDef& newModule) = 0;
+ virtual void removeModule(long moduleID) = 0;
+ virtual Arts::InterfaceDef queryInterface(const std::string& name) = 0;
+ virtual Arts::TypeDef queryType(const std::string& name) = 0;
+ virtual Arts::EnumDef queryEnum(const std::string& name) = 0;
+ virtual std::vector<std::string> * queryChildren(const std::string& name) = 0;
+ virtual std::vector<std::string> * queryInterfaces() = 0;
+ virtual std::vector<std::string> * queryTypes() = 0;
+ virtual std::vector<std::string> * queryEnums() = 0;
+};
+
+class ARTS_EXPORT InterfaceRepo_stub : virtual public InterfaceRepo_base, virtual public Arts::Object_stub {
+protected:
+ InterfaceRepo_stub();
+
+public:
+ InterfaceRepo_stub(Arts::Connection *connection, long objectID);
+
+ long insertModule(const Arts::ModuleDef& newModule);
+ void removeModule(long moduleID);
+ Arts::InterfaceDef queryInterface(const std::string& name);
+ Arts::TypeDef queryType(const std::string& name);
+ Arts::EnumDef queryEnum(const std::string& name);
+ std::vector<std::string> * queryChildren(const std::string& name);
+ std::vector<std::string> * queryInterfaces();
+ std::vector<std::string> * queryTypes();
+ std::vector<std::string> * queryEnums();
+};
+
+class ARTS_EXPORT InterfaceRepo_skel : virtual public InterfaceRepo_base, virtual public Arts::Object_skel {
+public:
+ InterfaceRepo_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT InterfaceRepo : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ InterfaceRepo_base *_cache;
+ inline InterfaceRepo_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(InterfaceRepo_base *)_pool->base->_cast(InterfaceRepo_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline InterfaceRepo(InterfaceRepo_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef InterfaceRepo_base _base_class;
+
+ inline InterfaceRepo() : Arts::Object(_Creator), _cache(0) {}
+ inline InterfaceRepo(const Arts::SubClass& s) :
+ Arts::Object(InterfaceRepo_base::_create(s.string())), _cache(0) {}
+ inline InterfaceRepo(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(InterfaceRepo_base::_fromString(r.string())):(InterfaceRepo_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline InterfaceRepo(const Arts::DynamicCast& c) : Arts::Object(InterfaceRepo_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline InterfaceRepo(const InterfaceRepo& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline InterfaceRepo(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static InterfaceRepo null() {return InterfaceRepo((InterfaceRepo_base*)0);}
+ inline static InterfaceRepo _from_base(InterfaceRepo_base* b) {return InterfaceRepo(b);}
+ inline InterfaceRepo& operator=(const InterfaceRepo& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline InterfaceRepo_base* _base() {return _cache?_cache:_method_call();}
+
+ inline long insertModule(const Arts::ModuleDef& newModule);
+ inline void removeModule(long moduleID);
+ inline Arts::InterfaceDef queryInterface(const std::string& name);
+ inline Arts::TypeDef queryType(const std::string& name);
+ inline Arts::EnumDef queryEnum(const std::string& name);
+ inline std::vector<std::string> * queryChildren(const std::string& name);
+ inline std::vector<std::string> * queryInterfaces();
+ inline std::vector<std::string> * queryTypes();
+ inline std::vector<std::string> * queryEnums();
+};
+
+class ARTS_EXPORT InterfaceRepoV2_base : virtual public Arts::InterfaceRepo_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static InterfaceRepoV2_base *_create(const std::string& subClass = "Arts::InterfaceRepoV2");
+ static InterfaceRepoV2_base *_fromString(std::string objectref);
+ static InterfaceRepoV2_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static InterfaceRepoV2_base *_fromDynamicCast(const Arts::Object& object);
+ inline InterfaceRepoV2_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual Arts::TypeIdentification identifyType(const std::string& name) = 0;
+};
+
+class ARTS_EXPORT InterfaceRepoV2_stub : virtual public InterfaceRepoV2_base, virtual public Arts::InterfaceRepo_stub {
+protected:
+ InterfaceRepoV2_stub();
+
+public:
+ InterfaceRepoV2_stub(Arts::Connection *connection, long objectID);
+
+ Arts::TypeIdentification identifyType(const std::string& name);
+};
+
+class ARTS_EXPORT InterfaceRepoV2_skel : virtual public InterfaceRepoV2_base, virtual public Arts::InterfaceRepo_skel {
+public:
+ InterfaceRepoV2_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT InterfaceRepoV2 : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ InterfaceRepoV2_base *_cache;
+ inline InterfaceRepoV2_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(InterfaceRepoV2_base *)_pool->base->_cast(InterfaceRepoV2_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline InterfaceRepoV2(InterfaceRepoV2_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef InterfaceRepoV2_base _base_class;
+
+ inline InterfaceRepoV2() : Arts::Object(_Creator), _cache(0) {}
+ inline InterfaceRepoV2(const Arts::SubClass& s) :
+ Arts::Object(InterfaceRepoV2_base::_create(s.string())), _cache(0) {}
+ inline InterfaceRepoV2(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(InterfaceRepoV2_base::_fromString(r.string())):(InterfaceRepoV2_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline InterfaceRepoV2(const Arts::DynamicCast& c) : Arts::Object(InterfaceRepoV2_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline InterfaceRepoV2(const InterfaceRepoV2& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline InterfaceRepoV2(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static InterfaceRepoV2 null() {return InterfaceRepoV2((InterfaceRepoV2_base*)0);}
+ inline static InterfaceRepoV2 _from_base(InterfaceRepoV2_base* b) {return InterfaceRepoV2(b);}
+ inline InterfaceRepoV2& operator=(const InterfaceRepoV2& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline operator Arts::InterfaceRepo() const { return Arts::InterfaceRepo(*_pool); }
+ inline InterfaceRepoV2_base* _base() {return _cache?_cache:_method_call();}
+
+ inline long insertModule(const Arts::ModuleDef& newModule);
+ inline void removeModule(long moduleID);
+ inline Arts::InterfaceDef queryInterface(const std::string& name);
+ inline Arts::TypeDef queryType(const std::string& name);
+ inline Arts::EnumDef queryEnum(const std::string& name);
+ inline std::vector<std::string> * queryChildren(const std::string& name);
+ inline std::vector<std::string> * queryInterfaces();
+ inline std::vector<std::string> * queryTypes();
+ inline std::vector<std::string> * queryEnums();
+ inline Arts::TypeIdentification identifyType(const std::string& name);
+};
+
+class ARTS_EXPORT FlowSystemSender_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static FlowSystemSender_base *_create(const std::string& subClass = "Arts::FlowSystemSender");
+ static FlowSystemSender_base *_fromString(std::string objectref);
+ static FlowSystemSender_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static FlowSystemSender_base *_fromDynamicCast(const Arts::Object& object);
+ inline FlowSystemSender_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual void processed() = 0;
+ virtual void disconnect() = 0;
+};
+
+class ARTS_EXPORT FlowSystemSender_stub : virtual public FlowSystemSender_base, virtual public Arts::Object_stub {
+protected:
+ FlowSystemSender_stub();
+
+public:
+ FlowSystemSender_stub(Arts::Connection *connection, long objectID);
+
+ void processed();
+ void disconnect();
+};
+
+class ARTS_EXPORT FlowSystemSender_skel : virtual public FlowSystemSender_base, virtual public Arts::Object_skel {
+public:
+ FlowSystemSender_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT FlowSystemSender : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ FlowSystemSender_base *_cache;
+ inline FlowSystemSender_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(FlowSystemSender_base *)_pool->base->_cast(FlowSystemSender_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline FlowSystemSender(FlowSystemSender_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef FlowSystemSender_base _base_class;
+
+ inline FlowSystemSender() : Arts::Object(_Creator), _cache(0) {}
+ inline FlowSystemSender(const Arts::SubClass& s) :
+ Arts::Object(FlowSystemSender_base::_create(s.string())), _cache(0) {}
+ inline FlowSystemSender(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(FlowSystemSender_base::_fromString(r.string())):(FlowSystemSender_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline FlowSystemSender(const Arts::DynamicCast& c) : Arts::Object(FlowSystemSender_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline FlowSystemSender(const FlowSystemSender& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline FlowSystemSender(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static FlowSystemSender null() {return FlowSystemSender((FlowSystemSender_base*)0);}
+ inline static FlowSystemSender _from_base(FlowSystemSender_base* b) {return FlowSystemSender(b);}
+ inline FlowSystemSender& operator=(const FlowSystemSender& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline FlowSystemSender_base* _base() {return _cache?_cache:_method_call();}
+
+ inline void processed();
+ inline void disconnect();
+};
+
+class ARTS_EXPORT FlowSystemReceiver_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static FlowSystemReceiver_base *_create(const std::string& subClass = "Arts::FlowSystemReceiver");
+ static FlowSystemReceiver_base *_fromString(std::string objectref);
+ static FlowSystemReceiver_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static FlowSystemReceiver_base *_fromDynamicCast(const Arts::Object& object);
+ inline FlowSystemReceiver_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual long receiveHandlerID() = 0;
+ virtual void disconnect() = 0;
+};
+
+class ARTS_EXPORT FlowSystemReceiver_stub : virtual public FlowSystemReceiver_base, virtual public Arts::Object_stub {
+protected:
+ FlowSystemReceiver_stub();
+
+public:
+ FlowSystemReceiver_stub(Arts::Connection *connection, long objectID);
+
+ long receiveHandlerID();
+ void disconnect();
+};
+
+class ARTS_EXPORT FlowSystemReceiver_skel : virtual public FlowSystemReceiver_base, virtual public Arts::Object_skel {
+protected:
+ // emitters for change notifications
+ inline void receiveHandlerID_changed(long newValue) {
+ _emit_changed("receiveHandlerID_changed",newValue);
+ }
+
+public:
+ FlowSystemReceiver_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT FlowSystemReceiver : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ FlowSystemReceiver_base *_cache;
+ inline FlowSystemReceiver_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(FlowSystemReceiver_base *)_pool->base->_cast(FlowSystemReceiver_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline FlowSystemReceiver(FlowSystemReceiver_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef FlowSystemReceiver_base _base_class;
+
+ inline FlowSystemReceiver() : Arts::Object(_Creator), _cache(0) {}
+ inline FlowSystemReceiver(const Arts::SubClass& s) :
+ Arts::Object(FlowSystemReceiver_base::_create(s.string())), _cache(0) {}
+ inline FlowSystemReceiver(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(FlowSystemReceiver_base::_fromString(r.string())):(FlowSystemReceiver_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline FlowSystemReceiver(const Arts::DynamicCast& c) : Arts::Object(FlowSystemReceiver_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline FlowSystemReceiver(const FlowSystemReceiver& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline FlowSystemReceiver(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static FlowSystemReceiver null() {return FlowSystemReceiver((FlowSystemReceiver_base*)0);}
+ inline static FlowSystemReceiver _from_base(FlowSystemReceiver_base* b) {return FlowSystemReceiver(b);}
+ inline FlowSystemReceiver& operator=(const FlowSystemReceiver& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline FlowSystemReceiver_base* _base() {return _cache?_cache:_method_call();}
+
+ inline long receiveHandlerID();
+ inline void disconnect();
+};
+
+class ARTS_EXPORT FlowSystem_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static FlowSystem_base *_create(const std::string& subClass = "Arts::FlowSystem");
+ static FlowSystem_base *_fromString(std::string objectref);
+ static FlowSystem_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static FlowSystem_base *_fromDynamicCast(const Arts::Object& object);
+ inline FlowSystem_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual void startObject(Arts::Object node) = 0;
+ virtual void stopObject(Arts::Object node) = 0;
+ virtual void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) = 0;
+ virtual void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort) = 0;
+ virtual Arts::AttributeType queryFlags(Arts::Object node, const std::string& port) = 0;
+ virtual void setFloatValue(Arts::Object node, const std::string& port, float value) = 0;
+ virtual Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender) = 0;
+};
+
+class ARTS_EXPORT FlowSystem_stub : virtual public FlowSystem_base, virtual public Arts::Object_stub {
+protected:
+ FlowSystem_stub();
+
+public:
+ FlowSystem_stub(Arts::Connection *connection, long objectID);
+
+ void startObject(Arts::Object node);
+ void stopObject(Arts::Object node);
+ void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ Arts::AttributeType queryFlags(Arts::Object node, const std::string& port);
+ void setFloatValue(Arts::Object node, const std::string& port, float value);
+ Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender);
+};
+
+class ARTS_EXPORT FlowSystem_skel : virtual public FlowSystem_base, virtual public Arts::Object_skel {
+public:
+ FlowSystem_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT FlowSystem : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ FlowSystem_base *_cache;
+ inline FlowSystem_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(FlowSystem_base *)_pool->base->_cast(FlowSystem_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline FlowSystem(FlowSystem_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef FlowSystem_base _base_class;
+
+ inline FlowSystem() : Arts::Object(_Creator), _cache(0) {}
+ inline FlowSystem(const Arts::SubClass& s) :
+ Arts::Object(FlowSystem_base::_create(s.string())), _cache(0) {}
+ inline FlowSystem(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(FlowSystem_base::_fromString(r.string())):(FlowSystem_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline FlowSystem(const Arts::DynamicCast& c) : Arts::Object(FlowSystem_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline FlowSystem(const FlowSystem& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline FlowSystem(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static FlowSystem null() {return FlowSystem((FlowSystem_base*)0);}
+ inline static FlowSystem _from_base(FlowSystem_base* b) {return FlowSystem(b);}
+ inline FlowSystem& operator=(const FlowSystem& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline FlowSystem_base* _base() {return _cache?_cache:_method_call();}
+
+ inline void startObject(Arts::Object node);
+ inline void stopObject(Arts::Object node);
+ inline void connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ inline void disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort);
+ inline Arts::AttributeType queryFlags(Arts::Object node, const std::string& port);
+ inline void setFloatValue(Arts::Object node, const std::string& port, float value);
+ inline Arts::FlowSystemReceiver createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender);
+};
+
+class ARTS_EXPORT GlobalComm_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static GlobalComm_base *_create(const std::string& subClass = "Arts::GlobalComm");
+ static GlobalComm_base *_fromString(std::string objectref);
+ static GlobalComm_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static GlobalComm_base *_fromDynamicCast(const Arts::Object& object);
+ inline GlobalComm_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual bool put(const std::string& variable, const std::string& value) = 0;
+ virtual std::string get(const std::string& variable) = 0;
+ virtual void erase(const std::string& variable) = 0;
+};
+
+class ARTS_EXPORT GlobalComm_stub : virtual public GlobalComm_base, virtual public Arts::Object_stub {
+protected:
+ GlobalComm_stub();
+
+public:
+ GlobalComm_stub(Arts::Connection *connection, long objectID);
+
+ bool put(const std::string& variable, const std::string& value);
+ std::string get(const std::string& variable);
+ void erase(const std::string& variable);
+};
+
+class ARTS_EXPORT GlobalComm_skel : virtual public GlobalComm_base, virtual public Arts::Object_skel {
+public:
+ GlobalComm_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT GlobalComm : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ GlobalComm_base *_cache;
+ inline GlobalComm_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(GlobalComm_base *)_pool->base->_cast(GlobalComm_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline GlobalComm(GlobalComm_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef GlobalComm_base _base_class;
+
+ inline GlobalComm() : Arts::Object(_Creator), _cache(0) {}
+ inline GlobalComm(const Arts::SubClass& s) :
+ Arts::Object(GlobalComm_base::_create(s.string())), _cache(0) {}
+ inline GlobalComm(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(GlobalComm_base::_fromString(r.string())):(GlobalComm_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline GlobalComm(const Arts::DynamicCast& c) : Arts::Object(GlobalComm_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline GlobalComm(const GlobalComm& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline GlobalComm(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static GlobalComm null() {return GlobalComm((GlobalComm_base*)0);}
+ inline static GlobalComm _from_base(GlobalComm_base* b) {return GlobalComm(b);}
+ inline GlobalComm& operator=(const GlobalComm& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline GlobalComm_base* _base() {return _cache?_cache:_method_call();}
+
+ inline bool put(const std::string& variable, const std::string& value);
+ inline std::string get(const std::string& variable);
+ inline void erase(const std::string& variable);
+};
+
+class ARTS_EXPORT TmpGlobalComm_base : virtual public Arts::GlobalComm_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static TmpGlobalComm_base *_create(const std::string& subClass = "Arts::TmpGlobalComm");
+ static TmpGlobalComm_base *_fromString(std::string objectref);
+ static TmpGlobalComm_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static TmpGlobalComm_base *_fromDynamicCast(const Arts::Object& object);
+ inline TmpGlobalComm_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+};
+
+class ARTS_EXPORT TmpGlobalComm_stub : virtual public TmpGlobalComm_base, virtual public Arts::GlobalComm_stub {
+protected:
+ TmpGlobalComm_stub();
+
+public:
+ TmpGlobalComm_stub(Arts::Connection *connection, long objectID);
+
+};
+
+class ARTS_EXPORT TmpGlobalComm_skel : virtual public TmpGlobalComm_base, virtual public Arts::GlobalComm_skel {
+public:
+ TmpGlobalComm_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT TmpGlobalComm : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ TmpGlobalComm_base *_cache;
+ inline TmpGlobalComm_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(TmpGlobalComm_base *)_pool->base->_cast(TmpGlobalComm_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline TmpGlobalComm(TmpGlobalComm_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef TmpGlobalComm_base _base_class;
+
+ inline TmpGlobalComm() : Arts::Object(_Creator), _cache(0) {}
+ inline TmpGlobalComm(const Arts::SubClass& s) :
+ Arts::Object(TmpGlobalComm_base::_create(s.string())), _cache(0) {}
+ inline TmpGlobalComm(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(TmpGlobalComm_base::_fromString(r.string())):(TmpGlobalComm_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline TmpGlobalComm(const Arts::DynamicCast& c) : Arts::Object(TmpGlobalComm_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline TmpGlobalComm(const TmpGlobalComm& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline TmpGlobalComm(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static TmpGlobalComm null() {return TmpGlobalComm((TmpGlobalComm_base*)0);}
+ inline static TmpGlobalComm _from_base(TmpGlobalComm_base* b) {return TmpGlobalComm(b);}
+ inline TmpGlobalComm& operator=(const TmpGlobalComm& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline operator Arts::GlobalComm() const { return Arts::GlobalComm(*_pool); }
+ inline TmpGlobalComm_base* _base() {return _cache?_cache:_method_call();}
+
+ inline bool put(const std::string& variable, const std::string& value);
+ inline std::string get(const std::string& variable);
+ inline void erase(const std::string& variable);
+};
+
+class ARTS_EXPORT TraderOffer_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static TraderOffer_base *_create(const std::string& subClass = "Arts::TraderOffer");
+ static TraderOffer_base *_fromString(std::string objectref);
+ static TraderOffer_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static TraderOffer_base *_fromDynamicCast(const Arts::Object& object);
+ inline TraderOffer_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual std::string interfaceName() = 0;
+ virtual std::vector<std::string> * getProperty(const std::string& name) = 0;
+};
+
+class ARTS_EXPORT TraderOffer_stub : virtual public TraderOffer_base, virtual public Arts::Object_stub {
+protected:
+ TraderOffer_stub();
+
+public:
+ TraderOffer_stub(Arts::Connection *connection, long objectID);
+
+ std::string interfaceName();
+ std::vector<std::string> * getProperty(const std::string& name);
+};
+
+class ARTS_EXPORT TraderOffer_skel : virtual public TraderOffer_base, virtual public Arts::Object_skel {
+protected:
+ // emitters for change notifications
+ inline void interfaceName_changed(const std::string& newValue) {
+ _emit_changed("interfaceName_changed",newValue);
+ }
+
+public:
+ TraderOffer_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT TraderOffer : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ TraderOffer_base *_cache;
+ inline TraderOffer_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(TraderOffer_base *)_pool->base->_cast(TraderOffer_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline TraderOffer(TraderOffer_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef TraderOffer_base _base_class;
+
+ inline TraderOffer() : Arts::Object(_Creator), _cache(0) {}
+ inline TraderOffer(const Arts::SubClass& s) :
+ Arts::Object(TraderOffer_base::_create(s.string())), _cache(0) {}
+ inline TraderOffer(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(TraderOffer_base::_fromString(r.string())):(TraderOffer_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline TraderOffer(const Arts::DynamicCast& c) : Arts::Object(TraderOffer_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline TraderOffer(const TraderOffer& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline TraderOffer(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static TraderOffer null() {return TraderOffer((TraderOffer_base*)0);}
+ inline static TraderOffer _from_base(TraderOffer_base* b) {return TraderOffer(b);}
+ inline TraderOffer& operator=(const TraderOffer& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline TraderOffer_base* _base() {return _cache?_cache:_method_call();}
+
+ inline std::string interfaceName();
+ inline std::vector<std::string> * getProperty(const std::string& name);
+};
+
+class ARTS_EXPORT TraderQuery_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static TraderQuery_base *_create(const std::string& subClass = "Arts::TraderQuery");
+ static TraderQuery_base *_fromString(std::string objectref);
+ static TraderQuery_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static TraderQuery_base *_fromDynamicCast(const Arts::Object& object);
+ inline TraderQuery_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual void supports(const std::string& property, const std::string& value) = 0;
+ virtual std::vector<Arts::TraderOffer> * query() = 0;
+};
+
+class ARTS_EXPORT TraderQuery_stub : virtual public TraderQuery_base, virtual public Arts::Object_stub {
+protected:
+ TraderQuery_stub();
+
+public:
+ TraderQuery_stub(Arts::Connection *connection, long objectID);
+
+ void supports(const std::string& property, const std::string& value);
+ std::vector<Arts::TraderOffer> * query();
+};
+
+class ARTS_EXPORT TraderQuery_skel : virtual public TraderQuery_base, virtual public Arts::Object_skel {
+public:
+ TraderQuery_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT TraderQuery : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ TraderQuery_base *_cache;
+ inline TraderQuery_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(TraderQuery_base *)_pool->base->_cast(TraderQuery_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline TraderQuery(TraderQuery_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef TraderQuery_base _base_class;
+
+ inline TraderQuery() : Arts::Object(_Creator), _cache(0) {}
+ inline TraderQuery(const Arts::SubClass& s) :
+ Arts::Object(TraderQuery_base::_create(s.string())), _cache(0) {}
+ inline TraderQuery(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(TraderQuery_base::_fromString(r.string())):(TraderQuery_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline TraderQuery(const Arts::DynamicCast& c) : Arts::Object(TraderQuery_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline TraderQuery(const TraderQuery& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline TraderQuery(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static TraderQuery null() {return TraderQuery((TraderQuery_base*)0);}
+ inline static TraderQuery _from_base(TraderQuery_base* b) {return TraderQuery(b);}
+ inline TraderQuery& operator=(const TraderQuery& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline TraderQuery_base* _base() {return _cache?_cache:_method_call();}
+
+ inline void supports(const std::string& property, const std::string& value);
+ inline std::vector<Arts::TraderOffer> * query();
+};
+
+class ARTS_EXPORT Loader_base : virtual public Arts::Object_base {
+public:
+ static unsigned long _IID; // interface ID
+
+ static Loader_base *_create(const std::string& subClass = "Arts::Loader");
+ static Loader_base *_fromString(std::string objectref);
+ static Loader_base *_fromReference(Arts::ObjectReference ref, bool needcopy);
+
+ static Loader_base *_fromDynamicCast(const Arts::Object& object);
+ inline Loader_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ void *_cast(unsigned long iid);
+
+ virtual std::string dataVersion() = 0;
+ virtual std::vector<Arts::TraderEntry> * traderEntries() = 0;
+ virtual std::vector<Arts::ModuleDef> * modules() = 0;
+ virtual Arts::Object loadObject(Arts::TraderOffer offer) = 0;
+};
+
+class ARTS_EXPORT Loader_stub : virtual public Loader_base, virtual public Arts::Object_stub {
+protected:
+ Loader_stub();
+
+public:
+ Loader_stub(Arts::Connection *connection, long objectID);
+
+ std::string dataVersion();
+ std::vector<Arts::TraderEntry> * traderEntries();
+ std::vector<Arts::ModuleDef> * modules();
+ Arts::Object loadObject(Arts::TraderOffer offer);
+};
+
+class ARTS_EXPORT Loader_skel : virtual public Loader_base, virtual public Arts::Object_skel {
+protected:
+ // emitters for change notifications
+ inline void dataVersion_changed(const std::string& newValue) {
+ _emit_changed("dataVersion_changed",newValue);
+ }
+
+public:
+ Loader_skel();
+
+ static std::string _interfaceNameSkel();
+ std::string _interfaceName();
+ bool _isCompatibleWith(const std::string& interfacename);
+ void _buildMethodTable();
+ void dispatch(Arts::Buffer *request, Arts::Buffer *result,long methodID);
+};
+
+}
+#include "reference.h"
+namespace Arts {
+class ARTS_EXPORT Loader : public Arts::Object {
+private:
+ static Arts::Object_base* _Creator();
+ Loader_base *_cache;
+ inline Loader_base *_method_call() {
+ _pool->checkcreate();
+ if(_pool->base) {
+ _cache=(Loader_base *)_pool->base->_cast(Loader_base::_IID);
+ assert(_cache);
+ }
+ return _cache;
+ }
+
+protected:
+ inline Loader(Loader_base* b) : Arts::Object(b), _cache(0) {}
+
+
+public:
+ typedef Loader_base _base_class;
+
+ inline Loader() : Arts::Object(_Creator), _cache(0) {}
+ inline Loader(const Arts::SubClass& s) :
+ Arts::Object(Loader_base::_create(s.string())), _cache(0) {}
+ inline Loader(const Arts::Reference &r) :
+ Arts::Object(r.isString()?(Loader_base::_fromString(r.string())):(Loader_base::_fromReference(r.reference(),true))), _cache(0) {}
+ inline Loader(const Arts::DynamicCast& c) : Arts::Object(Loader_base::_fromDynamicCast(c.object())), _cache(0) {}
+ inline Loader(const Loader& target) : Arts::Object(target._pool), _cache(target._cache) {}
+ inline Loader(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}
+ inline static Loader null() {return Loader((Loader_base*)0);}
+ inline static Loader _from_base(Loader_base* b) {return Loader(b);}
+ inline Loader& operator=(const Loader& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _cache = target._cache;
+ _pool->Inc();
+ return *this;
+ }
+ inline Loader_base* _base() {return _cache?_cache:_method_call();}
+
+ inline std::string dataVersion();
+ inline std::vector<Arts::TraderEntry> * traderEntries();
+ inline std::vector<Arts::ModuleDef> * modules();
+ inline Arts::Object loadObject(Arts::TraderOffer offer);
+};
+
+}
+// Forward wrapper calls to _base classes:
+
+inline long Arts::InterfaceRepo::insertModule(const Arts::ModuleDef& newModule)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->insertModule(newModule):static_cast<Arts::InterfaceRepo_base*>(_method_call())->insertModule(newModule);
+}
+
+inline void Arts::InterfaceRepo::removeModule(long moduleID)
+{
+ _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->removeModule(moduleID):static_cast<Arts::InterfaceRepo_base*>(_method_call())->removeModule(moduleID);
+}
+
+inline Arts::InterfaceDef Arts::InterfaceRepo::queryInterface(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterface(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterface(name);
+}
+
+inline Arts::TypeDef Arts::InterfaceRepo::queryType(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryType(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryType(name);
+}
+
+inline Arts::EnumDef Arts::InterfaceRepo::queryEnum(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnum(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnum(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryChildren(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryChildren(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryChildren(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryInterfaces()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterfaces():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterfaces();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryTypes()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryTypes():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryTypes();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepo::queryEnums()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnums():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnums();
+}
+
+inline long Arts::InterfaceRepoV2::insertModule(const Arts::ModuleDef& newModule)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->insertModule(newModule):static_cast<Arts::InterfaceRepo_base*>(_method_call())->insertModule(newModule);
+}
+
+inline void Arts::InterfaceRepoV2::removeModule(long moduleID)
+{
+ _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->removeModule(moduleID):static_cast<Arts::InterfaceRepo_base*>(_method_call())->removeModule(moduleID);
+}
+
+inline Arts::InterfaceDef Arts::InterfaceRepoV2::queryInterface(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterface(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterface(name);
+}
+
+inline Arts::TypeDef Arts::InterfaceRepoV2::queryType(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryType(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryType(name);
+}
+
+inline Arts::EnumDef Arts::InterfaceRepoV2::queryEnum(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnum(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnum(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryChildren(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryChildren(name):static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryChildren(name);
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryInterfaces()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryInterfaces():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryInterfaces();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryTypes()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryTypes():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryTypes();
+}
+
+inline std::vector<std::string> * Arts::InterfaceRepoV2::queryEnums()
+{
+ return _cache?static_cast<Arts::InterfaceRepo_base*>(_cache)->queryEnums():static_cast<Arts::InterfaceRepo_base*>(_method_call())->queryEnums();
+}
+
+inline Arts::TypeIdentification Arts::InterfaceRepoV2::identifyType(const std::string& name)
+{
+ return _cache?static_cast<Arts::InterfaceRepoV2_base*>(_cache)->identifyType(name):static_cast<Arts::InterfaceRepoV2_base*>(_method_call())->identifyType(name);
+}
+
+inline void Arts::FlowSystemSender::processed()
+{
+ _cache?static_cast<Arts::FlowSystemSender_base*>(_cache)->processed():static_cast<Arts::FlowSystemSender_base*>(_method_call())->processed();
+}
+
+inline void Arts::FlowSystemSender::disconnect()
+{
+ _cache?static_cast<Arts::FlowSystemSender_base*>(_cache)->disconnect():static_cast<Arts::FlowSystemSender_base*>(_method_call())->disconnect();
+}
+
+inline long Arts::FlowSystemReceiver::receiveHandlerID()
+{
+ return _cache?static_cast<Arts::FlowSystemReceiver_base*>(_cache)->receiveHandlerID():static_cast<Arts::FlowSystemReceiver_base*>(_method_call())->receiveHandlerID();
+}
+
+inline void Arts::FlowSystemReceiver::disconnect()
+{
+ _cache?static_cast<Arts::FlowSystemReceiver_base*>(_cache)->disconnect():static_cast<Arts::FlowSystemReceiver_base*>(_method_call())->disconnect();
+}
+
+inline void Arts::FlowSystem::startObject(Arts::Object node)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->startObject(node):static_cast<Arts::FlowSystem_base*>(_method_call())->startObject(node);
+}
+
+inline void Arts::FlowSystem::stopObject(Arts::Object node)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->stopObject(node):static_cast<Arts::FlowSystem_base*>(_method_call())->stopObject(node);
+}
+
+inline void Arts::FlowSystem::connectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->connectObject(sourceObject, sourcePort, destObject, destPort):static_cast<Arts::FlowSystem_base*>(_method_call())->connectObject(sourceObject, sourcePort, destObject, destPort);
+}
+
+inline void Arts::FlowSystem::disconnectObject(Arts::Object sourceObject, const std::string& sourcePort, Arts::Object destObject, const std::string& destPort)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->disconnectObject(sourceObject, sourcePort, destObject, destPort):static_cast<Arts::FlowSystem_base*>(_method_call())->disconnectObject(sourceObject, sourcePort, destObject, destPort);
+}
+
+inline Arts::AttributeType Arts::FlowSystem::queryFlags(Arts::Object node, const std::string& port)
+{
+ return _cache?static_cast<Arts::FlowSystem_base*>(_cache)->queryFlags(node, port):static_cast<Arts::FlowSystem_base*>(_method_call())->queryFlags(node, port);
+}
+
+inline void Arts::FlowSystem::setFloatValue(Arts::Object node, const std::string& port, float value)
+{
+ _cache?static_cast<Arts::FlowSystem_base*>(_cache)->setFloatValue(node, port, value):static_cast<Arts::FlowSystem_base*>(_method_call())->setFloatValue(node, port, value);
+}
+
+inline Arts::FlowSystemReceiver Arts::FlowSystem::createReceiver(Arts::Object destObject, const std::string& destPort, Arts::FlowSystemSender sender)
+{
+ return _cache?static_cast<Arts::FlowSystem_base*>(_cache)->createReceiver(destObject, destPort, sender):static_cast<Arts::FlowSystem_base*>(_method_call())->createReceiver(destObject, destPort, sender);
+}
+
+inline bool Arts::GlobalComm::put(const std::string& variable, const std::string& value)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->put(variable, value):static_cast<Arts::GlobalComm_base*>(_method_call())->put(variable, value);
+}
+
+inline std::string Arts::GlobalComm::get(const std::string& variable)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->get(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->get(variable);
+}
+
+inline void Arts::GlobalComm::erase(const std::string& variable)
+{
+ _cache?static_cast<Arts::GlobalComm_base*>(_cache)->erase(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->erase(variable);
+}
+
+inline bool Arts::TmpGlobalComm::put(const std::string& variable, const std::string& value)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->put(variable, value):static_cast<Arts::GlobalComm_base*>(_method_call())->put(variable, value);
+}
+
+inline std::string Arts::TmpGlobalComm::get(const std::string& variable)
+{
+ return _cache?static_cast<Arts::GlobalComm_base*>(_cache)->get(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->get(variable);
+}
+
+inline void Arts::TmpGlobalComm::erase(const std::string& variable)
+{
+ _cache?static_cast<Arts::GlobalComm_base*>(_cache)->erase(variable):static_cast<Arts::GlobalComm_base*>(_method_call())->erase(variable);
+}
+
+inline std::string Arts::TraderOffer::interfaceName()
+{
+ return _cache?static_cast<Arts::TraderOffer_base*>(_cache)->interfaceName():static_cast<Arts::TraderOffer_base*>(_method_call())->interfaceName();
+}
+
+inline std::vector<std::string> * Arts::TraderOffer::getProperty(const std::string& name)
+{
+ return _cache?static_cast<Arts::TraderOffer_base*>(_cache)->getProperty(name):static_cast<Arts::TraderOffer_base*>(_method_call())->getProperty(name);
+}
+
+inline void Arts::TraderQuery::supports(const std::string& property, const std::string& value)
+{
+ _cache?static_cast<Arts::TraderQuery_base*>(_cache)->supports(property, value):static_cast<Arts::TraderQuery_base*>(_method_call())->supports(property, value);
+}
+
+inline std::vector<Arts::TraderOffer> * Arts::TraderQuery::query()
+{
+ return _cache?static_cast<Arts::TraderQuery_base*>(_cache)->query():static_cast<Arts::TraderQuery_base*>(_method_call())->query();
+}
+
+inline std::string Arts::Loader::dataVersion()
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->dataVersion():static_cast<Arts::Loader_base*>(_method_call())->dataVersion();
+}
+
+inline std::vector<Arts::TraderEntry> * Arts::Loader::traderEntries()
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->traderEntries():static_cast<Arts::Loader_base*>(_method_call())->traderEntries();
+}
+
+inline std::vector<Arts::ModuleDef> * Arts::Loader::modules()
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->modules():static_cast<Arts::Loader_base*>(_method_call())->modules();
+}
+
+inline Arts::Object Arts::Loader::loadObject(Arts::TraderOffer offer)
+{
+ return _cache?static_cast<Arts::Loader_base*>(_cache)->loadObject(offer):static_cast<Arts::Loader_base*>(_method_call())->loadObject(offer);
+}
+
+#endif /* CORE_H */
diff --git a/mcop/core.idl b/mcop/core.idl
new file mode 100644
index 0000000..33081e7
--- /dev/null
+++ b/mcop/core.idl
@@ -0,0 +1,715 @@
+/*
+
+ Copyright (C) 1999-2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+module Arts {
+// MCOP protocol
+
+enum HeaderMagic { MCOP_MAGIC = 0x4d434f50 }; /* gets marshalled as "MCOP" */
+ /* decimal 1296256848 */
+enum MessageType {
+ mcopMessageInvalid = 0, /* never send this */
+ mcopServerHello = 1,
+ mcopClientHello = 2,
+ mcopAuthAccept = 3,
+ mcopInvocation = 4,
+ mcopReturn = 5,
+ mcopOnewayInvocation = 6
+};
+
+/**
+ * This type is sent as header of each MCOP message.
+ */
+struct Header {
+ /**
+ * the value 0x504f434d, which is marshalled as MCOP
+ */
+ HeaderMagic magic;
+ long messageLength;
+ MessageType messageType;
+};
+
+/**
+ * This is sent as start of each normal (twoway) invocation
+ */
+struct Invocation {
+ /**
+ * The ID of the object receiving the request
+ */
+ long objectID;
+ /**
+ * The ID of the method that is to be invoked
+ */
+ long methodID;
+ /**
+ * A unique number of the request (needed to send the return code back)
+ */
+ long requestID;
+};
+
+/**
+ * This is sent as start of each oneway invocation
+ */
+struct OnewayInvocation {
+ /**
+ * The ID of the object receiving the request
+ */
+ long objectID;
+ /**
+ * The ID of the method that is to be invoked
+ */
+ long methodID;
+};
+
+/**
+ * Body of the mcopServerHello MCOP message
+ */
+struct ServerHello {
+ string mcopVersion;
+ string serverID;
+ sequence<string> authProtocols;
+ string authSeed;
+};
+
+/**
+ * Body of the mcopClientHello MCOP message
+ */
+struct ClientHello {
+ string serverID;
+ string authProtocol;
+ string authData;
+};
+
+/**
+ * The message you get when you connect a MCOP server. The MCOP server can
+ * send you some useful information here. Usually, it will send you
+ *
+ * GlobalComm=<object reference of a global comm interface>
+ * InterfaceRepo=<object reference of an interface repository>
+ *
+ * But as this is called "hints" it doesn't necessarily need to happen.
+ */
+struct AuthAccept {
+ sequence<string> hints;
+};
+
+/**
+ * An object reference
+ */
+struct ObjectReference {
+ /**
+ * A unique ID for the server the object is located on, (a server ID may
+ * i.e. be composed of start time, hostname, and pid)
+ */
+ string serverID;
+
+ /**
+ * The number of the object under that server
+ */
+ long objectID;
+
+ /**
+ * where the server holding object can be reached
+ */
+ sequence<string> urls;
+};
+
+// Interface definitions
+
+/**
+ * The definition of a parameter of a method
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct ParamDef {
+ string type;
+ string name;
+ sequence<string> hints;
+};
+
+/**
+ * Twoway methods are such where the calling process does a call and is
+ * suspended until some result (maybe even a void result) gets back.
+ *
+ * Oneway methods are one shot and forget methods: you send the invocation,
+ * and continue. Maybe it will be received, maybe executed later. You will
+ * never hear the result.
+ */
+enum MethodType {
+ methodOneway = 1,
+ methodTwoway = 2
+};
+
+/**
+ * The definition of a method.
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct MethodDef {
+ string name;
+ string type;
+ MethodType flags;
+
+ sequence<ParamDef> signature;
+ sequence<string> hints;
+};
+
+/**
+ * an attribute
+ *
+ * flags should contain things like
+ *
+ * @li attribute is readonly/writeonly/readwrite
+ * @li attribute is incoming/outgoing stream
+ * @li if it's a stream, it also should contain the information whether it is
+ * asynchronous or synchronous
+ * @li NB20000320: see InterfaceDef for the meaning of streamDefault
+ */
+enum AttributeType {
+ streamIn = 1,
+ streamOut = 2,
+ streamMulti = 4,
+ attributeStream = 8,
+ attributeAttribute = 16,
+ streamAsync = 32,
+ streamDefault = 64
+};
+
+/**
+ * The definition of an attribute and/or stream
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct AttributeDef {
+ string name;
+ string type;
+ AttributeType flags;
+ sequence<string> hints;
+};
+
+/**
+ * InterfaceDef - interface definition structure
+ *
+ * defines what methods/attributes a particular interface supports: these
+ * do not contain the methods/attributes of inherited interfaces.
+ *
+ * inheritedInterfaces only contains the names of Interfaces that this one
+ * inherits in exactly one step. So to see if interface XYZ is inherited
+ * from ABC, you need to check the "inheritedInterfaces" of XYZ, and their
+ * "inheritedInterfaces" and their "inheritedInterfaces" and so on.
+ *
+ * - NB20000320: defaultPorts allows to connect to those port by default if
+ * connection is made in the corresponding direction.
+ * It cannot be just an attribute flag because of the syntax
+ * on a separate line.
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+
+struct InterfaceDef {
+ string name;
+
+ sequence<string> inheritedInterfaces;
+ sequence<MethodDef> methods;
+ sequence<AttributeDef> attributes;
+
+ sequence<string> defaultPorts;
+ sequence<string> hints;
+};
+
+// Type definitions (struct's and such)
+
+/**
+ * One component of a struct
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct TypeComponent {
+ string type;
+ string name;
+ sequence<string> hints;
+};
+
+/**
+ * The definition of a struct
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct TypeDef {
+ string name;
+
+ sequence<TypeComponent> contents;
+ sequence<string> hints;
+};
+
+/**
+ * One item of an enum value
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct EnumComponent {
+ string name;
+
+ long value;
+ sequence<string> hints;
+};
+
+/**
+ * The definition of an enum
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct EnumDef {
+ /**
+ * name if the enum, "_anonymous_" for anonymous enum - of course, when
+ * using namespaces, this can also lead to things like "Arts::_anonymous_",
+ * which would mean an anonymous enum in the Arts namespace
+ */
+ string name;
+
+ sequence<EnumComponent> contents;
+ sequence<string> hints;
+};
+
+/**
+ * The contents of an idl file
+ *
+ * hints is reserved for future extensions, such as default, min and maxvalues
+ */
+struct ModuleDef {
+ string moduleName;
+
+ sequence<EnumDef> enums;
+ sequence<TypeDef> types;
+ sequence<InterfaceDef> interfaces;
+ sequence<string> hints;
+};
+
+/**
+ * The interface repository
+ */
+interface InterfaceRepo {
+ /**
+ * inserts the contents of a module into the interface repository
+ *
+ * @returns an ID which can be used to remove the entry again
+ */
+ long insertModule(ModuleDef newModule);
+
+ /**
+ * removes the contents of a module from the interface repository
+ */
+ void removeModule(long moduleID);
+
+ /**
+ * queries the definition of an interface
+ */
+ InterfaceDef queryInterface(string name);
+
+ /**
+ * queries the definition of a type
+ */
+ TypeDef queryType(string name);
+
+ /**
+ * queries the definition of an enum value
+ */
+ EnumDef queryEnum(string name);
+
+ /**
+ * queries all interfaces that inherit a given interface
+ */
+ sequence<string> queryChildren(string name);
+
+ /**
+ * queries all interfaces
+ */
+ sequence<string> queryInterfaces();
+
+ /**
+ * queries all types
+ */
+ sequence<string> queryTypes();
+
+ /**
+ * queries all enums
+ */
+ sequence<string> queryEnums();
+};
+
+enum TypeIdentification {
+ tiUnknown = 0,
+ tiVoid = 1,
+ tiLong = 2,
+ tiByte = 3,
+ tiString = 4,
+ tiBoolean = 5,
+ tiFloat = 6,
+ tiEnum = 128,
+ tiType = 129,
+ tiInterface = 130
+};
+
+interface InterfaceRepoV2 : InterfaceRepo {
+ /**
+ * identifies whether a type is a primitive, enum, type or interface,
+ * or not known at all
+ */
+ TypeIdentification identifyType(string name);
+};
+
+/**
+ * Flow System interface
+ */
+
+/**
+ * Internal use: implement distributed asynchronous streams.
+ *
+ * The FlowSystemSender object transmits the packets that should be sent
+ * over the stream via _allocCustomMessage (Object_base).
+ */
+interface FlowSystemSender {
+ /**
+ * This method is invoked whenever the receiver has finished processing
+ * a packet of the stream
+ */
+ oneway void processed();
+
+ /**
+ * This method is for telling the local FlowSystemSender to break the
+ * connection to the remote Receiver (it's not intended to be called
+ * remotely)
+ */
+ void disconnect();
+};
+
+/**
+ * Internal use: implement distributed asynchronous streams.
+ *
+ * The FlowSystemReceiver object receives and extracts the packets sent by
+ * the sender object and injects them in the notification system again.
+ */
+interface FlowSystemReceiver {
+ /**
+ * The custom message ID which should be used to send the stream packets
+ */
+ readonly attribute long receiveHandlerID;
+
+ /**
+ * This method is for telling the local FlowSystemReceiver to break the
+ * connection to the remote Sender (it's not intended to be called
+ * remotely)
+ */
+ void disconnect();
+};
+
+/**
+ * A flow system.
+ *
+ * Flow systems handle the streaming between MCOP objects. As this streaming
+ * is network transparent (at least for asynchronous streams) they have this
+ * remote interface.
+ */
+interface FlowSystem {
+ /**
+ * This starts a scheduling node
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void startObject(object node);
+
+ /**
+ * This stops a scheduling node
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void stopObject(object node);
+
+ /**
+ * This connects two objects, maybe even remote
+ *
+ * it is important that
+ * - sourceObject/sourcePort points to the node the signal flow is
+ * coming from
+ * - destObject/destPort points to the node/port the signal flow is
+ * going to
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void connectObject(object sourceObject, string sourcePort,
+ object destObject, string destPort);
+
+ /**
+ * This disconnects two objects, maybe even remote
+ *
+ * it is important that
+ * @li sourceObject/sourcePort points to the node the signal flow is
+ * coming from
+ * @li destObject/destPort points to the node/port the signal flow is
+ * going to
+ *
+ * Don't use this manually. Use object->_node()->connect(...) instead.
+ */
+ void disconnectObject(object sourceObject, string sourcePort,
+ object destObject, string destPort);
+
+ /**
+ * queries the stream flags - returns 0 when such a stream isn't
+ * present
+ */
+ AttributeType queryFlags(object node, string port);
+
+ /**
+ * directly sets an audio port to a fixed value
+ */
+ void setFloatValue(object node, string port, float value);
+
+ /**
+ * network transparent connections
+ */
+ FlowSystemReceiver createReceiver(object destObject, string destPort,
+ FlowSystemSender sender);
+};
+
+/**
+ * A global communication space used to obtain initial object references
+ *
+ * MCOP needs a way to connect to initial (global) object references. This
+ * is done by these global communication spaces.
+ */
+interface GlobalComm {
+ /**
+ * puts a variable/value pair into the global communication
+ * space - it will not change the value of the variable if it is
+ * already present. Returns true if success, false if the variable
+ * was already there.
+ */
+ boolean put(string variable, string value);
+
+ /**
+ * gets the value of a variable out of the global communication
+ * space - it returns an empty string when the variable isn't there
+ */
+ string get(string variable);
+
+ /**
+ * removes a variable from the global communication space
+ */
+ void erase(string variable);
+};
+
+/**
+ * global communication based on the /tmp/mcop-<username> directory
+ */
+interface TmpGlobalComm : GlobalComm {
+};
+
+/*
+ * Trading interfaces follow - trading is used to locate objects with certain
+ * properties. This is especially recommended, if you want to allow that after
+ * your code has been released, people can extend it, without changing your
+ * code, by adding new components.
+ */
+
+/**
+ * TraderOffer - this contains an offer of an object (which is usually returned
+ * as result of a query.
+ */
+interface TraderOffer {
+ /**
+ * You can use this interface name to create one of the objects that
+ * fulfill your query
+ */
+ readonly attribute string interfaceName;
+
+ /**
+ * This allows you to query additional information about the offer,
+ * such as the author of the plugin, the name of the library that
+ * implements it (if it is a library) or similar.
+ *
+ * Since some properties support having multiple values, this always
+ * returns a sequence<string>, which may be empty if the property isn't
+ * present at all.
+ */
+ sequence<string> getProperty(string name);
+};
+
+/**
+ * TraderQuery - this is a query against the trader. The idea is simple: you
+ * say what you need, and the trader offers you components that do what you
+ * want.
+ */
+interface TraderQuery {
+ /**
+ * This restricts the query to only objects which support a "property"
+ * with the value "value". For instance, you could say
+ *
+ * aquery.supports("Interface","Arts::PlayObject");
+ *
+ * to restrict the matching objects to only those that support the
+ * interface Arts::PlayObject
+ */
+ void supports(string property, string value);
+
+ /**
+ * This performs the query, and returns a set of results
+ */
+ sequence<TraderOffer> query();
+};
+
+/**
+ * Arts::Object is the base object that every interface implicitely inherits
+ *
+ * it is also the source for generation of the Object_stub stuff
+ * (use mcopidl -e Arts::Object to avoid code generation for this interface)
+ */
+interface Object {
+ /**
+ * access to the flow system this object is running in
+ */
+ readonly attribute FlowSystem _flowSystem;
+
+ /** <interface description>
+ * returns the ID for methodinvocations to this specific method
+ * methodID = 0 => _lookupMethod (always)
+ */
+ long _lookupMethod(MethodDef methodDef);
+
+ /** <interface description>
+ * returns the name of the interface
+ * methodID = 1 => _interfaceName (always)
+ */
+ string _interfaceName();
+
+ /** <interface description>
+ * returns the interface description to a given interface
+ * methodID = 2 => _queryInterface (always)
+ */
+ InterfaceDef _queryInterface(string name);
+
+ /** <interface description>
+ * returns the type description to a given type
+ * methodID = 3 => _queryType (always)
+ */
+ TypeDef _queryType(string name);
+
+ /** <interface description>
+ * returns the enum description to a given enum
+ * methodID = 4 => _queryEnum (always)
+ */
+ EnumDef _queryEnum(string name);
+
+ /**
+ * stringifies the object to one string
+ */
+ string _toString();
+
+ /** <interface description>
+ * Run-time type compatibility check
+ */
+ boolean _isCompatibleWith(string interfacename);
+
+ /** <reference counting>
+ * prepares object for remote transmission (so that it will not be freed
+ * soon, since the remote receiver expects it to be there after receiving
+ * it)
+ */
+ void _copyRemote();
+
+ /** <reference counting>
+ * declares that the object is used remotely now (do that only after
+ * _copyRemote)
+ */
+ void _useRemote();
+
+ /** <reference counting>
+ * declares that the object is no longer used remotely
+ */
+ void _releaseRemote();
+
+ /** <aggregation>
+ * add a child object - this makes this object hold a strong reference to
+ * the child object (i.e. the child object will stay alive at least as
+ * long as the object does)
+ *
+ * if there is already a child with the same name, a postfix will be added
+ * automatically (i.e. if you add an object named "view" twice, the first
+ * will be called view, the second view1).
+ */
+ string _addChild(object child, string name);
+
+ /** <aggregation>
+ * removes a child object
+ */
+ boolean _removeChild(string name);
+
+ /** <aggregation>
+ * gets a child object
+ */
+ object _getChild(string name);
+
+ /** <aggregation>
+ * lists all children
+ */
+ sequence<string> _queryChildren();
+};
+
+/**
+ * a simple struct which can hold any other type
+ */
+struct Any {
+ string type;
+ sequence<byte> value;
+};
+
+/**
+ * TraderEntries as produced by the loader
+ */
+
+struct TraderEntry {
+ string interfaceName;
+ sequence<string> lines;
+};
+
+/**
+ * loader to load plugins (implemented in some language/binary format)
+ */
+interface Loader {
+ object loadObject(TraderOffer offer);
+
+ /*
+ * this is used for the type system to cache your trader data and
+ * module data as long as it stays unchanged
+ */
+ readonly attribute string dataVersion;
+
+ /*
+ * the trader entries of the components that can be loaded
+ */
+ readonly attribute sequence<TraderEntry> traderEntries;
+
+ /*
+ * the interface information of the components that can be loaded
+ */
+ readonly attribute sequence<ModuleDef> modules;
+};
+
+};
diff --git a/mcop/datapacket.cc b/mcop/datapacket.cc
new file mode 100644
index 0000000..8f9848f
--- /dev/null
+++ b/mcop/datapacket.cc
@@ -0,0 +1,65 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <string.h>
+#include "datapacket.h"
+#include "buffer.h"
+
+using namespace Arts;
+
+long GenericDataPacket::_staticDataPacketCount = 0;
+
+/**** specific DataPacket types ****/
+
+void FloatDataPacket::read(Buffer& stream)
+{
+ size = stream.readLong();
+ ensureCapacity(size);
+ for(int i=0;i<size;i++) contents[i] = stream.readFloat();
+}
+
+void FloatDataPacket::write(Buffer& stream)
+{
+ stream.writeLong(size);
+ for(int i=0;i<size;i++) stream.writeFloat(contents[i]);
+}
+
+void ByteDataPacket::read(Buffer& stream)
+{
+ size = stream.readLong();
+ ensureCapacity(size);
+
+ // we know that bytes are marshalled as bytes,
+ // so we can read them as block
+ unsigned char *buffer = (unsigned char *)stream.read(size);
+ if(buffer)
+ memcpy(contents,buffer,size);
+}
+
+void ByteDataPacket::write(Buffer& stream)
+{
+ // we know that bytes are marshalled as bytes,
+ // so we can write them as block
+
+ stream.writeLong(size);
+ stream.write(contents,size);
+}
diff --git a/mcop/datapacket.h b/mcop/datapacket.h
new file mode 100644
index 0000000..34cd211
--- /dev/null
+++ b/mcop/datapacket.h
@@ -0,0 +1,230 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef DATAPACKET_H
+#define DATAPACKET_H
+
+#include "arts_export.h"
+#include "buffer.h"
+
+/*
+ * BC - Status (2002-03-08): GenericDataChannel, DataPacket types
+ *
+ * These classes must be kept binary compatible, as the do interact with
+ * generated code. So you MUST KNOW WHAT YOU ARE DOING, once you start
+ * using the provided d pointers for extensions.
+ */
+
+namespace Arts {
+class GenericDataChannelPrivate;
+class GenericDataPacket;
+/*
+ * The GenericDataChannel interface is to be implemented by the flowsystem
+ */
+class ARTS_EXPORT GenericDataChannel {
+private:
+ GenericDataChannelPrivate *d; // unused
+
+protected:
+ friend class GenericDataPacket;
+
+ /*
+ * this is used internally by DataPacket
+ */
+ virtual void processedPacket(GenericDataPacket *packet) = 0;
+
+ /*
+ * used internally by DataPacket
+ */
+ virtual void sendPacket(GenericDataPacket *packet) = 0;
+
+public:
+ /*
+ * used to set pull delivery mode
+ */
+ virtual void setPull(int packets, int capacity) = 0;
+ virtual void endPull() = 0;
+
+ GenericDataChannel() : d(0)
+ {
+ }
+};
+
+/*
+ * DataPackets are the heard of asynchronous streaming (MCOP has synchronous
+ * and asynchronous streams). They are used
+ *
+ * - in the interface async streams expose to C++ implementations of MCOP
+ * interfaces (they directly deal with datapackets)
+ *
+ * - from the FlowSystem implemenentations
+ */
+
+/**
+ * The GenericDataPacket class provides the interface the flow system can
+ * use to deal with data packets.
+ */
+class GenericDataPacketPrivate;
+
+class ARTS_EXPORT GenericDataPacket {
+private:
+ GenericDataPacketPrivate *d;
+ static long _staticDataPacketCount;
+
+public:
+ /**
+ * the amount of active data packets (memory leak debugging only)
+ */
+ static long _dataPacketCount() { return _staticDataPacketCount; }
+
+ /**
+ * the channel this datapacket belongs to
+ */
+ GenericDataChannel *channel;
+
+ /**
+ * ensureCapactity ensures that there is room for at least capacity
+ * Elements in the packet. This is implemented destructive - that
+ * means: you may not find your old contents in the packet after
+ * calling ensureCapacity
+ */
+ virtual void ensureCapacity(int capacity) = 0;
+
+ /**
+ * read/write write the contents of the packet. Read will also
+ * automatically ensure that capacity is adapted before reading.
+ */
+ virtual void read(Buffer& stream) = 0;
+ virtual void write(Buffer& stream) = 0;
+
+ /**
+ * having size here (and not in the derived concrete DataPackets) is so
+ * that we can see whether the sender can't supply more data (and starts
+ * sending zero size packets
+ */
+ int size;
+
+ /**
+ * useCount is to be set from sendPacket
+ */
+ int useCount;
+
+ inline void send()
+ {
+ channel->sendPacket(this);
+ }
+ inline void processed()
+ {
+ useCount--;
+ if(useCount == 0)
+ {
+ if(channel)
+ channel->processedPacket(this);
+ else
+ delete this;
+ }
+ }
+
+ virtual ~GenericDataPacket()
+ {
+ _staticDataPacketCount--;
+ }
+
+protected:
+ GenericDataPacket(GenericDataChannel *channel)
+ :d(0),channel(channel),useCount(0)
+ {
+ _staticDataPacketCount++;
+ }
+};
+
+/**
+ * The DataPacket<T> interface is what C++ implementations of MCOP interfaces
+ * will need to use.
+ */
+template<class T>
+class DataPacket : public GenericDataPacket {
+public:
+ T *contents;
+
+protected:
+ DataPacket(GenericDataChannel *channel)
+ : GenericDataPacket(channel) {}
+ ~DataPacket() {}
+};
+
+/**
+ * The RawDataPacket<T> interface handles raw class T arrays of data
+ */
+template<class T>
+class RawDataPacket : public DataPacket<T> {
+protected:
+ int capacity;
+ void ensureCapacity(int newCapacity)
+ {
+ if(newCapacity > capacity)
+ {
+ delete[] this->contents;
+ capacity = newCapacity;
+ this->contents = new T[capacity];
+ }
+ }
+ RawDataPacket(int capacity, GenericDataChannel *channel)
+ :DataPacket<T>(channel), capacity(capacity)
+ {
+ this->size = capacity;
+ this->contents = new T[capacity];
+ }
+ ~RawDataPacket()
+ {
+ delete[] this->contents;
+ }
+};
+
+/**
+ * FloatDataPacket finally is one concrete DataPacket (which contains the
+ * information how to marshal a datapacket of type float)
+ */
+class ARTS_EXPORT FloatDataPacket : public RawDataPacket<float> {
+public:
+ FloatDataPacket(int capacity, GenericDataChannel *channel)
+ : RawDataPacket<float>(capacity, channel)
+ {
+ //
+ }
+ void read(Buffer& stream);
+ void write(Buffer& stream);
+};
+
+class ARTS_EXPORT ByteDataPacket : public RawDataPacket<mcopbyte> {
+public:
+ ByteDataPacket(int capacity, GenericDataChannel *channel)
+ : RawDataPacket<mcopbyte>(capacity, channel)
+ {
+ //
+ }
+ void read(Buffer& stream);
+ void write(Buffer& stream);
+};
+
+}
+#endif
diff --git a/mcop/debug.cc b/mcop/debug.cc
new file mode 100644
index 0000000..208727b
--- /dev/null
+++ b/mcop/debug.cc
@@ -0,0 +1,821 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ (see also below for details on the copyright of arts_strdup_printf,
+ which is taken from GLib)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "debug.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "thread.h"
+
+static int arts_debug_level = Arts::Debug::lInfo;
+static bool arts_debug_abort = false;
+static const char *arts_debug_prefix = "";
+static char *messageAppName = 0;
+static Arts::Mutex *arts_debug_mutex = 0;
+
+/* routines for variable length sprintf without buffer overflow (from GLib) */
+static char* arts_strdup_vprintf(const char *format, va_list args1);
+
+namespace Arts {
+
+static char * shell_quote(const char *s)
+{
+ char *result;
+ char *p;
+ p = result = static_cast<char*>( malloc(strlen(s)*5+1) );
+ while(*s)
+ {
+ if (*s == '\'')
+ {
+ *p++ = '\'';
+ *p++ = '"';
+ *p++ = *s++;
+ *p++ = '"';
+ *p++ = '\'';
+ }
+ else
+ {
+ *p++ = *s++;
+ }
+ }
+ *p = '\0';
+ return result;
+}
+
+/*
+ * Call the graphical application to display a message, if
+ * defined. Otherwise, send to standard error. Debug messages are
+ * always sent to standard error because they tend to be very verbose.
+ * Note that the external application is run in the background to
+ * avoid blocking the sound server.
+ */
+static void output_message(Debug::Level level, const char *msg) {
+ char *quoted_msg;
+ char *buff = 0;
+
+ /* default to text output if no message app is defined or if it is a debug message. */
+ if (messageAppName == 0 || !strcmp(messageAppName, "") || (level == Debug::lDebug))
+ {
+ fprintf(stderr, "%s\n", msg);
+ return;
+ }
+
+ quoted_msg = shell_quote(msg);
+ switch (level) {
+ case Debug::lFatal:
+ buff = arts_strdup_printf("%s -e 'Sound server fatal error:\n\n%s' &", messageAppName, quoted_msg);
+ break;
+ case Debug::lWarning:
+ buff = arts_strdup_printf("%s -w 'Sound server warning message:\n\n%s' &", messageAppName, quoted_msg);
+ break;
+ case Debug::lInfo:
+ buff = arts_strdup_printf("%s -i 'Sound server informational message:\n\n%s' &", messageAppName, quoted_msg);
+ break;
+ default:
+ break; // avoid compile warning
+ }
+ free(quoted_msg);
+
+ if(buff != 0)
+ {
+ system(buff);
+ free(buff);
+ }
+}
+
+/*
+ * Display a message using output_message. If the message is the same
+ * as the previous one, just increment a count but don't display
+ * it. This prevents flooding the user with duplicate warnings. If the
+ * message is not the same as the previous one, then we report the
+ * previously repeated message (if any) and reset the last message and
+ * count.
+ */
+static void display_message(Debug::Level level, const char *msg) {
+ static char lastMsg[1024];
+ static Debug::Level lastLevel;
+ static int msgCount = 0;
+
+ if(arts_debug_mutex)
+ arts_debug_mutex->lock();
+
+ if (!strncmp(msg, lastMsg, 1024))
+ {
+ msgCount++;
+ } else {
+ if (msgCount > 0)
+ {
+ char *buff;
+ buff = arts_strdup_printf("%s\n(The previous message was repeated %d times.)", lastMsg, msgCount);
+ output_message(lastLevel, buff);
+ free(buff);
+ }
+ strncpy(lastMsg, msg, 1024);
+ lastMsg[ 1023 ] = '\0';
+ lastLevel = level;
+ msgCount = 0;
+ output_message(level, msg);
+ }
+
+ if(arts_debug_mutex)
+ arts_debug_mutex->unlock();
+}
+
+static class DebugInitFromEnv {
+public:
+ DebugInitFromEnv() {
+ const char *env = getenv("ARTS_DEBUG");
+ if(env)
+ {
+ if(strcmp(env,"debug") == 0)
+ arts_debug_level = Debug::lDebug;
+ else if(strcmp(env,"info") == 0)
+ arts_debug_level = Debug::lInfo;
+ else if(strcmp(env,"warning") == 0)
+ arts_debug_level = Debug::lWarning;
+ else if(strcmp(env,"quiet") == 0)
+ arts_debug_level = Debug::lFatal;
+ else
+ {
+ fprintf(stderr,
+ "ARTS_DEBUG must be one of debug,info,warning,quiet\n");
+ }
+ }
+ env = getenv("ARTS_DEBUG_ABORT");
+ if(env)
+ arts_debug_abort = true;
+ }
+} debugInitFromEnv;
+
+}
+
+void Arts::Debug::init(const char *prefix, Level level)
+{
+ arts_debug_level = level;
+ arts_debug_prefix = prefix;
+}
+
+void Arts::Debug::fatal(const char *fmt, ...)
+{
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lFatal, buff);
+ free(buff);
+
+ if(arts_debug_abort) abort();
+ exit(1);
+}
+
+void Arts::Debug::warning(const char *fmt, ...)
+{
+ if(lWarning >= arts_debug_level)
+ {
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lWarning, buff);
+ free(buff);
+ }
+}
+
+void Arts::Debug::info(const char *fmt, ...)
+{
+ if(lInfo >= arts_debug_level)
+ {
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lInfo, buff);
+ free(buff);
+ }
+}
+
+void Arts::Debug::debug(const char *fmt, ...)
+{
+ if(lDebug >= arts_debug_level)
+ {
+ char *buff;
+ va_list ap;
+
+ va_start(ap, fmt);
+ buff = arts_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ display_message(Debug::lDebug, buff);
+ free(buff);
+ }
+}
+
+void Arts::Debug::messageApp(const char *appName)
+{
+ messageAppName = (char*) realloc(messageAppName, strlen(appName)+1);
+ strcpy(messageAppName, appName);
+}
+
+void Arts::Debug::initMutex()
+{
+ arts_return_if_fail(arts_debug_mutex == 0);
+
+ arts_debug_mutex = new Arts::Mutex();
+}
+
+void Arts::Debug::freeMutex()
+{
+ arts_return_if_fail(arts_debug_mutex != 0);
+
+ delete arts_debug_mutex;
+ arts_debug_mutex = 0;
+}
+
+/*
+ * For the sake of portability (snprintf is non-portable), what follows is an
+ * implementation of a variant g_strdup_printf, to format debug messages of
+ * an arbitary length appropriately. This is reduntant with flow/gsl/gslglib.c,
+ * however, as libmcop doesn't necessarily link against gslglib.c, this is a
+ * more-or-less complete copy.
+ */
+
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GScanner: Flexible lexical scanner for general purpose.
+ * Copyright (C) 1997, 1998 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 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define g_warning printf
+#define g_strerror strerror
+
+/*--- gslglib.h ---*/
+
+#include <limits.h>
+#include <float.h>
+#include <stddef.h>
+#include <stdarg.h>
+
+/* --- GLib typedefs --- */
+typedef void* gpointer;
+typedef const void* gconstpointer;
+typedef char gchar;
+typedef unsigned char guchar;
+typedef signed short gshort;
+typedef unsigned short gushort;
+typedef signed int gint;
+typedef unsigned int guint;
+typedef signed long glong;
+typedef unsigned long gulong;
+typedef float gfloat;
+typedef double gdouble;
+typedef size_t gsize;
+typedef gchar gint8;
+typedef guchar guint8;
+typedef gshort gint16;
+typedef gushort guint16;
+typedef gint gint32;
+typedef guint guint32;
+typedef gint gboolean;
+typedef gint32 GTime;
+#ifdef __alpha
+typedef long int gint64;
+typedef unsigned long int guint64;
+#else
+typedef long long int gint64;
+typedef unsigned long long int guint64;
+#endif
+typedef struct _GString GString;
+
+/* --- standard macros --- */
+#ifndef ABS
+#define ABS(a) ((a) > 0 ? (a) : -(a))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef CLAMP
+#define CLAMP(v,l,h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v))
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+/* --- configure stuff!!! --- */
+#ifdef WORDS_BIGENDIAN
+#define G_BYTE_ORDER G_BIG_ENDIAN
+#else
+#define G_BYTE_ORDER G_LITTLE_ENDIAN
+#endif
+
+/* #define GLIB_HAVE_STPCPY 1 */
+/* Define G_VA_COPY() to do the right thing for copying va_list variables.
+ * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
+ */
+#if !defined (G_VA_COPY)
+# if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32) || defined(WIN32)) || defined(__s390__) || defined(__x86_64__)
+# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
+# elif defined (G_VA_COPY_AS_ARRAY)
+# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list))
+# else /* va_list is a pointer */
+# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2))
+# endif /* va_list is a pointer */
+#endif /* !G_VA_COPY */
+
+/* --- glib macros --- */
+#define G_MINFLOAT FLT_MIN
+#define G_MAXFLOAT FLT_MAX
+#define G_MINDOUBLE DBL_MIN
+#define G_MAXDOUBLE DBL_MAX
+#define G_MINSHORT SHRT_MIN
+#define G_MAXSHORT SHRT_MAX
+#define G_MAXUSHORT USHRT_MAX
+#define G_MININT INT_MIN
+#define G_MAXINT INT_MAX
+#define G_MAXUINT UINT_MAX
+#define G_MINLONG LONG_MIN
+#define G_MAXLONG LONG_MAX
+#define G_MAXULONG ULONG_MAX
+#define G_USEC_PER_SEC 1000000
+#define G_LITTLE_ENDIAN 1234
+#define G_BIG_ENDIAN 4321
+
+#define G_STRINGIFY(macro_or_string) G_STRINGIFY_ARG (macro_or_string)
+#define G_STRINGIFY_ARG(contents) #contents
+#if defined __GNUC__ && !defined __cplusplus
+# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__) ":" __PRETTY_FUNCTION__ "()"
+#else
+# define G_STRLOC __FILE__ ":" G_STRINGIFY (__LINE__)
+#endif
+
+/* subtract from biased_exponent to form base2 exponent (normal numbers) */
+typedef union _GDoubleIEEE754 GDoubleIEEE754;
+typedef union _GFloatIEEE754 GFloatIEEE754;
+#define G_IEEE754_FLOAT_BIAS (127)
+#define G_IEEE754_DOUBLE_BIAS (1023)
+/* multiply with base2 exponent to get base10 exponent (nomal numbers) */
+#define G_LOG_2_BASE_10 (0.30102999566398119521)
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+union _GFloatIEEE754
+{
+ gfloat v_float;
+ struct {
+ guint mantissa : 23;
+ guint biased_exponent : 8;
+ guint sign : 1;
+ } mpn;
+};
+union _GDoubleIEEE754
+{
+ gdouble v_double;
+ struct {
+ guint mantissa_low : 32;
+ guint mantissa_high : 20;
+ guint biased_exponent : 11;
+ guint sign : 1;
+ } mpn;
+};
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+union _GFloatIEEE754
+{
+ gfloat v_float;
+ struct {
+ guint sign : 1;
+ guint biased_exponent : 8;
+ guint mantissa : 23;
+ } mpn;
+};
+union _GDoubleIEEE754
+{
+ gdouble v_double;
+ struct {
+ guint sign : 1;
+ guint biased_exponent : 11;
+ guint mantissa_high : 20;
+ guint mantissa_low : 32;
+ } mpn;
+};
+#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+#error unknown ENDIAN type
+#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#define GLIB_SIZEOF_INTMAX (8 /* educated guess */)
+
+typedef struct
+{
+ guint min_width;
+ guint precision;
+ gboolean alternate_format, zero_padding, adjust_left, locale_grouping;
+ gboolean add_space, add_sign, possible_sign, seen_precision;
+ gboolean mod_half, mod_long, mod_extra_long;
+} PrintfArgSpec;
+
+
+static gsize
+printf_string_upper_bound (const gchar *format,
+ gboolean may_warn,
+ va_list args)
+{
+ static gboolean honour_longs = sizeof(long) > 4 || sizeof(void*) > 4;
+ gsize len = 1;
+
+ if (!format)
+ return len;
+
+ while (*format)
+ {
+ register gchar c = *format++;
+
+ if (c != '%')
+ len += 1;
+ else /* (c == '%') */
+ {
+ PrintfArgSpec spec = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ gboolean seen_l = FALSE, conv_done = FALSE;
+ gsize conv_len = 0;
+ const gchar *spec_start = format;
+
+ do
+ {
+ c = *format++;
+ switch (c)
+ {
+ GDoubleIEEE754 u_double;
+ guint v_uint;
+ gint v_int;
+ const gchar *v_string;
+
+ /* beware of positional parameters
+ */
+ case '$':
+ if (may_warn)
+ g_warning (G_STRLOC ": unable to handle positional parameters (%%n$)");
+ len += 1024; /* try adding some safety padding */
+ break;
+
+ /* parse flags
+ */
+ case '#':
+ spec.alternate_format = TRUE;
+ break;
+ case '0':
+ spec.zero_padding = TRUE;
+ break;
+ case '-':
+ spec.adjust_left = TRUE;
+ break;
+ case ' ':
+ spec.add_space = TRUE;
+ break;
+ case '+':
+ spec.add_sign = TRUE;
+ break;
+ case '\'':
+ spec.locale_grouping = TRUE;
+ break;
+
+ /* parse output size specifications
+ */
+ case '.':
+ spec.seen_precision = TRUE;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ v_uint = c - '0';
+ c = *format;
+ while (c >= '0' && c <= '9')
+ {
+ format++;
+ v_uint = v_uint * 10 + c - '0';
+ c = *format;
+ }
+ if (spec.seen_precision)
+ spec.precision = MAX (spec.precision, v_uint);
+ else
+ spec.min_width = MAX (spec.min_width, v_uint);
+ break;
+ case '*':
+ v_int = va_arg (args, int);
+ if (spec.seen_precision)
+ {
+ /* forget about negative precision */
+ if (v_int >= 0)
+ spec.precision = MAX (spec.precision, (unsigned)v_int);
+ }
+ else
+ {
+ if (v_int < 0)
+ {
+ v_int = - v_int;
+ spec.adjust_left = TRUE;
+ }
+ spec.min_width = MAX (spec.min_width, (unsigned)v_int);
+ }
+ break;
+
+ /* parse type modifiers
+ */
+ case 'h':
+ spec.mod_half = TRUE;
+ break;
+ case 'l':
+ if (!seen_l)
+ {
+ spec.mod_long = TRUE;
+ seen_l = TRUE;
+ break;
+ }
+ /* else, fall through */
+ case 'L':
+ case 'q':
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ break;
+ case 'z':
+ case 'Z':
+ if (sizeof(size_t))
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+ case 't':
+ if (sizeof(ptrdiff_t) > 4)
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+ case 'j':
+ if (GLIB_SIZEOF_INTMAX > 4)
+ {
+ spec.mod_long = TRUE;
+ spec.mod_extra_long = TRUE;
+ }
+ break;
+
+ /* parse output conversions
+ */
+ case '%':
+ conv_len += 1;
+ break;
+ case 'O':
+ case 'D':
+ case 'I':
+ case 'U':
+ /* some C libraries feature long variants for these as well? */
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 'o':
+ conv_len += 2;
+ /* fall through */
+ case 'd':
+ case 'i':
+ conv_len += 1; /* sign */
+ /* fall through */
+ case 'u':
+ conv_len += 4;
+ /* fall through */
+ case 'x':
+ case 'X':
+ spec.possible_sign = TRUE;
+ conv_len += 10;
+ if (spec.mod_long && honour_longs)
+ conv_len *= 2;
+ if (spec.mod_extra_long)
+ conv_len *= 2;
+ if (spec.mod_extra_long)
+ {
+ (void) va_arg (args, gint64);
+ }
+ else if (spec.mod_long)
+ (void) va_arg (args, long);
+ else
+ (void) va_arg (args, int);
+ break;
+ case 'A':
+ case 'a':
+ /* 0x */
+ conv_len += 2;
+ /* fall through */
+ case 'g':
+ case 'G':
+ case 'e':
+ case 'E':
+ case 'f':
+ spec.possible_sign = TRUE;
+ /* n . dddddddddddddddddddddddd E +- eeee */
+ conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
+ if (may_warn && spec.mod_extra_long)
+ g_warning (G_STRLOC ": unable to handle long double, collecting double only");
+#ifdef HAVE_LONG_DOUBLE
+#error need to implement special handling for long double
+#endif
+ u_double.v_double = va_arg (args, double);
+ /* %f can expand up to all significant digits before '.' (308) */
+ if (c == 'f' &&
+ u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047)
+ {
+ gint exp = u_double.mpn.biased_exponent;
+
+ exp -= G_IEEE754_DOUBLE_BIAS;
+ exp = (gint)(exp * G_LOG_2_BASE_10 + 1);
+ conv_len += ABS (exp); /* exp can be <0 */
+ }
+ /* some printf() implementations require extra padding for rounding */
+ conv_len += 2;
+ /* we can't really handle locale specific grouping here */
+ if (spec.locale_grouping)
+ conv_len *= 2;
+ break;
+ case 'C':
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 'c':
+ conv_len += spec.mod_long ? MB_LEN_MAX : 1;
+ (void) va_arg (args, int);
+ break;
+ case 'S':
+ spec.mod_long = TRUE;
+ /* fall through */
+ case 's':
+ v_string = va_arg (args, char*);
+ if (!v_string)
+ conv_len += 8; /* hold "(null)" */
+ else if (spec.seen_precision)
+ conv_len += spec.precision;
+ else
+ conv_len += strlen (v_string);
+ conv_done = TRUE;
+ if (spec.mod_long)
+ {
+ if (may_warn)
+ g_warning (G_STRLOC": unable to handle wide char strings");
+ len += 1024; /* try adding some safety padding */
+ }
+ break;
+ case 'P': /* do we actually need this? */
+ /* fall through */
+ case 'p':
+ spec.alternate_format = TRUE;
+ conv_len += 10;
+ if (honour_longs)
+ conv_len *= 2;
+ /* fall through */
+ case 'n':
+ conv_done = TRUE;
+ (void) va_arg (args, void*);
+ break;
+ case 'm':
+ /* there's not much we can do to be clever */
+ v_string = g_strerror (errno);
+ v_uint = v_string ? strlen (v_string) : 0;
+ conv_len += MAX (256, v_uint);
+ break;
+
+ /* handle invalid cases
+ */
+ case '\000':
+ /* no conversion specification, bad bad */
+ conv_len += format - spec_start;
+ break;
+ default:
+ if (may_warn)
+ g_warning (G_STRLOC": unable to handle `%c' while parsing format",
+ c);
+ break;
+ }
+ conv_done |= conv_len > 0;
+ }
+ while (!conv_done);
+ /* handle width specifications */
+ conv_len = MAX (conv_len, MAX (spec.precision, spec.min_width));
+ /* handle flags */
+ conv_len += spec.alternate_format ? 2 : 0;
+ conv_len += (spec.add_space || spec.add_sign || spec.possible_sign);
+ /* finally done */
+ len += conv_len;
+ } /* else (c == '%') */
+ } /* while (*format) */
+
+ return len;
+}
+
+static char*
+#ifdef __GNUC__
+__attribute__ ( (format (printf, 1, 0) ) )
+#endif
+arts_strdup_vprintf (const char *format, va_list args1)
+{
+ gchar *buffer;
+#ifdef HAVE_VASPRINTF
+ if (vasprintf (&buffer, format, args1) < 0)
+ buffer = NULL;
+#else
+ va_list args2;
+
+ G_VA_COPY (args2, args1);
+
+ buffer = (gchar *)malloc (printf_string_upper_bound (format, TRUE, args1));
+
+ vsprintf (buffer, format, args2);
+ va_end (args2);
+#endif
+ return buffer;
+}
+
+char*
+#ifdef __GNUC__
+__attribute__ ( (format (printf, 1, 0) ) )
+#endif
+arts_strdup_printf (const char *format, ...)
+{
+ gchar *buffer;
+ va_list args;
+
+ va_start (args, format);
+ buffer = arts_strdup_vprintf (format, args);
+ va_end (args);
+
+ return buffer;
+}
diff --git a/mcop/debug.h b/mcop/debug.h
new file mode 100644
index 0000000..94cd01f
--- /dev/null
+++ b/mcop/debug.h
@@ -0,0 +1,138 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+
+ Some inspiration taken from glib.
+ Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ Modified by the GLib Team and others 1997-1999.
+
+ */
+
+#ifndef _ARTSDEBUG_H_
+#define _ARTSDEBUG_H_
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Debug.
+ *
+ * Collection class, no instance, no members. Thus binary compatible (will
+ * be kept).
+ */
+
+#define arts_fatal ::Arts::Debug::fatal
+#define arts_warning ::Arts::Debug::warning
+#define arts_info ::Arts::Debug::info
+#define arts_debug ::Arts::Debug::debug
+
+/* source compatibility with older sources */
+#define artsdebug ::Arts::Debug::debug
+#define setartsdebug(x) arts_warning("setartsdebug is obsolete")
+
+#ifdef __GNUC__
+
+#define arts_return_if_fail(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d (%s): assertion failed: (%s)", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
+ return; \
+ } \
+ } while(0)
+
+#define arts_return_val_if_fail(expr,val) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d (%s): assertion failed: (%s)", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
+ return (val); \
+ } \
+ } while(0)
+
+#define arts_assert(expr) \
+ do { \
+ if (!(expr)) \
+ arts_fatal ("file %s: line %d (%s): assertion failed: (%s)", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
+ } while(0)
+
+#else
+
+#define arts_return_if_fail(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d: assertion failed: (%s)", \
+ __FILE__, __LINE__, #expr); \
+ return; \
+ } \
+ } while(0)
+
+#define arts_return_val_if_fail(expr,val) \
+ do { \
+ if (!(expr)) \
+ { \
+ arts_warning ("file %s: line %d: assertion failed: (%s)", \
+ __FILE__, __LINE__, #expr); \
+ return (val); \
+ } \
+ } while(0)
+
+#define arts_assert(expr) \
+ do { \
+ if (!(expr)) \
+ arts_fatal ("file %s: line %d: assertion failed: (%s)", \
+ __FILE__, __LINE__, #expr); \
+ } while(0)
+
+#endif
+
+ARTS_EXPORT char* arts_strdup_printf (const char *format, ...);
+
+namespace Arts {
+ class ARTS_EXPORT Debug {
+ public:
+ enum Level { lFatal = 3, lWarning = 2, lInfo = 1, lDebug = 0 };
+
+ /**
+ * Initializes at which is the minimum level to react to. If you
+ * call this, call this before creating the Arts::Dispatcher object.
+ */
+ static void init(const char *prefix, Level level);
+
+ static void fatal(const char *fmt,...); // print on stderr & abort
+ static void warning(const char *fmt,...); // print on stderr
+ static void info(const char *fmt,...); // print on stdout
+ static void debug(const char *fmt,...); // print on stdout
+
+ /**
+ * This method sets the name of an external application to
+ * display messages graphically.
+ */
+ static void messageApp(const char *appName);
+
+ static void initMutex(); // called from the dispatcher constructor
+ static void freeMutex(); // called from the dispatcher destructor
+ };
+}
+
+#endif
diff --git a/mcop/delayedreturn.cc b/mcop/delayedreturn.cc
new file mode 100644
index 0000000..1eab0ed
--- /dev/null
+++ b/mcop/delayedreturn.cc
@@ -0,0 +1,71 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <assert.h>
+#include "anyref.h"
+#include "connection.h"
+#include "delayedreturn.h"
+
+using namespace Arts;
+using namespace std;
+
+DelayedReturn::DelayedReturn() : buffer(0), connection(0)
+{
+ //
+}
+
+void DelayedReturn::initialize(Connection *connection, Buffer *buffer)
+{
+ this->connection = connection;
+ this->buffer = buffer;
+ connection->_copy();
+}
+
+DelayedReturn::~DelayedReturn()
+{
+ connection->_release();
+ connection = 0;
+ buffer = 0;
+}
+
+void DelayedReturn::doReturn(const AnyConstRef& value)
+{
+ assert(connection);
+ assert(buffer);
+
+ value.write(buffer);
+ buffer->patchLength();
+ connection->qSendBuffer(buffer);
+
+ delete this;
+}
+
+void DelayedReturn::doReturn()
+{
+ assert(connection);
+ assert(buffer);
+
+ buffer->patchLength();
+ connection->qSendBuffer(buffer);
+
+ delete this;
+}
diff --git a/mcop/delayedreturn.h b/mcop/delayedreturn.h
new file mode 100644
index 0000000..fe2a140
--- /dev/null
+++ b/mcop/delayedreturn.h
@@ -0,0 +1,102 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_MCOP_DELAYEDRETURN_H
+#define ARTS_MCOP_DELAYEDRETURN_H
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): DelayedReturn
+ *
+ * This class will be kept binary compatible. It has a private d-pointer for
+ * further extensions.
+ */
+
+namespace Arts {
+
+class AnyConstRef;
+class Buffer;
+class Connection;
+class DelayedReturnPrivate;
+
+/**
+ * The "DelayedReturn" class implements delayed returning from functions.
+ *
+ * For instance, suppose you would like to return from a wait() operation
+ * only after a certain time has passed, without blocking other clients
+ * from using your interface during this time.
+ *
+ * Your implementation (in the skel file) of wait should look like this
+ *
+ * <pre>
+ * static DelayedReturn *delayedReturn = 0;
+ *
+ * bool TimeServer::waitUntil(long time)
+ * {
+ * if(time(0) < time)
+ * {
+ * // ... initialize timer here ...
+ * delayedReturn = Dispatcher::the()->delayReturn();
+ * }
+ * return false;
+ * }
+ *
+ * void timerEvent()
+ * {
+ * delayedReturn->doReturn(true);
+ * }
+ * </pre>
+ *
+ * NOTE: this class breaks for local use (i.e. you can only use it if the
+ * call was a remote call), so it is strongly recommended not to use it
+ * unless there is no alternative (and you should really know what you are
+ * doing, too).
+ */
+class ARTS_EXPORT DelayedReturn {
+friend class Dispatcher;
+private:
+ DelayedReturnPrivate *d;
+
+protected:
+ Buffer *buffer;
+ Connection *connection;
+
+ DelayedReturn();
+ void initialize(Connection *connection, Buffer *buffer);
+ ~DelayedReturn();
+
+public:
+ /**
+ * call this only once to make the request really return
+ */
+ void doReturn(const AnyConstRef& value);
+
+ /**
+ * return without value (for void functions)
+ */
+ void doReturn();
+};
+
+}
+
+#endif /* ARTS_MCOP_DELAYEDRETURN_H */
diff --git a/mcop/dispatcher.cc b/mcop/dispatcher.cc
new file mode 100644
index 0000000..c055f64
--- /dev/null
+++ b/mcop/dispatcher.cc
@@ -0,0 +1,1090 @@
+ /*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "dispatcher.h"
+#include "delayedreturn.h"
+#include "startupmanager.h"
+#include "unixconnection.h"
+#include "tcpconnection.h"
+#include "referenceclean.h"
+#include "core.h"
+#include "md5auth.h"
+#include "mcoputils.h"
+#include "loopback.h"
+#include "debug.h"
+#include "ifacerepo_impl.h"
+#include "thread.h"
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <signal.h>
+#include <cstring>
+#include <cstdlib>
+#include <errno.h>
+#include <iostream>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#elif HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+/* Dispatcher private data class (to ensure binary compatibility) */
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class DispatcherWakeUpHandler;
+
+class DispatcherPrivate {
+public:
+ GlobalComm globalComm;
+ InterfaceRepo interfaceRepo;
+ AuthAccept *accept;
+ LoopbackConnection *loopbackConnection;
+ DelayedReturn *delayedReturn;
+ bool allowNoAuthentication;
+ Mutex mutex;
+
+ /*
+ * Thread condition that gets signalled whenever something relevant for
+ * waitForResult happens. Note that broken connections are also relevant
+ * for waitForResult.
+ */
+ ThreadCondition requestResultCondition;
+
+ /*
+ * Thread condition that gets signalled whenever something relevant for
+ * the server connection process happens. This is either:
+ * - authentication fails
+ * - authentication succeeds
+ * - a connection breaks
+ */
+ ThreadCondition serverConnectCondition;
+
+ DispatcherWakeUpHandler *wakeUpHandler;
+};
+
+/**
+ * Class that performs dispatcher wakeup.
+ *
+ * The sending thread (requesting wakeup) writes a byte to a pipe. The
+ * main thread watches the pipe, and as soon as the byte arrives, gets
+ * woken by the IOManager. This should work, no matter what type of IOManager
+ * is used (i.e. StdIOManager/GIOManager/QIOManager).
+ */
+class DispatcherWakeUpHandler : public IONotify {
+private:
+ enum { wReceive = 0, wSend = 1 };
+ int wakeUpPipe[2];
+
+public:
+ DispatcherWakeUpHandler()
+ {
+ if(pipe(wakeUpPipe) != 0)
+ arts_fatal("can't initialize wakeUp pipe (%s)",strerror(errno));
+
+ Dispatcher::the()->ioManager()->watchFD(wakeUpPipe[wReceive],
+ IOType::read | IOType::reentrant, this);
+ }
+ virtual ~DispatcherWakeUpHandler()
+ {
+ Dispatcher::the()->ioManager()->remove(this, IOType::all);
+
+ close(wakeUpPipe[wSend]);
+ close(wakeUpPipe[wReceive]);
+ }
+ void notifyIO(int fd, int type)
+ {
+ arts_return_if_fail(fd == wakeUpPipe[wReceive]);
+ arts_return_if_fail(type == IOType::read);
+
+ mcopbyte one;
+ int result;
+ do
+ result = read(wakeUpPipe[wReceive],&one,1);
+ while(result < 0 && errno == EINTR);
+ }
+ void wakeUp()
+ {
+ mcopbyte one = 1;
+
+ int result;
+ do
+ result = write(wakeUpPipe[wSend],&one,1);
+ while(result < 0 && errno == EINTR);
+ }
+};
+
+}
+
+Dispatcher *Dispatcher::_instance = 0;
+
+Dispatcher::Dispatcher(IOManager *ioManager, StartServer startServer)
+{
+ assert(!_instance);
+ _instance = this;
+
+ /* private data pointer */
+ d = new DispatcherPrivate();
+
+ lock();
+
+ /* makes arts_debug/arts_message/arts_return_if_fail/... threadsafe */
+ Debug::initMutex();
+
+ generateServerID();
+
+ if(ioManager)
+ {
+ _ioManager = ioManager;
+ deleteIOManagerOnExit = false;
+ }
+ else
+ {
+ _ioManager = new StdIOManager;
+ deleteIOManagerOnExit = true;
+ }
+
+ d->wakeUpHandler = new DispatcherWakeUpHandler;
+
+ objectManager = new ObjectManager;
+
+ notificationManager = new NotificationManager;
+
+ if(startServer & startUnixServer)
+ {
+ unixServer = new UnixServer(this,serverID);
+ if(!unixServer->running())
+ {
+ delete unixServer;
+ arts_warning("MCOP: couldn't start UnixServer");
+ unixServer = 0;
+ }
+ }
+ else unixServer = 0;
+
+ if(startServer & startTCPServer)
+ {
+ tcpServer = new TCPServer(this);
+ if(!tcpServer->running())
+ {
+ delete tcpServer;
+ arts_warning("MCOP: couldn't start TCPServer");
+ tcpServer = 0;
+ }
+ }
+ else tcpServer = 0;
+
+ d->allowNoAuthentication = startServer & noAuthentication;
+ d->accept = 0;
+ d->loopbackConnection = new LoopbackConnection(serverID);
+ d->interfaceRepo = InterfaceRepo::_from_base(new InterfaceRepo_impl());
+ d->delayedReturn = 0;
+
+ _flowSystem = 0;
+ referenceClean = new ReferenceClean(objectPool);
+
+ /*
+ * setup signal handler for SIGPIPE
+ */
+ orig_sigpipe = signal(SIGPIPE,SIG_IGN);
+ if((orig_sigpipe != SIG_DFL) && (orig_sigpipe != SIG_IGN))
+ {
+ cerr << "mcop warning: user defined signal handler found for"
+ " SIG_PIPE, overriding" << endl;
+ }
+
+ StartupManager::startup();
+
+ /*
+ * this is required for publishing global references - might be a good
+ * reason for startup priorities as since this is required for cookie&co,
+ * no communication is possible without that
+ */
+
+
+ char *env = getenv("ARTS_SERVER");
+ bool envOk = false;
+ if(env)
+ {
+ string url = "tcp:"; url += env;
+ Connection *conn = connectUrl(url);
+ arts_debug("connection to %s for globalComm", url.c_str());
+ if(conn)
+ {
+ arts_debug("hint %s", conn->findHint("GlobalComm").c_str());
+ d->globalComm = Reference(conn->findHint("GlobalComm"));
+ envOk = true;
+ arts_debug("using globalcomm from env variable");
+ }
+ }
+
+ if(!envOk)
+ {
+ string globalCommName
+ = MCOPUtils::readConfigEntry("GlobalComm","Arts::TmpGlobalComm");
+ d->globalComm = GlobalComm(SubClass(globalCommName));
+ }
+
+ // --- initialize MD5auth ---
+ /*
+ * Path for random seed: better to store it in home, because some
+ * installations wipe /tmp on reboot.
+ */
+ string seedpath = MCOPUtils::createFilePath("random-seed");
+ string mcopdir = MCOPUtils::mcopDirectory();
+ if(!mcopdir.empty()) seedpath = mcopdir + "/random-seed";
+ arts_md5_auth_init_seed(seedpath.c_str());
+
+ /*
+ * first generate a new random cookie and try to set secret-cookie to it
+ * as put will not overwrite, this has no effect if there is already a
+ * secret cookie
+ */
+ char *cookie = arts_md5_auth_mkcookie();
+ globalComm().put("secret-cookie",cookie);
+
+ /*
+ * Then get the secret cookie from globalComm. As we've just set one,
+ * and as it is never removed, this always works.
+ */
+ string secretCookie = globalComm().get("secret-cookie");
+ if(!arts_md5_auth_set_cookie(secretCookie.c_str()))
+ {
+ /*
+ * Handle the case where the cookie obtained from GlobalComm is not
+ * a valid cookie (i.e. too short) - this should practically never
+ * happen. In this case, we will remove the cookie and overwrite it
+ * with our previously generated cookie.
+ */
+ arts_warning("bad md5 secret-cookie obtained from %s - replacing it",
+ globalComm()._interfaceName().c_str());
+
+ globalComm().erase("secret-cookie");
+ globalComm().put("secret-cookie",cookie);
+
+ if(!arts_md5_auth_set_cookie(cookie))
+ arts_fatal("error initializing md5 secret cookie "
+ "(generated cookie invalid)");
+ }
+ memset(cookie,0,strlen(cookie)); // try to keep memory clean
+ free(cookie);
+
+ string::iterator i; // try to keep memory clean from secret cookie
+ for(i=secretCookie.begin();i != secretCookie.end();i++) *i = 'y';
+
+ unlock();
+}
+
+Dispatcher::~Dispatcher()
+{
+ lock();
+
+ /* no interaction possible now anymore - remove our global references */
+ if(objectManager)
+ objectManager->removeGlobalReferences();
+
+ /* remove everything that might have been tagged for remote copying */
+ referenceClean->forceClean();
+ delete referenceClean;
+
+ d->globalComm = GlobalComm::null();
+
+ /* shutdown all extensions we loaded */
+ if(objectManager)
+ objectManager->shutdownExtensions();
+
+ StartupManager::shutdown();
+
+ /* drop all open connections */
+ list<Connection *>::iterator ci;
+ for(ci=connections.begin(); ci != connections.end();ci++)
+ {
+ Connection *conn = *ci;
+ conn->drop();
+ }
+ d->requestResultCondition.wakeAll();
+ d->serverConnectCondition.wakeAll();
+
+ /*
+ * remove signal handler for SIGPIPE
+ */
+ signal(SIGPIPE,orig_sigpipe);
+
+
+ d->interfaceRepo = InterfaceRepo::null();
+
+ if(d->accept)
+ {
+ delete d->accept;
+ d->accept = 0;
+ }
+
+ if(d->loopbackConnection)
+ {
+ d->loopbackConnection->_release();
+ d->loopbackConnection = 0;
+ }
+ if(unixServer)
+ {
+ delete unixServer;
+ unixServer = 0;
+ }
+
+ if(tcpServer)
+ {
+ delete tcpServer;
+ tcpServer = 0;
+ }
+
+ if(notificationManager)
+ {
+ delete notificationManager;
+ notificationManager = 0;
+ }
+
+ if(objectManager && Object_base::_objectCount() == 0)
+ {
+ objectManager->removeExtensions();
+ delete objectManager;
+ objectManager = 0;
+ }
+
+ if(d->wakeUpHandler)
+ {
+ delete d->wakeUpHandler;
+ d->wakeUpHandler = 0;
+ }
+
+ if(deleteIOManagerOnExit)
+ {
+ delete _ioManager;
+ _ioManager = 0;
+ }
+
+ if(Object_base::_objectCount())
+ {
+ cerr << "warning: leaving MCOP Dispatcher and still "
+ << Object_base::_objectCount() << " object references alive." << endl;
+ list<Object_skel *> which = objectPool.enumerate();
+ list<Object_skel *>::iterator i;
+ for(i = which.begin(); i != which.end();i++)
+ cerr << " - " << (*i)->_interfaceName() << endl;
+ }
+
+ if(Type::_typeCount())
+ {
+ cerr << "warning: leaving MCOP Dispatcher and still "
+ << Type::_typeCount() << " types alive." << endl;
+ }
+
+ if(GenericDataPacket::_dataPacketCount())
+ {
+ cerr << "warning: leaving MCOP Dispatcher and still "
+ << GenericDataPacket::_dataPacketCount()
+ << " data packets alive." << endl;
+ }
+
+ Debug::freeMutex();
+
+ unlock();
+
+ /* private data pointer */
+ assert(d);
+ delete d;
+ d = 0;
+
+ assert(_instance);
+ _instance = 0;
+}
+
+InterfaceRepo Dispatcher::interfaceRepo()
+{
+ return d->interfaceRepo;
+}
+
+FlowSystem_impl *Dispatcher::flowSystem()
+{
+ assert(_flowSystem);
+ return _flowSystem;
+}
+
+GlobalComm Dispatcher::globalComm()
+{
+ assert(!d->globalComm.isNull());
+ return d->globalComm;
+}
+
+void Dispatcher::setFlowSystem(FlowSystem_impl *fs)
+{
+ assert(!_flowSystem);
+ _flowSystem = fs;
+}
+
+Dispatcher *Dispatcher::the()
+{
+ return _instance;
+}
+
+Buffer *Dispatcher::waitForResult(long requestID, Connection *connection)
+{
+ bool isMainThread = SystemThreads::the()->isMainThread();
+ Buffer *b = requestResultPool[requestID];
+
+ connection->_copy(); // Keep extra ref
+
+ while(!b && !connection->broken()) {
+ if(isMainThread)
+ _ioManager->processOneEvent(true);
+ else
+ d->requestResultCondition.wait(d->mutex);
+
+ b = requestResultPool[requestID];
+ }
+
+ requestResultPool.releaseSlot(requestID);
+
+ if(connection->broken()) // connection went away before we got some result
+ b = 0;
+
+ connection->_release(); // Give up extra ref
+
+ return b;
+}
+
+Buffer *Dispatcher::createRequest(long& requestID, long objectID, long methodID)
+{
+ Buffer *buffer = new Buffer;
+
+ // write mcop header record
+ buffer->writeLong(MCOP_MAGIC);
+ buffer->writeLong(0); // message length - to be patched later
+ buffer->writeLong(mcopInvocation);
+
+ // generate a request ID
+ requestID = requestResultPool.allocSlot();
+
+ // write invocation record
+ buffer->writeLong(objectID);
+ buffer->writeLong(methodID);
+ buffer->writeLong(requestID);
+
+ return buffer;
+}
+
+Buffer *Dispatcher::createOnewayRequest(long objectID, long methodID)
+{
+ Buffer *buffer = new Buffer;
+
+ // write mcop header record
+ buffer->writeLong(MCOP_MAGIC);
+ buffer->writeLong(0); // message length - to be patched later
+ buffer->writeLong(mcopOnewayInvocation);
+
+ // write oneway invocation record
+ buffer->writeLong(objectID);
+ buffer->writeLong(methodID);
+
+ return buffer;
+}
+
+void Dispatcher::handle(Connection *conn, Buffer *buffer, long messageType)
+{
+ _activeConnection = conn;
+
+#ifdef DEBUG_IO
+ printf("got a message %ld, %ld bytes in body\n",
+ messageType,buffer->remaining());
+ if(conn->connState() == Connection::unknown)
+ cout << "connectionState = unknown" << endl;
+ if(conn->connState() == Connection::expectClientHello)
+ cout << "connectionState = expectClientHello" << endl;
+ if(conn->connState() == Connection::expectServerHello)
+ cout << "connectionState = expectServerHello" << endl;
+ if(conn->connState() == Connection::expectAuthAccept)
+ cout << "connectionState = expectAuthAccept" << endl;
+ if(conn->connState() == Connection::established)
+ cout << "connectionState = established" << endl;
+#endif
+ switch(conn->connState())
+ {
+ case Connection::established:
+ /*
+ * we're connected to a trusted server, so we can accept
+ * invocations
+ */
+ if(messageType == mcopInvocation) {
+#ifdef DEBUG_MESSAGES
+ printf("[got Invocation]\n");
+#endif
+ long objectID = buffer->readLong();
+ long methodID = buffer->readLong();
+ long requestID = buffer->readLong();
+
+ Buffer *result = new Buffer;
+ // write mcop header record
+ result->writeLong(MCOP_MAGIC);
+ result->writeLong(0); // message length - to be patched later
+ result->writeLong(mcopReturn);
+
+ // write result record (returnCode is written by dispatch)
+ result->writeLong(requestID);
+
+ // perform the request
+ Object_skel *object = objectPool[objectID];
+ object->_copy();
+ object->_dispatch(buffer,result,methodID);
+ object->_release();
+
+ assert(!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ if(d->delayedReturn)
+ {
+ delete result;
+
+ result = new Buffer;
+ result->writeLong(MCOP_MAGIC);
+ result->writeLong(0); // to be patched later
+ result->writeLong(mcopReturn);
+ result->writeLong(requestID);
+
+ d->delayedReturn->initialize(conn,result);
+ d->delayedReturn = 0;
+ }
+ else /* return normally */
+ {
+ result->patchLength();
+ conn->qSendBuffer(result);
+ }
+ return; /* everything ok - leave here */
+ }
+
+ if(messageType == mcopReturn)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got Return]\n");
+#endif
+ long requestID = buffer->readLong();
+ requestResultPool[requestID] = buffer;
+ d->requestResultCondition.wakeAll();
+
+ return; /* everything ok - leave here */
+ }
+
+ if(messageType == mcopOnewayInvocation) {
+#ifdef DEBUG_MESSAGES
+ printf("[got OnewayInvocation]\n");
+#endif
+ long objectID = buffer->readLong();
+ long methodID = buffer->readLong();
+
+ // perform the request
+ Object_skel *object = objectPool[objectID];
+ object->_copy();
+ object->_dispatch(buffer,methodID);
+ object->_release();
+
+ assert(!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ return; /* everything ok - leave here */
+ }
+ break;
+
+ case Connection::expectServerHello:
+ if(messageType == mcopServerHello)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got ServerHello]\n");
+#endif
+ /*
+ * if we get a server hello, answer with a client hello
+ */
+ ServerHello h;
+ h.readType(*buffer);
+ bool valid = (!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ if(!valid) break; // invalid hello received -> forget it
+
+ conn->setServerID(h.serverID);
+
+ /*
+ * check if md5auth or noauth is offered by the server
+ */
+ bool md5authSupported = false;
+ bool noauthSupported = false;
+ vector<string>::iterator ai;
+ for(ai = h.authProtocols.begin(); ai != h.authProtocols.end(); ai++)
+ {
+ if(*ai == "md5auth") md5authSupported = true;
+ if(*ai == "noauth") noauthSupported = true;
+ }
+
+ if(noauthSupported) // noauth is usually easier to pass ;)
+ {
+ Buffer *helloBuffer = new Buffer;
+
+ Header header(MCOP_MAGIC,0,mcopClientHello);
+ header.writeType(*helloBuffer);
+ ClientHello clientHello(serverID,"noauth","");
+ clientHello.writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+
+ conn->qSendBuffer(helloBuffer);
+ conn->setConnState(Connection::expectAuthAccept);
+ return; /* everything ok - leave here */
+ }
+ else if(md5authSupported)
+ {
+ Buffer *helloBuffer = new Buffer;
+
+ Header header(MCOP_MAGIC,0,mcopClientHello);
+ header.writeType(*helloBuffer);
+ ClientHello clientHello(serverID,"md5auth","");
+
+ const char *random_cookie = h.authSeed.c_str();
+ if(strlen(random_cookie) == 32)
+ {
+ char *response = arts_md5_auth_mangle(random_cookie);
+ clientHello.authData = response;
+#ifdef DEBUG_AUTH
+ printf(" got random_cookie = %s\n",random_cookie);
+ printf("reply with authData = %s\n",response);
+#endif
+ free(response);
+ }
+ clientHello.writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+
+ conn->qSendBuffer(helloBuffer);
+ conn->setConnState(Connection::expectAuthAccept);
+ return; /* everything ok - leave here */
+ }
+ else
+ {
+ cerr << "MCOP error: don't know authentication protocol" << endl;
+ cerr << " server offered: ";
+ for(ai = h.authProtocols.begin(); ai != h.authProtocols.end(); ai++)
+ cerr << *ai << " ";
+ cerr << endl;
+ }
+ }
+ break;
+
+ case Connection::expectClientHello:
+ if(messageType == mcopClientHello)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got ClientHello]\n");
+#endif
+ ClientHello c;
+ c.readType(*buffer);
+ bool valid = (!buffer->readError() && !buffer->remaining());
+ delete buffer;
+
+ if(valid && (
+ (c.authProtocol == "md5auth" && c.authData == conn->cookie())
+ || (c.authProtocol == "noauth" && d->allowNoAuthentication) ))
+ {
+ conn->setServerID(c.serverID);
+
+ /* build hints only for the first connection */
+ if(!d->accept)
+ {
+ d->accept = new AuthAccept();
+
+ d->accept->hints.push_back(
+ "GlobalComm="+d->globalComm.toString());
+ d->accept->hints.push_back(
+ "InterfaceRepo="+d->interfaceRepo.toString());
+ }
+
+ Buffer *helloBuffer = new Buffer;
+ Header header(MCOP_MAGIC,0,mcopAuthAccept);
+ header.writeType(*helloBuffer);
+ d->accept->writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+ conn->qSendBuffer(helloBuffer);
+ conn->setConnState(Connection::established);
+
+ return; /* everything ok - leave here */
+ }
+ }
+ break;
+
+ case Connection::expectAuthAccept:
+ if(messageType == mcopAuthAccept)
+ {
+#ifdef DEBUG_MESSAGES
+ printf("[got AuthAccept]\n");
+#endif
+ AuthAccept a;
+ a.readType(*buffer);
+ delete buffer;
+#ifdef DEBUG_MESSAGES
+
+ vector<string>::iterator hi;
+ for(hi = a.hints.begin(); hi != a.hints.end(); hi++)
+ cout << "[got ConnectionHint] " << *hi << endl;
+
+#endif
+
+ conn->setConnState(Connection::established);
+ conn->setHints(a.hints);
+ d->serverConnectCondition.wakeAll();
+ return; /* everything ok - leave here */
+ }
+ break;
+
+ case Connection::unknown:
+ assert(false);
+ break;
+ }
+
+ /*
+ * We shouldn't reach this point if everything went all right
+ */
+ cerr << "Fatal communication error with a client" << endl;
+ if(conn->connState() != Connection::established)
+ {
+ cerr << " Authentication of this client was not successful" << endl;
+ cerr << " Connection dropped" << endl;
+ conn->drop();
+ }
+}
+
+long Dispatcher::addObject(Object_skel *object)
+{
+ long objectID = objectPool.allocSlot();
+
+ objectPool[objectID] = object;
+ return objectID;
+}
+
+void Dispatcher::removeObject(long objectID)
+{
+ assert(objectPool[objectID]);
+ objectPool.releaseSlot(objectID);
+}
+
+void Dispatcher::generateServerID()
+{
+ char *buffer;
+ buffer = arts_strdup_printf("%s-%04x-%08lx",
+ MCOPUtils::getFullHostname().c_str(),
+ getpid(),time(0));
+ serverID = buffer;
+ free(buffer);
+}
+
+string Dispatcher::objectToString(long objectID)
+{
+ Buffer b;
+ ObjectReference oref;
+
+ oref.serverID = serverID;
+ oref.objectID = objectID;
+
+ // prefer a unix domainsocket connection over a plain tcp connection
+ if(unixServer) oref.urls.push_back(unixServer->url());
+ if(tcpServer) oref.urls.push_back(tcpServer->url());
+
+ oref.writeType(b);
+
+ return b.toString("MCOP-Object");
+}
+
+bool Dispatcher::stringToObjectReference(ObjectReference& r, const string& s)
+{
+ if(strncmp(s.c_str(),"global:",7) == 0)
+ {
+ // if the object reference starts with "global:", it refers to
+ // a global object which can be found with the objectManager
+
+ string lookup = objectManager->getGlobalReference(&s.c_str()[7]);
+ return stringToObjectReference(r,lookup);
+ }
+
+
+ Buffer b;
+ if(!b.fromString(s,"MCOP-Object")) return false;
+
+ r.readType(b);
+ if(b.readError() || b.remaining()) return false;
+
+ return true;
+}
+
+void *Dispatcher::connectObjectLocal(ObjectReference& reference,
+ const string& interface)
+{
+ if(reference.serverID == serverID)
+ {
+ void *result = objectPool[reference.objectID]->_cast(interface);
+
+ if(result)
+ {
+ objectPool[reference.objectID]->_copy();
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+Connection *Dispatcher::connectObjectRemote(ObjectReference& reference)
+{
+ if(reference.serverID == "null") // null reference?
+ return 0;
+
+ if(reference.serverID == serverID)
+ return loopbackConnection();
+
+ list<Connection *>::iterator i;
+
+ for(i=connections.begin(); i != connections.end();i++)
+ {
+ Connection *conn = *i;
+
+ if(conn->isConnected(reference.serverID))
+ {
+ // fixme: we should check for the existence of the object
+ // and increment a reference count or something like that
+ return conn;
+ }
+ }
+
+ /* try to connect the server */
+ vector<string>::iterator ui;
+ for(ui = reference.urls.begin(); ui != reference.urls.end(); ui++)
+ {
+ Connection *conn = connectUrl(*ui);
+ if(conn)
+ {
+ if(conn->isConnected(reference.serverID))
+ {
+ return conn;
+ }
+ else
+ {
+ /* we connected somewhere, but not the right server ;) */
+ connections.remove(conn);
+ conn->_release();
+ }
+ }
+ }
+ return 0;
+}
+
+Connection *Dispatcher::connectUrl(const string& url)
+{
+ Connection *conn = 0;
+ bool isMainThread = SystemThreads::the()->isMainThread();
+
+ if(strncmp(url.c_str(),"tcp:",4) == 0)
+ {
+ conn = new TCPConnection(url);
+ }
+ else if(strncmp(url.c_str(),"unix:",5) == 0)
+ {
+ conn = new UnixConnection(url);
+ }
+
+ if(conn)
+ {
+ conn->_copy(); // Keep extra ref for when the connection breaks
+ conn->setConnState(Connection::expectServerHello);
+
+ while((conn->connState() != Connection::established)
+ && !conn->broken())
+ {
+ if(isMainThread)
+ _ioManager->processOneEvent(true);
+ else
+ d->serverConnectCondition.wait(d->mutex);
+ }
+
+ if(conn->connState() == Connection::established)
+ {
+ connections.push_back(conn);
+ conn->_release(); // Give up extra ref
+ return conn;
+ }
+
+ // well - bad luck (building a connection failed)
+
+ // Give up extra ref
+ conn->_release();
+ }
+ return 0;
+}
+
+void Dispatcher::run()
+{
+ assert(SystemThreads::the()->isMainThread());
+
+ _ioManager->run();
+}
+
+void Dispatcher::terminate()
+{
+ _ioManager->terminate();
+}
+
+void Dispatcher::initiateConnection(Connection *connection)
+{
+ vector<string> authProtocols;
+ authProtocols.push_back("md5auth");
+
+ if(d->allowNoAuthentication)
+ authProtocols.push_back("noauth");
+
+ char *authSeed = arts_md5_auth_mkcookie();
+ char *authResult = arts_md5_auth_mangle(authSeed);
+
+ Buffer *helloBuffer = new Buffer;
+
+ Header header(MCOP_MAGIC,0,mcopServerHello);
+ header.writeType(*helloBuffer);
+ ServerHello serverHello("aRts/MCOP-1.0.0",serverID,authProtocols,authSeed);
+ serverHello.writeType(*helloBuffer);
+
+ helloBuffer->patchLength();
+
+ connection->qSendBuffer(helloBuffer);
+ connection->setConnState(Connection::expectClientHello);
+
+ connection->setCookie(authResult);
+ free(authSeed);
+ free(authResult);
+
+ connections.push_back(connection);
+}
+
+void Dispatcher::handleCorrupt(Connection *connection)
+{
+ if(connection->connState() != Connection::established)
+ {
+ cerr << "received corrupt message on unauthenticated connection" <<endl;
+ cerr << "closing connection." << endl;
+ connection->drop();
+ d->serverConnectCondition.wakeAll();
+ }
+ else
+ {
+ cerr << "WARNING: got corrupt MCOP message !??" << endl;
+ }
+}
+
+void Dispatcher::handleConnectionClose(Connection *connection)
+{
+ /*
+ * we can't use enumerate here, because the "existing objects list" might
+ * be changing due to the other _disconnectRemote calls we make, so we
+ * enumerate() the objects manually
+ */
+ unsigned long l;
+ for(l=0; l<objectPool.max(); l++)
+ {
+ Object_skel *skel = objectPool[l];
+ if(skel) skel->_disconnectRemote(connection);
+ }
+
+ d->requestResultCondition.wakeAll();
+ d->serverConnectCondition.wakeAll();
+
+ /*
+ * FIXME:
+ *
+ * there may be error handling to do (e.g., check that the _stub's that
+ * still refer to that connection don't crash now).
+ */
+ connection->_release();
+
+ list<Connection *>::iterator i;
+ for(i=connections.begin(); i != connections.end();i++)
+ {
+ if(*i == connection)
+ {
+ connections.erase(i);
+ return;
+ }
+ }
+}
+
+Connection *Dispatcher::activeConnection()
+{
+ return _activeConnection;
+}
+
+Connection *Dispatcher::loopbackConnection()
+{
+ return d->loopbackConnection;
+}
+
+DelayedReturn *Dispatcher::delayReturn()
+{
+ assert(!d->delayedReturn);
+
+ return d->delayedReturn = new DelayedReturn();
+}
+
+Object_skel *Dispatcher::getLocalObject(long objectID)
+{
+ Object_skel *result = objectPool[objectID];
+
+ if(result) result->_copy();
+ return result;
+}
+
+void Dispatcher::lock()
+{
+ _instance->d->mutex.lock();
+}
+
+void Dispatcher::unlock()
+{
+ _instance->d->mutex.unlock();
+}
+
+void Dispatcher::wakeUp()
+{
+ if(SystemThreads::the()->isMainThread()) return;
+
+ _instance->d->wakeUpHandler->wakeUp();
+}
+
+/*
+void Dispatcher::reloadTraderData() is declared in trader_impl.cc
+*/
diff --git a/mcop/dispatcher.h b/mcop/dispatcher.h
new file mode 100644
index 0000000..b143a1e
--- /dev/null
+++ b/mcop/dispatcher.h
@@ -0,0 +1,265 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef DISPATCHER_H
+#define DISPATCHER_H
+
+#include "common.h"
+#include "pool.h"
+#include "iomanager.h"
+#include "tcpserver.h"
+#include "unixserver.h"
+#include "connection.h"
+#include "notification.h"
+
+#include <deque>
+#include <stack>
+#include <vector>
+#include <list>
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Dispatcher
+ *
+ * This is part of the public API (and interacts with generated code) and
+ * has to be kept binary compatible.
+ */
+
+namespace Arts {
+
+class ObjectReference;
+class FlowSystem_impl;
+class GlobalComm;
+class InterfaceRepo;
+class ObjectManager;
+class Object_skel;
+class ReferenceClean;
+class DelayedReturn;
+
+extern "C" {
+ typedef void (*mcop_sighandler)(int);
+}
+
+class ARTS_EXPORT Dispatcher {
+private:
+ class DispatcherPrivate *d;
+
+protected:
+ static Dispatcher *_instance;
+
+ Pool<Buffer> requestResultPool;
+ Pool<Object_skel> objectPool;
+ std::list<Connection *> connections;
+
+ std::string serverID;
+ void generateServerID(); // helper function
+
+ bool deleteIOManagerOnExit;
+
+ TCPServer *tcpServer;
+ UnixServer *unixServer;
+ IOManager *_ioManager;
+ FlowSystem_impl *_flowSystem;
+ ObjectManager *objectManager;
+ ReferenceClean *referenceClean;
+ NotificationManager *notificationManager;
+
+ mcop_sighandler orig_sigpipe; // original signal handler for SIG_PIPE
+ Connection *_activeConnection; // internal use only (for refcounting)
+
+ /**
+ * connects to a given URL
+ *
+ * @returns a valid connection, or a 0 pointer on error
+ */
+ Connection *connectUrl(const std::string& url);
+
+public:
+ enum StartServer {
+ noServer = 0, // don't be a server
+ startUnixServer = 1, // listen on a unix domain socket
+ startTCPServer = 2, // listen on a tcp port
+ noAuthentication = 4 // don't require authentication
+ };
+
+ Dispatcher(IOManager *ioManager = 0, StartServer startServer = noServer);
+ ~Dispatcher();
+
+ static Dispatcher *the();
+ inline IOManager *ioManager() { return _ioManager; };
+ InterfaceRepo interfaceRepo();
+ FlowSystem_impl *flowSystem();
+ GlobalComm globalComm();
+ void setFlowSystem(FlowSystem_impl *fs);
+
+ void refillRequestIDs();
+
+ // blocking wait for result
+ Buffer *waitForResult(long requestID,Connection *connection);
+
+ // request creation for oneway and twoway requests
+ Buffer *createRequest(long& requestID, long objectID, long methodID);
+ Buffer *createOnewayRequest(long objectID, long methodID);
+
+ // processes messages
+ void handle(Connection *conn, Buffer *buffer, long messageType);
+
+ /*
+ * special hook to handle corrupt messages
+ */
+ void handleCorrupt(Connection *conn);
+
+ /**
+ * object registration
+ *
+ * do not call manually, this is used by the Object_skel constructor
+ * to register itself
+ */
+ long addObject(Object_skel *object);
+
+ /**
+ * object deregistration
+ *
+ * do not call manually, this is called by the Object_skel destructor
+ * as soon as the object is deleted
+ */
+ void removeObject(long objectID);
+
+ /**
+ * connects to a local object, returning a readily casted "interface" *
+ * if success, or NULL if this object is not local
+ */
+ void *connectObjectLocal(ObjectReference& reference, const std::string& interface);
+
+ /**
+ * connects to a remote object, establishing a connection if necessary
+ *
+ * returns NULL if connecting fails or object isn't present or whatever
+ * else could go wrong
+ */
+ Connection *connectObjectRemote(ObjectReference& reference);
+
+ /**
+ * stringification of objects (only used by the object implementations,
+ * which in turn provide a _toString method)
+ */
+ std::string objectToString(long objectID);
+
+ /**
+ * destringification of objects (mainly used by the object implementations,
+ * which in turn provide a _fromString method)
+ */
+ bool stringToObjectReference(ObjectReference& r, const std::string& s);
+
+ /**
+ * main loop
+ */
+ void run();
+
+ /**
+ * this function quits the main loop (it must be running, of course)
+ * and causes the run() function to return.
+ */
+ void terminate();
+
+ /**
+ * Is called by the transport services as soon as a new connection is
+ * created - this will send authentication request, etc.
+ */
+ void initiateConnection(Connection *connection);
+
+ /**
+ * Is called by the Connection as soon as the connection goes down,
+ * which may happen due to a normal cause (client exits), and may
+ * happen if an error occurs as well (network down)
+ */
+ void handleConnectionClose(Connection *connection);
+
+ /**
+ * Locks the dispatcher. Whenever you want to do anything with any kind
+ * of aRts object, you will hold a lock on Arts::Dispatcher. There is
+ * only one exception to the rule, and that is: you don't have to lock
+ * the dispatcher when the lock is already held.
+ *
+ * Generally, that is very often the case. Typical situations where you
+ * don't need to lock() the Dispatcher are:
+ *
+ * @li you receive a callback from the IOManager (timer or fd)
+ * @li you get call due to some MCOP request
+ * @li you are called from the NotificationManager
+ * @li you are called from the FlowSystem (calculateBlock)
+ */
+ static void lock();
+
+ /**
+ * Unlocks the dispatcher. Do this to release a lock you hold on
+ * the Arts::Dispatcher.
+ */
+ static void unlock();
+
+ /**
+ * Wakes the dispatcher - normally, the dispatcher will go to sleep in
+ * it's event loop, when nothing is to be done. If you change things from
+ * another thread, like: add a new Timer, write something to a connection,
+ * and so on, the dispatcher will not notice it. To wake the dispatcher
+ * up, this call is provided.
+ */
+ static void wakeUp();
+
+ /**
+ * - internal usage only -
+ *
+ * this will return the Connection the last request came from
+ */
+ Connection *activeConnection();
+
+ /**
+ * - internal usage only -
+ *
+ * this will return a loopback Connection for sending requests to myself
+ */
+ Connection *loopbackConnection();
+
+ /**
+ * - internal usage only -
+ *
+ * this will cause a function to return from a request later
+ * @see DelayedReturn
+ */
+ DelayedReturn *delayReturn();
+
+ /**
+ * - internal usage only -
+ *
+ * gets object with a given ID
+ * @returns the object if successful, 0 otherwise
+ */
+ Object_skel *getLocalObject(long ID);
+
+ /**
+ * reloads the trader data (do this if things have been added/changed
+ * there)
+ */
+ void reloadTraderData();
+};
+}
+#endif
diff --git a/mcop/dynamicrequest.cc b/mcop/dynamicrequest.cc
new file mode 100644
index 0000000..6ba64f7
--- /dev/null
+++ b/mcop/dynamicrequest.cc
@@ -0,0 +1,152 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "dynamicrequest.h"
+#include "common.h"
+#include "debug.h"
+#include <iostream>
+
+using namespace Arts;
+using namespace std;
+
+class Arts::DynamicRequestPrivate {
+public:
+ Connection *connection;
+ Buffer *buffer;
+ MethodDef method;
+ Object object;
+
+ /**
+ * methodID is kept between the requests, so that we don't need to lookup
+ * a method again when it gets called twice - the value for "we need to
+ * lookup again" is -1, which gets set whenever the current request differs
+ * from the last
+ */
+ long requestID, methodID, objectID;
+ unsigned long paramCount;
+
+ /**
+ * constructor
+ */
+ DynamicRequestPrivate(const Object &obj)
+ : buffer(0), object(obj), methodID(-1)
+ {
+ }
+};
+
+DynamicRequest::DynamicRequest(const Object& obj)
+{
+ d = new DynamicRequestPrivate(obj);
+ d->connection = obj._base()->_connection;
+ d->objectID = obj._base()->_objectID;
+}
+
+DynamicRequest::~DynamicRequest()
+{
+ delete d;
+}
+
+DynamicRequest& DynamicRequest::method(const string& method)
+{
+ assert(!d->buffer);
+
+ // methodID will be set later
+ d->buffer = Dispatcher::the()->createRequest(d->requestID, d->objectID, 0);
+
+ if(d->method.name != method)
+ {
+ d->method.name = method;
+ d->methodID = -1;
+ }
+ d->paramCount = 0;
+ return *this;
+}
+
+DynamicRequest& DynamicRequest::param(const AnyConstRef& ref)
+{
+ if(d->paramCount == d->method.signature.size())
+ {
+ ParamDef pd;
+ pd.type = ref.type();
+ d->method.signature.push_back(pd);
+ }
+ else
+ {
+ if(d->method.signature[d->paramCount].type != ref.type())
+ {
+ d->method.signature[d->paramCount].type = ref.type();
+ d->methodID = -1;
+ }
+ }
+ d->paramCount++;
+ ref.write(d->buffer);
+ return *this;
+}
+
+bool DynamicRequest::invoke()
+{
+ AnyRef voidReference;
+ return invoke(voidReference);
+}
+
+bool DynamicRequest::invoke(const AnyRef& returnCode)
+{
+ if(d->method.type != returnCode.type())
+ {
+ d->method.type = returnCode.type();
+ d->methodID = -1;
+ }
+ if(d->method.signature.size() != d->paramCount)
+ d->methodID = -1;
+
+ /*
+ * need to lookup method? (if the requested method is exactly the
+ * same as the last, we need not, which signigicantly improves performance
+ */
+ if(d->methodID == -1)
+ {
+ d->method.signature.resize(d->paramCount);
+ d->methodID = d->object._lookupMethod(d->method);
+
+ if(d->methodID == -1)
+ {
+ arts_warning("DynamicRequest: invalid method called");
+ return false;
+ }
+ }
+
+
+ d->buffer->patchLength();
+ d->buffer->patchLong(16,d->methodID);
+ d->connection->qSendBuffer(d->buffer);
+ d->buffer = 0;
+
+ Buffer *result =
+ Dispatcher::the()->waitForResult(d->requestID,d->connection);
+
+ if(result)
+ {
+ returnCode.read(result);
+ delete result;
+ }
+ return result != 0;
+}
diff --git a/mcop/dynamicrequest.h b/mcop/dynamicrequest.h
new file mode 100644
index 0000000..f749637
--- /dev/null
+++ b/mcop/dynamicrequest.h
@@ -0,0 +1,133 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef MCOP_DYNAMICREQUEST_H
+#define MCOP_DYNAMICREQUEST_H
+
+#include "buffer.h"
+#include "anyref.h"
+#include <vector>
+#include <string>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): DynamicRequest
+ *
+ * Has to be kept binary compatible (use d ptr).
+ */
+
+namespace Arts {
+
+class Object;
+class Type;
+class DynamicRequestPrivate;
+
+/**
+ * The DynamicRequest class can be used to invoke requests on objects, without
+ * using IDL generated code to do so (i.e. you can talk to objects without
+ * having to know their interfaces at compile time)
+ *
+ * Suppose you have the interface
+ *
+ * interface SimpleSoundServer {
+ * [...]
+ * long play(string file); // plays a file and returns an id
+ * [...]
+ * };
+ *
+ * And server is of type SimpleSoundServer, you can write in your C++ code:
+ *
+ * long id;
+ * if(DynamicRequest(server).method("play").param("/tmp/bong.wav").invoke(id))
+ * {
+ * cout << "playing file now, id is " << id << endl;
+ * }
+ * else
+ * {
+ * cout << "something went wrong with the dynamic request" << endl;
+ * }
+ *
+ * You can of course also add parameters and other information one-by-one:
+ *
+ * DynamicRequest request(server);
+ * request.method("play");
+ * request.param("/tmp/bong.wav");
+ *
+ * long id;
+ * if(request.invoke(id)) cout << "success" << endl;
+ */
+
+class ARTS_EXPORT DynamicRequest {
+public:
+ /**
+ * creates a dynamic request which will be sent to a specific object
+ */
+ DynamicRequest(const Object& object);
+
+ /**
+ * deletes the dynamic request
+ */
+ ~DynamicRequest();
+
+ /**
+ * says that the following method will be a oneway method, for example
+ *
+ * DynamicRequest(someobject).oneway().method("stop").invoke();
+ */
+ DynamicRequest& oneway();
+
+ /**
+ * sets the method to invoke
+ */
+ DynamicRequest& method(const std::string& method);
+
+ /**
+ * adds a parameter to the call
+ */
+ DynamicRequest& param(const AnyConstRef& value);
+
+ /**
+ * executes the request, call this if you don't expect a return type
+ *
+ * @returns true if the request could be performed
+ */
+ bool invoke();
+
+ /**
+ * executes the request: this version accepts an AnyRef& as result type
+ *
+ * @returns true if the request could be performed
+ */
+ bool invoke(const AnyRef& result);
+
+ /*
+ * TODO: Some types can't yet be used in dynamic requests, these are
+ * enum, sequence<enum>, type, sequence<type>, object, sequence<object>
+ */
+private:
+ DynamicRequestPrivate *d;
+};
+
+}
+
+#endif /* MCOP_DYNAMICREQUEST_H */
diff --git a/mcop/dynamicskeleton.cc b/mcop/dynamicskeleton.cc
new file mode 100644
index 0000000..99d6dd1
--- /dev/null
+++ b/mcop/dynamicskeleton.cc
@@ -0,0 +1,204 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "dynamicskeleton.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include "stdio.h"
+
+using namespace Arts;
+using namespace std;
+
+/* we could share the "class part" of those implicitely, as
+ types never change */
+
+namespace Arts {
+class DynamicSkeletonData {
+public:
+ DynamicSkeletonData(DynamicSkeletonBase *base,
+ Object_skel *skel,
+ const string& interfaceName,
+ const string& interfaceNameParent)
+ : base(base), skel(skel), interfaceName(interfaceName),
+ interfaceNameParent(interfaceNameParent)
+ {
+ }
+
+ enum InterfaceType { itNone, itParent, itDynamic };
+
+ void buildInterfaces();
+ void buildInterfaces(const string& s, InterfaceType t);
+ void buildMethodTable();
+
+ DynamicSkeletonBase *base;
+ Object_skel *skel;
+ string interfaceName, interfaceNameParent;
+ map<string, InterfaceType> interfaceMap;
+ map<string, void**> attrs;
+};
+}
+
+DynamicSkeletonBase::DynamicSkeletonBase(Object_skel *skel,
+ const std::string& interfaceName, const std::string& interfaceNameParent)
+{
+ arts_assert(skel != 0);
+ _dsInit(skel,interfaceName,interfaceNameParent);
+}
+
+DynamicSkeletonBase::DynamicSkeletonBase()
+{
+}
+
+void DynamicSkeletonBase::_dsInit(Object_skel *skel,
+ const std::string& interfaceName, const std::string& interfaceNameParent)
+{
+ d = new DynamicSkeletonData(this,skel,interfaceName,interfaceNameParent);
+ d->buildInterfaces();
+
+ /* TODO: optimize me! */
+ map<string, DynamicSkeletonData::InterfaceType>::iterator ii;
+ for(ii = d->interfaceMap.begin(); ii != d->interfaceMap.end(); ii++)
+ {
+ if(ii->second == DynamicSkeletonData::itDynamic)
+ {
+ InterfaceDef id;
+ id = Dispatcher::the()->interfaceRepo().queryInterface(ii->first);
+
+ vector<AttributeDef>::iterator ai;
+ for(ai = id.attributes.begin(); ai != id.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+ if((ad.flags & attributeStream) == attributeStream)
+ {
+ void**& data = d->attrs[ad.name.c_str()];
+ arts_assert(data == 0);
+ data = new (void*);
+ d->skel->_initStream(ad.name.c_str(),data,ad.flags);
+ }
+ }
+ }
+ }
+}
+
+DynamicSkeletonBase::~DynamicSkeletonBase()
+{
+ delete d;
+}
+
+std::string DynamicSkeletonBase::_dsInterfaceName()
+{
+ return d->interfaceName;
+}
+
+bool DynamicSkeletonBase::_dsIsCompatibleWith(const std::string& interfacename)
+{
+ d->buildInterfaces();
+ return d->interfaceMap[interfacename] != 0;
+}
+
+void DynamicSkeletonBase::_dsBuildMethodTable()
+{
+ d->buildMethodTable();
+}
+
+static void _dispatch_dynamic(void *object, long methodID, Buffer *request, Buffer *result)
+{
+ ((DynamicSkeletonBase *)object)->process(methodID, request, result);
+}
+
+void DynamicSkeletonData::buildMethodTable()
+{
+ buildInterfaces();
+
+ map<string, DynamicSkeletonData::InterfaceType>::iterator ii;
+ for(ii = interfaceMap.begin(); ii != interfaceMap.end(); ii++)
+ {
+ if(ii->second == itDynamic)
+ {
+ InterfaceDef id;
+ id = Dispatcher::the()->interfaceRepo().queryInterface(ii->first);
+
+ /* methods */
+ vector<MethodDef>::iterator mi;
+ for(mi = id.methods.begin(); mi != id.methods.end(); mi++)
+ skel->_addMethod(_dispatch_dynamic, base, *mi);
+
+ /* _get_ and _set_ methods for attributes */
+ vector<AttributeDef>::iterator ai;
+ for(ai = id.attributes.begin();ai != id.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if(ad.flags & attributeAttribute)
+ {
+ MethodDef md;
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ md.name = "_get_"+ad.name;
+ md.type = ad.type;
+ md.flags = methodTwoway;
+ /* no parameters (don't set md.signature) */
+
+ skel->_addMethod(_dispatch_dynamic, base, md);
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ md.name = "_set_"+ad.name;
+ md.type = "void";
+ md.flags = methodTwoway;
+
+ ParamDef pd;
+ pd.type = ad.type;
+ pd.name = "newValue";
+ md.signature.push_back(pd);
+
+ skel->_addMethod(_dispatch_dynamic, base, md);
+ }
+ }
+ }
+ }
+ }
+}
+
+void DynamicSkeletonData::buildInterfaces()
+{
+ if(interfaceMap.size() != 0) return;
+
+ buildInterfaces(interfaceName, itDynamic);
+ buildInterfaces(interfaceNameParent, itParent);
+}
+
+void DynamicSkeletonData::buildInterfaces(const string& name, DynamicSkeletonData::InterfaceType t)
+{
+ InterfaceDef id = Dispatcher::the()->interfaceRepo().queryInterface(name);
+
+ if(interfaceMap[name] == t) return;
+ interfaceMap[name] = t;
+
+ vector<string>::iterator ii;
+ for(ii = id.inheritedInterfaces.begin();
+ ii != id.inheritedInterfaces.end(); ii++)
+ {
+ buildInterfaces(*ii,t);
+ }
+ buildInterfaces("Arts::Object",t);
+}
diff --git a/mcop/dynamicskeleton.h b/mcop/dynamicskeleton.h
new file mode 100644
index 0000000..0c5cba7
--- /dev/null
+++ b/mcop/dynamicskeleton.h
@@ -0,0 +1,163 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_MCOP_DYNAMICSKELETON_H
+#define ARTS_MCOP_DYNAMICSKELETON_H
+
+#include "arts_export.h"
+
+#include "object.h"
+
+/*
+ * BC - Status (2002-03-08): DynamicSkeletonBase, DynamicSkeleton
+ *
+ * Will be kept binary compatible (using d ptr).
+ */
+namespace Arts {
+
+class DynamicSkeletonData;
+
+class ARTS_EXPORT DynamicSkeletonBase {
+private:
+ DynamicSkeletonData *d;
+
+protected:
+ DynamicSkeletonBase();
+ /* <obsolete compatibility code> */
+ DynamicSkeletonBase(Object_skel *skel,
+ const std::string& interfacename,
+ const std::string& interfacenameparent);
+ /* </obsolete compatibility code> */
+ virtual ~DynamicSkeletonBase();
+
+ void _dsInit(Object_skel *skel, const std::string& interfacename,
+ const std::string& interfacenameparent);
+ std::string _dsInterfaceName();
+ bool _dsIsCompatibleWith(const std::string& interfacename);
+ void _dsBuildMethodTable();
+
+public:
+ /**
+ * process is called whenever you get a request that you need to implement
+ * dynamically
+ *
+ * @param methodID contains the ID of the method that you need to
+ * implement - you can get the full signature by calling
+ * getMethodDef
+ *
+ * @param request contains the marshalled parameters
+ *
+ * @param result is for the return code - if your method returns a
+ * value, you need to write the it in the result Buffer
+ */
+ virtual void process(long methodID, Buffer *request, Buffer *result) = 0;
+};
+
+/**
+ * DynamicSkeleton is used to dynamically implement an interface (i.e. without
+ * static type bindings as generated by the MCOP idl compiler.
+ *
+ * You will always implement a mixed version: mcopidl generated skeletons up
+ * to a certain point, and above this, dynamically implemented interfaces.
+ * So you'll inherit DynamicSkeleton<Static_skel> and give the interface you
+ * want to implement dynamically as argument. Suppose your idl file looks
+ * like
+ *
+ * <pre>
+ * interface A { void a(); };
+ * interface B : A { void b(); };
+ * </pre>
+ *
+ * And you want to implement interface A "classic" (i.e. with mcopidl generated
+ * virtual void a()) and interface B "dynamic", you would do
+ *
+ * <pre>
+ * typedef Arts::DynamicSkeleton<A_skel> A_dskel; // convenient with typedef
+ *
+ * class B_impl : public A_dskel {
+ * public:
+ * B_impl() : A_dskel("B") { // we dynamically implement the B interface
+ * }
+ * void a() { // through A_skel
+ * arts_info("a called");
+ * }
+ * void process(long methodID, Arts::Buffer *request, Arts::Buffer *result)
+ * {
+ * const Arts::MethodDef& methodDef = getMethodDef(methodID);
+ *
+ * if(methodDef.name == "b")
+ * arts_info("b called!");
+ * else
+ * arts_fatal("Unknown method '%s' called");
+ * }
+ * };
+ * </pre>
+ */
+template<class Parent_skel>
+class DynamicSkeleton : virtual public Parent_skel, public DynamicSkeletonBase
+{
+public:
+ /**
+ * constructor
+ */
+ DynamicSkeleton(const std::string& interface)
+ {
+ _dsInit(this, interface, Parent_skel::_interfaceNameSkel());
+ }
+
+ /**
+ * getMethodDef returns a MethodDef structure for a given methodID - it
+ * is quite useful if you implement process
+ *
+ * <pre>
+ * void process(long methodID, Arts::Buffer *request, Arts::Buffer *result)
+ * {
+ * const Arts::MethodDef& methodDef = getMethodDef(methodID);
+ *
+ * if(methodDef.name == "hello") // the method named hello was called
+ * printf("Hello!\n");
+ * else // method with other name was called
+ * arts_fatal("Method '%s' not implemented",methodDef.name.c_str());
+ * }
+ * </pre>
+ */
+ const MethodDef& getMethodDef(long methodID) {
+ return this->_dsGetMethodDef(methodID);
+ }
+
+/*-- reimplemented from Arts::Object_skel: --*/
+ std::string _interfaceName() {
+ return _dsInterfaceName();
+ }
+
+ bool _isCompatibleWith(const std::string& interfacename) {
+ if(_dsIsCompatibleWith(interfacename)) return true;
+ return Parent_skel::_isCompatibleWith(interfacename);
+ }
+ void _buildMethodTable() {
+ Parent_skel::_buildMethodTable();
+ _dsBuildMethodTable();
+ }
+};
+
+}
+#endif /* ARTS_MCOP_DYNAMICSKELETON_H */
diff --git a/mcop/extensionloader.cc b/mcop/extensionloader.cc
new file mode 100644
index 0000000..82c56c5
--- /dev/null
+++ b/mcop/extensionloader.cc
@@ -0,0 +1,116 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "extensionloader.h"
+#include "startupmanager.h"
+#include "mcoputils.h"
+#include "debug.h"
+#include <unistd.h>
+#include <assert.h>
+
+using namespace std;
+using namespace Arts;
+
+ExtensionLoader::ExtensionLoader(const string& filename) :handle(0)
+{
+ string dlfilename;
+
+ assert(filename.size());
+ if(filename[0] == '/')
+ dlfilename = filename;
+ else
+ {
+ const vector<string> *path = MCOPUtils::extensionPath();
+
+ vector<string>::const_iterator pi;
+ for(pi = path->begin(); pi != path->end(); pi++)
+ {
+ dlfilename = *pi + "/" + filename;
+
+ if(access(dlfilename.c_str(),F_OK) == 0)
+ break;
+ }
+ }
+
+
+ /* this will catch all startup classes here */
+ StartupManager::setExtensionLoader(this);
+
+ lt_dlinit();
+ handle = lt_dlopen(dlfilename.c_str());
+
+ StartupManager::setExtensionLoader(0);
+
+ if(handle)
+ {
+ /* now process all startup classes of the loaded extension */
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses.begin(); i != startupClasses.end(); i++)
+ (*i)->startup();
+ needShutdown = true;
+ }
+ else
+ {
+ arts_warning("loading extension from '%s' failed: %s",
+ dlfilename.c_str(), lt_dlerror());
+ }
+}
+
+bool ExtensionLoader::success()
+{
+ return (handle != 0);
+}
+
+void ExtensionLoader::shutdown()
+{
+ if(handle && needShutdown)
+ {
+ /* shutdown the loaded extension properly */
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses.begin(); i != startupClasses.end(); i++)
+ (*i)->shutdown();
+ needShutdown = false;
+ }
+}
+
+ExtensionLoader::~ExtensionLoader()
+{
+ if(handle)
+ {
+ shutdown();
+ lt_dlclose(handle);
+
+ /*
+ * lt_dlexit & lt_dlinit have a counter, so there is no harm in
+ * calling one lt_dlinit in the constructor and one lt_dlexit here
+ */
+ lt_dlexit();
+ }
+}
+
+void ExtensionLoader::addStartupClass(class StartupClass *sc)
+{
+ startupClasses.push_back(sc);
+}
diff --git a/mcop/extensionloader.h b/mcop/extensionloader.h
new file mode 100644
index 0000000..ce67f12
--- /dev/null
+++ b/mcop/extensionloader.h
@@ -0,0 +1,59 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef EXTENSIONLOADER_H
+#define EXTENSIONLOADER_H
+
+#include <string>
+#include <list>
+#include <ltdl.h>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): ExtensionLoader
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. No binary compatibility guaranteed. (Interactions:
+ * ObjectManager, Startup stuff)
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT ExtensionLoader {
+protected:
+ std::list<class StartupClass *> startupClasses;
+ lt_dlhandle handle;
+ bool needShutdown;
+
+public:
+ ExtensionLoader(const std::string& path);
+ ~ExtensionLoader();
+
+ bool success();
+ void shutdown();
+
+ void addStartupClass(class StartupClass *sc);
+};
+
+}
+#endif /* EXTENSIONLOADER_H */
diff --git a/mcop/factory.cc b/mcop/factory.cc
new file mode 100644
index 0000000..f0cb2ab
--- /dev/null
+++ b/mcop/factory.cc
@@ -0,0 +1,36 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "factory.h"
+#include "objectmanager.h"
+
+using namespace Arts;
+
+void Factory::startup()
+{
+ ObjectManager::the()->registerFactory(this);
+}
+
+void Factory::shutdown()
+{
+ ObjectManager::the()->removeFactory(this);
+}
diff --git a/mcop/factory.h b/mcop/factory.h
new file mode 100644
index 0000000..91970ad
--- /dev/null
+++ b/mcop/factory.h
@@ -0,0 +1,69 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef FACTORY_H
+#define FACTORY_H
+
+#include <string>
+
+#include "arts_export.h"
+
+#include "object.h"
+#include "startupmanager.h"
+
+/*
+ * BC - Status (2002-03-08): Factory
+ *
+ * Will need to remain binary compatible (REGISTER_IMPLEMENTATION), d ptr
+ * provided for convenience, watch out for interactions with generated
+ * code.
+ */
+
+namespace Arts {
+
+class FactoryPrivate;
+
+class ARTS_EXPORT Factory : public StartupClass {
+private:
+ FactoryPrivate *d;
+public:
+ void startup();
+ void shutdown();
+ virtual Object_skel *createInstance() = 0;
+ virtual std::string interfaceName() = 0;
+};
+
+/*
+ * Dont's forget to place a semicolon after the use of this macro,
+ * like:
+ * REGISTER_IMPLEMENTATION(MyClass);
+ */
+#define REGISTER_IMPLEMENTATION(impl) \
+ class impl ## _Factory : virtual public Arts::Factory { \
+ public: \
+ std::string interfaceName() { return impl::_interfaceNameSkel(); } \
+ Arts::Object_skel *createInstance() { return new impl ; } \
+} The_ ## impl ## _Factory
+
+}
+
+#endif
diff --git a/mcop/flowsystem.cc b/mcop/flowsystem.cc
new file mode 100644
index 0000000..50ca26b
--- /dev/null
+++ b/mcop/flowsystem.cc
@@ -0,0 +1,180 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "flowsystem.h"
+#include "debug.h"
+
+using namespace Arts;
+
+//-------------- ScheduleNode -----------------
+
+ScheduleNode::ScheduleNode(Object_base *object) : _nodeObject(object)
+{
+ //
+}
+
+ScheduleNode::~ScheduleNode()
+{
+ //
+}
+
+Object ScheduleNode::nodeObject()
+{
+ assert(_nodeObject);
+ return Object::_from_base(_nodeObject->_copy());
+}
+
+RemoteScheduleNode *ScheduleNode::remoteScheduleNode()
+{
+ return 0;
+}
+
+void *ScheduleNode::cast(const std::string&)
+{
+ return 0;
+}
+
+
+//----------- RemoteScheduleNode -------------
+
+RemoteScheduleNode::RemoteScheduleNode(Object_stub *stub) : ScheduleNode(stub)
+{
+ //
+}
+
+RemoteScheduleNode *RemoteScheduleNode::remoteScheduleNode()
+{
+ return this;
+}
+
+void RemoteScheduleNode::initStream(const std::string&, void *, long)
+{
+ // not for stub objects
+ assert(false);
+}
+
+void RemoteScheduleNode::requireFlow()
+{
+ // stub objects can't require flow on this server (they don't live here)
+ assert(false);
+}
+
+void RemoteScheduleNode::virtualize(const std::string&, ScheduleNode *,
+ const std::string&)
+{
+ // (de)virtualization of ports is only implemented locally
+ assert(false);
+}
+
+void RemoteScheduleNode::devirtualize(const std::string&, ScheduleNode *,
+ const std::string&)
+{
+ // (de)virtualization of ports is only implemented locally
+ assert(false);
+}
+
+// interface to modify the node from outside
+
+void RemoteScheduleNode::start()
+{
+ FlowSystem remoteFs = nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.startObject(nodeObject());
+}
+
+void RemoteScheduleNode::stop()
+{
+ FlowSystem remoteFs = nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.stopObject(nodeObject());
+}
+
+void RemoteScheduleNode::connect(const std::string& port,
+ ScheduleNode *remoteNode,
+ const std::string& remotePort)
+{
+ arts_return_if_fail(remoteNode != 0);
+
+ FlowSystem fs = nodeObject()._flowSystem();
+ arts_return_if_fail(!fs.isNull());
+
+ AttributeType flags = fs.queryFlags(nodeObject(),port);
+ arts_return_if_fail(flags != 0);
+
+ // connectObject must be called as connectObject([sourcePort], [destPort]);
+
+ if(flags & streamOut) // if our port is an output port, this order
+ {
+ fs.connectObject(nodeObject(),port,remoteNode->nodeObject(),remotePort);
+ }
+ else if(flags & streamIn)
+ {
+ FlowSystem remoteFs = remoteNode->nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.connectObject(remoteNode->nodeObject(),
+ remotePort,nodeObject(),port);
+ } else {
+ assert(false);
+ }
+}
+
+void RemoteScheduleNode::disconnect(const std::string& port,
+ ScheduleNode *remoteNode,
+ const std::string& remotePort)
+{
+ arts_return_if_fail(remoteNode != 0);
+
+ FlowSystem fs = nodeObject()._flowSystem();
+ arts_return_if_fail(!fs.isNull());
+
+ AttributeType flags = fs.queryFlags(nodeObject(),port);
+ arts_return_if_fail(flags != 0);
+
+ // connectObject must be called as connectObject([sourcePort], [destPort]);
+
+ if(flags & streamOut) // if our port is an output port, this order
+ {
+ fs.disconnectObject(nodeObject(),port,remoteNode->nodeObject(),remotePort);
+ }
+ else if(flags & streamIn)
+ {
+ FlowSystem remoteFs = remoteNode->nodeObject()._flowSystem();
+ arts_return_if_fail(!remoteFs.isNull());
+
+ remoteFs.disconnectObject(remoteNode->nodeObject(),
+ remotePort,nodeObject(),port);
+ } else {
+ assert(false);
+ }
+}
+
+// constant values
+void RemoteScheduleNode::setFloatValue(const std::string& port, float value)
+{
+ FlowSystem fs = nodeObject()._flowSystem();
+ arts_return_if_fail(!fs.isNull());
+
+ fs.setFloatValue(nodeObject(), port, value);
+}
diff --git a/mcop/flowsystem.h b/mcop/flowsystem.h
new file mode 100644
index 0000000..c64c57b
--- /dev/null
+++ b/mcop/flowsystem.h
@@ -0,0 +1,147 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef FLOWSYSTEM_H
+#define FLOWSYSTEM_H
+
+#include "arts_export.h"
+#include "object.h"
+#include "common.h"
+
+/*
+ * BC - Status (2002-03-08): ScheduleNode, FlowSystem, FlowSystem_impl,
+ * RemoteScheduleNode
+ *
+ * Heavy interactions with generated and hand-written code, flowsystem binding
+ * and whatever. DO KEEP COMPATIBLE. Do not change the underlying IDL MODEL.
+ * d ptrs available.
+ */
+
+namespace Arts {
+
+class Object_skel;
+class Object_stub;
+class RemoteScheduleNode;
+class ScheduleNodePrivate;
+
+class ARTS_EXPORT ScheduleNode
+{
+private:
+ Object_base *_nodeObject;
+ ScheduleNodePrivate *d; // unused
+
+public:
+ ScheduleNode(Object_base *object);
+ virtual ~ScheduleNode();
+
+ Object nodeObject();
+
+ // check if this is a remote schedule node
+
+ virtual RemoteScheduleNode *remoteScheduleNode();
+
+ // other casts
+
+ virtual void *cast(const std::string& target);
+
+ // internal interface against Object_skel
+
+ typedef bool (*QueryInitStreamFunc)(Object_skel *object,
+ const std::string& name);
+
+ virtual void initStream(const std::string& name, void *ptr, long flags) = 0;
+
+ // interface against node implementation
+
+ virtual void requireFlow() = 0;
+ virtual void virtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort) = 0;
+ virtual void devirtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort) = 0;
+
+ // interface to modify the node from outside
+
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ virtual void connect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort) = 0;
+ virtual void disconnect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort) = 0;
+
+ // constant values
+ virtual void setFloatValue(const std::string& port, float value) = 0;
+};
+
+class RemoteScheduleNodePrivate;
+
+class ARTS_EXPORT RemoteScheduleNode : public ScheduleNode
+{
+private:
+ RemoteScheduleNodePrivate *d; // unused
+public:
+ RemoteScheduleNode(Object_stub *stub);
+
+ RemoteScheduleNode *remoteScheduleNode();
+
+ // internal interface against Object_skel
+
+ void initStream(const std::string& name, void *ptr, long flags);
+
+ // interface against node implementation
+
+ void requireFlow();
+ virtual void virtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort);
+ virtual void devirtualize(const std::string& port, ScheduleNode *implNode,
+ const std::string& implPort);
+
+ // interface to modify the node from outside
+
+ void start();
+ void stop();
+ void connect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort);
+ void disconnect(const std::string& port, ScheduleNode *remoteNode,
+ const std::string& remotePort);
+
+ // constant values
+ void setFloatValue(const std::string& port, float value);
+};
+
+class FlowSystem_impl_private;
+
+class FlowSystem_impl :virtual public FlowSystem_skel
+{
+private:
+ FlowSystem_impl_private *d;
+public:
+ virtual ScheduleNode *addObject(Object_skel *object) = 0;
+ virtual void removeObject(ScheduleNode *node) = 0;
+ virtual bool suspendable() = 0;
+ virtual bool suspended() = 0;
+ virtual void suspend() = 0;
+ virtual void restart() = 0;
+};
+
+}
+
+#endif
diff --git a/mcop/idlfilereg.cc b/mcop/idlfilereg.cc
new file mode 100644
index 0000000..4c15e24
--- /dev/null
+++ b/mcop/idlfilereg.cc
@@ -0,0 +1,44 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "common.h"
+
+using namespace Arts;
+
+IDLFileReg::IDLFileReg(const char *name, const char *contents)
+{
+ _name = name;
+ _contents = contents;
+}
+
+void IDLFileReg::startup()
+{
+ Buffer b;
+ b.fromString(_contents,"IDLFile");
+
+ nr = Dispatcher::the()->interfaceRepo().insertModule(ModuleDef(b));
+}
+
+void IDLFileReg::shutdown()
+{
+ Dispatcher::the()->interfaceRepo().removeModule(nr);
+}
diff --git a/mcop/idlfilereg.h b/mcop/idlfilereg.h
new file mode 100644
index 0000000..e9146ba
--- /dev/null
+++ b/mcop/idlfilereg.h
@@ -0,0 +1,51 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef IDLFILEREG_H
+#define IDLFILEREG_H
+
+#include <string>
+#include "startupmanager.h"
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): IDLFileReg
+ *
+ * Will be kept binary compatible by NOT TOUCHING AT ALL. Do not change this.
+ * (Interaction with generated code). Add a new class if you need something
+ * else than this does.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT IDLFileReg : public StartupClass {
+ long nr;
+ const char *_name, *_contents;
+public:
+ IDLFileReg(const char *name, const char *contents);
+ void startup();
+ void shutdown();
+};
+
+}
+#endif /* IDLFILEREG_H */
diff --git a/mcop/ifacerepo_impl.cc b/mcop/ifacerepo_impl.cc
new file mode 100644
index 0000000..5a7572c
--- /dev/null
+++ b/mcop/ifacerepo_impl.cc
@@ -0,0 +1,305 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "ifacerepo_impl.h"
+#include "debug.h"
+#include <iostream>
+#include <stdio.h>
+
+using namespace std;
+using namespace Arts;
+
+InterfaceRepo_impl::InterfaceRepo_impl()
+{
+ nextModuleID = 1;
+ tiMap["void"] = tiVoid;
+ tiMap["byte"] = tiByte;
+ tiMap["string"] = tiString;
+ tiMap["boolean"] = tiBoolean;
+ tiMap["float"] = tiFloat;
+ tiMap["long"] = tiLong;
+ tiMap["object"] = tiInterface;
+}
+
+InterfaceRepo_impl::~InterfaceRepo_impl()
+{
+ while(!unloadModuleList.empty())
+ {
+ removeModule(unloadModuleList.front());
+ unloadModuleList.pop_front();
+ }
+}
+
+long InterfaceRepo_impl::insertModule(const ModuleDef& newModule)
+{
+ long moduleID = nextModuleID++;
+
+ /* insert interfaces */
+ vector<InterfaceDef>::const_iterator ii;
+ for(ii=newModule.interfaces.begin();
+ ii != newModule.interfaces.end();ii++)
+ {
+ Buffer b;
+ ii->writeType(b);
+ InterfaceEntry *ie = new InterfaceEntry(b,moduleID);
+ interfaces.push_back(ie);
+
+ tiMap[ie->name] = tiInterface;
+ }
+
+ /* insert types */
+ vector<TypeDef>::const_iterator ti;
+ for(ti=newModule.types.begin();
+ ti != newModule.types.end();ti++)
+ {
+ Buffer b;
+ ti->writeType(b);
+ TypeEntry *entry = new TypeEntry(b,moduleID);
+ types.push_back(entry);
+
+ tiMap[entry->name] = tiType;
+ }
+
+ /* insert enums */
+ vector<EnumDef>::const_iterator ei;
+ for(ei=newModule.enums.begin();
+ ei != newModule.enums.end();ei++)
+ {
+ Buffer b;
+ ei->writeType(b);
+ EnumEntry *entry = new EnumEntry(b,moduleID);
+ enums.push_back(entry);
+
+ tiMap[entry->name] = tiEnum;
+ }
+
+ return moduleID;
+}
+
+void InterfaceRepo_impl::removeModule(long moduleID)
+{
+ /* erase interfaces */
+ list<InterfaceEntry *>::iterator ii;
+ ii = interfaces.begin();
+ while(ii != interfaces.end())
+ {
+ if((*ii)->moduleID == moduleID)
+ {
+ delete (*ii);
+ interfaces.erase(ii);
+ ii = interfaces.begin();
+ }
+ else ii++;
+ }
+
+ /* erase types */
+ list<TypeEntry *>::iterator ti;
+ ti = types.begin();
+ while(ti != types.end())
+ {
+ if((*ti)->moduleID == moduleID)
+ {
+ delete (*ti);
+ types.erase(ti);
+ ti = types.begin();
+ }
+ else ti++;
+ }
+
+ /* erase enums */
+ list<EnumEntry *>::iterator ei;
+ ei = enums.begin();
+ while(ei != enums.end())
+ {
+ if((*ei)->moduleID == moduleID)
+ {
+ delete (*ei);
+ enums.erase(ei);
+ ei = enums.begin();
+ }
+ else ei++;
+ }
+}
+
+InterfaceDef InterfaceRepo_impl::queryInterfaceLocal(const string& name)
+{
+ list<InterfaceEntry *>::iterator ii;
+
+ for(ii = interfaces.begin();ii != interfaces.end();ii++)
+ {
+ if((*ii)->name == name)
+ return **ii;
+ }
+ return InterfaceDef();
+}
+
+InterfaceDef InterfaceRepo_impl::queryInterface(const string& name)
+{
+ InterfaceDef def = queryInterfaceLocal(name);
+
+ if(def.name.empty())
+ {
+ TraderQuery q;
+ q.supports("Type",name);
+ vector<TraderOffer> *offers = q.query();
+ vector<TraderOffer>::iterator i;
+ for(i = offers->begin(); i != offers->end();i++)
+ {
+ TraderOffer& offer = *i;
+
+ if(def.name.empty())
+ {
+ vector<string> *types = offer.getProperty("TypeFile");
+ if(types->size() == 1)
+ {
+ const vector<string> *path = MCOPUtils::traderPath();
+
+ vector<string>::const_iterator pi = path->begin();
+ while(pi != path->end() && def.name.empty())
+ {
+ string filename = *pi++ + "/" + types->front();
+
+ FILE *extfile = fopen(filename.c_str(),"r");
+ if(extfile)
+ {
+ arts_debug("InterfaceRepo: loading %s",
+ filename.c_str());
+
+ Buffer b;
+ int c;
+ while((c = fgetc(extfile)) >= 0) b.writeByte(c);
+ fclose(extfile);
+
+ long id = insertModule(ModuleDef(b));
+ def = queryInterfaceLocal(name);
+ unloadModuleList.push_back(id);
+ }
+ }
+ }
+ delete types;
+ }
+ }
+ delete offers;
+ }
+
+ if(def.name.empty())
+ {
+ arts_warning("InterfaceRepo: no information about the interface %s "
+ "is known", name.c_str());
+ }
+
+ return def;
+}
+
+TypeDef InterfaceRepo_impl::queryType(const string& name)
+{
+ list<TypeEntry *>::iterator ti;
+
+ for(ti = types.begin();ti != types.end();ti++)
+ {
+ if((*ti)->name == name)
+ return **ti;
+ }
+
+ arts_warning("InterfaceRepo: no information about the type %s is known.",
+ name.c_str());
+ return TypeDef();
+}
+
+EnumDef InterfaceRepo_impl::queryEnum(const string& name)
+{
+ list<EnumEntry *>::iterator ei;
+
+ for(ei = enums.begin();ei != enums.end();ei++)
+ {
+ if((*ei)->name == name)
+ return **ei;
+ }
+
+ arts_warning("InterfaceRepo: no information about the enum %s is known.",
+ name.c_str());
+ return EnumDef();
+}
+
+vector<string> *InterfaceRepo_impl::queryChildren(const std::string& name)
+{
+ vector<string> *result = new vector<string>;
+ list<InterfaceEntry *>::iterator ii;
+
+ for(ii = interfaces.begin();ii != interfaces.end();ii++)
+ {
+ bool found = false;
+ vector<string>::iterator j;
+
+ for(j = (*ii)->inheritedInterfaces.begin();
+ j != (*ii)->inheritedInterfaces.end() && !found; j++)
+ {
+ if(*j == name)
+ {
+ result->push_back((*ii)->name);
+ found = true;
+ }
+ }
+ if((*ii)->inheritedInterfaces.empty() && ((name == "Arts::Object") || (name == "object")) && ((*ii)->name != "Arts::Object"))
+ result->push_back((*ii)->name);
+ }
+
+ return result;
+}
+
+vector<string> *InterfaceRepo_impl::queryInterfaces()
+{
+ vector<string> *result = new vector<string>;
+ list<InterfaceEntry *>::iterator ii;
+
+ for(ii = interfaces.begin();ii != interfaces.end();ii++)
+ result->push_back((*ii)->name);
+
+ return result;
+}
+
+vector<string> *InterfaceRepo_impl::queryTypes()
+{
+ vector<string> *result = new vector<string>;
+ list<TypeEntry *>::iterator ti;
+
+ for(ti = types.begin();ti != types.end();ti++)
+ result->push_back((*ti)->name);
+
+ return result;
+}
+
+vector<string> *InterfaceRepo_impl::queryEnums()
+{
+ vector<string> *result = new vector<string>;
+ list<EnumEntry *>::iterator ei;
+
+ for(ei = enums.begin();ei != enums.end();ei++)
+ result->push_back((*ei)->name);
+
+ return result;
+}
+
+TypeIdentification InterfaceRepo_impl::identifyType(const string& name)
+{
+ return tiMap[name];
+}
diff --git a/mcop/ifacerepo_impl.h b/mcop/ifacerepo_impl.h
new file mode 100644
index 0000000..ffa98de
--- /dev/null
+++ b/mcop/ifacerepo_impl.h
@@ -0,0 +1,98 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): InterfaceRepo_impl
+ *
+ * This is an implementation class, and not kept binary compatible. It's
+ * only here since the REGISTER_IMPLEMENTATION bootstrapping may not yet
+ * be done before the first piece of startup code (IDLFileReg) needs the
+ * Interface repository.
+ */
+
+#ifndef IFACEREPO_H
+#define IFACEREPO_H
+
+#include "common.h"
+#include <map>
+
+namespace Arts {
+
+class InterfaceRepo_impl : virtual public InterfaceRepoV2_skel {
+ class Entry {
+ public:
+ long moduleID;
+ Entry(long moduleID) : moduleID(moduleID)
+ {
+ }
+ };
+ class EnumEntry : public EnumDef, public Entry {
+ public:
+ EnumEntry(Buffer& stream, long moduleID)
+ :EnumDef(stream), Entry(moduleID)
+ {
+ }
+ };
+ class TypeEntry : public TypeDef, public Entry {
+ public:
+ TypeEntry(Buffer& stream, long moduleID)
+ :TypeDef(stream), Entry(moduleID)
+ {
+ }
+ };
+ class InterfaceEntry : public InterfaceDef, public Entry {
+ public:
+ InterfaceEntry(Buffer& stream, long moduleID)
+ :InterfaceDef(stream), Entry(moduleID)
+ {
+ };
+ };
+
+ std::list<EnumEntry *> enums;
+ std::list<TypeEntry *> types;
+ std::list<InterfaceEntry *> interfaces;
+ std::map<std::string, TypeIdentification> tiMap;
+ std::list<long> unloadModuleList;
+
+ long nextModuleID;
+
+ InterfaceDef queryInterfaceLocal(const std::string& name);
+public:
+
+ InterfaceRepo_impl();
+ ~InterfaceRepo_impl();
+
+ long insertModule(const ModuleDef& newModule);
+ void removeModule(long moduleID);
+ InterfaceDef queryInterface(const std::string& name);
+ TypeDef queryType(const std::string& name);
+ EnumDef queryEnum(const std::string& name);
+
+ TypeIdentification identifyType(const std::string& name);
+
+ std::vector<std::string> *queryChildren(const std::string& name);
+ std::vector<std::string> *queryInterfaces();
+ std::vector<std::string> *queryTypes();
+ std::vector<std::string> *queryEnums();
+};
+}
+#endif /* IFACEREPO_H */
diff --git a/mcop/iomanager.cc b/mcop/iomanager.cc
new file mode 100644
index 0000000..442318a
--- /dev/null
+++ b/mcop/iomanager.cc
@@ -0,0 +1,494 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "iomanager.h"
+#include "dispatcher.h"
+#include "notification.h"
+#include "thread.h"
+#include <stdio.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h> // Needed on some systems.
+#endif
+// WABA: NOTE!
+// sys/select.h is needed on e.g. AIX to define "fd_set".
+// However, we can not include config.h in a header file.
+// The right solution would be not to use "fd_set" in the
+// header file but to use it only in a private datastructure
+// defined in the .cc file.
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+/* internal data structures */
+class IOWatchFD {
+ int _fd, _types;
+ IONotify *_notify;
+
+public:
+ int activeTypes;
+
+ IOWatchFD(int fd, int types, IONotify *notify);
+
+ inline int fd() { return _fd; };
+ inline int types() { return _types; };
+ inline IONotify *notify() { return _notify; };
+ inline void remove(int types) { _types &= ~types; }
+};
+
+class TimeWatcher {
+ int milliseconds;
+ TimeNotify *_notify;
+ timeval nextNotify;
+ bool active, destroyed;
+
+ bool earlier(const timeval& reference);
+public:
+ TimeWatcher(int _milliseconds, TimeNotify *notify);
+
+ inline TimeNotify *notify() { return _notify; };
+ timeval advance(const timeval& currentTime);
+ void destroy();
+};
+}
+
+/*
+ * Enable this if you want to debug how long certain plugins / operations
+ * take to perform. You'll get the times between two select() calls that are
+ * done by the IOManager, which is equivalent to the time the input/output
+ * remains unserved. For apps like artsd, it gives the minimum audio latency
+ * users will need to specify to avoid dropouts.
+ */
+#undef IOMANAGER_DEBUG_LATENCY
+
+#ifdef IOMANAGER_DEBUG_LATENCY
+static timeval iomanager_debug_latency_time = { 0, 0 };
+
+static void iomanager_debug_latency_end()
+{
+ if(iomanager_debug_latency_time.tv_sec)
+ {
+ timeval end;
+ gettimeofday(&end,0);
+
+ float diff = (end.tv_usec-iomanager_debug_latency_time.tv_usec)/1000.0
+ + (end.tv_sec-iomanager_debug_latency_time.tv_sec)*1000.0;
+
+ /* change this value if you get your screen filled up with messages */
+ if(diff >= 1.5)
+ fprintf(stderr,"IOManager: latency for operation: %2.3f ms\n",diff);
+ }
+}
+
+static void iomanager_debug_latency_start()
+{
+ gettimeofday(&iomanager_debug_latency_time,0);
+}
+#else
+static inline void iomanager_debug_latency_end()
+{
+}
+
+static inline void iomanager_debug_latency_start()
+{
+}
+#endif
+
+IOWatchFD::IOWatchFD(int fd, int types, IONotify *notify)
+{
+ _fd = fd;
+ _types = types;
+ _notify = notify;
+ activeTypes = 0;
+}
+
+StdIOManager::StdIOManager()
+{
+ // force initialization of the fd_set's
+ fdListChanged = true;
+ timeListChanged = false;
+ level = 0;
+}
+
+void StdIOManager::processOneEvent(bool blocking)
+{
+ assert(SystemThreads::the()->isMainThread());
+
+ level++;
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::lock();
+
+ // notifications not carried out reentrant
+ if(level == 1)
+ NotificationManager::the()->run();
+
+ // FIXME: timers *could* change the file descriptors to select...
+ //---
+ if(fdListChanged)
+ {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ FD_ZERO(&reentrant_readfds);
+ FD_ZERO(&reentrant_writefds);
+ FD_ZERO(&reentrant_exceptfds);
+
+ maxfd = 0;
+
+ list<IOWatchFD *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++)
+ {
+ IOWatchFD *w = *i;
+
+ if(w->types() & IOType::read) FD_SET(w->fd(),&readfds);
+ if(w->types() & IOType::write) FD_SET(w->fd(),&writefds);
+ if(w->types() & IOType::except) FD_SET(w->fd(),&exceptfds);
+
+ if(w->types() & IOType::reentrant)
+ {
+ if(w->types() & IOType::read)
+ FD_SET(w->fd(),&reentrant_readfds);
+ if(w->types() & IOType::write)
+ FD_SET(w->fd(),&reentrant_writefds);
+ if(w->types() & IOType::except)
+ FD_SET(w->fd(),&reentrant_exceptfds);
+ }
+
+ if(w->types() && w->fd() > maxfd) maxfd = w->fd();
+ }
+
+ fdListChanged = false;
+ }
+ fd_set rfd,wfd,efd;
+ if(level == 1)
+ {
+ rfd = readfds;
+ wfd = writefds;
+ efd = exceptfds;
+ }
+ else
+ {
+ // watch out, this is reentrant I/O
+ rfd = reentrant_readfds;
+ wfd = reentrant_writefds;
+ efd = reentrant_exceptfds;
+ }
+
+ /* default timeout 5 seconds */
+ long selectabs;
+
+ if(blocking)
+ selectabs = 5000000;
+ else
+ selectabs = 0;
+
+ /* prepare timers - only at level 1 */
+ if(level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<TimeWatcher *>::iterator ti;
+
+ timeListChanged = false;
+ ti = timeList.begin();
+ while(ti != timeList.end())
+ {
+ TimeWatcher *w = *ti++;
+ timeval timertime = w->advance(currenttime);
+
+ // if that may happen in the next ten seconds
+ if(timertime.tv_sec < currenttime.tv_sec+10)
+ {
+ long timerabs = (timertime.tv_sec - currenttime.tv_sec)*1000000;
+ timerabs += (timertime.tv_usec - currenttime.tv_usec);
+
+ if(timerabs < selectabs) selectabs = timerabs;
+ }
+
+ if(timeListChanged)
+ {
+ ti = timeList.begin();
+ timeListChanged = false;
+ }
+ }
+ }
+
+ timeval select_timeout;
+ select_timeout.tv_sec = selectabs / 1000000;
+ select_timeout.tv_usec = selectabs % 1000000;
+
+ if(level == 1) iomanager_debug_latency_end();
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::unlock();
+
+ int retval = select(maxfd+1,&rfd,&wfd,&efd,&select_timeout);
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::lock();
+
+ if(level == 1) iomanager_debug_latency_start();
+
+ if(retval > 0)
+ {
+ /*
+ * the problem is, that objects that are being notified may change
+ * the watch list, add fds, remove fds, remove objects and whatever
+ * else
+ *
+ * so we can' notify them from the loop - but we can make a stack
+ * of "notifications to do" and send them as soon as we looked up
+ * in the list what to send
+ */
+ long tonotify = 0;
+
+ list<IOWatchFD *>::iterator i;
+ for(i = fdList.begin(); i != fdList.end(); i++) {
+ IOWatchFD *w = *i;
+ int match = 0;
+
+ if(FD_ISSET(w->fd(),&rfd) && (w->types() & IOType::read))
+ match |= IOType::read;
+
+ if(FD_ISSET(w->fd(),&wfd) && (w->types() & IOType::write))
+ match |= IOType::write;
+
+ if(FD_ISSET(w->fd(),&efd) && (w->types() & IOType::except))
+ match |= IOType::except;
+
+ if((w->types() & IOType::reentrant) == 0 && level != 1)
+ match = 0;
+
+ if(match) {
+ tonotify++;
+ w->activeTypes = match;
+ notifyStack.push(w);
+ }
+ }
+
+ while(tonotify != 0)
+ {
+ if(!fdListChanged)
+ {
+ IOWatchFD *w = notifyStack.top();
+ int activeTypes = w->activeTypes;
+ int fd = w->fd();
+ IONotify *notify = w->notify();
+
+ w->activeTypes = 0;
+ notify->notifyIO(fd, activeTypes);
+ // warning: w and notify might no longer exist here
+ }
+
+ notifyStack.pop();
+ tonotify--;
+ }
+ }
+ /* handle timers - only at level 1 */
+ if(level == 1 && timeList.size())
+ {
+ struct timeval currenttime;
+ gettimeofday(&currenttime,0);
+
+ list<TimeWatcher *>::iterator ti;
+
+ timeListChanged = false;
+ ti = timeList.begin();
+ while(ti != timeList.end())
+ {
+ TimeWatcher *w = *ti++;
+ w->advance(currenttime);
+ if (timeListChanged)
+ {
+ ti = timeList.begin();
+ timeListChanged = false;
+ }
+ }
+ }
+
+ // notifications not carried out reentrant
+ if(level == 1)
+ NotificationManager::the()->run();
+
+ // we release and acquire the lock only on level 1
+ if(level == 1)
+ Dispatcher::unlock();
+
+ level--;
+}
+
+void StdIOManager::run()
+{
+ assert(SystemThreads::the()->isMainThread());
+ assert(level == 0);
+
+ // FIXME: this might not be threadsafe, as there is no lock here!
+ terminated = false;
+ while(!terminated)
+ processOneEvent(true);
+}
+
+void StdIOManager::terminate()
+{
+ terminated = true;
+ Dispatcher::wakeUp();
+}
+
+void StdIOManager::watchFD(int fd, int types, IONotify *notify)
+{
+ /*
+ IOWatchFD *watchfd = findWatch(fd,notify);
+ if(watchfd)
+ {
+ watchfd->add(types);
+ }
+ else
+ {
+ fdList.push_back(new IOWatchFD(fd,types,notify));
+ }
+ */
+
+ // FIXME: might want to reuse old watches
+ fdList.push_back(new IOWatchFD(fd,types,notify));
+ fdListChanged = true;
+ Dispatcher::wakeUp();
+}
+
+void StdIOManager::remove(IONotify *notify, int types)
+{
+ list<IOWatchFD *>::iterator i;
+
+ i = fdList.begin();
+
+ while(i != fdList.end())
+ {
+ IOWatchFD *w = *i;
+
+ if(w->notify() == notify) w->remove(types);
+
+ // nothing left to watch?
+ if(w->types() == 0 || w->types() == IOType::reentrant)
+ {
+ i = fdList.erase(i);
+ delete w; // FIXME: shouldn't we have a destroy() similar
+ // to the one for timers
+ }
+ else i++;
+ }
+ fdListChanged = true;
+}
+
+void StdIOManager::addTimer(int milliseconds, TimeNotify *notify)
+{
+ if (milliseconds == -1 && notify == 0) {
+ // HACK: in order to not add a virtual function to IOManager we're calling addTimer with
+ // magic values. This call tells the ioManager that notifications are pending and
+ // NotificationManager::run() should get called soon.
+ } else {
+ timeList.push_back(new TimeWatcher(milliseconds,notify));
+ timeListChanged = true;
+ Dispatcher::wakeUp();
+ }
+}
+
+void StdIOManager::removeTimer(TimeNotify *notify)
+{
+ list<TimeWatcher *>::iterator i;
+
+ i = timeList.begin();
+
+ while(i != timeList.end())
+ {
+ TimeWatcher *w = *i;
+
+ if(w->notify() == notify)
+ {
+ i = timeList.erase(i);
+ timeListChanged = true;
+ w->destroy();
+ }
+ else i++;
+ }
+}
+
+TimeWatcher::TimeWatcher(int _milliseconds, TimeNotify *notify)
+ : milliseconds(_milliseconds),_notify(notify),active(false),destroyed(false)
+{
+ gettimeofday(&nextNotify,0);
+
+ nextNotify.tv_usec += (milliseconds%1000)*1000;
+ nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000);
+ nextNotify.tv_usec %= 1000000;
+}
+
+timeval TimeWatcher::advance(const timeval& currentTime)
+{
+ active = true;
+ while(earlier(currentTime))
+ {
+ nextNotify.tv_usec += (milliseconds%1000)*1000;
+ nextNotify.tv_sec += (milliseconds/1000)+(nextNotify.tv_usec/1000000);
+ nextNotify.tv_usec %= 1000000;
+
+ _notify->notifyTime();
+
+ if(destroyed)
+ {
+ delete this;
+
+ struct timeval never = { 0xffffffff, 0 };
+ return never;
+ }
+ }
+ active = false;
+ return nextNotify;
+}
+
+bool TimeWatcher::earlier(const timeval& reference)
+{
+ if(nextNotify.tv_sec > reference.tv_sec) return false;
+ if(nextNotify.tv_sec < reference.tv_sec) return true;
+
+ return (nextNotify.tv_usec < reference.tv_usec);
+}
+
+void TimeWatcher::destroy()
+{
+ if(active)
+ {
+ destroyed = true;
+ }
+ else
+ {
+ delete this;
+ }
+}
diff --git a/mcop/iomanager.h b/mcop/iomanager.h
new file mode 100644
index 0000000..a226e0c
--- /dev/null
+++ b/mcop/iomanager.h
@@ -0,0 +1,214 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08):
+ * BINARY COMPATIBLE: IONotify, TimeNotify, IOManager
+ * NO BC FOR: StdIOManager
+ *
+ * Whereas the first three are part of the Interface (i.e. DEFINITELY to be
+ * kept binary compatible), the next three are part of the implementation
+ * in libmcop and subject to any kind of change.
+ */
+
+#ifndef IOMANAGER_H
+#define IOMANAGER_H
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <list>
+#include <stack>
+
+#include "arts_export.h"
+
+namespace Arts {
+// constants:
+
+/**
+ * What does the reentrant flag do?
+ *
+ * The IOManager offers a processOneEvent call. This means, that you can ask
+ * that I/O is handled, even while in a routine that handles I/O. As a
+ * practical example: you may have got a remote invocation for the function
+ * foo. Now you are in function foo() and call function bar() on a remote
+ * server. When you wait for the result, you obviously will again require
+ * the IOManager to wait for it. Thus this is a case where you need reentrant
+ * I/O handling.
+ *
+ * That way, you get a multiple level stack:
+ *
+ * <pre>
+ * [...]
+ * |
+ * [ Hander for I/O ]
+ * |
+ * [ IOManager ] level 2
+ * |
+ * [ Some other function ]
+ * |
+ * [ Hander for I/O ]
+ * |
+ * [ IOManager ] level 1
+ * |
+ * [ main() ]
+ * </pre>
+ *
+ * What reentrant does, is to allow that IO Watch to be activated at levels
+ * higher than one.
+ *
+ * Timers and notifications, on the other hand will only be carried out at
+ * level 1.
+ */
+struct IOType {
+ enum { read = 1, write = 2, except = 4, reentrant = 8, all = 15 };
+};
+
+/**
+ * IONotify is the base class you can derive from to receive callbacks about
+ * IO activity. You will need to call the watchFD function of the IOManager
+ * to start watching a filedescriptor.
+ *
+ * @see Arts::IOManager
+ */
+class ARTS_EXPORT IONotify {
+public:
+ /**
+ * This is the function that gets called if something relevant happened
+ * on the filedescriptor you watched with IOManager::watchFD.
+ *
+ * @param fd is the filedescriptor that has seen some IO activity
+ * @param type is the type of activity (as combination of IOType)
+ */
+ virtual void notifyIO(int fd, int type) = 0;
+};
+
+/**
+ * TimeNotify is the base class you can derive from to receive timer callbacks.
+ * You will need to call the addTimer function of the IOManager to start
+ * watching a filedescriptor.
+ *
+ * @see Arts::IOManager
+ */
+class ARTS_EXPORT TimeNotify {
+public:
+ /**
+ * This function gets whenever the timer is activated. Note that the
+ * IOManager will try to "catch up" lost time, that is, if you have a
+ * 300ms timer that didn't get called for a second (because there was
+ * something else to do), you'll receive three calls in a row.
+ */
+ virtual void notifyTime() = 0;
+};
+
+/**
+ * Provides services like timers and notifications when filedescriptors get
+ * ready to read/write.
+ */
+class ARTS_EXPORT IOManager {
+public:
+ virtual ~IOManager() {};
+
+ /**
+ * processes exactly one io event
+ */
+ virtual void processOneEvent(bool blocking) = 0;
+
+ /**
+ * enters a loop which processes io events, until terminate is called
+ *
+ * may only be called once (use processOneEvent for other purposes)
+ */
+ virtual void run() = 0;
+
+ /**
+ * terminates the io event loop (which was started with run)
+ */
+ virtual void terminate() = 0;
+
+ /**
+ * starts watching one filedescriptor for certain types of operations
+ *
+ * notifies the notify object when e.g. the fd requires (allows) reading
+ * and types contained IOType::read.
+ *
+ * @see Arts::IOType
+ * @see Arts::IONotify
+ */
+ virtual void watchFD(int fd, int types, IONotify *notify) = 0;
+
+ /**
+ * stops watching a filedescriptor
+ */
+ virtual void remove(IONotify *notify, int types) = 0;
+ /*
+ * BCI when breaking BC, probably int fd should be added as argument
+ * to remove, this would be more consistent with the way watches are added
+ */
+
+ /**
+ * starts a periodic timer
+ *
+ * @see Arts::TimeNotify
+ */
+ virtual void addTimer(int milliseconds, TimeNotify *notify) = 0;
+
+ /**
+ * stops the timer
+ */
+ virtual void removeTimer(TimeNotify *notify) = 0;
+};
+
+class IOWatchFD;
+class TimeWatcher;
+
+class ARTS_EXPORT StdIOManager : public IOManager {
+protected:
+ std::list<IOWatchFD *> fdList;
+ std::list<TimeWatcher *> timeList;
+ std::stack<IOWatchFD *> notifyStack;
+
+ bool terminated;
+
+ bool fdListChanged; // causes the fd_sets to be rebuilt before using them
+ bool timeListChanged;
+ fd_set readfds, writefds, exceptfds;
+ fd_set reentrant_readfds, reentrant_writefds, reentrant_exceptfds;
+ int maxfd;
+
+ int level;
+
+public:
+ StdIOManager();
+
+ void processOneEvent(bool blocking);
+ void run();
+ void terminate();
+ void watchFD(int fd, int types, IONotify *notify);
+ void remove(IONotify *notify, int types);
+ void addTimer(int milliseconds, TimeNotify *notify);
+ void removeTimer(TimeNotify *notify);
+};
+
+}
+
+#endif
diff --git a/mcop/loopback.cc b/mcop/loopback.cc
new file mode 100644
index 0000000..0cc58a8
--- /dev/null
+++ b/mcop/loopback.cc
@@ -0,0 +1,57 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "loopback.h"
+#include "common.h"
+
+using namespace Arts;
+using namespace std;
+
+LoopbackConnection::LoopbackConnection(const std::string& serverID)
+{
+ setServerID(serverID);
+ _connState = established;
+}
+
+void LoopbackConnection::qSendBuffer(Buffer *buffer)
+{
+ assert(buffer->size() >= 12);
+
+ long magic = buffer->readLong();
+ assert(magic == MCOP_MAGIC);
+
+ /* messageSize, irrelevant here, since we've got the buffer already */
+ buffer->readLong();
+ long messageType = buffer->readLong();
+
+ Dispatcher::the()->handle(this,buffer,messageType);
+}
+
+void LoopbackConnection::drop()
+{
+ assert(false);
+}
+
+bool LoopbackConnection::broken()
+{
+ return false;
+}
diff --git a/mcop/loopback.h b/mcop/loopback.h
new file mode 100644
index 0000000..0e0c092
--- /dev/null
+++ b/mcop/loopback.h
@@ -0,0 +1,51 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef MCOP_LOOPBACKCONNECTION_H
+#define MCOP_LOOPBACKCONNECTION_H
+
+#include "connection.h"
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): LoopbackConnection
+ *
+ * Not part of the public API. Do NOT use it in your apps. No binary
+ * compatibility guaranteed.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT LoopbackConnection : public Connection
+{
+public:
+ LoopbackConnection(const std::string& serverID);
+
+ void qSendBuffer(Buffer *buffer);
+ void drop();
+ bool broken();
+};
+
+}
+
+#endif /* MCOP_LOOPBACKCONNECTION_H */
diff --git a/mcop/mcopconfig.cc b/mcop/mcopconfig.cc
new file mode 100644
index 0000000..ad56c55
--- /dev/null
+++ b/mcop/mcopconfig.cc
@@ -0,0 +1,67 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "mcopconfig.h"
+#include "mcoputils.h"
+#include <fstream>
+
+using namespace std;
+using namespace Arts;
+
+MCOPConfig::MCOPConfig(const string& filename) :filename(filename)
+{
+}
+
+string MCOPConfig::readEntry(const string& key, const string& defaultValue)
+{
+ ifstream in(filename.c_str());
+ string keyvalue;
+
+ while(in >> keyvalue)
+ {
+ int i = keyvalue.find("=",0);
+ if(i != 0 && keyvalue.substr( 0, i ) == key)
+ return keyvalue.substr( i+1, keyvalue.size()-(i+1) );
+ }
+ return defaultValue;
+}
+
+vector<string> *MCOPConfig::readListEntry(const string& key)
+{
+ vector<string> *result = new vector<string>;
+
+ ifstream in(filename.c_str());
+ string keyvalue;
+
+ while(in >> keyvalue)
+ {
+ string k;
+
+ MCOPUtils::tokenize(keyvalue,k,*result);
+ if(k == key)
+ return result;
+
+ result->clear();
+ }
+
+ return result;
+}
diff --git a/mcop/mcopconfig.h b/mcop/mcopconfig.h
new file mode 100644
index 0000000..04531f0
--- /dev/null
+++ b/mcop/mcopconfig.h
@@ -0,0 +1,55 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): MCOPConfig
+ *
+ * Is guaranteed to stay binary compatible. d ptr provided.
+ */
+
+#ifndef MCOPCONFIG_H
+#define MCOPCONFIG_H
+
+#include <string>
+#include <vector>
+
+#include "arts_export.h"
+
+namespace Arts {
+
+class MCOPConfigPrivate;
+class ARTS_EXPORT MCOPConfig {
+private:
+ MCOPConfigPrivate *d; // unused
+protected:
+ std::string filename;
+
+public:
+ MCOPConfig(const std::string& filename);
+
+ std::string readEntry(const std::string& key,
+ const std::string& defaultValue = "");
+ std::vector<std::string> *readListEntry(const std::string& key);
+};
+
+}
+#endif /* MCOPCONFIG_H */
diff --git a/mcop/mcoputils.cc b/mcop/mcoputils.cc
new file mode 100644
index 0000000..14275fb
--- /dev/null
+++ b/mcop/mcoputils.cc
@@ -0,0 +1,574 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "mcoputils.h"
+#include "mcopconfig.h"
+#include "debug.h"
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <config.h>
+#include <ctype.h>
+#include <cstdlib>
+#include <cstring>
+#include <stdio.h>
+#include <map>
+
+using namespace std;
+using namespace Arts;
+
+// 0: Dir ok
+// 1: Dir not ok
+static int check_tmp_dir(const char *tmp_dir)
+{
+ int result;
+ struct stat stat_buf;
+ result = lstat(tmp_dir, &stat_buf);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ return 1;
+ }
+ if ((result == -1) || (!S_ISDIR(stat_buf.st_mode)))
+ {
+ arts_warning("Error: \"%s\" is not a directory.\n", tmp_dir);
+ return 1;
+ }
+
+ if (stat_buf.st_uid != getuid())
+ {
+ arts_warning("Error: \"%s\" is owned by uid %d instead of uid %d.\n", tmp_dir, stat_buf.st_uid, getuid());
+ return 1;
+ }
+ return 0;
+}
+
+
+// 0: Link not ok
+// != 0: location of mcop directory
+static char *locate_mcop_dir()
+{
+ struct passwd *pw_ent;
+ char kde_tmp_dir[PATH_MAX+1];
+ char user_tmp_dir[PATH_MAX+1];
+ int uid = getuid();
+ const char *home_dir = getenv("HOME");
+ const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME");
+ const char *kde_prefix = "/socket-";
+ const char *tmp;
+ char *tmp_buf;
+ int result;
+ struct stat stat_buf;
+
+ tmp = getenv("KDETMP");
+ if (!tmp || !tmp[0])
+ tmp = getenv("TMPDIR");
+ if (!tmp || !tmp[0])
+ tmp = "/tmp";
+
+ kde_tmp_dir[0] = 0;
+
+ pw_ent = getpwuid(uid);
+ if (!pw_ent)
+ {
+ arts_warning("Error: Can not find password entry for uid %d.\n", getuid());
+ return 0;
+ }
+
+ strncpy(user_tmp_dir, tmp, PATH_MAX );
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, "/ksocket-", PATH_MAX - strlen(user_tmp_dir) );
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(user_tmp_dir));
+ user_tmp_dir[ PATH_MAX ] = '\0';
+
+ if (!kde_home || !kde_home[0])
+ {
+ kde_home = "~/.kde/";
+ }
+
+ if (kde_home[0] == '~')
+ {
+ if (uid == 0)
+ {
+ home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root";
+ }
+ if (!home_dir || !home_dir[0])
+ {
+ arts_fatal("Aborting. $HOME not set!");
+ }
+ if (strlen(home_dir) > (PATH_MAX-100))
+ {
+ arts_fatal("Aborting. Home directory path too long!");
+ }
+ kde_home++;
+ strncpy(kde_tmp_dir, home_dir, PATH_MAX);
+ kde_tmp_dir[ PATH_MAX ] = '\0';
+ }
+ strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir));
+
+ /** Strip trailing '/' **/
+ if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/')
+ kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0;
+
+ result = stat(kde_tmp_dir, &stat_buf);
+ if (result == -1)
+ {
+ return 0;
+ }
+
+ strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir));
+ if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0)
+ {
+ arts_fatal("Aborting. Could not determine hostname or hostname too long.");
+ }
+ kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0';
+
+ result = lstat(kde_tmp_dir, &stat_buf);
+ if ((result == 0) && (S_ISDIR(stat_buf.st_mode)))
+ {
+ /* $KDEHOME/socket-$HOSTNAME is a normal directory. Do nothing. */
+ tmp_buf = (char *) malloc(PATH_MAX+1);
+ if (!tmp_buf)
+ return 0;
+
+ strncpy(tmp_buf, kde_tmp_dir, PATH_MAX);
+ tmp_buf[ PATH_MAX ] = '\0';
+
+ return tmp_buf;
+ }
+
+ if ((result == -1) && (errno == ENOENT))
+ {
+ // Link mising...
+ return 0;
+ }
+ if ((result == -1) || (!S_ISLNK(stat_buf.st_mode)))
+ {
+ arts_warning("Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir);
+ return 0;
+ }
+ tmp_buf = (char *) malloc(PATH_MAX+1);
+ if (!tmp_buf)
+ return 0;
+
+ /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
+ result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX);
+ if (result == -1)
+ {
+ arts_warning("Error: \"%s\" could not be read.\n", kde_tmp_dir);
+ free(tmp_buf);
+ return 0;
+ }
+ tmp_buf[result] = '\0';
+// printf("Link points to \"%s\"\n", tmp_buf);
+ if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0)
+ {
+ arts_warning("Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir);
+ free(tmp_buf);
+ return 0;
+ }
+ result = check_tmp_dir(tmp_buf);
+ if (result == 0) return tmp_buf; /* Success */
+
+ free(tmp_buf);
+ return 0;
+}
+
+/* blatant and literal copy from lnusertemp to avoid kdelibs dependency */
+/* Copyright (c) 2000 Waldo Bastian <bastian@kde.org>, released under LGPL */
+
+static
+int create_link(const char *file, const char *tmp_dir)
+{
+ int result;
+ result = check_tmp_dir(tmp_dir);
+ if (result)
+ {
+ return result;
+ }
+ result = symlink(tmp_dir, file);
+ if (result == -1)
+ {
+ fprintf(stderr, "Error: Can not create link from \"%s\" to \"%s\"\n", file, tmp_dir);
+ return 1;
+ }
+ printf("Created link from \"%s\" to \"%s\"\n", file, tmp_dir);
+ return 0;
+}
+
+
+static
+int build_link(const char *tmp_prefix, const char *kde_prefix)
+{
+ struct passwd *pw_ent;
+ char kde_tmp_dir[PATH_MAX+1];
+ char user_tmp_dir[PATH_MAX+1];
+ char tmp_buf[PATH_MAX+1];
+ int uid = getuid();
+ const char *home_dir = getenv("HOME");
+ const char *kde_home = uid ? getenv("KDEHOME") : getenv("KDEROOTHOME");
+ int result;
+ struct stat stat_buf;
+
+ kde_tmp_dir[0] = 0;
+
+ pw_ent = getpwuid(uid);
+ if (!pw_ent)
+ {
+ fprintf(stderr, "Error: Can not find password entry for uid %d.\n", getuid());
+ return 1;
+ }
+
+ strncpy(user_tmp_dir, tmp_prefix, PATH_MAX);
+ user_tmp_dir[ PATH_MAX ] = '\0';
+ strncat(user_tmp_dir, pw_ent->pw_name, PATH_MAX - strlen(tmp_prefix));
+
+ if (!kde_home || !kde_home[0])
+ {
+ kde_home = "~/.kde/";
+ }
+
+ if (kde_home[0] == '~')
+ {
+ if (uid == 0)
+ {
+ home_dir = pw_ent->pw_dir ? pw_ent->pw_dir : "/root";
+ }
+ if (!home_dir || !home_dir[0])
+ {
+ fprintf(stderr, "Aborting. $HOME not set!");
+ exit(255);
+ }
+ if (strlen(home_dir) > (PATH_MAX-100))
+ {
+ fprintf(stderr, "Aborting. Home directory path too long!");
+ exit(255);
+ }
+ kde_home++;
+ strncpy(kde_tmp_dir, home_dir, PATH_MAX);
+ kde_tmp_dir[ PATH_MAX ] = '\0';
+ }
+ strncat(kde_tmp_dir, kde_home, PATH_MAX - strlen(kde_tmp_dir));
+
+ /** Strip trailing '/' **/
+ if ( kde_tmp_dir[strlen(kde_tmp_dir)-1] == '/')
+ kde_tmp_dir[strlen(kde_tmp_dir)-1] = 0;
+
+ result = stat(kde_tmp_dir, &stat_buf);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ result = mkdir(kde_tmp_dir, 0700);
+ }
+ if (result == -1)
+ {
+ return 1;
+ }
+
+ strncat(kde_tmp_dir, kde_prefix, PATH_MAX - strlen(kde_tmp_dir));
+ if (gethostname(kde_tmp_dir+strlen(kde_tmp_dir), PATH_MAX - strlen(kde_tmp_dir) - 1) != 0)
+ {
+ perror("Aborting. Could not determine hostname: ");
+ exit(255);
+ }
+ kde_tmp_dir[sizeof(kde_tmp_dir)-1] = '\0';
+
+ result = lstat(kde_tmp_dir, &stat_buf);
+ if ((result == 0) && (S_ISDIR(stat_buf.st_mode)))
+ {
+ /* $KDEHOME/tmp is a normal directory. Do nothing. */
+ printf("Directory \"%s\" already exists.\n", kde_tmp_dir);
+ return 0;
+ }
+ if ((result == -1) && (errno == ENOENT))
+ {
+ printf("Creating link %s.\n", kde_tmp_dir);
+ result = create_link(kde_tmp_dir, user_tmp_dir);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+ }
+ if ((result == -1) || (!S_ISLNK(stat_buf.st_mode)))
+ {
+ fprintf(stderr, "Error: \"%s\" is not a link or a directory.\n", kde_tmp_dir);
+ return 1;
+ }
+ /* kde_tmp_dir is a link. Check whether it points to a valid directory. */
+ result = readlink(kde_tmp_dir, tmp_buf, PATH_MAX);
+ if (result == -1)
+ {
+ fprintf(stderr, "Error: \"%s\" could not be read.\n", kde_tmp_dir);
+ return 1;
+ }
+ tmp_buf[result] = '\0';
+ printf("Link points to \"%s\"\n", tmp_buf);
+ if (strncmp(tmp_buf, user_tmp_dir, strlen(user_tmp_dir)) != 0)
+ {
+ fprintf(stderr, "Error: \"%s\" points to \"%s\" instead of \"%s\".\n", kde_tmp_dir, tmp_buf, user_tmp_dir);
+ unlink(kde_tmp_dir);
+ printf("Creating link %s.\n", kde_tmp_dir);
+ result = create_link(kde_tmp_dir, user_tmp_dir);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+ return 1;
+ }
+ result = check_tmp_dir(tmp_buf);
+ if (result == 0) return 0; /* Success */
+ unlink(kde_tmp_dir);
+ strncat(user_tmp_dir, "XXXXXX", PATH_MAX - strlen(user_tmp_dir));
+ mktemp(user_tmp_dir); /* We want a directory, not a file, so using mkstemp makes no sense and is wrong */
+ return create_link(kde_tmp_dir, user_tmp_dir);
+}
+
+string MCOPUtils::createFilePath(string name)
+{
+ static char *mcop_dir = 0;
+ if (!mcop_dir)
+ {
+ mcop_dir = locate_mcop_dir();
+ }
+ if (!mcop_dir)
+ {
+
+ const char *tmp = 0;
+ tmp = getenv("KDETMP");
+ if (!tmp || !tmp[0])
+ tmp = getenv("TMPDIR");
+ if (!tmp || !tmp[0])
+ tmp = "/tmp";
+
+ char tmp_prefix[PATH_MAX+1];
+ strcpy(tmp_prefix, tmp);
+ strcat(tmp_prefix, "/ksocket-");
+
+ build_link(tmp_prefix, "/socket-");
+ mcop_dir = locate_mcop_dir();
+ }
+ if (!mcop_dir)
+ {
+ arts_fatal("can't create mcop directory");
+ }
+ string tmpdir = mcop_dir;
+ return tmpdir+"/"+name;
+}
+
+/*
+ * try to figure out full hostname - this is important as every client which
+ * tries to connect objects located here will need to be able to resolve that
+ * correctly
+ */
+string MCOPUtils::getFullHostname()
+{
+ char buffer[1024];
+ string result;
+ struct hostent *hp;
+
+ if(gethostname(buffer,1024) == 0) {
+ buffer[1023] = '\0';
+ result = buffer;
+ } else
+ return "localhost";
+
+ /*
+ * if gethostname() isn't a FQDN (guess that by checking whether it
+ * contains a dot), try to look it up to ensure it is
+ */
+ if(result.find('.') == string::npos && (hp = gethostbyname(buffer)) != 0)
+ result = hp->h_name;
+
+ return result;
+}
+
+string MCOPUtils::readConfigEntry(const string& key, const string& defaultValue)
+{
+ const char *home = getenv("HOME");
+ if(home)
+ {
+ string rcname = home + string("/.mcoprc");
+
+ MCOPConfig config(rcname);
+ return config.readEntry(key,defaultValue);
+ }
+ return defaultValue;
+}
+
+/** IID generation **/
+
+unsigned long MCOPUtils::makeIID(const string& interfaceName)
+{
+ static map<string, unsigned long> *iidmapobj = 0;
+ static unsigned long nextiid = 1;
+
+ if(!iidmapobj) iidmapobj = new map<string,unsigned long>;
+
+ map<string,unsigned long>& iidmap = *iidmapobj;
+
+ if(iidmap.find(interfaceName) == iidmap.end()) {
+ iidmap[interfaceName] = nextiid++;
+ return nextiid-1; // no need to lookup in the map thrice
+ }
+
+ return iidmap[interfaceName];
+}
+
+static vector<string> *readPath(const string& name, const string& defaultValue)
+{
+ vector<string> *result = 0;
+ const char *home = getenv("HOME");
+
+ if(home)
+ {
+ string rcname = home + string("/.mcoprc");
+
+ MCOPConfig config(rcname);
+ result = config.readListEntry(name);
+ }
+ if(!result)
+ result = new vector<string>;
+ if(result->empty())
+ result->push_back(defaultValue);
+
+ return result;
+}
+
+const vector<string> *MCOPUtils::extensionPath()
+{
+ static vector<string> *result = 0;
+
+ if(!result) result = readPath("ExtensionPath", EXTENSION_DIR);
+ return result;
+}
+
+const vector<string> *MCOPUtils::traderPath()
+{
+ static vector<string> *result = 0;
+
+ if(!result)
+ {
+ result = readPath("TraderPath", TRADER_DIR);
+
+ const char *home = getenv("HOME");
+ if(home) result->push_back(home + string("/.mcop/trader-cache"));
+ }
+ return result;
+}
+
+string MCOPUtils::mcopDirectory()
+{
+ static bool initialized = false;
+ static string mcopDirectory;
+
+ if(initialized)
+ return mcopDirectory;
+ initialized = true;
+
+ const char *home = getenv("HOME");
+ arts_return_val_if_fail(home != 0, "");
+
+ mcopDirectory = home + string("/.mcop");
+
+ mkdir(home,0755);
+ if(mkdir(mcopDirectory.c_str(),0755) != 0)
+ {
+ string why = strerror(errno);
+
+ struct stat st;
+ stat(mcopDirectory.c_str(),&st);
+ if(!S_ISDIR(st.st_mode))
+ {
+ arts_warning("can't create directory %s (%s)",
+ mcopDirectory.c_str(), why.c_str());
+
+ mcopDirectory = "";
+ }
+ }
+ return mcopDirectory;
+}
+
+bool MCOPUtils::tokenize(const string& line, string& key,vector<string>& values)
+{
+ string value;
+ enum { sKey, sValue, sValueQuoted, sValueQuotedEscaped, sBad } state;
+
+ state = sKey;
+ for(string::const_iterator i = line.begin(); i != line.end(); i++)
+ {
+ char c = *i;
+ unsigned char uc = static_cast<unsigned char>(c);
+
+ arts_assert(c != '\n');
+
+ if(state == sKey)
+ {
+ if(c == ' ' || c == '\t')
+ ; // ignore
+ else if(isalnum(c))
+ key += c;
+ else if(c == '=')
+ state = sValue;
+ else
+ state = sBad;
+ }
+ else if(state == sValue)
+ {
+ if(c == ' ' || c == '\t')
+ ; // ignore
+ else if(c == '"')
+ state = sValueQuoted;
+ else if(c == ',')
+ {
+ values.push_back(value);
+ value = "";
+ }
+ else if(uc > 32 && uc < 128)
+ value += c;
+ else
+ state = sBad;
+ }
+ else if(state == sValueQuoted)
+ {
+ if(c == '"')
+ state = sValue;
+ else if(c == '\\')
+ state = sValueQuotedEscaped;
+ else
+ value += c;
+ }
+ else if(state == sValueQuotedEscaped)
+ {
+ value += c;
+ state = sValueQuoted;
+ }
+ }
+ if(state == sValue)
+ values.push_back(value);
+
+ return(state != sBad);
+}
diff --git a/mcop/mcoputils.h b/mcop/mcoputils.h
new file mode 100644
index 0000000..ecfe9b0
--- /dev/null
+++ b/mcop/mcoputils.h
@@ -0,0 +1,97 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): MCOPUtils
+ *
+ * Collection class for all kinds of utility functions. BC, since never
+ * instanciated.
+ */
+
+#ifndef MCOPUTILS_H
+#define MCOPUTILS_H
+
+#include <string>
+#include <vector>
+
+#include "arts_export.h"
+
+namespace Arts {
+
+class ARTS_EXPORT MCOPUtils {
+public:
+ /**
+ * Returns the full pathname to a file in the mcop directory which
+ * is called "name". It will also care that no other characters than
+ * A-Z,a-z,0-9,-,_ occur.
+ *
+ * The result is something like /tmp/mcop-<username>/name, the directory
+ * will be created when necessary.
+ */
+ static std::string createFilePath(std::string name);
+
+ /**
+ * Returns the fully qualified hostname, such as "www.kde.org" (of course
+ * this may fail due to misconfiguration).
+ *
+ * The result is "localhost" if nothing at all can be found out.
+ */
+ static std::string getFullHostname();
+
+ /**
+ * Returns configuration values from .mcoprc
+ */
+ static std::string readConfigEntry(const std::string& key,
+ const std::string& defaultValue = "");
+
+ /**
+ * Makes an interface ID from string - if the given string is already
+ * known, the returned IID will be the one returned last time. If not,
+ * a new IID is generated
+ */
+ static unsigned long makeIID(const std::string& interfaceName);
+
+ /**
+ * Returns the directories for the trader to look into
+ */
+ static const std::vector<std::string> *traderPath();
+
+ /**
+ * Returns the directories from where extensions can be loaded
+ */
+ static const std::vector<std::string> *extensionPath();
+
+ /**
+ * Returns the full path of the ~/.mcop directory
+ */
+ static std::string mcopDirectory();
+
+ /**
+ * Tokenization of a key = value1, "value 2", "value III" line into the key
+ * and the values.
+ */
+ static bool tokenize(const std::string& line, std::string& key,
+ std::vector<std::string>& values);
+};
+
+}
+#endif /* MCOPUTILS_H */
diff --git a/mcop/md5.c b/mcop/md5.c
new file mode 100644
index 0000000..782ce30
--- /dev/null
+++ b/mcop/md5.c
@@ -0,0 +1,197 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "md5.h"
+
+/*
+ * this is okay for all architectures with int = 32bit, so IMHO all
+ * current architectures supported by KDE.
+ */
+typedef unsigned int uint32;
+
+static void MD5Transform(uint32 buf[4], uint32 in[MD5_BINARY_LEN]);
+
+void arts_md5sum(unsigned char *message, long len, char *md5sum)
+{
+ long finalsize = len+1; /* in bytes */
+ int i = 0, j = 0;
+ unsigned char w = '\0';
+ uint32 buffer[4] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
+ uint32 in[MD5_BINARY_LEN];
+
+ while((finalsize & 63) != 56) finalsize++;
+ finalsize += 8;
+
+ for( i=0, j=0;i<finalsize;i++)
+ {
+ if(i < len) {
+ w = message[i];
+ } else if(i == len) {
+ w = 0x80;
+ } else if((finalsize-i > 8) || (finalsize-i <= 4)) {
+ w = 0;
+ } else {
+ /* well, the length thing encoded in here will only
+ work until 2^32 bits (though md5 would support 2^64
+ bits) */
+ w = ((len*8) >> ((i+8-finalsize)*8)) & 0xff;
+ }
+ switch(i & 3) {
+ case 0: in[j] = w;
+ break;
+ case 1: in[j] |= w << 8;
+ break;
+ case 2: in[j] |= w << 16;
+ break;
+ case 3: in[j] |= w << 24;
+ j++;
+ if(j == MD5_BINARY_LEN) {
+ MD5Transform(buffer,in);
+ j = 0;
+ }
+ break;
+ }
+ }
+
+ for( i=0, j=0;j<4;j++)
+ {
+ md5sum[i++] = buffer[j] & 0xff;
+ md5sum[i++] = (buffer[j] >> 8) & 0xff;
+ md5sum[i++] = (buffer[j] >> 16) & 0xff;
+ md5sum[i++] = (buffer[j] >> 24) & 0xff;
+ }
+}
+
+/*
+ * I used the central part of Colin Plumb's public domain MD5 implementation
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ */
+
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(uint32 buf[4], uint32 in[MD5_BINARY_LEN])
+{
+ uint32 a = buf[0];
+ uint32 b = buf[1];
+ uint32 c = buf[2];
+ uint32 d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
diff --git a/mcop/md5.h b/mcop/md5.h
new file mode 100644
index 0000000..5670d7e
--- /dev/null
+++ b/mcop/md5.h
@@ -0,0 +1,45 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): arts_md5sum
+ *
+ * No binary compatibility guaranteed (part of Dispatcher's security model).
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#define MD5_BINARY_LEN 16
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+void arts_md5sum(unsigned char *message, long len, char *md5sum);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/mcop/md5auth.cc b/mcop/md5auth.cc
new file mode 100644
index 0000000..1e6fe1a
--- /dev/null
+++ b/mcop/md5auth.cc
@@ -0,0 +1,213 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#elif HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+#include "md5.h"
+#include "md5auth.h"
+#include "debug.h"
+
+// MD5_BINARY_LEN is defined in md5.h
+#define MD5_COOKIE_LEN (MD5_BINARY_LEN*2)
+#define MD5_MANGLE_LEN (MD5_COOKIE_LEN*2)
+
+
+
+struct random_info {
+ struct timeval tv;
+ int pid;
+ struct utsname un;
+ char dev_urandom[MD5_BINARY_LEN];
+ char seed[MD5_COOKIE_LEN+1];
+ int number;
+};
+
+static char md5_seed[MD5_COOKIE_LEN+1];
+static char md5_cookie[MD5_COOKIE_LEN+1];
+static int md5_init = 0;
+static int md5_random_cookie_number = 0;
+
+static char *md5_to_ascii_overwrite(char *md5)
+{
+ char outascii[MD5_COOKIE_LEN+1];
+ char *result;
+ int i;
+
+ // convert to readable text
+ for(i = 0; i < MD5_BINARY_LEN; i++) {
+ sprintf(&outascii[i*2],"%02x",md5[i] & 0xff);
+ }
+ outascii[MD5_COOKIE_LEN] = 0;
+ result = strdup(outascii);
+
+ // try to zero out traces
+ memset(md5,0,MD5_BINARY_LEN);
+ memset(outascii,0,MD5_COOKIE_LEN);
+
+ // well, here it is
+ return result;
+}
+
+char *arts_md5_auth_mangle(const char *cookie)
+{
+ char mangle[MD5_MANGLE_LEN+1];
+ char out[MD5_BINARY_LEN];
+ assert(md5_init);
+
+ // concat the two cookies and mangle them to a new one
+ strncpy(mangle,md5_cookie, MD5_COOKIE_LEN);
+ mangle[MD5_COOKIE_LEN] = 0;
+ strncat(mangle,cookie, MD5_COOKIE_LEN);
+ mangle[MD5_MANGLE_LEN] = 0;
+ arts_md5sum((unsigned char *)mangle,MD5_MANGLE_LEN,out);
+
+ // try to zero out traces
+ memset(mangle,0,MD5_MANGLE_LEN);
+
+ return md5_to_ascii_overwrite(out);
+}
+
+char *arts_md5_auth_mkcookie()
+{
+ struct random_info r;
+ char out[MD5_BINARY_LEN];
+ int rndfd;
+
+ memset(&r,0,sizeof(struct random_info));
+
+ // collect some "random" system information
+ gettimeofday(&r.tv,0);
+ r.pid = getpid();
+ uname(&r.un);
+
+ // linux random device ; if that works, we have good random anyway, the
+ // above are just helpers for the case that it doesn't
+ rndfd = open("/dev/urandom",O_RDONLY);
+ if(rndfd != -1)
+ {
+ read(rndfd,r.dev_urandom,MD5_BINARY_LEN);
+ close(rndfd);
+ }
+
+ // ensure that two cookies that are requested very shortly after each
+ // other (so that it looks like "at the same time") won't be the same
+ r.number = ++md5_random_cookie_number;
+
+ // this is some seed from a file which is updated sometimes with a
+ // new "arts_md5_auth_mkcookie()" after initialization
+ strncpy(r.seed,md5_seed,MD5_COOKIE_LEN);
+
+ // build hash value of all information
+ arts_md5sum((unsigned char *)&r,sizeof(struct random_info),out);
+
+ // zero out traces and return
+ memset(&r,0,sizeof(struct random_info));
+ return md5_to_ascii_overwrite(out);
+}
+
+const char *arts_md5_auth_cookie()
+{
+ assert(md5_init);
+ return md5_cookie;
+}
+
+static int md5_load_cookie(const char *filename, char *cookie)
+{
+ int fd = open(filename,O_RDONLY);
+ int i;
+
+ if(fd != -1) {
+ struct stat st;
+ for(i=0;i<5;i++) {
+ fstat(fd,&st);
+ if(st.st_size == MD5_COOKIE_LEN) {
+ lseek(fd, 0, SEEK_SET);
+ if(read(fd,cookie,MD5_COOKIE_LEN) == MD5_COOKIE_LEN)
+ {
+ cookie[MD5_COOKIE_LEN] = 0;
+ close(fd);
+ return 1;
+ }
+ }
+ arts_warning("MCOP: "
+ "authority file has wrong size (just being written?)");
+ sleep(1);
+ }
+ }
+ return 0;
+}
+
+void arts_md5_auth_init_seed(const char *seedname)
+{
+ // don't care if it works - no harm is being done if it doesn't
+ md5_load_cookie(seedname,md5_seed);
+
+ /*
+ * maxage ensures that not everybody will try to update the seed
+ * at the same time, while it will take at most 5 hours between
+ * updates (if there are any initialization calls)
+ */
+ struct stat st;
+ int maxage = 300 + (getpid() & 0xfff)*4;
+ int lstat_result = lstat(seedname,&st);
+ if(lstat_result != 0 || (time(0) - st.st_mtime) > maxage)
+ {
+ int fd = open(seedname,O_TRUNC|O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
+ if(fd != -1) {
+ char *cookie = arts_md5_auth_mkcookie();
+ write(fd,cookie,strlen(cookie));
+ memset(cookie,0,strlen(cookie));
+ free(cookie);
+ close(fd);
+ }
+ }
+}
+
+bool arts_md5_auth_set_cookie(const char *cookie)
+{
+ if(strlen(cookie) != MD5_COOKIE_LEN)
+ return false;
+
+ strncpy(md5_cookie,cookie,MD5_COOKIE_LEN);
+ md5_cookie[MD5_COOKIE_LEN] = 0;
+ md5_init = 1;
+ return true;
+}
diff --git a/mcop/md5auth.h b/mcop/md5auth.h
new file mode 100644
index 0000000..c0197ff
--- /dev/null
+++ b/mcop/md5auth.h
@@ -0,0 +1,105 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): arts_md5_*
+ *
+ * No guarantees - do not use.
+ */
+
+#ifndef MD5_AUTH_H
+#define MD5_AUTH_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * How that MD5 auth stuff is supposed to work:
+ *
+ * Initialization:
+ *
+ * Your service calls arts_md5_auth_set_cookie and passes a "secret cookie".
+ * Lets call the "secret cookie" S. As soon as a client wants to connect,
+ * he needs the same secret cookie S.
+ *
+ * Of course the user can copy the "secret cookie" using a secure connection
+ * to any computer from which he wants to access the service.
+ *
+ * 0. SERVER: if no common secret cookie is available, generate a random
+ * cookie and keep it secret - ensure (through secure connections)
+ * that the client gets the secret cookie
+ *
+ * 1. SERVER: generate a new (random) cookie R
+ * 2. SERVER: send it to the client
+ * 3. CLIENT: (should get/have the "secret cookie" S from somewhere secure)
+ * 4. CLIENT: mangle the cookies R and S to a mangled cookie M
+ * 5. CLIENT: send M to the server
+ * 6. SERVER: verify that mangling R and S gives just the same thing as the
+ * cookie M received from the client. If yes, authentication is successful.
+ *
+ * The advantage of that protocol is, that even somebody who can read all
+ * network traffic can't find out the secret cookie S, as that is never
+ * transferred as plaintext.
+ */
+
+/*
+ * generates a new random cookie R (also be used to generate secret cookies)
+ * => free it when you don't need it any more
+ */
+char *arts_md5_auth_mkcookie();
+
+/*
+ * mangles a "secret cookie" with another "random cookie"
+ * => free result when done
+ */
+char *arts_md5_auth_mangle(const char *random);
+
+/*
+ * using arts_md5_auth_init_seed, the security will be improved by loading a
+ * randomseed from that file, and (if it has no recent date) saving a new
+ * seed to it - this will ensure that the arts_md5_auth_mkcookie() routine will
+ * return a really unpredictable result (as it depends on all processes that
+ * ever have touched the seed)
+ */
+void arts_md5_auth_init_seed(const char *seedname);
+
+/*
+ * use this routine to set the "secret cookie" - you can pass a newly
+ * generated random cookie here, or the secret cookie you got from
+ * elsewhere (to communicate with others)
+ *
+ * returns true if success (good cookie), false if setting the cookie failed
+ */
+bool arts_md5_auth_set_cookie(const char *cookie);
+
+/*
+ * returns "secret cookie"
+ */
+const char *arts_md5_auth_cookie();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/mcop/namedstore.h b/mcop/namedstore.h
new file mode 100644
index 0000000..e5fad59
--- /dev/null
+++ b/mcop/namedstore.h
@@ -0,0 +1,125 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_NAMEDSTORE_H
+#define ARTS_NAMEDSTORE_H
+
+#include <string>
+#include <list>
+#include <vector>
+#include "stdio.h"
+
+/*
+ * BC - Status (2002-03-08): NamedStore
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. These are part of the implementation of object.cc and not
+ * to be used elsewhere.
+ */
+
+namespace Arts {
+
+/**
+ * -- internal class --
+ *
+ * this stores key-value pairs, where key is a string which is kept unique
+ */
+template<class T>
+class NamedStore
+{
+private:
+ class Element {
+ public:
+ T t;
+ std::string name;
+
+ Element(const T& t, const std::string& name) :t(t), name(name) { }
+ };
+ typedef std::list<Element> Element_list;
+ Element_list elements;
+
+public:
+ bool get(const std::string& name, T& result)
+ {
+ typename Element_list::iterator i;
+ for(i = elements.begin(); i != elements.end(); i++)
+ {
+ if(i->name == name)
+ {
+ result = i->t;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ bool remove(const std::string& name)
+ {
+ typename Element_list::iterator i;
+ for(i = elements.begin(); i != elements.end(); i++)
+ {
+ if(i->name == name)
+ {
+ elements.erase(i);
+ return true;
+ }
+ }
+ return false;
+ }
+ std::vector<std::string> *contents()
+ {
+ std::vector<std::string> *result = new std::vector<std::string>;
+
+ typename Element_list::iterator i;
+ for(i = elements.begin(); i != elements.end(); i++)
+ result->push_back(i->name);
+
+ return result;
+ }
+ std::string put(const std::string& name, const T& t)
+ {
+ std::string xname = name;
+ int append = 1;
+
+ for(;;)
+ {
+ typename Element_list::iterator i;
+
+ i = elements.begin();
+ while(i != elements.end() && i->name != xname)
+ i++;
+
+ if(i == elements.end())
+ {
+ elements.push_back(Element(t,xname));
+ return xname;
+ }
+
+ char buffer[1024];
+ sprintf(buffer,"%d",append++);
+ xname = name + std::string(buffer);
+ }
+ }
+};
+
+}
+#endif /* ARTS_NAMEDSTORE_H */
diff --git a/mcop/notification.cc b/mcop/notification.cc
new file mode 100644
index 0000000..3fd70d1
--- /dev/null
+++ b/mcop/notification.cc
@@ -0,0 +1,101 @@
+ /*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "notification.h"
+#include "debug.h"
+#include "dispatcher.h"
+
+using namespace Arts;
+
+void NotificationClient::notify(const Notification&)
+{
+}
+
+NotificationManager::NotificationManager()
+{
+ arts_assert(!instance);
+ instance = this;
+}
+
+NotificationManager::~NotificationManager()
+{
+ arts_assert(instance);
+ instance = 0;
+}
+
+void NotificationManager::send(Notification wm)
+{
+ if (todo.empty()) {
+ // HACK: in order to not add a virtual function to IOManager we're calling addTimer with
+ // magic values. This call tells the ioManager that notifications are pending and
+ // NotificationManager::run() should get called soon.
+ Arts::Dispatcher::the()->ioManager()->addTimer(-1, 0);
+ }
+ todo.push(wm);
+}
+
+bool NotificationManager::run()
+{
+ if(todo.empty()) return false;
+
+ while(!todo.empty())
+ {
+ Notification wm = todo.front();
+ todo.pop();
+
+ /*
+ * we'll copy and remove the notification first, to be sure that
+ * nothing bad happens to it if we rebuild "todo" (for instance in
+ * removeClient)
+ */
+ wm.receiver->notify(wm);
+ }
+ return true;
+}
+
+void NotificationManager::removeClient(NotificationClient *client)
+{
+ std::queue<Notification> newTodo;
+
+ while(!todo.empty())
+ {
+ const Notification& n = todo.front();
+ if(n.receiver != client)
+ newTodo.push(n);
+ else
+ {
+ arts_debug("NotificationManager: removing one notification");
+ NotificationDestroyFunction destroy =
+ (NotificationDestroyFunction)n.internal;
+ if(destroy) destroy(n);
+ }
+ todo.pop();
+ }
+ todo = newTodo;
+}
+
+void Notification::setDestroy(NotificationDestroyFunction destroy)
+{
+ internal = (void*)destroy;
+}
+
+NotificationManager *NotificationManager::instance = 0;
diff --git a/mcop/notification.h b/mcop/notification.h
new file mode 100644
index 0000000..6a8582f
--- /dev/null
+++ b/mcop/notification.h
@@ -0,0 +1,87 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef NOTIFICATION_H
+#define NOTIFICATION_H
+
+#include <queue>
+#include "arts_export.h"
+
+namespace Arts {
+
+/*
+ * BC - Status (2002-03-08): Notification, NotificationClient,
+ * NotificationManager
+ *
+ * All need to be kept BC, NotificationManager with usual d ptr.
+ *
+ * Notifications have to be FAST. Currently, they use ID, data & receiver.
+ * However, there may be future extensions. For this, one more internal
+ * field is provided. Set it to ZERO currently when sending notifications.
+ */
+
+struct Notification;
+typedef void (*NotificationDestroyFunction)(const Notification& n);
+
+struct Notification {
+ class NotificationClient *receiver;
+ int ID;
+ void *data;
+ void *internal; /* handle with care, equivalent to private d ptr */
+
+ void setDestroy(NotificationDestroyFunction destroy);
+};
+
+class ARTS_EXPORT NotificationClient {
+public:
+ virtual void notify(const Notification& wm);
+};
+
+class NotificationManagerPrivate;
+class ARTS_EXPORT NotificationManager {
+private:
+ NotificationManagerPrivate *d; // unused
+protected:
+ std::queue<Notification> todo;
+ static NotificationManager *instance;
+
+public:
+ NotificationManager();
+ ~NotificationManager();
+
+ static inline NotificationManager *the()
+ {
+ return instance;
+ }
+ void send(Notification wm);
+ inline bool pending()
+ {
+ return !todo.empty();
+ }
+ bool run();
+ void removeClient(NotificationClient *client);
+
+};
+
+}
+
+#endif /* NOTIFICATION_H */
diff --git a/mcop/object.cc b/mcop/object.cc
new file mode 100644
index 0000000..9f01912
--- /dev/null
+++ b/mcop/object.cc
@@ -0,0 +1,1528 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "object.h"
+#include "dispatcher.h"
+#include "flowsystem.h"
+#include "weakreference.h"
+#include "namedstore.h"
+#include "debug.h"
+#include "anyref.h"
+#include <stdio.h>
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+ class AttributeSlotBind;
+}
+
+class Arts::ObjectInternalData {
+public:
+ struct MethodTableEntry {
+ union {
+ DispatchFunction dispatcher;
+ OnewayDispatchFunction onewayDispatcher;
+ DynamicDispatchFunction dynamicDispatcher;
+ } dispFunc;
+ enum { dfNormal, dfOneway, dfDynamic } dispatchStyle;
+ void *object;
+ MethodDef methodDef;
+ };
+
+ list<WeakReferenceBase *> weakReferences;
+ NamedStore<Arts::Object> children;
+ bool stubForLocalObject;
+
+ // for _skel classes only:
+ bool methodTableInit;
+ std::vector<MethodTableEntry> methodTable;
+ list<AttributeSlotBind *> attributeSlots;
+};
+
+struct Object_base::ObjectStreamInfo {
+ string name;
+ long flags;
+ void *ptr;
+};
+
+/*****************************************************************************/
+/* the following methods/classes are necessary for attribute notifications */
+/*****************************************************************************/
+
+namespace Arts {
+ class AttributeDataPacket : public GenericDataPacket {
+ public:
+ Buffer b;
+ AttributeDataPacket(GenericDataChannel *channel)
+ : GenericDataPacket(channel)
+ {
+ size = 0;
+ b.writeLong(0);
+ }
+ void add(const AnyConstRef& r)
+ {
+ r.write(&b);
+ b.patchLong(0,++size);
+ }
+
+ void ensureCapacity(int)
+ {
+ }
+ void read(Buffer& stream)
+ {
+ vector<mcopbyte> all;
+ size = stream.readLong();
+ b.patchLong(0,size);
+ stream.read(all,stream.remaining());
+ b.write(all);
+ }
+ void write(Buffer& stream)
+ {
+ vector<mcopbyte> all;
+ b.rewind();
+ b.read(all,b.remaining());
+ stream.write(all);
+ }
+ };
+ class AttributeSlotBind : public GenericAsyncStream {
+ public:
+ GenericDataPacket *createPacket(int)
+ {
+ return allocPacket();
+ }
+ AttributeDataPacket *allocPacket()
+ {
+ return new AttributeDataPacket(channel);
+ }
+
+ void freePacket(GenericDataPacket *packet)
+ {
+ delete packet;
+ }
+
+ GenericAsyncStream *createNewStream()
+ {
+ return new AttributeSlotBind();
+ }
+
+ virtual ~AttributeSlotBind()
+ {
+ }
+
+ string method;
+ bool output;
+ };
+}
+
+bool Object_skel::_initAttribute(const AttributeDef& attribute)
+{
+ long flags = attribute.flags;
+
+ if(flags & attributeAttribute)
+ {
+ flags |= attributeStream | streamAsync;
+ flags &= ~attributeAttribute;
+ }
+ else
+ {
+ arts_warning("attribute init on stream %s", attribute.name.c_str());
+ return false;
+ }
+
+ list<AttributeSlotBind *>::iterator i;
+ for(i = _internalData->attributeSlots.begin();
+ i != _internalData->attributeSlots.end(); i++)
+ {
+ AttributeSlotBind *b = *i;
+ if(b->method == "_set_"+attribute.name
+ || b->method == attribute.name + "_changed")
+ {
+ arts_warning("double attribute init %s",b->method.c_str());
+ return false;
+ }
+ }
+ if(flags & streamIn)
+ {
+ AttributeSlotBind *b = new AttributeSlotBind();
+ b->output = false;
+ b->method = "_set_"+attribute.name;
+ _internalData->attributeSlots.push_back(b);
+
+ _scheduleNode->initStream(attribute.name, b, flags & (~streamOut));
+ }
+ if(flags & streamOut)
+ {
+ string changed = attribute.name + "_changed";
+ AttributeSlotBind *b = new AttributeSlotBind();
+ b->output = true;
+ b->method = changed;
+ _internalData->attributeSlots.push_back(b);
+
+ _scheduleNode->initStream(changed, b, flags & (~streamIn));
+ }
+ return true;
+}
+
+void Object_skel::_defaultNotify(const Notification& notification)
+{
+ list<AttributeSlotBind *>::iterator i;
+ list<AttributeSlotBind *>& slots = _internalData->attributeSlots;
+
+ for(i = slots.begin(); i != slots.end(); i++)
+ {
+ if((*i)->notifyID() == notification.ID)
+ {
+ GenericDataPacket *dp = (GenericDataPacket *)notification.data;
+ Buffer params;
+
+ dp->write(params);
+
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+
+ typedef ObjectInternalData::MethodTableEntry MTE;
+ vector<MTE>::iterator mti;
+
+ for(mti = _internalData->methodTable.begin();
+ mti != _internalData->methodTable.end(); mti++)
+ {
+ if(mti->methodDef.name == (*i)->method)
+ {
+ Buffer result;
+
+ long count = params.readLong();
+ while(params.remaining())
+ {
+ if(mti->dispatchStyle == MTE::dfNormal)
+ {
+ mti->dispFunc.dispatcher(mti->object, &params, &result);
+ }
+ else if(mti->dispatchStyle == MTE::dfDynamic)
+ {
+ long methodID;
+ methodID = mti - _internalData->methodTable.begin();
+ mti->dispFunc.dynamicDispatcher(mti->object, methodID,
+ &params, &result);
+ }
+ else
+ {
+ arts_assert(0);
+ }
+ count--;
+ }
+ arts_assert(count == 0);
+ }
+ }
+ dp->processed();
+ }
+ }
+}
+
+void Object_skel::notify(const Notification& notification)
+{
+ _copy();
+ _defaultNotify(notification);
+ _release();
+}
+
+/* for simplicity and efficiency, enums are emitted as normal "long" values,
+ * so that finding out/using the enum type via value.type() is not be possible
+ */
+void Object_skel::_emit_changed(const char *attrib, const AnyConstRef& value)
+{
+ list<AttributeSlotBind *>::iterator i;
+ list<AttributeSlotBind *>& slots = _internalData->attributeSlots;
+
+ for(i = slots.begin(); i != slots.end(); i++)
+ {
+ if((*i)->method == attrib)
+ {
+ AttributeDataPacket *adp =
+ (AttributeDataPacket *)(*i)->createPacket(1);
+ adp->add(value);
+ adp->send();
+ return;
+ }
+ }
+}
+
+
+bool Object_skel::_generateSlots(const std::string& name,
+ const std::string& interface)
+{
+ InterfaceDef d = _queryInterface(interface);
+ vector<string>::iterator ii;
+ for(ii = d.inheritedInterfaces.begin();
+ ii != d.inheritedInterfaces.end(); ii++)
+ {
+ if(_generateSlots(name, *ii)) return true;
+ }
+
+ vector<AttributeDef>::iterator ai;
+ for(ai = d.attributes.begin(); ai != d.attributes.end(); ai++)
+ {
+ if(ai->flags & attributeAttribute)
+ {
+ if((ai->flags & streamIn && ai->name == name)
+ || (ai->flags & streamOut && ai->name+"_changed" == name))
+ {
+ _initAttribute(*ai);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Object_skel::_QueryInitStreamFunc(Object_skel *skel, const
+ std::string& name)
+{
+ /*
+ * this function
+ *
+ * checks if there is a stream which should be added called <name>,
+ * and returns true if it in fact added a stream, so that requesting
+ * function needs to retry
+ */
+ bool result = skel->_generateSlots(name, skel->_interfaceName());
+ if(!result)
+ {
+ arts_warning("used stream %s on object %s, which doesn't seem to exist",
+ name.c_str(), skel->_interfaceName().c_str());
+ }
+ return result;
+}
+
+/*****************************************************************************/
+
+
+/*
+ * Object: common for every object
+ */
+
+long Object_base::_staticObjectCount = 0;
+
+Object_base::Object_base() : _deleteOk(false), _scheduleNode(0), _nextNotifyID(1),
+ _refCnt(1)
+{
+ _internalData = new Arts::ObjectInternalData();
+ _internalData->stubForLocalObject = false;
+ _staticObjectCount++;
+}
+
+void Object_base::_destroy()
+{
+ _deleteOk = true;
+
+ if(_scheduleNode && !_internalData->stubForLocalObject)
+ {
+ if(_scheduleNode->remoteScheduleNode())
+ {
+ delete _scheduleNode;
+ }
+ else
+ {
+ FlowSystem_impl *fs = Dispatcher::the()->flowSystem();
+ assert(fs);
+
+ fs->removeObject(_scheduleNode);
+ }
+ }
+ delete this;
+}
+
+Object_base::~Object_base()
+{
+ if(!_deleteOk)
+ {
+ arts_fatal("reference counting violation - you may not call delete "
+ "manually - use _release() instead");
+ }
+ assert(_deleteOk);
+
+ /* remove attribute slots */
+ list<AttributeSlotBind *>::iterator ai;
+ for(ai = _internalData->attributeSlots.begin();
+ ai != _internalData->attributeSlots.end(); ai++)
+ {
+ delete (*ai);
+ }
+
+ /* clear stream list */
+ list<ObjectStreamInfo *>::iterator osii;
+ for(osii = _streamList.begin(); osii != _streamList.end(); osii++)
+ delete (*osii);
+
+ /* inform weak references that we don't exist any longer */
+ while(!_internalData->weakReferences.empty())
+ _internalData->weakReferences.front()->release();
+
+ /* inform notification manager that we don't exist any longer */
+ NotificationManager::the()->removeClient(this);
+
+ delete _internalData;
+ _staticObjectCount--;
+}
+
+ScheduleNode *Object_base::_node()
+{
+ if(!_scheduleNode)
+ {
+ switch(_location())
+ {
+ case objectIsLocal:
+ {
+ FlowSystem_impl *fs = Dispatcher::the()->flowSystem();
+ assert(fs);
+ _scheduleNode = fs->addObject(_skel());
+
+ /* init streams */
+
+ list<ObjectStreamInfo *>::iterator osii;
+ for(osii = _streamList.begin(); osii != _streamList.end(); osii++)
+ {
+ _scheduleNode->initStream((*osii)->name,(*osii)->ptr,(*osii)->flags);
+ }
+ _scheduleNode->initStream("QueryInitStreamFunc",
+ (void *)Object_skel::_QueryInitStreamFunc, -1);
+ }
+ break;
+
+ case objectIsRemote:
+ {
+ /*
+ * if we're just a stub to an object that is local inside
+ * this process, then we don't create a new schedule node,
+ * but find the one associated with the implementation
+ *
+ * (this happens for instance for objects implemented as
+ * artsbuilder structures)
+ */
+ if(_internalData->stubForLocalObject)
+ {
+ Dispatcher *disp = Dispatcher::the();
+ Object_skel *localObject;
+
+ localObject = disp->getLocalObject(_stub()->_objectID);
+ arts_assert(localObject);
+
+ _scheduleNode = localObject->_node();
+ localObject->_release();
+ }
+ else
+ {
+ _scheduleNode = new RemoteScheduleNode(_stub());
+ }
+ }
+ break;
+ }
+
+ assert(_scheduleNode);
+ }
+ return _scheduleNode;
+}
+
+bool Object_base::_isEqual(Object_base *object) const
+{
+ return (_internalObjectID == object->_internalObjectID);
+}
+
+void *Object_base::_cast(unsigned long iid)
+{
+ if(iid == Object_base::_IID) return (Object *)this;
+ return 0;
+}
+
+void *Object_base::_cast(const std::string& interface)
+{
+ return _cast(MCOPUtils::makeIID(interface));
+}
+
+bool Object_base::_error()
+{
+ // no error as default ;)
+ return false;
+}
+
+Object_skel *Object_base::_skel()
+{
+ assert(false);
+ return 0;
+}
+
+Object_stub *Object_base::_stub()
+{
+ assert(false);
+ return 0;
+}
+
+Object_stub *Object_stub::_stub()
+{
+ return this;
+}
+
+Object_base::ObjectLocation Object_stub::_location() const
+{
+ return objectIsRemote;
+}
+
+Object_skel *Object_skel::_skel()
+{
+ return this;
+}
+
+Object_base::ObjectLocation Object_skel::_location() const
+{
+ return objectIsLocal;
+}
+
+void Object_skel::_initStream(const string& name, void *ptr, long flags)
+{
+ ObjectStreamInfo *osi = new ObjectStreamInfo;
+ osi->name = name;
+ osi->ptr = ptr;
+ osi->flags = flags;
+ _streamList.push_back(osi);
+}
+
+void Object_base::calculateBlock(unsigned long)
+{
+}
+
+string Object_base::_interfaceName()
+{
+ assert(0); // derived classes *must* override this
+ return "";
+}
+
+Buffer *Object_base::_allocCustomMessage(long /*handlerID*/)
+{
+ assert(0);
+ return 0;
+}
+
+void Object_base::_sendCustomMessage(Buffer *buffer)
+{
+ assert(0);
+ delete buffer;
+}
+
+// Default I/O: nothing at this level, use child virtuals
+vector<std::string> Object_base::_defaultPortsIn() const
+{
+ vector<std::string> ret;
+ return ret;
+}
+vector<std::string> Object_base::_defaultPortsOut() const
+{
+ vector<std::string> ret;
+ return ret;
+}
+
+// Weak References
+
+void Object_base::_addWeakReference(WeakReferenceBase *b)
+{
+ _internalData->weakReferences.push_back(b);
+}
+
+void Object_base::_removeWeakReference(WeakReferenceBase *b)
+{
+ _internalData->weakReferences.remove(b);
+}
+
+/*
+ * Stuff for object skeletons
+ */
+
+Object_skel::Object_skel() :_remoteSendCount(0), _remoteSendUpdated(false)
+{
+ _objectID = Dispatcher::the()->addObject(this);
+ _connection = Dispatcher::the()->loopbackConnection();
+ _internalData->methodTableInit = false;
+
+/* big enough for our header + 0x + needed number of hex characters + ending NULL */
+ char ioid[7 + 2*sizeof(void *)+1];
+ sprintf(ioid,"SKEL:%p",(void *)this);
+ _internalObjectID = ioid;
+}
+
+Object_skel::~Object_skel()
+{
+ Dispatcher::the()->removeObject(_objectID);
+}
+
+// flow system
+
+FlowSystem Object_skel::_flowSystem()
+{
+ FlowSystem_base *fs = Dispatcher::the()->flowSystem();
+ if(fs)
+ return FlowSystem::_from_base(fs->_copy());
+ else
+ return FlowSystem::null();
+}
+
+// reference counting
+
+void Object_skel::_release()
+{
+ arts_return_if_fail(_refCnt > 0);
+
+ _refCnt--;
+ if(_refCnt == 0) _destroy();
+}
+
+void Object_skel::_copyRemote()
+{
+ // cout << "_copyRemote();" << endl;
+
+ _copy();
+ _remoteSendCount++;
+ _remoteSendUpdated = true;
+}
+
+void Object_skel::_releaseRemote()
+{
+ //cout << "_releaseRemote();" << endl;
+
+ Connection *conn = Dispatcher::the()->activeConnection();
+ list<Connection *>::iterator i;
+ bool found = false;
+
+ for(i=_remoteUsers.begin(); !found && i != _remoteUsers.end(); i++)
+ {
+ found = (*i) == conn;
+ if(found)
+ {
+ _remoteUsers.erase(i);
+ break;
+ }
+ }
+ assert(found);
+ _release();
+}
+
+void Object_skel::_useRemote()
+{
+ //cout << "_useRemote();" << endl;
+
+ Connection *conn = Dispatcher::the()->activeConnection();
+ if(_remoteSendCount == 0)
+ {
+ arts_warning("_useRemote without prior _copyRemote() - this might fail sometimes");
+ _copyRemote();
+ }
+
+ _remoteSendCount--;
+ _remoteUsers.push_back(conn);
+}
+
+/*
+ * This is needed when we've received an object from wire which we now
+ * hold locally. Of course it has been _copyRemote()d (rightly so), but
+ * we will not use it remotely, so we need to cancel the _copyRemote().
+ *
+ * Added to _base due to BC.
+ */
+void Object_base::_cancelCopyRemote()
+{
+ assert(_location() == objectIsLocal);
+
+ if(_skel()->_remoteSendCount == 0)
+ {
+ arts_warning("_cancelCopyRemote without prior _copyRemote() - this might fail sometimes");
+ }
+ else
+ {
+ _skel()->_remoteSendCount--;
+ _release();
+ }
+}
+
+void Object_skel::_disconnectRemote(Connection *conn)
+{
+ //cout << "_disconnectRemote();" << endl;
+
+ int rcount = 0;
+ list<Connection *>::iterator i;
+
+ i=_remoteUsers.begin();
+ while(i != _remoteUsers.end())
+ {
+ if((*i) == conn)
+ {
+ _remoteUsers.erase(i);
+ i = _remoteUsers.begin();
+ rcount++;
+ }
+ else i++;
+ }
+
+ while(rcount) {
+ arts_debug("client disconnected: dropped one object reference");
+ rcount--;
+ _release();
+ }
+ /* warning: object may not exist any longer here */
+}
+
+void Object_skel::_referenceClean()
+{
+ if(_remoteSendCount > 0)
+ {
+ if(_remoteSendUpdated)
+ {
+ // this ensures that every client gets at least five
+ // seconds to connect
+ _remoteSendUpdated = false;
+ }
+ else
+ {
+ int rcount = _remoteSendCount;
+
+ arts_debug("_referenceClean: found unused object marked by "
+ "_copyRemote => releasing");
+
+ while(rcount--)
+ {
+ _remoteSendCount--;
+ _release();
+ }
+ }
+ /* warning: object may be gone here */
+ }
+}
+
+string Object_skel::_toString()
+{
+ return Dispatcher::the()->objectToString(_objectID);
+}
+
+string Object_skel::_interfaceName()
+{
+ assert(0); // derived classes *must* override this
+ return "";
+}
+
+string Object_skel::_interfaceNameSkel()
+{
+ // derived classes *must* override this, but we return a sane value here
+ // anyway, because DynamicSkeleton depends on this
+ return "Arts::Object";
+}
+
+bool Object_skel::_isCompatibleWith(const std::string& interfacename)
+{
+ if (interfacename=="Arts::Object") return true;
+ return false;
+}
+
+InterfaceDef Object_skel::_queryInterface(const string& name)
+{
+ return Dispatcher::the()->interfaceRepo().queryInterface(name);
+}
+
+TypeDef Object_skel::_queryType(const string& name)
+{
+ return Dispatcher::the()->interfaceRepo().queryType(name);
+}
+
+EnumDef Object_skel::_queryEnum(const string& name)
+{
+ return Dispatcher::the()->interfaceRepo().queryEnum(name);
+}
+
+// Aggregation
+std::string Object_skel::_addChild(Arts::Object child, const std::string& name)
+{
+ return _internalData->children.put(name,child);
+}
+
+bool Object_skel::_removeChild(const std::string& name)
+{
+ return _internalData->children.remove(name);
+}
+
+Arts::Object Object_skel::_getChild(const std::string& name)
+{
+ Arts::Object result;
+ if(_internalData->children.get(name,result))
+ return result;
+ else
+ return Arts::Object::null();
+}
+
+std::vector<std::string> *Object_skel::_queryChildren()
+{
+ return _internalData->children.contents();
+}
+
+void Object_skel::_addMethod(DispatchFunction disp, void *obj,
+ const MethodDef& md)
+{
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.dispatcher = disp;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfNormal;
+ me.object = obj;
+ me.methodDef = md;
+ _internalData->methodTable.push_back(me);
+}
+
+void Object_skel::_addMethod(OnewayDispatchFunction disp, void *obj,
+ const MethodDef& md)
+{
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.onewayDispatcher = disp;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfOneway;
+ me.object = obj;
+ me.methodDef = md;
+ _internalData->methodTable.push_back(me);
+}
+
+void Object_skel::_addMethod(DynamicDispatchFunction disp, void *obj,
+ const MethodDef& md)
+{
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.dynamicDispatcher = disp;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfDynamic;
+ me.object = obj;
+ me.methodDef = md;
+ _internalData->methodTable.push_back(me);
+}
+
+
+long Object_skel::_addCustomMessageHandler(OnewayDispatchFunction handler,
+ void *obj)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+ Arts::ObjectInternalData::MethodTableEntry me;
+ me.dispFunc.onewayDispatcher = handler;
+ me.dispatchStyle = ObjectInternalData::MethodTableEntry::dfOneway;
+ me.object = obj;
+ me.methodDef.name = "_userdefined_customdatahandler";
+ _internalData->methodTable.push_back(me);
+ return _internalData->methodTable.size()-1;
+}
+
+void Object_skel::_dispatch(Buffer *request, Buffer *result,long methodID)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+
+ const ObjectInternalData::MethodTableEntry& me
+ = _internalData->methodTable[methodID];
+
+ if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfNormal)
+ me.dispFunc.dispatcher(me.object, request, result);
+ else if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfDynamic)
+ me.dispFunc.dynamicDispatcher(me.object, methodID, request, result);
+ else
+ {
+ arts_assert(0);
+ }
+}
+
+void Object_skel::_dispatch(Buffer *request,long methodID)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+ const ObjectInternalData::MethodTableEntry& me
+ = _internalData->methodTable[methodID];
+
+ if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfOneway)
+ me.dispFunc.onewayDispatcher(me.object, request);
+ else if(me.dispatchStyle == ObjectInternalData::MethodTableEntry::dfDynamic)
+ me.dispFunc.dynamicDispatcher(me.object, methodID, request, 0);
+ else
+ {
+ arts_assert(0);
+ }
+}
+
+long Object_skel::_lookupMethod(const MethodDef& md)
+{
+ long mcount = 0;
+
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+
+ vector<Arts::ObjectInternalData::MethodTableEntry>::iterator i;
+ for(i=_internalData->methodTable.begin(); i != _internalData->methodTable.end(); i++)
+ {
+ MethodDef& mdm = i->methodDef;
+ if(mdm.name == md.name && mdm.type == md.type)
+ {
+ /* TODO: compare signature
+ vector<ParamDef *>::const_iterator j,k;
+ j = md.signature.begin();
+ k = mdm.signature.begin();
+ while(j != md.signature.end() && (*j) == (*k))
+ {
+ j++;
+ k++;
+ }
+
+ if(j == md.signature.end() && k == mdm.signature.end())
+ */
+ return mcount;
+ }
+ mcount++;
+ }
+ arts_warning("_lookupMethod %s %s failed this might be caused by "
+ "incompatible IDL files and is likely to result in crashes",
+ md.type.c_str(),md.name.c_str());
+ return -1;
+}
+
+const MethodDef& Object_skel::_dsGetMethodDef(long methodID)
+{
+ if(!_internalData->methodTableInit)
+ {
+ // take care that the object base methods are at the beginning
+ Object_skel::_buildMethodTable();
+ _buildMethodTable();
+ _internalData->methodTableInit = true;
+ }
+ return _internalData->methodTable[methodID].methodDef;
+}
+
+// _lookupMethod
+static void _dispatch_Arts_Object_00(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::MethodDef methodDef(*request);
+ result->writeLong(((Arts::Object_skel *)object)->_lookupMethod(methodDef));
+}
+
+// _interfaceName
+static void _dispatch_Arts_Object_01(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::Object_skel *)object)->_interfaceName());
+}
+
+// _queryInterface
+static void _dispatch_Arts_Object_02(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::InterfaceDef _returnCode = ((Arts::Object_skel *)object)->_queryInterface(name);
+ _returnCode.writeType(*result);
+}
+
+// _queryType
+static void _dispatch_Arts_Object_03(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::TypeDef _returnCode = ((Arts::Object_skel *)object)->_queryType(name);
+ _returnCode.writeType(*result);
+}
+
+// _queryEnum
+static void _dispatch_Arts_Object_04(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::EnumDef _returnCode = ((Arts::Object_skel *)object)->_queryEnum(name);
+ _returnCode.writeType(*result);
+}
+
+// _toString
+static void _dispatch_Arts_Object_05(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ result->writeString(((Arts::Object_skel *)object)->_toString());
+}
+
+// _isCompatibleWith
+static void _dispatch_Arts_Object_06(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string interfacename;
+ request->readString(interfacename);
+ result->writeBool(((Arts::Object_skel *)object)->_isCompatibleWith(interfacename));
+}
+
+// _copyRemote
+static void _dispatch_Arts_Object_07(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::Object_skel *)object)->_copyRemote();
+}
+
+// _useRemote
+static void _dispatch_Arts_Object_08(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::Object_skel *)object)->_useRemote();
+}
+
+// _releaseRemote
+static void _dispatch_Arts_Object_09(void *object, Arts::Buffer *, Arts::Buffer *)
+{
+ ((Arts::Object_skel *)object)->_releaseRemote();
+}
+
+// _addChild
+static void _dispatch_Arts_Object_10(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ Arts::Object_base* _temp_child;
+ readObject(*request,_temp_child);
+ Arts::Object child = Arts::Object::_from_base(_temp_child);
+ std::string name;
+ request->readString(name);
+ result->writeString(((Arts::Object_skel *)object)->_addChild(child,name));
+}
+
+// _removeChild
+static void _dispatch_Arts_Object_11(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ result->writeBool(((Arts::Object_skel *)object)->_removeChild(name));
+}
+
+// _getChild
+static void _dispatch_Arts_Object_12(void *object, Arts::Buffer *request, Arts::Buffer *result)
+{
+ std::string name;
+ request->readString(name);
+ Arts::Object returnCode = ((Arts::Object_skel *)object)->_getChild(name);
+ writeObject(*result,returnCode._base());
+}
+
+// _queryChildren
+static void _dispatch_Arts_Object_13(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ std::vector<std::string> *_returnCode = ((Arts::Object_skel *)object)->_queryChildren();
+ result->writeStringSeq(*_returnCode);
+ delete _returnCode;
+}
+
+// _get__flowSystem
+static void _dispatch_Arts_Object_14(void *object, Arts::Buffer *, Arts::Buffer *result)
+{
+ Arts::FlowSystem returnCode = ((Arts::Object_skel *)object)->_flowSystem();
+ writeObject(*result,returnCode._base());
+}
+
+void Arts::Object_skel::_buildMethodTable()
+{
+ Arts::Buffer m;
+ m.fromString(
+ "MethodTable:0000000e5f6c6f6f6b75704d6574686f6400000000056c6f6e6700"
+ "000000020000000100000010417274733a3a4d6574686f64446566000000000a6d"
+ "6574686f644465660000000000000000000000000f5f696e746572666163654e61"
+ "6d650000000007737472696e6700000000020000000000000000000000105f7175"
+ "657279496e746572666163650000000013417274733a3a496e7465726661636544"
+ "656600000000020000000100000007737472696e6700000000056e616d65000000"
+ "0000000000000000000b5f717565727954797065000000000e417274733a3a5479"
+ "706544656600000000020000000100000007737472696e6700000000056e616d65"
+ "0000000000000000000000000b5f7175657279456e756d000000000e417274733a"
+ "3a456e756d44656600000000020000000100000007737472696e6700000000056e"
+ "616d650000000000000000000000000a5f746f537472696e670000000007737472"
+ "696e6700000000020000000000000000000000125f6973436f6d70617469626c65"
+ "576974680000000008626f6f6c65616e0000000002000000010000000773747269"
+ "6e67000000000e696e746572666163656e616d650000000000000000000000000c"
+ "5f636f707952656d6f74650000000005766f696400000000020000000000000000"
+ "0000000b5f75736552656d6f74650000000005766f696400000000020000000000"
+ "0000000000000f5f72656c6561736552656d6f74650000000005766f6964000000"
+ "000200000000000000000000000a5f6164644368696c640000000007737472696e"
+ "67000000000200000002000000076f626a65637400000000066368696c64000000"
+ "000000000007737472696e6700000000056e616d65000000000000000000000000"
+ "0d5f72656d6f76654368696c640000000008626f6f6c65616e0000000002000000"
+ "0100000007737472696e6700000000056e616d650000000000000000000000000a"
+ "5f6765744368696c6400000000076f626a65637400000000020000000100000007"
+ "737472696e6700000000056e616d650000000000000000000000000f5f71756572"
+ "794368696c6472656e00000000082a737472696e67000000000200000000000000"
+ "00000000115f6765745f5f666c6f7753797374656d0000000011417274733a3a46"
+ "6c6f7753797374656d00000000020000000000000000",
+ "MethodTable"
+ );
+ _addMethod(_dispatch_Arts_Object_00,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_01,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_02,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_03,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_04,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_05,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_06,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_07,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_08,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_09,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_10,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_11,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_12,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_13,this,Arts::MethodDef(m));
+ _addMethod(_dispatch_Arts_Object_14,this,Arts::MethodDef(m));
+}
+
+/*
+ * Stuff for object stubs
+ */
+
+Object_stub::Object_stub()
+{
+ assert(0); // never use this constructor, as it doesn't assign an object ID
+}
+
+Object_stub::Object_stub(Connection *connection, long objectID)
+{
+ _connection = connection;
+ _connection->_copy();
+ _objectID = objectID;
+ _lookupCacheRandom = rand();
+
+ if(_connection == Dispatcher::the()->loopbackConnection())
+ _internalData->stubForLocalObject = true;
+
+ char ioid[128];
+ sprintf(ioid,"STUB:%ld:%p",_objectID,(void *)connection);
+ _internalObjectID = ioid;
+}
+
+Object_stub::~Object_stub()
+{
+ /*
+ * invalidate method lookup cache entries of this object, as it might
+ * happen, that another Object_stub is created just at the same position
+ */
+ if(_lookupMethodCache)
+ {
+ for(long p=0;p<_lookupMethodCacheSize;p++)
+ {
+ if(_lookupMethodCache[p].obj == this)
+ _lookupMethodCache[p].obj = NULL;
+ }
+ }
+ _connection->_release();
+}
+
+bool Object_stub::_error()
+{
+ /*
+ * servers are trustworthy - they don't do things wrong (e.g. send
+ * wrong buffers or things like that) - however, if the connection is
+ * lost, this indicates that something went terrible wrong (probably
+ * the remote server crashed, or maybe the network is dead), and you
+ * can't rely on results of invocations any longer
+ */
+ return _connection->broken();
+}
+
+void Object_stub::_release()
+{
+ arts_return_if_fail(_refCnt > 0);
+
+ _refCnt--;
+ if(_refCnt == 0)
+ {
+ _releaseRemote();
+ _destroy();
+ }
+}
+
+Object_base *Object_base::_create(const std::string& subClass)
+{
+ Object_skel *skel = ObjectManager::the()->create(subClass);
+ assert(skel);
+ return skel;
+}
+
+Object_base *Object_base::_fromString(const string& objectref)
+{
+ Object_base *result = 0;
+ ObjectReference r;
+
+ if(Dispatcher::the()->stringToObjectReference(r,objectref))
+ {
+ result = (Object_base *)Dispatcher::the()->connectObjectLocal(r,"Object");
+ if(!result)
+ {
+ Connection *conn = Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Object_stub(conn,r.objectID);
+ result->_useRemote();
+ }
+ }
+ }
+ return result;
+}
+
+Object_base *Object_base::_fromReference(ObjectReference r, bool needcopy)
+{
+ Object_base *result;
+ result = (Object_base *)Dispatcher::the()->connectObjectLocal(r,"Object");
+ if(result)
+ {
+ if(!needcopy)
+ result->_cancelCopyRemote();
+ }
+ else
+ {
+ Connection *conn = Dispatcher::the()->connectObjectRemote(r);
+ if(conn)
+ {
+ result = new Object_stub(conn,r.objectID);
+ if(needcopy) result->_copyRemote();
+ result->_useRemote();
+ }
+ }
+ return result;
+}
+
+string Object_stub::_interfaceName()
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,1);
+ // methodID = 1 => _interfaceName (always)
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return ""; // error
+ string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+InterfaceDef Object_stub::_queryInterface(const string& name)
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,2);
+ // methodID = 2 => _queryInterface (always)
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return InterfaceDef(); // error
+ InterfaceDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+TypeDef Object_stub::_queryType(const string& name)
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,3);
+ // methodID = 3 => _queryType (always)
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return TypeDef(); // error
+ TypeDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+EnumDef Object_stub::_queryEnum(const string& name)
+{
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,4);
+ // methodID = 4 => _queryEnum (always)
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return EnumDef(); // error occurred
+ EnumDef _returnCode(*result);
+ delete result;
+ return _returnCode;
+}
+
+long Object_stub::_lookupMethod(const MethodDef& methodDef)
+{
+ long requestID;
+ Buffer *request, *result;
+ request = Dispatcher::the()->createRequest(requestID,_objectID,0);
+ // methodID = 0 => _lookupMethod (always)
+ methodDef.writeType(*request);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return 0; // error
+ long returnCode = result->readLong();
+ delete result;
+ return returnCode;
+}
+
+Object_stub::methodCacheEntry *Object_stub::_lookupMethodCache = 0;
+
+long Object_stub::_lookupMethodFast(const char *method)
+{
+ unsigned long c1 = (unsigned long)this;
+ unsigned long c2 = (unsigned long)method;
+ unsigned long pos = (c1^c2^_lookupCacheRandom)%_lookupMethodCacheSize;
+ /* FIXME this hashing method sucks. at a bare minimum, we're using only every 4th bin */
+
+ if(!_lookupMethodCache)
+ _lookupMethodCache = new methodCacheEntry[_lookupMethodCacheSize];
+
+ if(_lookupMethodCache[pos].obj == this && _lookupMethodCache[pos].method == method)
+ return _lookupMethodCache[pos].ID;
+
+ Buffer _methodBuffer;
+ _methodBuffer.fromString(method,"method");
+ long methodID = _lookupMethod(MethodDef(_methodBuffer));
+ //cout << "methodID = " << methodID << endl;
+
+ _lookupMethodCache[pos].obj = this;
+ _lookupMethodCache[pos].method = method;
+ _lookupMethodCache[pos].ID = methodID;
+ return methodID;
+}
+
+// other (normal) methods without fixed location
+
+std::string Arts::Object_stub::_toString()
+{
+ long methodID = _lookupMethodFast("method:0000000a5f746f537472696e670000000007737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+bool Arts::Object_stub::_isCompatibleWith(const std::string& interfacename)
+{
+ long methodID = _lookupMethodFast("method:000000125f6973436f6d70617469626c65576974680000000008626f6f6c65616e00000000020000000100000007737472696e67000000000e696e746572666163656e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(interfacename);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return false; // error occurred
+ bool returnCode = result->readBool();
+ delete result;
+ return returnCode;
+}
+
+void Arts::Object_stub::_copyRemote()
+{
+ long methodID = _lookupMethodFast("method:0000000c5f636f707952656d6f74650000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::Object_stub::_useRemote()
+{
+ long methodID = _lookupMethodFast("method:0000000b5f75736552656d6f74650000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+void Arts::Object_stub::_releaseRemote()
+{
+ long methodID = _lookupMethodFast("method:0000000f5f72656c6561736552656d6f74650000000005766f696400000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(result) delete result;
+}
+
+std::string Arts::Object_stub::_addChild(Arts::Object child, const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a5f6164644368696c640000000007737472696e67000000000200000002000000076f626a65637400000000066368696c64000000000000000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ writeObject(*request,child._base());
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return""; // error occurred
+ std::string returnCode;
+ result->readString(returnCode);
+ delete result;
+ return returnCode;
+}
+
+bool Arts::Object_stub::_removeChild(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000d5f72656d6f76654368696c640000000008626f6f6c65616e00000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if(!result) return false; // error occurred
+ bool returnCode = result->readBool();
+ delete result;
+ return returnCode;
+}
+
+Arts::Object Arts::Object_stub::_getChild(const std::string& name)
+{
+ long methodID = _lookupMethodFast("method:0000000a5f6765744368696c6400000000076f626a65637400000000020000000100000007737472696e6700000000056e616d65000000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->writeString(name);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::Object::null();
+ Arts::Object_base* returnCode;
+ readObject(*result,returnCode);
+ delete result;
+ return Arts::Object::_from_base(returnCode);
+}
+
+std::vector<std::string> * Arts::Object_stub::_queryChildren()
+{
+ long methodID = _lookupMethodFast("method:0000000f5f71756572794368696c6472656e00000000082a737472696e6700000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ std::vector<std::string> *_returnCode = new std::vector<std::string>;
+ if(!result) return _returnCode; // error occurred
+ result->readStringSeq(*_returnCode);
+ delete result;
+ return _returnCode;
+}
+
+Arts::FlowSystem Arts::Object_stub::_flowSystem()
+{
+ long methodID = _lookupMethodFast("method:000000115f6765745f5f666c6f7753797374656d0000000011417274733a3a466c6f7753797374656d00000000020000000000000000");
+ long requestID;
+ Arts::Buffer *request, *result;
+ request = Arts::Dispatcher::the()->createRequest(requestID,_objectID,methodID);
+ request->patchLength();
+ _connection->qSendBuffer(request);
+
+ result = Arts::Dispatcher::the()->waitForResult(requestID,_connection);
+ if (!result) return Arts::FlowSystem::null();
+ Arts::FlowSystem_base* returnCode;
+ readObject(*result,returnCode);
+ delete result;
+ return Arts::FlowSystem::_from_base(returnCode);
+}
+
+/*
+ * custom messaging
+ */
+
+Buffer *Object_stub::_allocCustomMessage(long handlerID)
+{
+ return Dispatcher::the()->createOnewayRequest(_objectID,handlerID);
+}
+
+void Object_stub::_sendCustomMessage(Buffer *buffer)
+{
+ buffer->patchLength();
+ _connection->qSendBuffer(buffer);
+}
+
+unsigned long Object_base::_IID = MCOPUtils::makeIID("Object");
+
+/*
+ * global cleanup
+ */
+
+void Object_stub::_cleanupMethodCache()
+{
+ if(_lookupMethodCache)
+ {
+ delete[] _lookupMethodCache;
+ _lookupMethodCache = 0;
+ }
+}
+
+namespace Arts {
+ static class Object_stub_Shutdown : public StartupClass {
+ public:
+ void startup() { }
+ void shutdown() { Object_stub::_cleanupMethodCache(); }
+ } The_Object_stub_Shutdown;
+}
diff --git a/mcop/object.h b/mcop/object.h
new file mode 100644
index 0000000..efe8c59
--- /dev/null
+++ b/mcop/object.h
@@ -0,0 +1,390 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef OBJECT_H
+#define OBJECT_H
+
+#include "buffer.h"
+#include "connection.h"
+#include "notification.h"
+
+#include <assert.h>
+#include <map>
+#include <list>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): Object_base, Object_skel, Object_stub
+ *
+ * All of them have to be kept binary compatible carefully, due to interaction
+ * with generated code. There are d ptrs in _skel and _stub, NOT TO BE USED
+ * NORMALLY. Normally, do use _internalData instead, as this is much faster
+ * than creating two d objects per MCOP implementation/stub. Handle with care.
+ */
+
+
+namespace Arts {
+/* custom dispatching functions */
+
+typedef void (*DispatchFunction)(void *object, Buffer *request, Buffer *result);
+typedef void (*OnewayDispatchFunction)(void *object, Buffer *request);
+typedef void (*DynamicDispatchFunction)(void *object, long methodID, Buffer *request, Buffer *result);
+
+class ScheduleNode;
+class Object_skel;
+class Object_stub;
+class FlowSystem;
+class MethodDef;
+class ObjectReference;
+class WeakReferenceBase;
+class Object;
+class ObjectManager;
+class DynamicSkeletonData;
+class DynamicSkeletonBase;
+
+class ARTS_EXPORT Object_base : public NotificationClient {
+private:
+ friend class DynamicRequest;
+ friend class ObjectManager;
+ bool _deleteOk; // ensure that "delete" is not called manually
+
+protected:
+ /**
+ * ObjectInternalData contains private data structures for
+ * - Object_base
+ * - Object_stub
+ * - Object_skel
+ *
+ * This is an optimization over adding each of them private data pointers,
+ * which would lead to some more bloat.
+ */
+ class ObjectInternalData *_internalData;
+
+ struct ObjectStreamInfo;
+
+ Object_base();
+ virtual ~Object_base();
+
+ /*
+ * internal management for streams
+ */
+ ScheduleNode *_scheduleNode;
+ std::list<ObjectStreamInfo *> _streamList;
+
+ virtual Object_skel *_skel();
+ virtual Object_stub *_stub();
+
+ enum ObjectLocation { objectIsLocal, objectIsRemote };
+ virtual ObjectLocation _location() const = 0;
+
+ long _objectID;
+ Connection *_connection;
+ std::string _internalObjectID; // two objects are "_isEqual" when these match
+ long _nextNotifyID;
+ long _refCnt; // reference count
+ static long _staticObjectCount;
+
+ void _destroy(); // use this instead of delete (takes care of
+ // properly removing flow system node)
+public:
+ static unsigned long _IID; // interface ID
+ /**
+ * custom messaging: these can be used to send a custom data to other
+ * objects. Warning: these are *not* usable for local objects. You may
+ * only use these functions if you know that you are talking to a remote
+ * object. Use _allocCustomMessage to allocate a message. Put the data
+ * you want to send in the Buffer. After that, call _sendCustomMessage.
+ * Don't free the buffer - this will happen automatically.
+ */
+
+ virtual Buffer *_allocCustomMessage(long handlerID);
+ virtual void _sendCustomMessage(Buffer *data);
+
+ /*
+ * generic capabilities, which allow find out what you can do with an
+ * object even if you don't know it's interface
+ */
+ virtual long _lookupMethod(const Arts::MethodDef &) = 0;
+ virtual std::string _interfaceName() = 0;
+ virtual class InterfaceDef _queryInterface(const std::string& name) = 0;
+ virtual class TypeDef _queryType(const std::string& name) = 0;
+ virtual class EnumDef _queryEnum(const std::string& name) = 0;
+ virtual std::string _toString() = 0;
+
+ /*
+ * stuff for streaming (put in a seperate interface?)
+ */
+ virtual void calculateBlock(unsigned long cycles);
+ ScheduleNode *_node();
+ virtual FlowSystem _flowSystem() = 0;
+
+ /*
+ * reference counting
+ */
+ virtual void _release() = 0;
+ virtual void _copyRemote() = 0;
+ virtual void _useRemote() = 0;
+ virtual void _releaseRemote() = 0;
+
+ // BC issue: added _cancelCopyRemote here to avoid virtual function
+ void _cancelCopyRemote();
+
+ void _addWeakReference(WeakReferenceBase *reference);
+ void _removeWeakReference(WeakReferenceBase *reference);
+
+ inline Object_base *_copy() {
+ assert(_refCnt > 0);
+ _refCnt++;
+ return this;
+ }
+
+ // Default I/O info
+ virtual std::vector<std::string> _defaultPortsIn() const;
+ virtual std::vector<std::string> _defaultPortsOut() const;
+
+ // cast operation
+ virtual void *_cast(unsigned long iid);
+ void *_cast(const std::string& interface);
+
+ // Run-time type compatibility check
+ virtual bool _isCompatibleWith(const std::string& interfacename) = 0;
+
+ // Aggregation
+ virtual std::string _addChild(Arts::Object child, const std::string& name) = 0;
+ virtual bool _removeChild(const std::string& name) = 0;
+ virtual Arts::Object _getChild(const std::string& name) = 0;
+ virtual std::vector<std::string> * _queryChildren() = 0;
+
+ /*
+ * when this is true, a fatal communication error has occurred (of course
+ * only possible for remote objects) - maybe your returncode is invalid,
+ * maybe your last invocation didn't succeed...
+ */
+ virtual bool _error();
+
+ inline static long _objectCount() { return _staticObjectCount; }
+ inline long _mkNotifyID() { return _nextNotifyID++; }
+
+ // object creation
+ static Object_base *_create(const std::string& subClass = "Object");
+
+ // comparison
+ bool _isEqual(Object_base *object) const;
+
+ // static converter (from reference)
+ static Object_base *_fromString(const std::string& objectref);
+ static Object_base *_fromReference(class ObjectReference ref, bool needcopy);
+};
+
+/*
+ * Dispatching
+ */
+
+class Buffer;
+class MethodDef;
+
+
+class Object_skel_private;
+class AnyConstRef;
+class AttributeDef;
+
+class ARTS_EXPORT Object_skel : virtual public Object_base {
+private:
+ friend class Object_base;
+ friend class DynamicSkeletonData;
+ friend class DynamicSkeletonBase;
+
+ Object_skel_private *_d_skel;// do not use until there is a very big problem
+
+ // reference counting - remote object watching
+
+ long _remoteSendCount; // don't kill objects just sent to other server
+ bool _remoteSendUpdated; // timeout if they don't want the object
+ std::list<class Connection *> _remoteUsers; // who is using it?
+
+protected:
+ void _addMethod(DispatchFunction disp, void *object, const MethodDef& md);
+ void _addMethod(OnewayDispatchFunction disp, void *object,
+ const MethodDef& md);
+ void _addMethod(DynamicDispatchFunction disp, void *object,
+ const MethodDef& md);
+ void _initStream(const std::string& name, void *ptr, long flags);
+
+ /** stuff relative to attribute notifications **/
+ bool _initAttribute(const Arts::AttributeDef& attribute);
+ static bool _QueryInitStreamFunc(Object_skel *skel,const std::string& name);
+ bool _generateSlots(const std::string& name, const std::string& interface);
+
+ /** for DynamicSkeleton: **/
+ const MethodDef& _dsGetMethodDef(long methodID);
+
+protected:
+ void _defaultNotify(const Notification& notification);
+ void notify(const Notification& notification);
+ void _emit_changed(const char *stream, const AnyConstRef& value);
+
+ /**
+ * custom messaging: this is used to install a custom data handler that
+ * can be used to receive non-standard messages
+ */
+ long _addCustomMessageHandler(OnewayDispatchFunction handler, void *object);
+
+ Object_skel *_skel();
+ ObjectLocation _location() const;
+
+public:
+ Object_skel();
+ virtual ~Object_skel();
+
+ // reference counting connection drop
+ void _disconnectRemote(class Connection *connection);
+ void _referenceClean();
+
+ // synchronous & asynchronous dispatching
+ void _dispatch(Buffer *request, Buffer *result,long methodID);
+ void _dispatch(Buffer *request, long methodID);
+ long _lookupMethod(const MethodDef &);
+
+ /*
+ * standard interface for every object skeleton
+ */
+ static std::string _interfaceNameSkel();
+ virtual void _buildMethodTable();
+
+ /*
+ * reference counting
+ */
+ virtual void _release();
+ virtual void _copyRemote();
+ virtual void _useRemote();
+ virtual void _releaseRemote();
+
+ /*
+ * streaming
+ */
+ FlowSystem _flowSystem();
+
+ /*
+ * to inspect the (remote) object interface
+ */
+ virtual std::string _interfaceName();
+ InterfaceDef _queryInterface(const std::string& name);
+ TypeDef _queryType(const std::string& name);
+ EnumDef _queryEnum(const std::string& name);
+ virtual std::string _toString();
+
+ // Run-time type compatibility check
+ bool _isCompatibleWith(const std::string& interfacename);
+
+ // Aggregation
+ std::string _addChild(Arts::Object child, const std::string& name);
+ bool _removeChild(const std::string& name);
+ Arts::Object _getChild(const std::string& name);
+ std::vector<std::string> * _queryChildren();
+};
+
+class Object_stub_private;
+
+class ARTS_EXPORT Object_stub : virtual public Object_base {
+private:
+ friend class Object_base;
+
+ Object_stub_private *_d_stub;// do not use until there is a very big problem
+
+protected:
+ long _lookupCacheRandom;
+
+ Object_stub();
+ Object_stub(Connection *connection, long objectID);
+ virtual ~Object_stub();
+
+ virtual Object_stub *_stub();
+ ObjectLocation _location() const;
+
+ enum { _lookupMethodCacheSize = 337 };
+ static struct methodCacheEntry {
+ methodCacheEntry() : obj(NULL),method(NULL),ID(0) {} ;
+ Object_stub *obj;
+ const char *method;
+ long ID;
+ } *_lookupMethodCache;
+
+ long _lookupMethodFast(const char *method);
+ long _lookupMethod(const MethodDef &);
+
+public:
+ /*
+ * custom messaging
+ */
+
+ Buffer *_allocCustomMessage(long handlerID);
+ void _sendCustomMessage(Buffer *data);
+
+ /*
+ * to inspect the (remote) object interface
+ */
+ std::string _interfaceName();
+ InterfaceDef _queryInterface(const std::string& name);
+ TypeDef _queryType(const std::string& name);
+ EnumDef _queryEnum(const std::string& name);
+ std::string _toString();
+
+ /*
+ * streaming
+ */
+ FlowSystem _flowSystem();
+
+ /*
+ * reference counting
+ */
+ virtual void _release();
+ virtual void _copyRemote();
+ virtual void _useRemote();
+ virtual void _releaseRemote();
+
+ // Run-time type compatibility check
+ bool _isCompatibleWith(const std::string& interfacename);
+
+ // Aggregation
+ std::string _addChild(Arts::Object child, const std::string& name);
+ bool _removeChild(const std::string& name);
+ Arts::Object _getChild(const std::string& name);
+ std::vector<std::string> * _queryChildren();
+
+ /*
+ * communication error? this is true when your connection to the remote
+ * object is lost (e.g. when the remote server crashed) - your return
+ * values are then undefined, so check this before relying too much
+ * on some invocation
+ */
+
+ bool _error();
+
+ /*
+ * global cleanup
+ */
+ static void _cleanupMethodCache();
+};
+
+}
+#endif
diff --git a/mcop/objectmanager.cc b/mcop/objectmanager.cc
new file mode 100644
index 0000000..0617ea4
--- /dev/null
+++ b/mcop/objectmanager.cc
@@ -0,0 +1,289 @@
+ /*
+
+ Copyright (C) 2000,2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "mcoputils.h"
+#include "mcopconfig.h"
+#include "objectmanager.h"
+#include "dispatcher.h"
+#include "extensionloader.h"
+#include "debug.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+class Arts::ObjectManagerPrivate {
+public:
+ struct LoaderData {
+ LoaderData() : init(false) { }
+ bool init;
+ Loader loader;
+ };
+
+ list<ExtensionLoader *> extensions;
+ map<string, long> capabilities;
+ map<string, LoaderData> loaders;
+};
+
+Object_skel *ObjectManager::create(const string& name)
+{
+ list<Factory *>::iterator i;
+
+ /* first try: look through all factories we have */
+
+ for(i = factories.begin();i != factories.end(); i++)
+ {
+ Factory *f = *i;
+ if(f->interfaceName() == name ) return f->createInstance();
+ }
+
+ /* second try: look if there is a suitable extension we could load */
+
+ TraderQuery query;
+ query.supports("InterfaceName", name);
+ vector<TraderOffer> *offers = query.query();
+
+ vector<TraderOffer>::iterator oi;
+ for(oi = offers->begin(); oi != offers->end(); oi++)
+ {
+ /*
+ * check whether we provide everything that this
+ * implementation requires to run
+ */
+ bool requirementsOk = true;
+ vector<string> *requires = oi->getProperty("Requires");
+
+ vector<string>::iterator ri;
+ for(ri = requires->begin(); ri != requires->end(); ri++)
+ {
+ if(d->capabilities[*ri] <= 0)
+ requirementsOk = false;
+ }
+ delete requires;
+
+ vector<string> *language = oi->getProperty("Language");
+ vector<string> *libs = oi->getProperty("Library");
+
+ if(language->size() == 0 && libs->size() == 1)
+ {
+ arts_warning("ObjectManager: %s - assuming 'Language=C++' because library given",name.c_str());
+ language->push_back("C++");
+ }
+ if(language->size() != 1)
+ {
+ arts_warning("ObjectManager: %s - Language missing", name.c_str());
+ requirementsOk = false;
+ }
+ if(requirementsOk && language->front() == "C++" && libs->empty())
+ {
+ arts_warning("ObjectManager: %s - Library missing", name.c_str());
+ requirementsOk = false;
+ }
+
+ /* loading C++ components */
+ if(requirementsOk && language->front() == "C++")
+ {
+ string library = libs->front();
+
+ ExtensionLoader *e = new ExtensionLoader(library);
+ if(e->success())
+ {
+ d->extensions.push_back(e);
+ for(i = factories.begin();i != factories.end(); i++)
+ {
+ Factory *f = *i;
+ if(f->interfaceName() == name)
+ {
+ delete language;
+ delete libs;
+ delete offers;
+ return f->createInstance();
+ }
+ }
+ }
+ else
+ {
+ arts_warning("MCOP ObjectManager:"
+ " Could not load extension %s.", library.c_str());
+ delete e;
+ }
+ }
+ delete libs;
+
+ /* other languages/binary formats */
+ if(requirementsOk)
+ {
+ string lang = language->front();
+ ObjectManagerPrivate::LoaderData &ld = d->loaders[lang];
+
+ if(!ld.init)
+ {
+ TraderQuery query;
+ query.supports("Interface", "Arts::Loader");
+ query.supports("LoadLanguage", lang);
+
+ vector<TraderOffer> *loffers = query.query();
+
+ // TODO: error checking for SubClass
+ if(loffers->size() > 0)
+ {
+ ld.loader = SubClass(loffers->front().interfaceName());
+ }
+ else
+ {
+ ld.loader = Arts::Loader::null();
+ }
+
+ delete loffers;
+ }
+ ld.init = true;
+
+ if(!ld.loader.isNull())
+ {
+ /*
+ * ### change when breaking BC:
+ * it's bad that ObjectManager has to return _skel()s, but
+ * well, can't change it now
+ */
+
+ Object obj = ld.loader.loadObject(*oi);
+ delete language;
+ delete offers;
+ return obj._base()->_copy()->_skel();
+ }
+ }
+
+ delete language;
+ }
+
+ arts_warning("MCOP ObjectManager: can't find implementation for %s.",
+ name.c_str());
+
+ delete offers;
+ return 0;
+}
+
+void ObjectManager::registerFactory(Factory *factory)
+{
+ factories.push_back(factory);
+}
+
+void ObjectManager::removeFactory(Factory *factory)
+{
+ list<Factory *>::iterator i;
+
+ i = factories.begin();
+ while(i != factories.end())
+ {
+ if(*i == factory) {
+ factories.erase(i);
+ i = factories.begin();
+ }
+ else i++;
+ }
+}
+
+ObjectManager *ObjectManager::_instance = 0;
+
+ObjectManager::ObjectManager()
+{
+ assert(!_instance);
+ _instance = this;
+ d = new ObjectManagerPrivate;
+}
+
+ObjectManager::~ObjectManager()
+{
+ // they should be unloaded before this object can be deleted
+ assert(d->extensions.empty());
+ delete d;
+ assert(_instance);
+ _instance = 0;
+}
+
+ObjectManager *ObjectManager::the()
+{
+ assert(_instance);
+ return _instance;
+}
+
+void ObjectManager::shutdownExtensions()
+{
+ // give up references to the loaders
+ d->loaders.clear();
+
+ // shuts down all dynamically loaded extensions
+ list<ExtensionLoader *>::iterator i;
+ for(i=d->extensions.begin(); i != d->extensions.end(); i++)
+ (*i)->shutdown();
+}
+
+void ObjectManager::removeExtensions()
+{
+ // unloads all dynamically loaded extensions
+ list<ExtensionLoader *>::iterator i;
+ for(i=d->extensions.begin(); i != d->extensions.end(); i++)
+ delete *i;
+
+ d->extensions.clear();
+}
+
+/*
+ * global references
+ */
+
+bool ObjectManager::addGlobalReference(Object object, const string& name)
+{
+ bool result;
+
+ result = Dispatcher::the()->globalComm().put(name,object.toString());
+ if(result)
+ referenceNames.push_back(name);
+
+ return result;
+}
+
+string ObjectManager::getGlobalReference(const string& name)
+{
+ return Dispatcher::the()->globalComm().get(name);
+}
+
+void ObjectManager::removeGlobalReferences()
+{
+ list<string>::iterator i;
+
+ for(i=referenceNames.begin(); i != referenceNames.end();i++)
+ Dispatcher::the()->globalComm().erase(*i);
+}
+
+void ObjectManager::provideCapability(const string& name)
+{
+ d->capabilities[name]++;
+}
+
+void ObjectManager::removeCapability(const string& name)
+{
+ d->capabilities[name]--;
+}
diff --git a/mcop/objectmanager.h b/mcop/objectmanager.h
new file mode 100644
index 0000000..47a5c11
--- /dev/null
+++ b/mcop/objectmanager.h
@@ -0,0 +1,75 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef OBJECTMANAGER_H
+#define OBJECTMANAGER_H
+
+#include "object.h"
+#include "factory.h"
+#include <list>
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): ObjectManager
+ *
+ * Keep binary compatible (since accessible via ::the()), use d ptr when
+ * changing it.
+ */
+
+namespace Arts {
+
+class Object;
+class ObjectManagerPrivate;
+
+class ARTS_EXPORT ObjectManager {
+private:
+ ObjectManagerPrivate *d;
+
+protected:
+ static ObjectManager *_instance;
+ std::list<Factory *> factories;
+ std::list<std::string> referenceNames;
+
+public:
+ ObjectManager();
+ ~ObjectManager();
+
+ static ObjectManager *the();
+ Object_skel *create(const std::string& name);
+
+ bool addGlobalReference(Object object, const std::string& name);
+ std::string getGlobalReference(const std::string& name);
+ void removeGlobalReferences();
+ void removeExtensions();
+ void shutdownExtensions();
+
+ void registerFactory(Factory *factory);
+ void removeFactory(Factory *factory);
+
+ void provideCapability(const std::string& capability);
+ void removeCapability(const std::string& capability);
+};
+
+}
+
+#endif /* OBJECTMANAGER_H */
diff --git a/mcop/pool.h b/mcop/pool.h
new file mode 100644
index 0000000..199f422
--- /dev/null
+++ b/mcop/pool.h
@@ -0,0 +1,89 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_POOL_H
+#define ARTS_POOL_H
+
+
+/*
+ * BC - Status (2002-03-08): Pool<type>
+ *
+ * Needs to be kept binary compatible by NOT TOUCHING. When you want something
+ * else, write a fresh one (used as part of Arts::Dispatcher, thus changing
+ * this breaks Arts::Dispatcher binary compatibility).
+ */
+
+
+/**
+ * A pool object of the type T keeps a pool of T* pointers, that are numbered.
+ *
+ * You allocate and release slots, and store T*'s in there. It should take
+ * about no time to find a new free slot to store the T object into and to
+ * release a slot to be reused.
+ *
+ * The pool object internally keeps track which slots are used.
+ */
+#include <stack>
+#include <vector>
+#include <list>
+
+namespace Arts {
+
+template <class T>
+class Pool {
+ std::stack<unsigned long> freeIDs;
+ std::vector<T *> storage;
+public:
+ inline T*& operator[](unsigned long n) { return storage[n]; }
+ inline void releaseSlot(unsigned long n) {
+ freeIDs.push(n);
+ storage[n] = 0;
+ }
+ unsigned long allocSlot() {
+ unsigned long slot;
+ if(freeIDs.empty())
+ {
+ unsigned long n;
+ for(n=0;n<32;n++) {
+ freeIDs.push(storage.size());
+ storage.push_back(0);
+ }
+ }
+ slot = freeIDs.top();
+ freeIDs.pop();
+ return slot;
+ }
+ std::list<T *> enumerate() {
+ std::list<T *> items;
+ //std::vector<T *>::iterator i;
+ int n,max = storage.size();
+
+ for(n=0; n < max; n++)
+ if(storage[n]) items.push_back(storage[n]);
+
+ return items;
+ }
+ unsigned long max() { return storage.size(); }
+};
+
+}
+#endif /* POOL_H */
diff --git a/mcop/reference.cc b/mcop/reference.cc
new file mode 100644
index 0000000..3f214bf
--- /dev/null
+++ b/mcop/reference.cc
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu, nicolas.brodu@free.fr
+ Stefan Westerfeld, stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#include "common.h"
+
+using namespace Arts;
+
+// For technical reasons, this is here too: FlowSystem isn't declared when
+// the wrapper is already needed, so we can't make this function inline,
+// unfortunately...
+FlowSystem Object::_flowSystem() const
+{
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_flowSystem();
+}
diff --git a/mcop/reference.h b/mcop/reference.h
new file mode 100644
index 0000000..ae59df6
--- /dev/null
+++ b/mcop/reference.h
@@ -0,0 +1,349 @@
+/*
+ Copyright (C) 2000 Nicolas Brodu, nicolas.brodu@free.fr
+ Stefan Westerfeld, stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * BC - Status (2002-03-08): Reference, SubClass, Object, DynamicCast.
+ *
+ * Part of the public API. Must be kept binary compatible by NOT TOUCHING
+ * AT ALL. Interaction with generated and written code.
+ */
+
+
+#ifndef MCOP_REFERENCE_H
+#define MCOP_REFERENCE_H
+
+#include "common.h"
+#include <string>
+#include <vector>
+
+#include "arts_export.h"
+
+namespace Arts {
+
+// Acts as a string or ObjectReference, but enables a different constructor
+class ARTS_EXPORT Reference {
+private:
+ ObjectReference myref;
+ std::string mys;
+ bool strMode;
+public:
+
+ inline explicit Reference(const ObjectReference& ref) {
+ myref=ref;
+ strMode=false;
+ }
+
+ inline explicit Reference(const std::string& s) {
+ mys=s;
+ strMode=true;
+ }
+
+ inline explicit Reference(const char* c) {
+ mys=c;
+ strMode=true;
+ }
+ inline Reference& operator=(const std::string& s) {
+ mys=s;
+ strMode=true;
+ return *this;
+ }
+ inline Reference& operator=(const char*c) {
+ mys=c;
+ strMode=true;
+ return *this;
+ }
+ inline bool isString() const {return strMode;}
+// inline operator const std::string() const {return mys;}
+ inline const std::string& string() const {return mys;}
+// inline operator const ObjectReference() const {return myref;}
+ inline const ObjectReference& reference() const {return myref;}
+};
+
+// Acts as a string, but enables a different constructor
+class ARTS_EXPORT SubClass {
+private:
+ std::string mys;
+public:
+
+ inline explicit SubClass(const std::string& s) : mys(s) {}
+ inline explicit SubClass(const char* c) : mys(c) {}
+ inline SubClass& operator=(const std::string& s) {mys=s; return *this;}
+ inline SubClass& operator=(const char*c) {mys=c; return *this;}
+// inline operator const std::string() const {return mys;}
+ inline const std::string& string() const {return mys;}
+};
+
+
+class ScheduleNode;
+class FlowSystem;
+
+// Object has _no_ virtual, and must not have. That way, all the
+// wrappers can be passed as argument or return type, and there is also
+// no virtual table bloat.
+// Moreover, the virtual mechanism still works correctly thanks to the
+// _pool->base redirection.
+class ARTS_EXPORT Object {
+protected:
+ // Pool of common variables for a bunch a wrappers
+ class Pool {
+ friend class Object;
+ Object_base* (*creator)();
+ bool created;
+ int count;
+ public:
+ Object_base* base;
+ inline Pool(Object_base* b)
+ : creator(0), created(true), count(1), base(b) {}
+ inline Pool(Object_base* (*cor)())
+ : creator(cor), created(false), count(1), base(0) {}
+ inline void Inc() {count++;}
+ inline void Dec() {
+ if (--count==0) {
+ if(base) base->_release();
+ delete this;
+ }
+ }
+ inline void checkcreate() {
+ if (!created) {base = creator(); created=true;}
+ }
+ } *_pool;
+
+ inline Object(Object_base* (*cor)()) {
+ _pool = new Pool(cor);
+ }
+ inline Object(Pool* p) : _pool(p) {
+ _pool->Inc();
+ }
+ inline Object(Pool& p) : _pool(&p) {
+ _pool->Inc();
+ }
+ inline Object(Object_base* b) {
+ _pool = new Pool(b);
+ }
+public:
+ typedef Object_base _base_class;
+
+ // Dynamic cast constructor of inherited classes needs to access the _pool
+ // of a generic object if casting successful. But it could not without this
+ inline Pool* _get_pool() const {return _pool;}
+
+ inline ~Object() {
+ _pool->Dec();
+ }
+
+ // Those constructors are public, since we don't need an actual creator.
+ // They enable generic object creation (like from a subclass defined at
+ // run-time!)
+ inline Object(const SubClass& s) {
+ _pool = new Pool(Object_base::_create(s.string()));
+ }
+ inline Object(const Reference &r) {
+ _pool = new Pool(r.isString()?(Object_base::_fromString(r.string())):(Object_base::_fromReference(r.reference(),true)));
+ }
+ inline Object(const Object& target) : _pool(target._pool) {
+ _pool->Inc();
+ }
+ inline Object() { // creates a null object
+ _pool = new Pool((Object_base*)0);
+ }
+ inline Object& operator=(const Object& target) {
+ if (_pool == target._pool) return *this;
+ _pool->Dec();
+ _pool = target._pool;
+ _pool->Inc();
+ return *this;
+ }
+ // No problem for the creator, this class has protected constructors.
+ // So creator should give back an actual implementation
+ inline Object_base* _base() const {
+ _pool->checkcreate();
+ return _pool->base;
+ }
+
+ // null, error?
+ inline bool isNull() const {
+ _pool->checkcreate();
+ return !(_pool->base);
+ }
+ inline bool error() const {
+ _pool->checkcreate();
+ return _pool->base && _pool->base->_error();
+ }
+
+ // Comparision
+ inline bool _isEqual(const Object& other) const {
+ if(isNull() != other.isNull()) return false;
+
+ // we can assume that things are created here, as we've
+ // called isNull of both wrappers once
+ if(!isNull())
+ return _pool->base->_isEqual(other._pool->base);
+
+ // both null references
+ return true;
+ }
+
+
+// Object_base wrappers
+
+ // Custom messaging - see Object_base for comments
+ inline Buffer *_allocCustomMessage(long handlerID) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_allocCustomMessage(handlerID);
+ }
+
+ inline void _sendCustomMessage(Buffer *data) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_sendCustomMessage(data);
+ }
+
+ // generic capabilities, which allow find out what you can do with an
+ // object even if you don't know it's interface
+ inline long _lookupMethod(const MethodDef& methodDef) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_lookupMethod(methodDef);
+ }
+ inline std::string _interfaceName() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_interfaceName();
+ }
+ inline InterfaceDef _queryInterface(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryInterface(name);
+ }
+ inline TypeDef _queryType(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryType(name);
+ }
+ inline EnumDef _queryEnum(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryEnum(name);
+ }
+ // Stringification
+ inline std::string _toString() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_toString();
+ }
+ inline std::string toString() const {return _toString();}
+
+ // stuff for streaming (put in a seperate interface?)
+ inline void calculateBlock(unsigned long cycles) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->calculateBlock(cycles);
+ }
+ // Node info
+ inline ScheduleNode *_node() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_node();
+ }
+
+ // Ah! Flowsystem is not defined yet, so cannot be returned inline.
+ FlowSystem _flowSystem() const;
+
+ inline void _copyRemote() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_copyRemote();
+ }
+ inline void _useRemote() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_useRemote();
+ }
+ inline void _releaseRemote() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ _pool->base->_releaseRemote();
+ }
+
+ // Default I/O info
+ inline std::vector<std::string> _defaultPortsIn() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_defaultPortsIn();
+ }
+ inline std::vector<std::string> _defaultPortsOut() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_defaultPortsOut();
+ }
+
+ // aggregation
+ inline std::string _addChild(Arts::Object child, const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_addChild(child, name);
+ }
+ inline bool _removeChild(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_removeChild(name);
+ }
+ inline Arts::Object _getChild(const std::string& name) const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_getChild(name);
+ }
+ inline std::vector<std::string> * _queryChildren() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_queryChildren();
+ }
+ // Do we really need those in the Wrapper?
+ // And would it really be sensible to make _cast wrappers?
+/* inline void _release() const {
+ _pool->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_release();
+ }
+ inline Object_base *_copy() const {
+ _poo->checkcreate();
+ assert(_pool->base);
+ return _pool->base->_copy();
+ }
+*/
+
+ // Object::null() returns a null object (and not just a reference to one)
+ inline static Object null() {return Object((Object_base*)0);}
+ inline static Object _from_base(Object_base* b) {return Object(b);}
+};
+
+// Enables a different constructor, that should do the cast
+class ARTS_EXPORT DynamicCast {
+private:
+ Object obj;
+public:
+ inline explicit DynamicCast(const Object& o) : obj(o) {}
+ inline const Object& object() const {return obj;}
+};
+
+}
+
+#endif
diff --git a/mcop/referenceclean.cc b/mcop/referenceclean.cc
new file mode 100644
index 0000000..58e7001
--- /dev/null
+++ b/mcop/referenceclean.cc
@@ -0,0 +1,87 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "referenceclean.h"
+#include "time.h"
+
+using namespace std;
+using namespace Arts;
+
+ReferenceClean::ReferenceClean(Pool<Object_skel>& objectPool)
+ :objectPool(objectPool)
+{
+ Dispatcher::the()->ioManager()->addTimer(5000, this);
+}
+
+void ReferenceClean::notifyTime()
+{
+ /*
+ * This last_notify and now check is because IOManager accumulates
+ * notifyTime() calls, so it may happen that we don't get one for ten
+ * seconds, and then two. However, this breaks the "second-chance"
+ * algorithm referenceClean is using, which depends on the fact that
+ * there is some significant time delay between two calls. So we'll
+ * verify it by hand.
+ */
+
+ static time_t last_notify = 0;
+ time_t now;
+
+ time(&now);
+ if(now-last_notify > 4)
+ {
+ clean();
+ last_notify = now;
+ }
+}
+
+void ReferenceClean::forceClean()
+{
+ /*
+ * as we're giving a second chance on reference clean, we need to
+ * clean twice to really really clean up
+ */
+ clean();
+ clean();
+}
+
+void ReferenceClean::clean()
+{
+ /*
+ * we manually iterate through the pool here, to get around the problem
+ * that if an object disappears, ten other objects might cease to exist
+ * as well (as they are dependant), which would break a list which we
+ * could obtain via enumerate() and would probably lead to a crash
+ */
+ unsigned long l;
+
+ for(l=0; l<objectPool.max(); l++)
+ {
+ Object_skel *skel = objectPool[l];
+ if(skel) skel->_referenceClean();
+ }
+}
+
+ReferenceClean::~ReferenceClean()
+{
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
diff --git a/mcop/referenceclean.h b/mcop/referenceclean.h
new file mode 100644
index 0000000..13b6ec7
--- /dev/null
+++ b/mcop/referenceclean.h
@@ -0,0 +1,60 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): ReferenceClean
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. Can be changed arbitrarily even non BC.
+ */
+
+#ifndef REFERENCECLEAN_H
+#define REFERENCECLEAN_H
+
+#include "iomanager.h"
+#include "dispatcher.h"
+
+namespace Arts {
+
+class ReferenceClean : public TimeNotify {
+ Pool<Object_skel>& objectPool;
+protected:
+ void clean();
+
+public:
+ ReferenceClean(Pool<Object_skel>& objectPool);
+
+ /**
+ * this routine forces cleaning of all tagged remote objects
+ *
+ * it will be called on dispatcher shutdown, since after this there
+ * is no remote interaction anyway, it is be used to prevent memory
+ * leaks
+ */
+ void forceClean();
+
+ void notifyTime();
+ virtual ~ReferenceClean();
+};
+
+}
+#endif
diff --git a/mcop/socketconnection.cc b/mcop/socketconnection.cc
new file mode 100644
index 0000000..f3bc3e8
--- /dev/null
+++ b/mcop/socketconnection.cc
@@ -0,0 +1,205 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "tcpconnection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#define queue cqueue
+#include <netdb.h>
+#undef queue
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#undef DEBUG_CONNECTION_DATA
+
+using namespace Arts;
+
+/*
+ * These parameters impact the performance significantly. There are two sides:
+ *
+ * when you use too large buffers for reading/writing
+ * - it may be, that each operation takes too long, so that for instance
+ * an important real time audio job drops during that time
+ * - it may be, that dealing with large buffers (allocation, cache, etc)
+ * itself causes a penalty
+ *
+ * on the other hand, small buffers lead to repeated operating system calls,
+ * which is bad especially if you even go through all the chain: check what
+ * can be written with select, invoke the corresponding object, actually
+ * read (or write), do messages, do timers, go sleep again on select.
+ */
+static const int MCOP_MAX_READ_SIZE=8192;
+static const int MCOP_MAX_WRITE_SIZE=8192;
+
+SocketConnection::SocketConnection()
+{
+}
+
+SocketConnection::SocketConnection(int _fd)
+ : fd(_fd), _broken(false)
+{
+ arts_debug("socketconnection created, fd = %d",fd);
+ Dispatcher::the()->ioManager()->watchFD(fd,
+ IOType::read|IOType::except|IOType::reentrant,this);
+ initReceive();
+}
+
+void SocketConnection::qSendBuffer(Buffer *buffer)
+{
+ if(_broken)
+ {
+ // forget it ;) - no connection there any longer
+ delete buffer;
+ return;
+ }
+ if(pending.size() == 0)
+ {
+ // if there is nothing pending already, it may be that we are lucky
+ // and can write the buffer right now without blocking
+
+ writeBuffer(buffer);
+ if(!buffer->remaining())
+ {
+ delete buffer;
+ return;
+ }
+
+ // but if it blocks, we'll need to watch for write chances to send
+ // that buffer later
+ Dispatcher::the()->ioManager()->watchFD(fd,IOType::write|IOType::reentrant,this);
+ }
+ pending.push_back(buffer);
+}
+
+#ifdef DEBUG_CONNECTION_DATA
+static void connection_hex_dump(unsigned char *buffer, long len)
+{
+ int i = 0;
+ printf("Connection: received %ld bytes:\n\n",len);
+ while (i < len)
+ {
+ unsigned int j, n, d[16];
+
+ for (n = 0; n < 16; n++)
+ if (i < len)
+ d[n] = buffer[i++];
+ else
+ break;
+ printf (" ");
+
+ for (j = 0; j < n; j++) printf ("%s %02x", j == 8 ? " " : "", d[j]);
+ for (; j < 16; j++) printf ("%s ", j == 8 ? " " : "");
+ printf (" ");
+
+ for (j = 0; j < n; j++)
+ printf ("%c", d[j] >= 32 ? d[j] : '.');
+ printf ("\n");
+ }
+}
+#endif
+
+void SocketConnection::notifyIO(int _fd, int types)
+{
+ assert(_fd == fd);
+
+ if(types & IOType::read)
+ {
+ unsigned char buffer[MCOP_MAX_READ_SIZE];
+ long n = read(fd,buffer,MCOP_MAX_READ_SIZE);
+
+#ifdef DEBUG_CONNECTION_DATA
+ connection_hex_dump(buffer,n);
+#endif
+
+ if(n > 0)
+ {
+ receive(buffer,n);
+ // warning: the object may not exist any more here!
+ return;
+ }
+ else if(n == 0 /* remote end closed connection */
+ || (n == -1 && errno != EAGAIN && errno != EINTR)) /* some error */
+ {
+ close(fd);
+ _broken = true;
+ Dispatcher::the()->ioManager()->remove(this,IOType::all);
+
+ Dispatcher::the()->handleConnectionClose(this);
+ // warning: the object may not exist any more here!
+ return;
+ }
+ }
+
+ if(types & IOType::write)
+ {
+ assert(pending.size() != 0);
+
+ Buffer *pbuffer = *pending.begin();
+ if(pbuffer->remaining()) writeBuffer(pbuffer);
+
+ // no else => it could have been sent in the if(..remaining..) above
+ if(!pbuffer->remaining())
+ {
+ delete pbuffer;
+ pending.pop_front();
+
+ if(pending.size() == 0)
+ Dispatcher::the()->ioManager()->remove(this,IOType::write);
+ }
+ }
+
+ if(types & IOType::except)
+ {
+ assert(false);
+ }
+}
+
+void SocketConnection::writeBuffer(Buffer *buffer)
+{
+ long len = MCOP_MAX_WRITE_SIZE;
+ if(buffer->remaining() < len) len = buffer->remaining();
+
+ void *data = buffer->peek(len);
+ long written = write(fd,data,len);
+
+ if(written > 0)
+ buffer->skip(len);
+}
+
+bool SocketConnection::broken()
+{
+ return _broken;
+}
+
+void SocketConnection::drop()
+{
+ if(!_broken)
+ {
+ close(fd);
+ _broken = true;
+ Dispatcher::the()->ioManager()->remove(this,IOType::all);
+ }
+}
diff --git a/mcop/socketconnection.h b/mcop/socketconnection.h
new file mode 100644
index 0000000..aaeaeb2
--- /dev/null
+++ b/mcop/socketconnection.h
@@ -0,0 +1,64 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): SocketConnection
+ *
+ * None of these classes is considered part of the public API. Do NOT use it
+ * in your apps. No BC guaranteed.
+ */
+
+#ifndef SOCKETCONNECTION_H
+#define SOCKETCONNECTION_H
+
+#include "buffer.h"
+#include "iomanager.h"
+#include "connection.h"
+#include <list>
+#include <string>
+
+namespace Arts {
+
+class SocketConnection :public Connection, public IONotify {
+protected:
+ std::string serverID;
+ int fd;
+ bool _broken;
+
+ std::list<Buffer *> pending;
+ void writeBuffer(Buffer *buffer);
+
+ SocketConnection();
+
+public:
+ SocketConnection(int _fd);
+
+ void qSendBuffer(Buffer *buffer);
+ void notifyIO(int _fd, int types);
+
+ void drop();
+ bool broken();
+};
+
+}
+
+#endif /* SOCKETCONNECTION_H */
diff --git a/mcop/startupmanager.cc b/mcop/startupmanager.cc
new file mode 100644
index 0000000..89daf16
--- /dev/null
+++ b/mcop/startupmanager.cc
@@ -0,0 +1,150 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "startupmanager.h"
+#include "extensionloader.h"
+#include "debug.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * StartupClass implementation
+ */
+
+StartupClass::StartupClass()
+{
+ StartupManager::add(this);
+}
+
+void StartupClass::shutdown()
+{
+ // shutdown is optional, startup is mandatory
+}
+
+/*
+ * StartupManager implementation
+ */
+
+list<StartupClass *> *StartupManager::startupClasses = 0;
+ExtensionLoader *StartupManager::activeExtensionLoader = 0;
+bool StartupManager::running = false;
+
+void StartupManager::add(StartupClass *sc)
+{
+ if(activeExtensionLoader)
+ {
+ activeExtensionLoader->addStartupClass(sc);
+ }
+ else
+ {
+ if(running)
+ {
+ /*
+ * the problem with adding a StartupClass when we're already running
+ * is that we can't execute the startup() function immediately (for
+ * this might break the dependancy of the StartupClass on other
+ * globally constructed objects)
+ *
+ * so will never execute it, which is likely to break something
+ * else (i.e. implementations defined in the library the startup
+ * class is contained in can't be found)
+ *
+ * usually, this warning is triggered when an application
+ * dynamically loads a library containing StartupClasses, without
+ * libmcop knowing about it
+ */
+ arts_warning("MCOP StartupManager: adding a StartupClass after Dispatcher init will not work.");
+ }
+
+ if(!startupClasses) startupClasses = new list<StartupClass *>;
+
+ startupClasses->push_back(sc);
+ }
+}
+
+void StartupManager::setExtensionLoader(ExtensionLoader *extension)
+{
+ /*
+ * this is not reentrant: you can't load two extensions at the same time,
+ * and it is impossible that an extension loads an extension while being
+ * loaded (nothing forbids you to load another extension from an extension
+ * in a StartupClass or any time later - just don't do it while being
+ * lt_dlopen()d
+ */
+ if(activeExtensionLoader)
+ arts_assert(extension == 0);
+ else
+ arts_assert(extension != 0);
+
+ activeExtensionLoader = extension;
+}
+
+void StartupManager::startup()
+{
+ arts_return_if_fail(running == false);
+ running = true;
+
+ if(startupClasses)
+ {
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses->begin(); i != startupClasses->end(); i++)
+ (*i)->startup();
+ }
+}
+
+void StartupManager::shutdown()
+{
+ arts_return_if_fail(running == true);
+ running = false;
+
+ if(startupClasses)
+ {
+ list<StartupClass *>::iterator i;
+
+ for(i = startupClasses->begin(); i != startupClasses->end(); i++)
+ (*i)->shutdown();
+ }
+}
+
+void StartupManager::internalFreeAll()
+{
+ if(startupClasses)
+ {
+ startupClasses->erase(startupClasses->begin(),startupClasses->end());
+
+ delete startupClasses;
+ startupClasses = 0;
+ }
+}
+
+namespace Arts {
+
+static class StartupManagerFree {
+public:
+ ~StartupManagerFree() { StartupManager::internalFreeAll(); }
+} The_StartupManagerFree;
+
+}
diff --git a/mcop/startupmanager.h b/mcop/startupmanager.h
new file mode 100644
index 0000000..028b421
--- /dev/null
+++ b/mcop/startupmanager.h
@@ -0,0 +1,75 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef STARTUPMANAGER_H
+#define STARTUPMANAGER_H
+
+#include "arts_export.h"
+
+#include <list>
+
+/*
+ * BC - Status (2002-03-08): StartupClass, StartupManager.
+ *
+ * The class needs to be kept BC, as the startup system bases on inheritance
+ * and virtual functions. Do not change.
+ *
+ * The manager is a collection class without nonstatic data, so no BC issues
+ * here.
+ */
+
+namespace Arts {
+
+class ARTS_EXPORT StartupClass {
+public:
+ StartupClass();
+ virtual void startup() = 0;
+ virtual void shutdown();
+};
+
+class StartupManager {
+ static std::list<StartupClass *> *startupClasses;
+ static class ExtensionLoader *activeExtensionLoader;
+ static bool running;
+public:
+ static void add(StartupClass *sc);
+ static void startup();
+ static void shutdown();
+
+ /**
+ * since extensions will register startup classes in the same global way
+ * all other classes do (with StartupManager::add(<some startup class>)),
+ * the StartupManager supports forwarding all add requests to the
+ * active extension, which will allow synchronizing the lt_dlopen
+ * lt_dlclose with the calls of startup()/shutdown() of all StartupClasses
+ * present in the extension
+ */
+ static void setExtensionLoader(class ExtensionLoader *extension);
+
+ /**
+ * to free all resources when the application terminates (internal use only)
+ */
+ static void internalFreeAll();
+};
+
+}
+#endif /* STARTUPMANAGER_H */
diff --git a/mcop/tcpconnection.cc b/mcop/tcpconnection.cc
new file mode 100644
index 0000000..e0c086e
--- /dev/null
+++ b/mcop/tcpconnection.cc
@@ -0,0 +1,152 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "tcpconnection.h"
+#include "dispatcher.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#define queue cqueue
+#include <netdb.h>
+#undef queue
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <errno.h>
+#include "debug.h"
+#include <stdlib.h>
+
+using namespace std;
+using namespace Arts;
+
+static struct sockaddr_in *parse_tcp_url(const char *url)
+{
+ static struct sockaddr_in addr;
+
+ char *work = strdup(url);
+
+ char *type = strtok(work,":");
+ if(type == 0 || strcmp(type,"tcp") != 0) {
+ free(work);
+ return 0;
+ }
+
+ char *host = strtok(NULL,":");
+ if(host == 0) {
+ free(work);
+ return 0;
+ }
+
+ char *port = strtok(NULL,":\n");
+ if(port == 0) {
+ free(work);
+ return 0;
+ }
+
+ long portno = atol(port);
+ if(portno < 1 || portno > 65535) {
+ free(work);
+ return 0;
+ }
+
+ struct hostent *server = gethostbyname(host);
+ if(server == 0)
+ {
+ arts_warning("parse_tcp_url: unknown host '%s'",host);
+ free(work);
+ return 0;
+ }
+
+ memset((void *) &addr, '\0', sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = *(u_long *)server->h_addr;
+ addr.sin_port = htons(portno);
+
+ free(work);
+ return &addr;
+}
+
+static int tcp_connect(const char *url)
+{
+ struct sockaddr_in *remote_addr = parse_tcp_url(url);
+ if(remote_addr == 0)
+ {
+ arts_warning("tcp_connect: couldn't parse url %s",url);
+ return -1;
+ }
+
+ int my_socket = socket(AF_INET,SOCK_STREAM,0);
+ if(my_socket < 0)
+ {
+ arts_warning("tcp_connect: unable to open socket for read");
+ return -1;
+ }
+
+ struct linger lin;
+ lin.l_onoff=1; /* block a closing socket for 1 second */
+ lin.l_linger=100; /* if data is waiting to be sent */
+ if ( setsockopt( my_socket, SOL_SOCKET, SO_LINGER,
+ (char*)&lin, sizeof(struct linger) ) < 0 )
+ {
+ arts_warning("tcp_connect: unable to set socket linger value to %d",
+ lin.l_linger);
+ close(my_socket);
+ return -1;
+ }
+
+#ifdef TCP_NODELAY
+ // enable TCP sending without nagle algorithm - this sends out requests
+ // faster, because they are not queued in the hope that more data will
+ // need to be sent soon
+ int on = 1;
+ if(setsockopt(my_socket, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&on, sizeof(on)) < 0)
+ {
+ arts_debug("couldn't set TCP_NODELAY on socket %d\n", my_socket);
+ }
+#endif
+
+ int rc;
+ rc=connect(my_socket,(struct sockaddr *)remote_addr, sizeof(*remote_addr));
+ if(rc != 0)
+ {
+ arts_warning("tcp_connect: can't connect to server (%s)", url);
+ close(my_socket);
+ return -1;
+ }
+
+ return my_socket;
+}
+
+TCPConnection::TCPConnection(const string& url)
+{
+ fd = tcp_connect(url.c_str());
+ _broken = (fd == -1);
+
+ if(!_broken)
+ {
+ Dispatcher::the()->ioManager()->watchFD(fd,
+ IOType::read|IOType::except|IOType::reentrant,this);
+ initReceive();
+ }
+}
diff --git a/mcop/tcpconnection.h b/mcop/tcpconnection.h
new file mode 100644
index 0000000..654bfe2
--- /dev/null
+++ b/mcop/tcpconnection.h
@@ -0,0 +1,43 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): TCPConnection
+ *
+ * Not part of the public API. Do NOT use it in your apps. Binary incompatible
+ * changes allowed.
+ */
+
+#ifndef TCPCONNECTION_H
+#define TCPCONNECTION_H
+
+#include "socketconnection.h"
+
+namespace Arts {
+
+class TCPConnection :public SocketConnection {
+public:
+ TCPConnection(const std::string& url);
+};
+
+}
+#endif /* TCPCONNECTION_H */
diff --git a/mcop/tcpserver.cc b/mcop/tcpserver.cc
new file mode 100644
index 0000000..d62e28c
--- /dev/null
+++ b/mcop/tcpserver.cc
@@ -0,0 +1,193 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "tcpserver.h"
+#include "socketconnection.h"
+#include "dispatcher.h"
+#define queue cqueue
+#include <arpa/inet.h>
+#undef queue
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "mcoputils.h"
+#include "debug.h"
+
+using namespace std;
+using namespace Arts;
+
+bool TCPServer::running()
+{
+ return socketOk;
+}
+
+TCPServer::TCPServer(Dispatcher *dispatcher)
+{
+ this->dispatcher = dispatcher;
+
+ socketOk = initSocket();
+ if(socketOk) {
+ IOManager *iom = dispatcher->ioManager();
+ iom->watchFD(theSocket,IOType::read|IOType::except,this);
+ }
+}
+
+TCPServer::~TCPServer()
+{
+ if(socketOk)
+ {
+ IOManager *iom = dispatcher->ioManager();
+ iom->remove(this,IOType::read|IOType::except);
+ close(theSocket);
+ }
+}
+
+static int TCPServerPort = 0;
+
+void TCPServer::setPort(int port)
+{
+ TCPServerPort = port;
+}
+
+bool TCPServer::initSocket()
+{
+ struct sockaddr_in socket_addr;
+
+ theSocket = socket(PF_INET,SOCK_STREAM,0);
+ if(theSocket < 0)
+ {
+ arts_warning("MCOP TCPServer: can't create a socket");
+ return false;
+ }
+
+ if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0)
+ {
+ arts_warning("MCOP TCPServer: can't initialize non blocking I/O");
+ close(theSocket);
+ return false;
+ }
+
+ if (TCPServerPort)
+ {
+ int optval = 1;
+ if(setsockopt (theSocket, SOL_SOCKET, SO_REUSEADDR,
+ (const char *)&optval, sizeof (optval)) < 0)
+ {
+ arts_warning("MCOP TCPServer: can't set address reuse");
+ close(theSocket);
+ return false;
+ }
+ }
+
+#ifdef TCP_NODELAY
+ // enable TCP sending without nagle algorithm - this sends out requests
+ // faster, because they are not queued in the hope that more data will
+ // need to be sent soon
+ int on = 1;
+ if(setsockopt(theSocket, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&on, sizeof(on)) < 0)
+ {
+ arts_debug("couldn't set TCP_NODELAY on socket %d\n", theSocket);
+ }
+#endif
+
+ socket_addr.sin_family = AF_INET;
+ socket_addr.sin_port = htons( TCPServerPort ); // 0 = choose port freely
+ socket_addr.sin_addr.s_addr = htonl( inet_addr("0.0.0.0") );
+ if ( bind( theSocket, (struct sockaddr *) &socket_addr,
+ sizeof(struct sockaddr_in) ) < 0 )
+ {
+ arts_warning("MCOP TCPServer: can't bind to port/address");
+ close(theSocket);
+ return false;
+ }
+
+ socklen_t sz = sizeof(struct sockaddr_in);
+ int r = getsockname (theSocket,(struct sockaddr *)&socket_addr, &sz);
+ if(r == 0) {
+ thePort = ntohs(socket_addr.sin_port);
+ }
+ else
+ {
+ arts_warning("MCOP TCPServer: getsockname failed");
+ close(theSocket);
+ return false;
+ }
+
+ if(listen(theSocket,16) < 0)
+ {
+ arts_warning("MCOP TCPServer: can't listen on the socket");
+ close(theSocket);
+ return false;
+ }
+
+ arts_debug("TCPServer: listening on '%s'", url().c_str());
+ return true;
+}
+
+string TCPServer::url()
+{
+ char xport[200];
+ sprintf(xport,"%d",thePort);
+
+ return "tcp:"+MCOPUtils::getFullHostname()+":"+xport;
+}
+
+void TCPServer::notifyIO(int fd, int types)
+{
+ assert(fd == theSocket);
+ assert(socketOk);
+
+ arts_debug("TCPManager: got notifyIO");
+ if(types & IOType::read)
+ {
+ int clientfd;
+ struct sockaddr_in incoming;
+ socklen_t size_in = sizeof(struct sockaddr_in);
+
+ clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in );
+ if(clientfd > 0)
+ {
+ // non blocking I/O
+ int flags = fcntl (fd, F_GETFL, 0);
+ assert (flags != -1);
+
+ int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+ assert(nbl_result >= 0);
+
+ Dispatcher::the()->initiateConnection(
+ new SocketConnection(clientfd));
+ }
+ }
+ arts_assert((types & IOType::write) == 0);
+ arts_assert((types & IOType::except) == 0);
+}
+
+// vim: sw=4 ts=4
diff --git a/mcop/tcpserver.h b/mcop/tcpserver.h
new file mode 100644
index 0000000..93cecca
--- /dev/null
+++ b/mcop/tcpserver.h
@@ -0,0 +1,61 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef TCPSERVER_H
+#define TCPSERVER_H
+
+#include <string>
+#include "arts_export.h"
+#include "iomanager.h"
+/*
+ * BC - Status (2002-03-08): TCPServer
+ *
+ * Not part of the public API. Do NOT use it in your apps. Binary incompatible
+ * changes allowed.
+ */
+
+namespace Arts {
+
+class Dispatcher;
+
+class ARTS_EXPORT TCPServer :public IONotify {
+protected:
+ Dispatcher *dispatcher;
+
+ int theSocket;
+ int thePort;
+ bool socketOk;
+ bool initSocket();
+
+public:
+ TCPServer(Dispatcher *dispatcher);
+ virtual ~TCPServer();
+ bool running();
+ std::string url();
+ static void setPort(int port);
+
+ void notifyIO(int fd, int types);
+};
+
+}
+
+#endif /* TCPSERVER_H */
diff --git a/mcop/thread.cc b/mcop/thread.cc
new file mode 100644
index 0000000..2d81118
--- /dev/null
+++ b/mcop/thread.cc
@@ -0,0 +1,169 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "thread.h"
+#include <string.h>
+
+using namespace Arts;
+
+// Thread:
+Thread::~Thread()
+{
+ delete impl;
+}
+
+Thread_impl::~Thread_impl()
+{
+}
+
+// Mutex:
+Mutex::~Mutex()
+{
+ delete impl;
+}
+
+Mutex_impl::~Mutex_impl()
+{
+}
+
+// ThreadCondition:
+
+ThreadCondition::~ThreadCondition()
+{
+ delete impl;
+}
+
+ThreadCondition_impl::~ThreadCondition_impl()
+{
+}
+
+// Semaphore
+Semaphore::~Semaphore()
+{
+ delete impl;
+}
+
+Semaphore_impl::~Semaphore_impl()
+{
+}
+
+// No threading:
+
+namespace Arts {
+
+class SystemThreadsNoMutex_impl : public Mutex_impl {
+public:
+ void lock() {};
+ bool tryLock() { return true; };
+ void unlock() {};
+};
+
+static Thread *systemThreadsNoneCurrent = 0;
+
+class SystemThreadsNoThread_impl : public Thread_impl {
+private:
+ Thread *thread;
+public:
+ SystemThreadsNoThread_impl(Thread *thread) : thread(thread) {}
+ void setPriority(int) {}
+ void start() {
+ Thread *oldCurrent = systemThreadsNoneCurrent;
+
+ systemThreadsNoneCurrent = thread;
+ thread->run();
+ systemThreadsNoneCurrent = oldCurrent;
+ }
+ void waitDone() {}
+};
+
+class SystemThreadsNoThreadCondition_impl : public ThreadCondition_impl {
+public:
+ void wakeOne() {};
+ void wakeAll() {};
+ void wait(Mutex_impl *) {};
+};
+
+class SystemThreadsNoSemaphore_impl : public Semaphore_impl {
+public:
+ void wait() {}
+ int tryWait() { return 0; }
+ void post() {}
+ int getValue() { return 0; }
+};
+
+class SystemThreadsNone : public SystemThreads {
+public:
+ bool isMainThread() {
+ return (systemThreadsNoneCurrent == 0);
+ }
+ Mutex_impl *createMutex_impl() {
+ return new SystemThreadsNoMutex_impl();
+ }
+ Mutex_impl *createRecMutex_impl() {
+ return new SystemThreadsNoMutex_impl();
+ }
+ Thread_impl *createThread_impl(Thread *thread) {
+ return new SystemThreadsNoThread_impl(thread);
+ }
+ ThreadCondition_impl *createThreadCondition_impl() {
+ return new SystemThreadsNoThreadCondition_impl();
+ }
+ Thread *getCurrentThread() {
+ return systemThreadsNoneCurrent;
+ }
+ Semaphore_impl *createSemaphore_impl(int, int) {
+ return new SystemThreadsNoSemaphore_impl();
+ }
+};
+
+}
+
+static SystemThreadsNone systemThreadsNone;
+static SystemThreads *SystemThreads_the = 0;
+
+SystemThreads *SystemThreads::the()
+{
+ if(!SystemThreads_the) return &systemThreadsNone;
+ return SystemThreads_the;
+}
+
+bool SystemThreads::init(SystemThreads *the)
+{
+ if(SystemThreads_the)
+ return false;
+ else
+ {
+ SystemThreads_the = the;
+ return true;
+ }
+}
+
+bool SystemThreads::supported()
+{
+ return (SystemThreads_the != 0);
+}
+
+SystemThreads::~SystemThreads()
+{
+}
+
+namespace Arts { void ARTS_EXPORT *gslGlobalMutexTable = 0; }
diff --git a/mcop/thread.h b/mcop/thread.h
new file mode 100644
index 0000000..882e596
--- /dev/null
+++ b/mcop/thread.h
@@ -0,0 +1,375 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_MCOP_THREAD_H
+#define ARTS_MCOP_THREAD_H
+
+#include "arts_export.h"
+
+/*
+ * BC - Status (2002-03-08): SystemThreads, Thread, Mutex, ThreadCondition,
+ * Semaphore
+ *
+ * These classes are kept binary compatible. As the threading implementation
+ * can be changed, also
+ *
+ * Thread_impl, Mutex_impl, ThreadCondition_impl and Semaphore_impl need
+ * to remain as they are. The implementation of these depends on what thread
+ * system is used, and can attach the required data as necessary to the
+ * base classes. So i.e. a posix mutex can contain the pthread_mutex_t in
+ * the PosixMutex_impl.
+ */
+
+namespace Arts {
+
+class Mutex_impl;
+class Thread_impl;
+class ThreadCondition_impl;
+class Thread;
+class Semaphore_impl;
+
+/**
+ * Encapsulates the operating system threading facilities
+ */
+class ARTS_EXPORT SystemThreads {
+public:
+ static SystemThreads *the();
+ static bool init(SystemThreads *the);
+
+ /**
+ * Check whether there is threading support available
+ *
+ * If there is no real threading support, the Threading classes try to
+ * gracefully degrade the performance. For instance, locking a mutex will
+ * do * nothing, and calling the start() function of a Thread will execute
+ * it's run function.
+ *
+ * @returns true if there are real threads
+ */
+ static bool supported();
+
+ /**
+ * Check wether the current thread is the main thread
+ *
+ * The main thread is the thread that the application's main() was
+ * executed in. The IOManager event loop will only run in the main
+ * thread.
+ */
+ virtual bool isMainThread() = 0;
+
+ virtual Mutex_impl *createMutex_impl() = 0;
+ virtual Mutex_impl *createRecMutex_impl() = 0;
+ virtual Thread_impl *createThread_impl(Thread *thread) = 0;
+ virtual ThreadCondition_impl *createThreadCondition_impl() = 0;
+ virtual Semaphore_impl *createSemaphore_impl(int, int) = 0;
+ virtual ~SystemThreads();
+
+ /**
+ * Returns a pointer to the current thread, or a null pointer if
+ * we're the main thread (isMainThread() is true).
+ */
+ virtual Thread *getCurrentThread() = 0;
+};
+
+/**
+ * Base class for platform specific thread code
+ */
+class ARTS_EXPORT Thread_impl
+{
+public:
+ virtual void setPriority(int) =0;
+ virtual void start() = 0;
+ virtual void waitDone() = 0;
+ virtual ~Thread_impl();
+};
+
+/**
+ * Base class for platform specific mutex code
+ */
+class ARTS_EXPORT Mutex_impl {
+public:
+ virtual void lock() = 0;
+ virtual bool tryLock() = 0;
+ virtual void unlock() = 0;
+ virtual ~Mutex_impl();
+};
+
+/**
+ * Base class for platform specific thread condition code
+ */
+class ARTS_EXPORT ThreadCondition_impl {
+public:
+ virtual void wakeOne() = 0;
+ virtual void wakeAll() = 0;
+ virtual void wait(Mutex_impl *impl) = 0;
+ virtual ~ThreadCondition_impl();
+};
+
+class ARTS_EXPORT Semaphore_impl {
+public:
+ virtual void wait() = 0;
+ virtual int tryWait() = 0;
+ virtual void post() = 0;
+ virtual int getValue() = 0;
+ virtual ~Semaphore_impl();
+};
+
+/**
+ * A thread of execution
+ *
+ * Example for implementing a thread:
+ *
+ * <pre>
+ * class Counter : public Arts::Thread
+ * {
+ * public:
+ * void run() {
+ * for(int i = 0;i < 10;i++)
+ * {
+ * printf("%d\n",i+1);
+ * sleep(1);
+ * }
+ * }
+ * }; // start the thread with Counter c; c.start();
+ * </pre>
+ */
+class ARTS_EXPORT Thread {
+private:
+ Thread_impl *impl;
+
+public:
+ Thread() : impl(SystemThreads::the()->createThread_impl(this))
+ {
+ }
+
+ virtual ~Thread();
+
+ /**
+ * set the priority parameters for the thread
+ *
+ * FIXME: what should be minimum, maximum, recommended?
+ */
+ inline void setPriority(int priority) {
+ impl->setPriority(priority);
+ }
+
+ /**
+ * starts the run() method in a thread
+ */
+ inline void start()
+ {
+ impl->start();
+ }
+
+ /**
+ * waits until the thread is executed completely
+ */
+ inline void waitDone()
+ {
+ impl->waitDone();
+ }
+
+ /**
+ * implement this method, if you want to create an own thread - then
+ * you can simply call thread.start() to start execution of run() in
+ * a seperate thread
+ */
+ virtual void run() = 0;
+};
+
+/**
+ * A mutex
+ *
+ * To protect a critical section, you can use a mutex, which will ensure that
+ * only one thread at a time can lock it. Here is an example for a thread-safe
+ * random number generator:
+ *
+ * <pre>
+ * class RandomGenerator {
+ * Arts::Mutex mutex;
+ * long seed;
+ * public:
+ * long get() {
+ * mutex.lock();
+ * // do complicated calculation with seed here
+ * mutex.unlock();
+ * return seed;
+ * }
+ * };
+ * </pre>
+ */
+class ARTS_EXPORT Mutex {
+private:
+ Mutex_impl *impl;
+ friend class ThreadCondition;
+
+public:
+ /**
+ * constructor
+ *
+ * @param recursive whether to create a recursive mutex (may be locked by
+ * the same thread more than once), or a normal mutex
+ */
+ inline Mutex(bool recursive = false)
+ : impl(recursive?SystemThreads::the()->createRecMutex_impl()
+ :SystemThreads::the()->createMutex_impl())
+ {
+ }
+
+ /**
+ * destructor
+ */
+ virtual ~Mutex();
+
+ /**
+ * locks the mutex
+ */
+ inline void lock() {
+ impl->lock();
+ }
+
+ /**
+ * tries to lock the mutex, returning immediately in any case (even if
+ * mutex is locked by another thread)
+ *
+ * @returns true if successful (mutex locked), false otherwise
+ */
+ inline bool tryLock() {
+ return impl->tryLock();
+ }
+
+ /**
+ * unlocks the mutex
+ */
+ inline void unlock() {
+ impl->unlock();
+ }
+};
+
+/**
+ * A thread condition
+ *
+ * Thread conditions are used to let a different thread know that a certain
+ * condition might have changed. For instance, if you have a thread that
+ * waits until a counter exceeds a limit, the thread would look like this:
+ *
+ * <pre>
+ * class WaitCounter : public Arts::Thread
+ * {
+ * int counter;
+ * Arts::Mutex mutex;
+ * Arts::ThreadCondition cond;
+ *
+ * public:
+ * WaitCounter() : counter(0) {}
+ *
+ * void run() { // run will terminate once the counter reaches 20
+ * mutex.lock();
+ * while(counter < 20)
+ * cond.wait(mutex);
+ * mutex.unlock();
+ * }
+ *
+ * void inc() { // inc will increment the counter and indicate the change
+ * mutex.lock();
+ * counter++;
+ * cond.wakeOne();
+ * mutex.unlock();
+ * }
+ * };
+ * </pre>
+ */
+class ARTS_EXPORT ThreadCondition {
+private:
+ ThreadCondition_impl *impl;
+
+public:
+ ThreadCondition()
+ : impl(SystemThreads::the()->createThreadCondition_impl())
+ {
+ }
+
+ virtual ~ThreadCondition();
+
+ /**
+ * wakes one waiting thread
+ */
+ inline void wakeOne()
+ {
+ impl->wakeOne();
+ }
+
+ /**
+ * wakes all waiting threads
+ */
+ inline void wakeAll()
+ {
+ impl->wakeAll();
+ }
+
+ /**
+ * Waits until the condition changes. You will need to lock the mutex
+ * before calling this. Internally it will unlock the mutex (to let
+ * others change the condition), and relock it once the wait succeeds.
+ */
+ inline void wait(Mutex& mutex)
+ {
+ impl->wait(mutex.impl);
+ }
+};
+
+class ARTS_EXPORT Semaphore {
+private:
+ Semaphore_impl *impl;
+
+public:
+ Semaphore(int shared=0, int count=0)
+ {
+ impl = SystemThreads::the()->createSemaphore_impl(shared, count);
+ }
+
+ virtual ~Semaphore();
+
+ inline void wait()
+ {
+ impl->wait();
+ }
+
+ inline int tryWait()
+ {
+ return impl->tryWait();
+ }
+
+ inline void post()
+ {
+ impl->post();
+ }
+
+ inline int getValue()
+ {
+ return impl->getValue();
+ }
+};
+
+}
+
+#endif /* ARTS_MCOP_THREAD_H */
diff --git a/mcop/tmpglobalcomm.cc b/mcop/tmpglobalcomm.cc
new file mode 100644
index 0000000..9332bce
--- /dev/null
+++ b/mcop/tmpglobalcomm.cc
@@ -0,0 +1,82 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "common.h"
+#include "mcoputils.h"
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class TmpGlobalComm_impl : virtual public TmpGlobalComm_skel {
+public:
+ bool put(const string& variable, const string& value)
+ {
+ string filename = MCOPUtils::createFilePath(variable);
+
+ int fd = open(filename.c_str(),O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR);
+ if(fd != -1)
+ {
+ int result = write(fd,value.c_str(),value.size());
+
+ assert(result == (int)value.size());
+ close(fd);
+ return true;
+ }
+
+ return false;
+ }
+
+ string get(const string& variable)
+ {
+ string result = "";
+ string filename = MCOPUtils::createFilePath(variable);
+
+ int fd = open(filename.c_str(),O_RDONLY);
+ if(fd != -1)
+ {
+ char buffer[8192];
+ int size = read(fd,buffer,8192);
+ if(size > 0 && size < 8192) {
+ buffer[size] = 0;
+ result = buffer;
+ }
+
+ close(fd);
+ }
+ return result;
+ }
+
+ void erase(const string& variable)
+ {
+ string filename = MCOPUtils::createFilePath(variable);
+ unlink(filename.c_str());
+ }
+};
+
+REGISTER_IMPLEMENTATION(TmpGlobalComm_impl);
+
+}
diff --git a/mcop/trader_impl.cc b/mcop/trader_impl.cc
new file mode 100644
index 0000000..6dd84bd
--- /dev/null
+++ b/mcop/trader_impl.cc
@@ -0,0 +1,345 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "common.h"
+#include "debug.h"
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <cstring>
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+
+// TraderRestriction
+struct TraderRestriction {
+ TraderRestriction(const string& key, const string& value)
+ :key(key), value(value) { }
+
+ string key;
+ string value;
+};
+
+// TraderHelper (internal, no public interface)
+class TraderHelper {
+private:
+ vector<class TraderOffer_impl *> allOffers;
+ static TraderHelper *_instance;
+
+protected:
+ TraderHelper();
+ ~TraderHelper();
+ void addDirectory(const string& directory, const string& iface = "",
+ map< pair<dev_t,ino_t>, bool > *dirsDone = 0);
+
+public:
+ vector<TraderOffer> *doQuery(const vector<TraderRestriction>& query);
+ void load();
+ void unload();
+ static TraderHelper *the();
+ static void shutdown();
+};
+
+// TraderQuery
+class TraderQuery_impl : virtual public TraderQuery_skel {
+private:
+ vector<TraderRestriction> restrictions;
+public:
+ void supports(const string& property, const string& value);
+ vector<TraderOffer> *query();
+};
+
+REGISTER_IMPLEMENTATION(TraderQuery_impl);
+
+// TraderOffer
+class TraderOffer_impl : virtual public TraderOffer_skel {
+private:
+ string _interfaceName;
+ map<string, vector<string> > property;
+
+public:
+ TraderOffer_impl(const string& interfaceName, const string& filename);
+
+ bool match(const vector<TraderRestriction>& restrictions);
+
+ // IDL
+ string interfaceName();
+ vector<string>* getProperty(const string& name);
+};
+
+}
+
+// TraderQuery
+//----------------------------------------------------------------------------
+void TraderQuery_impl::supports(const string& property, const string& value)
+{
+ restrictions.push_back(TraderRestriction(property,value));
+}
+
+vector<TraderOffer> *TraderQuery_impl::query()
+{
+ return TraderHelper::the()->doQuery(restrictions);
+}
+
+// TraderOffer
+//----------------------------------------------------------------------------
+TraderOffer_impl::TraderOffer_impl(const string& interfaceName,
+ const string& filename)
+ :_interfaceName(interfaceName)
+{
+ ifstream file(filename.c_str());
+ string line;
+
+ while(getline(file,line))
+ {
+ string key;
+ vector<string> values;
+
+ if(MCOPUtils::tokenize(line,key,values))
+ property[key] = values;
+ }
+
+ vector<string>& iname = property["InterfaceName"];
+ if(iname.empty())
+ iname.push_back(interfaceName);
+}
+
+bool TraderOffer_impl::match(const vector<TraderRestriction>& restrictions)
+{
+ vector<TraderRestriction>::const_iterator i;
+
+ for(i = restrictions.begin(); i != restrictions.end();i++)
+ {
+ const TraderRestriction& res = *i;
+ const vector<string>& myvalues = property[res.key];
+ bool okay = false;
+
+ vector<string>::const_iterator offerIt = myvalues.begin();
+ while(!okay && offerIt != myvalues.end())
+ {
+ if(res.value == *offerIt)
+ okay = true;
+ else
+ offerIt++;
+ }
+
+ if(!okay) return false;
+ }
+ return true;
+}
+
+string TraderOffer_impl::interfaceName()
+{
+ return _interfaceName;
+}
+
+vector<string>* TraderOffer_impl::getProperty(const string& name)
+{
+ return new vector<string>(property[name]);
+}
+
+// TraderHelper
+//----------------------------------------------------------------------------
+
+TraderHelper::TraderHelper()
+{
+ load();
+}
+
+TraderHelper::~TraderHelper()
+{
+ unload();
+}
+
+void TraderHelper::load()
+{
+ const vector<string> *path = MCOPUtils::traderPath();
+
+ vector<string>::const_iterator pi;
+ for(pi = path->begin(); pi != path->end(); pi++) addDirectory(*pi);
+}
+
+void TraderHelper::unload()
+{
+ vector<TraderOffer_impl *>::iterator i;
+
+ for(i = allOffers.begin(); i != allOffers.end(); i++)
+ {
+ TraderOffer_impl *offer = *i;
+ offer->_release();
+ }
+ allOffers.clear();
+}
+
+void TraderHelper::addDirectory(const string& directory, const string& iface,
+ map< pair<dev_t,ino_t>, bool > *dirsDone)
+{
+ bool created_dirs_done = false;
+ arts_debug("addDirectory(%s,%s)", directory.c_str(), iface.c_str());
+
+ if(!dirsDone)
+ {
+ /* map to prevent doing directories again due to symlinks */
+ dirsDone = new map< pair<dev_t,ino_t>, bool >;
+
+ struct stat st;
+ stat(directory.c_str(), &st);
+ (*dirsDone)[make_pair(st.st_dev, st.st_ino)] = true;
+ created_dirs_done = true;
+ }
+
+ DIR *dir = opendir(directory.c_str());
+ if(!dir) return;
+
+ struct dirent *de;
+ while((de = readdir(dir)) != 0)
+ {
+ string currentEntry = directory + "/" + de->d_name;
+
+ string currentIface = iface;
+ if(!iface.empty()) currentIface += "::";
+ currentIface += de->d_name;
+
+ struct stat st;
+ stat(currentEntry.c_str(),&st);
+
+ // recurse into subdirectories
+ if(S_ISDIR(st.st_mode))
+ {
+ bool& done = (*dirsDone)[make_pair(st.st_dev, st.st_ino)];
+ if(strcmp(de->d_name,".") && strcmp(de->d_name,"..") && !done)
+ {
+ done = true;
+ addDirectory(currentEntry,currentIface,dirsDone);
+ }
+ }
+ else if(S_ISREG(st.st_mode))
+ {
+ if(strlen(de->d_name) > 10 &&
+ strncmp(&de->d_name[strlen(de->d_name)-10],".mcopclass",10) == 0)
+ {
+ // cut .mcopclass for currentIface;
+ currentIface = currentIface.substr(0, currentIface.size()-10);
+ allOffers.push_back(
+ new TraderOffer_impl(currentIface,currentEntry) );
+ }
+ }
+ }
+
+ if (created_dirs_done)
+ delete dirsDone;
+
+ closedir(dir);
+}
+
+static inline int getOfferPreference(TraderOffer offer)
+{
+ int result = 0;
+
+ vector<string> *p = offer.getProperty("Preference");
+ if(!p->empty())
+ result = atoi(p->front().c_str());
+ delete p;
+
+ return result;
+}
+
+static bool traderOfferCmp(TraderOffer offer1, TraderOffer offer2)
+{
+ int p1 = getOfferPreference(offer1);
+ int p2 = getOfferPreference(offer2);
+
+ if(p1 > p2)
+ return true;
+ if(p1 < p2)
+ return false;
+
+ /* if the Preference= entry doesn't indicate which offer is better,
+ * sort the offers by name to make the trader results at least
+ * independant from the order they are read from the file system */
+ return offer1.interfaceName() < offer2.interfaceName();
+}
+
+vector<TraderOffer> *TraderHelper::doQuery(const
+ vector<TraderRestriction>& query)
+{
+ vector<TraderOffer> *result = new vector<TraderOffer>;
+
+ vector<TraderOffer_impl *>::iterator i;
+ for(i = allOffers.begin(); i != allOffers.end(); i++)
+ {
+ TraderOffer_impl *offer = *i;
+
+ if(offer->match(query))
+ {
+ result->push_back(TraderOffer::_from_base(offer->_copy()));
+ }
+ }
+
+ /* sort trader query result by Preference= line for more than one result */
+ if(result->size() > 1)
+ sort(result->begin(), result->end(), traderOfferCmp);
+ return result;
+}
+
+TraderHelper *TraderHelper::_instance = 0;
+TraderHelper *TraderHelper::the()
+{
+ if(!_instance) _instance = new TraderHelper();
+ return _instance;
+}
+
+void TraderHelper::shutdown()
+{
+ if(_instance)
+ {
+ delete _instance;
+ _instance = 0;
+ }
+}
+
+namespace Arts {
+
+// trader shutdown
+class TraderShutdown :public StartupClass
+{
+public:
+ void startup() { };
+ void shutdown() { TraderHelper::shutdown(); };
+};
+
+static TraderShutdown traderShutdown;
+
+}
+
+// Dispatcher function for reloading the trader data:
+void Dispatcher::reloadTraderData()
+{
+ TraderHelper::the()->unload();
+ TraderHelper::the()->load();
+}
diff --git a/mcop/type.cc b/mcop/type.cc
new file mode 100644
index 0000000..541876b
--- /dev/null
+++ b/mcop/type.cc
@@ -0,0 +1,31 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "type.h"
+#include <assert.h>
+
+long Arts::Type::_staticTypeCount = 0;
+
+Arts::Type::~Type()
+{
+ _staticTypeCount--;
+}
diff --git a/mcop/type.h b/mcop/type.h
new file mode 100644
index 0000000..2f95d20
--- /dev/null
+++ b/mcop/type.h
@@ -0,0 +1,85 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef TYPE_H
+#define TYPE_H
+
+#include "arts_export.h"
+#include "buffer.h"
+
+/*
+ * BC - Status (2002-03-08): Type
+ *
+ * Keep binary compatible. DO NOT TOUCH, DO NOT CHANGE.
+ */
+
+namespace Arts {
+
+/**
+ * Base class for the IDL mapping of struct-like types
+ */
+class ARTS_EXPORT Type {
+private:
+ static long _staticTypeCount;
+
+public:
+ inline static long _typeCount() { return _staticTypeCount; }
+ /**
+ * constructor
+ */
+ inline Type()
+ {
+ _staticTypeCount++;
+ }
+
+ /**
+ * copy constructor
+ */
+ inline Type(const Type&)
+ {
+ _staticTypeCount++;
+ }
+
+ /**
+ * virtual destructor (since we have virtual functions and this stuff
+ */
+ virtual ~Type();
+
+ /**
+ * read the type from a stream
+ */
+ virtual void readType(Buffer& stream) = 0;
+
+ /**
+ * write the type to a stream
+ */
+ virtual void writeType(Buffer& stream) const = 0;
+
+ /**
+ * type name
+ */
+ virtual std::string _typeName() const = 0;
+};
+
+}
+
+#endif
diff --git a/mcop/unixconnection.cc b/mcop/unixconnection.cc
new file mode 100644
index 0000000..adda10d
--- /dev/null
+++ b/mcop/unixconnection.cc
@@ -0,0 +1,114 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "unixconnection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdlib.h>
+
+using namespace std;
+using namespace Arts;
+
+static struct sockaddr_un *parse_unix_url(const char *url)
+{
+ static struct sockaddr_un addr;
+
+ char *work = strdup(url);
+
+ char *type = strtok(work,":");
+ if(type == 0 || strcmp(type,"unix") != 0) {
+ free(work);
+ return 0;
+ }
+
+ char *path = strtok(NULL,":\n");
+ if(path == 0) {
+ free(work);
+ return 0;
+ }
+
+ int maxlen = sizeof(addr.sun_path);
+ memset((void *) &addr, '\0', sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path,path,maxlen);
+ addr.sun_path[maxlen-1] = 0;
+ free(work);
+ return &addr;
+}
+
+static int unix_connect(const char *url)
+{
+ struct sockaddr_un *remote_addr = parse_unix_url(url);
+ if(remote_addr == 0)
+ {
+ arts_warning("unix_connect: couldn't parse url %s",url);
+ return -1;
+ }
+
+ int my_socket = socket(AF_UNIX,SOCK_STREAM,0);
+ if(my_socket < 0)
+ {
+ arts_warning("unix_connect: unable to open socket for read");
+ return -1;
+ }
+
+ struct linger lin;
+ lin.l_onoff=1; /* block a closing socket for 1 second */
+ lin.l_linger=100; /* if data is waiting to be sent */
+ if ( setsockopt( my_socket, SOL_SOCKET, SO_LINGER,
+ (char*)&lin, sizeof(struct linger) ) < 0 )
+ {
+ arts_warning("unix_connect: unable to set socket linger value to %d",
+ lin.l_linger);
+ close(my_socket);
+ return -1;
+ }
+
+ int rc;
+ rc=connect(my_socket,(struct sockaddr *)remote_addr, sizeof(*remote_addr));
+ if(rc != 0)
+ {
+ arts_warning("unix_connect: can't connect to server (%s)",url);
+ close(my_socket);
+ return -1;
+ }
+
+ return my_socket;
+}
+
+UnixConnection::UnixConnection(const string& url)
+{
+ fd = unix_connect(url.c_str());
+ _broken = (fd == -1);
+
+ if(!_broken)
+ {
+ Dispatcher::the()->ioManager()->watchFD(fd,
+ IOType::read|IOType::except|IOType::reentrant,this);
+ initReceive();
+ }
+}
diff --git a/mcop/unixconnection.h b/mcop/unixconnection.h
new file mode 100644
index 0000000..54a5643
--- /dev/null
+++ b/mcop/unixconnection.h
@@ -0,0 +1,43 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): UnixConnection
+ *
+ * Not part of the public API. Do NOT use it in your apps. Can change, even
+ * binary incompatible.
+ */
+
+#ifndef UNIXCONNECTION_H
+#define UNIXCONNECTION_H
+
+#include "socketconnection.h"
+
+namespace Arts {
+
+class UnixConnection :public SocketConnection {
+public:
+ UnixConnection(const std::string& url);
+};
+
+}
+#endif /* UNIXCONNECTION_H */
diff --git a/mcop/unixserver.cc b/mcop/unixserver.cc
new file mode 100644
index 0000000..65cfa76
--- /dev/null
+++ b/mcop/unixserver.cc
@@ -0,0 +1,151 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <config.h>
+#include "mcoputils.h"
+#include "unixserver.h"
+#include "socketconnection.h"
+#include "dispatcher.h"
+#include "debug.h"
+#define queue cqueue
+#include <arpa/inet.h>
+#undef queue
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+using namespace std;
+using namespace Arts;
+
+bool UnixServer::running()
+{
+ return socketOk;
+}
+
+UnixServer::UnixServer(Dispatcher *dispatcher, const string& serverID)
+{
+ this->dispatcher = dispatcher;
+
+ socketOk = initSocket(serverID);
+ if(socketOk) {
+ IOManager *iom = dispatcher->ioManager();
+ iom->watchFD(theSocket,IOType::read|IOType::except,this);
+ }
+}
+
+UnixServer::~UnixServer()
+{
+ if(socketOk) {
+ IOManager *iom = dispatcher->ioManager();
+ iom->remove(this,IOType::read|IOType::except);
+ close(theSocket);
+ unlink(xserverpath.c_str());
+ }
+}
+
+bool UnixServer::initSocket(const string& serverID)
+{
+ struct sockaddr_un socket_addr;
+
+ theSocket = socket(PF_UNIX,SOCK_STREAM,0);
+ if(theSocket < 0)
+ {
+ arts_warning("MCOP UnixServer: can't create a socket");
+ return false;
+ }
+
+ if(fcntl(theSocket,F_SETFL,O_NONBLOCK)<0)
+ {
+ arts_warning("MCOP UnixServer: can't initialize non blocking I/O");
+ close(theSocket);
+ return false;
+ }
+
+ int maxlen = sizeof(socket_addr.sun_path);
+ string pathname = MCOPUtils::createFilePath(serverID);
+
+ socket_addr.sun_family = AF_UNIX;
+ strncpy(socket_addr.sun_path,pathname.c_str(),maxlen);
+ socket_addr.sun_path[maxlen-1] = 0;
+
+ xserverpath = socket_addr.sun_path;
+
+ if ( bind( theSocket, (struct sockaddr *) &socket_addr,
+ sizeof(struct sockaddr_un) ) < 0 )
+ {
+ arts_warning("MCOP UnixServer: can't bind to file \"%s\"",
+ pathname.c_str());
+ close(theSocket);
+ return false;
+ }
+
+ if(listen(theSocket,16) < 0)
+ {
+ arts_warning("MCOP UnixServer: can't listen on the socket");
+ close(theSocket);
+ return false;
+ }
+ return true;
+}
+
+string UnixServer::url()
+{
+ return string("unix:") + xserverpath;
+}
+
+void UnixServer::notifyIO(int fd, int types)
+{
+ assert(fd == theSocket);
+ assert(socketOk);
+
+ arts_debug("UnixManager: got notifyIO");
+ if(types & IOType::read)
+ {
+ int clientfd;
+ struct sockaddr_un incoming;
+ socklen_t size_in = sizeof(struct sockaddr_un);
+
+ clientfd = accept(theSocket, (struct sockaddr*) &incoming, &size_in );
+ if(clientfd > 0)
+ {
+ // non blocking I/O
+ int flags = fcntl (fd, F_GETFL, 0);
+ assert (flags != -1);
+
+ int nbl_result = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+ assert(nbl_result >= 0);
+
+ Dispatcher::the()->initiateConnection(
+ new SocketConnection(clientfd));
+ }
+ }
+ arts_assert((types & IOType::write) == 0);
+ arts_assert((types & IOType::except) == 0);
+}
diff --git a/mcop/unixserver.h b/mcop/unixserver.h
new file mode 100644
index 0000000..b492e39
--- /dev/null
+++ b/mcop/unixserver.h
@@ -0,0 +1,59 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): UnixServer
+ *
+ * Not part of the public API. Do NOT use it in your apps. Can change, even
+ * binary incompatible.
+ */
+
+#ifndef UNIXSERVER_H
+#define UNIXSERVER_H
+
+#include <string>
+#include "iomanager.h"
+
+namespace Arts {
+
+class Dispatcher;
+
+class UnixServer :public IONotify {
+protected:
+ Dispatcher *dispatcher;
+
+ std::string xserverpath;
+ int theSocket;
+ bool socketOk;
+ bool initSocket(const std::string& serverID);
+
+public:
+ UnixServer(Dispatcher *dispatcher, const std::string& serverID);
+ virtual ~UnixServer();
+ bool running();
+ std::string url();
+
+ void notifyIO(int fd, int types);
+};
+
+}
+#endif /* UNIXSERVER_H */
diff --git a/mcop/weakreference.h b/mcop/weakreference.h
new file mode 100644
index 0000000..76bb381
--- /dev/null
+++ b/mcop/weakreference.h
@@ -0,0 +1,131 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): WeakReference(Base)
+ *
+ * Has to be kept binary compatible by not touching it. Add a new class if
+ * you need something else.
+ */
+
+#ifndef MCOP_WEAKREFERENCE_H
+#define MCOP_WEAKREFERENCE_H
+
+#include "arts_export.h"
+
+namespace Arts {
+
+class ARTS_EXPORT WeakReferenceBase {
+public:
+ virtual void release() = 0;
+};
+
+/**
+ * The WeakReference class can be used to safely store an object, without
+ * disallowing that it gets destroyed. A typical situation where you may want
+ * to use this is when you implement a datastructure, where A refers B, and
+ * B refers A. Using "normal" references, this structure would never get
+ * freed.
+ *
+ * Usage example:
+ *
+ * Synth_WAVE_SIN sin;
+ * WeakReference<Synth_PLAY_WAV> weak_sin;
+ *
+ * {
+ * Synth_WAVE_SIN test = weak_sin;
+ * if(test.isNull())
+ * printf("#1 missing object\n");
+ * else
+ * test.start();
+ * }
+ *
+ * // now, the strong reference leaves
+ * sin = Synth_WAVE_SIN::null();
+ *
+ * {
+ * Synth_WAVE_SIN test = weak_sin;
+ * if(test.isNull())
+ * printf("#2 missing object\n");
+ * else
+ * test.stop();
+ *
+ * This would output "#2 missing object".
+ *
+ */
+
+template<class SmartWrapper>
+class WeakReference : public WeakReferenceBase
+{
+private:
+ typename SmartWrapper::_base_class *content;
+
+public:
+ WeakReference()
+ {
+ content = 0;
+ }
+ WeakReference(const WeakReference<SmartWrapper>& source)
+ :WeakReferenceBase(source), content(source.content)
+ {
+ if(content)
+ content->_addWeakReference(this);
+ }
+ WeakReference(SmartWrapper& source)
+ {
+ content = source._base();
+ if(content)
+ content->_addWeakReference(this);
+ }
+ inline WeakReference<SmartWrapper>& operator=(const
+ WeakReference<SmartWrapper>& source)
+ {
+ release();
+ content = source.content;
+ if(content)
+ content->_addWeakReference(this);
+ return *this;
+ }
+ virtual ~WeakReference()
+ {
+ release();
+ }
+ void release()
+ {
+ if(content)
+ {
+ content->_removeWeakReference(this);
+ content = 0;
+ }
+ }
+ inline operator SmartWrapper() const
+ {
+ if(content)
+ return SmartWrapper::_from_base(content->_copy());
+ else
+ return SmartWrapper::null();
+ }
+};
+
+}
+
+#endif /* MCOP_WEAKREFERENCE_H */
diff --git a/mcop_mt/Makefile.am b/mcop_mt/Makefile.am
new file mode 100644
index 0000000..70cce62
--- /dev/null
+++ b/mcop_mt/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop -I$(top_srcdir)/flow -I$(top_builddir)/flow $(all_includes)
+
+lib_LTLIBRARIES = libmcop_mt.la
+
+libmcop_mt_la_SOURCES = threads_posix.cc
+libmcop_mt_la_LIBADD = $(top_builddir)/mcop/libmcop.la \
+ $(top_builddir)/flow/libartsflow.la $(LIBPTHREAD) \
+ $(LIBPOSIX4) $(LIBSEM)
+libmcop_mt_la_LDFLAGS = -no-undefined -version-info 1:0 $(USE_THREADS) $(all_libraries)
diff --git a/mcop_mt/threads_posix.cc b/mcop_mt/threads_posix.cc
new file mode 100644
index 0000000..771d0fc
--- /dev/null
+++ b/mcop_mt/threads_posix.cc
@@ -0,0 +1,399 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* only compile this if we have libpthread available */
+#ifdef HAVE_LIBPTHREAD
+
+#include <gsl/gslconfig.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <debug.h>
+#include <string.h>
+
+#include "thread.h"
+
+/*
+ * define this if you want to protect mutexes against being locked twice by
+ * the same thread
+ */
+#undef PTHREAD_DEBUG
+
+namespace Arts {
+
+extern void *gslGlobalMutexTable;
+
+namespace PosixThreads {
+
+class ThreadCondition_impl;
+
+class Mutex_impl : public Arts::Mutex_impl {
+protected:
+ friend class ThreadCondition_impl;
+ pthread_mutex_t mutex;
+
+#ifdef PTHREAD_DEBUG
+ pthread_t owner;
+#endif
+
+public:
+ Mutex_impl()
+ {
+ pthread_mutex_init(&mutex, 0);
+#ifdef PTHREAD_DEBUG
+ owner = 0;
+#endif
+ }
+ void lock()
+ {
+#ifdef PTHREAD_DEBUG
+ pthread_t self = pthread_self();
+ arts_assert(owner != self);
+#endif
+
+ pthread_mutex_lock(&mutex);
+
+#ifdef PTHREAD_DEBUG
+ arts_assert(!owner);
+ owner = self;
+#endif
+ }
+ bool tryLock()
+ {
+#ifdef PTHREAD_DEBUG
+ pthread_t self = pthread_self();
+ arts_assert(owner != self);
+#endif
+
+ int result = pthread_mutex_trylock(&mutex);
+
+#ifdef PTHREAD_DEBUG
+ if(result == 0)
+ {
+ arts_assert(!owner);
+ owner = self;
+ }
+#endif
+ return(result == 0);
+ }
+ void unlock()
+ {
+#ifdef PTHREAD_DEBUG
+ arts_assert(owner == pthread_self());
+ owner = 0;
+#endif
+
+ pthread_mutex_unlock(&mutex);
+ }
+};
+
+class RecMutex_impl : public Arts::Mutex_impl {
+protected:
+ friend class ThreadCondition_impl;
+ pthread_mutex_t mutex;
+ pthread_t owner;
+ int count;
+
+public:
+ RecMutex_impl()
+ {
+ pthread_mutex_init(&mutex, 0);
+ owner = 0;
+ count = 0;
+ }
+ void lock()
+ {
+ pthread_t self = pthread_self();
+ if(owner != self)
+ {
+ pthread_mutex_lock(&mutex);
+#ifdef PTHREAD_DEBUG
+ arts_assert(count == 0);
+ arts_assert(!owner);
+#endif
+ owner = self;
+ }
+ count++;
+ }
+ bool tryLock()
+ {
+ pthread_t self = pthread_self();
+ if(owner != self)
+ {
+ int result = pthread_mutex_trylock(&mutex);
+ if(result != 0)
+ return false;
+
+#ifdef PTHREAD_DEBUG
+ arts_assert(count == 0);
+ arts_assert(!owner);
+#endif
+ owner = self;
+ }
+ count++;
+ return true;
+ }
+ void unlock()
+ {
+#ifdef PTHREAD_DEBUG
+ arts_assert(owner == pthread_self());
+ arts_assert(count > 0);
+#endif
+
+ count--;
+ if(count == 0)
+ {
+ owner = 0;
+ pthread_mutex_unlock(&mutex);
+ }
+ }
+};
+
+
+class Thread_impl : public Arts::Thread_impl {
+protected:
+ friend class PosixThreads;
+ pthread_t pthread;
+ Thread *thread;
+
+public:
+ Thread_impl(Thread *thread) : thread(thread) {
+ }
+ void setPriority(int priority) {
+ struct sched_param sp;
+ sp.sched_priority = priority;
+ if (pthread_setschedparam(pthread, SCHED_FIFO, &sp))
+ arts_debug("Thread::setPriority: sched_setscheduler failed");
+ }
+ static pthread_key_t privateDataKey;
+ static void *threadStartInternal(void *impl)
+ {
+ pthread_setspecific(privateDataKey, impl);
+
+ ((Thread_impl *)impl)->thread->run();
+ return 0;
+ }
+ void start() {
+ pthread_create(&pthread,0,threadStartInternal,this);
+ }
+ void waitDone() {
+ void *foo;
+ pthread_join(pthread,&foo);
+ }
+};
+
+pthread_key_t Thread_impl::privateDataKey;
+
+class ThreadCondition_impl : public Arts::ThreadCondition_impl {
+protected:
+ pthread_cond_t cond;
+
+public:
+ ThreadCondition_impl() {
+ pthread_cond_init(&cond, 0);
+ }
+ ~ThreadCondition_impl() {
+ pthread_cond_destroy(&cond);
+ }
+ void wakeOne() {
+ pthread_cond_signal(&cond);
+ }
+ void wakeAll() {
+ pthread_cond_broadcast(&cond);
+ }
+ void wait(Arts::Mutex_impl *mutex) {
+#ifdef PTHREAD_DEBUG
+ pthread_t self = pthread_self();
+ arts_assert(((Mutex_impl *)mutex)->owner == self);
+ ((Mutex_impl *)mutex)->owner = 0;
+#endif
+
+ pthread_cond_wait(&cond, &((Mutex_impl*)mutex)->mutex);
+
+#ifdef PTHREAD_DEBUG
+ arts_assert(((Mutex_impl *)mutex)->owner == 0);
+ ((Mutex_impl *)mutex)->owner = self;
+#endif
+ }
+};
+
+class Semaphore_impl : public Arts::Semaphore_impl
+{
+private:
+ sem_t semaphore;
+
+public:
+ Semaphore_impl(int shared, int count) {
+ sem_init(&semaphore, shared, count);
+ }
+
+ ~Semaphore_impl() {
+ sem_destroy(&semaphore);
+ }
+
+ void wait() {
+ sem_wait(&semaphore);
+ }
+
+ int tryWait() {
+ return sem_trywait(&semaphore);
+ }
+
+ void post() {
+ sem_post(&semaphore);
+ }
+
+ int getValue() {
+ int retval;
+ sem_getvalue(&semaphore, &retval);
+ return retval;
+ }
+};
+
+class PosixThreads : public SystemThreads {
+private:
+ pthread_t mainThread;
+public:
+ PosixThreads() {
+ mainThread = pthread_self();
+ }
+ bool isMainThread() {
+ return pthread_equal(pthread_self(), mainThread);
+ }
+ Arts::Mutex_impl *createMutex_impl() {
+ return new Mutex_impl();
+ }
+ Arts::Mutex_impl *createRecMutex_impl() {
+ return new RecMutex_impl();
+ }
+ Arts::Thread_impl *createThread_impl(Arts::Thread *thread) {
+ return new Thread_impl(thread);
+ }
+ Arts::ThreadCondition_impl *createThreadCondition_impl() {
+ return new ThreadCondition_impl();
+ }
+ Thread *getCurrentThread() {
+ void *data = pthread_getspecific(Thread_impl::privateDataKey);
+
+ if(data)
+ return ((Thread_impl *)data)->thread;
+ else
+ return 0; /* main thread */
+ }
+ Arts::Semaphore_impl *createSemaphore_impl(int shared, int count) {
+ return new Semaphore_impl(shared, count);
+ }
+};
+
+// set posix threads on startup
+static class SetSystemThreads {
+private:
+ PosixThreads posixThreads;
+
+public:
+ SetSystemThreads() {
+ if(pthread_key_create(&Thread_impl::privateDataKey, 0))
+ arts_debug("SystemThreads init: pthread_key_create failed");
+
+ SystemThreads::init(&posixThreads);
+
+ }
+ ~SetSystemThreads() {
+ SystemThreads::init(0);
+
+ if(pthread_key_delete(Thread_impl::privateDataKey))
+ arts_debug("SystemThreads init: pthread_key_delete failed");
+ }
+} initOnStartup;
+
+#include <gsl/gslcommon.h>
+/* -fast- locking for gsl on platforms with unix98 support */
+#if (GSL_HAVE_MUTEXATTR_SETTYPE > 0)
+static void pth_mutex_init (GslMutex *mutex)
+{
+ /* need NULL attribute here, which is the fast mutex on glibc
+ * and cannot be chosen through the pthread_mutexattr_settype()
+ */
+ pthread_mutex_init ((pthread_mutex_t*) mutex, NULL);
+}
+static void pth_rec_mutex_init (GslRecMutex *mutex)
+{
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init (&attr);
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init ((pthread_mutex_t*) mutex, &attr);
+ pthread_mutexattr_destroy (&attr);
+}
+static void pth_rec_cond_init (GslCond *cond)
+{
+ pthread_cond_init ((pthread_cond_t*) cond, NULL);
+}
+static void pth_rec_cond_wait_timed (GslCond *cond, GslMutex *mutex,
+ gulong abs_secs, gulong abs_usecs)
+{
+ struct timespec abstime;
+
+ abstime.tv_sec = abs_secs;
+ abstime.tv_nsec = abs_usecs * 1000;
+ pthread_cond_timedwait ((pthread_cond_t*) cond, (pthread_mutex_t*) mutex, &abstime);
+}
+static GslMutexTable pth_mutex_table = {
+ pth_mutex_init,
+ (void (*) (GslMutex*)) pthread_mutex_lock,
+ (int (*) (GslMutex*)) pthread_mutex_trylock,
+ (void (*) (GslMutex*)) pthread_mutex_unlock,
+ (void (*) (GslMutex*)) pthread_mutex_destroy,
+ pth_rec_mutex_init,
+ (void (*) (GslRecMutex*)) pthread_mutex_lock,
+ (int (*) (GslRecMutex*)) pthread_mutex_trylock,
+ (void (*) (GslRecMutex*)) pthread_mutex_unlock,
+ (void (*) (GslRecMutex*)) pthread_mutex_destroy,
+ pth_rec_cond_init,
+ (void (*) (GslCond*)) pthread_cond_signal,
+ (void (*) (GslCond*)) pthread_cond_broadcast,
+ (void (*) (GslCond*, GslMutex*)) pthread_cond_wait,
+ pth_rec_cond_wait_timed,
+ (void (*) (GslCond*)) pthread_cond_destroy,
+};
+
+static class SetGslMutexTable {
+public:
+ SetGslMutexTable()
+ {
+ gslGlobalMutexTable = &pth_mutex_table;
+ }
+} initGslMutexTable;
+#endif
+
+}
+
+}
+
+#endif
diff --git a/mcopidl/Makefile.am b/mcopidl/Makefile.am
new file mode 100644
index 0000000..da189e5
--- /dev/null
+++ b/mcopidl/Makefile.am
@@ -0,0 +1,19 @@
+KDE_CXXFLAGS = $(NOOPT_CXXFLAGS)
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop $(all_includes)
+####### Files
+
+bin_PROGRAMS = mcopidl
+
+mcopidl_SOURCES = mcopidl.cc yacc.cc scanner.cc namespace.cc
+mcopidl_LDFLAGS = $(all_libraries)
+mcopidl_LDADD = ../mcop/libmcop.la $(LIBPTHREAD)
+noinst_HEADERS = yacc.cc.h
+
+mcopidl.o: $(top_srcdir)/mcop/common.h
+
+####### Build rules
+
+parser:
+ cd $(srcdir) && flex -B -8 -oscanner.cc scanner.ll ;\
+ bison -d -t -o yacc.cc yacc.yy
+
diff --git a/mcopidl/mcopidl.cc b/mcopidl/mcopidl.cc
new file mode 100644
index 0000000..2f8ff23
--- /dev/null
+++ b/mcopidl/mcopidl.cc
@@ -0,0 +1,2645 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld, stefan@space.twc.de
+ Nicolas Brodu, nicolas.brodu@free.fr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include <cstdlib>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+#include <list>
+#include <stack>
+#include <ctype.h>
+#include "common.h"
+#include "namespace.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+int idl_in_include;
+int idl_line_no;
+string idl_filename;
+
+/*
+ * if we start parsing an include file, we push the name of the file
+ * and the line number where we left it on the stack for later usage
+ */
+stack<pair<int,string> > idl_include_stack;
+
+list<EnumDef> enums;
+list<TypeDef> structs;
+list<InterfaceDef> interfaces;
+list<string> packetTypes; // just an evil hack to get experimental video
+list<string> customIncludes; // just an evil hack to get experimental video
+list<string> includes; // files to include
+list<string> includePath; // path for the includes
+
+// names that occur in included files -> no code generation
+list<string> includedNames;
+
+ModuleDef module;
+
+void addEnumTodo( const EnumDef& edef )
+{
+ enums.push_back(edef);
+
+ if(idl_in_include)
+ {
+ includedNames.push_back(edef.name);
+ }
+ else
+ {
+ module.enums.push_back(edef);
+ }
+}
+
+void addStructTodo( const TypeDef& type )
+{
+ structs.push_back(type);
+
+ if(idl_in_include)
+ {
+ includedNames.push_back(type.name);
+ }
+ else
+ {
+ module.types.push_back(type);
+ }
+}
+
+void addInterfaceTodo( const InterfaceDef& iface )
+{
+ interfaces.push_back(iface);
+
+ if(idl_in_include)
+ {
+ includedNames.push_back(iface.name);
+ }
+ else
+ {
+ module.interfaces.push_back(iface);
+ }
+}
+
+bool fromInclude(string name)
+{
+ list<string>::iterator i;
+
+ for(i=includedNames.begin(); i != includedNames.end();i++)
+ if(*i == name) return true;
+
+ return false;
+}
+
+void startInclude( const char *line )
+{
+ const char *file = "*unknown*";
+ char *l = strdup(line);
+ char *a = strtok(l,"<\"");
+ if(a)
+ {
+ char *b = strtok(0,">\"");
+ if(b) file = b;
+ }
+
+ idl_in_include++;
+ idl_include_stack.push(make_pair(idl_line_no, idl_filename));
+ idl_line_no = 0;
+ idl_filename = file;
+ free(l);
+}
+
+void endInclude()
+{
+ assert(!idl_include_stack.empty());
+ idl_line_no = idl_include_stack.top().first;
+ idl_filename = idl_include_stack.top().second;
+ idl_include_stack.pop();
+
+ idl_in_include--;
+}
+
+bool isPacketType( string type )
+{
+ list<string>::iterator i;
+
+ for(i=packetTypes.begin();i != packetTypes.end(); i++)
+ if((*i) == type) return true;
+
+ return false;
+}
+
+bool isStruct( string type )
+{
+ list<TypeDef>::iterator i;
+
+ for(i=structs.begin();i != structs.end(); i++)
+ if(i->name == type) return true;
+
+ return false;
+}
+
+bool isEnum( string type )
+{
+ list<EnumDef>::iterator i;
+
+ for(i=enums.begin();i != enums.end(); i++)
+ if(i->name == type) return true;
+
+ return false;
+}
+
+bool isInterface( string type )
+{
+ list<InterfaceDef>::iterator i;
+
+ for(i=interfaces.begin();i != interfaces.end(); i++)
+ if(i->name == type) return true;
+
+ return (type == "object");
+}
+
+string formatMultiLineString(string s, string indent)
+{
+ string result = indent+"\"";
+ string::iterator si = s.begin();
+
+ int lineLen = 80-indent.size()-6;
+ int i = 0;
+
+ while(si != s.end())
+ {
+ if(i == lineLen)
+ {
+ result += "\"\n" + indent + "\"";
+ i = 0;
+ }
+
+ result += *si++;
+ i++;
+ }
+ return result+"\"";
+}
+
+#define MODEL_MEMBER 1
+#define MODEL_ARG 2
+#define MODEL_READ 3
+#define MODEL_REQ_READ 4
+#define MODEL_RES_READ 5
+#define MODEL_WRITE 6
+#define MODEL_REQ_WRITE 7
+#define MODEL_RESULT 8
+#define MODEL_INVOKE 9
+#define MODEL_STREAM 10
+#define MODEL_MSTREAM 11
+#define MODEL_ASTREAM 12
+#define MODEL_AMSTREAM 13
+#define MODEL_ASTREAM_PACKETPTR 14
+#define MODEL_SEQ 1024
+
+#define MODEL_MEMBER_SEQ (MODEL_MEMBER|MODEL_SEQ)
+#define MODEL_ARG_SEQ (MODEL_ARG|MODEL_SEQ)
+#define MODEL_READ_SEQ (MODEL_READ|MODEL_SEQ)
+#define MODEL_WRITE_SEQ (MODEL_WRITE|MODEL_SEQ)
+#define MODEL_REQ_READ_SEQ (MODEL_REQ_READ|MODEL_SEQ)
+#define MODEL_RES_READ_SEQ (MODEL_RES_READ|MODEL_SEQ)
+#define MODEL_REQ_WRITE_SEQ (MODEL_REQ_WRITE|MODEL_SEQ)
+#define MODEL_RESULT_SEQ (MODEL_RESULT|MODEL_SEQ)
+#define MODEL_INVOKE_SEQ (MODEL_INVOKE|MODEL_SEQ)
+
+/**
+ * generates a piece of code for the specified type/name
+ *
+ * model determines if the code is a parameter declaration, type member
+ * declaration, write-to-stream code for, read-from-stream code or whatever
+ * else
+ */
+string createTypeCode(string type, const string& name, long model,
+ string indent = "")
+{
+ string result = "";
+
+ if(type.length() >= 1 && type[0] == '*')
+ {
+ model |= MODEL_SEQ;
+ type = type.substr(1,type.length()-1);
+ }
+
+ if(type == "void")
+ {
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if(result) delete result;\n";
+ }
+ else if(model==MODEL_INVOKE)
+ {
+ result = indent + name+";\n";
+ }
+ else
+ {
+ result = "void";
+ }
+ }
+ else if(type == "float")
+ {
+ if(model==MODEL_MEMBER) result = "float";
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<float>";
+ if(model==MODEL_ARG) result = "float";
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<float>&";
+ if(model==MODEL_RESULT) result = "float";
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<float> *";
+ if(model==MODEL_STREAM) result = "float *"+name;
+ if(model==MODEL_MSTREAM) result = "float **"+name;
+ if(model==MODEL_ASTREAM) result = "Arts::FloatAsyncStream "+name;
+ if(model==MODEL_AMSTREAM) assert(false);
+ if(model==MODEL_ASTREAM_PACKETPTR) result = "Arts::DataPacket<float> *";
+ if(model==MODEL_READ)
+ result = name+" = stream.readFloat()";
+ if(model==MODEL_READ_SEQ)
+ result = "stream.readFloatSeq("+name+")";
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if(!result) return 0.0; // error occurred\n";
+ result += indent + "float returnCode = result->readFloat();\n";
+ result += indent + "delete result;\n";
+ result += indent + "return returnCode;\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<float> *_returnCode ="
+ " new std::vector<float>;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "result->readFloatSeq(*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_REQ_READ)
+ result = indent + "float "+name+" = request->readFloat();\n";
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<float> "+name+";\n"
+ + indent + "request->readFloatSeq("+name+");\n";
+ if(model==MODEL_WRITE)
+ result = "stream.writeFloat("+name+")";
+ if(model==MODEL_WRITE_SEQ)
+ result = "stream.writeFloatSeq("+name+")";
+ if(model==MODEL_REQ_WRITE)
+ result = "request->writeFloat("+name+")";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "request->writeFloatSeq("+name+")";
+ if(model==MODEL_INVOKE)
+ result = indent + "result->writeFloat("+name+");\n";
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<float> *_returnCode = "+name+";\n"
+ + indent + "result->writeFloatSeq(*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ }
+ else if(type == "boolean")
+ {
+ if(model==MODEL_MEMBER) result = "bool";
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<bool>";
+ if(model==MODEL_ARG) result = "bool";
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<bool>&";
+ if(model==MODEL_RESULT) result = "bool";
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<bool> *";
+ if(model==MODEL_READ)
+ result = name+" = stream.readBool()";
+ if(model==MODEL_READ_SEQ)
+ result = "stream.readBoolSeq("+name+")";
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if(!result) return false; // error occurred\n";
+ result += indent + "bool returnCode = result->readBool();\n";
+ result += indent + "delete result;\n";
+ result += indent + "return returnCode;\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<bool> *_returnCode ="
+ " new std::vector<bool>;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "result->readBoolSeq(*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_REQ_READ)
+ result = indent + "bool "+name+" = request->readBool();\n";
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<bool> "+name+";\n"
+ + indent + "request->readBoolSeq("+name+");\n";
+ if(model==MODEL_WRITE)
+ result = "stream.writeBool("+name+")";
+ if(model==MODEL_WRITE_SEQ)
+ result = "stream.writeBoolSeq("+name+")";
+ if(model==MODEL_REQ_WRITE)
+ result = "request->writeBool("+name+")";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "request->writeBoolSeq("+name+")";
+ if(model==MODEL_INVOKE)
+ result = indent + "result->writeBool("+name+");\n";
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<bool> *_returnCode = "+name+";\n"
+ + indent + "result->writeBoolSeq(*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ }
+ else if(type == "byte")
+ {
+ if(model==MODEL_MEMBER) result = "Arts::mcopbyte";
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<Arts::mcopbyte>";
+ if(model==MODEL_ARG) result = "Arts::mcopbyte";
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<Arts::mcopbyte>&";
+ if(model==MODEL_RESULT) result = "Arts::mcopbyte";
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<Arts::mcopbyte> *";
+ if(model==MODEL_READ)
+ result = name+" = stream.readByte()";
+ if(model==MODEL_READ_SEQ)
+ result = "stream.readByteSeq("+name+")";
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if(!result) return 0; // error occurred\n";
+ result += indent + "Arts::mcopbyte returnCode = result->readByte();\n";
+ result += indent + "delete result;\n";
+ result += indent + "return returnCode;\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<Arts::mcopbyte> *_returnCode ="
+ " new std::vector<Arts::mcopbyte>;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "result->readByteSeq(*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_REQ_READ)
+ result = indent + "Arts::mcopbyte "+name+" = request->readByte();\n";
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<Arts::mcopbyte> "+name+";\n"
+ + indent + "request->readByteSeq("+name+");\n";
+ if(model==MODEL_WRITE)
+ result = "stream.writeByte("+name+")";
+ if(model==MODEL_WRITE_SEQ)
+ result = "stream.writeByteSeq("+name+")";
+ if(model==MODEL_REQ_WRITE)
+ result = "request->writeByte("+name+")";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "request->writeByteSeq("+name+")";
+ if(model==MODEL_INVOKE)
+ result = indent + "result->writeByte("+name+");\n";
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<Arts::mcopbyte> *_returnCode = "+name+";\n"
+ + indent + "result->writeByteSeq(*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ if(model==MODEL_ASTREAM)
+ result = "Arts::ByteAsyncStream "+name;
+ if(model==MODEL_ASTREAM_PACKETPTR) result = "Arts::DataPacket<Arts::mcopbyte> *";
+ }
+ else if(type == "long")
+ {
+ if(model==MODEL_MEMBER) result = "long";
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<long>";
+ if(model==MODEL_ARG) result = "long";
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<long>&";
+ if(model==MODEL_RESULT) result = "long";
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<long> *";
+ if(model==MODEL_READ)
+ result = name+" = stream.readLong()";
+ if(model==MODEL_READ_SEQ)
+ result = "stream.readLongSeq("+name+")";
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if(!result) return 0; // error occurred\n";
+ result += indent + "long returnCode = result->readLong();\n";
+ result += indent + "delete result;\n";
+ result += indent + "return returnCode;\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<long> *_returnCode ="
+ " new std::vector<long>;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "result->readLongSeq(*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_REQ_READ)
+ result = indent + "long "+name+" = request->readLong();\n";
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<long> "+name+";\n"
+ + indent + "request->readLongSeq("+name+");\n";
+ if(model==MODEL_WRITE)
+ result = "stream.writeLong("+name+")";
+ if(model==MODEL_WRITE_SEQ)
+ result = "stream.writeLongSeq("+name+")";
+ if(model==MODEL_REQ_WRITE)
+ result = "request->writeLong("+name+")";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "request->writeLongSeq("+name+")";
+ if(model==MODEL_INVOKE)
+ result = indent + "result->writeLong("+name+");\n";
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<long> *_returnCode = "+name+";\n"
+ + indent + "result->writeLongSeq(*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ } else if(type == "string") {
+ if(model==MODEL_MEMBER) result = "std::string";
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<std::string>";
+ if(model==MODEL_ARG) result = "const std::string&";
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<std::string>&";
+ if(model==MODEL_RESULT) result = "std::string";
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<std::string> *";
+ if(model==MODEL_READ)
+ result = "stream.readString("+name+")";
+ if(model==MODEL_READ_SEQ)
+ result = "stream.readStringSeq("+name+")";
+ if(model==MODEL_REQ_READ)
+ {
+ result = indent + "std::string "+name+";\n"
+ + indent + "request->readString("+name+");\n";
+ }
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<std::string> "+name+";\n"
+ + indent + "request->readStringSeq("+name+");\n";
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if(!result) return\"\"; // error occurred\n";
+ result += indent + "std::string returnCode;\n";
+ result += indent + "result->readString(returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return returnCode;\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<std::string> *_returnCode ="
+ " new std::vector<std::string>;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "result->readStringSeq(*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_WRITE)
+ result = "stream.writeString("+name+")";
+ if(model==MODEL_WRITE_SEQ)
+ result = "stream.writeStringSeq("+name+")";
+ if(model==MODEL_REQ_WRITE)
+ result = "request->writeString("+name+")";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "request->writeStringSeq("+name+")";
+ if(model==MODEL_INVOKE)
+ result = indent + "result->writeString("+name+");\n";
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<std::string> *_returnCode = "+name+";\n"
+ + indent + "result->writeStringSeq(*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ } else if(isPacketType(type)) {
+ if(model==MODEL_ASTREAM)
+ result = type+"AsyncStream "+name;
+ if(model==MODEL_ASTREAM_PACKETPTR) result = "Arts::DataPacket<"+type+"> *";
+ } else if(isStruct(type)) {
+ if(model==MODEL_MEMBER)
+ result = type;
+ if(model==MODEL_MEMBER_SEQ)
+ result = "std::vector<"+type+">";
+
+ if(model==MODEL_ARG)
+ result = "const "+type+"&";
+ if(model==MODEL_ARG_SEQ)
+ result = "const std::vector<"+type+">&";
+
+ if(model==MODEL_READ)
+ result = name+".readType(stream)";
+ if(model==MODEL_READ_SEQ)
+ result = "Arts::readTypeSeq(stream,"+name+")";
+ if(model==MODEL_REQ_READ)
+ result = indent + type+" "+name+"(*request);\n";
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<"+type+"> "+name+";\n"
+ + indent + "Arts::readTypeSeq(*request,"+name+");\n";
+
+ if(model==MODEL_WRITE)
+ result = name+".writeType(stream)";
+ if(model==MODEL_REQ_WRITE)
+ result = name+".writeType(*request)";
+ if(model==MODEL_WRITE_SEQ)
+ result = "Arts::writeTypeSeq(stream,"+name+")";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "Arts::writeTypeSeq(*request,"+name+")";
+
+ if(model==MODEL_INVOKE)
+ result = indent + type + " _returnCode = "+name+";\n"
+ + indent + "_returnCode.writeType(*result);\n";
+
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<"+type+"> *_returnCode = "+name+";\n"
+ + indent + "Arts::writeTypeSeq(*result,*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ if(model==MODEL_RES_READ)
+ {
+ result = indent +
+ "if(!result) return "+type+"(); // error occurred\n";
+ result += indent+ type + " _returnCode(*result);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<"+type+"> *_returnCode ="
+ " new std::vector<"+type+">;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "Arts::readTypeSeq(*result,*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+
+ if(model==MODEL_RESULT) result = type;
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<"+type+"> *";
+ } else if(isEnum(type)) {
+ if(model==MODEL_MEMBER) result = type;
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<"+type+">";
+ if(model==MODEL_ARG) result = type;
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<"+type+">&";
+ if(model==MODEL_RESULT) result = type;
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<"+type+"> *";
+ if(model==MODEL_READ)
+ result = name+" = ("+type+")stream.readLong()";
+ if(model==MODEL_READ_SEQ)
+ result = "stream.readLongSeq("+name+")"; // TODO
+ if(model==MODEL_RES_READ)
+ {
+ result = indent +
+ "if(!result) return ("+type+")0; // error occurred\n";
+ result += indent + type+" returnCode = ("+
+ type+")result->readLong();\n";
+ result += indent + "delete result;\n";
+ result += indent + "return returnCode;\n";
+ }
+ if(model==MODEL_REQ_READ)
+ result = indent +
+ type+" "+name+" = ("+type+")request->readLong();\n";
+ if(model==MODEL_WRITE)
+ result = "stream.writeLong("+name+")";
+ if(model==MODEL_WRITE_SEQ)
+ result = "stream.writeLongSeq("+name+")"; // TODO
+ if(model==MODEL_REQ_WRITE)
+ result = "request->writeLong("+name+")";
+ if(model==MODEL_INVOKE)
+ result = indent + "result->writeLong("+name+");\n";
+ } else if(isInterface(type)) {
+ // the "object class" is called Object
+ if(type == "object") type = "Arts::Object";
+
+ if(model==MODEL_MEMBER) result = type+"_var";
+ if(model==MODEL_MEMBER_SEQ) result = "std::vector<"+type+">";
+ if(model==MODEL_ARG) result = type;
+ if(model==MODEL_ARG_SEQ) result = "const std::vector<"+type+">&";
+ if(model==MODEL_RESULT) result = type;
+ if(model==MODEL_RESULT_SEQ) result = "std::vector<"+type+"> *";
+ if(model==MODEL_READ)
+ result = "Arts::readObject(stream,"+name+")";
+ if(model==MODEL_READ_SEQ)
+ result = "Arts::readObjectSeq(stream,"+name+")";
+ if(model==MODEL_RES_READ)
+ {
+ result = indent + "if (!result) return "+type+"::null();\n"; // error occurred\n";
+ result += indent + type+"_base* returnCode;\n";
+ result += indent + "Arts::readObject(*result,returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return "+type+"::_from_base(returnCode);\n";
+ }
+ if(model==MODEL_RES_READ_SEQ)
+ {
+ result = indent + "std::vector<"+type+"> *_returnCode ="
+ " new std::vector<"+type+">;\n";
+ result += indent + "if(!result) return _returnCode; // error occurred\n";
+ result += indent + "Arts::readObjectSeq(*result,*_returnCode);\n";
+ result += indent + "delete result;\n";
+ result += indent + "return _returnCode;\n";
+ }
+ if(model==MODEL_REQ_READ)
+ {
+ result = indent + type +"_base* _temp_"+name+";\n";
+ result += indent + "Arts::readObject(*request,_temp_"+name+");\n";
+ result += indent + type+" "+name+" = "+type+"::_from_base(_temp_"+name+");\n";
+ }
+ if(model==MODEL_REQ_READ_SEQ)
+ result = indent + "std::vector<"+type+"> "+name+";\n"
+ + indent + "Arts::readObjectSeq(*request,"+name+");\n";
+ if(model==MODEL_WRITE)
+ result = "Arts::writeObject(stream,"+name+"._base())";
+ if(model==MODEL_WRITE_SEQ)
+ result = "Arts::writeObjectSeq(stream,"+name+")";
+ if(model==MODEL_REQ_WRITE)
+ result = "Arts::writeObject(*request,"+name+"._base())";
+ if(model==MODEL_REQ_WRITE_SEQ)
+ result = "Arts::writeObjectSeq(*request,"+name+")";
+ if(model==MODEL_INVOKE)
+ {
+ result = indent + type+" returnCode = "+name+";\n"
+ + indent + "Arts::writeObject(*result,returnCode._base());\n";
+ }
+ if(model==MODEL_INVOKE_SEQ)
+ {
+ result = indent + "std::vector<"+type+"> *_returnCode = "+name+";\n"
+ + indent + "Arts::writeObjectSeq(*result,*_returnCode);\n"
+ + indent + "delete _returnCode;\n";
+ }
+ }
+ else
+ {
+ fprintf(stderr,"error: undefined type %s occurred\n",type.c_str());
+ exit(1);
+ }
+
+ if((model & ~MODEL_SEQ) == MODEL_MEMBER
+ || (model & ~MODEL_SEQ) == MODEL_ARG)
+ {
+ result += " ";
+ result += name;
+ }
+ return result;
+}
+
+string buildInheritanceList(const InterfaceDef& interface, const string& append)
+{
+ vector<string>::const_iterator ii;
+ string result = "";
+ bool first = true;
+
+ for(ii=interface.inheritedInterfaces.begin();
+ ii != interface.inheritedInterfaces.end();ii++)
+ {
+ if(!first) result += ",\n\t"; else first = false;
+ result += "virtual public "+*ii+append;
+ }
+
+ return result;
+}
+
+string mkdef(string prefix)
+{
+ string result;
+
+ for(unsigned int i=0;i<prefix.length();i++)
+ result += toupper(prefix[i]);
+ result += "_H";
+
+ return result;
+}
+
+const char *generated_disclaimer =
+ "/* this file was generated by the MCOP idl compiler - DO NOT EDIT */\n\n";
+
+FILE *startHeader(string prefix)
+{
+ string header_name = prefix+".h.new";
+ FILE *header = fopen(header_name.c_str(),"w");
+
+ fprintf(header,"%s", generated_disclaimer);
+ fprintf(header,"#ifndef %s\n",mkdef(prefix).c_str());
+ fprintf(header,"#define %s\n\n",mkdef(prefix).c_str());
+ fprintf(header,"#include \"common.h\"\n\n");
+ fprintf(header,"#include \"arts_export.h\"\n\n");
+
+ list<string>::iterator cii;
+ for(cii=customIncludes.begin(); cii != customIncludes.end(); cii++)
+ fprintf(header,"#include \"%s\"\n",(*cii).c_str());
+ if(!customIncludes.empty()) fprintf(header,"\n");
+
+ return (header);
+}
+
+void endHeader(FILE *header, string prefix)
+{
+ fprintf(header,"#endif /* %s */\n",mkdef(prefix).c_str());
+ fclose(header);
+}
+
+FILE *startSource(string prefix)
+{
+ string header_name = prefix+".h";
+ string source_name = prefix+".cc.new";
+
+ FILE *source = fopen(source_name.c_str(),"w");
+ fprintf(source,"%s", generated_disclaimer);
+ fprintf(source,"#include \"%s\"\n\n",header_name.c_str());
+
+ return source;
+}
+
+void endSource(FILE *source)
+{
+ fclose(source);
+}
+
+/* moves file BASE.new to BASE, but only if there are any changes. Otherwise
+ BASE.new is simply removed */
+void moveIfChanged(string base)
+{
+ string newn = base+".new";
+ FILE *oldf = fopen(base.c_str(), "r");
+ if (!oldf) {
+ rename(newn.c_str(), base.c_str());
+ return;
+ }
+ FILE *newf = fopen(newn.c_str(), "r");
+ if (!newf) {
+ fclose(oldf);
+ return;
+ }
+ bool different = false;
+ unsigned char *oldb, *newb;
+ size_t blen = 65536;
+ oldb = new unsigned char[blen];
+ newb = new unsigned char[blen];
+ while (1) {
+ size_t olen = fread(oldb, 1, blen, oldf);
+ size_t nlen = fread(newb, 1, blen, newf);
+ if (olen != nlen) {
+ different = true;
+ break;
+ }
+ if (!olen) break;
+ if (memcmp(oldb, newb, olen)) {
+ different = true;
+ break;
+ }
+ if (olen < blen) break;
+ }
+ delete [] newb;
+ delete [] oldb;
+ fclose(newf);
+ fclose(oldf);
+ if (different) {
+ rename(newn.c_str(), base.c_str());
+ } else {
+ unlink(newn.c_str());
+ }
+}
+
+bool haveIncluded(string filename)
+{
+ list<string>::iterator i;
+
+ for(i = ::includes.begin();i != ::includes.end();i++)
+ if(*i == filename) return true;
+
+ return false;
+}
+
+void doIncludeHeader(FILE *header)
+{
+ list<string>::iterator i;
+ bool done_something = false;
+
+ for(i = ::includes.begin();i != ::includes.end();i++)
+ {
+ char *include = strdup((*i).c_str());
+ if(strlen(include) >= 4)
+ {
+ if(strcmp(&include[strlen(include)-4],".idl") == 0)
+ {
+ include[strlen(include)-4] = 0;
+ if(!done_something)
+ {
+ fprintf(header,"// includes of other idl definitions\n");
+ done_something = true;
+ }
+ fprintf(header,"#include \"%s.h\"\n",include);
+ }
+ }
+ free(include);
+ }
+ if(done_something) fprintf(header,"\n");
+}
+
+void doEnumHeader(FILE *header)
+{
+ list<EnumDef>::iterator edi;
+ vector<EnumComponent>::iterator i;
+ NamespaceHelper nspace(header);
+
+ for(edi = enums.begin();edi != enums.end(); edi++)
+ {
+ EnumDef& ed = *edi;
+
+ if(fromInclude(ed.name)) continue; // should come from the include
+
+ nspace.setFromSymbol(ed.name);
+ string ename = nspace.printableForm(ed.name);
+ if(ename == "_anonymous_") ename = "";
+
+ fprintf(header,"enum %s {",ename.c_str());
+ int first = 0;
+ for(i=ed.contents.begin();i != ed.contents.end();i++)
+ {
+ if(first != 0) fprintf(header,", ");
+ first++;
+ fprintf(header,"%s = %ld",i->name.c_str(),i->value);
+ }
+ fprintf(header,"};\n");
+ }
+}
+
+void doStructHeader(FILE *header)
+{
+ list<TypeDef>::iterator csi;
+ vector<TypeComponent>::iterator i;
+ NamespaceHelper nspace(header);
+
+ for(csi = structs.begin();csi != structs.end(); csi++)
+ {
+ TypeDef& d = *csi;
+
+ if(fromInclude(d.name)) continue; // should come from the include
+
+ nspace.setFromSymbol(d.name.c_str());
+ string tname = nspace.printableForm(d.name);
+
+ fprintf(header,"class ARTS_EXPORT %s : public Arts::Type {\n",tname.c_str());
+ fprintf(header,"public:\n");
+
+ /** constructor without arguments **/
+ fprintf(header,"\t%s();\n",tname.c_str());
+
+ /** constructor with arguments **/
+ fprintf(header,"\t%s(",tname.c_str());
+ int first = 0;
+ for(i=d.contents.begin();i != d.contents.end();i++)
+ {
+ string name = createTypeCode(i->type,"_a_" + i->name,MODEL_ARG);
+ if(first != 0) fprintf(header,", ");
+ first++;
+ fprintf(header,"%s",name.c_str());
+ }
+ fprintf(header,");\n");
+
+ /** constructor from stream **/
+ fprintf(header,"\t%s(Arts::Buffer& stream);\n",tname.c_str());
+
+ /** copy constructor (from same type) **/
+ fprintf(header,"\t%s(const %s& copyType);\n",
+ tname.c_str(),tname.c_str());
+
+ /** assignment operator **/
+ fprintf(header,"\t%s& operator=(const %s& assignType);\n",
+ tname.c_str(),tname.c_str());
+
+ /** data members **/
+ for(i=d.contents.begin();i != d.contents.end();i++)
+ {
+ string name = createTypeCode(i->type,i->name,MODEL_MEMBER);
+ fprintf(header,"\t%s;\n",name.c_str());
+ }
+
+ fprintf(header,"\n// marshalling functions\n");
+
+ /** marshalling function for reading from stream **/
+ fprintf(header,"\tvoid readType(Arts::Buffer& stream);\n");
+
+ /** marshalling function for writing to stream **/
+ fprintf(header,"\tvoid writeType(Arts::Buffer& stream) const;\n");
+
+ /** returns the name of the type **/
+ fprintf(header, "\tstd::string _typeName() const;\n");
+ fprintf(header,"};\n\n");
+ }
+}
+
+void doStructSource(FILE *source)
+{
+ list<TypeDef>::iterator csi;
+ vector<TypeComponent>::iterator i;
+
+ fprintf(source,"// Implementation\n");
+ for(csi = structs.begin();csi != structs.end(); csi++)
+ {
+ TypeDef& d = *csi;
+
+ if(fromInclude(d.name)) continue; // should come from the include
+
+ string tname = NamespaceHelper::nameOf(d.name);
+
+ fprintf(source,"%s::%s()\n{\n}\n\n",d.name.c_str(),tname.c_str());
+
+ fprintf(source,"%s::%s(",d.name.c_str(),tname.c_str());
+ int first = 0;
+ for(i=d.contents.begin();i != d.contents.end();i++)
+ {
+ string name = createTypeCode(i->type,"_a_" + i->name,MODEL_ARG);
+ if(first != 0) fprintf(source,", ");
+ first++;
+ fprintf(source,"%s",name.c_str());
+ }
+ fprintf(source,")\n{\n");
+ for(i=d.contents.begin();i != d.contents.end();i++)
+ {
+ string n = "_a_" + i->name;
+ fprintf(source,"\tthis->%s = %s;\n",i->name.c_str(),n.c_str());
+ }
+ fprintf(source,"}\n\n");
+
+ /** constructor from stream **/
+ fprintf(source,"%s::%s(Arts::Buffer& stream)\n{\n",d.name.c_str(),tname.c_str());
+ fprintf(source,"\treadType(stream);\n");
+ fprintf(source,"}\n\n");
+
+ /** copy constructor **/
+
+ fprintf(source,"%s::%s(const %s& copyType) : Arts::Type(copyType)\n{\n",
+ d.name.c_str(),tname.c_str(),d.name.c_str());
+ fprintf(source,"\tArts::Buffer buffer;\n");
+ fprintf(source,"\tcopyType.writeType(buffer);\n");
+ fprintf(source,"\treadType(buffer);\n");
+ fprintf(source,"}\n\n");
+
+ /** assignment operator **/
+ fprintf(source,"%s& %s::operator=(const %s& assignType)\n{\n",
+ d.name.c_str(),d.name.c_str(),d.name.c_str());
+ fprintf(source,"\tArts::Buffer buffer;\n");
+ fprintf(source,"\tassignType.writeType(buffer);\n");
+ fprintf(source,"\treadType(buffer);\n");
+ fprintf(source,"\treturn *this;\n");
+ fprintf(source,"}\n\n");
+
+#if 0 /* not needed if types use vector<Type> instead of vector<Type *> */
+ /** virtual destuctor: free type contents **/
+ fprintf(source,"%s::~%s()\n{\n",d.name.c_str(),tname.c_str());
+ for(i=d->contents.begin();i != d->contents.end();i++)
+ {
+ string stype = (*i)->type;
+ string type = stype.substr(1,stype.length()-1);
+ if(stype[0] == '*' && isStruct(type))
+ {
+ fprintf(source,"\tfreeTypeSeq(%s);\n",(*i)->name.c_str());
+ }
+ }
+ fprintf(source,"}\n\n");
+#endif
+ /** marshalling function for reading from stream **/
+ fprintf(source,"void %s::readType(Arts::Buffer& stream)\n{\n",d.name.c_str());
+ for(i=d.contents.begin();i != d.contents.end();i++)
+ {
+ string code = createTypeCode(i->type,i->name,MODEL_READ);
+ fprintf(source,"\t%s;\n",code.c_str());
+ }
+ fprintf(source,"}\n\n");
+
+ /** marshalling function for writing to stream **/
+ fprintf(source,"void %s::writeType(Arts::Buffer& stream) const\n{\n",d.name.c_str());
+ for(i=d.contents.begin();i != d.contents.end();i++)
+ {
+ string code = createTypeCode(i->type,i->name,MODEL_WRITE);
+ fprintf(source,"\t%s;\n",code.c_str());
+ }
+ fprintf(source,"}\n\n");
+
+ /** returns the name of the type **/
+ fprintf(source,"std::string %s::_typeName() const\n{\n",d.name.c_str());
+ fprintf(source,"\treturn \"%s\";\n",d.name.c_str());
+ fprintf(source,"}\n\n");
+ }
+}
+
+string createReturnCode(const MethodDef& md)
+{
+ return createTypeCode(md.type,"",MODEL_RESULT,"");
+}
+
+string createParamList(const MethodDef& md)
+{
+ string result;
+ int first = 0;
+ vector<ParamDef>::const_iterator pi;
+
+ for(pi = md.signature.begin(); pi != md.signature.end(); pi++)
+ {
+ const ParamDef& pd = *pi;
+ string p = createTypeCode(pd.type,pd.name,MODEL_ARG,"");
+
+ if(first != 0) result += ", ";
+ first++;
+ result += p;
+ }
+ return result;
+}
+
+string createCallParamList(const MethodDef& md)
+{
+ string result;
+ bool first = true;
+ vector<ParamDef>::const_iterator pi;
+
+ for(pi = md.signature.begin(); pi != md.signature.end(); pi++)
+ {
+ if (!first) result += ", ";
+ first = false;
+ result += pi->name;
+ }
+ return result;
+}
+
+void createStubCode(FILE *source, string iface, string method,
+ const MethodDef& md)
+{
+ string rc = createReturnCode(md);
+ string params = createParamList(md);
+ vector<ParamDef>::const_iterator pi;
+
+ Buffer b;
+ md.writeType(b);
+
+ fprintf(source,"%s %s_stub::%s(%s)\n",rc.c_str(),iface.c_str(),
+ method.c_str(), params.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\tlong methodID = _lookupMethodFast(\"%s\");\n",
+ b.toString("method").c_str());
+ if(md.flags & methodTwoway)
+ {
+ fprintf(source,"\tlong requestID;\n");
+ fprintf(source,"\tArts::Buffer *request, *result;\n");
+ fprintf(source,"\trequest = Arts::Dispatcher::the()->"
+ "createRequest(requestID,_objectID,methodID);\n");
+ }
+ else
+ {
+ fprintf(source,"\tArts::Buffer *request = Arts::Dispatcher::the()->"
+ "createOnewayRequest(_objectID,methodID);\n");
+ }
+
+ for(pi = md.signature.begin(); pi != md.signature.end(); pi++)
+ {
+ const ParamDef& pd = *pi;
+ string p;
+ p = createTypeCode(pd.type,pd.name,MODEL_REQ_WRITE);
+ fprintf(source,"\t%s;\n",p.c_str());
+ }
+ fprintf(source,"\trequest->patchLength();\n");
+ fprintf(source,"\t_connection->qSendBuffer(request);\n\n");
+
+ if(md.flags & methodTwoway)
+ {
+ fprintf(source,"\tresult = "
+ "Arts::Dispatcher::the()->waitForResult(requestID,_connection);\n");
+
+ fprintf(source,"%s",
+ createTypeCode(md.type,"",MODEL_RES_READ,"\t").c_str());
+ }
+ fprintf(source,"}\n\n");
+}
+
+bool haveStreams(const InterfaceDef& d)
+{
+ vector<AttributeDef>::const_iterator ai;
+
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ if(ai->flags & attributeStream) return true;
+
+ return false;
+}
+
+bool haveAsyncStreams(const InterfaceDef& d)
+{
+ vector<AttributeDef>::const_iterator ai;
+
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ if((ai->flags & attributeStream) && (ai->flags & streamAsync))
+ return true;
+
+ return false;
+}
+
+string dispatchFunctionName(string interface, long mcount)
+{
+ char number[20];
+ sprintf(number,"%02ld",mcount);
+
+ string nspace = NamespaceHelper::namespaceOf(interface);
+ for (string::iterator i = nspace.begin(); i != nspace.end(); i++)
+ if(*i == ':') *i = '_';
+
+ string iname = NamespaceHelper::nameOf(interface);
+
+ return "_dispatch_" + nspace + "_" + iname + "_" + number;
+}
+
+void createDispatchFunction(FILE *source, long mcount,
+ const InterfaceDef& d, const MethodDef& md,string name)
+{
+ /** calculate signature (prevents unused argument warnings) **/
+ string signature = "void *object, ";
+
+ if(md.signature.size() == 0)
+ signature += "Arts::Buffer *";
+ else
+ signature += "Arts::Buffer *request";
+
+ if(md.flags & methodTwoway)
+ {
+ if(md.type == "void")
+ signature += ", Arts::Buffer *";
+ else
+ signature += ", Arts::Buffer *result";
+ }
+ else
+ {
+ if(md.type != "void")
+ {
+ cerr << "method " << md.name << " in interface " << d.name <<
+ " is declared oneway, but not void" << endl;
+ exit(1);
+ }
+ }
+
+ fprintf(source,"// %s\n",md.name.c_str());
+ fprintf(source,"static void %s(%s)\n",
+ dispatchFunctionName(d.name,mcount).c_str(), signature.c_str());
+ fprintf(source,"{\n");
+
+ string call = "(("+d.name+"_skel *)object)->"+name + "(";
+ int first = 1;
+ vector<ParamDef>::const_iterator pi;
+ for(pi = md.signature.begin(); pi != md.signature.end(); pi++)
+ {
+ const ParamDef& pd = *pi;
+ string p;
+
+ if(!first) call += ",";
+ first = 0;
+ call += pd.name;
+ p = createTypeCode(pd.type,pd.name,MODEL_REQ_READ, "\t");
+ fprintf(source,"%s",p.c_str());
+ }
+ call += ")";
+ string invoke = createTypeCode(md.type,call,MODEL_INVOKE,"\t");
+ fprintf(source,"%s",invoke.c_str());
+ fprintf(source,"}\n\n");
+}
+
+// generate a list of all parents. There can be repetitions
+vector<std::string> allParents(const InterfaceDef& iface)
+{
+ vector<std::string> ret;
+ list<InterfaceDef>::iterator interIt;
+ vector<std::string>::const_iterator si;
+ // For all inherited interfaces
+ for (si = iface.inheritedInterfaces.begin(); si != iface.inheritedInterfaces.end(); si++)
+ {
+ ret.push_back(*si);
+ // Find the corresponding interface definition
+ for (interIt=interfaces.begin(); interIt!=interfaces.end(); interIt++) {
+ InterfaceDef& parent = *interIt;
+ if (parent.name == (*si)) {
+ // Now add this parent's parents
+ vector<std::string> ppar = allParents(parent);
+ ret.insert(ret.end(), ppar.begin(), ppar.end());
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+// generate a list of all parents - without repetitions
+vector<string> allParentsUnique(const InterfaceDef& iface)
+{
+ map<string,bool> done;
+ vector<string> parents = allParents(iface),result;
+ vector<string>::iterator i;
+
+ for(i=parents.begin();i!=parents.end();i++)
+ {
+ string& name = *i;
+ if(!done[name])
+ {
+ result.push_back(name);
+ done[name] = true;
+ }
+ }
+
+ return result;
+}
+
+InterfaceDef findInterface(const string& iface)
+{
+ list<InterfaceDef>::iterator i;
+ for(i=interfaces.begin();i != interfaces.end(); i++)
+ {
+ const InterfaceDef& d = *i;
+ if(d.name == iface) return d;
+ }
+ return InterfaceDef();
+}
+
+InterfaceDef mergeAllParents(const InterfaceDef& iface)
+{
+ InterfaceDef result = iface;
+
+ vector<string> parents = allParentsUnique(iface);
+ vector<string>::iterator pi;
+
+ for(pi = parents.begin(); pi != parents.end(); pi++)
+ {
+ string parent = *pi;
+
+ list<InterfaceDef>::iterator i;
+ for(i=interfaces.begin();i != interfaces.end(); i++)
+ {
+ const InterfaceDef& d = *i;
+ if(d.name == parent)
+ {
+ /* merge attributes */
+ vector<AttributeDef>::const_iterator ai;
+
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ result.attributes.push_back(*ai);
+
+ /* merge methods */
+ vector<MethodDef>::const_iterator mi;
+
+ for(mi = d.methods.begin(); mi != d.methods.end(); mi++)
+ {
+ result.methods.push_back(*mi);
+ }
+ }
+ }
+ }
+ return result;
+}
+
+struct ForwardCode {
+ bool constructor;
+ string fullifacename, result, mname, params, callparams;
+ string baseclass;
+};
+
+void checkSymbolDefinition(const string& name, const string& type,
+ const InterfaceDef& where, map<string,string>& defs)
+{
+ string xwhere = where.name + "::" + name + " ("+type+")";
+ string& mapentry = defs[name];
+
+ if(mapentry.empty())
+ {
+ mapentry = xwhere;
+ }
+ else
+ {
+ cerr << idl_filename << ": warning: " << xwhere
+ << " collides with " << mapentry << endl;
+ }
+}
+
+void doInterfacesHeader(FILE *header)
+{
+ list<InterfaceDef>::iterator ii;
+ vector<MethodDef>::iterator mi;
+ vector<AttributeDef>::iterator ai;
+ string inherits;
+ NamespaceHelper nspace(header);
+ list<ForwardCode> forwardCode;
+
+ /*
+ * this allows it to the various interfaces as parameters, returncodes
+ * and attributes even before their declaration
+ */
+ for(ii = interfaces.begin();ii != interfaces.end(); ii++)
+ {
+ InterfaceDef& d = *ii;
+ if(!fromInclude(d.name))
+ {
+ nspace.setFromSymbol(d.name);
+ fprintf(header,"class %s;\n",nspace.printableForm(d.name).c_str());
+ }
+ }
+ fprintf(header,"\n");
+
+ for(ii = interfaces.begin();ii != interfaces.end(); ii++)
+ {
+ InterfaceDef& d = *ii;
+ string iname;
+ string fullifacename = d.name;
+
+ if(fromInclude(d.name)) continue; // should come from the include
+
+ // create abstract interface
+ inherits = buildInheritanceList(d,"_base");
+ if(inherits.empty()) inherits = "virtual public Arts::Object_base";
+
+ nspace.setFromSymbol(d.name);
+ iname = nspace.printableForm(d.name);
+
+ fprintf(header,"class ARTS_EXPORT %s_base : %s {\n",iname.c_str(),inherits.c_str());
+ fprintf(header,"public:\n");
+ fprintf(header,"\tstatic unsigned long _IID; // interface ID\n\n");
+ fprintf(header,"\tstatic %s_base *_create(const std::string& subClass"
+ " = \"%s\");\n", iname.c_str(),d.name.c_str());
+ fprintf(header,"\tstatic %s_base *_fromString(const std::string& objectref);\n",
+ iname.c_str());
+ fprintf(header,"\tstatic %s_base *_fromReference(Arts::ObjectReference ref,"
+ " bool needcopy);\n\n",iname.c_str());
+
+ fprintf(header,"\tstatic %s_base *_fromDynamicCast(const Arts::Object&"
+ " object);\n", iname.c_str());
+
+ /* reference counting: _copy */
+ fprintf(header,"\tinline %s_base *_copy() {\n"
+ "\t\tassert(_refCnt > 0);\n"
+ "\t\t_refCnt++;\n"
+ "\t\treturn this;\n"
+ "\t}\n\n",iname.c_str());
+
+ // Default I/O info
+ fprintf(header,"\tvirtual std::vector<std::string> _defaultPortsIn() const;\n");
+ fprintf(header,"\tvirtual std::vector<std::string> _defaultPortsOut() const;\n");
+ fprintf(header,"\n");
+
+ // Casting
+ fprintf(header,"\tvoid *_cast(unsigned long iid);\n\n");
+
+ /* attributes (not for streams) */
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+ string rc = createTypeCode(ad.type,"",MODEL_RESULT);
+ string pc = createTypeCode(ad.type,"newValue",MODEL_ARG);
+
+ if(ad.flags & attributeAttribute)
+ {
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ fprintf(header,"\tvirtual %s %s() = 0;\n",rc.c_str(),
+ ad.name.c_str());
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ fprintf(header,"\tvirtual void %s(%s) = 0;\n",
+ ad.name.c_str(), pc.c_str());
+ }
+ }
+ }
+
+ /* methods */
+ for(mi = d.methods.begin(); mi != d.methods.end(); mi++)
+ {
+ MethodDef& md = *mi;
+ string rc = createReturnCode(md);
+ string params = createParamList(md);
+
+ fprintf(header,"\tvirtual %s %s(%s) = 0;\n",rc.c_str(),
+ md.name.c_str(), params.c_str());
+ }
+ fprintf(header,"};\n\n");
+
+ // create stub
+
+ inherits = buildInheritanceList(d,"_stub");
+ if(inherits.empty()) inherits = "virtual public Arts::Object_stub";
+
+ fprintf(header,"class ARTS_EXPORT %s_stub : virtual public %s_base, %s {\n",
+ iname.c_str(), iname.c_str(),inherits.c_str());
+ fprintf(header,"protected:\n");
+ fprintf(header,"\t%s_stub();\n\n",iname.c_str());
+
+ fprintf(header,"public:\n");
+ fprintf(header,"\t%s_stub(Arts::Connection *connection, long objectID);\n\n",
+ iname.c_str());
+ /* attributes (not for streams) */
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+ string rc = createTypeCode(ad.type,"",MODEL_RESULT);
+ string pc = createTypeCode(ad.type,"newValue",MODEL_ARG);
+
+ if(ad.flags & attributeAttribute)
+ {
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ fprintf(header,"\t%s %s();\n",rc.c_str(),
+ ad.name.c_str());
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ fprintf(header,"\tvoid %s(%s);\n",
+ ad.name.c_str(), pc.c_str());
+ }
+ }
+ }
+ /* methods */
+ for(mi = d.methods.begin(); mi != d.methods.end(); mi++)
+ {
+ MethodDef& md = *mi;
+ string rc = createReturnCode(md);
+ string params = createParamList(md);
+
+ fprintf(header,"\t%s %s(%s);\n",rc.c_str(),
+ md.name.c_str(), params.c_str());
+ }
+ fprintf(header,"};\n\n");
+
+ // create skeleton
+
+ inherits = buildInheritanceList(d,"_skel");
+ if(inherits.empty()) inherits = "virtual public Arts::Object_skel";
+
+ fprintf(header,"class ARTS_EXPORT %s_skel : virtual public %s_base,"
+ " %s {\n",iname.c_str(),iname.c_str(),inherits.c_str());
+
+ bool firstStream = true;
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if(ad.flags & attributeStream)
+ {
+ if(firstStream)
+ {
+ fprintf(header,"protected:\n");
+ fprintf(header,"\t// variables for streams\n");
+ firstStream = false;
+ }
+
+ /** generate declaration of the variable: multi stream? **/
+ string decl;
+
+ if(ad.flags & streamMulti)
+ {
+ if(ad.flags & streamAsync)
+ decl = createTypeCode(ad.type,ad.name,MODEL_AMSTREAM);
+ else
+ decl = createTypeCode(ad.type,ad.name,MODEL_MSTREAM);
+ }
+ else
+ {
+ if(ad.flags & streamAsync)
+ decl = createTypeCode(ad.type,ad.name,MODEL_ASTREAM);
+ else
+ decl = createTypeCode(ad.type,ad.name,MODEL_STREAM);
+ }
+
+ decl += ";";
+
+ /** write to source **/
+ string comment;
+
+ if(ad.flags & streamIn) comment = "incoming stream";
+ if(ad.flags & streamOut) comment = "outgoing stream";
+
+ fprintf(header,"\t%-40s // %s\n",decl.c_str(),comment.c_str());
+ }
+ }
+ if(!firstStream) fprintf(header,"\n");
+
+ bool haveAsyncStreams = false;
+
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if((ad.flags & attributeStream) && (ad.flags & streamAsync))
+ {
+ if(!haveAsyncStreams)
+ {
+ fprintf(header,"\t// handler for asynchronous streams\n");
+ haveAsyncStreams = true;
+ }
+
+ string ptype =
+ createTypeCode(ad.type,"",MODEL_ASTREAM_PACKETPTR);
+
+ if(ad.flags & streamIn)
+ {
+ fprintf(header,"\tvirtual void process_%s(%s) = 0;\n",
+ ad.name.c_str(),ptype.c_str());
+ }
+ else
+ {
+ fprintf(header,"\tvirtual void request_%s(%s);\n",
+ ad.name.c_str(),ptype.c_str());
+ }
+ }
+ }
+ if(haveAsyncStreams) fprintf(header,"\n");
+
+ bool haveChangeNotifications = false;
+
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if((ad.flags & attributeAttribute) && (ad.flags & streamOut)
+ && (ad.type == "byte" || ad.type == "float" || ad.type == "long"
+ || ad.type == "string" || ad.type == "boolean"
+ || ad.type == "*byte" || ad.type == "*float" || ad.type == "*long"
+ || ad.type == "*string" || isEnum(ad.type)))
+ {
+ if(!haveChangeNotifications)
+ {
+ fprintf(header,"protected:\n");
+ fprintf(header,"\t// emitters for change notifications\n");
+ haveChangeNotifications = true;
+ }
+
+ string pc = createTypeCode(ad.type,"newValue",MODEL_ARG);
+
+ fprintf(header,"\tinline void %s_changed(%s) {\n",
+ ad.name.c_str(),pc.c_str());
+ fprintf(header,"\t\t_emit_changed(\"%s_changed\",newValue);\n",
+ ad.name.c_str());
+ fprintf(header,"\t}\n");
+ }
+ }
+ if(haveChangeNotifications) fprintf(header,"\n");
+
+ fprintf(header,"public:\n");
+ fprintf(header,"\t%s_skel();\n\n",iname.c_str());
+
+ fprintf(header,"\tstatic std::string _interfaceNameSkel();\n");
+ fprintf(header,"\tstd::string _interfaceName();\n");
+ fprintf(header,"\tbool _isCompatibleWith(const std::string& interfacename);\n");
+ fprintf(header,"\tvoid _buildMethodTable();\n");
+ fprintf(header,"\tvoid dispatch(Arts::Buffer *request, Arts::Buffer *result,"
+ "long methodID);\n");
+
+ if(haveAsyncStreams)
+ fprintf(header,"\tvoid notify(const Arts::Notification& notification);\n");
+
+ fprintf(header,"};\n\n");
+
+ nspace.leaveAll();
+
+ // Create object wrapper for easy C++ syntax
+
+ fprintf(header,"#include \"reference.h\"\n");
+
+ // Allow connect facility only if there is something to connect to!
+/* if (haveStreams(d)) {
+ fprintf(header,"#include \"flowsystem.h\"\n");
+ }
+ fprintf(header,"\n");
+*/
+ nspace.setFromSymbol(d.name);
+
+ inherits = ": public Arts::Object";
+
+ fprintf(header,"class ARTS_EXPORT %s %s {\n",iname.c_str(),inherits.c_str());
+ fprintf(header,"private:\n");
+ fprintf(header,"\tstatic Arts::Object_base* _Creator();\n");
+ fprintf(header,"\t%s_base *_cache;\n",iname.c_str());
+ fprintf(header,"\tinline %s_base *_method_call() {\n",iname.c_str());
+ fprintf(header,"\t\t_pool->checkcreate();\n");
+ fprintf(header,"\t\tif(_pool->base) {\n");
+ fprintf(header,"\t\t\t_cache="
+ "(%s_base *)_pool->base->_cast(%s_base::_IID);\n",
+ iname.c_str(),iname.c_str());
+ fprintf(header,"\t\t\tassert(_cache);\n");
+ fprintf(header,"\t\t}\n");
+ fprintf(header,"\t\treturn _cache;\n");
+ fprintf(header,"\t}\n");
+
+ // This constructor is now protected. use ::null() and ::_from_base()
+ // if necessary. It is protected, though there should be noinherited
+ // class
+ fprintf(header,"\nprotected:\n");
+ fprintf(header,"\tinline %s(%s_base* b) : Arts::Object(b), _cache(0) {}\n\n",
+ iname.c_str(),iname.c_str());
+
+ fprintf(header,"\npublic:\n");
+ fprintf(header,"\ttypedef %s_base _base_class;\n\n",iname.c_str());
+ // empty constructor: specify creator for create-on-demand
+ fprintf(header,"\tinline %s() : Arts::Object(_Creator), _cache(0) {}\n",iname.c_str());
+
+ // constructors from reference and for subclass
+ fprintf(header,"\tinline %s(const Arts::SubClass& s) :\n"
+ "\t\tArts::Object(%s_base::_create(s.string())), _cache(0) {}\n",
+ iname.c_str(),iname.c_str());
+ fprintf(header,"\tinline %s(const Arts::Reference &r) :\n"
+ "\t\tArts::Object("
+ "r.isString()?(%s_base::_fromString(r.string())):"
+ "(%s_base::_fromReference(r.reference(),true))), _cache(0) {}\n",
+ iname.c_str(),iname.c_str(), iname.c_str());
+ fprintf(header,"\tinline %s(const Arts::DynamicCast& c) : "
+ "Arts::Object(%s_base::_fromDynamicCast(c.object())), "
+ "_cache(0) {}\n", iname.c_str(),iname.c_str());
+
+ // copy constructors
+ fprintf(header,"\tinline %s(const %s& target) : Arts::Object(target._pool), _cache(target._cache) {}\n",
+ iname.c_str(),iname.c_str());
+ fprintf(header,"\tinline %s(Arts::Object::Pool& p) : Arts::Object(p), _cache(0) {}\n",
+ iname.c_str());
+
+ // null object
+ // %s::null() returns a null object (and not just a reference to one)
+ fprintf(header,"\tinline static %s null() {return %s((%s_base*)0);}\n",
+ iname.c_str(),iname.c_str(),iname.c_str());
+ fprintf(header,"\tinline static %s _from_base(%s_base* b) {return %s(b);}\n",
+ iname.c_str(),iname.c_str(),iname.c_str());
+
+ // copy operator.
+ fprintf(header,"\tinline %s& operator=(const %s& target) {\n",
+ iname.c_str(),iname.c_str());
+ // test for equality
+ fprintf(header,"\t\tif (_pool == target._pool) return *this;\n");
+ fprintf(header,"\t\t_pool->Dec();\n");
+ fprintf(header,"\t\t_pool = target._pool;\n");
+ fprintf(header,"\t\t_cache = target._cache;\n");
+ fprintf(header,"\t\t_pool->Inc();\n");
+ fprintf(header,"\t\treturn *this;\n");
+ fprintf(header,"\t}\n");
+
+ // casts to parent interfaces
+ vector<string> parents = allParentsUnique(d);
+ for (vector<std::string>::iterator si = parents.begin();
+ si != parents.end(); si++)
+ {
+ string &s = *si;
+ fprintf(header,"\tinline operator %s() const { return %s(*_pool); }\n",
+ s.c_str(), s.c_str());
+ }
+
+ // conversion to _base* object
+ fprintf(header,"\tinline %s_base* _base() {return _cache?_cache:_method_call();}\n",iname.c_str());
+ fprintf(header,"\n");
+
+ vector<string> all = parents;
+ vector<string>::iterator i;
+ all.push_back(d.name);
+ // InterfaceDef allMerged = mergeAllParents(d);
+
+ map<string, string> definitionMap;
+
+ for(i=all.begin();i != all.end();i++)
+ {
+ InterfaceDef id = findInterface(*i);
+ string baseclass = id.name+"_base";
+
+ /* attributes */
+ for(ai = id.attributes.begin();ai != id.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+ ForwardCode fc;
+ fc.fullifacename = fullifacename;
+ fc.constructor = false;
+ fc.mname = ad.name;
+ fc.baseclass = baseclass;
+
+ checkSymbolDefinition(ad.name, "attribute", id, definitionMap);
+
+ if(ad.flags & attributeAttribute)
+ {
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ fc.params = "";
+ fc.callparams = "";
+ fc.result = createTypeCode(ad.type,"",MODEL_RESULT);
+ fprintf(header,"\tinline %s %s();\n",
+ fc.result.c_str(), fc.mname.c_str());
+ forwardCode.push_back(fc);
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ fc.params =
+ createTypeCode(ad.type,"_newValue",MODEL_ARG);
+ fc.callparams = "_newValue";
+ fc.result="void";
+ fprintf(header,"\tinline void %s(%s);\n",
+ fc.mname.c_str(), fc.params.c_str());
+ forwardCode.push_back(fc);
+ }
+ }
+ }
+
+ /* methods */
+ for(mi = id.methods.begin(); mi != id.methods.end(); mi++)
+ {
+ MethodDef& md = *mi;
+ ForwardCode fc;
+ fc.fullifacename = fullifacename;
+ fc.result = createReturnCode(md);
+ fc.params = createParamList(md);
+ fc.callparams = createCallParamList(md);
+ fc.constructor = (md.name == "constructor");
+ fc.baseclass = baseclass;
+
+ checkSymbolDefinition(md.name, "method", id, definitionMap);
+
+ // map constructor methods to the real things
+ if (md.name == "constructor") {
+ fc.mname = iname;
+ fprintf(header,"\tinline %s(%s);\n",
+ iname.c_str(),fc.params.c_str());
+ } else {
+ fc.mname = md.name;
+ fprintf(header,"\tinline %s %s(%s);\n",fc.result.c_str(),
+ md.name.c_str(),fc.params.c_str());
+ }
+
+ forwardCode.push_back(fc);
+ }
+ }
+ fprintf(header,"};\n\n");
+ }
+
+ nspace.leaveAll();
+
+ /*
+ * Forwarding code. We have to do this here, as the classes may depend on
+ * each other, e.g. an argument of one function are a SmartWrapper which is
+ * declared later in the text.
+ */
+ if(!forwardCode.empty())
+ fprintf(header,"// Forward wrapper calls to _base classes:\n\n");
+
+ list<ForwardCode>::iterator fi;
+ for(fi = forwardCode.begin(); fi != forwardCode.end(); fi++)
+ {
+ if(fi->constructor)
+ {
+ fprintf(header,"inline %s::%s(%s)\n", fi->fullifacename.c_str(),
+ fi->mname.c_str(), fi->params.c_str());
+ fprintf(header,"\t\t: Arts::Object(%s_base::_create())\n",
+ fi->mname.c_str());
+ fprintf(header,"{\n");
+ fprintf(header,"\tstatic_cast<%s*>(_method_call())->constructor(%s);\n",
+ fi->baseclass.c_str(),fi->callparams.c_str());
+ fprintf(header,"}\n\n");
+ }
+ else
+ {
+ fprintf(header,"inline %s %s::%s(%s)\n",
+ fi->result.c_str(), fi->fullifacename.c_str(),
+ fi->mname.c_str(), fi->params.c_str());
+ fprintf(header,"{\n");
+ fprintf(header,"\t%s _cache?static_cast<%s*>(_cache)->%s(%s):"
+ "static_cast<%s*>(_method_call())->%s(%s);\n",
+ fi->result=="void"?"":"return",
+ fi->baseclass.c_str(),
+ fi->mname.c_str(),fi->callparams.c_str(),
+ fi->baseclass.c_str(),
+ fi->mname.c_str(),fi->callparams.c_str());
+
+ fprintf(header,"}\n\n");
+ }
+ }
+}
+
+enum DefaultDirection {defaultIn, defaultOut};
+bool addParentDefaults(InterfaceDef& iface, vector<std::string>& ports, DefaultDirection dir);
+bool lookupParentPort(InterfaceDef& iface, string port, vector<std::string>& ports, DefaultDirection dir);
+
+bool addDefaults(InterfaceDef& iface, vector<std::string>& ports, DefaultDirection dir)
+{
+ vector<AttributeDef>::iterator ai;
+ vector<std::string>::iterator di;
+ bool hasDefault = false;
+ // Go through the default ports of this interface
+ for (di = iface.defaultPorts.begin(); di != iface.defaultPorts.end(); di++) {
+ bool foundIn = false, foundOut = false;
+ // Find the corresponding attribute definition
+ for (ai = iface.attributes.begin(); ai != iface.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if ((ad.flags & attributeStream) && ((*di)==ad.name)) {
+ // Add this port to the list
+ if (ad.flags & streamIn) {
+ foundIn=true;
+ if (dir==defaultIn) ports.push_back(*di);
+ }
+ // Add this port to the list
+ if (ad.flags & streamOut) {
+ foundOut=true;
+ if (dir==defaultOut) ports.push_back(*di);
+ }
+ }
+ }
+ bool found = false;
+ // Not found, might come from a parent
+ if (!(foundIn || foundOut)) {
+ found = lookupParentPort(iface, *di, ports, dir);
+ }
+ if ((found) || (foundIn && (dir==defaultIn)) || (foundOut && (dir==defaultOut)))
+ hasDefault = true;
+ }
+ // If no default was specified, then try to inherit some
+ if (!hasDefault)
+ hasDefault = addParentDefaults(iface, ports, dir);
+
+ // Still have no default?
+ // If we have only one stream in a given direction, make it default.
+ if (!hasDefault) {
+ vector<AttributeDef>::iterator foundPos;
+ int found = 0;
+ for (ai = iface.attributes.begin(); ai != iface.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+ if (ad.flags & attributeStream) {
+ if ((ad.flags & streamIn) && (dir == defaultIn)) {
+ found++; foundPos=ai;
+ }
+ if ((ad.flags & streamOut) && (dir == defaultOut)) {
+ found++; foundPos=ai;
+ }
+ }
+ }
+ if (found == 1) {hasDefault=true; ports.push_back(foundPos->name);}
+ }
+ return hasDefault;
+}
+
+
+bool addParentDefaults(InterfaceDef& iface, vector<std::string>& ports, DefaultDirection dir)
+{
+ list<InterfaceDef>::iterator interIt;
+ vector<std::string>::iterator si;
+ bool hasDefault = false;
+ // For all inherited interfaces
+ for (si = iface.inheritedInterfaces.begin(); si != iface.inheritedInterfaces.end(); si++)
+ {
+ // Find the corresponding interface definition
+ for (interIt=interfaces.begin(); interIt!=interfaces.end(); interIt++) {
+ InterfaceDef& parent = *interIt;
+ if (parent.name == (*si)) {
+ // Now add the default ports of this parent
+ bool b = addDefaults(parent, ports, dir);
+ if (b) hasDefault = true;
+ break;
+ }
+ }
+ }
+ return hasDefault;
+}
+
+bool lookupParentPort(InterfaceDef& iface, string port, vector<std::string>& ports, DefaultDirection dir)
+{
+ list<InterfaceDef>::iterator interIt;
+ vector<AttributeDef>::iterator ai;
+ vector<std::string>::iterator si;
+ // For all inherited interfaces
+ for (si = iface.inheritedInterfaces.begin(); si != iface.inheritedInterfaces.end(); si++)
+ {
+ // Find the corresponding interface definition
+ for (interIt=interfaces.begin(); interIt!=interfaces.end(); interIt++) {
+ InterfaceDef& parent = *interIt;
+ if (parent.name == (*si)) {
+ // Now look at the ports of this parent
+ vector<AttributeDef>::iterator foundPos;
+ bool found = false;
+ for (ai = parent.attributes.begin(); ai != parent.attributes.end(); ai++) {
+ if ((ai->flags & attributeStream) && (ai->name==port)){
+ if (((ai->flags & streamIn) && (dir == defaultIn))
+ || ((ai->flags & streamOut) && (dir == defaultOut))) {
+ found = true; foundPos=ai; break;
+ }
+ }
+ }
+ if (found) {ports.push_back(port); return true;}
+ // Not found, look recursively at the parent ancestors
+ bool b = lookupParentPort(parent, port, ports, dir);
+ if (b) return true; // done
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+void doInterfacesSource(FILE *source)
+{
+ list<InterfaceDef>::iterator ii;
+ vector<MethodDef>::iterator mi;
+ vector<AttributeDef>::iterator ai;
+
+ long mcount;
+
+ for(ii = interfaces.begin();ii != interfaces.end(); ii++)
+ {
+ InterfaceDef& d = *ii;
+
+ if(fromInclude(d.name)) continue; // should come from the include
+
+ string iname = NamespaceHelper::nameOf(d.name);
+
+ // create static functions
+
+ fprintf(source,"%s_base *%s_base::_create(const std::string& subClass)\n",
+ d.name.c_str(),d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\tArts::Object_skel *skel = "
+ "Arts::ObjectManager::the()->create(subClass);\n");
+ fprintf(source,"\tassert(skel);\n");
+ fprintf(source,"\t%s_base *castedObject = "
+ "(%s_base *)skel->_cast(%s_base::_IID);\n",
+ d.name.c_str(),d.name.c_str(),d.name.c_str());
+ fprintf(source,"\tassert(castedObject);\n");
+ fprintf(source,"\treturn castedObject;\n");
+ fprintf(source,"}\n\n");
+
+
+ fprintf(source,"%s_base *%s_base::_fromString(const std::string& objectref)\n",
+ d.name.c_str(),d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\tArts::ObjectReference r;\n\n");
+ fprintf(source,"\tif(Arts::Dispatcher::the()->stringToObjectReference(r,objectref))\n");
+ fprintf(source,"\t\treturn %s_base::_fromReference(r,true);\n",
+ d.name.c_str());
+ fprintf(source,"\treturn 0;\n");
+ fprintf(source,"}\n\n");
+
+ fprintf(source,"%s_base *%s_base::_fromDynamicCast(const Arts::Object& object)\n",
+ d.name.c_str(),d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\tif(object.isNull()) return 0;\n\n");
+ fprintf(source,"\t%s_base *castedObject = (%s_base *)object._base()->_cast(%s_base::_IID);\n",
+ d.name.c_str(), d.name.c_str(), d.name.c_str());
+ fprintf(source,"\tif(castedObject) return castedObject->_copy();\n\n");
+ fprintf(source,"\treturn _fromString(object._toString());\n");
+ fprintf(source,"}\n\n");
+
+ fprintf(source,"%s_base *%s_base::_fromReference(Arts::ObjectReference r,"
+ " bool needcopy)\n",d.name.c_str(),d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\t%s_base *result;\n",d.name.c_str());
+ fprintf(source,
+ "\tresult = (%s_base *)Arts::Dispatcher::the()->connectObjectLocal(r,\"%s\");\n",
+ d.name.c_str(),d.name.c_str());
+ fprintf(source,"\tif(result)\n");
+ fprintf(source,"\t{\n");
+ fprintf(source,"\t\tif(!needcopy)\n");
+ fprintf(source,"\t\t\tresult->_cancelCopyRemote();\n");
+ fprintf(source,"\t}\n");
+ fprintf(source,"\telse\n");
+ fprintf(source,"\t{\n");
+ fprintf(source,"\t\tArts::Connection *conn = "
+ "Arts::Dispatcher::the()->connectObjectRemote(r);\n");
+ fprintf(source,"\t\tif(conn)\n");
+ fprintf(source,"\t\t{\n");
+ fprintf(source,"\t\t\tresult = new %s_stub(conn,r.objectID);\n",
+ d.name.c_str());
+ fprintf(source,"\t\t\tif(needcopy) result->_copyRemote();\n");
+ fprintf(source,"\t\t\tresult->_useRemote();\n");
+
+ // Type checking
+ /*
+ * One may wonder why we first claim that we want to use the object
+ * using _useRemote, then check if we *can* to use it (if the
+ * type is right), and finally, if we can't release it
+ * again.
+ *
+ * However, if we don't, we can't release it either, as we may not
+ * release an object which we don't use. If we would not call release,
+ * we would on the other hand create a *local* memory leak, as the
+ * _stub wouldn't get removed.
+ */
+ fprintf(source,"\t\t\tif (!result->_isCompatibleWith(\"%s\")) {\n",
+ d.name.c_str());
+ fprintf(source,"\t\t\t\tresult->_release();\n");
+ fprintf(source,"\t\t\t\treturn 0;\n");
+ fprintf(source,"\t\t\t}\n");
+
+ fprintf(source,"\t\t}\n");
+ fprintf(source,"\t}\n");
+ fprintf(source,"\treturn result;\n");
+ fprintf(source,"}\n\n");
+
+
+ // Default I/O info
+ vector<std::string> portsIn, portsOut;
+ vector<std::string>::iterator si, di;
+ addDefaults(d, portsIn, defaultIn);
+ addDefaults(d, portsOut, defaultOut);
+
+ vector<std::string> done; // don't repeat values
+ fprintf(source,"std::vector<std::string> %s_base::_defaultPortsIn() const {\n",d.name.c_str());
+ fprintf(source,"\tstd::vector<std::string> ret;\n");
+ // Loop through all the values
+ for (si = portsIn.begin(); si != portsIn.end(); si++)
+ {
+ // repeated value? (virtual public like merging...)
+ bool skipIt = false;
+ for (di = done.begin(); di != done.end(); di++) {
+ if ((*di)==(*si)) {skipIt = true; break;}
+ }
+ if (skipIt) continue;
+ fprintf(source,"\tret.push_back(\"%s\");\n",(*si).c_str());
+ done.push_back(*si);
+ }
+ fprintf(source,"\treturn ret;\n}\n");
+ done.clear();
+ fprintf(source,"std::vector<std::string> %s_base::_defaultPortsOut() const {\n",d.name.c_str());
+ fprintf(source,"\tstd::vector<std::string> ret;\n");
+ // Loop through all the values
+ for (si = portsOut.begin(); si != portsOut.end(); si++)
+ {
+ // repeated value? (virtual public like merging...)
+ bool skipIt = false;
+ for (di = done.begin(); di != done.end(); di++) {
+ if ((*di)==(*si)) {skipIt = true; break;}
+ }
+ if (skipIt) continue;
+ fprintf(source,"\tret.push_back(\"%s\");\n",(*si).c_str());
+ done.push_back(*si);
+ }
+ fprintf(source,"\treturn ret;\n}\n\n");
+
+ /** _cast operation **/
+ vector<std::string> parentCast = allParentsUnique(d);
+
+ fprintf(source,"void *%s_base::_cast(unsigned long iid)\n",
+ d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\tif(iid == %s_base::_IID) return (%s_base *)this;\n",
+ d.name.c_str(),d.name.c_str());
+
+ vector<std::string>::iterator pci;
+ for(pci = parentCast.begin(); pci != parentCast.end();pci++)
+ {
+ string& pc = *pci;
+ fprintf(source,"\tif(iid == %s_base::_IID) "
+ "return (%s_base *)this;\n",pc.c_str(),pc.c_str());
+ }
+ fprintf(source,"\tif(iid == Arts::Object_base::_IID) return (Arts::Object_base *)this;\n");
+ fprintf(source,"\treturn 0;\n");
+ fprintf(source,"}\n\n");
+
+ // create stub
+
+ /** constructors **/
+ fprintf(source,"%s_stub::%s_stub()\n" ,d.name.c_str(),iname.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\t// constructor for subclasses"
+ " (don't use directly)\n");
+ fprintf(source,"}\n\n");
+
+ fprintf(source,"%s_stub::%s_stub(Arts::Connection *connection, "
+ "long objectID)\n",d.name.c_str(),iname.c_str());
+ fprintf(source," : Arts::Object_stub(connection, objectID)\n");
+ fprintf(source,"{\n");
+ fprintf(source,"\t// constructor to create a stub for an object\n");
+ fprintf(source,"}\n\n");
+
+ /** stub operations **/
+
+ /** stub operations for object methods **/
+ for(mi = d.methods.begin(); mi != d.methods.end(); mi++)
+ {
+ MethodDef& md = *mi;
+ createStubCode(source,d.name.c_str(),md.name.c_str(),md);
+ }
+
+ /** stub operations for attributes **/
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if(ad.flags & attributeAttribute)
+ {
+ MethodDef md;
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ md.name = "_get_"+ad.name;
+ md.type = ad.type;
+ md.flags = methodTwoway;
+ /* no parameters (don't set md.signature) */
+
+ createStubCode(source,d.name.c_str(),ad.name.c_str(),md);
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ md.name = "_set_"+ad.name;
+ md.type = "void";
+ md.flags = methodTwoway;
+
+ ParamDef pd;
+ pd.type = ad.type;
+ pd.name = "newValue";
+ md.signature.push_back(pd);
+
+ createStubCode(source,d.name.c_str(),ad.name.c_str(),md);
+ }
+ }
+ }
+
+ // create skeleton
+
+ /** _interfaceName **/
+ fprintf(source,"std::string %s_skel::_interfaceName()\n",
+ d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\treturn \"%s\";\n",d.name.c_str());
+ fprintf(source,"}\n\n");
+
+ // Run-time type compatibility check
+ fprintf(source,"bool %s_skel::_isCompatibleWith(const std::string& interfacename)\n",
+ d.name.c_str());
+ fprintf(source,"{\n");
+ // Interface is compatible with itself!
+ fprintf(source,"\tif (interfacename == \"%s\") return true;\n",d.name.c_str());
+ // It also provides the parent interfaces
+ for(pci = parentCast.begin(); pci != parentCast.end();pci++)
+ {
+ fprintf(source,"\tif (interfacename == \"%s\") return true;\n", pci->c_str());
+ }
+ // and is ultimately an Object
+ fprintf(source,"\tif (interfacename == \"Arts::Object\") return true;\n");
+ fprintf(source,"\treturn false;\n"); // And nothing else
+ fprintf(source,"}\n\n");
+
+ fprintf(source,"std::string %s_skel::_interfaceNameSkel()\n",
+ d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\treturn \"%s\";\n",d.name.c_str());
+ fprintf(source,"}\n\n");
+
+ /** dispatch operations **/
+ Buffer methodTable;
+
+ /** dispatch operations for object methods **/
+ mcount = 0;
+ for(mi = d.methods.begin(); mi != d.methods.end(); mi++, mcount++)
+ {
+ MethodDef& md = *mi;
+ md.writeType(methodTable);
+
+ createDispatchFunction(source,mcount,d,md,md.name);
+ }
+
+ /** dispatch operations for attributes **/
+
+ for(ai = d.attributes.begin();ai != d.attributes.end();ai++)
+ {
+ AttributeDef& ad = *ai;
+
+ if(ad.flags & attributeAttribute)
+ {
+ MethodDef md;
+ if(ad.flags & streamOut) /* readable from outside */
+ {
+ md.name = "_get_"+ad.name;
+ md.type = ad.type;
+ md.flags = methodTwoway;
+ /* no parameters (don't set md.signature) */
+
+ md.writeType(methodTable);
+ createDispatchFunction(source,mcount++,d,md,ad.name);
+ }
+ if(ad.flags & streamIn) /* writeable from outside */
+ {
+ md.name = "_set_"+ad.name;
+ md.type = "void";
+ md.flags = methodTwoway;
+
+ ParamDef pd;
+ pd.type = ad.type;
+ pd.name = "newValue";
+
+ md.signature.push_back(pd);
+
+ md.writeType(methodTable);
+ createDispatchFunction(source,mcount++,d,md,ad.name);
+ }
+ }
+ }
+
+ /** methodTable **/
+
+ string methodTableString = formatMultiLineString(
+ methodTable.toString("MethodTable")," ");
+
+ fprintf(source,"void %s_skel::_buildMethodTable()\n",d.name.c_str());
+ fprintf(source,"{\n");
+ fprintf(source,"\tArts::Buffer m;\n");
+ fprintf(source,"\tm.fromString(\n");
+ fprintf(source,"%s,\n",methodTableString.c_str());
+ fprintf(source,"\t\t\"MethodTable\"\n");
+ fprintf(source,"\t);\n");
+
+ long i;
+ for(i=0;i<mcount;i++)
+ fprintf(source,"\t_addMethod(%s,this,Arts::MethodDef(m));\n",
+ dispatchFunctionName(d.name,i).c_str());
+
+ vector<string>::iterator ii = d.inheritedInterfaces.begin();
+ while(ii != d.inheritedInterfaces.end())
+ {
+ fprintf(source,"\t%s_skel::_buildMethodTable();\n",
+ ii->c_str());
+ ii++;
+ }
+ fprintf(source,"}\n\n");
+
+ fprintf(source,"%s_skel::%s_skel()\n", d.name.c_str(),iname.c_str());
+ fprintf(source,"{\n");
+ for(ai = d.attributes.begin(); ai != d.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+ if((ad.flags & attributeStream) == attributeStream)
+ {
+ fprintf(source,"\t_initStream(\"%s\",&%s,%d);\n",
+ ad.name.c_str(),ad.name.c_str(),ad.flags);
+ }
+ }
+ fprintf(source,"}\n\n");
+
+ /** notification operation **/
+ if(haveAsyncStreams(d))
+ {
+ fprintf(source,"void %s_skel::notify(const Arts::Notification "
+ "&notification)\n", d.name.c_str());
+ fprintf(source,"{\n");
+ for(ai = d.attributes.begin(); ai != d.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+ if((ad.flags & (attributeStream|streamAsync))
+ == (attributeStream|streamAsync))
+ {
+ const char *fname=(ad.flags&streamIn)?"process":"request";
+ string packettype =
+ createTypeCode(ad.type,"",MODEL_ASTREAM_PACKETPTR);
+
+ fprintf(source,"\tif(%s.notifyID() == notification.ID)\n",
+ ad.name.c_str());
+ fprintf(source,
+ "\t\t%s_%s((%s)notification.data);\n",
+ fname,ad.name.c_str(),packettype.c_str());
+ }
+ }
+ fprintf(source,"}\n\n");
+
+ /*
+ * create empty request_ methods for output streams
+ * (not everybody uses requesting)
+ */
+ for(ai = d.attributes.begin(); ai != d.attributes.end(); ai++)
+ {
+ AttributeDef& ad = *ai;
+ if((ad.flags & (attributeStream|streamAsync|streamOut))
+ == (attributeStream|streamAsync|streamOut))
+ {
+ string packettype =
+ createTypeCode(ad.type,"",MODEL_ASTREAM_PACKETPTR);
+ fprintf(source,"void %s_skel::request_%s(%s)\n",
+ d.name.c_str(),ad.name.c_str(),packettype.c_str());
+ fprintf(source,"{\n");
+ fprintf(source," assert(false); // this default is for "
+ "modules who don't want requesting\n");
+ fprintf(source,"}\n\n");
+ }
+ }
+ }
+
+ // Smartwrapper statics
+ // _Creator
+ fprintf(source,"Arts::Object_base* %s::_Creator() {\n",d.name.c_str());
+ fprintf(source,"\treturn %s_base::_create();\n",d.name.c_str());
+ fprintf(source,"}\n\n");
+
+ // IID
+ fprintf(source,"unsigned long %s_base::_IID = "
+ "Arts::MCOPUtils::makeIID(\"%s\");\n\n",d.name.c_str(),d.name.c_str());
+ }
+}
+
+void doInterfaceRepoSource(FILE *source, string prefix)
+{
+ Buffer b;
+ module.moduleName = "";
+ module.writeType(b);
+
+ string data = formatMultiLineString(b.toString("IDLFile")," ");
+
+ fprintf(source,"static Arts::IDLFileReg IDLFileReg_%s(\"%s\",\n%s\n);\n",
+ prefix.c_str(),prefix.c_str(),data.c_str());
+}
+
+void doTypeFile(string prefix)
+{
+ Buffer b;
+ module.moduleName = prefix;
+ module.writeType(b);
+
+ FILE *typeFile = fopen((prefix+".mcoptype.new").c_str(),"w");
+ unsigned long towrite = b.size();
+ fwrite(b.read(towrite),1,towrite,typeFile);
+ fclose(typeFile);
+}
+
+void doTypeIndex(string prefix)
+{
+ FILE *typeIndex = fopen((prefix+".mcopclass.new").c_str(),"w");
+
+ vector<string> supportedTypes;
+
+ vector<InterfaceDef>::iterator ii;
+ for(ii = module.interfaces.begin(); ii != module.interfaces.end(); ii++)
+ if(!fromInclude(ii->name)) supportedTypes.push_back(ii->name);
+
+ vector<TypeDef>::iterator ti;
+ for(ti = module.types.begin(); ti != module.types.end(); ti++)
+ if(!fromInclude(ti->name)) supportedTypes.push_back(ti->name);
+
+ string supportedTypesList;
+ vector<string>::iterator si;
+ bool first = true;
+ for(si = supportedTypes.begin(); si != supportedTypes.end(); si++)
+ {
+ if(!first) supportedTypesList += ",";
+
+ supportedTypesList += (*si);
+ first = false;
+ }
+ fprintf(typeIndex, "# this file was generated by the MCOP idl compiler - DO NOT EDIT\n");
+ fprintf(typeIndex,"Type=%s\n",supportedTypesList.c_str());
+ fprintf(typeIndex,"TypeFile=%s.mcoptype\n",prefix.c_str());
+ fclose(typeIndex);
+}
+
+void exit_usage(char *name)
+{
+ fprintf(stderr,"usage: %s [ <options> ] <filename>\n",name);
+ fprintf(stderr,"\nOptions:\n");
+ fprintf(stderr," -I <directory> search in <directory> for includes\n");
+ fprintf(stderr," -e <name> exclude a struct/interface/enum from code generation\n");
+ fprintf(stderr," -t create .mcoptype/.mcopclass files with type information\n");
+ exit(1);
+}
+extern void mcopidlParse(const char *code);
+
+bool match(vector<char>::iterator start, const char *string)
+{
+ while(*string && *start)
+ if(*string++ != *start++) return false;
+
+ return (*string == 0);
+}
+
+bool fileExists(const char *filename)
+{
+ FILE *test = fopen(filename,"r");
+ if(test)
+ {
+ fclose(test);
+ return true;
+ }
+ return false;
+}
+
+string searchFile(const char *filename,list<string>& path)
+{
+ if(fileExists(filename)) return filename;
+
+ list<string>::iterator i;
+ for(i = path.begin(); i != path.end(); i++)
+ {
+ string location = *i + "/" + filename;
+ if(fileExists(location.c_str())) return location;
+ }
+ fprintf(stderr,"file '%s' not found\n",filename);
+ exit(1);
+}
+
+void append_file_to_vector(const char *filename, vector<char>& v)
+{
+ FILE *f = fopen(filename,"r");
+ if(!f) {
+ fprintf(stderr,"file '%s' not found\n",filename);
+ exit(1);
+ }
+
+ char buffer[1024];
+ long l;
+ while((l = fread(buffer,1,1024,f)) > 0)
+ v.insert(v.end(),buffer, buffer+l);
+ fclose(f);
+}
+
+void append_string_to_vector(const char *string, vector<char>& v)
+{
+ while(*string) v.push_back(*string++);
+}
+
+void preprocess(vector<char>& input, vector<char>& output)
+{
+ string filename;
+ enum { lineStart, idlCode, commentC, filenameFind,
+ filenameIn1, filenameIn2 } state = lineStart;
+
+ vector<char>::iterator i = input.begin();
+
+ while(i != input.end())
+ {
+ if(state != commentC && match(i,"/*")) // check if here starts a comment
+ {
+ state = commentC;
+ i += 2;
+ }
+ else if(state == commentC)
+ {
+ if(match(i,"*/")) // leave comment state?
+ {
+ state = idlCode;
+ i += 2;
+ }
+ else // skip comments
+ {
+ if(*i == '\n') output.push_back(*i); // keep line numbering
+ i++;
+ }
+ }
+ else if(state == filenameFind)
+ {
+ switch(*i++)
+ {
+ case ' ': // skip whitespaces
+ case '\t':
+ break;
+
+ case '"': state = filenameIn1;
+ break;
+ case '<': state = filenameIn2;
+ break;
+ default: cerr << "bad char after #include statement" << endl;
+ assert(0); // error handling!
+ }
+ }
+ else if((state == filenameIn1 && *i == '"')
+ || (state == filenameIn2 && *i == '>'))
+ {
+ append_string_to_vector("#startinclude <",output);
+ append_string_to_vector(filename.c_str(),output);
+ append_string_to_vector(">\n",output);
+
+ if(!haveIncluded(filename))
+ {
+ ::includes.push_back(filename);
+
+ // load include, preprocess
+ vector<char> file,filepp;
+
+ string location = searchFile(filename.c_str(),includePath);
+ append_file_to_vector(location.c_str(),file);
+ preprocess(file,filepp);
+
+ // append preprocessed file
+ output.insert(output.end(),filepp.begin(),filepp.end());
+ }
+
+ append_string_to_vector("#endinclude",output);
+ state = idlCode;
+ i++;
+ }
+ else if(state == filenameIn1 || state == filenameIn2)
+ {
+ filename += *i++;
+ }
+ else if(state == lineStart) // check if we're on lineStart
+ {
+ if(match(i,"#include"))
+ {
+ i += 8;
+ state = filenameFind;
+ filename = "";
+ }
+ else
+ {
+ if(*i != ' ' && *i != '\t' && *i != '\n') state = idlCode;
+ output.push_back(*i++);
+ }
+ }
+ else
+ {
+ if(*i == '\n') state = lineStart; // newline handling
+ output.push_back(*i++);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ /*
+ * parse command line options
+ */
+ int c;
+ bool makeTypeInfo = false;
+ while((c = getopt(argc, argv, "I:P:C:te:")) != -1)
+ {
+ switch(c)
+ {
+ case 'I': includePath.push_back(optarg);
+ break;
+ case 'P': packetTypes.push_back(optarg);
+ break;
+ case 'C': customIncludes.push_back(optarg);
+ break;
+ case 't': makeTypeInfo = true;
+ break;
+ case 'e': includedNames.push_back(optarg);
+ break;
+ default: exit_usage(argv[0]);
+ break;
+ }
+ }
+
+ if((argc-optind) != 1) exit_usage(argv[0]);
+
+ const char *inputfile = argv[optind];
+
+ /*
+ * find out prefix (filename without .idl)
+ */
+
+ char *prefix = strdup(inputfile);
+
+ if(strlen(prefix) < 4 || strcmp(&prefix[strlen(prefix)-4],".idl")) {
+ fprintf(stderr,"filename must end in .idl\n");
+ exit(1);
+ } else {
+ prefix[strlen(prefix)-4] = 0;
+ }
+
+ /*
+ * strip path (mcopidl always outputs the result into the current directory)
+ */
+ char *pathless = strrchr(prefix,'/');
+ if(pathless)
+ prefix = pathless+1;
+
+ /*
+ * load file
+ */
+
+ idl_line_no = 1;
+ idl_in_include = 0;
+ idl_filename = inputfile;
+
+ vector<char> contents,contentspp;
+ append_file_to_vector(inputfile,contents);
+
+ // trailing zero byte (mcopidlParse wants a C-style string as argument)
+ contents.push_back(0);
+
+ // preprocess (throws includes into contents, removes C-style comments)
+ preprocess(contents,contentspp);
+
+ // call lex&yacc parser
+ mcopidlParse(&contentspp[0]);
+
+ // generate code for C++ header file
+ FILE *header = startHeader(prefix);
+ doIncludeHeader(header);
+ doEnumHeader(header);
+ doStructHeader(header);
+ doInterfacesHeader(header);
+ endHeader(header,prefix);
+ moveIfChanged(string(prefix)+".h");
+
+ // generate code for C++ source file
+ FILE *source = startSource(prefix);
+ doStructSource(source);
+ doInterfacesSource(source);
+ doInterfaceRepoSource(source,prefix);
+ endSource(source);
+ moveIfChanged(string(prefix)+".cc");
+
+ // create type file
+ if(makeTypeInfo)
+ {
+ doTypeFile(prefix);
+ doTypeIndex(prefix);
+ moveIfChanged(string(prefix)+".mcoptype");
+ moveIfChanged(string(prefix)+".mcopclass");
+ }
+
+ return 0;
+}
diff --git a/mcopidl/namespace.cc b/mcopidl/namespace.cc
new file mode 100644
index 0000000..1e863a0
--- /dev/null
+++ b/mcopidl/namespace.cc
@@ -0,0 +1,208 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <list>
+#include <string>
+#include <map>
+#include "namespace.h"
+#include <assert.h>
+
+using namespace std;
+
+/* generic utilities */
+
+static list<string> symbolToList(string symbol)
+{
+ list<string> result;
+ string current;
+
+ string::iterator si;
+ for(si = symbol.begin(); si != symbol.end(); si++)
+ {
+ if(*si != ':')
+ {
+ current += *si;
+ }
+ else
+ {
+ if(!current.empty())
+ result.push_back(current);
+
+ current = "";
+ }
+ }
+
+ result.push_back(current);
+ return result;
+}
+
+static string listToSymbol(list<string>& symlist)
+{
+ string s;
+ list<string>::iterator si;
+ for(si = symlist.begin(); si != symlist.end(); si++)
+ {
+ if(!s.empty()) s += "::";
+ s += *si;
+ }
+ return s;
+}
+
+/* ModuleHelper */
+static list<string> modulePath;
+static map<string,bool> moduleDefinitions;
+
+void ModuleHelper::enter(const char *name)
+{
+ modulePath.push_back(name);
+}
+
+void ModuleHelper::leave()
+{
+ assert(!modulePath.empty());
+ modulePath.pop_back();
+}
+
+string prependModulePath(string s)
+{
+ if(modulePath.empty())
+ return s;
+ else
+ return listToSymbol(modulePath)+"::"+s;
+}
+
+void ModuleHelper::define(const char *name)
+{
+ moduleDefinitions[prependModulePath(name)] = true;
+}
+
+char *ModuleHelper::qualify(const char *name)
+{
+ char *result = 0;
+
+ // TODO: nested namespaces
+
+ string inCurrentModule = prependModulePath(name);
+ if(moduleDefinitions[inCurrentModule])
+ {
+ result = strdup(inCurrentModule.c_str());
+ }
+ else if(moduleDefinitions[name])
+ {
+ result = strdup(name);
+ }
+ else
+ {
+ fprintf(stderr,"warning: qualifyName failed for %s\n",name);
+ result = strdup(name);
+ }
+
+ return result;
+}
+
+
+/* NamespaceHelper */
+NamespaceHelper::NamespaceHelper(FILE *outputfile) : out(outputfile)
+{
+}
+
+NamespaceHelper::~NamespaceHelper()
+{
+ leaveAll();
+}
+
+void NamespaceHelper::setFromSymbol(string symbol)
+{
+ list<string> symlist = symbolToList(symbol);
+ symlist.pop_back();
+
+ /* check that the current namespace doesn't contain wrong parts at end */
+ list<string>::iterator ni,si;
+ ni = currentNamespace.begin();
+ si = symlist.begin();
+ long wrong = currentNamespace.size();
+ while(ni != currentNamespace.end() && si != symlist.end() && *ni == *si)
+ {
+ ni++;
+ si++;
+ wrong--;
+ }
+ while(wrong--)
+ {
+ fprintf(out,"}\n");
+ }
+
+ /* enter new components at the end */
+ while(si != symlist.end())
+ {
+ fprintf(out,"namespace %s {\n",(*si++).c_str());
+ }
+ currentNamespace = symlist;
+}
+
+void NamespaceHelper::leaveAll()
+{
+ setFromSymbol("unqualified");
+}
+
+string NamespaceHelper::printableForm(string symbol)
+{
+ list<string> symlist = symbolToList(symbol);
+ list<string> current = currentNamespace;
+
+ while(!current.empty())
+ {
+ // namespace longer than symbol?
+ assert(!symlist.empty());
+
+ if(*current.begin() == *symlist.begin())
+ {
+ current.pop_front();
+ symlist.pop_front();
+ }
+ else
+ {
+ return "::"+symbol;
+ }
+ }
+
+ return listToSymbol(symlist);
+}
+
+string NamespaceHelper::nameOf(string symbol)
+{
+ if(symbol.empty()) return "";
+
+ list<string> symlist = symbolToList(symbol);
+ return symlist.back();
+}
+
+string NamespaceHelper::namespaceOf(string symbol)
+{
+ list<string> symlist = symbolToList(symbol);
+ if(symlist.size() < 2) return "";
+
+ symlist.pop_back();
+ return listToSymbol(symlist);
+}
diff --git a/mcopidl/namespace.h b/mcopidl/namespace.h
new file mode 100644
index 0000000..479e30f
--- /dev/null
+++ b/mcopidl/namespace.h
@@ -0,0 +1,91 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+#ifndef _MCOPIDL_NAMESPACE_H__
+#define _MCOPIDL_NAMESPACE_H__
+
+#include <stdio.h>
+#include <string>
+#include <list>
+
+/**
+ * This class is used while parsing IDL files. It is used to produce fully
+ * qualified names (e.g. Arts::Object rather than just Object) of all type
+ * identifiers.
+ */
+class ModuleHelper {
+public:
+ static void enter(const char *name);
+ static void leave();
+ static void define(const char *name);
+ static char *qualify(const char *name);
+};
+
+/**
+ * This class is used during code generation. It generates the namespace
+ * opening and closing code.
+ */
+class NamespaceHelper {
+protected:
+ FILE *out;
+ std::list<std::string> currentNamespace;
+
+public:
+ NamespaceHelper(FILE *outputfile);
+ ~NamespaceHelper();
+
+ /**
+ * This method will cause the NamespaceHelper to enter the namespace the
+ * symbol is in. That means setFromSymbol("Arts::Object") will enter the
+ * namespace Arts. Since this generates code, it should only be called
+ * outside of class definitions.
+ */
+ void setFromSymbol(std::string symbol);
+
+ /**
+ * This leaves all open namespaces which is useful if you want to include
+ * a file or such, or if you are at the end of a file.
+ */
+ void leaveAll();
+
+ /**
+ * The shortest printable form of a symbol - using "Arts::Object" as
+ * example, this would be "Arts::Object", if you are in no namespace,
+ * ::Arts::Object, if you are in a different namespace, and just Object,
+ * if you are in the Arts namespace.
+ */
+ std::string printableForm(std::string symbol);
+
+ /**
+ * Returns only the last component of the symbol (the name) cutting the
+ * namespace components
+ */
+ static std::string nameOf(std::string symbol);
+
+ /**
+ * Returns everything but the last component of the symbol, which is
+ * the namespace (e.g. namespaceOf("Arts::Object") returns Arts, and
+ * nameOf("Arts::Object") returns Object).
+ */
+ static std::string namespaceOf(std::string symbol);
+};
+
+#endif
diff --git a/mcopidl/scanner.cc b/mcopidl/scanner.cc
new file mode 100644
index 0000000..76139f7
--- /dev/null
+++ b/mcopidl/scanner.cc
@@ -0,0 +1,2090 @@
+#line 2 "scanner.cc"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator). This
+ * avoids problems with code like:
+ *
+ * if ( condition_holds )
+ * yyless( 5 );
+ * else
+ * do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ *yy_cp = yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! yy_current_buffer ) \
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+ yy_current_buffer->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define YY_USES_REJECT
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext_ptr = yy_bp; \
+ yyleng = (int) (yy_cp - yy_bp); \
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 48
+#define YY_END_OF_BUFFER 49
+static yyconst short int yy_acclist[507] =
+ { 0,
+ 5, 5, 49, 5, 47, 48, 1, 5, 47, 48,
+ 2, 48, 5, 47, 48, 5, 12, 47, 48, 5,
+ 13, 47, 48, 6, 47, 48, 5, 16, 47, 48,
+ 5, 47, 48, 5, 45, 47, 48, 5, 44, 47,
+ 48, 5, 18, 47, 48, 5, 17, 47, 48, 5,
+ 14, 47, 48, 5, 19, 47, 48, 5, 15, 47,
+ 48, 5, 42, 43, 47, 48, 5, 42, 43, 47,
+ 48, 5, 42, 43, 47, 48, 5, 42, 43, 47,
+ 48, 5, 42, 43, 47, 48, 5, 42, 43, 47,
+ 48, 5, 42, 43, 47, 48, 5, 42, 43, 47,
+
+ 48, 5, 42, 43, 47, 48, 5, 42, 43, 47,
+ 48, 5, 42, 43, 47, 48, 5, 42, 43, 47,
+ 48, 5, 42, 43, 47, 48, 5, 10, 47, 48,
+ 5, 11, 47, 48, 5, 5, 5, 4, 3, 5,
+ 7, 5, 45, 5, 46, 5, 44, 5, 5, 42,
+ 43, 5, 5, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 42, 43, 5, 42, 43, 5, 42, 43,
+ 5, 42, 43, 5, 42, 43, 5, 33, 42, 43,
+ 5, 42, 43, 5, 42, 43, 5, 42, 43, 5,
+ 42, 43, 5, 42, 43, 5, 42, 43, 5, 42,
+
+ 43, 5, 42, 43, 5, 42, 43, 5, 42, 43,
+ 5, 5, 5, 7, 7, 5, 46, 5, 43, 5,
+ 5, 42, 43, 5, 42, 43, 5, 42, 43, 5,
+ 42, 43, 5, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 42, 43, 5, 42, 43, 5, 42, 43,
+ 5, 42, 43, 5, 42, 43, 5, 42, 43, 5,
+ 42, 43, 5, 34, 42, 43, 5, 42, 43, 5,
+ 42, 43, 5, 42, 43, 5, 42, 43, 5, 5,
+ 5, 43, 5, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 42, 43, 5, 21, 42, 43, 5, 42,
+
+ 43, 5, 29, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 22, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 42, 43, 5, 42, 43, 5, 42, 43,
+ 5, 42, 43, 5, 42, 43, 5, 42, 43, 5,
+ 42, 43, 5, 20, 42, 43, 5, 5, 5, 39,
+ 42, 43, 5, 42, 43, 5, 35, 42, 43, 5,
+ 42, 43, 5, 42, 43, 5, 36, 42, 43, 5,
+ 42, 43, 5, 42, 43, 5, 38, 42, 43, 5,
+ 42, 43, 5, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 42, 43, 5, 42, 43, 5, 42, 43,
+
+ 5, 5, 5, 42, 43, 5, 42, 43, 5, 42,
+ 43, 5, 42, 43, 5, 28, 42, 43, 5, 25,
+ 42, 43, 5, 40, 42, 43, 5, 42, 43, 5,
+ 42, 43, 5, 37, 42, 43, 5, 24, 42, 43,
+ 5, 26, 42, 43, 5, 5, 5, 42, 43, 5,
+ 23, 42, 43, 5, 41, 42, 43, 5, 42, 43,
+ 5, 42, 43, 5, 42, 43, 5, 5, 5, 42,
+ 43, 5, 42, 43, 5, 32, 42, 43, 5, 31,
+ 42, 43, 5, 5, 5, 30, 42, 43, 5, 27,
+ 42, 43, 5, 5, 5, 9, 5, 5, 9, 9,
+
+ 5, 5, 8, 5, 8, 8
+ } ;
+
+static yyconst short int yy_accept[177] =
+ { 0,
+ 1, 2, 3, 4, 7, 11, 13, 16, 20, 24,
+ 27, 31, 34, 38, 42, 46, 50, 54, 58, 62,
+ 67, 72, 77, 82, 87, 92, 97, 102, 107, 112,
+ 117, 122, 127, 131, 135, 136, 137, 138, 139, 140,
+ 142, 144, 146, 148, 149, 152, 153, 156, 159, 162,
+ 165, 168, 171, 174, 177, 181, 184, 187, 190, 193,
+ 196, 199, 202, 205, 208, 211, 212, 213, 215, 216,
+ 218, 220, 221, 224, 227, 230, 233, 236, 239, 242,
+ 245, 248, 251, 254, 257, 260, 263, 267, 270, 273,
+ 276, 279, 280, 281, 283, 286, 289, 292, 295, 299,
+
+ 302, 306, 309, 312, 316, 319, 322, 325, 328, 331,
+ 334, 337, 340, 343, 347, 348, 349, 353, 356, 360,
+ 363, 366, 370, 373, 376, 380, 383, 386, 389, 392,
+ 395, 398, 401, 402, 403, 406, 409, 412, 415, 419,
+ 423, 427, 430, 433, 437, 441, 445, 446, 447, 450,
+ 454, 458, 461, 464, 467, 468, 469, 472, 475, 479,
+ 483, 484, 485, 489, 493, 494, 495, 497, 498, 500,
+ 501, 502, 504, 506, 507, 507
+ } ;
+
+static yyconst int yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 1, 4, 1, 1, 1, 1, 5,
+ 6, 7, 1, 8, 1, 1, 9, 10, 11, 11,
+ 11, 11, 11, 11, 11, 12, 12, 13, 14, 15,
+ 16, 17, 1, 1, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 20, 19, 19,
+ 1, 1, 1, 1, 19, 1, 21, 22, 23, 24,
+
+ 25, 26, 27, 19, 28, 29, 19, 30, 31, 32,
+ 33, 19, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 19, 43, 1, 44, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst int yy_meta[45] =
+ { 0,
+ 1, 1, 2, 1, 1, 1, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1
+ } ;
+
+static yyconst short int yy_base[185] =
+ { 0,
+ 0, 0, 302, 0, 0, 669, 20, 0, 0, 289,
+ 0, 39, 39, 41, 279, 0, 0, 0, 0, 80,
+ 124, 24, 33, 36, 62, 69, 75, 81, 112, 39,
+ 66, 109, 0, 0, 0, 259, 222, 669, 669, 239,
+ 44, 159, 110, 185, 115, 232, 121, 118, 206, 198,
+ 128, 211, 136, 217, 202, 220, 227, 230, 233, 236,
+ 239, 257, 245, 249, 252, 217, 212, 225, 0, 0,
+ 295, 339, 281, 285, 278, 294, 321, 313, 329, 340,
+ 337, 299, 291, 332, 354, 348, 357, 363, 360, 377,
+ 380, 164, 153, 166, 383, 394, 374, 398, 388, 391,
+
+ 401, 404, 408, 411, 420, 423, 429, 432, 438, 447,
+ 441, 450, 457, 453, 146, 139, 460, 470, 463, 481,
+ 473, 476, 489, 495, 485, 492, 498, 505, 512, 515,
+ 518, 521, 152, 115, 524, 531, 528, 549, 535, 538,
+ 541, 552, 557, 560, 563, 566, 106, 103, 569, 572,
+ 575, 591, 579, 594, 93, 104, 597, 600, 603, 606,
+ 92, 85, 609, 612, 85, 71, 83, 63, 76, 0,
+ 54, 71, 60, 0, 669, 64, 62, 650, 653, 46,
+ 656, 659, 662, 665
+ } ;
+
+static yyconst short int yy_def[185] =
+ { 0,
+ 175, 1, 175, 176, 176, 175, 176, 176, 176, 175,
+ 176, 176, 176, 176, 176, 176, 176, 176, 176, 177,
+ 177, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 176, 176, 176, 176, 176, 175, 175, 178,
+ 176, 176, 176, 175, 21, 176, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 176, 176, 178, 179, 42,
+ 180, 180, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 176, 176, 72, 21, 21, 21, 21, 21, 21,
+
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 176, 176, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 176, 176, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 176, 176, 21, 21,
+ 21, 21, 21, 21, 176, 176, 21, 21, 21, 21,
+ 176, 176, 21, 21, 176, 176, 181, 176, 181, 182,
+ 176, 183, 183, 184, 0, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175
+ } ;
+
+static yyconst short int yy_nxt[714] =
+ { 0,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 14, 15, 16, 17, 18, 19, 20, 20, 20,
+ 21, 22, 20, 23, 24, 25, 20, 26, 20, 27,
+ 28, 20, 29, 20, 30, 31, 20, 20, 32, 20,
+ 20, 20, 33, 34, 36, 39, 94, 40, 41, 41,
+ 43, 43, 43, 41, 41, 37, 50, 52, 42, 45,
+ 45, 45, 45, 62, 35, 51, 174, 53, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 174, 172, 42,
+ 35, 35, 170, 35, 35, 35, 171, 35, 35, 170,
+ 63, 54, 46, 35, 35, 35, 35, 45, 45, 45,
+
+ 55, 45, 64, 45, 45, 45, 45, 56, 168, 167,
+ 45, 45, 45, 57, 166, 165, 45, 45, 58, 43,
+ 43, 43, 35, 35, 35, 35, 162, 35, 35, 35,
+ 161, 35, 35, 59, 156, 155, 46, 35, 35, 35,
+ 35, 65, 148, 60, 45, 45, 45, 45, 45, 61,
+ 45, 45, 45, 45, 74, 45, 45, 45, 45, 47,
+ 48, 49, 73, 45, 77, 45, 35, 35, 70, 70,
+ 70, 45, 45, 79, 147, 134, 70, 133, 46, 70,
+ 70, 70, 70, 70, 70, 35, 35, 116, 35, 35,
+ 35, 115, 35, 35, 35, 35, 35, 35, 35, 35,
+
+ 35, 35, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 35, 35, 75,
+ 76, 69, 93, 45, 45, 45, 78, 45, 81, 45,
+ 92, 45, 45, 45, 72, 69, 45, 45, 45, 80,
+ 83, 82, 45, 45, 45, 45, 45, 45, 67, 84,
+ 86, 85, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 87, 45, 88, 89, 91,
+ 45, 45, 45, 90, 45, 45, 45, 45, 45, 45,
+ 66, 44, 45, 45, 45, 35, 35, 38, 35, 35,
+
+ 35, 175, 35, 35, 175, 97, 175, 46, 35, 35,
+ 35, 35, 95, 45, 45, 45, 45, 45, 45, 96,
+ 45, 45, 45, 98, 175, 104, 45, 45, 105, 45,
+ 45, 45, 175, 100, 45, 45, 45, 35, 35, 35,
+ 35, 175, 35, 35, 35, 99, 35, 35, 45, 45,
+ 45, 35, 35, 35, 35, 35, 45, 45, 45, 101,
+ 102, 103, 175, 175, 45, 45, 45, 45, 106, 45,
+ 175, 175, 45, 45, 45, 45, 45, 45, 107, 175,
+ 175, 35, 35, 45, 45, 45, 109, 108, 175, 45,
+ 45, 45, 45, 45, 45, 45, 45, 110, 45, 45,
+
+ 45, 111, 175, 114, 112, 117, 119, 175, 175, 45,
+ 45, 45, 45, 45, 113, 45, 45, 45, 45, 45,
+ 45, 118, 120, 45, 45, 45, 45, 45, 121, 45,
+ 45, 45, 175, 45, 45, 45, 45, 45, 45, 45,
+ 122, 45, 123, 45, 45, 45, 45, 45, 45, 124,
+ 125, 126, 127, 175, 175, 45, 45, 45, 45, 45,
+ 45, 130, 175, 175, 45, 45, 45, 45, 45, 45,
+ 128, 129, 175, 45, 45, 45, 45, 45, 45, 132,
+ 175, 131, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 135, 45, 45, 45, 45, 45, 45, 45, 45,
+
+ 45, 136, 137, 175, 175, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 138, 175, 45, 45, 45, 139,
+ 45, 45, 45, 175, 45, 45, 45, 45, 140, 45,
+ 45, 45, 45, 45, 45, 45, 142, 175, 175, 141,
+ 45, 45, 45, 143, 145, 144, 175, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 146, 45, 45,
+ 45, 149, 150, 45, 151, 45, 45, 45, 45, 152,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 154,
+ 175, 153, 175, 175, 45, 45, 45, 45, 45, 45,
+ 175, 175, 45, 45, 45, 45, 45, 45, 45, 45,
+
+ 45, 45, 45, 45, 45, 157, 45, 45, 45, 45,
+ 45, 45, 45, 158, 45, 45, 45, 175, 160, 175,
+ 159, 163, 175, 175, 164, 175, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 68, 175, 68, 69, 175, 69, 169, 175, 169, 170,
+ 175, 170, 173, 175, 173, 174, 175, 174, 3, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175
+ } ;
+
+static yyconst short int yy_chk[714] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 7, 12, 180, 12, 13, 13,
+ 14, 14, 14, 41, 41, 7, 22, 23, 13, 22,
+ 22, 22, 177, 30, 176, 22, 173, 24, 23, 23,
+ 23, 24, 24, 24, 30, 30, 30, 172, 171, 13,
+ 20, 20, 169, 20, 20, 20, 168, 20, 20, 167,
+ 31, 25, 20, 20, 20, 20, 20, 25, 25, 25,
+
+ 26, 31, 31, 31, 26, 26, 26, 27, 166, 165,
+ 27, 27, 27, 28, 162, 161, 28, 28, 28, 43,
+ 43, 43, 20, 20, 21, 21, 156, 21, 21, 21,
+ 155, 21, 21, 29, 148, 147, 21, 21, 21, 21,
+ 21, 32, 134, 29, 32, 32, 32, 29, 29, 29,
+ 45, 45, 45, 48, 48, 48, 47, 47, 47, 21,
+ 21, 21, 47, 51, 51, 51, 21, 21, 42, 42,
+ 42, 53, 53, 53, 133, 116, 42, 115, 94, 42,
+ 42, 42, 42, 42, 42, 44, 44, 93, 44, 44,
+ 44, 92, 44, 44, 44, 44, 44, 44, 44, 44,
+
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 49,
+ 50, 68, 67, 50, 50, 50, 52, 55, 55, 55,
+ 66, 49, 49, 49, 46, 40, 52, 52, 52, 54,
+ 57, 56, 54, 54, 54, 56, 56, 56, 37, 58,
+ 60, 59, 57, 57, 57, 58, 58, 58, 59, 59,
+ 59, 60, 60, 60, 61, 61, 61, 62, 63, 65,
+ 63, 63, 63, 64, 64, 64, 64, 65, 65, 65,
+ 36, 15, 62, 62, 62, 71, 71, 10, 71, 71,
+
+ 71, 3, 71, 71, 0, 75, 0, 71, 71, 71,
+ 71, 71, 73, 75, 75, 75, 73, 73, 73, 74,
+ 74, 74, 74, 76, 0, 82, 83, 83, 83, 76,
+ 76, 76, 0, 78, 82, 82, 82, 71, 71, 72,
+ 72, 0, 72, 72, 72, 77, 72, 72, 78, 78,
+ 78, 72, 72, 72, 72, 72, 77, 77, 77, 79,
+ 80, 81, 0, 0, 79, 79, 79, 84, 84, 84,
+ 0, 0, 81, 81, 81, 80, 80, 80, 85, 0,
+ 0, 72, 72, 86, 86, 86, 88, 86, 0, 85,
+ 85, 85, 87, 87, 87, 89, 89, 89, 88, 88,
+
+ 88, 90, 0, 91, 90, 95, 97, 0, 0, 97,
+ 97, 97, 90, 90, 90, 91, 91, 91, 95, 95,
+ 95, 96, 98, 99, 99, 99, 100, 100, 100, 96,
+ 96, 96, 0, 98, 98, 98, 101, 101, 101, 102,
+ 102, 102, 103, 103, 103, 103, 104, 104, 104, 105,
+ 106, 107, 108, 0, 0, 105, 105, 105, 106, 106,
+ 106, 111, 0, 0, 107, 107, 107, 108, 108, 108,
+ 109, 110, 0, 109, 109, 109, 111, 111, 111, 113,
+ 0, 112, 110, 110, 110, 112, 112, 112, 114, 114,
+ 114, 118, 113, 113, 113, 117, 117, 117, 119, 119,
+
+ 119, 120, 121, 0, 0, 118, 118, 118, 121, 121,
+ 121, 122, 122, 122, 123, 0, 120, 120, 120, 124,
+ 125, 125, 125, 0, 123, 123, 123, 126, 126, 126,
+ 124, 124, 124, 127, 127, 127, 128, 0, 0, 127,
+ 128, 128, 128, 129, 131, 130, 0, 129, 129, 129,
+ 130, 130, 130, 131, 131, 131, 132, 132, 132, 135,
+ 135, 135, 136, 137, 137, 137, 136, 136, 136, 138,
+ 139, 139, 139, 140, 140, 140, 141, 141, 141, 143,
+ 0, 142, 0, 0, 138, 138, 138, 142, 142, 142,
+ 0, 0, 143, 143, 143, 144, 144, 144, 145, 145,
+
+ 145, 146, 146, 146, 149, 149, 149, 150, 150, 150,
+ 151, 151, 151, 152, 153, 153, 153, 0, 154, 0,
+ 153, 157, 0, 0, 158, 0, 152, 152, 152, 154,
+ 154, 154, 157, 157, 157, 158, 158, 158, 159, 159,
+ 159, 160, 160, 160, 163, 163, 163, 164, 164, 164,
+ 178, 0, 178, 179, 0, 179, 181, 0, 181, 182,
+ 0, 182, 183, 0, 183, 184, 0, 184, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+
+ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
+ 175, 175, 175
+ } ;
+
+static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
+static char *yy_full_match;
+static int yy_lp;
+#define REJECT \
+{ \
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yy_full_match; /* restore poss. backed-over text */ \
+++yy_lp; \
+goto find_rule; \
+}
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "scanner.ll"
+#define INITIAL 0
+/*
+Copyright (C) 1999 Stefan Westerfeld
+stefan@space.twc.de
+Copyright (C) 1999 Torben Weis <weis@kde.org>
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+This program 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 General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#line 25 "scanner.ll"
+
+/*
+ This is the lex file for mcopidl. It is based on the dcopidl (kidl)
+ lex file, which was written by Torben Weis.
+*/
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "common.h"
+
+using namespace std;
+using namespace Arts;
+
+#ifndef KDE_USE_FINAL
+#include "yacc.cc.h"
+#endif
+
+extern int idl_line_no;
+int comment_mode;
+
+static long ascii_to_longlong( long base, const char *s )
+{
+ long ll = 0;
+ while( *s != '\0' ) {
+ char c = *s++;
+ if( c >= 'a' )
+ c -= 'a' - 'A';
+ c -= '0';
+ if( c > 9 )
+ c -= 'A' - '0' - 10;
+ ll = ll * base + c;
+ }
+ return ll;
+}
+
+extern void startInclude(const char *line);
+extern void endInclude();
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+#line 710 "scanner.cc"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines. This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( yy_current_buffer->yy_is_interactive ) \
+ { \
+ int c = '*', n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+ && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 100 "scanner.ll"
+
+
+#line 864 "scanner.cc"
+
+ if ( yy_init )
+ {
+ yy_init = 0;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! yy_current_buffer )
+ yy_current_buffer =
+ yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yy_start;
+ yy_state_ptr = yy_state_buf;
+ *yy_state_ptr++ = yy_current_state;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 176 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yy_state_ptr++ = yy_current_state;
+ ++yy_cp;
+ }
+ while ( yy_current_state != 175 );
+
+yy_find_action:
+ yy_current_state = *--yy_state_ptr;
+ yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+ for ( ; ; ) /* until we find what rule we matched */
+ {
+ if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
+ {
+ yy_act = yy_acclist[yy_lp];
+ {
+ yy_full_match = yy_cp;
+ break;
+ }
+ }
+ --yy_cp;
+ yy_current_state = *--yy_state_ptr;
+ yy_lp = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+
+do_action: /* This label is used only to access EOF actions. */
+
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 102 "scanner.ll"
+;
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 103 "scanner.ll"
+{ idl_line_no++; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 105 "scanner.ll"
+{ comment_mode = 1; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 106 "scanner.ll"
+{ if (!comment_mode) { REJECT; } else { comment_mode = 0; } }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 107 "scanner.ll"
+{ if (!comment_mode) { REJECT; } }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 108 "scanner.ll"
+{ if (!comment_mode) { REJECT; } }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 110 "scanner.ll"
+;
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 112 "scanner.ll"
+{ startInclude(yytext); }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 113 "scanner.ll"
+{ endInclude(); }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 116 "scanner.ll"
+return T_LEFT_CURLY_BRACKET;
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 117 "scanner.ll"
+return T_RIGHT_CURLY_BRACKET;
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 118 "scanner.ll"
+return T_LEFT_PARANTHESIS;
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 119 "scanner.ll"
+return T_RIGHT_PARANTHESIS;
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 120 "scanner.ll"
+return T_LESS;
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 121 "scanner.ll"
+return T_GREATER;
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 122 "scanner.ll"
+return T_COMMA;
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 123 "scanner.ll"
+return T_SEMICOLON;
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 124 "scanner.ll"
+return T_COLON;
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 125 "scanner.ll"
+return T_EQUAL;
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 127 "scanner.ll"
+return T_VOID;
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 128 "scanner.ll"
+return T_BYTE;
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 129 "scanner.ll"
+return T_LONG;
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 130 "scanner.ll"
+return T_BOOLEAN;
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 131 "scanner.ll"
+return T_STRING;
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 132 "scanner.ll"
+return T_OBJECT;
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 133 "scanner.ll"
+return T_STRUCT;
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 134 "scanner.ll"
+return T_INTERFACE;
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 135 "scanner.ll"
+return T_MODULE;
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 136 "scanner.ll"
+return T_ENUM;
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 137 "scanner.ll"
+return T_ATTRIBUTE;
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 138 "scanner.ll"
+return T_SEQUENCE;
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 139 "scanner.ll"
+return T_READONLY;
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 140 "scanner.ll"
+return T_IN;
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 141 "scanner.ll"
+return T_OUT;
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 142 "scanner.ll"
+return T_AUDIO;
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 143 "scanner.ll"
+return T_FLOAT;
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 144 "scanner.ll"
+return T_STREAM;
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 145 "scanner.ll"
+return T_MULTI;
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 146 "scanner.ll"
+return T_ASYNC;
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 147 "scanner.ll"
+return T_ONEWAY;
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 148 "scanner.ll"
+return T_DEFAULT;
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 150 "scanner.ll"
+{
+ yylval._str = strdup(yytext); // TAKE CARE: free that thing
+ return T_IDENTIFIER;
+ }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 155 "scanner.ll"
+{
+ yylval._str = strdup(yytext); // TAKE CARE: free that thing
+ return T_QUALIFIED_IDENTIFIER;
+ }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 160 "scanner.ll"
+{
+ yylval._int = ascii_to_longlong( 10, yytext );
+ return T_INTEGER_LITERAL;
+ }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 164 "scanner.ll"
+{
+ yylval._int = ascii_to_longlong( 8, yytext );
+ return T_INTEGER_LITERAL;
+ }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 168 "scanner.ll"
+{
+ yylval._int = ascii_to_longlong( 16, yytext + 2 );
+ return T_INTEGER_LITERAL;
+ }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 173 "scanner.ll"
+{
+ return T_UNKNOWN;
+ }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 177 "scanner.ll"
+ECHO;
+ YY_BREAK
+#line 1205 "scanner.cc"
+ case YY_STATE_EOF(INITIAL):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between yy_current_buffer and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yy_current_buffer->yy_input_file = yyin;
+ yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p =
+ yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+ } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+ {
+ register char *dest = yy_current_buffer->yy_ch_buf;
+ register char *source = yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( yy_current_buffer->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = yy_current_buffer;
+
+ int yy_c_buf_p_offset =
+ (int) (yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yy_flex_realloc( (void *) b->yy_ch_buf,
+ b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = yy_current_buffer->yy_buf_size -
+ number_to_move - 1;
+#endif
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart( yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+ return ret_val;
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+ {
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = yy_start;
+ yy_state_ptr = yy_state_buf;
+ *yy_state_ptr++ = yy_current_state;
+
+ for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 176 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yy_state_ptr++ = yy_current_state;
+ }
+
+ return yy_current_state;
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+ {
+ register int yy_is_jam;
+
+ register YY_CHAR yy_c = 1;
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 176 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 175);
+ if ( ! yy_is_jam )
+ *yy_state_ptr++ = yy_current_state;
+
+ return yy_is_jam ? 0 : yy_current_state;
+ }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+ {
+ register char *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yy_n_chars + 2;
+ register char *dest = &yy_current_buffer->yy_ch_buf[
+ yy_current_buffer->yy_buf_size + 2];
+ register char *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ yy_current_buffer->yy_n_chars =
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+
+ yytext_ptr = yy_bp;
+ yy_hold_char = *yy_cp;
+ yy_c_buf_p = yy_cp;
+ }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+ {
+ int c;
+
+ *yy_c_buf_p = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* This was really a NUL. */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yy_c_buf_p - yytext_ptr;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart( yyin );
+
+ /* fall through */
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ return EOF;
+
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
+ *yy_c_buf_p = '\0'; /* preserve yytext */
+ yy_hold_char = *++yy_c_buf_p;
+
+
+ return c;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+ {
+ if ( ! yy_current_buffer )
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* Flush out information for old buffer. */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer( b, file );
+
+ return b;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+ {
+ if ( ! b )
+ return;
+
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yy_flex_free( (void *) b->yy_ch_buf );
+
+ yy_flex_free( (void *) b );
+ }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+ {
+ yy_flush_buffer( b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+ b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+ b->yy_is_interactive = 0;
+#else
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == yy_current_buffer )
+ yy_load_buffer_state();
+ }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+ {
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer( b );
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+ {
+ int len;
+ for ( len = 0; yy_str[len]; ++len )
+ ;
+
+ return yy_scan_bytes( yy_str, len );
+ }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+ {
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = len + 2;
+ buf = (char *) yy_flex_alloc( n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < len; ++i )
+ buf[i] = bytes[i];
+
+ buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer( buf, n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+ }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+ {
+ if ( yy_start_stack_ptr >= yy_start_stack_depth )
+ {
+ yy_size_t new_size;
+
+ yy_start_stack_depth += YY_START_STACK_INCR;
+ new_size = yy_start_stack_depth * sizeof( int );
+
+ if ( ! yy_start_stack )
+ yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+ else
+ yy_start_stack = (int *) yy_flex_realloc(
+ (void *) yy_start_stack, new_size );
+
+ if ( ! yy_start_stack )
+ YY_FATAL_ERROR(
+ "out of memory expanding start-condition stack" );
+ }
+
+ yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+ BEGIN(new_state);
+ }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+ {
+ if ( --yy_start_stack_ptr < 0 )
+ YY_FATAL_ERROR( "start-condition stack underflow" );
+
+ BEGIN(yy_start_stack[yy_start_stack_ptr]);
+ }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+ {
+ return yy_start_stack[yy_start_stack_ptr - 1];
+ }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+ {
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+ }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ yytext[yyleng] = yy_hold_char; \
+ yy_c_buf_p = yytext + n; \
+ yy_hold_char = *yy_c_buf_p; \
+ *yy_c_buf_p = '\0'; \
+ yyleng = n; \
+ } \
+ while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+ {
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+ }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+ {
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+ }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+ {
+ return (void *) malloc( size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+ {
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+ }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+ {
+ free( ptr );
+ }
+
+#if YY_MAIN
+int main()
+ {
+ yylex();
+ return 0;
+ }
+#endif
+#line 177 "scanner.ll"
+
+
+void mcopidlInitFlex( const char *_code )
+{
+ comment_mode = 0;
+ yy_switch_to_buffer( yy_scan_string( _code ) );
+}
diff --git a/mcopidl/scanner.ll b/mcopidl/scanner.ll
new file mode 100644
index 0000000..10896d2
--- /dev/null
+++ b/mcopidl/scanner.ll
@@ -0,0 +1,183 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ Copyright (C) 1999 Torben Weis <weis@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+%{
+
+/*
+ This is the lex file for mcopidl. It is based on the dcopidl (kidl)
+ lex file, which was written by Torben Weis.
+*/
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "common.h"
+
+using namespace std;
+using namespace Arts;
+
+#ifndef KDE_USE_FINAL
+#include "yacc.cc.h"
+#endif
+
+extern int idl_line_no;
+int comment_mode;
+
+static long ascii_to_longlong( long base, const char *s )
+{
+ long ll = 0;
+ while( *s != '\0' ) {
+ char c = *s++;
+ if( c >= 'a' )
+ c -= 'a' - 'A';
+ c -= '0';
+ if( c > 9 )
+ c -= 'A' - '0' - 10;
+ ll = ll * base + c;
+ }
+ return ll;
+}
+
+extern void startInclude(const char *line);
+extern void endInclude();
+
+%}
+
+%option noyywrap
+
+/*--------------------------------------------------------------------------*/
+
+Digits [0-9]+
+Oct_Digit [0-7]
+Hex_Digit [a-fA-F0-9]
+Int_Literal [1-9][0-9]*
+Oct_Literal 0{Oct_Digit}*
+Hex_Literal (0x|0X){Hex_Digit}*
+Esc_Sequence1 "\\"[ntvbrfa\\\?\'\"]
+Esc_Sequence2 "\\"{Oct_Digit}{1,3}
+Esc_Sequence3 "\\"(x|X){Hex_Digit}{1,2}
+Esc_Sequence ({Esc_Sequence1}|{Esc_Sequence2}|{Esc_Sequence3})
+Char ([^\n\t\"\'\\]|{Esc_Sequence})
+Char_Literal "'"({Char}|\")"'"
+String_Literal \"({Char}|"'")*\"
+Float_Literal1 {Digits}"."{Digits}(e|E)("+"|"-")?{Digits}
+Float_Literal2 {Digits}(e|E)("+"|"-")?{Digits}
+Float_Literal3 {Digits}"."{Digits}
+Float_Literal4 "."{Digits}
+Float_Literal5 "."{Digits}(e|E)("+"|"-")?{Digits}
+
+/*--------------------------------------------------------------------------*/
+
+Kidl_Identifier [_a-zA-Z][a-zA-Z0-9_]*
+
+Qualified_Identifier ("::")?[_a-zA-Z](("::")?[a-zA-Z0-9_])*
+
+/*--------------------------------------------------------------------------*/
+
+%%
+
+[ \t] ;
+[\n] { idl_line_no++; }
+
+"/\*" { comment_mode = 1; }
+"\*/" { if (!comment_mode) { REJECT; } else { comment_mode = 0; } }
+[^\n*]* { if (!comment_mode) { REJECT; } }
+"*" { if (!comment_mode) { REJECT; } }
+
+"//"[^\n]* ;
+
+"#startinclude"[^\n]* { startInclude(yytext); }
+"#endinclude"[^\n]* { endInclude(); }
+
+
+"{" return T_LEFT_CURLY_BRACKET;
+"}" return T_RIGHT_CURLY_BRACKET;
+"(" return T_LEFT_PARANTHESIS;
+")" return T_RIGHT_PARANTHESIS;
+"<" return T_LESS;
+">" return T_GREATER;
+"," return T_COMMA;
+";" return T_SEMICOLON;
+":" return T_COLON;
+"=" return T_EQUAL;
+
+void return T_VOID;
+byte return T_BYTE;
+long return T_LONG;
+boolean return T_BOOLEAN;
+string return T_STRING;
+object return T_OBJECT;
+struct return T_STRUCT;
+interface return T_INTERFACE;
+module return T_MODULE;
+"enum" return T_ENUM;
+attribute return T_ATTRIBUTE;
+sequence return T_SEQUENCE;
+readonly return T_READONLY;
+in return T_IN;
+out return T_OUT;
+audio return T_AUDIO;
+float return T_FLOAT;
+stream return T_STREAM;
+multi return T_MULTI;
+async return T_ASYNC;
+oneway return T_ONEWAY;
+default return T_DEFAULT;
+
+{Kidl_Identifier} {
+ yylval._str = strdup(yytext); // TAKE CARE: free that thing
+ return T_IDENTIFIER;
+ }
+
+{Qualified_Identifier} {
+ yylval._str = strdup(yytext); // TAKE CARE: free that thing
+ return T_QUALIFIED_IDENTIFIER;
+ }
+
+{Int_Literal} {
+ yylval._int = ascii_to_longlong( 10, yytext );
+ return T_INTEGER_LITERAL;
+ }
+{Oct_Literal} {
+ yylval._int = ascii_to_longlong( 8, yytext );
+ return T_INTEGER_LITERAL;
+ }
+{Hex_Literal} {
+ yylval._int = ascii_to_longlong( 16, yytext + 2 );
+ return T_INTEGER_LITERAL;
+ }
+
+. {
+ return T_UNKNOWN;
+ }
+
+%%
+
+void mcopidlInitFlex( const char *_code )
+{
+ comment_mode = 0;
+ yy_switch_to_buffer( yy_scan_string( _code ) );
+}
diff --git a/mcopidl/yacc.cc b/mcopidl/yacc.cc
new file mode 100644
index 0000000..2d6fac7
--- /dev/null
+++ b/mcopidl/yacc.cc
@@ -0,0 +1,1507 @@
+
+/* A Bison parser, made from yacc.yy
+ by GNU Bison version 1.28 */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define T_STRUCT 257
+#define T_ENUM 258
+#define T_INTERFACE 259
+#define T_MODULE 260
+#define T_VOID 261
+#define T_LEFT_CURLY_BRACKET 262
+#define T_RIGHT_CURLY_BRACKET 263
+#define T_LEFT_PARANTHESIS 264
+#define T_RIGHT_PARANTHESIS 265
+#define T_LESS 266
+#define T_GREATER 267
+#define T_EQUAL 268
+#define T_SEMICOLON 269
+#define T_COLON 270
+#define T_COMMA 271
+#define T_IDENTIFIER 272
+#define T_QUALIFIED_IDENTIFIER 273
+#define T_INTEGER_LITERAL 274
+#define T_UNKNOWN 275
+#define T_BOOLEAN 276
+#define T_STRING 277
+#define T_LONG 278
+#define T_BYTE 279
+#define T_OBJECT 280
+#define T_SEQUENCE 281
+#define T_AUDIO 282
+#define T_FLOAT 283
+#define T_IN 284
+#define T_OUT 285
+#define T_STREAM 286
+#define T_MULTI 287
+#define T_ATTRIBUTE 288
+#define T_READONLY 289
+#define T_ASYNC 290
+#define T_ONEWAY 291
+#define T_DEFAULT 292
+
+#line 22 "yacc.yy"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include "common.h"
+#include "namespace.h"
+
+using namespace std;
+using namespace Arts;
+
+extern int idl_line_no;
+extern string idl_filename;
+
+extern int yylex();
+extern void mcopidlInitFlex( const char *_code );
+extern void addEnumTodo( const EnumDef& edef );
+extern void addStructTodo( const TypeDef& type );
+extern void addInterfaceTodo( const InterfaceDef& iface );
+
+void yyerror( const char *s )
+{
+ printf( "%s:%i: %s\n", idl_filename.c_str(), idl_line_no, s );
+ exit(1);
+ // theParser->parse_error( idl_lexFile, s, idl_line_no );
+}
+
+static struct ParserGlobals {
+ vector<string> noHints;
+} *g;
+
+
+#line 55 "yacc.yy"
+typedef union
+{
+ // generic data types
+ long _int;
+ char* _str;
+ unsigned short _char;
+ double _float;
+
+ vector<char*> *_strs;
+
+ // types
+ vector<TypeComponent> *_typeComponentSeq;
+ TypeComponent* _typeComponent;
+
+ // enums
+ vector<EnumComponent> *_enumComponentSeq;
+
+ // interfaces
+ InterfaceDef *_interfaceDef;
+
+ ParamDef* _paramDef;
+ vector<ParamDef> *_paramDefSeq;
+
+ MethodDef* _methodDef;
+ vector<MethodDef> *_methodDefSeq;
+
+ AttributeDef* _attributeDef;
+ vector<AttributeDef> *_attributeDefSeq;
+} YYSTYPE;
+#ifndef YYDEBUG
+#define YYDEBUG 1
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 133
+#define YYFLAG -32768
+#define YYNTBASE 39
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 292 ? yytranslate[x] : 75)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 4, 7, 9, 11, 13, 15, 16, 21,
+ 22, 30, 31, 39, 41, 43, 45, 49, 53, 59,
+ 60, 65, 66, 75, 77, 80, 81, 82, 91, 93,
+ 96, 99, 102, 104, 110, 112, 114, 116, 118, 120,
+ 122, 129, 133, 135, 138, 140, 143, 146, 150, 153,
+ 157, 165, 167, 170, 172, 176, 179, 181, 185, 187,
+ 191, 193, 195, 197, 202, 204, 209, 211, 213, 215,
+ 217, 219, 221, 223, 225, 227, 229
+};
+
+static const short yyrhs[] = { 40,
+ 0, 74, 0, 41, 40, 0, 42, 0, 49, 0,
+ 53, 0, 45, 0, 0, 3, 18, 43, 15, 0,
+ 0, 3, 18, 44, 8, 71, 9, 15, 0, 0,
+ 4, 47, 46, 8, 48, 9, 15, 0, 18, 0,
+ 74, 0, 18, 0, 18, 14, 20, 0, 48, 17,
+ 18, 0, 48, 17, 18, 14, 20, 0, 0, 5,
+ 18, 50, 15, 0, 0, 5, 18, 51, 52, 8,
+ 56, 9, 15, 0, 74, 0, 16, 69, 0, 0,
+ 0, 6, 18, 54, 8, 40, 9, 55, 15, 0,
+ 74, 0, 64, 56, 0, 57, 56, 0, 62, 56,
+ 0, 61, 0, 58, 34, 72, 68, 15, 0, 74,
+ 0, 35, 0, 74, 0, 37, 0, 74, 0, 38,
+ 0, 60, 63, 72, 32, 68, 15, 0, 38, 68,
+ 15, 0, 30, 0, 30, 33, 0, 31, 0, 31,
+ 33, 0, 36, 30, 0, 36, 30, 33, 0, 36,
+ 31, 0, 36, 31, 33, 0, 59, 72, 18, 10,
+ 65, 11, 15, 0, 74, 0, 67, 66, 0, 74,
+ 0, 66, 17, 67, 0, 72, 18, 0, 18, 0,
+ 68, 17, 18, 0, 70, 0, 69, 17, 70, 0,
+ 18, 0, 19, 0, 74, 0, 72, 68, 15, 71,
+ 0, 73, 0, 27, 12, 73, 13, 0, 22, 0,
+ 23, 0, 24, 0, 25, 0, 26, 0, 28, 0,
+ 29, 0, 7, 0, 18, 0, 19, 0, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 124, 126, 126, 128, 128, 128, 128, 130, 132, 132,
+ 134, 145, 148, 160, 160, 162, 169, 175, 183, 190,
+ 192, 192, 193, 214, 216, 218, 221, 224, 226, 230,
+ 236, 247, 254, 256, 270, 272, 275, 277, 280, 282,
+ 285, 298, 303, 305, 306, 307, 308, 309, 310, 311,
+ 315, 325, 330, 338, 343, 353, 368, 370, 372, 374,
+ 376, 380, 386, 390, 409, 410, 423, 425, 426, 427,
+ 428, 429, 430, 431, 432, 436, 442
+};
+#endif
+
+
+#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
+
+static const char * const yytname[] = { "$","error","$undefined.","T_STRUCT",
+"T_ENUM","T_INTERFACE","T_MODULE","T_VOID","T_LEFT_CURLY_BRACKET","T_RIGHT_CURLY_BRACKET",
+"T_LEFT_PARANTHESIS","T_RIGHT_PARANTHESIS","T_LESS","T_GREATER","T_EQUAL","T_SEMICOLON",
+"T_COLON","T_COMMA","T_IDENTIFIER","T_QUALIFIED_IDENTIFIER","T_INTEGER_LITERAL",
+"T_UNKNOWN","T_BOOLEAN","T_STRING","T_LONG","T_BYTE","T_OBJECT","T_SEQUENCE",
+"T_AUDIO","T_FLOAT","T_IN","T_OUT","T_STREAM","T_MULTI","T_ATTRIBUTE","T_READONLY",
+"T_ASYNC","T_ONEWAY","T_DEFAULT","aidlfile","definitions","definition","structdef",
+"@1","@2","enumdef","@3","enumname","enumbody","interfacedef","@4","@5","inheritedinterfaces",
+"moduledef","@6","@7","classbody","attributedef","maybereadonly","maybeoneway",
+"maybedefault","streamdef","defaultdef","direction","methoddef","paramdefs",
+"paramdefs1","paramdef","identifierlist","interfacelist","interfacelistelem",
+"structbody","type","simpletype","epsilon", NULL
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 39, 40, 40, 41, 41, 41, 41, 43, 42, 44,
+ 42, 46, 45, 47, 47, 48, 48, 48, 48, 50,
+ 49, 51, 49, 52, 52, 54, 55, 53, 56, 56,
+ 56, 56, 57, 57, 58, 58, 59, 59, 60, 60,
+ 61, 62, 63, 63, 63, 63, 63, 63, 63, 63,
+ 64, 65, 65, 66, 66, 67, 68, 68, 69, 69,
+ 70, 70, 71, 71, 72, 72, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 74
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 2, 1, 1, 1, 1, 0, 4, 0,
+ 7, 0, 7, 1, 1, 1, 3, 3, 5, 0,
+ 4, 0, 8, 1, 2, 0, 0, 8, 1, 2,
+ 2, 2, 1, 5, 1, 1, 1, 1, 1, 1,
+ 6, 3, 1, 2, 1, 2, 2, 3, 2, 3,
+ 7, 1, 2, 1, 3, 2, 1, 3, 1, 3,
+ 1, 1, 1, 4, 1, 4, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0
+};
+
+static const short yydefact[] = { 77,
+ 0, 77, 0, 0, 1, 77, 4, 7, 5, 6,
+ 2, 8, 14, 12, 15, 22, 26, 3, 0, 0,
+ 0, 0, 77, 0, 9, 77, 0, 21, 0, 0,
+ 24, 77, 74, 75, 76, 67, 68, 69, 70, 71,
+ 0, 72, 73, 0, 0, 65, 63, 16, 0, 61,
+ 62, 25, 59, 77, 0, 0, 0, 57, 0, 0,
+ 0, 0, 0, 36, 38, 40, 0, 77, 0, 0,
+ 0, 33, 77, 77, 37, 27, 0, 11, 77, 0,
+ 17, 13, 18, 60, 0, 0, 31, 0, 0, 43,
+ 45, 0, 0, 32, 30, 0, 66, 64, 58, 0,
+ 42, 23, 0, 0, 44, 46, 47, 49, 0, 28,
+ 19, 0, 77, 48, 50, 0, 34, 0, 77, 0,
+ 52, 0, 0, 53, 54, 56, 41, 51, 0, 55,
+ 0, 0, 0
+};
+
+static const short yydefgoto[] = { 131,
+ 5, 6, 7, 19, 20, 8, 21, 14, 49, 9,
+ 22, 23, 30, 10, 24, 96, 67, 68, 69, 70,
+ 71, 72, 73, 93, 74, 118, 124, 119, 59, 52,
+ 53, 44, 45, 46, 75
+};
+
+static const short yypact[] = { 44,
+ -13, 13, 16, 20,-32768, 44,-32768,-32768,-32768,-32768,
+-32768, 5,-32768,-32768,-32768, 27,-32768,-32768, 30, 10,
+ 43, 54, 56, 65,-32768, 39, 64,-32768, 3, 75,
+-32768, 44,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 72,-32768,-32768, 76, 68,-32768,-32768, 73, -5,-32768,
+-32768, 71,-32768, -10, 80, 52, 77,-32768, -8, 70,
+ 78, 79, 3,-32768,-32768, 68, 82, -10, 60, 39,
+ -16,-32768, -10, -10, -1,-32768, 83,-32768, 39, 81,
+-32768,-32768, 84,-32768, 22, 85,-32768, 39, 86, 62,
+ 69, 25, 39,-32768,-32768, 88,-32768,-32768,-32768, 87,
+-32768,-32768, 68, 91,-32768,-32768, 89, 90, 74,-32768,
+-32768, 26, 39,-32768,-32768, 68,-32768, 94,-32768, 92,
+-32768, 37, 93, 95,-32768,-32768,-32768,-32768, 39,-32768,
+ 109, 111,-32768
+};
+
+static const short yypgoto[] = {-32768,
+ 4,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768, -57,-32768,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768, -15, -63,-32768,
+ 53, 36, -69, 61, 0
+};
+
+
+#define YYLAST 123
+
+
+static const short yytable[] = { 11,
+ 89, 15, 85, 61, 12, 11, 79, -29, 80, 18,
+ 87, 62, -10, 90, 91, 94, 95, 26, 103, 92,
+ 50, 51, 31, 109, 64, 47, 65, 66, -39, -39,
+ 13, 11, -35, 16, -39, 55, 101, 17, 80, 112,
+ 117, -20, 80, 120, 25, 33, 1, 2, 3, 4,
+ 27, 127, 122, 80, 107, 108, 34, 35, 33, 120,
+ 36, 37, 38, 39, 40, 41, 42, 43, 28, 34,
+ 35, 29, 32, 36, 37, 38, 39, 40, 47, 42,
+ 43, 48, 54, 56, 57, 58, 60, 63, 76, 81,
+ 86, 78, 82, 88, 105, 97, 83, 100, 99, 102,
+ 113, 106, 110, 104, 123, 116, 111, 128, 132, 126,
+ 133, 129, 121, 130, 98, 84, 77, 0, 125, 0,
+ 0, 114, 115
+};
+
+static const short yycheck[] = { 0,
+ 70, 2, 66, 9, 18, 6, 15, 9, 17, 6,
+ 68, 17, 8, 30, 31, 73, 74, 8, 88, 36,
+ 18, 19, 23, 93, 35, 26, 37, 38, 30, 31,
+ 18, 32, 34, 18, 36, 32, 15, 18, 17, 103,
+ 15, 15, 17, 113, 15, 7, 3, 4, 5, 6,
+ 8, 15, 116, 17, 30, 31, 18, 19, 7, 129,
+ 22, 23, 24, 25, 26, 27, 28, 29, 15, 18,
+ 19, 16, 8, 22, 23, 24, 25, 26, 79, 28,
+ 29, 18, 8, 12, 9, 18, 14, 17, 9, 20,
+ 9, 15, 15, 34, 33, 13, 18, 14, 18, 15,
+ 10, 33, 15, 18, 11, 32, 20, 15, 0, 18,
+ 0, 17, 113, 129, 79, 63, 56, -1, 119, -1,
+ -1, 33, 33
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/share/misc/bison.simple"
+/* This file comes from bison-1.28. */
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+#ifndef YYSTACK_USE_ALLOCA
+#ifdef alloca
+#define YYSTACK_USE_ALLOCA
+#else /* alloca not defined */
+#ifdef __GNUC__
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
+#define YYSTACK_USE_ALLOCA
+#include <alloca.h>
+#else /* not sparc */
+/* We think this test detects Watcom and Microsoft C. */
+/* This used to test MSDOS, but that is a bad idea
+ since that symbol is in the user namespace. */
+#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
+#if 0 /* No need for malloc.h, which pollutes the namespace;
+ instead, just don't use alloca. */
+#include <malloc.h>
+#endif
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+/* I don't know what this was needed for, but it pollutes the namespace.
+ So I turned it off. rms, 2 May 1997. */
+/* #include <malloc.h> */
+ #pragma alloca
+#define YYSTACK_USE_ALLOCA
+#else /* not MSDOS, or __TURBOC__, or _AIX */
+#if 0
+#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
+ and on HPUX 10. Eventually we can turn this on. */
+#define YYSTACK_USE_ALLOCA
+#define alloca __builtin_alloca
+#endif /* __hpux */
+#endif
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc */
+#endif /* not GNU C */
+#endif /* alloca not defined */
+#endif /* YYSTACK_USE_ALLOCA not defined */
+
+#ifdef YYSTACK_USE_ALLOCA
+#define YYSTACK_ALLOC alloca
+#else
+#define YYSTACK_ALLOC malloc
+#endif
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Define __yy_memcpy. Note that the size argument
+ should be passed with type unsigned int, because that is what the non-GCC
+ definitions require. With GCC, __builtin_memcpy takes an arg
+ of type size_t, but it can handle unsigned int. */
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (to, from, count)
+ char *to;
+ char *from;
+ unsigned int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *to, char *from, unsigned int count)
+{
+ register char *t = to;
+ register char *f = from;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 217 "/usr/share/misc/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#ifdef __cplusplus
+#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#else /* not __cplusplus */
+#define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#endif /* not __cplusplus */
+#else /* not YYPARSE_PARAM */
+#define YYPARSE_PARAM_ARG
+#define YYPARSE_PARAM_DECL
+#endif /* not YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+#ifdef YYPARSE_PARAM
+int yyparse (void *);
+#else
+int yyparse (void);
+#endif
+#endif
+
+int
+yyparse(YYPARSE_PARAM_ARG)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+ int yyfree_stacks = 0;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+#ifndef YYSTACK_USE_ALLOCA
+ yyfree_stacks = 1;
+#endif
+ yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss, (char *)yyss1,
+ size * (unsigned int) sizeof (*yyssp));
+ yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs, (char *)yyvs1,
+ size * (unsigned int) sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls, (char *)yyls1,
+ size * (unsigned int) sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 8:
+#line 131 "yacc.yy"
+{ ModuleHelper::define(yyvsp[0]._str); ;
+ break;}
+case 10:
+#line 132 "yacc.yy"
+{ ModuleHelper::define(yyvsp[0]._str); ;
+ break;}
+case 11:
+#line 137 "yacc.yy"
+{
+ char *qualified = ModuleHelper::qualify(yyvsp[-5]._str);
+ addStructTodo(TypeDef(qualified,*yyvsp[-2]._typeComponentSeq,g->noHints));
+ free(qualified);
+ free(yyvsp[-5]._str);
+ ;
+ break;}
+case 12:
+#line 146 "yacc.yy"
+{ ModuleHelper::define(yyvsp[0]._str); ;
+ break;}
+case 13:
+#line 151 "yacc.yy"
+{
+ char *qualified = ModuleHelper::qualify(yyvsp[-5]._str);
+ addEnumTodo(EnumDef(qualified,*yyvsp[-2]._enumComponentSeq,g->noHints));
+ free(qualified);
+ free(yyvsp[-5]._str);
+ delete yyvsp[-2]._enumComponentSeq;
+ ;
+ break;}
+case 14:
+#line 160 "yacc.yy"
+{ yyval._str = yyvsp[0]._str; ;
+ break;}
+case 15:
+#line 160 "yacc.yy"
+{ yyval._str = strdup("_anonymous_"); ;
+ break;}
+case 16:
+#line 164 "yacc.yy"
+{
+ yyval._enumComponentSeq = new vector<EnumComponent>;
+ yyval._enumComponentSeq->push_back(EnumComponent(yyvsp[0]._str,0,g->noHints));
+ free(yyvsp[0]._str);
+ ;
+ break;}
+case 17:
+#line 170 "yacc.yy"
+{
+ yyval._enumComponentSeq = new vector<EnumComponent>;
+ yyval._enumComponentSeq->push_back(EnumComponent(yyvsp[-2]._str,yyvsp[0]._int,g->noHints));
+ free(yyvsp[-2]._str);
+ ;
+ break;}
+case 18:
+#line 176 "yacc.yy"
+{
+ EnumComponent& last = (*yyvsp[-2]._enumComponentSeq)[yyvsp[-2]._enumComponentSeq->size()-1];
+
+ yyval._enumComponentSeq = yyvsp[-2]._enumComponentSeq;
+ yyval._enumComponentSeq->push_back(EnumComponent(yyvsp[0]._str,last.value+1,g->noHints));
+ free(yyvsp[0]._str);
+ ;
+ break;}
+case 19:
+#line 184 "yacc.yy"
+{
+ yyval._enumComponentSeq = yyvsp[-4]._enumComponentSeq;
+ yyval._enumComponentSeq->push_back(EnumComponent(yyvsp[-2]._str,yyvsp[0]._int,g->noHints));
+ free(yyvsp[-2]._str);
+ ;
+ break;}
+case 20:
+#line 191 "yacc.yy"
+{ ModuleHelper::define(yyvsp[0]._str); ;
+ break;}
+case 22:
+#line 192 "yacc.yy"
+{ ModuleHelper::define(yyvsp[0]._str); ;
+ break;}
+case 23:
+#line 197 "yacc.yy"
+{
+ vector<char *>::iterator ii;
+ for(ii=yyvsp[-4]._strs->begin(); ii != yyvsp[-4]._strs->end(); ii++)
+ {
+ yyvsp[-2]._interfaceDef->inheritedInterfaces.push_back(*ii);
+ free(*ii);
+ }
+ delete yyvsp[-4]._strs;
+ char *qualified = ModuleHelper::qualify(yyvsp[-6]._str);
+ yyvsp[-2]._interfaceDef->name = qualified;
+ free(qualified);
+ free(yyvsp[-6]._str);
+ addInterfaceTodo(*yyvsp[-2]._interfaceDef);
+ delete yyvsp[-2]._interfaceDef;
+ ;
+ break;}
+case 24:
+#line 215 "yacc.yy"
+{ yyval._strs = new vector<char *>; ;
+ break;}
+case 25:
+#line 216 "yacc.yy"
+{ yyval._strs = yyvsp[0]._strs; ;
+ break;}
+case 26:
+#line 219 "yacc.yy"
+{ ModuleHelper::enter(yyvsp[0]._str); free(yyvsp[0]._str); ;
+ break;}
+case 27:
+#line 222 "yacc.yy"
+{ ModuleHelper::leave(); ;
+ break;}
+case 29:
+#line 227 "yacc.yy"
+{
+ yyval._interfaceDef = new InterfaceDef();
+ ;
+ break;}
+case 30:
+#line 231 "yacc.yy"
+{
+ yyval._interfaceDef = yyvsp[0]._interfaceDef;
+ yyval._interfaceDef->methods.insert(yyval._interfaceDef->methods.begin(),*yyvsp[-1]._methodDef);
+ delete yyvsp[-1]._methodDef;
+ ;
+ break;}
+case 31:
+#line 237 "yacc.yy"
+{
+ yyval._interfaceDef = yyvsp[0]._interfaceDef;
+ yyval._interfaceDef->attributes.insert(yyval._interfaceDef->attributes.begin(),yyvsp[-1]._attributeDefSeq->begin(),yyvsp[-1]._attributeDefSeq->end());
+ if ((*yyvsp[-1]._attributeDefSeq)[0].flags & streamDefault) {
+ vector<std::string> sv;
+ for (vector<AttributeDef>::iterator i=yyvsp[-1]._attributeDefSeq->begin(); i!=yyvsp[-1]._attributeDefSeq->end(); i++)
+ sv.push_back(i->name);
+ yyval._interfaceDef->defaultPorts.insert(yyval._interfaceDef->defaultPorts.begin(),sv.begin(),sv.end());
+ }
+ ;
+ break;}
+case 32:
+#line 248 "yacc.yy"
+{
+ yyval._interfaceDef = yyvsp[0]._interfaceDef;
+ for (vector<char *>::iterator i=yyvsp[-1]._strs->begin(); i!=yyvsp[-1]._strs->end(); i++)
+ yyval._interfaceDef->defaultPorts.insert(yyval._interfaceDef->defaultPorts.begin(), *i);
+ ;
+ break;}
+case 34:
+#line 257 "yacc.yy"
+{
+ // 16 == attribute
+ vector<char *>::iterator i;
+ yyval._attributeDefSeq = new vector<AttributeDef>;
+ for(i=yyvsp[-1]._strs->begin();i != yyvsp[-1]._strs->end();i++)
+ {
+ yyval._attributeDefSeq->push_back(AttributeDef((*i),yyvsp[-2]._str,(AttributeType)(yyvsp[-4]._int + 16),g->noHints));
+ free(*i);
+ }
+ delete yyvsp[-1]._strs;
+ ;
+ break;}
+case 35:
+#line 271 "yacc.yy"
+{ yyval._int = 1+2; /* in&out (read & write) */ ;
+ break;}
+case 36:
+#line 272 "yacc.yy"
+{ yyval._int = 2; /* out (readonly) */ ;
+ break;}
+case 37:
+#line 276 "yacc.yy"
+{ yyval._int = methodTwoway; ;
+ break;}
+case 38:
+#line 277 "yacc.yy"
+{ yyval._int = methodOneway; ;
+ break;}
+case 39:
+#line 281 "yacc.yy"
+{ yyval._int = 0; ;
+ break;}
+case 40:
+#line 282 "yacc.yy"
+{ yyval._int = streamDefault; ;
+ break;}
+case 41:
+#line 286 "yacc.yy"
+{
+ // 8 == stream
+ vector<char *>::iterator i;
+ yyval._attributeDefSeq = new vector<AttributeDef>;
+ for(i=yyvsp[-1]._strs->begin();i != yyvsp[-1]._strs->end();i++)
+ {
+ yyval._attributeDefSeq->push_back(AttributeDef((*i),yyvsp[-3]._str,(AttributeType)((yyvsp[-4]._int|yyvsp[-5]._int) + 8),g->noHints));
+ free(*i);
+ }
+ delete yyvsp[-1]._strs;
+ ;
+ break;}
+case 42:
+#line 299 "yacc.yy"
+{
+ yyval._strs = yyvsp[-1]._strs;
+ ;
+ break;}
+case 43:
+#line 304 "yacc.yy"
+{ yyval._int = streamIn; ;
+ break;}
+case 44:
+#line 305 "yacc.yy"
+{ yyval._int = streamIn|streamMulti; ;
+ break;}
+case 45:
+#line 306 "yacc.yy"
+{ yyval._int = streamOut; ;
+ break;}
+case 46:
+#line 307 "yacc.yy"
+{ yyval._int = streamOut|streamMulti; ;
+ break;}
+case 47:
+#line 308 "yacc.yy"
+{ yyval._int = streamAsync|streamIn; ;
+ break;}
+case 48:
+#line 309 "yacc.yy"
+{ yyval._int =streamAsync|streamIn|streamMulti ;
+ break;}
+case 49:
+#line 310 "yacc.yy"
+{ yyval._int = streamAsync|streamOut; ;
+ break;}
+case 50:
+#line 311 "yacc.yy"
+{ yyval._int = streamAsync|streamOut|streamMulti; ;
+ break;}
+case 51:
+#line 318 "yacc.yy"
+{
+ yyval._methodDef = new MethodDef(yyvsp[-4]._str,yyvsp[-5]._str,(MethodType)yyvsp[-6]._int,*yyvsp[-2]._paramDefSeq,g->noHints);
+ free(yyvsp[-4]._str);
+ free(yyvsp[-5]._str);
+ ;
+ break;}
+case 52:
+#line 327 "yacc.yy"
+{
+ yyval._paramDefSeq = new vector<ParamDef>;
+ ;
+ break;}
+case 53:
+#line 331 "yacc.yy"
+{
+ yyval._paramDefSeq = yyvsp[0]._paramDefSeq;
+ yyval._paramDefSeq->insert(yyval._paramDefSeq->begin(),*yyvsp[-1]._paramDef);
+ delete yyvsp[-1]._paramDef;
+ ;
+ break;}
+case 54:
+#line 340 "yacc.yy"
+{
+ yyval._paramDefSeq = new vector<ParamDef>;
+ ;
+ break;}
+case 55:
+#line 344 "yacc.yy"
+{
+ yyval._paramDefSeq = yyvsp[-2]._paramDefSeq;
+ yyval._paramDefSeq->push_back(*yyvsp[0]._paramDef);
+ delete yyvsp[0]._paramDef;
+ //$$->insert($$->begin(),$3);
+ ;
+ break;}
+case 56:
+#line 354 "yacc.yy"
+{
+ yyval._paramDef = new ParamDef(string(yyvsp[-1]._str),string(yyvsp[0]._str),g->noHints);
+ free(yyvsp[-1]._str);
+ free(yyvsp[0]._str);
+ ;
+ break;}
+case 57:
+#line 369 "yacc.yy"
+{ yyval._strs = new vector<char *>; yyval._strs->push_back(yyvsp[0]._str); ;
+ break;}
+case 58:
+#line 370 "yacc.yy"
+{ yyval._strs = yyvsp[-2]._strs; yyval._strs->push_back(yyvsp[0]._str); ;
+ break;}
+case 59:
+#line 373 "yacc.yy"
+{ yyval._strs = new vector<char *>; yyval._strs->push_back(yyvsp[0]._str); ;
+ break;}
+case 60:
+#line 374 "yacc.yy"
+{ yyval._strs = yyvsp[-2]._strs; yyval._strs->push_back(yyvsp[0]._str); ;
+ break;}
+case 61:
+#line 376 "yacc.yy"
+{
+ yyval._str = ModuleHelper::qualify(yyvsp[0]._str);
+ free(yyvsp[0]._str);
+ ;
+ break;}
+case 62:
+#line 380 "yacc.yy"
+{
+ yyval._str = ModuleHelper::qualify(yyvsp[0]._str);
+ free(yyvsp[0]._str);
+ ;
+ break;}
+case 63:
+#line 386 "yacc.yy"
+{
+ // is empty by default
+ yyval._typeComponentSeq = new vector<TypeComponent>;
+ ;
+ break;}
+case 64:
+#line 390 "yacc.yy"
+{
+ yyval._typeComponentSeq = yyvsp[0]._typeComponentSeq;
+ vector<char *>::reverse_iterator i;
+ for(i = yyvsp[-2]._strs->rbegin();i != yyvsp[-2]._strs->rend();i++)
+ {
+ char *identifier = *i;
+
+ yyval._typeComponentSeq->insert(yyval._typeComponentSeq->begin(),TypeComponent(yyvsp[-3]._str,identifier,g->noHints));
+ free(identifier);
+ }
+ delete yyvsp[-2]._strs;
+ ;
+ break;}
+case 66:
+#line 411 "yacc.yy"
+{
+ // a sequence<long> is for instance coded as *long
+
+ // alloc new size: add one for the null byte and one for the '*' char
+ char *result = (char *)malloc(strlen(yyvsp[-1]._str)+2);
+ result[0] = '*';
+ strcpy(&result[1],yyvsp[-1]._str);
+ free(yyvsp[-1]._str); /* fails */
+
+ yyval._str = result;
+ ;
+ break;}
+case 67:
+#line 424 "yacc.yy"
+{ yyval._str = strdup("boolean"); ;
+ break;}
+case 68:
+#line 425 "yacc.yy"
+{ yyval._str = strdup("string"); ;
+ break;}
+case 69:
+#line 426 "yacc.yy"
+{ yyval._str = strdup("long"); ;
+ break;}
+case 70:
+#line 427 "yacc.yy"
+{ yyval._str = strdup("byte"); ;
+ break;}
+case 71:
+#line 428 "yacc.yy"
+{ yyval._str = strdup("object"); ;
+ break;}
+case 72:
+#line 429 "yacc.yy"
+{ yyval._str = strdup("float"); ;
+ break;}
+case 73:
+#line 430 "yacc.yy"
+{ yyval._str = strdup("float"); ;
+ break;}
+case 74:
+#line 431 "yacc.yy"
+{ yyval._str = strdup("void"); ;
+ break;}
+case 75:
+#line 432 "yacc.yy"
+{
+ yyval._str = ModuleHelper::qualify(yyvsp[0]._str);
+ free(yyvsp[0]._str);
+ ;
+ break;}
+case 76:
+#line 436 "yacc.yy"
+{
+ yyval._str = ModuleHelper::qualify(yyvsp[0]._str);
+ free(yyvsp[0]._str);
+ ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 543 "/usr/share/misc/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+
+ yyacceptlab:
+ /* YYACCEPT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 0;
+
+ yyabortlab:
+ /* YYABORT comes here. */
+ if (yyfree_stacks)
+ {
+ free (yyss);
+ free (yyvs);
+#ifdef YYLSP_NEEDED
+ free (yyls);
+#endif
+ }
+ return 1;
+}
+#line 443 "yacc.yy"
+
+
+void mcopidlParse( const char *_code )
+{
+ g = new ParserGlobals;
+ mcopidlInitFlex( _code );
+ yyparse();
+ delete g;
+}
diff --git a/mcopidl/yacc.cc.h b/mcopidl/yacc.cc.h
new file mode 100644
index 0000000..a600e21
--- /dev/null
+++ b/mcopidl/yacc.cc.h
@@ -0,0 +1,75 @@
+
+#ifndef YACC_CC_H
+#define YACC_CC_H
+
+typedef union
+{
+ // generic data types
+ long _int;
+ char* _str;
+ unsigned short _char;
+ double _float;
+
+ vector<char*> *_strs;
+
+ // types
+ vector<TypeComponent> *_typeComponentSeq;
+ TypeComponent* _typeComponent;
+
+ // enums
+ vector<EnumComponent> *_enumComponentSeq;
+
+ // interfaces
+ InterfaceDef *_interfaceDef;
+
+ ParamDef* _paramDef;
+ vector<ParamDef> *_paramDefSeq;
+
+ MethodDef* _methodDef;
+ vector<MethodDef> *_methodDefSeq;
+
+ AttributeDef* _attributeDef;
+ vector<AttributeDef> *_attributeDefSeq;
+} YYSTYPE;
+#define T_STRUCT 257
+#define T_ENUM 258
+#define T_INTERFACE 259
+#define T_MODULE 260
+#define T_VOID 261
+#define T_LEFT_CURLY_BRACKET 262
+#define T_RIGHT_CURLY_BRACKET 263
+#define T_LEFT_PARANTHESIS 264
+#define T_RIGHT_PARANTHESIS 265
+#define T_LESS 266
+#define T_GREATER 267
+#define T_EQUAL 268
+#define T_SEMICOLON 269
+#define T_COLON 270
+#define T_COMMA 271
+#define T_IDENTIFIER 272
+#define T_QUALIFIED_IDENTIFIER 273
+#define T_INTEGER_LITERAL 274
+#define T_UNKNOWN 275
+#define T_BOOLEAN 276
+#define T_STRING 277
+#define T_LONG 278
+#define T_BYTE 279
+#define T_OBJECT 280
+#define T_SEQUENCE 281
+#define T_AUDIO 282
+#define T_FLOAT 283
+#define T_IN 284
+#define T_OUT 285
+#define T_STREAM 286
+#define T_MULTI 287
+#define T_ATTRIBUTE 288
+#define T_READONLY 289
+#define T_ASYNC 290
+#define T_ONEWAY 291
+#define T_DEFAULT 292
+
+
+extern YYSTYPE yylval;
+
+#endif // YACC_CC_H
+
diff --git a/mcopidl/yacc.yy b/mcopidl/yacc.yy
new file mode 100644
index 0000000..9e90fbe
--- /dev/null
+++ b/mcopidl/yacc.yy
@@ -0,0 +1,451 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld, stefan@space.twc.de
+ Nicolas Brodu, nicolas.brodu@free.fr
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+%{
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include "common.h"
+#include "namespace.h"
+
+using namespace std;
+using namespace Arts;
+
+extern int idl_line_no;
+extern string idl_filename;
+
+extern int yylex();
+extern void mcopidlInitFlex( const char *_code );
+extern void addEnumTodo( const EnumDef& edef );
+extern void addStructTodo( const TypeDef& type );
+extern void addInterfaceTodo( const InterfaceDef& iface );
+
+void yyerror( const char *s )
+{
+ printf( "%s:%i: %s\n", idl_filename.c_str(), idl_line_no, s );
+ exit(1);
+ // theParser->parse_error( idl_lexFile, s, idl_line_no );
+}
+
+static struct ParserGlobals {
+ vector<string> noHints;
+} *g;
+
+%}
+
+%union
+{
+ // generic data types
+ long _int;
+ char* _str;
+ unsigned short _char;
+ double _float;
+
+ vector<char*> *_strs;
+
+ // types
+ vector<TypeComponent> *_typeComponentSeq;
+ TypeComponent* _typeComponent;
+
+ // enums
+ vector<EnumComponent> *_enumComponentSeq;
+
+ // interfaces
+ InterfaceDef *_interfaceDef;
+
+ ParamDef* _paramDef;
+ vector<ParamDef> *_paramDefSeq;
+
+ MethodDef* _methodDef;
+ vector<MethodDef> *_methodDefSeq;
+
+ AttributeDef* _attributeDef;
+ vector<AttributeDef> *_attributeDefSeq;
+}
+
+%token T_STRUCT T_ENUM T_INTERFACE T_MODULE T_VOID
+%token T_LEFT_CURLY_BRACKET T_RIGHT_CURLY_BRACKET
+%token T_LEFT_PARANTHESIS T_RIGHT_PARANTHESIS
+%token T_LESS T_GREATER T_EQUAL
+%token T_SEMICOLON T_COLON T_COMMA
+%token<_str> T_IDENTIFIER T_QUALIFIED_IDENTIFIER
+%type<_str> type
+%type<_str> simpletype
+%type<_str> enumname
+%type<_str> interfacelistelem
+/*%type<_typeComponent> typecomponentdef*/
+%type<_typeComponentSeq> structbody
+%type<_paramDef> paramdef
+%type<_paramDefSeq> paramdefs
+%type<_paramDefSeq> paramdefs1
+%type<_methodDef> methoddef
+%type<_attributeDefSeq> attributedef
+%type<_attributeDefSeq> streamdef
+%type<_interfaceDef> classbody
+%type<_enumComponentSeq> enumbody
+%type<_strs> interfacelist
+%type<_strs> identifierlist
+%type<_strs> defaultdef
+%type<_strs> inheritedinterfaces
+
+%type<_int> maybereadonly
+%type<_int> direction
+%type<_int> maybeoneway
+%type<_int> maybedefault
+
+%token T_INTEGER_LITERAL T_UNKNOWN
+%type<_int> T_INTEGER_LITERAL
+
+%token T_BOOLEAN T_STRING T_LONG T_BYTE T_OBJECT T_SEQUENCE T_AUDIO T_FLOAT
+%token T_IN T_OUT T_STREAM T_MULTI T_ATTRIBUTE T_READONLY T_ASYNC T_ONEWAY
+%token T_DEFAULT
+
+%%
+
+aidlfile: definitions;
+
+definitions: epsilon | definition definitions ;
+
+definition: structdef | interfacedef | moduledef | enumdef ;
+
+structdef:
+ T_STRUCT T_IDENTIFIER { ModuleHelper::define($2); } T_SEMICOLON
+ | T_STRUCT T_IDENTIFIER { ModuleHelper::define($2); }
+ T_LEFT_CURLY_BRACKET
+ structbody
+ T_RIGHT_CURLY_BRACKET
+ T_SEMICOLON
+ {
+ char *qualified = ModuleHelper::qualify($2);
+ addStructTodo(TypeDef(qualified,*$5,g->noHints));
+ free(qualified);
+ free($2);
+ }
+ ;
+
+enumdef:
+ T_ENUM enumname { ModuleHelper::define($2); }
+ T_LEFT_CURLY_BRACKET
+ enumbody
+ T_RIGHT_CURLY_BRACKET
+ T_SEMICOLON
+ {
+ char *qualified = ModuleHelper::qualify($2);
+ addEnumTodo(EnumDef(qualified,*$5,g->noHints));
+ free(qualified);
+ free($2);
+ delete $5;
+ }
+ ;
+
+enumname: T_IDENTIFIER { $$ = $1; } | epsilon { $$ = strdup("_anonymous_"); };
+
+enumbody:
+ T_IDENTIFIER
+ {
+ $$ = new vector<EnumComponent>;
+ $$->push_back(EnumComponent($1,0,g->noHints));
+ free($1);
+ }
+ | T_IDENTIFIER T_EQUAL T_INTEGER_LITERAL
+ {
+ $$ = new vector<EnumComponent>;
+ $$->push_back(EnumComponent($1,$3,g->noHints));
+ free($1);
+ }
+ | enumbody T_COMMA T_IDENTIFIER
+ {
+ EnumComponent& last = (*$1)[$1->size()-1];
+
+ $$ = $1;
+ $$->push_back(EnumComponent($3,last.value+1,g->noHints));
+ free($3);
+ }
+ | enumbody T_COMMA T_IDENTIFIER T_EQUAL T_INTEGER_LITERAL
+ {
+ $$ = $1;
+ $$->push_back(EnumComponent($3,$5,g->noHints));
+ free($3);
+ };
+
+interfacedef:
+ T_INTERFACE T_IDENTIFIER { ModuleHelper::define($2); } T_SEMICOLON
+ | T_INTERFACE T_IDENTIFIER { ModuleHelper::define($2); } inheritedinterfaces
+ T_LEFT_CURLY_BRACKET
+ classbody
+ T_RIGHT_CURLY_BRACKET
+ T_SEMICOLON
+ {
+ vector<char *>::iterator ii;
+ for(ii=$4->begin(); ii != $4->end(); ii++)
+ {
+ $6->inheritedInterfaces.push_back(*ii);
+ free(*ii);
+ }
+ delete $4;
+ char *qualified = ModuleHelper::qualify($2);
+ $6->name = qualified;
+ free(qualified);
+ free($2);
+ addInterfaceTodo(*$6);
+ delete $6;
+ }
+ ;
+
+inheritedinterfaces:
+ epsilon { $$ = new vector<char *>; }
+ | T_COLON interfacelist { $$ = $2; };
+
+moduledef:
+ T_MODULE T_IDENTIFIER { ModuleHelper::enter($2); free($2); }
+ T_LEFT_CURLY_BRACKET
+ definitions
+ T_RIGHT_CURLY_BRACKET { ModuleHelper::leave(); }
+ T_SEMICOLON
+ ;
+
+classbody:
+ epsilon {
+ $$ = new InterfaceDef();
+ }
+ | methoddef classbody
+ {
+ $$ = $2;
+ $$->methods.insert($$->methods.begin(),*$1);
+ delete $1;
+ }
+ | attributedef classbody
+ {
+ $$ = $2;
+ $$->attributes.insert($$->attributes.begin(),$1->begin(),$1->end());
+ if ((*$1)[0].flags & streamDefault) {
+ vector<std::string> sv;
+ for (vector<AttributeDef>::iterator i=$1->begin(); i!=$1->end(); i++)
+ sv.push_back(i->name);
+ $$->defaultPorts.insert($$->defaultPorts.begin(),sv.begin(),sv.end());
+ }
+ }
+ | defaultdef classbody
+ {
+ $$ = $2;
+ for (vector<char *>::iterator i=$1->begin(); i!=$1->end(); i++)
+ $$->defaultPorts.insert($$->defaultPorts.begin(), *i);
+ };
+
+attributedef:
+ streamdef
+ | maybereadonly T_ATTRIBUTE type identifierlist T_SEMICOLON
+ {
+ // 16 == attribute
+ vector<char *>::iterator i;
+ $$ = new vector<AttributeDef>;
+ for(i=$4->begin();i != $4->end();i++)
+ {
+ $$->push_back(AttributeDef((*i),$3,(AttributeType)($1 + 16),g->noHints));
+ free(*i);
+ }
+ delete $4;
+ }
+ ;
+
+maybereadonly:
+ epsilon { $$ = 1+2; /* in&out (read & write) */ }
+ | T_READONLY { $$ = 2; /* out (readonly) */ }
+ ;
+
+maybeoneway:
+ epsilon { $$ = methodTwoway; }
+ | T_ONEWAY { $$ = methodOneway; }
+ ;
+
+maybedefault:
+ epsilon { $$ = 0; }
+ | T_DEFAULT { $$ = streamDefault; }
+ ;
+
+streamdef: maybedefault direction type T_STREAM identifierlist T_SEMICOLON
+ {
+ // 8 == stream
+ vector<char *>::iterator i;
+ $$ = new vector<AttributeDef>;
+ for(i=$5->begin();i != $5->end();i++)
+ {
+ $$->push_back(AttributeDef((*i),$3,(AttributeType)(($2|$1) + 8),g->noHints));
+ free(*i);
+ }
+ delete $5;
+ };
+
+defaultdef: T_DEFAULT identifierlist T_SEMICOLON
+ {
+ $$ = $2;
+ };
+
+direction:
+ T_IN { $$ = streamIn; }
+ | T_IN T_MULTI { $$ = streamIn|streamMulti; }
+ | T_OUT { $$ = streamOut; }
+ | T_OUT T_MULTI { $$ = streamOut|streamMulti; }
+ | T_ASYNC T_IN { $$ = streamAsync|streamIn; }
+ | T_ASYNC T_IN T_MULTI { $$ =streamAsync|streamIn|streamMulti }
+ | T_ASYNC T_OUT { $$ = streamAsync|streamOut; }
+ | T_ASYNC T_OUT T_MULTI { $$ = streamAsync|streamOut|streamMulti; }
+ ;
+
+// CacheElement getFromCache(string name, bool hit)
+methoddef:
+ maybeoneway type T_IDENTIFIER
+ T_LEFT_PARANTHESIS paramdefs T_RIGHT_PARANTHESIS T_SEMICOLON
+ {
+ $$ = new MethodDef($3,$2,(MethodType)$1,*$5,g->noHints);
+ free($3);
+ free($2);
+ }
+ ;
+
+paramdefs:
+ epsilon
+ {
+ $$ = new vector<ParamDef>;
+ }
+ | paramdef paramdefs1
+ {
+ $$ = $2;
+ $$->insert($$->begin(),*$1);
+ delete $1;
+ };
+
+// at least one parameter (ex: "long a" or "long a, long b, string c")
+paramdefs1:
+ epsilon
+ {
+ $$ = new vector<ParamDef>;
+ }
+ | paramdefs1 T_COMMA paramdef
+ {
+ $$ = $1;
+ $$->push_back(*$3);
+ delete $3;
+ //$$->insert($$->begin(),$3);
+ }
+ ;
+
+// one parameter (ex: "long a")
+paramdef: type T_IDENTIFIER
+ {
+ $$ = new ParamDef(string($1),string($2),g->noHints);
+ free($1);
+ free($2);
+ };
+
+/*
+typecomponentdef: type T_IDENTIFIER T_SEMICOLON
+ {
+ $$ = new TypeComponent($1,string($2));
+ free($2);
+ };
+*/
+
+identifierlist:
+ T_IDENTIFIER { $$ = new vector<char *>; $$->push_back($1); }
+ | identifierlist T_COMMA T_IDENTIFIER { $$ = $1; $$->push_back($3); }
+
+interfacelist:
+ interfacelistelem { $$ = new vector<char *>; $$->push_back($1); }
+ | interfacelist T_COMMA interfacelistelem { $$ = $1; $$->push_back($3); }
+
+interfacelistelem: T_IDENTIFIER {
+ $$ = ModuleHelper::qualify($1);
+ free($1);
+ }
+ | T_QUALIFIED_IDENTIFIER {
+ $$ = ModuleHelper::qualify($1);
+ free($1);
+ }
+ ;
+
+structbody: epsilon {
+ // is empty by default
+ $$ = new vector<TypeComponent>;
+ }
+ | type identifierlist T_SEMICOLON structbody {
+ $$ = $4;
+ vector<char *>::reverse_iterator i;
+ for(i = $2->rbegin();i != $2->rend();i++)
+ {
+ char *identifier = *i;
+
+ $$->insert($$->begin(),TypeComponent($1,identifier,g->noHints));
+ free(identifier);
+ }
+ delete $2;
+ };
+ /*
+ | typecomponentdef structbody {
+ $$ = $2;
+ $$->insert($$->begin(),$1);
+ };
+ */
+
+type: simpletype
+ | T_SEQUENCE T_LESS simpletype T_GREATER
+ {
+ // a sequence<long> is for instance coded as *long
+
+ // alloc new size: add one for the null byte and one for the '*' char
+ char *result = (char *)malloc(strlen($3)+2);
+ result[0] = '*';
+ strcpy(&result[1],$3);
+ free($3); /* fails */
+
+ $$ = result;
+ };
+
+simpletype:
+ T_BOOLEAN { $$ = strdup("boolean"); }
+ | T_STRING { $$ = strdup("string"); }
+ | T_LONG { $$ = strdup("long"); }
+ | T_BYTE { $$ = strdup("byte"); }
+ | T_OBJECT { $$ = strdup("object"); }
+ | T_AUDIO { $$ = strdup("float"); }
+ | T_FLOAT { $$ = strdup("float"); }
+ | T_VOID { $$ = strdup("void"); }
+ | T_IDENTIFIER {
+ $$ = ModuleHelper::qualify($1);
+ free($1);
+ }
+ | T_QUALIFIED_IDENTIFIER {
+ $$ = ModuleHelper::qualify($1);
+ free($1);
+ };
+
+
+epsilon: /* empty */ ;
+%%
+
+void mcopidlParse( const char *_code )
+{
+ g = new ParserGlobals;
+ mcopidlInitFlex( _code );
+ yyparse();
+ delete g;
+}
diff --git a/qtmcop/Makefile.am b/qtmcop/Makefile.am
new file mode 100644
index 0000000..74f638a
--- /dev/null
+++ b/qtmcop/Makefile.am
@@ -0,0 +1,14 @@
+lib_LTLIBRARIES = libqtmcop.la
+
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop $(all_includes) $(QT_INCLUDES)
+KDE_OPTIONS = qtonly
+
+libqtmcop_la_SOURCES = qiomanager.cc
+libqtmcop_la_LIBADD = $(top_builddir)/mcop/libmcop.la $(LIB_QT)
+libqtmcop_la_LDFLAGS = -no-undefined -version-info 1:0 $(KDE_RPATH) \
+ $(KDE_MT_LDFLAGS) $(QT_LDFLAGS) $(USER_LDFLAGS) $(X_LDFLAGS) $(LDFLAGS_AS_NEEDED)
+
+METASOURCES = qiomanager_p.moc
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = qiomanager.h
diff --git a/qtmcop/qiomanager.cc b/qtmcop/qiomanager.cc
new file mode 100644
index 0000000..c49d83c
--- /dev/null
+++ b/qtmcop/qiomanager.cc
@@ -0,0 +1,299 @@
+ /*
+
+ Copyright (C) 1999-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "qiomanager.h"
+#include "qiomanager_p.h"
+#include <qsocketnotifier.h>
+#include <qapplication.h>
+#include "debug.h"
+#include "dispatcher.h"
+#include "thread.h"
+
+using namespace std;
+using namespace Arts;
+
+/*
+ * Collected incompatibilities of QIOManager (compared against StdIOManager):
+ *
+ * - StdIOManager catches up timers (i.e. if a 100ms timer hasn't been
+ * notified for half a second, it will get notified five times to
+ * catch up the lost time
+ * - StdIOManager is able to watch the same filedescriptor twice for reading
+ * - StdIOManager sends notifications soon after they have been produced,
+ * whereas we use a hackish 50ms timer to deliver them
+ */
+
+/*
+ * Fallback for the case where we should perform blocking
+ */
+namespace Arts {
+class QIOManagerBlocking : public StdIOManager {
+public:
+ void setLevel(int newLevel) { level = newLevel; }
+};
+}
+
+/*
+ * QIOManager is a singleton (or at least supposed to be used only once at
+ * most, and the behaviour would pretty undefined if you violate this), so we
+ * use static variables for private data here.
+ */
+static int qioLevel;
+static QIOManager *qioManager = 0;
+static QIOManagerBlocking *qioManagerBlocking = 0;
+static bool qioBlocking;
+
+/*
+ * QIOWatch:
+ */
+QIOWatch::QIOWatch(int fd, int type, IONotify *notify,
+ QSocketNotifier::Type qtype, bool reentrant)
+ : _fd(fd), _type(type), _client(notify), _reentrant(reentrant)
+{
+ qsocketnotify = new QSocketNotifier(fd,qtype,this);
+ connect(qsocketnotify,SIGNAL(activated(int)),this,SLOT(notify(int)));
+}
+
+void QIOWatch::notify(int socket)
+{
+ arts_assert(socket == _fd);
+ qioManager->dispatch(this);
+}
+
+/*
+ * QTimeWatch:
+ */
+QTimeWatch::QTimeWatch(int milliseconds, TimeNotify *notify)
+{
+ timer = new QTimer(this);
+ connect( timer, SIGNAL(timeout()), this, SLOT(notify()) );
+ timer->start(milliseconds);
+ _client = notify;
+}
+
+void QTimeWatch::notify()
+{
+ qioManager->dispatch(this);
+}
+
+/*
+ * Handle NotificationManager::the()->run() from time to time
+ */
+namespace Arts {
+
+class HandleNotifications : public TimeNotify {
+public:
+ void notifyTime()
+ {
+ Arts::Dispatcher::the()->ioManager()->removeTimer(this);
+ NotificationManager::the()->run();
+ delete this;
+ }
+};
+}
+
+/*
+ * QIOManager:
+ */
+QIOManager::QIOManager()
+{
+ assert(!qioManager);
+ qioManager = this;
+ qioLevel = 0;
+ qioBlocking = true;
+ qioManagerBlocking = new QIOManagerBlocking();
+}
+
+QIOManager::~QIOManager()
+{
+ assert(qioManager);
+ qioManager = 0;
+
+ delete qioManagerBlocking;
+ qioManagerBlocking = 0;
+}
+
+void QIOManager::processOneEvent(bool blocking)
+{
+ assert(SystemThreads::the()->isMainThread());
+
+ if(qioBlocking)
+ {
+ qioLevel++;
+ if(qioLevel == 1)
+ Dispatcher::lock();
+
+ /*
+ * we explicitly take the level to qioManagerBlocking, so that it
+ * will process reentrant watchFDs only
+ */
+ qioManagerBlocking->setLevel(qioLevel);
+ qioManagerBlocking->processOneEvent(blocking);
+
+ if(qioLevel == 1)
+ Dispatcher::unlock();
+ qioLevel--;
+ }
+ else
+ {
+ if(blocking)
+ qApp->processOneEvent();
+ else
+ qApp->processEvents(0);
+ }
+}
+
+void QIOManager::run()
+{
+ arts_warning("QIOManager::run() not implemented.");
+}
+
+void QIOManager::terminate()
+{
+ arts_warning("QIOManager::terminate() not implemented.");
+}
+
+void QIOManager::watchFD(int fd, int types, IONotify *notify)
+{
+ bool r = (types & IOType::reentrant) != 0;
+
+ if(types & IOType::read)
+ {
+ fdList.push_back(
+ new QIOWatch(fd, IOType::read, notify, QSocketNotifier::Read, r)
+ );
+ }
+ if(types & IOType::write)
+ {
+ fdList.push_back(
+ new QIOWatch(fd, IOType::write, notify, QSocketNotifier::Write, r)
+ );
+ }
+ if(types & IOType::except)
+ {
+ fdList.push_back(
+ new QIOWatch(fd, IOType::except, notify, QSocketNotifier::Exception,
+ r)
+ );
+ }
+ if(r) qioManagerBlocking->watchFD(fd, types, notify);
+}
+
+void QIOManager::remove(IONotify *notify, int types)
+{
+ list<QIOWatch *>::iterator i;
+
+ i = fdList.begin();
+ while(i != fdList.end())
+ {
+ QIOWatch *w = *i;
+
+ if(w->type() & types && w->client() == notify)
+ {
+ delete w;
+ fdList.erase(i);
+ i = fdList.begin();
+ }
+ else i++;
+ }
+ qioManagerBlocking->remove(notify, types);
+}
+
+void QIOManager::addTimer(int milliseconds, TimeNotify *notify)
+{
+ if (milliseconds == -1 && notify == 0)
+ {
+ // HACK: in order to not add a virtual function to IOManager we're calling addTimer with
+ // magic values. This call tells the ioManager that notifications are pending and
+ // NotificationManager::run() should get called soon.
+ notify = new HandleNotifications();
+ milliseconds = 0;
+ }
+ timeList.push_back(new QTimeWatch(milliseconds,notify));
+}
+
+void QIOManager::removeTimer(TimeNotify *notify)
+{
+ list<QTimeWatch *>::iterator i;
+
+ i = timeList.begin();
+ while(i != timeList.end())
+ {
+ QTimeWatch *w = *i;
+
+ if(w->client() == notify)
+ {
+ delete w;
+ timeList.erase(i);
+ i = timeList.begin();
+ }
+ else i++;
+ }
+}
+
+void QIOManager::dispatch(QIOWatch *ioWatch)
+{
+ qioLevel++;
+ if(qioLevel == 1)
+ Dispatcher::lock();
+
+ /*
+ * FIXME: there is main loop pollution for (qioBlocking == false) here:
+ *
+ * As QIOManager will never disable the socket notifiers that are not
+ * to be carried out reentrant, these will (maybe) fire again and again,
+ * so that CPU is wasted.
+ */
+ if(qioLevel == 1 || ioWatch->reentrant())
+ ioWatch->client()->notifyIO(ioWatch->fd(),ioWatch->type());
+
+ if(qioLevel == 1)
+ Dispatcher::unlock();
+ qioLevel--;
+}
+
+void QIOManager::dispatch(QTimeWatch *timeWatch)
+{
+ qioLevel++;
+ if(qioLevel == 1)
+ Dispatcher::lock();
+
+ // timers are never done reentrant
+ if(qioLevel == 1)
+ timeWatch->client()->notifyTime();
+
+ if(qioLevel == 1)
+ Dispatcher::unlock();
+ qioLevel--;
+}
+
+bool QIOManager::blocking()
+{
+ return qioBlocking;
+}
+
+void QIOManager::setBlocking(bool blocking)
+{
+ qioBlocking = blocking;
+}
+
+#include "qiomanager_p.moc"
diff --git a/qtmcop/qiomanager.h b/qtmcop/qiomanager.h
new file mode 100644
index 0000000..7bef332
--- /dev/null
+++ b/qtmcop/qiomanager.h
@@ -0,0 +1,106 @@
+ /*
+
+ Copyright (C) 1999-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): QIOManager.
+ *
+ * QIOManager is kept binary compatible.
+ */
+
+#ifndef QIOMANAGER_H
+#define QIOMANAGER_H
+
+#include "iomanager.h"
+#include <qobject.h>
+#include <qtimer.h>
+#include <qsocketnotifier.h>
+#include <list>
+#include "arts_export.h"
+
+namespace Arts {
+
+class QIOWatch;
+class QTimeWatch;
+
+/**
+ * QIOManager performs MCOP I/O inside the Qt event loop. This way, you will
+ * be able to receive requests and notifications inside Qt application. The
+ * usual way to set it up is:
+ *
+ * <pre>
+ * KApplication app(argc, argv); // as usual
+ *
+ * Arts::QIOManager qiomanager;
+ * Arts::Dispatcher dispatcher(&qiomanager);
+ * ...
+ * return app.exec(); // as usual
+ * </pre>
+ */
+
+class ARTS_EXPORT QIOManager : public IOManager {
+protected:
+ friend class QIOWatch;
+ friend class QTimeWatch;
+
+ std::list<QIOWatch *> fdList;
+ std::list<QTimeWatch *> timeList;
+
+ void dispatch(QIOWatch *ioWatch);
+ void dispatch(QTimeWatch *timeWatch);
+
+public:
+ QIOManager();
+ ~QIOManager();
+
+ void processOneEvent(bool blocking);
+ void run();
+ void terminate();
+ void watchFD(int fd, int types, IONotify *notify);
+ void remove(IONotify *notify, int types);
+ void addTimer(int milliseconds, TimeNotify *notify);
+ void removeTimer(TimeNotify *notify);
+
+ /**
+ * This controls what QIOManager will do while waiting for the result
+ * of an MCOP request, the possibilities are:
+ *
+ * @li block until the request is completed (true)
+ * @li open a local event loop (false)
+ *
+ * It is much easier to write working and reliable code with blocking
+ * enabled, so this is the default. If you disable blocking, you have
+ * to deal with the fact that timers, user interaction and similar
+ * "unpredictable" things will possibly influence your code in all
+ * places where you make a remote MCOP call (which is quite often in
+ * MCOP applications).
+ */
+ void setBlocking(bool blocking);
+
+ /**
+ * Query whether blocking is enabled.
+ */
+ bool blocking();
+};
+
+}
+
+#endif
diff --git a/qtmcop/qiomanager_p.h b/qtmcop/qiomanager_p.h
new file mode 100644
index 0000000..78cdbdc
--- /dev/null
+++ b/qtmcop/qiomanager_p.h
@@ -0,0 +1,77 @@
+ /*
+
+ Copyright (C) 1999-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+/*
+ * BC - Status (2002-03-08): QIOWatch, QTimeWatch.
+ *
+ * These classes provide implementation details and not meant to be used
+ * in any way.
+ */
+
+#ifndef QIOMANAGER_P_H
+#define QIOMANAGER_P_H
+
+#include "iomanager.h"
+#include <qobject.h>
+#include <qtimer.h>
+#include <qsocketnotifier.h>
+#include <list>
+
+namespace Arts {
+
+class QIOWatch : public QObject {
+ Q_OBJECT
+protected:
+ QSocketNotifier *qsocketnotify;
+ int _fd;
+ int _type;
+ IONotify *_client;
+ bool _reentrant;
+
+public:
+ QIOWatch(int fd, int type, IONotify *notify, QSocketNotifier::Type qtype,
+ bool reentrant);
+
+ inline IONotify *client() { return _client; }
+ inline int type() { return _type; }
+ inline int fd() { return _fd; }
+ inline bool reentrant() { return _reentrant; }
+public slots:
+ void notify(int socket);
+};
+
+class QTimeWatch : public QObject {
+ Q_OBJECT
+protected:
+ QTimer *timer;
+ TimeNotify *_client;
+public:
+ QTimeWatch(int milliseconds, TimeNotify *notify);
+
+ inline TimeNotify *client() { return _client; }
+public slots:
+ void notify();
+};
+
+}
+
+#endif
diff --git a/soundserver/FileInputStream.mcopclass b/soundserver/FileInputStream.mcopclass
new file mode 100644
index 0000000..c7b7a20
--- /dev/null
+++ b/soundserver/FileInputStream.mcopclass
@@ -0,0 +1,5 @@
+Interface=Arts::FileInputStream,Arts::InputStream,Arts::SynthModule,Arts::Object
+Author="Stefan Westerfeld <stefan@space.twc.de>"
+URL="http://www.arts-project.org"
+Language=C++
+Library=libkmedia2.la
diff --git a/soundserver/GSLPlayObject.mcopclass b/soundserver/GSLPlayObject.mcopclass
new file mode 100644
index 0000000..2f7ca0a
--- /dev/null
+++ b/soundserver/GSLPlayObject.mcopclass
@@ -0,0 +1,7 @@
+Interface=Arts::GSLPlayObject,Arts::PitchablePlayObject,Arts::PlayObject,Arts::PlayObject_private,Arts::SynthModule,Arts::Object
+Author="Hans Meine <hans_meine@gmx.net>"
+URL="http://www.arts-project.org/"
+Extension=wav,mp3,ogg
+Language=C++
+Library=libartsgslplayobject.la
+MimeType=audio/wav,audio/x-wav,audio/x-mp3,audio/x-mp1,audio/x-mp2,audio/vorbis,application/ogg
diff --git a/soundserver/Makefile.am b/soundserver/Makefile.am
new file mode 100644
index 0000000..eee67b4
--- /dev/null
+++ b/soundserver/Makefile.am
@@ -0,0 +1,122 @@
+# $Id: Makefile.am 434809 2005-07-15 13:20:54Z mueller $
+
+# necessary for artswrapper
+artsdpath = $(bindir)/artsd
+
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop -I$(top_srcdir)/flow \
+ -I$(top_builddir)/flow -DEXECUTE=\"$(artsdpath)\" $(all_includes)
+MCOPINC = -I$(srcdir) -I$(top_srcdir)/flow -I$(top_srcdir)/mcop
+FLOWLIBS = $(top_builddir)/flow/libartsflow.la
+
+####### install idl files
+
+artsincludedir = $(includedir)/arts
+artsinclude_HEADERS = soundserver.h soundserver.idl kmedia2.h kmedia2.idl \
+ artsversion.h
+
+####### libsoundserver_idl, libkmedia2_idl (idl files as library)
+
+lib_LTLIBRARIES = libkmedia2_idl.la libsoundserver_idl.la \
+ libartsgslplayobject.la libartswavplayobject.la libkmedia2.la
+
+AM_LDFLAGS = $(LDFLAGS_AS_NEEDED)
+
+libsoundserver_idl_la_LIBADD = libkmedia2_idl.la \
+ $(top_builddir)/flow/libartsflow_idl.la
+libsoundserver_idl_la_LDFLAGS = -no-undefined -version-info 1:0 $(all_libraries)
+libsoundserver_idl_la_SOURCES = soundserver.cc
+libsoundserver_idl_la_COMPILE_FIRST = soundserver.h
+
+libkmedia2_idl_la_SOURCES = kmedia2.cc
+libkmedia2_idl_la_COMPILE_FIRST = kmedia2.h
+libkmedia2_idl_la_LIBADD = $(top_builddir)/flow/libartsflow.la
+libkmedia2_idl_la_LDFLAGS = -no-undefined -version-info 1:0 $(all_libraries)
+
+libkmedia2_la_SOURCES = fileinputstream_impl.cc stdoutwriter_impl.cc
+libkmedia2_la_LIBADD = libkmedia2_idl.la $(FLOWLIBS)
+libkmedia2_la_LDFLAGS = -no-undefined -version-info 1:0 $(all_libraries)
+libkmedia2_la_COMPILE_FIRST = kmedia2.h ../flow/artsflow.h
+
+libartswavplayobject_la_SOURCES = wavplayobject_impl.cc
+libartswavplayobject_la_LIBADD = $(top_builddir)/mcop/libmcop.la \
+ libsoundserver_idl.la $(FLOWLIBS)
+libartswavplayobject_la_LDFLAGS = -no-undefined -module $(all_libraries)
+libartswavplayobject_la_COMPILE_FIRST = soundserver.h ../flow/artsflow.h
+
+libartsgslplayobject_la_SOURCES = gslplayobject_impl.cc
+libartsgslplayobject_la_LIBADD = $(top_builddir)/mcop/libmcop.la \
+ libsoundserver_idl.la $(FLOWLIBS)
+libartsgslplayobject_la_LDFLAGS = -no-undefined -module $(all_libraries)
+libartsgslplayobject_la_COMPILE_FIRST = soundserver.h ../flow/artsflow.h
+
+###### "real" programs
+
+bin_PROGRAMS = artsd artsplay artscat artswrapper artsshell artsrec
+
+artsd_LDADD = libsoundserver_idl.la $(FLOWLIBS) \
+ $(top_builddir)/mcop_mt/libmcop_mt.la
+artsd_LDFLAGS = $(USE_THREADS)
+artsd_SOURCES = soundserverv2_impl.cc soundserver_impl.cc simplesoundserver_impl.cc artsd.cc cpuusage.cc samplestorage_impl.cc crashhandler.cc soundserverstartup_impl.cc
+artsd_COMPILE_FIRST = soundserver.h artsversion.h
+
+artscat_LDADD = libsoundserver_idl.la $(FLOWLIBS) $(LIBPTHREAD)
+artscat_LDFLAGS = $(USE_THREADS)
+artscat_SOURCES = artscat.cc
+artscat_COMPILE_FIRST = soundserver.h artsversion.h
+
+artsrec_LDADD = libsoundserver_idl.la $(FLOWLIBS) $(LIBPTHREAD)
+artsrec_LDFLAGS = $(USE_THREADS)
+artsrec_SOURCES = artsrec.cc
+artsrec_COMPILE_FIRST = soundserver.h artsversion.h
+
+artsplay_LDADD = libsoundserver_idl.la $(LIBPTHREAD)
+artsplay_LDFLAGS = $(USE_THREADS)
+artsplay_SOURCES = artsplay.cc
+artsplay_COMPILE_FIRST = soundserver.h artsversion.h
+
+artswrapper_SOURCES = artswrapper.c
+artswrapper_CFLAGS = $(KDE_USE_FPIE)
+artswrapper_INCLUDES = -I$(top_builddir) -DEXECUTE=\"$(artsdpath)\"
+artswrapper_LDADD = $(LIBPOSIX4)
+artswrapper_LDFLAGS = $(KDE_USE_PIE)
+
+artsshell_LDADD = libsoundserver_idl.la $(LIBPTHREAD)
+artsshell_LDFLAGS = $(USE_THREADS)
+artsshell_SOURCES = artsshell.cc tradercheck.cc
+artsshell_COMPILE_FIRST = soundserver.h artsversion.h ../flow/artsflow.h
+
+DISTCLEANFILES = soundserver.cc soundserver.h soundserver.mcopclass \
+ soundserver.mcoptype kmedia2.h kmedia2.cc kmedia2.mcopclass kmedia2.mcoptype artsversion.h
+
+####### Build rules
+soundserver.mcoptype: soundserver.h
+soundserver.mcopclass: soundserver.h
+soundserver.cc soundserver.h: $(top_srcdir)/soundserver/soundserver.idl kmedia2.h $(MCOPIDL) ../flow/artsflow.h
+ $(MCOPIDL) -t $(MCOPINC) $(top_srcdir)/soundserver/soundserver.idl
+
+kmedia2.mcoptype: kmedia2.h
+kmedia2.mcopclass: kmedia2.h
+kmedia2.cc kmedia2.h: $(top_srcdir)/soundserver/kmedia2.idl $(MCOPIDL) ../flow/artsflow.h
+ $(MCOPIDL) -t $(MCOPINC) $(top_srcdir)/soundserver/kmedia2.idl
+
+
+artsversion.h: artsversion-new.h
+ (cmp -s artsversion-new.h artsversion.h \
+ || cp artsversion-new.h artsversion.h)
+
+if HAVE_WAVSUPPORT
+WAV_MCOPCLASS = WavPlayObject.mcopclass
+endif
+
+mcopclassdir = $(libdir)/mcop/Arts
+mcopclass_DATA = FileInputStream.mcopclass $(WAV_MCOPCLASS) GSLPlayObject.mcopclass
+
+#install-exec-hook:
+# @(chown root $(DESTDIR)$(bindir)/artswrapper && chmod 4755 $(DESTDIR)$(bindir)/artswrapper) \
+# || echo "please make $(DESTDIR)$(bindir)/artswrapper suid root"
+
+######## install idl typeinfo files
+
+mcoptypedir = $(libdir)/mcop
+mcoptype_DATA = soundserver.mcoptype soundserver.mcopclass \
+ kmedia2.mcoptype kmedia2.mcopclass
diff --git a/soundserver/WavPlayObject.mcopclass b/soundserver/WavPlayObject.mcopclass
new file mode 100644
index 0000000..1f25805
--- /dev/null
+++ b/soundserver/WavPlayObject.mcopclass
@@ -0,0 +1,7 @@
+Interface=Arts::WavPlayObject,Arts::PlayObject,Arts::PlayObject_private,Arts::SynthModule,Arts::Object
+Author="Stefan Westerfeld <stefan@space.twc.de>"
+URL="http://www.arts-project.org"
+Extension=wav
+Language=C++
+Library=libartswavplayobject.la
+MimeType=audio/wav,audio/x-wav
diff --git a/soundserver/artscat.cc b/soundserver/artscat.cc
new file mode 100644
index 0000000..28b1aaf
--- /dev/null
+++ b/soundserver/artscat.cc
@@ -0,0 +1,244 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "soundserver.h"
+#include "stdsynthmodule.h"
+#include "artsversion.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
+using namespace Arts;
+
+int cfgSamplingRate = 44100;
+int cfgBits = 16;
+int cfgChannels = 2;
+string cfgTitle = "artscat";
+
+class Sender : public ByteSoundProducerV2_skel,
+ public StdSynthModule,
+ public IONotify
+{
+protected:
+ FILE *pfile;
+ int pfd;
+ int packets;
+ bool waiting;
+ queue< DataPacket<mcopbyte>* > wqueue;
+public:
+ Sender(FILE *input,float minStreamBufferTime) : pfile(input), waiting(false)
+ {
+ pfd = fileno(pfile);
+
+ int rc = fcntl(pfd, F_SETFL, O_NONBLOCK);
+ assert(rc != -1);
+
+ /*
+ * calculate stream buffer parameters
+ */
+ float streamBufferTime;
+ packets = 7;
+ do {
+ packets++;
+ streamBufferTime = (float)(packets * packetCapacity * 1000)
+ / (float)(samplingRate() * channels() * 2);
+ } while(streamBufferTime < minStreamBufferTime);
+ }
+
+ ~Sender()
+ {
+ if(waiting) Dispatcher::the()->ioManager()->remove(this,IOType::read);
+ }
+
+ long samplingRate() { return cfgSamplingRate; }
+ long channels() { return cfgChannels; }
+ long bits() { return cfgBits; }
+ bool finished() { return (pfile == 0); }
+ string title() { return cfgTitle; }
+
+ void streamStart()
+ {
+ /*
+ * start streaming
+ */
+ outdata.setPull(packets, packetCapacity);
+ }
+
+ enum { packetCapacity = 4096 };
+ void handle_eof()
+ {
+ /*
+ * cleanup
+ */
+ outdata.endPull();
+ pclose(pfile);
+ pfile = 0;
+ pfd = 0;
+
+ /*
+ * remove all packets from the wqueue
+ */
+ while(!wqueue.empty())
+ {
+ DataPacket<mcopbyte> *packet = wqueue.front();
+ packet->size = 0;
+ packet->send();
+ wqueue.pop();
+ }
+
+ /*
+ * go out of the waiting mode
+ */
+ if(waiting)
+ {
+ Dispatcher::the()->ioManager()->remove(this,IOType::read);
+ waiting = false;
+ }
+
+ /*
+ * terminate dispatcher to end the program
+ */
+ Dispatcher::the()->terminate();
+ }
+ void request_outdata(DataPacket<mcopbyte> *packet)
+ {
+ if(!waiting)
+ {
+ packet->size = read(pfd, packet->contents, packetCapacity);
+ if(packet->size > 0)
+ {
+ // got something - done here
+ packet->send();
+ return;
+ }
+ Dispatcher::the()->ioManager()->watchFD(pfd,IOType::read,this);
+ waiting = true;
+ }
+
+ wqueue.push(packet);
+ }
+
+ void notifyIO(int,int)
+ {
+ assert(waiting);
+
+ DataPacket<mcopbyte> *packet = wqueue.front();
+ packet->size = read(pfd, packet->contents, packetCapacity);
+ assert(packet->size >= 0);
+ if(packet->size == 0) {
+ handle_eof();
+ return;
+ }
+ packet->send();
+
+ wqueue.pop();
+
+ if(wqueue.empty())
+ {
+ Dispatcher::the()->ioManager()->remove(this,IOType::read);
+ waiting = false;
+ }
+ }
+};
+
+static void exitUsage(const char *progname)
+{
+ fprintf(stderr,"usage: %s [ options ] [ <filename> ]\n",progname);
+ fprintf(stderr,"-r <samplingrate> set samplingrate to use\n");
+ fprintf(stderr,"-b <bits> set number of bits (8 or 16)\n");
+ fprintf(stderr,"-c <channels> set number of channels (1 or 2)\n");
+ fprintf(stderr,"-t <title> set stream title\n");
+ fprintf(stderr,"-v show version\n");
+ fprintf(stderr,"-h display this help and exit\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ bool titleSetByUser = false;
+ int optch;
+ while((optch = getopt(argc,argv,"r:b:c:t:hv")) > 0)
+ {
+ switch(optch)
+ {
+ case 'r':
+ cfgSamplingRate = atoi(optarg);
+ break;
+ case 'b':
+ cfgBits = atoi(optarg);
+ break;
+ case 'c':
+ cfgChannels = atoi(optarg);
+ break;
+ case 't':
+ cfgTitle = optarg;
+ titleSetByUser = true;
+ break;
+ case 'v':
+ printf("artscat %s\n",ARTS_VERSION);
+ exit(0);
+ break;
+ case 'h':
+ default:
+ exitUsage(argc?argv[0]:"artscat");
+ break;
+ }
+ }
+
+ FILE *infile = stdin;
+
+ if (optind < argc)
+ {
+ string filename = argv[optind];
+ if(filename != "-")
+ {
+ infile = fopen(filename.c_str(),"r");
+ if(!infile)
+ {
+ cerr << "Can't open file '" << argv[optind] << "'." << endl;
+ exit(1);
+ }
+ if(!titleSetByUser) cfgTitle = filename;
+ }
+ }
+ Dispatcher dispatcher;
+ SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer"));
+
+ if(server.isNull())
+ {
+ cerr << "Can't connect to sound server" << endl;
+ return 1;
+ }
+
+ ByteSoundProducerV2 sender = ByteSoundProducerV2::_from_base(new Sender(infile,server.minStreamBufferTime()));
+ server.attach(sender);
+ sender.start();
+ dispatcher.run();
+ server.detach(sender);
+}
diff --git a/soundserver/artsd.cc b/soundserver/artsd.cc
new file mode 100644
index 0000000..e02529e
--- /dev/null
+++ b/soundserver/artsd.cc
@@ -0,0 +1,376 @@
+ /*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+ 2003 Arnold Krille <arnold@arnoldarts.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "mcoputils.h"
+#include <signal.h>
+#include <math.h>
+#include <iostream>
+#include <cstring>
+#include <cstdlib>
+#include <stdio.h>
+#include "soundserver.h"
+#include "audiosubsys.h"
+#include "audioio.h"
+#include "tcpserver.h"
+#include "cpuusage.h"
+#include "debug.h"
+#include "artsversion.h"
+#include "crashhandler.h"
+
+using namespace std;
+using namespace Arts;
+
+extern "C" void stopServer(int)
+{
+ Dispatcher::the()->terminate();
+}
+
+static void initSignals()
+{
+ signal(SIGHUP ,stopServer);
+ signal(SIGINT ,stopServer);
+ signal(SIGTERM,stopServer);
+}
+
+static void exitUsage(const char *progname)
+{
+ fprintf(stderr,"usage: %s [ options ]\n",progname);
+ fprintf(stderr,"\n");
+ fprintf(stderr,"server/network options:\n");
+ fprintf(stderr,"-n enable network transparency\n");
+ fprintf(stderr,"-p <port> set TCP port to use (implies -n)\n");
+ fprintf(stderr,"-u public, no authentication (dangerous!)\n");
+ fprintf(stderr,"-N use larger network buffers\n");
+ fprintf(stderr,"-w <n> increase network buffers by factor of <n>\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"audio options:\n");
+ fprintf(stderr,"-a <audioiomethod> select audio i/o method (oss, alsa, ...)\n");
+ fprintf(stderr,"-r <samplingrate> set samplingrate to use\n");
+ fprintf(stderr,"-b <bits> set number of bits (8 or 16)\n");
+ fprintf(stderr,"-d enable full duplex operation\n");
+ fprintf(stderr,"-V <volume>[dB] set output volume\n");
+ fprintf(stderr,"-D <devicename> audio device (usually /dev/dsp)\n");
+ fprintf(stderr,"-F <fragments> number of fragments\n");
+ fprintf(stderr,"-S <size> fragment size in bytes\n");
+ fprintf(stderr,"-s <seconds> auto-suspend time in seconds\n");
+ fprintf(stderr,"-f force starting artsd (if no soundcard is there, uses the null output device)\n");
+ fprintf(stderr,"\n");
+ fprintf(stderr,"misc options:\n");
+ fprintf(stderr,"-h display this help and exit\n");
+ fprintf(stderr,"-A list possible audio i/o methods (for -a)\n");
+ fprintf(stderr,"-v show version\n");
+ fprintf(stderr,"-l <level> information level\n");
+ fprintf(stderr," 3: quiet, 2: warnings, 1: info, 0: debug\n");
+ fprintf(stderr,"-m <appName> application to display messages\n");
+ fprintf(stderr,"-c <appName> application to display crash dialogs\n");
+ exit(1);
+}
+
+static void exitListAudioIO()
+{
+ fprintf(stderr,"possible choices for the audio i/o method:\n");
+ fprintf(stderr,"\n");
+
+ for(int i = 0; i < AudioIO::queryAudioIOCount(); i++)
+ {
+ fprintf(stderr, " %-10s%s\n",
+ AudioIO::queryAudioIOParamStr(i, AudioIO::name),
+ AudioIO::queryAudioIOParamStr(i, AudioIO::fullName));
+ }
+ fprintf(stderr,"\n");
+ exit(0);
+}
+
+static Dispatcher::StartServer cfgServers = Dispatcher::startUnixServer;
+static int cfgSamplingRate = 0;
+static int cfgBits = 0;
+static int cfgFragmentCount= 0;
+static int cfgFragmentSize = 0;
+static int cfgPort = 0;
+static int cfgDebugLevel = 2;
+static const char *cfgDebugApp = 0;
+static const char *cfgCrashApp = 0;
+static bool cfgFullDuplex = 0;
+static bool cfgForceStart = 0;
+static const char *cfgDeviceName = 0;
+#if defined(__osf__)
+// osf/1 does not have sound devices so avoid the default auto-detect
+static const char *cfgAudioIO = "null";
+#else
+static const char *cfgAudioIO = 0;
+#endif
+static int cfgAutoSuspend = 0;
+static int cfgBuffers = 0;
+static float cfgVolume = 0.0;
+
+static bool cmdListAudioIO = false;
+
+static void handleArgs(int argc, char **argv)
+{
+ int optch;
+ while((optch = getopt(argc,argv,"r:p:nuF:S:hD:dl:a:Ab:s:m:vNw:fV:c:")) > 0)
+ {
+ switch(optch)
+ {
+ case 'p': cfgPort = atoi(optarg); // setting a port => network transparency
+ case 'n': cfgServers = static_cast<Dispatcher::StartServer>( cfgServers | Dispatcher::startTCPServer);
+ break;
+ case 'a': cfgAudioIO = optarg;
+ break;
+ case 'r': cfgSamplingRate = atoi(optarg);
+ break;
+ case 'b': cfgBits = atoi(optarg);
+ break;
+ case 's': cfgAutoSuspend = atoi(optarg);
+ break;
+ case 'F': cfgFragmentCount = atoi(optarg);
+ break;
+ case 'S': cfgFragmentSize = atoi(optarg);
+ break;
+ case 'D': cfgDeviceName = optarg;
+ break;
+ case 'd': cfgFullDuplex = true;
+ break;
+ case 'l': cfgDebugLevel = atoi(optarg);
+ break;
+ case 'm': cfgDebugApp = optarg;
+ break;
+ case 'c': cfgCrashApp = optarg;
+ break;
+ case 'u': cfgServers = static_cast<Dispatcher::StartServer>( cfgServers | Dispatcher::noAuthentication);
+ break;
+ case 'A': cmdListAudioIO = true;
+ break;
+ case 'v': printf("artsd %s\n",ARTS_VERSION);
+ exit(0);
+ break;
+ case 'N': cfgBuffers = 5;
+ break;
+ case 'w': cfgBuffers = atoi(optarg);
+ break;
+ case 'f': cfgForceStart = true;
+ break;
+ case 'V':
+ if ( strstr( optarg,"dB" )&& strlen( strstr( optarg,"dB" ) )==2 ) {
+ char* val = ( char* )calloc( strlen( optarg )-1, sizeof( char ) );
+ strncpy( val, optarg, strlen( optarg )-2 );
+ cfgVolume = pow( 10, atof( val )/20.0 );
+ free( val );
+ } else cfgVolume = atof( optarg );
+ break;
+ case 'h':
+ default:
+ exitUsage(argc?argv[0]:"artsd");
+ break;
+ }
+ }
+}
+
+static bool publishReferences(SoundServerV2 server,
+ AudioManager audioManager,
+ bool silent)
+{
+ ObjectManager *om = ObjectManager::the();
+ bool result;
+
+ result=om->addGlobalReference(server,"Arts_SoundServerV2")
+ && om->addGlobalReference(server,"Arts_SoundServer")
+ && om->addGlobalReference(server,"Arts_SimpleSoundServer")
+ && om->addGlobalReference(server,"Arts_PlayObjectFactory")
+ && om->addGlobalReference(audioManager,"Arts_AudioManager");
+
+ if(!result && !silent)
+ {
+ cerr <<
+"Error: Can't add object reference (probably artsd is already running)."
+ << endl <<
+" If you are sure it is not already running, remove the relevant files:"
+ << endl << endl <<
+" "<< MCOPUtils::createFilePath("Arts_SoundServerV2") << endl <<
+" "<< MCOPUtils::createFilePath("Arts_SoundServer") << endl <<
+" "<< MCOPUtils::createFilePath("Arts_SimpleSoundServer") << endl <<
+" "<< MCOPUtils::createFilePath("Arts_PlayObjectFactory") << endl <<
+" "<< MCOPUtils::createFilePath("Arts_AudioManager") << endl << endl;
+ }
+ return result;
+}
+
+static int cleanReference(const string& reference)
+{
+ Object test;
+ test = Reference("global:"+reference);
+ if(test.isNull())
+ {
+ Dispatcher::the()->globalComm().erase(reference);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static void cleanUnusedReferences()
+{
+ int i = 0;
+
+ cerr << "There are already artsd objects registered, "
+ "looking if they are active..." << endl;
+
+ sleep(1); // maybe an artsd process has just started (give it some time)
+
+ i += cleanReference("Arts_SoundServerV2");
+ i += cleanReference("Arts_SoundServer");
+ i += cleanReference("Arts_SimpleSoundServer");
+ i += cleanReference("Arts_PlayObjectFactory");
+ i += cleanReference("Arts_AudioManager");
+
+ if(i)
+ cerr << "... cleaned " <<i<< " unused mcop global references." << endl;
+ cerr << endl;
+}
+
+int main(int argc, char **argv)
+{
+ handleArgs(argc, argv);
+
+ Debug::init("[artsd]", static_cast<Debug::Level>(cfgDebugLevel));
+
+ arts_debug("artsd version is %s",ARTS_VERSION);
+ if (cfgDebugApp)
+ Debug::messageApp(cfgDebugApp);
+ if (cfgCrashApp)
+ {
+ CrashHandler::setCrashHandler(CrashHandler::defaultCrashHandler);
+ CrashHandler::setCrashApp(cfgCrashApp);
+ CrashHandler::setApplicationName("artsd");
+ CrashHandler::setApplicationPath(argc ? argv[0] : "artsd");
+ CrashHandler::setApplicationVersion (ARTS_VERSION);
+ CrashHandler::setProgramName("Soundserver");
+ CrashHandler::setBugAddress("submit@bugs.kde.org");
+ }
+
+ if(cfgPort) TCPServer::setPort(cfgPort);
+
+ CPUUsage cpuUsage;
+ Dispatcher dispatcher(0,cfgServers);
+ string warnNullDevice;
+
+ initSignals();
+
+ /* execute commands, if any */
+ if(cmdListAudioIO) exitListAudioIO();
+
+ /* apply configuration */
+ if(cfgAudioIO) AudioSubSystem::the()->audioIO(cfgAudioIO);
+ if(cfgSamplingRate) AudioSubSystem::the()->samplingRate(cfgSamplingRate);
+ if(cfgFragmentCount) AudioSubSystem::the()->fragmentCount(cfgFragmentCount);
+ if(cfgFragmentSize) AudioSubSystem::the()->fragmentSize(cfgFragmentSize);
+ if(cfgFullDuplex) AudioSubSystem::the()->fullDuplex(cfgFullDuplex);
+ if(cfgDeviceName) AudioSubSystem::the()->deviceName(cfgDeviceName);
+ if(cfgBits) AudioSubSystem::the()->format(cfgBits);
+
+ SoundServerStartup startup;
+ startup.lock();
+
+ if(cfgForceStart && !AudioSubSystem::the()->check())
+ {
+ warnNullDevice = "Error while initializing the sound driver:\n";
+ warnNullDevice += AudioSubSystem::the()->error();
+ warnNullDevice += "\n\nThe sound server will continue, using the null output device.";
+
+ AudioSubSystem::the()->audioIO("null");
+ }
+
+ if(!AudioSubSystem::the()->check())
+ {
+ string msg = "Error while initializing the sound driver:\n";
+ msg += AudioSubSystem::the()->error();
+ arts_fatal("%s", msg.c_str());
+ exit(1);
+ }
+
+ /* start sound server implementation */
+ SoundServerV2 server;
+ AudioManager audioManager;
+
+ if (fabs(cfgVolume) > 1e-10)
+ server.outVolume().scaleFactor(cfgVolume);
+
+ if (cfgAutoSuspend)
+ server.autoSuspendSeconds(cfgAutoSuspend);
+
+ if (cfgBuffers)
+ server.bufferSizeMultiplier(cfgBuffers);
+
+ /* make global MCOP references available */
+ if(!publishReferences(server,audioManager,true))
+ {
+ cleanUnusedReferences();
+ if(!publishReferences(server,audioManager,false)) return 1;
+ }
+
+ startup.unlock();
+
+ /* warn if we are using the null device */
+ if (!warnNullDevice.empty())
+ {
+ /* hack to get this message to the user in any case */
+ Debug::init("[artsd]", static_cast<Debug::Level>(1));
+ arts_info("%s", warnNullDevice.c_str());
+ Debug::init("[artsd]", static_cast<Debug::Level>(cfgDebugLevel));
+ }
+
+ /* warn if there was a problem with artswrapper */
+ char *wrapper = getenv("STARTED_THROUGH_ARTSWRAPPER");
+ if (wrapper && !strcmp(wrapper, "2"))
+ arts_warning(
+ "Can't set real-time scheduling priority.\n"
+ "You need to run artswrapper as root or\n"
+ "setuid root. This means that you will\n"
+ "likely not be able to produce acceptable\n"
+ "sound (i.e. without clicks and breaks).");
+
+ if (wrapper && !strcmp(wrapper, "3"))
+ arts_warning(
+ "This system has no support for real-time\n"
+ "scheduling priority. This means that you\n"
+ "will likely not be able to produce acceptable\n"
+ "sound (i.e. without clicks and breaks).");
+
+ dispatcher.run();
+ return 0;
+}
+
+#ifdef __SUNPRO_CC
+/* See bottom of simplesoundserver_impl.cc for the reason this is here. */
+#include "simplesoundserver_impl.h"
+REGISTER_IMPLEMENTATION(SimpleSoundServer_impl);
+#include "soundserver_impl.h"
+REGISTER_IMPLEMENTATION(SoundServer_impl);
+#include "soundserverv2_impl.h"
+REGISTER_IMPLEMENTATION(SoundServerV2_impl);
+#include "soundserverstartup_impl.h"
+REGISTER_IMPLEMENTATION(SoundServerStartup_impl);
+#endif
diff --git a/soundserver/artsplay.cc b/soundserver/artsplay.cc
new file mode 100644
index 0000000..22b500a
--- /dev/null
+++ b/soundserver/artsplay.cc
@@ -0,0 +1,77 @@
+ /*
+
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+ */
+
+#include "soundserver.h"
+#include "artsversion.h"
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+/* returns the absolute path to a filename */
+static string absolutePath(const string& path)
+{
+ if(path[0] == '/') return path;
+
+ char buffer[PATH_MAX];
+ getcwd(buffer,PATH_MAX);
+
+ if(buffer[strlen(buffer)-1] == '/')
+ return buffer + path;
+ else
+ return string(buffer) + '/' + path;
+}
+
+int main(int argc, char **argv)
+{
+ if(argc != 2)
+ {
+ cerr << "usage: " << argv[0] << " <filename>" << endl;
+ return 1;
+ }
+ if(strcmp(argv[1],"-v") == 0)
+ {
+ cout << "artsplay " << ARTS_VERSION << endl;
+ return 0;
+ }
+
+ Dispatcher dispatcher;
+ SimpleSoundServer server;
+ server = Arts::Reference("global:Arts_SimpleSoundServer");
+
+ if(server.isNull())
+ {
+ cerr << "Can't connect to sound server" << endl;
+ return 1;
+ }
+ return server.play(absolutePath(argv[1])) != 0;
+}
diff --git a/soundserver/artsrec.cc b/soundserver/artsrec.cc
new file mode 100644
index 0000000..81e01fe
--- /dev/null
+++ b/soundserver/artsrec.cc
@@ -0,0 +1,194 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+ 2001 Matthias Kretz
+ kretz@kde.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "soundserver.h"
+#include "stdsynthmodule.h"
+#include "artsversion.h"
+#include "debug.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
+using namespace Arts;
+
+int cfgSamplingRate = 44100;
+int cfgBits = 16;
+int cfgChannels = 2;
+
+class Receiver : public ByteSoundReceiver_skel,
+ public StdSynthModule,
+ public IONotify
+{
+protected:
+ FILE *pfile;
+ int pfd;
+ int packets;
+ bool waiting;
+ queue< DataPacket<mcopbyte>* > wqueue;
+public:
+ Receiver(FILE *input,float minStreamBufferTime) : pfile(input), waiting(false)
+ {
+ pfd = fileno(pfile);
+
+ int rc = fcntl(pfd, F_SETFL, O_NONBLOCK);
+ assert(rc != -1);
+
+ /*
+ * calculate stream buffer parameters
+ */
+ float streamBufferTime;
+ packets = 7;
+ do {
+ packets++;
+ streamBufferTime = (float)(packets * packetCapacity * 1000)
+ / (float)(samplingRate() * channels() * 2);
+ } while(streamBufferTime < minStreamBufferTime);
+ }
+
+ ~Receiver()
+ {
+ if(waiting) Dispatcher::the()->ioManager()->remove(this,IOType::write);
+ }
+
+ long samplingRate() { return cfgSamplingRate; }
+ long channels() { return cfgChannels; }
+ long bits() { return cfgBits; }
+ bool finished() { return (pfile == 0); }
+ string title() { return "artsrec"; }
+
+ enum { packetCapacity = 4096 };
+ void process_indata(DataPacket<mcopbyte> *packet)
+ {
+ if(!waiting)
+ {
+ int size = write( pfd, packet->contents, packet->size );
+ if( size != packet->size ) {
+ arts_debug( "Not written enough" );
+ //Dispatcher::the()->ioManager()->watchFD(pfd,IOType::write,this);
+ //waiting = true;
+ }
+ packet->processed();
+ return;
+ }
+
+ wqueue.push(packet);
+ }
+
+ void notifyIO(int,int)
+ {
+#if 0
+ assert(waiting);
+
+ DataPacket<mcopbyte> *packet = wqueue.front();
+ packet->size = read(pfd, packet->contents, packetCapacity);
+ assert(packet->size >= 0);
+ if(packet->size == 0) {
+ return;
+ }
+ packet->send();
+
+ wqueue.pop();
+
+ if(wqueue.empty())
+ {
+ Dispatcher::the()->ioManager()->remove(this,IOType::write);
+ waiting = false;
+ }
+#endif
+ }
+};
+
+static void exitUsage(const char *progname)
+{
+ fprintf(stderr,"usage: %s [ options ] [ <filename> ]\n",progname);
+ fprintf(stderr,"-r <samplingrate> set samplingrate to use\n");
+ fprintf(stderr,"-b <bits> set number of bits (8 or 16)\n");
+ fprintf(stderr,"-c <channels> set number of channels (1 or 2)\n");
+ fprintf(stderr,"-v show version\n");
+ fprintf(stderr,"-h display this help and exit\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int optch;
+ while((optch = getopt(argc,argv,"r:b:c:hv")) > 0)
+ {
+ switch(optch)
+ {
+ case 'r': cfgSamplingRate = atoi(optarg);
+ break;
+ case 'b': cfgBits = atoi(optarg);
+ break;
+ case 'c': cfgChannels = atoi(optarg);
+ break;
+ case 'v':
+ printf("artsrec %s\n",ARTS_VERSION);
+ exit(0);
+ break;
+ case 'h':
+ default:
+ exitUsage(argc?argv[0]:"artsrec");
+ break;
+ }
+ }
+
+ FILE *outfile = stdout;
+
+ if (optind < argc)
+ {
+ string filename = argv[optind];
+ if(filename != "-")
+ {
+ outfile = fopen(filename.c_str(),"w");
+ if(!outfile)
+ {
+ cerr << "Can't open file '" << argv[optind] << "'." << endl;
+ exit(1);
+ }
+ }
+ }
+ Dispatcher dispatcher;
+ SimpleSoundServer server(Reference("global:Arts_SimpleSoundServer"));
+
+ if(server.isNull())
+ {
+ cerr << "Can't connect to sound server" << endl;
+ return 1;
+ }
+
+ ByteSoundReceiver receiver = ByteSoundReceiver::_from_base(new Receiver(outfile,server.minStreamBufferTime()));
+ server.attachRecorder(receiver);
+ receiver.start();
+ dispatcher.run();
+ receiver.stop();
+ server.detachRecorder(receiver);
+}
diff --git a/soundserver/artsshell.cc b/soundserver/artsshell.cc
new file mode 100644
index 0000000..21257b2
--- /dev/null
+++ b/soundserver/artsshell.cc
@@ -0,0 +1,671 @@
+/*
+
+ Copyright (C) 2000-2001 Jeff Tranter
+ tranter@kde.org
+
+ Stefan Westerfeld
+ stefan@space.twc.de
+
+ 2002 Matthias Kretz <kretz@kde.org>
+ 2003 Arnold Krille <arnold@arnoldarts.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+------------------------------------------------------------------------
+
+ artsshell - command line access to aRts functions
+
+This is a utility (similar to what was in aRts 0.3) to provide command
+line access to aRts functions.
+
+usage:
+
+artsshell [options] <command> [command-options]
+
+Options:
+
+-q - suppress all output.
+-h - display command usage.
+-v - show version.
+
+Commands:
+
+help, ?
+
+Show brief summary of commands.
+
+version
+
+Display aRts version.
+
+suspend
+
+This suspends the sound server if it is not in use. It can be useful
+when running programs that are not artsd-enabled, although in most
+cases you should try to use artsdsp first.
+
+Returns zero status if successful or if the sound server was already
+suspended, 1 if unable to connect to the sound server (e.g. it is not
+running), and 2 if unable to suspend the sound server (e.g. it is
+being used by an application). The sound server will attempt to start
+again if it receives any requests.
+
+status
+
+Display status information about the server, i.e. is it running, is it
+suspended, real-time status, etc.
+
+terminate
+
+Terminate the sound server.
+
+autosuspend <seconds>
+
+Sets the autosuspend time for the specified number of seconds. A value
+of zero disables the autosuspend feature.
+
+networkbuffers <n>
+
+When running artsd over a network connection a large buffer size is
+desirable to avoid dropouts. This command allows increasing the buffer
+size by a factor of <n> from the default.
+
+stereoeffect insert [top|bottom] <module name>
+stereoeffect remove <id>
+stereoeffect list
+
+Inserts or removes a stereo effect into the stereo effect stack. The
+list option lists all stereo effects. When inserting, returns an
+identifier that can be used for removing it. It can be installed at
+the top or the bottom (the default).
+
+e.g. stereoeffect insert bottom Arts::Synth_FREEVERB
+ stereoeffect remove 1
+ stereoeffect list
+
+midi (future)
+
+When the MIDI manager functionality is all implemented this would be a
+good place to implement the commands. Possible options include:
+
+midi list
+midi route <from> <to>
+
+execute (future)
+
+Being able to load a module into the sound server from the command
+line would be useful. The relevant code could be taken from
+artbuilder. Suggested command format:
+
+execute <module.arts>
+
+*/
+
+#include <unistd.h>
+#include <iostream>
+#include "soundserver.h"
+#include "dispatcher.h"
+#include "artsversion.h"
+#include "tradercheck.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <cstring>
+#include <math.h>
+
+bool quiet = false;
+const char *filename = 0;
+
+using namespace std;
+
+const char* commandsmessage = "\
+Commands:\n\
+ suspend - suspend sound server\n\
+ status - display sound server status information\n\
+ terminate - terminate sound server (might confuse/kill apps using it)\n\
+ autosuspend <secs> - set autosuspend time\n\
+ networkbuffers <n> - increase network buffers by a factor of <n>\n\
+ volume [<volume>] - display/set the volume of the soundserver\n\
+ volumedb [<volume>] - display/set the volume in dB (decibel).\n\
+ 6dB means amplification by 2\n\
+ Note: If you want to use negative values from the commandline\n\
+ you have to use:\n\
+ artsshell -- volumedb -NN\n\
+ since otherwise the negative value gets lost...\n\
+ stereoeffect insert [top|bottom] <name>\n\
+ - insert stereo effect\n\
+ stereoeffect remove <id>\n\
+ - remove stereo effect\n\
+ stereoeffect list - list available effects\n\
+ tradercheck - check consistency of the trader data (information\n\
+ stored in mcopclass/mcoptype files)\n\
+ traderquery [ <requirement1> <requirement2> ... <requirementN> ]\n\
+ - query the trader for implementations with given requirements\n\
+ version - show sound server version\n\
+ help, ? - show commands\n";
+
+void help()
+{
+ cout << commandsmessage << endl;
+}
+
+// Display command usage and exit
+void usage()
+{
+ cerr <<
+"usage: artsshell [options] <command> [command-options]\n\
+\n\
+Options:\n\
+ -q - suppress all output\n\
+ -h - display command usage\n\
+ -v - show version\n\
+ -f <filename> - execute commands from <filename>\n\n" << commandsmessage << endl;
+ exit(0);
+}
+
+// Parse command line options
+void parseOptions(int argc, char **argv)
+{
+ int optch;
+
+ if (argc == 0)
+ usage();
+
+ while((optch = getopt(argc, argv, "qhvf:1234567890")) > 0)
+ {
+ switch(optch)
+ {
+ case 'q': quiet = true;
+ break;
+ case 'v':
+ printf("artsshell %s\n", ARTS_VERSION);
+ exit(0);
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+}
+
+
+// Suspend sound server, if possible
+int suspend(Arts::SoundServer server)
+{
+ switch (server.secondsUntilSuspend())
+ {
+ case 0:
+ if (!quiet)
+ cerr << "sound server was already suspended" << endl;
+ return 0;
+ break;
+
+ case -1:
+ if (!quiet)
+ cerr << "sound server is busy" << endl;
+ return 2;
+ break;
+
+ default:
+ if (server.suspend() == true)
+ {
+ if (!quiet)
+ cerr << "sound server suspended" << endl;
+ return 0;
+ } else {
+ if (!quiet)
+ cerr << "unable to suspend sound server" << endl;
+ return 2;
+ }
+ }
+ return 0;
+}
+
+
+// Display server status information
+void status(Arts::SoundServerV2 server)
+{
+ Arts::RealtimeStatus rtStatus = server.realtimeStatus();
+ long seconds = server.secondsUntilSuspend();
+
+ cout << "server status: ";
+ switch (seconds)
+ {
+ case -1:
+ cout << "busy" << endl;
+ break;
+ case 0:
+ cout << "suspended" << endl;
+ break;
+ case -2:
+ cout << "running, autosuspend disabled" << endl;
+ break;
+ default:
+ cout << "running, will suspend in " << seconds << " s" << endl;
+ }
+
+ cout << "real-time status: ";
+ switch (rtStatus)
+ {
+ case Arts::rtRealtime:
+ cout << "real-time" << endl;
+ break;
+ case Arts::rtNoSupport:
+ cout << "no real-time support" << endl;
+ break;
+ case Arts::rtNoWrapper:
+ cout << "not started through real-time wrapper" << endl;
+ break;
+ case Arts::rtNoRealtime:
+ cout << "not real-time" << endl;
+ break;
+ default:
+ cout << "unknown" << endl;
+ break;
+ }
+
+ cout << "server buffer time: " << server.serverBufferTime() << " ms" << endl;
+ cout << "buffer size multiplier: " << server.bufferSizeMultiplier() << endl;
+ cout << "minimum stream buffer time: " << server.minStreamBufferTime() << " ms" << endl;
+ cout << "auto suspend time: " << server.autoSuspendSeconds() << " s" << endl;
+ cout << "audio method: " << server.audioMethod() << endl;
+ cout << "sampling rate: " << server.samplingRate() << endl;
+ cout << "channels: " << server.channels() << endl;
+ cout << "sample size: " << server.bits() << " bits" << endl;
+
+ if (server.fullDuplex())
+ cout << "duplex: full" << endl;
+ else
+ cout << "duplex: half" << endl;
+ cout << "device: " << server.audioDevice() << endl;
+ cout << "fragments: " << server.fragments() << endl;
+ cout << "fragment size: " << server.fragmentSize() << endl;
+}
+
+// terminate the sound server
+void terminate(Arts::SoundServer server)
+{
+ if(server.terminate())
+ {
+ cout << "sound server terminated" << endl;
+ return;
+ }
+ else
+ {
+ cout << "there were problems terminating the sound server" << endl;
+ return;
+ }
+}
+
+
+// set autosuspend time
+void autosuspend(Arts::SoundServerV2 server, int secs)
+{
+ server.autoSuspendSeconds(secs);
+}
+
+// set network buffers size
+void networkBuffers(Arts::SoundServerV2 server, int n)
+{
+ if (n > 0)
+ server.bufferSizeMultiplier(n);
+}
+
+// set the output volume
+void setVolume(Arts::SoundServerV2 server, float volume)
+{
+ server.outVolume().scaleFactor(volume);
+}
+
+// return the output volume
+float getVolume(Arts::SoundServerV2 server)
+{
+ return server.outVolume().scaleFactor();
+}
+
+// set the output volume in dB
+void setDecibelVolume( Arts::SoundServerV2 server, float volume )
+{
+ setVolume( server, pow( 10, volume/20 ) );
+}
+
+// get the output volume in dB
+float getDecibelVolume( Arts::SoundServerV2 server )
+{
+ return 20*log10( getVolume( server ) );
+}
+
+// stereoeffect command
+void stereoEffect(Arts::SoundServerV2 server, int argc, char **argv)
+{
+ // stereoeffect list
+ if (!strcmp(argv[0], "list"))
+ {
+ Arts::TraderQuery query = Arts::DynamicCast( server.createObject( "Arts::TraderQuery" ) );
+ if( query.isNull() )
+ {
+ cerr << "unable to create a query" << endl;
+ return;
+ }
+ query.supports("Interface", "Arts::StereoEffect");
+ vector<Arts::TraderOffer> *offers = query.query();
+ vector<Arts::TraderOffer>::iterator i;
+ for (i = offers->begin(); i != offers->end(); i++)
+ cout << i->interfaceName() << endl;
+ delete offers;
+ return;
+ }
+
+ // stereoeffect insert [top|bottom] <module name>
+ if (!strcmp(argv[0], "insert"))
+ {
+ if (argc < 2 || argc > 3)
+ {
+ cerr << "invalid arguments" << endl;
+ return;
+ }
+
+ bool bottom = true;
+ if (argc == 3)
+ {
+ if (!strcmp(argv[1], "bottom"))
+ bottom = true;
+ else if (!strcmp(argv[1], "top"))
+ bottom = false;
+ else
+ {
+ cerr << "invalid arguments" << endl;
+ return;
+ }
+ }
+
+ char *name;
+ if (argc == 2)
+ name = argv[1];
+ else
+ name = argv[2];
+
+ // first check if the interface exists using the Trader
+ Arts::TraderQuery query = Arts::DynamicCast( server.createObject( "Arts::TraderQuery" ) );
+ if( query.isNull() )
+ {
+ cerr << "unable to create a query" << endl;
+ return;
+ }
+ query.supports("Interface", name);
+ vector<Arts::TraderOffer> *offers = query.query();
+ if (offers->empty())
+ {
+ cerr << "no such interface: " << name << endl;
+ delete offers;
+ return;
+ }
+ delete offers;
+
+ Arts::Object obj = (server.createObject(name));
+ if (obj.isNull())
+ {
+ cerr << "unable to create: " << name << endl;
+ return;
+ }
+ Arts::StereoEffect effect = Arts::DynamicCast(obj);
+ if (effect.isNull())
+ {
+ cerr << "unable to load effect: " << name << endl;
+ return;
+ }
+ effect.start();
+ Arts::StereoEffectStack effectstack = server.outstack();
+ long id;
+ if (bottom)
+ id = effectstack.insertBottom(effect, name);
+ else
+ id = effectstack.insertTop(effect, name);
+ cout << id << endl;
+ return;
+ }
+
+ // stereoeffect remove <id>
+ if (!strcmp(argv[0], "remove"))
+ {
+ if (argc != 2)
+ {
+ cerr << "invalid arguments" << endl;
+ return;
+ }
+ Arts::StereoEffectStack effectstack = server.outstack();
+ long id = atoi(argv[1]);
+ effectstack.remove(id);
+ return;
+ }
+
+ cerr << "invalid arguments" << endl;
+}
+
+// traderquery command
+void traderQuery(Arts::SoundServerV2 server, int argc, char **argv)
+{
+ Arts::TraderQuery query = Arts::DynamicCast( server.createObject( "Arts::TraderQuery" ) );
+ if( query.isNull() )
+ {
+ cerr << "unable to create a query" << endl;
+ return;
+ }
+
+ for(int i=0;i<argc;i++)
+ {
+ char *buffer = strdup(argv[i]);
+ char *key = strtok(buffer,"=");
+ char *value = strtok(0,"\n");
+
+ query.supports(key, value);
+ }
+ vector<Arts::TraderOffer> *offers = query.query();
+ vector<Arts::TraderOffer>::iterator i;
+ for (i = offers->begin(); i != offers->end(); i++)
+ cout << i->interfaceName() << endl;
+ delete offers;
+}
+
+// tradercheck command
+void traderCheck()
+{
+ Arts::TraderCheck check;
+ check.run();
+}
+
+void version()
+{
+ cout << "aRts version " << ARTS_VERSION << endl;
+}
+
+int executeCommand(Arts::SoundServerV2 server, int argc, char **argv)
+{
+ if (!strcmp(argv[0], "help") || !strcmp(argv[0], "?")) {
+ help();
+ return 0;
+ }
+
+ if (!strcmp(argv[0], "version")) {
+ version();
+ return 0;
+ }
+
+ if (!strcmp(argv[0], "suspend")) {
+ suspend(server);
+ return 0;
+ }
+
+ if (!strcmp(argv[0], "status")) {
+ status(server);
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "terminate")) {
+ terminate(server);
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "volume") && (argc == 2)) {
+ setVolume(server,atof(argv[1]));
+ return 0;
+ }
+ if(!strcmp(argv[0], "volume") && (argc == 1)) {
+ cout << getVolume(server) << endl;;
+ return 0;
+ }
+
+ if ( !strcmp( argv[ 0 ],"volumedb" ) && ( argc==2 ) ) {
+ setDecibelVolume( server, atof( argv[ 1 ] ) );
+ return 0;
+ }
+ if ( !strcmp( argv[ 0 ],"volumedb" ) && ( argc==1 ) ) {
+ cout << getDecibelVolume( server ) << endl;
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "cpuusage") && (argc == 1)) {
+ printf("%.1f\n",server.cpuUsage());
+ return 0;
+ }
+
+
+ if(!strcmp(argv[0], "autosuspend") && (argc == 2)) {
+ int secs = atoi(argv[1]);
+ autosuspend(server, secs);
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "networkbuffers") && (argc == 2)) {
+ int n = atoi(argv[1]);
+ networkBuffers(server, n);
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "stereoeffect") && (argc >= 2)) {
+ stereoEffect(server, argc-1, &argv[1]);
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "traderquery")) {
+ traderQuery(server, argc-1, &argv[1]);
+ return 0;
+ }
+
+ if(!strcmp(argv[0], "tradercheck")) {
+ traderCheck();
+ return 0;
+ }
+
+ return -1;
+}
+
+int execute(Arts::SoundServerV2 server, const char *filename)
+{
+ char command[1024];
+ FILE *input = stdin;
+ bool prompt;
+
+ if(filename)
+ {
+ input = fopen(filename,"r");
+ if(!input)
+ {
+ printf("can't open file '%s'\n", filename);
+ return 1;
+ }
+ }
+
+ prompt = isatty(fileno(input));
+
+ if(prompt)
+ {
+ printf("> ");
+ fflush(stdout);
+ }
+
+ while(fgets(command, 1024, input) != 0)
+ {
+ char **argv = 0;
+ int argc = 0;
+ while(char *arg = strtok(argc?0:command, " \t\n"))
+ {
+ argv = (char **)realloc(argv, sizeof(char *)*(argc+1));
+ argv[argc++] = arg;
+ }
+ if (argv != 0)
+ {
+ if (executeCommand(server, argc, argv) == -1)
+ cerr << "Invalid command, type 'help' for a list of commands." << endl;
+ free(argv);
+ }
+
+ if(prompt)
+ {
+ printf("> ");
+ fflush(stdout);
+ }
+ }
+
+ if(prompt)
+ printf("\n");
+
+ if(input != stdin)
+ fclose(input);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ Arts::Dispatcher dispatcher;
+ Arts::SoundServerV2 server(Arts::Reference("global:Arts_SoundServer"));
+
+ parseOptions(argc, argv);
+
+ if (server.isNull())
+ {
+ if (!quiet)
+ cerr << "unable to connect to sound server" << endl;
+ exit(1);
+ }
+
+ if (argc == optind)
+ return execute (server, filename);
+
+ if (executeCommand (server, argc-optind, &argv[optind]) == -1)
+ usage();
+
+ return 0;
+}
+
+// vim: sw=4 ts=4
diff --git a/soundserver/artsversion-new.h.in b/soundserver/artsversion-new.h.in
new file mode 100644
index 0000000..6c87684
--- /dev/null
+++ b/soundserver/artsversion-new.h.in
@@ -0,0 +1,31 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_VERSION
+
+/* version information for all aRts utilities and programs */
+#define ARTS_MAJOR_VERSION (@ARTS_MAJOR_VERSION@)
+#define ARTS_MINOR_VERSION (@ARTS_MINOR_VERSION@)
+#define ARTS_MICRO_VERSION (@ARTS_MICRO_VERSION@)
+#define ARTS_VERSION ("@ARTS_VERSION@")
+
+#endif
diff --git a/soundserver/artswrapper.c b/soundserver/artswrapper.c
new file mode 100644
index 0000000..53cc56a
--- /dev/null
+++ b/soundserver/artswrapper.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+ * adjust_priority
+ *
+ * sets realtime priority
+ */
+
+#include "config.h"
+
+#ifdef HAVE_REALTIME_SCHED
+#include <sched.h>
+
+void adjust_priority()
+{
+ int sched = sched_getscheduler(0);
+ if(sched == SCHED_FIFO || sched == SCHED_RR)
+ {
+ printf(">> since the scheduling policy is not standard, I assume\n");
+ printf(" it has been adjusted to fit the needs of realtime audio\n");
+ }
+ else
+ {
+ struct sched_param sp;
+ long priority = (sched_get_priority_max(SCHED_FIFO) +
+ sched_get_priority_min(SCHED_FIFO))/2;
+
+ sp.sched_priority = priority;
+
+ if(sched_setscheduler(0, SCHED_FIFO, &sp) != -1)
+ {
+ printf(">> running as realtime process now (priority %ld)\n",
+ priority);
+ putenv("STARTED_THROUGH_ARTSWRAPPER=1");
+ }
+ else
+ {
+ /* can't set realtime priority */
+ putenv("STARTED_THROUGH_ARTSWRAPPER=2");
+ }
+ }
+}
+#else
+void adjust_priority()
+{
+ int prio;
+
+ prio = getpriority(PRIO_PROCESS,getpid());
+ if(prio > -10)
+ {
+ setpriority(PRIO_PROCESS,getpid(),-17);
+ prio = getpriority(PRIO_PROCESS,getpid());
+ }
+
+ /* no system support for realtime priority */
+ putenv("STARTED_THROUGH_ARTSWRAPPER=3");
+
+ if(prio > -10) {
+ printf(">> synthesizer priority is %d (which is unacceptable,",prio);
+ printf(" try running as root)\n");
+ }
+ else {
+ printf(">> synthesizer priority is %d (which is the best\n",prio);
+ printf(" we can get out of a non realtime system)\n");
+ }
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ if(argc == 2)
+ {
+ if(strcmp(argv[1],"check") == 0)
+ {
+ /* backward compatibility with old artswrapper */
+ printf("okay\n");
+ return 0;
+ }
+ }
+
+ adjust_priority();
+
+ /* drop root privileges if running setuid root
+ (due to realtime priority stuff) */
+ if (geteuid() != getuid())
+ {
+#if defined (HAVE_SETEUID) && !defined (HAVE_SETEUID_FAKE)
+ seteuid(getuid());
+#else
+ setreuid(-1, getuid());
+#endif
+ if (geteuid() != getuid()) {
+ perror("setuid()");
+ return 2;
+ }
+ }
+
+ if(argc == 0)
+ return 1;
+
+/*
+ * Real-time status is passed to artsd via the environment variable
+ * STARTED_THROUGH_ARTSWRAPPER. It has one of the following values:
+ *
+ * unset - not running as real-time
+ * 1 - running as real-time
+ * 2 - no privileges to set real-time scheduling
+ * 3 - no support for real-time scheduling
+ */
+ argv[0] = EXECUTE;
+ execv(EXECUTE,argv);
+ perror(EXECUTE);
+ return 1;
+}
diff --git a/soundserver/cpuusage.cc b/soundserver/cpuusage.cc
new file mode 100644
index 0000000..6c5dd47
--- /dev/null
+++ b/soundserver/cpuusage.cc
@@ -0,0 +1,137 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "cpuusage.h"
+#include "dispatcher.h"
+#include "debug.h"
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <signal.h>
+
+#include <iostream>
+
+using namespace std;
+
+namespace Arts {
+
+class Benchmark
+{
+private:
+ struct timeval _start,_stop;
+public:
+ void start()
+ {
+ gettimeofday(&_start,NULL);
+ }
+ float stop()
+ {
+ gettimeofday(&_stop,NULL);
+
+ float diff = _stop.tv_sec-_start.tv_sec;
+ diff += (float)(_stop.tv_usec-_start.tv_usec)/1000000;
+ return diff;
+ }
+};
+
+class CPUUsagePrivate
+{
+public:
+ clock_t oldclock;
+ int stalled;
+ float usage;
+ Benchmark b;
+};
+
+/** signal handlers **/
+
+static CPUUsage *cpuUsage = 0;
+
+extern "C" void cpuUsageCheck(int)
+{
+ if(cpuUsage != 0)
+ cpuUsage->check();
+
+ signal(SIGALRM, cpuUsageCheck);
+}
+
+/** main stuff **/
+
+CPUUsage::CPUUsage() : d(new CPUUsagePrivate())
+{
+ d->oldclock = clock();
+ d->usage = 0;
+ d->stalled = 0;
+ d->b.start();
+ cpuUsage = this;
+
+ /* setup signal handler & timer */
+
+ struct itimerval oldvalue;
+ struct itimerval newvalue = {{ 1, 0 }, {1, 0}}; // 1 second
+
+ setitimer(ITIMER_REAL, &newvalue, &oldvalue);
+ signal(SIGALRM, cpuUsageCheck);
+}
+
+CPUUsage::~CPUUsage()
+{
+ delete d;
+ cpuUsage = 0;
+}
+
+float CPUUsage::usage()
+{
+ return d->usage;
+}
+
+void CPUUsage::check()
+{
+ float cpu_time = (clock()-d->oldclock)/(float)CLOCKS_PER_SEC;
+ float real_time = d->b.stop();
+
+ if(cpu_time > 0 && real_time > 0) // there may be wraparounds
+ {
+ d->usage = cpu_time / real_time;
+
+ if(d->usage > 0.95) // more than 95% -> not good! (probably freeze)
+ d->stalled++;
+ else
+ d->stalled=0;
+
+ // ok, cancel synthesis due to cpu overload! brutal method
+ if(d->stalled > 15)
+ arts_fatal("cpu overload, aborting");
+ }
+
+ // prepare for next checkpoint
+ d->oldclock = clock();
+ d->b.start();
+}
+
+CPUUsage *CPUUsage::the()
+{
+ return cpuUsage;
+}
+
+}
diff --git a/soundserver/cpuusage.h b/soundserver/cpuusage.h
new file mode 100644
index 0000000..764d30f
--- /dev/null
+++ b/soundserver/cpuusage.h
@@ -0,0 +1,53 @@
+ /*
+
+ Copyright (C) 2000-2002 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+
+#ifndef _arts_cpuusage_h
+#define _arts_cpuusage_h
+
+#include "iomanager.h"
+
+namespace Arts {
+class CPUUsage
+{
+private:
+ class CPUUsagePrivate *d;
+
+public:
+ CPUUsage();
+ ~CPUUsage();
+
+ static CPUUsage *the();
+
+ /**
+ * get the current CPU usage
+ */
+ float usage();
+
+ /**
+ * check the current CPU usage
+ */
+ void check();
+};
+}
+
+#endif
diff --git a/soundserver/crashhandler.cc b/soundserver/crashhandler.cc
new file mode 100644
index 0000000..d3ba374
--- /dev/null
+++ b/soundserver/crashhandler.cc
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2003 Stefan Westerfeld
+ *
+ * This code is based on code from the KDE Libraries
+ * Copyright (C) 2000 Timo Hummel <timo.hummel@sap.com>
+ * Tom Braun <braunt@fh-konstanz.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file is used to catch signals which would normally
+ * crash the application (like segmentation fault, floating
+ * point exception and such).
+ */
+
+#include <string.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "crashhandler.h"
+#include "audiosubsys.h"
+#include "debug.h"
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_REALTIME_SCHED
+#include <sched.h>
+#endif
+
+using namespace Arts;
+
+CrashHandler::HandlerType CrashHandler::_crashHandler = 0;
+const char *CrashHandler::appName = 0;
+const char *CrashHandler::appPath = 0;
+const char *CrashHandler::appVersion = 0;
+const char *CrashHandler::programName = 0;
+const char *CrashHandler::bugAddress = 0;
+const char *CrashHandler::crashApp = 0;
+
+// This function sets the function which should be responsible for
+// the application crash handling.
+void
+CrashHandler::setCrashHandler (HandlerType handler)
+{
+ if (!handler)
+ handler = SIG_DFL;
+
+ sigset_t mask;
+ sigemptyset(&mask);
+
+#ifdef SIGSEGV
+ signal (SIGSEGV, handler);
+ sigaddset(&mask, SIGSEGV);
+#endif
+#ifdef SIGFPE
+ signal (SIGFPE, handler);
+ sigaddset(&mask, SIGFPE);
+#endif
+#ifdef SIGILL
+ signal (SIGILL, handler);
+ sigaddset(&mask, SIGILL);
+#endif
+#ifdef SIGABRT
+ signal (SIGABRT, handler);
+ sigaddset(&mask, SIGABRT);
+#endif
+
+ sigprocmask(SIG_UNBLOCK, &mask, 0);
+
+ _crashHandler = handler;
+}
+
+void
+CrashHandler::defaultCrashHandler (int sig)
+{
+ // WABA: Do NOT use kdDebug() in this function because it is much too risky!
+ // Handle possible recursions
+ static int crashRecursionCounter = 0;
+ crashRecursionCounter++; // Nothing before this, please !
+
+ signal(SIGALRM, SIG_DFL);
+ alarm(3); // Kill me... (in case we deadlock in malloc)
+
+ if (crashRecursionCounter < 2) {
+ Arts::AudioSubSystem *a = Arts::AudioSubSystem::the();
+ if(a) a->emergencyCleanup();
+
+#ifdef HAVE_REALTIME_SCHED
+ struct sched_param sp;
+ sp.sched_priority = 0;
+ if (sched_setscheduler(0, SCHED_OTHER, &sp) != 0)
+ fprintf(stderr, "CrashHandler: can't stop running as realtime process (%s)\n", strerror(errno));
+#endif
+
+ crashRecursionCounter++; //
+ }
+
+ // Close all remaining file descriptors
+ struct rlimit rlp;
+ getrlimit(RLIMIT_NOFILE, &rlp);
+ for (int i = 0; i < (int)rlp.rlim_cur; i++)
+ close(i);
+
+ bool shuttingDown = false;
+
+ // don't load drkonqi during shutdown
+ if ( !shuttingDown )
+ {
+ if (crashRecursionCounter < 3)
+ {
+ if (appName)
+ {
+#ifndef NDEBUG
+ fprintf(stderr, "CrashHandler: crashing... crashRecursionCounter = %d\n", crashRecursionCounter);
+ fprintf(stderr, "CrashHandler: Application Name = %s path = %s pid = %d\n", appName ? appName : "<unknown>" , appPath ? appPath : "<unknown>", getpid());
+#else
+ fprintf(stderr, "CrashHandler: Application '%s' crashing...\n", appName ? appName : "<unknown>");
+#endif
+
+ pid_t pid = fork();
+
+ if (pid <= 0) {
+ // this code is leaking, but this should not hurt cause we will do a
+ // exec() afterwards. exec() is supposed to clean up.
+ char * argv[18]; // don't forget to update this
+ int i = 0;
+
+ // argument 0 has to be drkonqi
+ argv[i++] = strdup(crashApp);
+
+ char *display = getenv("DISPLAY");
+
+ if (display) {
+ // start up on the correct display
+ argv[i++] = strdup("-display");
+ argv[i++] = display;
+ }
+
+ // we have already tested this
+ argv[i++] = strdup("--appname");
+ argv[i++] = strdup(appName);
+
+ // only add apppath if it's not NULL
+ if (appPath) {
+ argv[i++] = strdup("--apppath");
+ argv[i++] = strdup(appPath);
+ }
+
+ // signal number -- will never be NULL
+ argv[i++] = strdup("--signal");
+ argv[i++] = arts_strdup_printf("%d", sig);
+
+ // pid number -- only include if this is the child
+ // the debug stuff will be disabled if we was not able to fork
+ if (pid == 0) {
+ argv[i++] = strdup("--pid");
+ argv[i++] = arts_strdup_printf("%d", getppid());
+ }
+
+ if (appVersion) {
+ argv[i++] = strdup("--appversion");
+ argv[i++] = strdup(appVersion);
+ }
+
+ if (programName) {
+ argv[i++] = strdup("--programname");
+ argv[i++] = strdup(programName);
+ }
+
+ if (bugAddress) {
+ argv[i++] = strdup("--bugaddress");
+ argv[i++] = strdup(bugAddress);
+ }
+
+ // NULL terminated list
+ argv[i++] = NULL;
+
+ setgid(getgid());
+ if (getuid() != geteuid())
+ setuid(getuid());
+ if (getuid() != geteuid()) {
+ perror("setuid()");
+ exit(255);
+ }
+
+ execvp(crashApp, argv);
+
+ // we could clean up here
+ // i = 0;
+ // while (argv[i])
+ // free(argv[i++]);
+ }
+ else
+ {
+
+ alarm(0); // Seems we made it....
+
+ fprintf(stderr, "ArtsCrash: ... waiting for child to exit\n");
+ // wait for child to exit
+ waitpid(pid, NULL, 0);
+ _exit(253);
+ }
+ }
+ else {
+ fprintf(stderr, "Unknown appname\n");
+ }
+ }
+
+ if (crashRecursionCounter < 4)
+ {
+ fprintf(stderr, "Unable to start %s\n", crashApp);
+ }
+ }
+
+ _exit(255);
+}
diff --git a/soundserver/crashhandler.h b/soundserver/crashhandler.h
new file mode 100644
index 0000000..a9264a1
--- /dev/null
+++ b/soundserver/crashhandler.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2003 Stefan Westerfeld
+ *
+ * This code is based on code from the KDE Libraries
+ * Copyright (C) 2000 Timo Hummel <timo.hummel@sap.com>
+ * Tom Braun <braunt@fh-konstanz.de>
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __ARTS_CRASHHANDLER_H
+#define __ARTS_CRASHHANDLER_H
+
+#include <string>
+
+namespace Arts {
+
+/**
+ * This class handles segmentation-faults.
+ * By default it displays a message-box saying the application crashed.
+ * This default can be overridden by setting a custom crash handler with
+ * setCrashHandler().
+ */
+class CrashHandler
+{
+ private: // ;o)
+ static const char *appName;
+ static const char *appPath;
+ static const char *appVersion;
+ static const char *programName;
+ static const char *bugAddress;
+ static const char *crashApp;
+
+ public:
+ /**
+ * The default crash handler.
+ * @param signal the signal number
+ */
+ static void defaultCrashHandler (int signal);
+
+ /**
+ * This function type is a pointer to a crash handler function.
+ * The function's argument is the number of the signal.
+ */
+ typedef void (*HandlerType)(int);
+
+ /**
+ * Install a function to be called in case a SIGSEGV is caught.
+ * @param handler HandlerType handler can be one of
+ * @li null in which case signal-catching is disabled
+ * (by calling signal(SIGSEGV, SIG_DFL))
+ * @li if handler is omitted the default crash handler is installed.
+ * @li an user defined function in the form:
+ * static (if in a class) void myCrashHandler(int);
+ * @param handler the crash handler
+ */
+
+ static void setCrashHandler (HandlerType handler = defaultCrashHandler);
+
+ /**
+ * Returns the installed crash handler.
+ * @return the crash handler
+ */
+ static HandlerType crashHandler() { return _crashHandler; }
+
+ /**
+ * Sets the application @p path which should be passed to
+ * Dr. Konqi, our nice crash display application.
+ * @param path the application path.
+ */
+ static void setApplicationPath (const std::string& path) { appPath = strdup(path.c_str()); }
+
+ /**
+ * Sets the application name @p name which should be passed to
+ * Dr. Konqi, our nice crash display application.
+ * @param name the name of the application, as shown in Dr. Konqi
+ */
+ static void setApplicationName (const std::string& name) { appName = strdup(name.c_str()); }
+
+ /**
+ * Sets the application version @p name which should be passed to
+ * Dr. Konqi, our nice crash display application.
+ * @param name the name of the application, as shown in Dr. Konqi
+ */
+ static void setApplicationVersion (const std::string& name) { appVersion = strdup(name.c_str()); }
+
+ /**
+ * Sets the program name @p name which should be passed to
+ * Dr. Konqi, our nice crash display application.
+ * @param name the name of the application, as shown in Dr. Konqi
+ */
+ static void setProgramName (const std::string& name) { programName = strdup(name.c_str()); }
+
+ /**
+ * Sets the bug adress name @p name which should be passed to
+ * Dr. Konqi, our nice crash display application.
+ * @param name the name of the application, as shown in Dr. Konqi
+ */
+ static void setBugAddress (const std::string& name) { bugAddress = strdup(name.c_str()); }
+
+ /**
+ * Sets the crash application @p app which will be called to
+ * handle the crash. To use Dr. Konqi (KDE), pass "drkonqi" here.
+ * @param app the name of the application that handles the crash
+ */
+ static void setCrashApp (const std::string& app) { crashApp = strdup(app.c_str()); }
+
+ protected:
+ /**
+ * Pointer to the crash handler.
+ */
+ static HandlerType _crashHandler;
+};
+
+}
+
+#endif
+
diff --git a/soundserver/fileinputstream_impl.cc b/soundserver/fileinputstream_impl.cc
new file mode 100644
index 0000000..e44faa2
--- /dev/null
+++ b/soundserver/fileinputstream_impl.cc
@@ -0,0 +1,193 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "kmedia2.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+#include <cstring>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+class FileInputStream_impl : virtual public FileInputStream_skel,
+ virtual public StdSynthModule
+{
+protected:
+ string _filename;
+ int age, fd;
+ unsigned int _size, position;
+ mcopbyte *data;
+ queue< DataPacket<mcopbyte>* > wqueue;
+
+public:
+ static const unsigned int PACKET_COUNT;
+ static const unsigned int PACKET_SIZE;
+
+ FileInputStream_impl()
+ {
+ fd = -1;
+ position = 0;
+ data = 0;
+ age = 0;
+ _size = 0;
+ }
+ ~FileInputStream_impl()
+ {
+ arts_assert(wqueue.size() == 0);
+
+ close();
+ }
+
+ void close()
+ {
+ if(data != 0)
+ {
+ munmap((char*)data, _size);
+ data = 0;
+ }
+
+ if(fd >= 0)
+ {
+ ::close(fd);
+ fd = -1;
+ }
+ }
+
+ bool open(const string& filename)
+ {
+ close();
+
+ fd = ::open(filename.c_str(), O_RDONLY);
+ if(fd < 0)
+ return false;
+
+ _size = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+
+ data = (mcopbyte *)mmap(0, _size, PROT_READ, MAP_SHARED, fd, 0);
+ if(data == 0)
+ {
+ close();
+ return false;
+ }
+
+ position = 0;
+ if(_filename != filename)
+ {
+ _filename = filename;
+ filename_changed(filename);
+ }
+ return true;
+ }
+
+ string filename() { return _filename; }
+ void filename(const string& newfilename) { open(newfilename); }
+
+ long size() { return _size; }
+ bool eof()
+ {
+ return (fd < 0 || position >= _size)
+ && (wqueue.size() == PACKET_COUNT);
+ }
+ bool seekOk() { return true; }
+
+ long seek(long newPosition)
+ {
+ arts_return_val_if_fail(fd < 0, -1);
+ arts_return_val_if_fail(newPosition < 0, -1);
+ arts_return_val_if_fail(newPosition > (long)_size, -1);
+
+ long ageBeforeSeek = age;
+ position = newPosition;
+
+ processQueue();
+ return ageBeforeSeek;
+ }
+
+ void processQueue()
+ {
+ unsigned int qsize = wqueue.size();
+
+ for(unsigned int i = 0; i < qsize; i++)
+ {
+ if(position < _size)
+ {
+ DataPacket<mcopbyte> *packet = wqueue.front();
+ wqueue.pop();
+
+ packet->size = min(PACKET_SIZE, _size - position);
+ memcpy(packet->contents, data+position, packet->size);
+ age += packet->size;
+ position += packet->size;
+ packet->send();
+ }
+ }
+ }
+
+ void request_outdata(DataPacket<mcopbyte> *packet)
+ {
+ wqueue.push(packet);
+ processQueue();
+ }
+
+ void streamStart()
+ {
+ /*
+ * start streaming
+ */
+ outdata.setPull(PACKET_COUNT, PACKET_SIZE);
+ }
+
+ void streamEnd()
+ {
+ /*
+ * end streaming
+ */
+ outdata.endPull();
+
+ while(!wqueue.empty())
+ {
+ DataPacket<mcopbyte> *packet = wqueue.front();
+ packet->size = 0;
+ packet->send();
+ wqueue.pop();
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(FileInputStream_impl);
+
+const unsigned int
+FileInputStream_impl::PACKET_COUNT = 8;
+
+const unsigned int
+FileInputStream_impl::PACKET_SIZE = 8192;
+
+}
diff --git a/soundserver/gslplayobject_impl.cc b/soundserver/gslplayobject_impl.cc
new file mode 100644
index 0000000..7781fac
--- /dev/null
+++ b/soundserver/gslplayobject_impl.cc
@@ -0,0 +1,235 @@
+ /*
+
+ Copyright (C) 2002 Hans Meine
+ hans_meine@gmx.net
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "flowsystem.h"
+#include "soundserver.h"
+#include "artsflow.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+#include <math.h>
+
+using namespace std;
+using namespace Arts;
+
+class GSLPlayObject_impl : public GSLPlayObject_skel, public StdSynthModule {
+protected:
+ DataHandlePlay leftPlay_, rightPlay_;
+ poState state_;
+ WaveDataHandle dhandle_;
+ std::string filename_;
+
+ int sampleCount()
+ {
+ if(!dhandle_.isLoaded()) return 0;
+ return dhandle_.valueCount() / dhandle_.channelCount();
+ }
+
+public:
+ /*
+ * construction, destruction
+ */
+ GSLPlayObject_impl()
+ : leftPlay_(DataHandlePlay::null()),
+ rightPlay_(DataHandlePlay::null()),
+ state_(posIdle)
+ {
+ }
+
+ float speed() { return leftPlay_.speed(); }
+ void speed(float newSpeed)
+ {
+ if(newSpeed != speed())
+ {
+ leftPlay_.speed(newSpeed);
+ if(!rightPlay_.isNull())
+ rightPlay_.speed(newSpeed);
+ speed_changed(newSpeed);
+ }
+ }
+
+ void streamStart()
+ {
+ arts_return_if_fail(dhandle_.isLoaded());
+
+ if(dhandle_.channelCount()>=2)
+ {
+ rightPlay_ = leftPlay_.clone();
+ rightPlay_.channelIndex(1);
+ }
+
+ leftPlay_.start();
+ if(!rightPlay_.isNull())
+ rightPlay_.start();
+
+ arts_debug("GSLPlayObject: streamStart(%d channels) playing %d, %d",
+ dhandle_.channelCount(),
+ leftPlay_.channelIndex(),
+ rightPlay_.isNull() ? -1 : rightPlay_.channelIndex());
+
+ _node()->virtualize("left", leftPlay_._node(), "outvalue");
+ if(dhandle_.channelCount()>=2)
+ _node()->virtualize("right", rightPlay_._node(), "outvalue");
+ else
+ _node()->virtualize("right", leftPlay_._node(), "outvalue");
+ }
+
+ void streamEnd()
+ {
+ arts_return_if_fail(dhandle_.isLoaded());
+
+ _node()->devirtualize("left", leftPlay_._node(), "outvalue");
+ if(dhandle_.channelCount()>=2)
+ _node()->devirtualize("right", rightPlay_._node(), "outvalue");
+ else
+ _node()->devirtualize("right", leftPlay_._node(), "outvalue");
+
+ leftPlay_.stop();
+ if(!rightPlay_.isNull())
+ rightPlay_.stop();
+ }
+
+ /*
+ * KMedia2 private interface
+ */
+ bool loadMedia(const std::string &filename)
+ {
+ arts_return_val_if_fail(!dhandle_.isLoaded(), false);
+
+ arts_debug("GSLPlayObject: loadMedia('%s')", filename.c_str());
+ filename_ = filename;
+ dhandle_.load(filename);
+ if(dhandle_.isLoaded())
+ {
+ leftPlay_ = dhandle_.createPlayer();
+ if(dhandle_.channelCount()>2)
+ arts_debug("GSLPlayObject: can't play more than 2 channels, "
+ "playing first two!");
+
+ leftPlay_._node()->connect("finished_changed", _node(), "done");
+ }
+ return dhandle_.isLoaded();
+ }
+
+ /*
+ * KMedia2 interface
+ */
+ std::string description()
+ {
+ return "no description available (see "__FILE__")";
+ }
+
+ poTime currentTime()
+ {
+ if(!dhandle_.isLoaded())
+ return poTime(0, 0, 0, "samples");
+
+ float timesec = leftPlay_.pos()
+ / dhandle_.channelCount()
+ / dhandle_.mixerFrequency();
+ float timems = (timesec - floor(timesec)) * 1000.0;
+
+ return poTime((long)timesec, (long)timems,
+ (long)leftPlay_.pos(), "samples");
+ }
+
+ poTime overallTime()
+ {
+ float timesec = (float)sampleCount() / dhandle_.mixerFrequency();
+ float timems = (timesec - floor(timesec)) * 1000.0;
+
+ return poTime((long)timesec, (long)timems,
+ (long)sampleCount(), "samples");
+ }
+
+ poCapabilities capabilities()
+ {
+ return static_cast<poCapabilities>(capPause | capSeek);
+ }
+
+ std::string mediaName()
+ {
+ return filename_;
+ }
+
+ poState state()
+ {
+ return state_;
+ }
+
+ bool done() { return leftPlay_.finished(); }
+ void done(bool d)
+ {
+ if(d && (state_ == posPlaying))
+ halt();
+ }
+
+ void play()
+ {
+ leftPlay_.paused(false);
+ if(!rightPlay_.isNull())
+ rightPlay_.paused(false);
+ state_ = posPlaying;
+ }
+
+ void halt()
+ {
+ leftPlay_.paused(true);
+ if(!rightPlay_.isNull())
+ rightPlay_.paused(true);
+ state_ = posIdle;
+ seek(poTime(-1, -1, 0, "samples"));
+ }
+
+ void pause()
+ {
+ leftPlay_.paused(true);
+ if(!rightPlay_.isNull())
+ rightPlay_.paused(true);
+ state_ = posPaused;
+ }
+
+ void seek(const class poTime &newTime)
+ {
+ long newsamples = -1;
+ if(newTime.seconds != -1 && newTime.ms != -1)
+ {
+ float flnewtime = (float)newTime.seconds+((float)newTime.ms/1000.0);
+ newsamples = (long)(flnewtime * dhandle_.mixerFrequency());
+ }
+ else if(newTime.custom >= 0 && newTime.customUnit == "samples")
+ {
+ newsamples = (long)newTime.custom;
+ }
+
+ if(newsamples > sampleCount())
+ newsamples = sampleCount();
+
+ if(newsamples >= 0)
+ {
+ leftPlay_.pos(newsamples * dhandle_.channelCount());
+ if(!rightPlay_.isNull())
+ rightPlay_.pos(newsamples * dhandle_.channelCount());
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(GSLPlayObject_impl);
diff --git a/soundserver/kmedia2.idl b/soundserver/kmedia2.idl
new file mode 100644
index 0000000..cdcb101
--- /dev/null
+++ b/soundserver/kmedia2.idl
@@ -0,0 +1,242 @@
+/*
+
+NEW KMedia2 layout:
+===================
+
+KMedia1 itself doesn't play anything. Instead it has a backend for every
+media type to play. It tells these backends: "start playing now", "stop
+playing now" and similar things (using libmediatool). So there is a backend
+for wave files, tacker files, midi files, etc., which all provide one
+common interface.
+
+The idea is to keep everything the old KMedia1 interface could do, but to
+move to a new IPC architecture (MCOP).
+
+That way, KMedia2 objects will be able to use the aRts streaming abilities.
+Of course, not every KMedia2 object will need these, but some of them. The
+result will be much nicer, if every of these objects can be treated in the
+standard "flow graph" way, like other aRts objects can.
+
+The ultimate media player, which KMedia2 aims to be, should play midi,
+video, audio, etc. It is about seeing a file, choosing a component which
+might be able to decode it, and play it. So it is not about starting
+the right application, but about loading the right component.
+
+This gives you the advantage that you can for instance reuse components
+even between quite different media types. It may for instance make sense
+to reuse a reverb effect to play midi, audio and video files.
+
+*/
+
+#include "artsflow.idl"
+
+module Arts {
+
+enum poState {
+ posIdle,
+ posPlaying,
+ posPaused
+};
+
+// use 2^n values here, since they can (should) be or'd together
+enum poCapabilities {
+ capSeek = 1,
+ capPause = 2
+};
+
+/**
+ * KMedia2 time information
+ *
+ * This is a time value which contains either milliseconds & seconds, or
+ * a custom unit or both. It is a flexible time base.
+ *
+ * If a value isn't there, it is set to -1.
+ */
+struct poTime {
+ /**
+ * time it takes in seconds; -1 if no clock time known
+ */
+ long seconds;
+
+ /**
+ * additional time in milliseconds (this doesn't contain all the time)
+ * -1 if no clock time known
+ */
+ long ms;
+
+ /**
+ * some custom time information
+ * -1 if no custom time known
+ */
+ float custom;
+
+ /**
+ * for instance for a tracker "pattern"
+ */
+ string customUnit;
+};
+
+/**
+ * private part of the PlayObject API (don't use)
+ */
+interface PlayObject_private {
+ /**
+ * loads a file
+ */
+ boolean loadMedia(string filename);
+};
+
+/**
+ * KMedia2 PlayObject - these can be used by Kaiman for instance
+ */
+interface PlayObject : PlayObject_private {
+ readonly attribute string description;
+ readonly attribute poTime currentTime;
+ readonly attribute poTime overallTime;
+ readonly attribute poCapabilities capabilities;
+ readonly attribute string mediaName;
+ readonly attribute poState state;
+
+ /**
+ * starts playing the media
+ */
+ void play();
+ /**
+ * seeks to a specific time
+ */
+ void seek(poTime newTime); // could be handled by setting currentTime
+ /**
+ * pauses playing the media
+ */
+ void pause();
+ /**
+ * stop playing the media. Normally this function would called stop,
+ * but the name is reserved for the start/stop mechanism of the
+ * aRts objects.
+ */
+ void halt();
+};
+
+/**
+ * use this to create new PlayObjects for media
+ */
+interface PlayObjectFactory {
+ /**
+ * creates a play object (or returns a null reference if this is not
+ * possible)
+ *
+ * @param filename the name of the file to create a play object for
+ */
+ PlayObject createPlayObject(string filename);
+};
+
+/**
+ * UNSTABLE/EXPERIMENTAL!
+ */
+interface InputStream : SynthModule {
+ /**
+ * whether the stream is at the end of the input
+ */
+ readonly attribute boolean eof;
+
+ /**
+ * total size of the stream in bytes
+ * -1: unknown
+ */
+ readonly attribute long size;
+
+ /**
+ * whether the stream can be seeked
+ */
+ readonly attribute boolean seekOk;
+
+ /**
+ * this returns the new AGE of the stream, where AGE is defined as the
+ * number of bytes that have been sent since the stream exists
+ */
+ long seek(long position);
+
+ /**
+ * the stream data
+ */
+ async out byte stream outdata;
+};
+
+/**
+ * UNSTABLE/EXPERIMENTAL! Example stream for files.
+ */
+interface FileInputStream : InputStream {
+ attribute string filename;
+
+ boolean open(string filename);
+};
+
+interface StdoutWriter : SynthModule {
+ async in byte stream indata;
+};
+
+interface StreamPlayObject : PlayObject {
+ /**
+ * prepares the playobject for the stream
+ */
+ boolean streamMedia(InputStream instream);
+
+ /**
+ * last used inputstream
+ * it should never change
+ */
+ InputStream inputStream();
+};
+
+/**
+ * Playobject with adjustable speed
+ */
+interface PitchablePlayObject {
+ /**
+ * speed relative to "original"/intended one
+ * (1.0=normal, 2.0=double ;-), 1.05=5% faster)
+ */
+ attribute float speed;
+};
+
+/**
+ * KMedia2 VideoPlayObject - new interface for video support
+ *
+ * Some of the communication is done using the X11 protocol.
+ */
+interface VideoPlayObject {
+ /**
+ * video output window (active)
+ */
+ attribute long x11WindowId;
+ /**
+ * take a snapshot and draw it onto a pixmap
+ * returns the X11 pixmap ID or -1 on error
+ */
+ long x11Snapshot();
+};
+
+/**
+ * Extended Version of PlayObjectFactory
+ */
+interface PlayObjectFactoryV2 : PlayObjectFactory {
+ /**
+ * creates a PlayObject
+ *
+ * @param url the url to create a play object for
+ * @param mimetype mimetype for the url
+ * @param createBUS specifies wheter to create the bus-uplink or not
+ */
+ PlayObject createPlayObjectForURL(string url, string mimetype, boolean createBUS);
+
+ /**
+ * creates a StreamPlayObject (used internally!)
+ *
+ * @param instream specifies the InputStream
+ * @param mimetype mimetype for the InputStream
+ * @param createBUS specifies wheter to create the bus-uplink or not
+ */
+ PlayObject createPlayObjectForStream(InputStream instream, string mimetype, boolean createBUS);
+};
+
+};
diff --git a/soundserver/samplestorage_impl.cc b/soundserver/samplestorage_impl.cc
new file mode 100644
index 0000000..8c14d23
--- /dev/null
+++ b/soundserver/samplestorage_impl.cc
@@ -0,0 +1,202 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <dirent.h>
+#include "soundserver.h"
+#include "debug.h"
+
+using namespace Arts;
+using namespace std;
+
+namespace Arts {
+
+class SampleStorageEntry_impl : public SampleStorageEntry_skel {
+protected:
+ string _name, _filename;
+ bool _completed;
+ FILE *file;
+
+public:
+ SampleStorageEntry_impl(const string& name, const string& filename)
+ {
+ _name = name;
+ _filename = filename;
+ _completed = false;
+ file = fopen(_filename.c_str(),"w");
+ }
+ ~SampleStorageEntry_impl()
+ {
+ if(file)
+ {
+ fclose(file);
+ file = 0;
+ }
+ unlink(_filename.c_str());
+ }
+
+ string name() { return _name; }
+ string filename() { return _filename; }
+ bool completed() { return _completed; }
+
+ void write(const vector<mcopbyte>& data)
+ {
+ arts_return_if_fail(file != 0);
+
+ fwrite(&data[0],1,data.size(),file);
+ }
+ void finish()
+ {
+ arts_return_if_fail(file != 0);
+
+ fclose(file);
+ file = 0;
+ _completed = true;
+ }
+};
+
+class SampleStorage_impl : public SampleStorage_skel {
+protected:
+ string directory;
+ long uniqueID;
+ vector<SampleStorageEntry> entries;
+
+public:
+ SampleStorage_impl()
+ {
+ uniqueID = 1;
+ }
+
+ void constructor(const string& newDirectory, bool clearOnInit)
+ {
+ arts_return_if_fail(directory.empty());
+
+ directory = newDirectory;
+ mkdir(directory.c_str(),0700);
+
+ if(clearOnInit) clear();
+ }
+
+ void clear()
+ {
+ DIR *dir = opendir(directory.c_str());
+ if(!dir) return;
+
+ struct dirent *de;
+ while((de = readdir(dir)) != 0)
+ {
+ string currentEntry = directory + "/" + de->d_name;
+
+ if(de->d_name[0] != '.')
+ {
+ unlink(currentEntry.c_str());
+ }
+ }
+ closedir(dir);
+ }
+
+ string encodeName(const string& name)
+ {
+ string::const_iterator i;
+ string result;
+
+ for(i = name.begin(); i != name.end(); i++)
+ {
+ unsigned char c = *i;
+
+ if ((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ c == '_' || c == '-')
+ {
+ result += c;
+ }
+ else
+ {
+ char hex[17] = "0123456789ABCDEF";
+
+ result += '=';
+ result += hex[(c >> 4) & 0xf];
+ result += hex[c & 0xf];
+ }
+ }
+ return result;
+ }
+
+ SampleStorageEntry createEntry(const string& name)
+ {
+ char uniqueprefix[32];
+ sprintf(uniqueprefix,"s%ld-",uniqueID++);
+ string filename = directory + string("/")
+ + uniqueprefix + encodeName(name);
+
+ return SampleStorageEntry::_from_base(
+ new SampleStorageEntry_impl(name, filename)
+ );
+ }
+
+ SampleStorageEntry findEntry(const string& name)
+ {
+ vector<SampleStorageEntry>::iterator i;
+
+ for(i = entries.begin(); i != entries.end(); i++)
+ if(i->name() == name) return *i;
+
+ return SampleStorageEntry::null();
+ }
+
+ void addEntry(SampleStorageEntry entry)
+ {
+ arts_return_if_fail(!entry.isNull());
+
+ /* remove the old entry for that name, if any */
+ SampleStorageEntry oldEntry = findEntry(entry.name());
+ if(!oldEntry.isNull())
+ removeEntry(oldEntry);
+
+ /* add the new entry */
+ entries.push_back(entry);
+ }
+
+ void removeEntry(SampleStorageEntry entry)
+ {
+ arts_return_if_fail(!entry.isNull());
+
+ vector<SampleStorageEntry>::iterator i;
+ for(i = entries.begin(); i != entries.end(); i++)
+ {
+ if(i->name() == entry.name())
+ {
+ entries.erase(i);
+ return;
+ }
+ }
+ arts_warning("SampleStorage::removeEntry(%s) failed\n",
+ entry.name().c_str());
+ }
+
+};
+REGISTER_IMPLEMENTATION(SampleStorage_impl);
+
+}
diff --git a/soundserver/simplesoundserver_impl.cc b/soundserver/simplesoundserver_impl.cc
new file mode 100644
index 0000000..608f146
--- /dev/null
+++ b/soundserver/simplesoundserver_impl.cc
@@ -0,0 +1,453 @@
+ /*
+
+ Copyright (C) 1999-2001 Stefan Westerfeld
+ stefan@space.twc.de
+ 2001 Matthias Kretz
+ kretz@kde.org
+ 2003 Allan Sandfeld Jensen
+ kde@carewolf.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "simplesoundserver_impl.h"
+#include "artsflow.h"
+#include "flowsystem.h"
+#include "audiosubsys.h"
+#include "connect.h"
+#include "debug.h"
+#include "reference.h"
+
+#include <stdio.h>
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+void SoundServerJob::detach(const Object&)
+{
+ // nothing by default
+}
+
+SoundServerJob::~SoundServerJob()
+{
+ // virtual destructor, since we've got virtual functions
+}
+
+PlayWavJob::PlayWavJob(const string& filename) :terminated(false)
+{
+ arts_debug("play '%s'!",filename.c_str());
+
+ connect(wav,out);
+ wav.filename(filename);
+ wav.start();
+ out.start();
+}
+
+void PlayWavJob::terminate()
+{
+ terminated = true;
+}
+
+bool PlayWavJob::done()
+{
+ return terminated || wav.finished();
+}
+
+PlayObjectJob::PlayObjectJob(PlayObject newPlob)
+ : plob(newPlob), terminated(false)
+{
+ plob.play();
+}
+
+void PlayObjectJob::terminate()
+{
+ terminated = true;
+ plob.halt();
+}
+
+bool PlayObjectJob::done()
+{
+ return terminated || (plob.state() == posIdle);
+}
+
+PlayStreamJob::PlayStreamJob(ByteSoundProducer bsp) : sender(bsp)
+{
+ int samplingRate = bsp.samplingRate();
+ int channels = bsp.channels();
+ int bits = bsp.bits();
+
+ arts_debug("incoming stream, parameters: rate=%d, %d bit, %d channels",
+ samplingRate, bits, channels);
+
+ if((samplingRate < 500 || samplingRate > 2000000)
+ || (channels != 1 && channels != 2) || (bits != 8 && bits != 16))
+ {
+ arts_warning("invalid stream parameters: rate=%d, %d bit, %d channels",
+ samplingRate, bits, channels);
+ terminate();
+ return;
+ }
+
+ convert.samplingRate(samplingRate);
+ convert.channels(channels);
+ convert.bits(bits);
+ ByteSoundProducerV2 senderv2 = DynamicCast(sender);
+ if(!senderv2.isNull())
+ out.title(senderv2.title());
+
+ connect(sender,"outdata",convert,"indata");
+ connect(convert,out);
+
+ convert.start();
+ out.start();
+}
+
+void PlayStreamJob::detach(const Object& object)
+{
+ if(object._isEqual(sender))
+ terminate();
+}
+
+void PlayStreamJob::terminate()
+{
+ sender = ByteSoundProducer::null();
+}
+
+bool PlayStreamJob::done()
+{
+ // when the sender is not alive any longer, assign a null object
+ if(!sender.isNull() && sender.error())
+ sender = ByteSoundProducer::null();
+
+ return sender.isNull() && !convert.running();
+}
+
+RecordStreamJob::RecordStreamJob(ByteSoundReceiver bsr) : receiver(bsr)
+{
+ int samplingRate = bsr.samplingRate();
+ int channels = bsr.channels();
+ int bits = bsr.bits();
+
+ arts_debug("outgoing stream, parameters: rate=%d, %d bit, %d channels",
+ samplingRate, bits, channels);
+
+ if((samplingRate < 500 || samplingRate > 2000000)
+ || (channels != 1 && channels != 2) || (bits != 8 && bits != 16))
+ {
+ arts_warning("invalid stream parameters: rate=%d, %d bit, %d channels",
+ samplingRate, bits, channels);
+ terminate();
+ return;
+ }
+
+ convert.samplingRate(samplingRate);
+ convert.channels(channels);
+ convert.bits(bits);
+ in.title(receiver.title());
+
+ connect(in,convert);
+ connect(convert,"outdata",receiver,"indata");
+
+ in.start();
+ convert.start();
+}
+
+void RecordStreamJob::detach(const Object& object)
+{
+ if(object._isEqual(receiver))
+ terminate();
+}
+
+void RecordStreamJob::terminate()
+{
+ receiver = ByteSoundReceiver::null();
+ convert.stop();
+ in.stop();
+}
+
+bool RecordStreamJob::done()
+{
+ // when the sender is not alive any longer, assign a null object
+ if(!receiver.isNull() && receiver.error())
+ receiver = ByteSoundReceiver::null();
+
+ return receiver.isNull();
+}
+
+/*
+ * ( This place where other objects for playing wave files and such will
+ * be connected, to get their output mixed with the other clients ).
+ * _____________________
+ * | soundcardBus | (a Synth_BUS_DOWNLINK for "out_soundcard")
+ * ~~~~~~~~~~~~~~~~~~~~~
+ * | |
+ * ___V____________V____
+ * | outstack | (here the user can plugin various effects)
+ * ~~~~~~~~~~~~~~~~~~~~~
+ * | |
+ * ___V____________V____
+ * | outVolume | (global output volume for the soundserver)
+ * ~~~~~~~~~~~~~~~~~~~~~
+ * | |
+ * ___V____________V____
+ * | playSound | (output to soundcard)
+ * ~~~~~~~~~~~~~~~~~~~~~
+ */
+SimpleSoundServer_impl::SimpleSoundServer_impl() : autoSuspendTime(0), bufferMultiplier(1)
+{
+ soundcardBus.busname("out_soundcard");
+ connect(soundcardBus,_outstack);
+ connect(_outstack,_outVolume);
+ connect(_outVolume,playSound);
+
+ if(AudioSubSystem::the()->fullDuplex())
+ {
+ recordBus.busname("in_soundcard");
+ connect(recordSound,recordBus);
+
+ recordBus.start();
+ recordSound.start();
+ }
+
+ soundcardBus.start();
+ _outVolume.start();
+ playSound.start();
+
+ asCount = 0; // AutoSuspend
+ Dispatcher::the()->ioManager()->addTimer(200,this);
+
+ // load Arts::MidiManager when installed
+ TraderQuery query;
+ query.supports("InterfaceName","Arts::MidiManager");
+
+ vector<TraderOffer> *offers = query.query();
+ if(offers->size())
+ _addChild(Arts::SubClass("Arts::MidiManager"),
+ "Extension_Arts::MidiManager");
+ delete offers;
+}
+
+SimpleSoundServer_impl::~SimpleSoundServer_impl()
+{
+ /*
+ * we don't need to care about the flow system nodes we started, since
+ * we have put them into Object_var's, which means that they will be
+ * freed automatically here
+ */
+ Dispatcher::the()->ioManager()->removeTimer(this);
+}
+
+long SimpleSoundServer_impl::play(const string& filename)
+{
+ PlayObject tmp( createPlayObject( filename ) );
+ if ( tmp.isNull() )
+ return 0; // No success creating the PlayObject and playing the file...
+ jobs.push_back(new PlayObjectJob(tmp));
+ return 1;
+}
+
+float SimpleSoundServer_impl::serverBufferTime()
+{
+ float hardwareBuffer = AudioSubSystem::the()->fragmentSize()
+ * AudioSubSystem::the()->fragmentCount();
+
+ float playSpeed = AudioSubSystem::the()->channels()
+ * AudioSubSystem::the()->samplingRate()
+ * (AudioSubSystem::the()->bits() / 8);
+
+ return 1000.0 * hardwareBuffer / playSpeed;
+}
+
+float SimpleSoundServer_impl::minStreamBufferTime()
+{
+ /*
+ * It is sane to assume that client side stream buffers must be >= server
+ * side hardware buffers (or it can come to dropouts during hardware
+ * buffer refill). The buffer size can be increased using the multiplier.
+ */
+ return bufferMultiplier * serverBufferTime();
+}
+
+void SimpleSoundServer_impl::attach(ByteSoundProducer bsp)
+{
+ arts_return_if_fail(!bsp.isNull());
+
+ jobs.push_back(new PlayStreamJob(bsp));
+}
+
+void SimpleSoundServer_impl::detach(ByteSoundProducer bsp)
+{
+ arts_return_if_fail(!bsp.isNull());
+ arts_debug("detach incoming stream");
+
+ list<SoundServerJob *>::iterator j;
+
+ for(j = jobs.begin();j != jobs.end();j++)
+ (*j)->detach(bsp);
+}
+
+void SimpleSoundServer_impl::attachRecorder(ByteSoundReceiver bsr)
+{
+ arts_return_if_fail(!bsr.isNull());
+ jobs.push_back(new RecordStreamJob(bsr));
+}
+
+void SimpleSoundServer_impl::detachRecorder(ByteSoundReceiver bsr)
+{
+ arts_return_if_fail(!bsr.isNull());
+ arts_debug("detach outgoing stream");
+
+ list<SoundServerJob *>::iterator j;
+
+ for(j = jobs.begin();j != jobs.end();j++)
+ (*j)->detach(bsr);
+}
+
+StereoEffectStack SimpleSoundServer_impl::outstack()
+{
+ return _outstack;
+}
+
+Object SimpleSoundServer_impl::createObject(const string& name)
+{
+ // don't use SubClass(name) as this will abort if the object is not found
+ return Object::_from_base(ObjectManager::the()->create(name));
+}
+
+void SimpleSoundServer_impl::notifyTime()
+{
+ static long lock = 0;
+ assert(!lock); // paranoid reentrancy check (remove me later)
+ lock++;
+ /*
+ * Three times the same game: look if a certain object is still
+ * active - if yes, keep, if no, remove
+ */
+
+ /* look for jobs which may have terminated by now */
+ list<SoundServerJob *>::iterator i;
+
+ i = jobs.begin();
+ while(i != jobs.end())
+ {
+ SoundServerJob *job = *i;
+
+ if(job->done())
+ {
+ delete job;
+ jobs.erase(i);
+ arts_debug("job finished");
+ i = jobs.begin();
+ }
+ else i++;
+ }
+
+/*
+ * AutoSuspend
+ */
+ if(Dispatcher::the()->flowSystem()->suspendable() &&
+ !Dispatcher::the()->flowSystem()->suspended() &&
+ autoSuspendTime != 0)
+ {
+ asCount++;
+ if(asCount > autoSuspendTime*5)
+ {
+ Dispatcher::the()->flowSystem()->suspend();
+ arts_info("sound server suspended");
+ }
+ }
+ else
+ asCount = 0;
+ lock--;
+}
+
+PlayObject SimpleSoundServer_impl::createPlayObject(const string& filename)
+{
+ string objectType = "";
+
+ /*
+ * figure out extension (as lowercased letters)
+ */
+ string extension = "";
+ bool extensionok = false;
+ string::const_reverse_iterator i;
+ for(i = filename.rbegin(); i != filename.rend() && !extensionok; i++)
+ {
+ if(*i == '.')
+ extensionok = true;
+ else
+ extension.insert(extension.begin(), (char)tolower(*i));
+ }
+
+ /*
+ * query trader for PlayObjects which support this
+ */
+ if(extensionok)
+ {
+ arts_debug("search playobject, extension = %s",extension.c_str());
+
+ TraderQuery query;
+ query.supports("Interface","Arts::PlayObject");
+ query.supports("Extension",extension);
+
+ vector<TraderOffer> *offers = query.query();
+ if(!offers->empty())
+ objectType = offers->front().interfaceName(); // first offer
+
+ delete offers;
+ }
+
+ /*
+ * create a PlayObject and connect it
+ */
+ if(!objectType.empty())
+ {
+ arts_debug("creating %s to play file %s", objectType.c_str(), filename.c_str() );
+
+ PlayObject result = SubClass(objectType);
+ if(result.loadMedia(filename))
+ {
+ // TODO: check for existence of left & right streams
+ Synth_BUS_UPLINK uplink;
+ uplink.busname("out_soundcard");
+ connect(result,"left",uplink,"left");
+ connect(result,"right",uplink,"right");
+ uplink.start();
+ result._node()->start();
+ result._addChild(uplink,"uplink");
+ return result;
+ }
+ else arts_warning("couldn't load file %s", filename.c_str());
+ }
+ else arts_warning("file format extension %s unsupported",extension.c_str());
+
+ return PlayObject::null();
+}
+
+#ifndef __SUNPRO_CC
+/* SunPRO CC has problems finding the SimpleSoundServer_impl constructor
+ implementation from a template instantiation file, if this is here,
+ although I verified that the requested and provided symbols do indeed match,
+ and the latter is global. Wonderfully this problem goes away, if we don't
+ register the implementation here, but in another file. I bet this is
+ because of the static var that is created by the macro. */
+REGISTER_IMPLEMENTATION(SimpleSoundServer_impl);
+#endif
diff --git a/soundserver/simplesoundserver_impl.h b/soundserver/simplesoundserver_impl.h
new file mode 100644
index 0000000..88a530a
--- /dev/null
+++ b/soundserver/simplesoundserver_impl.h
@@ -0,0 +1,148 @@
+ /*
+
+ Copyright (C) 1999-2000 Stefan Westerfeld
+ stefan@space.twc.de
+ 2001 Matthias Kretz
+ kretz@kde.org
+ 2003 Allan Sandfeld Jensen
+ kde@carewolf.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#ifndef SIMPLESOUNDSERVER_IMPL_H
+#define SIMPLESOUNDSERVER_IMPL_H
+
+#include "soundserver.h"
+#include "artsflow.h"
+#include <list>
+#include "arts_export.h"
+
+namespace Arts {
+
+class ARTS_EXPORT SoundServerJob
+{
+public:
+ long ID;
+ virtual ~SoundServerJob();
+
+ virtual void detach(const Object& object);
+ virtual void terminate() = 0;
+ virtual bool done() = 0;
+};
+
+class ARTS_EXPORT PlayWavJob : public SoundServerJob
+{
+protected:
+ Synth_PLAY_WAV wav;
+ Synth_AMAN_PLAY out;
+ bool terminated;
+
+public:
+ PlayWavJob(const std::string& filename);
+
+ void terminate();
+ bool done();
+};
+
+class ARTS_EXPORT PlayObjectJob : public SoundServerJob
+{
+protected:
+ PlayObject plob;
+ bool terminated;
+
+public:
+ PlayObjectJob(PlayObject newPlob);
+
+ void terminate();
+ bool done();
+};
+
+class ARTS_EXPORT PlayStreamJob : public SoundServerJob
+{
+protected:
+ ByteSoundProducer sender;
+ ByteStreamToAudio convert;
+ Synth_AMAN_PLAY out;
+
+public:
+ PlayStreamJob(ByteSoundProducer bsp);
+
+ void detach(const Object& object);
+ void terminate();
+ bool done();
+};
+
+class ARTS_EXPORT RecordStreamJob : public SoundServerJob
+{
+protected:
+ ByteSoundReceiver receiver;
+ AudioToByteStream convert;
+ Synth_AMAN_RECORD in;
+
+public:
+ RecordStreamJob(ByteSoundReceiver bsr);
+
+ void detach(const Object& object);
+ void terminate();
+ bool done();
+};
+
+class ARTS_EXPORT SimpleSoundServer_impl : virtual public SimpleSoundServer_skel,
+ public TimeNotify
+{
+protected:
+ Synth_PLAY playSound;
+ Synth_RECORD recordSound;
+ Synth_BUS_DOWNLINK soundcardBus;
+ Synth_BUS_UPLINK recordBus;
+ std::list<SoundServerJob *> jobs;
+ StereoEffectStack _outstack;
+ StereoVolumeControl _outVolume;
+ long asCount;
+ long autoSuspendTime;
+ long bufferMultiplier;
+
+public:
+ SimpleSoundServer_impl();
+ ~SimpleSoundServer_impl();
+
+ void notifyTime();
+
+ // streaming audio
+ float minStreamBufferTime();
+ float serverBufferTime();
+ void attach(ByteSoundProducer bsp);
+ void detach(ByteSoundProducer bsp);
+ void attachRecorder(ByteSoundReceiver bsr);
+ void detachRecorder(ByteSoundReceiver bsr);
+
+ // simple soundserver interface
+ long play(const std::string& s);
+
+ // kmedia2
+ PlayObject createPlayObject(const std::string& filename);
+ StereoEffectStack outstack();
+ Object createObject(const std::string& name);
+};
+
+}
+
+#endif /* SIMPLESOUNDSERVER_IMPL_H */
diff --git a/soundserver/soundserver.idl b/soundserver/soundserver.idl
new file mode 100644
index 0000000..7c2cc41
--- /dev/null
+++ b/soundserver/soundserver.idl
@@ -0,0 +1,294 @@
+#include "artsflow.idl"
+#include "kmedia2.idl"
+#include "core.idl"
+
+module Arts {
+
+/**
+ * One entry of the sample storage - initially, you'll need to fill the entry.
+ *
+ * To do so, call write repeatedly to fill it with data, and finish() when
+ * you are done. After that you can use the filename attribute to get the
+ * name of the file on the server that has stored the data. You can use
+ * this filename for other things (i.e. SimpleSoundServer::play).
+ */
+interface SampleStorageEntry {
+ readonly attribute string name;
+ readonly attribute string filename;
+ readonly attribute boolean completed;
+
+ void write(sequence<byte> data);
+ void finish();
+};
+
+/**
+ * Interface for storing files on the sound server
+ */
+interface SampleStorage {
+ void constructor(string directory, boolean clearOnInit);
+
+ /**
+ * creates a new entry which you can use to store a sample - if you just
+ * create an entry, it will be private to you, i.e. you can use it, and
+ * as soon as you don't need it any longer, it will be freed
+ *
+ * if you want that the entry stays in the storage, you need to add it,
+ * and it will stay then until you remove it
+ */
+ SampleStorageEntry createEntry(string name);
+
+ /**
+ * add an entry (which will make it accessible via findEntry) - remember
+ * to eventually call removeEntry, or the entry will stay there forever
+ */
+ void addEntry(SampleStorageEntry entry);
+
+ /**
+ * removes an entry, that is, the entry will only stay there until
+ * nobody needs it any more and then get freed
+ */
+ void removeEntry(SampleStorageEntry entry);
+
+ /**
+ * finds an entry by name
+ */
+ SampleStorageEntry findEntry(string name);
+};
+
+/**
+ * Producer of byte sound
+ *
+ * This is used inside the sound server interface
+ */
+interface ByteSoundProducer : SynthModule
+{
+ readonly attribute long samplingRate;
+ readonly attribute long channels;
+ readonly attribute long bits;
+
+ async out byte stream outdata;
+};
+
+/**
+ * V2 version of the ByteSoundProducer interface that implements the title
+ * attribute
+ */
+interface ByteSoundProducerV2 : ByteSoundProducer
+{
+ readonly attribute string title;
+};
+
+/**
+ * Receiver of byte sound
+ */
+interface ByteSoundReceiver : SynthModule
+{
+ readonly attribute long samplingRate;
+ readonly attribute long channels;
+ readonly attribute long bits;
+ readonly attribute string title;
+
+ async in byte stream indata;
+};
+
+/**
+ * This is a very simple sound server interface
+ *
+ * WARNING: This currently inherits a KMedia2 PlayObjectFactory for test
+ * purposes, but don't rely on that
+ */
+
+interface SimpleSoundServer : PlayObjectFactory
+{
+ readonly attribute StereoEffectStack outstack;
+
+ /**
+ * tries to play the sound in "filename"
+ *
+ * returns an ID when success 0 when it fails
+ */
+ long play(string filename);
+
+ /**
+ * returns true if the sound in ID is still playing
+ */
+ //boolean isPlaying(long ID);
+
+ /**
+ * stops a playing sound by ID
+ */
+ //void stop(long ID);
+
+ /**
+ * specifies the minimum amount of milliseconds that have to be buffered
+ * to allow safe streaming (without interruptions) from/to external apps
+ *
+ * this depends on the realtime parameters the sound server itself uses
+ * to talk to the hardware
+ */
+ readonly attribute float minStreamBufferTime;
+
+ /**
+ * specifies the amount of milliseconds the server itself spends with
+ * the hardware (buffering latency) - so if you stream into the server,
+ * you should have a yourStreamBufferTime >= minStreamBufferTime, and
+ * the total latency is
+ *
+ * totalLatency = yourStreamBufferTime + serverBufferTime
+ */
+ readonly attribute float serverBufferTime;
+
+ /**
+ * attaches a byte sound producer (read: a client which produces/mixes
+ * an audio stream itself and just wants playback via the soundserver)
+ */
+ void attach(ByteSoundProducer producer);
+
+ /**
+ * detaches a previous attached byte sound producer
+ */
+ void detach(ByteSoundProducer producer);
+
+ /**
+ * attaches a byte sound receiver (a client that records an
+ * audio stream from the soundserver)
+ */
+ void attachRecorder(ByteSoundReceiver receiver);
+
+ /**
+ * detaches a previous attached byte sound receiver
+ */
+ void detachRecorder(ByteSoundReceiver receiver);
+
+ object createObject(string name);
+};
+
+enum RealtimeStatus { rtRealtime, rtNoSupport, rtNoWrapper, rtNoRealtime };
+
+/**
+ * This is an enhanced sound server interface which can be used to
+ * query status information or suspend the soundserver right away
+ */
+interface SoundServer : SimpleSoundServer
+{
+ readonly attribute RealtimeStatus realtimeStatus;
+
+ /**
+ * Returns how many seconds you have to wait _now_ for the soundserver
+ * to suspend. A value of -1 signals that the sound server is busy and
+ * will not suspend automatically at the moment.
+ */
+ readonly attribute long secondsUntilSuspend;
+
+ /**
+ * Makes the soundserver suspend now _if_ it is not busy playing, that
+ * is, if it is "suspendable". Returns true if successful.
+ */
+ boolean suspend();
+
+ /**
+ * Asks the soundserver if it is suspended. Returns true if so.
+ */
+ boolean suspended();
+
+ /**
+ * Permanently terminates the sound server - this is not intended to be
+ * widely used. However, it provides a way to "kill" the sound server,
+ * even if you don't reside on the same host with it, and even if you
+ * don't know the process id, and so on. In the future it also offers
+ * the possibility for interested apps to be informed before the server
+ * goes away, and for important apps to block termination.
+ *
+ * Returns true if successful.
+ */
+ boolean terminate();
+};
+
+/**
+ * This is an even more enhanced sound server interface that supports changing
+ * the autosuspend time, and returning more information about the server
+ * settings.
+ */
+interface SoundServerV2 : SoundServer, PlayObjectFactoryV2
+{
+ /**
+ * Time in seconds after which server will suspend if idle.
+ */
+ attribute long autoSuspendSeconds;
+
+ /**
+ * Multiplier for size of network buffers. Default is 1,
+ * which is fragment size * fragment count. (expressed
+ * as milliseconds).
+ */
+ attribute long bufferSizeMultiplier;
+
+ /**
+ * Current CPU usage in percent
+ */
+ readonly attribute float cpuUsage;
+
+ /**
+ * AudioSubSystem parameters
+ */
+ readonly attribute string audioMethod;
+ readonly attribute long samplingRate;
+ readonly attribute long channels;
+ readonly attribute long bits;
+ readonly attribute boolean fullDuplex;
+ readonly attribute string audioDevice;
+ readonly attribute long fragments;
+ readonly attribute long fragmentSize;
+
+ /**
+ * version
+ */
+ readonly attribute string version;
+
+ /**
+ * global output volume for the sound server
+ */
+ readonly attribute StereoVolumeControl outVolume;
+
+ /**
+ * for storing samples on the sound server
+ */
+ readonly attribute SampleStorage sampleStorage;
+
+ /**
+ * this method checks for new object implementations (you can call this
+ * if you have implemented and installed new components in C++ or with
+ * artsbuilder, to make the soundserver use them without restart)
+ */
+ void checkNewObjects();
+};
+
+/**
+ * A KMedia2 Wave PlayObject
+ */
+interface WavPlayObject : PlayObject, SynthModule
+{
+ out audio stream left,right;
+};
+
+/**
+ * An advanced KMedia2 PlayObject based on GSL datahandles
+ */
+interface GSLPlayObject : PlayObject, PitchablePlayObject, SynthModule
+{
+ attribute boolean done;
+
+ out audio stream left,right;
+};
+
+/**
+ * Helper interface to ensure that artsd gets initialized properly when
+ * multiple artsd processes are started at the same time.
+ */
+interface SoundServerStartup
+{
+ void lock();
+ void unlock();
+};
+
+};
diff --git a/soundserver/soundserver_impl.cc b/soundserver/soundserver_impl.cc
new file mode 100644
index 0000000..26a9b1f
--- /dev/null
+++ b/soundserver/soundserver_impl.cc
@@ -0,0 +1,90 @@
+ /*
+
+ Copyright (C) 2000 Hans Meine
+ hans@meine.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "soundserver_impl.h"
+#include "artsflow.h"
+#include "flowsystem.h"
+#include "audiosubsys.h"
+#include "connect.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <iostream>
+#include <algorithm>
+
+using namespace Arts;
+
+#include "config.h"
+
+#ifdef HAVE_REALTIME_SCHED
+#include <sched.h>
+RealtimeStatus SoundServer_impl::realtimeStatus() {
+ int sched = sched_getscheduler(0);
+ if (sched == SCHED_FIFO || sched == SCHED_RR) return rtRealtime;
+ if (!getenv("STARTED_THROUGH_ARTSWRAPPER")) return rtNoWrapper;
+ return rtNoRealtime;
+}
+#else
+RealtimeStatus SoundServer_impl::realtimeStatus() {
+ return rtNoSupport;
+}
+#endif
+
+long SoundServer_impl::secondsUntilSuspend() {
+ if (Dispatcher::the()->flowSystem()->suspended())
+ return 0;
+ if (Dispatcher::the()->flowSystem()->suspendable() && autoSuspendTime == 0)
+ return -2;
+ if (Dispatcher::the()->flowSystem()->suspendable())
+ return (autoSuspendTime*5 - asCount)/5;
+ return -1;
+}
+
+bool SoundServer_impl::suspend() {
+ if (Dispatcher::the()->flowSystem()->suspended())
+ {
+ return true;
+ }
+ if(Dispatcher::the()->flowSystem()->suspendable())
+ {
+ Dispatcher::the()->flowSystem()->suspend();
+ arts_info("sound server suspended by client");
+ return true;
+ }
+ return false;
+}
+
+bool SoundServer_impl::suspended() {
+ return Dispatcher::the()->flowSystem()->suspended();
+}
+
+bool SoundServer_impl::terminate() {
+ Dispatcher::the()->terminate();
+ return true;
+}
+
+#ifndef __SUNPRO_CC
+/* See bottom of simplesoundserver_impl.cc for the reason this is here. */
+REGISTER_IMPLEMENTATION(SoundServer_impl);
+#endif
diff --git a/soundserver/soundserver_impl.h b/soundserver/soundserver_impl.h
new file mode 100644
index 0000000..de2aff6
--- /dev/null
+++ b/soundserver/soundserver_impl.h
@@ -0,0 +1,46 @@
+ /*
+
+ Copyright (C) 2000 Hans Meine
+ hans@meine.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#ifndef SOUNDSERVER_IMPL_H
+#define SOUNDSERVER_IMPL_H
+
+#include "soundserver.h"
+#include "simplesoundserver_impl.h"
+#include "soundserver.h"
+
+namespace Arts {
+
+ class SoundServer_impl : virtual public SoundServer_skel,
+ public SimpleSoundServer_impl
+ {
+ RealtimeStatus realtimeStatus();
+ long secondsUntilSuspend();
+ bool suspend();
+ bool suspended();
+ bool terminate();
+ };
+}
+
+#endif /* VERBOSESOUNDSERVER_IMPL_H */
diff --git a/soundserver/soundserverstartup_impl.cc b/soundserver/soundserverstartup_impl.cc
new file mode 100644
index 0000000..ba68dd4
--- /dev/null
+++ b/soundserver/soundserverstartup_impl.cc
@@ -0,0 +1,99 @@
+ /*
+
+ Copyright (C) 2003 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#include "config.h"
+#include "debug.h"
+#include "soundserverstartup_impl.h"
+#include <sys/time.h>
+#include <time.h>
+#include <cstdlib>
+
+using namespace Arts;
+
+SoundServerStartup_impl::SoundServerStartup_impl()
+{
+ locked = false;
+ /*
+ * create a sane random seed, pseudo random is not enough for
+ * our purposes
+ */
+ timeval tv;
+ gettimeofday(&tv, NULL);
+
+ int pid = getpid();
+ srand(tv.tv_sec);
+ srand(rand() + tv.tv_usec);
+ srand(rand() + pid);
+}
+
+SoundServerStartup_impl::~SoundServerStartup_impl()
+{
+ if (locked)
+ unlock();
+}
+
+void SoundServerStartup_impl::cleanReference()
+{
+ SoundServerStartup test = Reference("global:Arts_SoundServerStartup");
+ if(test.isNull())
+ Dispatcher::the()->globalComm().erase("Arts_SoundServerStartup");
+}
+
+void SoundServerStartup_impl::lock()
+{
+ arts_return_if_fail (!locked);
+
+ while (!ObjectManager::the()->addGlobalReference(self(), "Arts_SoundServerStartup"))
+ {
+ arts_debug ("[artsd: %5d] parallel startup detected: sleeping",getpid());
+
+ /*
+ * if several instances of artsd are started at the same time,
+ * we don't want all of them to retry getting a reference at
+ * exactly the same moment ; thus we sleep for a random amount
+ * of time, rather than for exactly one second, if possible
+ */
+#ifdef HAVE_USLEEP
+ usleep((rand() % 700000) + 200000);
+#else
+ sleep(1);
+#endif
+ cleanReference();
+ }
+ locked = true;
+ arts_debug ("[artsd: %5d] SoundServerStartup --> got lock",getpid());
+}
+
+void SoundServerStartup_impl::unlock()
+{
+ arts_return_if_fail (locked);
+
+ arts_debug ("[artsd: %5d] SoundServerStartup <-- released lock",getpid());
+ Dispatcher::the()->globalComm().erase("Arts_SoundServerStartup");
+ locked = false;
+}
+
+namespace Arts {
+#ifndef __SUNPRO_CC
+ /* See bottom of simplesoundserver_impl.cc for the reason this is here. */
+REGISTER_IMPLEMENTATION(SoundServerStartup_impl);
+#endif
+}
diff --git a/soundserver/soundserverstartup_impl.h b/soundserver/soundserverstartup_impl.h
new file mode 100644
index 0000000..d84731a
--- /dev/null
+++ b/soundserver/soundserverstartup_impl.h
@@ -0,0 +1,49 @@
+ /*
+
+ Copyright (C) 2003 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef SOUNDSERVERSTARTUP_IMPL_H
+#define SOUNDSERVERSTARTUP_IMPL_H
+
+#include "soundserver.h"
+
+namespace Arts {
+
+class SoundServerStartup_impl : public SoundServerStartup_skel {
+protected:
+ bool locked;
+
+ void cleanReference();
+public:
+ SoundServerStartup self() {
+ return SoundServerStartup::_from_base(_copy());
+ }
+
+ SoundServerStartup_impl();
+ ~SoundServerStartup_impl();
+
+ void lock();
+ void unlock();
+};
+
+}
+
+#endif // SOUNDSERVERSTARTUP_IMPL_H
+
diff --git a/soundserver/soundserverv2_impl.cc b/soundserver/soundserverv2_impl.cc
new file mode 100644
index 0000000..0abe5c7
--- /dev/null
+++ b/soundserver/soundserverv2_impl.cc
@@ -0,0 +1,386 @@
+ /*
+
+ Copyright (C) 2001 Jeff Tranter
+ tranter@kde.org
+ 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "artsflow.h"
+#include "flowsystem.h"
+#include "audiosubsys.h"
+#include "connect.h"
+#include "debug.h"
+#include "soundserverv2_impl.h"
+#include "artsversion.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fstream>
+#include <set>
+#include <cstring>
+#include <cstdlib>
+
+#include "config.h"
+
+using namespace Arts;
+using namespace std;
+
+SoundServerV2_impl::SoundServerV2_impl()
+ : _sampleStorage(SampleStorage(
+ MCOPUtils::createFilePath("artsd-samples"),true))
+{
+ checkNewObjects();
+}
+
+std::string SoundServerV2_impl:: audioMethod() {
+ return AudioSubSystem::the()->audioIO();
+}
+
+long SoundServerV2_impl:: samplingRate() {
+ return AudioSubSystem::the()->samplingRate();
+}
+
+long SoundServerV2_impl:: channels() {
+ return AudioSubSystem::the()->channels();
+}
+
+long SoundServerV2_impl:: bits() {
+ return AudioSubSystem::the()->bits();
+}
+
+bool SoundServerV2_impl:: fullDuplex() {
+ return AudioSubSystem::the()->fullDuplex();
+}
+
+std::string SoundServerV2_impl:: audioDevice() {
+ return AudioSubSystem::the()->deviceName();
+}
+
+long SoundServerV2_impl::fragments() {
+ return AudioSubSystem::the()->fragmentCount();
+}
+
+long SoundServerV2_impl::fragmentSize() {
+ return AudioSubSystem::the()->fragmentSize();
+}
+
+long SoundServerV2_impl::autoSuspendSeconds() {
+ return autoSuspendTime;
+}
+
+void SoundServerV2_impl::autoSuspendSeconds(long int newValue) {
+ autoSuspendTime = newValue;
+}
+
+std::string SoundServerV2_impl::version() {
+ return ARTS_VERSION;
+}
+
+long SoundServerV2_impl::bufferSizeMultiplier() {
+ return bufferMultiplier;
+}
+
+void SoundServerV2_impl::bufferSizeMultiplier(long newValue) {
+ bufferMultiplier = newValue;
+}
+
+StereoVolumeControl SoundServerV2_impl::outVolume() {
+ return _outVolume;
+}
+
+SampleStorage SoundServerV2_impl::sampleStorage() {
+ return _sampleStorage;
+}
+
+PlayObject SoundServerV2_impl::createPlayObjectForURL(const std::string& url, const std::string& mimetype, bool createBUS)
+{
+ arts_debug("search playobject, mimetype = %s", mimetype.c_str());
+
+ TraderQuery query;
+ query.supports("Interface","Arts::PlayObject");
+ query.supports("MimeType", mimetype);
+
+ string objectType;
+
+ vector<TraderOffer> *offers = query.query();
+ if(!offers->empty())
+ objectType = offers->front().interfaceName(); // first offer
+
+ delete offers;
+
+ /*
+ * create a PlayObject and connect it
+ */
+ if(!objectType.empty())
+ {
+ arts_debug("creating %s to play file", objectType.c_str());
+
+ PlayObject result = SubClass(objectType);
+ if(result.loadMedia(url))
+ {
+ if(createBUS)
+ {
+ // TODO: check for existence of left & right streams
+ Synth_BUS_UPLINK uplink;
+ uplink.busname("out_soundcard");
+ connect(result,"left",uplink,"left");
+ connect(result,"right",uplink,"right");
+ uplink.start();
+ result._node()->start();
+ result._addChild(uplink,"uplink");
+ return result;
+ }
+ else
+ return result;
+ }
+ else arts_warning("couldn't load file %s", url.c_str());
+ }
+ else arts_warning("mimetype %s unsupported", mimetype.c_str());
+
+ return PlayObject::null();
+}
+
+PlayObject SoundServerV2_impl::createPlayObjectForStream(InputStream instream, const std::string& mimetype, bool createBUS)
+{
+ arts_debug("search streamplayobject, mimetype = %s", mimetype.c_str());
+
+ TraderQuery query;
+ query.supports("Interface","Arts::StreamPlayObject");
+ query.supports("MimeType", mimetype);
+
+ string objectType;
+
+ vector<TraderOffer> *offers = query.query();
+ if(!offers->empty())
+ objectType = offers->front().interfaceName(); // first offer
+
+ delete offers;
+
+ /*
+ * create a PlayObject and connect it
+ */
+ if(!objectType.empty())
+ {
+ arts_debug("creating %s to play file", objectType.c_str());
+
+ StreamPlayObject result = SubClass(objectType);
+ result.streamMedia(instream);
+
+ if(createBUS)
+ {
+ // TODO: check for existence of left & right streams
+ Synth_BUS_UPLINK uplink;
+ uplink.busname("out_soundcard");
+ connect(result,"left",uplink,"left");
+ connect(result,"right",uplink,"right");
+ uplink.start();
+ result._node()->start();
+ result._addChild(uplink,"uplink");
+ return result;
+ }
+ else
+ return result;
+ }
+ else arts_warning("mimetype %s unsupported for streaming", mimetype.c_str());
+
+ return PlayObject::null();
+}
+
+static void clearDirectory(const string& directory)
+{
+ DIR *dir = opendir(directory.c_str());
+ if(!dir) return;
+
+ struct dirent *de;
+ while((de = readdir(dir)) != 0)
+ {
+ string currentEntry = directory + "/" + de->d_name;
+
+ if(de->d_name[0] != '.')
+ {
+ unlink(currentEntry.c_str());
+ }
+ }
+ closedir(dir);
+}
+
+/* copied from mcopidl */
+static void doTypeIndex(string dir, string prefix, ModuleDef& module)
+{
+ FILE *typeIndex = fopen((dir+"/"+prefix+".mcopclass").c_str(),"w");
+
+ vector<string> supportedTypes;
+
+ vector<InterfaceDef>::iterator ii;
+ for(ii = module.interfaces.begin(); ii != module.interfaces.end(); ii++)
+ supportedTypes.push_back(ii->name);
+
+ vector<TypeDef>::iterator ti;
+ for(ti = module.types.begin(); ti != module.types.end(); ti++)
+ supportedTypes.push_back(ti->name);
+
+ string supportedTypesList;
+ vector<string>::iterator si;
+ bool first = true;
+ for(si = supportedTypes.begin(); si != supportedTypes.end(); si++)
+ {
+ if(!first) supportedTypesList += ",";
+
+ supportedTypesList += (*si);
+ first = false;
+ }
+ fprintf(typeIndex, "# this file was generated by artsd - do not edit\n");
+ fprintf(typeIndex,"Type=%s\n",supportedTypesList.c_str());
+ fprintf(typeIndex,"TypeFile=%s.mcoptype\n",prefix.c_str());
+ fclose(typeIndex);
+}
+
+void SoundServerV2_impl::checkNewObjects()
+{
+ const char *home = getenv("HOME");
+ arts_return_if_fail(home != 0);
+
+ string dir = home + string("/.mcop/trader-cache");
+ string dataVersionFileName = dir + "/cache-data-version";
+
+ mkdir(home,0755);
+ mkdir((home+string("/.mcop")).c_str(),0755);
+ if(mkdir(dir.c_str(),0755) != 0)
+ {
+ string why = strerror(errno);
+
+ struct stat st;
+ stat(dir.c_str(),&st);
+ if(!S_ISDIR(st.st_mode))
+ {
+ arts_warning("can't create directory %s to fill it with"
+ " trader data (%s)", dir.c_str(), why.c_str());
+ return;
+ }
+ }
+
+ TraderQuery query;
+ query.supports("Interface", "Arts::Loader");
+ vector<TraderOffer> *offers = query.query();
+ vector<TraderOffer>::iterator i;
+
+ set<string> newDataVersion, cacheDataVersion;
+ for(i = offers->begin(); i != offers->end(); i++)
+ {
+ // TODO: error checking?
+ Arts::Loader loader = SubClass(i->interfaceName());
+ newDataVersion.insert(loader.dataVersion());
+ }
+
+ /* change this line if you change the cache update code */
+ newDataVersion.insert("Cache-Update-Code-Version:1.0");
+
+ /* load cache-data-version file */
+ {
+ ifstream infile(dataVersionFileName.c_str());
+
+ string line;
+ while(infile >> line)
+ cacheDataVersion.insert(line);
+ }
+
+ /* if it differs, rebuild trader cache */
+ if(cacheDataVersion != newDataVersion)
+ {
+ clearDirectory(dir);
+
+ /* save new cache-data-version file */
+ {
+ ofstream out(dataVersionFileName.c_str());
+
+ set<string>::iterator i;
+ for(i = newDataVersion.begin(); i != newDataVersion.end(); i++)
+ out << *i << endl;
+ }
+ rebuildTraderCache(dir, offers);
+ }
+ delete offers;
+}
+
+void SoundServerV2_impl::rebuildTraderCache(const string& directory,
+ vector<TraderOffer> *offers)
+{
+ vector<TraderOffer>::iterator i;
+
+ for(i = offers->begin(); i != offers->end(); i++)
+ {
+ // TODO: error checking?
+ Arts::Loader loader = SubClass(i->interfaceName());
+
+ /* put trader-information in ~/.mcop/trader-cache */
+ vector<TraderEntry> *entries = loader.traderEntries();
+ vector<TraderEntry>::iterator ei;
+ for(ei = entries->begin(); ei != entries->end(); ei++)
+ {
+ const TraderEntry& entry = *ei;
+
+ FILE *traderFile = fopen((directory+"/"+entry.interfaceName+".mcopclass").c_str(),"w");
+ fprintf(traderFile, "# this file was generated by artsd - do not edit\n");
+ vector<string>::const_iterator li;
+ for(li = entry.lines.begin(); li != entry.lines.end(); li++)
+ fprintf(traderFile,"%s\n", li->c_str());
+
+ fclose(traderFile);
+ }
+ delete entries;
+
+ /* put type-information in ~/.mcop/trader-cache */
+ vector<ModuleDef> *modules = loader.modules();
+ vector<ModuleDef>::iterator mi;
+ for(mi = modules->begin(); mi != modules->end(); mi++)
+ {
+ Arts::ModuleDef& module = *mi;
+
+ Buffer b;
+ module.writeType(b);
+
+ FILE *typeFile = fopen((directory + "/" + module.moduleName+".arts.mcoptype").c_str(),"w");
+ unsigned long towrite = b.size();
+ fwrite(b.read(towrite),1,towrite,typeFile);
+ fclose(typeFile);
+
+ doTypeIndex(directory,module.moduleName+".arts",module);
+ }
+ delete modules;
+ }
+ Dispatcher::the()->reloadTraderData();
+}
+
+float SoundServerV2_impl::cpuUsage()
+{
+ return CPUUsage::the()->usage() * 100.0;
+}
+
+
+#ifndef __SUNPRO_CC
+/* See bottom of simplesoundserver_impl.cc for the reason this is here. */
+REGISTER_IMPLEMENTATION(SoundServerV2_impl);
+#endif
diff --git a/soundserver/soundserverv2_impl.h b/soundserver/soundserverv2_impl.h
new file mode 100644
index 0000000..22bd1cf
--- /dev/null
+++ b/soundserver/soundserverv2_impl.h
@@ -0,0 +1,71 @@
+ /*
+
+ Copyright (C) 2001 Jeff Tranter
+ tranter@kde.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#ifndef SOUNDSERVERV2_IMPL_H
+#define SOUNDSERVERV2_IMPL_H
+
+#include "soundserver.h"
+#include "simplesoundserver_impl.h"
+#include "soundserver_impl.h"
+#include "soundserver.h"
+#include "cpuusage.h"
+
+namespace Arts {
+ class SoundServerV2_impl : virtual public SoundServerV2_skel,
+ public SoundServer_impl
+ {
+ protected:
+ SampleStorage _sampleStorage;
+
+ void rebuildTraderCache(const std::string& directory,
+ std::vector<TraderOffer> *offers);
+
+ public:
+ SoundServerV2_impl();
+
+ long autoSuspendSeconds();
+ void autoSuspendSeconds(long newValue);
+ std::string audioMethod();
+ long samplingRate();
+ long channels();
+ long bits();
+ bool fullDuplex();
+ std::string audioDevice();
+ long fragments();
+ long fragmentSize();
+ std::string version();
+ long bufferSizeMultiplier();
+ void bufferSizeMultiplier(long newValue);
+ StereoVolumeControl outVolume();
+ SampleStorage sampleStorage();
+ void checkNewObjects();
+ float cpuUsage();
+
+ Arts::PlayObject createPlayObjectForURL(const std::string& url, const std::string& mimetype, bool createBUS);
+ Arts::PlayObject createPlayObjectForStream(Arts::InputStream instream, const std::string& mimetype, bool createBUS);
+ };
+}
+
+#endif /* SOUNDSERVERV2_IMPL_H */
diff --git a/soundserver/stdoutwriter_impl.cc b/soundserver/stdoutwriter_impl.cc
new file mode 100644
index 0000000..d93ca2b
--- /dev/null
+++ b/soundserver/stdoutwriter_impl.cc
@@ -0,0 +1,52 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "kmedia2.h"
+#include "stdsynthmodule.h"
+#include <errno.h>
+
+using namespace std;
+using namespace Arts;
+
+namespace Arts {
+
+class StdoutWriter_impl : virtual public StdoutWriter_skel,
+ virtual public StdSynthModule
+{
+public:
+ StdoutWriter_impl()
+ {
+ }
+ void process_indata(DataPacket<mcopbyte> *data)
+ {
+ int result;
+ errno = 0;
+ do {
+ result = write(1, data->contents, data->size);
+ } while(errno == EINTR && result <= 0);
+ data->processed();
+ }
+};
+
+REGISTER_IMPLEMENTATION(StdoutWriter_impl);
+
+}
diff --git a/soundserver/tradercheck.cc b/soundserver/tradercheck.cc
new file mode 100644
index 0000000..f14cd7e
--- /dev/null
+++ b/soundserver/tradercheck.cc
@@ -0,0 +1,213 @@
+ /*
+
+ Copyright (C) 2000-2003 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "common.h"
+#include "debug.h"
+#include "tradercheck.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <map>
+
+using namespace Arts;
+using namespace std;
+
+bool TraderCheck::haveProperty(TraderOffer& offer, const string& property)
+{
+ vector<string>* plist = offer.getProperty(property);
+ bool result = !plist->empty();
+ delete plist;
+
+ return result;
+}
+
+string TraderCheck::getSingleProperty(TraderOffer& offer, const string& property)
+{
+ string result="";
+
+ vector<string>* plist = offer.getProperty(property);
+ if(!plist->empty())
+ result = plist->front();
+ delete plist;
+
+ return result;
+}
+
+bool TraderCheck::findFile(const vector<string> *path, const string& filename)
+{
+ vector<string>::const_iterator pi;
+ for(pi = path->begin(); pi != path->end(); pi++)
+ {
+ string pfilename = *pi + "/" + filename;
+
+ if(access(pfilename.c_str(),F_OK) == 0)
+ return true;
+ }
+ return false;
+}
+
+void TraderCheck::collectInterfaces(const string& interfaceName, map<string, int>& i)
+{
+ InterfaceDef idef = interfaceRepo.queryInterface(interfaceName);
+
+ if(!idef.name.empty())
+ {
+ if(i[idef.name] == 1) return;
+ i[idef.name]++;
+ }
+ vector<string>::const_iterator ii;
+ for(ii = idef.inheritedInterfaces.begin(); ii != idef.inheritedInterfaces.end(); ii++)
+ collectInterfaces(*ii, i);
+ collectInterfaces("Arts::Object", i);
+}
+
+
+void
+#ifdef __GNUC__
+__attribute__ ( ( format ( printf, 3, 4 ) ) )
+#endif
+TraderCheck::check(bool cond, const char *fmt, ...)
+{
+ if(cond)
+ return;
+
+ if(!wroteHeader)
+ {
+ wroteHeader = true;
+ printf("Trader inconsistency in \'%s\':\n", interfaceName.c_str());
+
+ }
+ printf(" * ");
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ printf("\n");
+}
+
+void TraderCheck::run()
+{
+ interfaceRepo = DynamicCast(Dispatcher::the()->interfaceRepo());
+
+ /* prevent the screen from being filled with aRts warnings */
+ Debug::init("", Debug::lFatal);
+
+ TraderQuery everything; /* a query without any restriction */
+ vector<TraderOffer> *allObjects = everything.query();
+ vector<TraderOffer>::iterator i;
+
+ for(i = allObjects->begin(); i != allObjects->end(); i++)
+ {
+ TraderOffer& offer = *i;
+
+ wroteHeader = false;
+ interfaceName = offer.interfaceName();
+
+
+ if(haveProperty(offer,"Type"))
+ {
+ // check type file consistency
+ check(haveProperty(offer,"TypeFile"),
+ "trader entries with a Type entry MUST have a TypeFile entry");
+
+ check(!haveProperty(offer,"Language"),
+ "trader entries with a Type entry MUST NOT have a Language entry");
+ }
+ else if(haveProperty(offer,"Language") || haveProperty(offer,"Library"))
+ {
+ // check class file consistency
+ InterfaceDef idef = interfaceRepo.queryInterface(offer.interfaceName());
+ if(idef.name.empty())
+ {
+ check(false, "interface type not found");
+ }
+ else
+ {
+ // verify correctness of the Interface= line
+ map<string,int> ifaces;
+ collectInterfaces(offer.interfaceName(), ifaces);
+
+ vector<string>* plist = offer.getProperty("Interface");
+ vector<string>::iterator pi;
+ for(pi = plist->begin(); pi != plist->end(); pi++)
+ {
+ ifaces[*pi]+=2;
+ }
+ delete plist;
+
+ map<string,int>::iterator ii;
+
+ for(ii = ifaces.begin(); ii != ifaces.end(); ii++)
+ {
+ switch(ii->second)
+ {
+ case 0:
+ check(false, "INTERNAL verification error");
+ break;
+
+ case 1:
+ check(false, "missing interface %s in Interface entry",
+ ii->first.c_str());
+ break;
+
+ case 2:
+ check(false, "given unimplemented(?) interface %s in Interface entry",
+ ii->first.c_str());
+ break;
+
+ case 3:
+ /* the way things should be */
+ break;
+
+ default:
+ check(false, "given interface %s in Interface entry more than once?",
+ ii->first.c_str());
+ break;
+ }
+ }
+ }
+
+ if(haveProperty(offer,"Library"))
+ {
+ check(getSingleProperty(offer,"Language") == "C++",
+ "trader entries with a Library entry SHOULD have a Language=C++ entry");
+
+ }
+
+ if (getSingleProperty(offer,"Language") == "C++")
+ {
+ string library = getSingleProperty(offer,"Library");
+ check(!library.empty(),
+ "entries with a Language entry must have a Library entry");
+ check(findFile(MCOPUtils::extensionPath(), library),
+ "Library entry MUST be loadable via extension path");
+ }
+
+ check(haveProperty(offer, "Interface"),
+ "entries with Language/Library MUST have an Interface entry");
+ }
+ else
+ {
+ check(false,"entry MUST have either Language or Type entry");
+ }
+ }
+ delete allObjects;
+}
diff --git a/soundserver/tradercheck.h b/soundserver/tradercheck.h
new file mode 100644
index 0000000..aa0b894
--- /dev/null
+++ b/soundserver/tradercheck.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2003 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+#ifndef TRADERCHECK_H
+#define TRADERCHECK_H
+
+#include "core.h"
+
+namespace Arts {
+
+/**
+ * This is an internal class used by artscontrol to check the consistency of
+ * the entries in the trader made through mcopclass/mcoptype files
+ */
+class TraderCheck {
+protected:
+ bool wroteHeader;
+ std::string interfaceName;
+ Arts::InterfaceRepoV2 interfaceRepo;
+
+ void check(bool cond, const char *fmt, ...);
+ bool haveProperty(Arts::TraderOffer& offer, const std::string& property);
+ std::string getSingleProperty(Arts::TraderOffer& offer, const std::string& property);
+ bool findFile(const std::vector<std::string> *path, const std::string& filename);
+ void collectInterfaces(const std::string& interfaceName, std::map<std::string, int>& i);
+
+public:
+ void run();
+};
+
+}
+
+#endif
+
diff --git a/soundserver/wavplayobject_impl.cc b/soundserver/wavplayobject_impl.cc
new file mode 100644
index 0000000..1a5fb82
--- /dev/null
+++ b/soundserver/wavplayobject_impl.cc
@@ -0,0 +1,172 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "config.h"
+
+#ifdef HAVE_LIBAUDIOFILE
+
+#include "soundserver.h"
+#include "cachedwav.h"
+#include "stdsynthmodule.h"
+#include "convert.h"
+#include "debug.h"
+#include <math.h>
+
+using namespace std;
+using namespace Arts;
+
+class WavPlayObject_impl :public WavPlayObject_skel, public StdSynthModule {
+protected:
+ CachedWav *wav;
+ double flpos;
+ poState _state;
+
+ int sampleCount()
+ {
+ if(!wav) return 0;
+ return wav->bufferSize / wav->channelCount / (wav->sampleWidth/8);
+ }
+public:
+ /*
+ * construction, destruction
+ */
+ WavPlayObject_impl() :wav(0), flpos(0.0), _state(posIdle)
+ {
+ arts_debug("WavPlayObject_impl");
+ }
+
+ virtual ~WavPlayObject_impl()
+ {
+ arts_debug("~WavPlayObject_impl");
+ if(wav) wav->decRef();
+ }
+
+ /*
+ * KMedia2 private interface
+ */
+
+ bool loadMedia(const string &filename) {
+ arts_debug("Wav: loadMedia %s", filename.c_str());
+ wav = CachedWav::load(Cache::the(), filename);
+ return (wav != 0);
+ }
+
+ /*
+ * KMedia2 interface
+ */
+ string description() {
+ return "no description (see "__FILE__")";
+ }
+
+ poTime currentTime() {
+ if(!wav) return poTime(0,0,0,"samples");
+
+ float timesec = flpos / (float)wav->samplingRate;
+ float timems = (timesec - floor(timesec)) * 1000.0;
+
+ return poTime( int( timesec ), int( timems ), (int)flpos, "samples" );
+ }
+
+ poTime overallTime() {
+ float timesec = (float)sampleCount() / (float)wav->samplingRate;
+ float timems = (timesec - floor(timesec)) * 1000.0;
+
+ return poTime( int( timesec ), int( timems ), sampleCount(), "samples" );
+ }
+
+ poCapabilities capabilities() {
+ return static_cast<poCapabilities>(capPause+capSeek);
+ }
+
+ string mediaName() {
+ return wav ? wav->mediaName() : "";
+ }
+
+ poState state() {
+ return _state;
+ }
+
+ void play() {
+ _state = posPlaying;
+ }
+
+ void halt() {
+ _state = posIdle;
+ flpos = 0.0;
+ }
+
+ void seek(const class poTime &newTime) {
+ if(!wav) return;
+
+ float fnewsamples = -1;
+ if(newTime.seconds != -1 && newTime.ms != -1)
+ {
+ float flnewtime = (float)newTime.seconds+((float)newTime.ms/1000.0);
+ fnewsamples = flnewtime * (float)wav->samplingRate;
+ }
+ else if(newTime.custom >= 0 && newTime.customUnit == "samples")
+ {
+ fnewsamples = newTime.custom;
+ }
+
+ if(fnewsamples > (float)sampleCount())
+ fnewsamples = (float)sampleCount();
+
+ if(fnewsamples >= 0) flpos = fnewsamples;
+ }
+
+ void pause() {
+ arts_debug("pause");
+ _state = posPaused;
+ }
+
+ void calculateBlock(unsigned long samples) {
+ unsigned long haveSamples = 0;
+
+ if(wav && _state == posPlaying)
+ {
+ double speed = wav->samplingRate / samplingRateFloat;
+
+ haveSamples = uni_convert_stereo_2float(samples, wav->buffer,
+ wav->bufferSize,wav->channelCount,wav->sampleWidth,
+ left,right,speed,flpos);
+
+ flpos += (double)haveSamples * speed;
+ }
+
+ if(haveSamples != samples)
+ {
+ unsigned long i;
+
+ for(i=haveSamples;i<samples;i++)
+ left[i] = right[i] = 0.0;
+
+ if(_state == posPlaying) {
+ _state = posIdle;
+ flpos = 0.0;
+ }
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(WavPlayObject_impl);
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..2d533f6
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,44 @@
+check_PROGRAMS = testbuffer testifacerepo testanyref testwrapper \
+ testchangenotify testflowsystem testdispatcher testnotification \
+ testremote
+
+TESTS = $(check_PROGRAMS)
+
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_srcdir)/flow \
+ -I$(top_builddir)/flow -I$(top_srcdir)/soundserver \
+ -I$(top_builddir)/soundserver -I$(top_srcdir)/artsc \
+ -I$(top_builddir)/mcop $(all_includes)
+
+AM_LDFLAGS = $(all_libraries)
+LDADD = $(top_builddir)/mcop/libmcop.la
+FLOWLIBS = $(top_builddir)/flow/libartsflow.la
+
+testbuffer_SOURCES = testbuffer.cc
+testifacerepo_SOURCES = testifacerepo.cc
+testanyref_SOURCES = testanyref.cc
+testdispatcher_SOURCES = testdispatcher.cc
+testnotification_SOURCES = testnotification.cc
+testwrapper_SOURCES = wrapper.cc testwrapper.cc
+
+testchangenotify_LDADD = $(FLOWLIBS)
+testchangenotify_SOURCES = value.cc value_impl.cc testchangenotify.cc
+
+testflowsystem_LDADD = $(FLOWLIBS)
+testflowsystem_SOURCES = value.cc value_impl.cc testflowsystem.cc
+
+testremote_LDADD = $(FLOWLIBS)
+testremote_SOURCES = remotetest.cc value.cc value_impl.cc testremote.cc
+
+DISTCLEANFILES = wrapper.h wrapper.cc value.h value.cc \
+ remotetest.h remotetest.cc
+
+wrapper.cc wrapper.h: $(top_srcdir)/tests/wrapper.idl $(MCOPIDL)
+ $(MCOPIDL) $(top_srcdir)/tests/wrapper.idl
+
+value_impl.o: value.h
+value.cc value.h: $(top_srcdir)/tests/value.idl $(MCOPIDL)
+ $(MCOPIDL) $(top_srcdir)/tests/value.idl
+
+remotetest.cc remotetest.h: $(top_srcdir)/tests/remotetest.idl $(MCOPIDL)
+ $(MCOPIDL) $(top_srcdir)/tests/remotetest.idl
+
diff --git a/tests/README.test b/tests/README.test
new file mode 100644
index 0000000..d605c21
--- /dev/null
+++ b/tests/README.test
@@ -0,0 +1,72 @@
+ C++ automatic testing similar to JUnit
+ Stefan Westerfeld <stw@kde.org>
+
+What it is:
+===========
+
+These tests use a little testing framework, which consists currently only
+of the file test.h. It is very much inspired by JUnit (www.junit.org), but it
+is maybe even simpler. But it integrates nicely in Makefile.am automatic
+testing. You can simply type
+
+make check
+
+to see if all tests pass. The motivation behind it is, when you are working
+on a large project, it is often impossible to test quickly whether everything
+still works all right after changes (which you should before committing ...).
+This is even more true if you are not working alone on the code.
+
+With a consistent set of tests that verify whether everything is still all
+right, things like breaking one thing while fixing another can be made less
+likely at least.
+
+How to add a new set of tests:
+==============================
+
+1. create a new .cc file, for this example we'll suppose testarithmetic.cc
+2. #include "test.h"
+3. create a struct which will hold all your tests
+
+struct TestArithmetic : public TestCase {
+ TESTCASE(TestArithmetic);
+};
+
+4. if you want to, override the following methods:
+
+ void setUp()
+ {
+ /*
+ * This method is supposed to build a little test world, which will be
+ * built for each test method that is executed - the idea is that your
+ * tests will use this environment to test in.
+ */
+ }
+ void tearDown()
+ {
+ /*
+ * This method should completely destroy your test world again, so
+ * that for the next test, a fresh one can be created.
+ */
+ }
+
+5. define new tests like this
+
+ TEST(arithmetic) {
+ long a = 2;
+ long b = 2;
+ long c = a+b;
+
+ testAssert(c < 5); // you assert that this condition is true
+ testEquals(4,c); // you assert that the first (expected) value
+ } // equals the second (computed) value
+
+6. define a main for your test like this
+
+TESTMAIN(TestArithmetic);
+
+7. add the following to the Makefile.am (you may want to add more source files,
+ as required)
+
+testarithmetic_SOURCES = testarithmetic.cc
+
+8. add it to check_PROGRAMS
diff --git a/tests/remotetest.idl b/tests/remotetest.idl
new file mode 100644
index 0000000..6301077
--- /dev/null
+++ b/tests/remotetest.idl
@@ -0,0 +1,11 @@
+interface RemoteTest {
+ readonly attribute long fortyTwo;
+
+ object createObject(string name);
+ oneway void die();
+};
+
+interface Calculator {
+ long add(long a, long b);
+ string concat(string a, string b);
+};
diff --git a/tests/test.h b/tests/test.h
new file mode 100644
index 0000000..a72b13d
--- /dev/null
+++ b/tests/test.h
@@ -0,0 +1,130 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef ARTS_TESTS_H
+#define ARTS_TESTS_H
+
+#include <string>
+#include <list>
+#include <iostream>
+#include <stdio.h>
+
+const char *noTest = "noTest";
+const char *noClass = "noClass";
+const char *currentClass = noClass;
+const char *currentTest = noTest;
+
+#define testCaption() \
+ fprintf (stderr,"\n %s::%s (%s:%d)\n", \
+ currentClass, currentTest, __FILE__, __LINE__);
+
+#define testAssert(expr) \
+ if (!(expr)) { \
+ testCaption(); \
+ fprintf (stderr," => test assertion failed: (%s)\n", #expr); \
+ exit(1); \
+ }
+
+template<typename T1, typename T2>
+inline void testEqualsCheck(const T1& expected, const T2& got,
+ const char *file, int line, const char *expr, const char *expr2)
+{
+ if(! (static_cast<T2>(expected) == got) ) {
+ std::cerr << std::endl
+
+ << " " << currentClass << "::" << currentTest
+ << " (" << file << ":" << line << ")" << std::endl
+
+ << " => test assertion failed:"
+ << " (" << expr << " == " << expr2 << ")" << std::endl
+
+ << " => expected '" << expected << "'" << " got "
+ << "'" << got << "'." << std::endl;
+ exit(1);
+ }
+}
+
+#define testEquals(expr, expr2) \
+ testEqualsCheck(expr, expr2, __FILE__, __LINE__, #expr, #expr2)
+
+#define TEST(func) \
+ struct t ## func : TestClass \
+ { \
+ t ## func() { \
+ if(!tests) tests = new list<TestClass *>; \
+ tests->push_back(this); \
+ } \
+ void invoke() { \
+ currentTest = #func; \
+ instance->func(); \
+ currentTest = noTest; \
+ } \
+ } i ## func; \
+ void func()
+
+struct TestClass {
+ virtual void invoke() = 0;
+};
+
+struct TestCase {
+ virtual void setUp() { };
+ virtual void tearDown() { };
+ virtual ~TestCase() { };
+};
+
+#define TESTCASE(name) \
+ static list<TestClass *> *tests; \
+ static name *instance; \
+ name () { \
+ instance = this; \
+ } \
+ void testAll() { \
+ currentClass = #name; \
+ list<TestClass *>::iterator i; \
+ for(i = tests->begin(); i != tests->end(); i++) \
+ { \
+ setUp(); \
+ (*i)->invoke(); \
+ tearDown(); \
+ } \
+ currentClass = noClass; \
+ } \
+ int count() { \
+ return tests->size(); \
+ }
+
+#define TESTMAINFUNC(name,func) \
+ name *name::instance = 0; \
+ list<TestClass *> *name::tests = 0; \
+ int func() \
+ { \
+ name tb; \
+ fprintf(stderr,"%-20s: %5d test methods - ", \
+ #name,tb.count()); \
+ tb.testAll(); \
+ return 0; \
+ }
+
+#define TESTMAIN(name) TESTMAINFUNC(name,main)
+
+#endif // ARTS_TESTS_H
+
diff --git a/tests/testanyref.cc b/tests/testanyref.cc
new file mode 100644
index 0000000..d2ac7fa
--- /dev/null
+++ b/tests/testanyref.cc
@@ -0,0 +1,97 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "common.h"
+#include "test.h"
+
+using namespace Arts;
+using namespace std;
+
+struct TestAnyRef : public TestCase
+{
+ TESTCASE(TestAnyRef);
+
+ Dispatcher dispatcher;
+ Buffer *buffer, *buffer2;
+ Any any;
+
+ void setUp() {
+ buffer = new Buffer();
+ any.type = "";
+ any.value.clear();
+ }
+ void tearDown() {
+ delete buffer; buffer = 0;
+ }
+ void copy(AnyRef& src, AnyRef& dest)
+ {
+ Buffer tmp;
+ src.write(&tmp);
+ tmp.rewind();
+ dest.read(&tmp);
+ }
+ TEST(ioAnyFloat) {
+ // create a buffer with a float and a end-of-buffer delimiter
+ float f = 1.1;
+ buffer->writeFloat(f);
+ buffer->writeLong(12345678);
+ buffer->rewind();
+
+ // see if reading it as float reads the *only* the float
+ any.type = "float";
+
+ AnyRef ref(any);
+ ref.read(buffer);
+ testEquals(12345678,buffer->readLong());
+ testEquals(4, any.value.size());
+
+ // check if the value is all right by copying it to a "real" float
+ float f2;
+ AnyRef ref2(f2);
+ copy(ref,ref2);
+ testEquals(f,f2);
+ }
+ TEST(ioAnyType) {
+ // do the same again with a complex structured type
+ Arts::InterfaceDef objInterface =
+ Dispatcher::the()->interfaceRepo().queryInterface("Arts::Object");
+ testEquals("Arts::Object", objInterface.name);
+
+ objInterface.writeType(*buffer);
+ buffer->writeLong(12345678);
+ buffer->rewind();
+
+ vector<mcopbyte> objInterfaceRaw;
+ buffer->read(objInterfaceRaw, buffer->remaining() - 4);
+ buffer->rewind();
+ testAssert(objInterfaceRaw.size() > 50);
+
+ any.type = "Arts::InterfaceDef";
+ AnyRef ref(any);
+ ref.read(buffer);
+ testEquals(12345678,buffer->readLong());
+ testAssert(objInterfaceRaw == any.value);
+ }
+
+};
+
+TESTMAIN(TestAnyRef);
diff --git a/tests/testbuffer.cc b/tests/testbuffer.cc
new file mode 100644
index 0000000..caa8b70
--- /dev/null
+++ b/tests/testbuffer.cc
@@ -0,0 +1,139 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "buffer.h"
+#include "test.h"
+
+using namespace Arts;
+using namespace std;
+
+struct TestBuffer : public TestCase
+{
+ TESTCASE(TestBuffer);
+
+ Arts::Buffer *buffer, *buffer1234;
+
+ void setUp() {
+ buffer = new Buffer();
+ buffer1234 = new Buffer();
+ buffer1234->writeByte(1);
+ buffer1234->writeByte(2);
+ buffer1234->writeByte(3);
+ buffer1234->writeByte(4);
+ }
+ void tearDown() {
+ delete buffer; buffer = 0;
+ delete buffer1234; buffer1234 = 0;
+ }
+ TEST(writeByte) {
+ buffer->writeByte(0x42);
+
+ testEquals("42",buffer->toString(""));
+ testEquals(0x42,buffer->readByte());
+ }
+ TEST(writeLong) {
+ buffer->writeLong(10001025);
+
+ testEquals("00989a81",buffer->toString(""));
+ testEquals(10001025, buffer->readLong());
+ }
+ TEST(writeString) {
+ buffer->writeString("hello");
+
+ /* __size__ h e l l o \0 */
+ testEquals("00000006""68656c6c6f00",buffer->toString(""));
+
+ string s;
+ buffer->readString(s);
+ testEquals("hello", s);
+ }
+ TEST(writeBool) {
+ buffer->writeBool(true);
+ buffer->writeBool(false);
+
+ testEquals("0100",buffer->toString(""));
+ testEquals(true, buffer->readBool());
+ testEquals(false, buffer->readBool());
+ }
+ TEST(writeFloat) {
+ float f = 2.15;
+ buffer->writeFloat(f);
+
+ testEquals("4009999a",buffer->toString(""));
+ testEquals(f,buffer->readFloat());
+ }
+ TEST(write) {
+ vector<mcopbyte> b;
+ b.push_back(1);
+ b.push_back(2);
+
+ buffer->write(b);
+
+ testEquals("0102",buffer->toString(""));
+
+ char c[2] = { 3,4 };
+ buffer->write(c,2);
+
+ testEquals("01020304",buffer->toString(""));
+ }
+ TEST(read) {
+ vector<mcopbyte> bytes;
+ buffer1234->read(bytes,4);
+
+ testEquals(4, bytes.size());
+ testEquals(1, bytes[0]);
+ testEquals(2, bytes[1]);
+ testEquals(3, bytes[2]);
+ testEquals(4, bytes[3]);
+
+ // read shall overwrite the vector it gets as parameter
+ buffer1234->rewind();
+ buffer1234->read(bytes,3);
+ testEquals(3, bytes.size());
+ }
+ TEST(errorHandling)
+ {
+ testEquals(false, buffer1234->readError());
+ testEquals(4, buffer1234->size());
+ testEquals(4, buffer1234->remaining());
+ buffer1234->readLong();
+ testEquals(4, buffer1234->size());
+ testEquals(0, buffer1234->remaining());
+ testEquals(false, buffer1234->readError());
+ buffer1234->readByte();
+ testEquals(4, buffer1234->size());
+ testEquals(0, buffer1234->remaining());
+ testEquals(true, buffer1234->readError());
+
+ testEquals(false, buffer->readError());
+ buffer->writeLong(0xdddddddd);
+ buffer->writeLong(0x12345678);
+
+ // check that it terminates properly upon reading broken data
+ string s;
+ testEquals(false,buffer->readError());
+ buffer->readString(s);
+ testEquals(true, buffer->readError());
+ }
+};
+
+TESTMAIN(TestBuffer);
diff --git a/tests/testchangenotify.cc b/tests/testchangenotify.cc
new file mode 100644
index 0000000..bc40a96
--- /dev/null
+++ b/tests/testchangenotify.cc
@@ -0,0 +1,195 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "value.h"
+#include "connect.h"
+#include "test.h"
+#include <iostream.h>
+#include <stdio.h>
+
+using namespace std;
+using namespace Arts;
+
+struct TestChangeNotify : public TestCase
+{
+ TESTCASE(TestChangeNotify);
+
+ Arts::Dispatcher dispatcher;
+ float zero, three, four;
+
+ void setUp()
+ {
+ zero = 0.0;
+ three = 3.0;
+ four = 4.0;
+ }
+
+ void process()
+ {
+ dispatcher.ioManager()->processOneEvent(false);
+ }
+
+ TEST(floatValue)
+ {
+ FloatValue f;
+
+ testEquals(zero, f.value());
+
+ f.value(three);
+ testEquals(three, f.value());
+ }
+ TEST(stringValue)
+ {
+ StringValue s;
+
+ testEquals("",s.value());
+
+ s.value("hello");
+ testEquals("hello", s.value());
+ }
+ TEST(floatNotify)
+ {
+ FloatValue f1, f2;
+
+ connect(f1,"value_changed",f2,"value");
+ f1.value(three);
+
+ process();
+ testEquals(three, f2.value());
+ }
+ TEST(floatMultiNotify)
+ {
+ FloatValue f1, f2, f3;
+
+ connect(f1,"value_changed",f2,"value");
+ connect(f1,"value_changed",f3,"value");
+ f1.value(three);
+
+ process();
+ testEquals(three, f2.value());
+ testEquals(three, f3.value());
+ }
+ TEST(floatCrossNotify)
+ {
+ FloatValue f1, f2;
+
+ connect(f1,"value_changed",f2,"value");
+ connect(f2,"value_changed",f1,"value");
+ f1.value(three);
+
+ process();
+ testEquals(three, f1.value());
+ testEquals(three, f2.value());
+
+ f2.value(four);
+
+ process();
+ testEquals(four, f1.value());
+ testEquals(four, f2.value());
+ }
+ TEST(stringNotify)
+ {
+ StringValue s1, s2;
+
+ connect(s1,"value_changed",s2,"value");
+ s1.value("hello");
+
+ process();
+ testEquals("hello", s2.value());
+ }
+ TEST(stringMultiNotify)
+ {
+ StringValue s1, s2, s3;
+
+ connect(s1,"value_changed",s2,"value");
+ connect(s1,"value_changed",s3,"value");
+ s1.value("hello");
+
+ process();
+ testEquals("hello", s2.value());
+ testEquals("hello", s3.value());
+ }
+ TEST(stringCrossNotify)
+ {
+ StringValue s1, s2;
+
+ connect(s1,"value_changed",s2,"value");
+ connect(s2,"value_changed",s1,"value");
+ s1.value("world");
+
+ process();
+ testEquals("world", s1.value());
+ testEquals("world", s2.value());
+
+ s2.value("test");
+
+ process();
+ testEquals("test", s1.value());
+ testEquals("test", s2.value());
+ }
+ TEST(floatSenderToValue1)
+ {
+ FloatSender sender;
+ FloatValue f;
+
+ connect(sender,"outstream",f,"value");
+ vector<float> data;
+ data.push_back(three);
+ sender.send(data);
+
+ process();
+ testEquals(three,f.value());
+ }
+ TEST(floatSenderToValue2)
+ {
+ FloatSender sender;
+ FloatValue f;
+
+ connect(sender,"outstream",f,"value");
+ vector<float> data;
+ data.push_back(three);
+ data.push_back(four);
+ sender.send(data);
+
+ process();
+ testEquals(four,f.value());
+ }
+ TEST(myEnumNotify)
+ {
+ MyEnumValue e1, e2;
+
+ connect(e1,"value_changed",e2,"value");
+
+ testEquals(meIdle, e1.value());
+ testEquals(meIdle, e2.value());
+
+ e1.value(meHelloWorld);
+ process();
+
+ testEquals(meHelloWorld, e1.value());
+ testEquals(meHelloWorld, e2.value());
+ }
+};
+
+TESTMAIN(TestChangeNotify);
diff --git a/tests/testdispatcher.cc b/tests/testdispatcher.cc
new file mode 100644
index 0000000..c3d68a8
--- /dev/null
+++ b/tests/testdispatcher.cc
@@ -0,0 +1,41 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "dispatcher.h"
+#include "test.h"
+
+using namespace Arts;
+using namespace std;
+
+struct TestDispatcher : public TestCase
+{
+ TESTCASE(TestDispatcher);
+
+ TEST(newDispatcher) {
+ for(int i = 0;i < 10; i++) {
+ Dispatcher *dispatcher = new Dispatcher();
+ delete dispatcher;
+ }
+ }
+};
+
+TESTMAIN(TestDispatcher);
diff --git a/tests/testflowsystem.cc b/tests/testflowsystem.cc
new file mode 100644
index 0000000..7763fb2
--- /dev/null
+++ b/tests/testflowsystem.cc
@@ -0,0 +1,83 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "flowsystem.h"
+#include "connect.h"
+#include "value.h"
+#include "test.h"
+
+using namespace Arts;
+using namespace std;
+
+struct TestFlowSystem : public TestCase
+{
+ TESTCASE(TestFlowSystem);
+
+ Dispatcher dispatcher;
+ StringValue v1, v2;
+
+ void process() {
+ dispatcher.ioManager()->processOneEvent(false);
+ }
+ void setUp() {
+ /* initialize v1, v2 with values */
+ v1 = StringValue(); v1.value("v1");
+ v2 = StringValue(); v2.value("v2");
+ }
+ void tearDown() {
+ v1 = StringValue::null();
+ v2 = StringValue::null();
+ }
+ TEST(connectObject) {
+ dispatcher.flowSystem()->connectObject(v1,"value_changed",v2,"value");
+
+ testEquals("v1",v1.value());
+ testEquals("v2",v2.value());
+
+ v1.value("test");
+ process();
+
+ testEquals("test",v1.value());
+ testEquals("test",v2.value());
+ }
+ // at the time of writing, this fails: disconnectObject is not implemented
+ TEST(disconnectObject) {
+ connect(v1,"value_changed",v2,"value");
+
+ /* here we have a connection, so this should be sent */
+ v1.value("sendThis");
+ process();
+ testEquals("sendThis", v2.value());
+
+ dispatcher.flowSystem()->disconnectObject(v1,"value_changed",
+ v2,"value");
+
+ /* here we don't have a connection, so this should not be sent */
+ v1.value("v1only");
+ process();
+
+ testEquals("v1only", v1.value());
+ testEquals("sendThis", v2.value());
+ }
+};
+
+TESTMAIN(TestFlowSystem);
diff --git a/tests/testifacerepo.cc b/tests/testifacerepo.cc
new file mode 100644
index 0000000..8464cf5
--- /dev/null
+++ b/tests/testifacerepo.cc
@@ -0,0 +1,84 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include <algorithm>
+#include "common.h"
+#include "test.h"
+
+using namespace Arts;
+using namespace std;
+
+struct TestInterfaceRepo : public TestCase
+{
+ TESTCASE(TestInterfaceRepo);
+
+ Arts::Dispatcher dispatcher;
+ Arts::InterfaceRepo interfaceRepo;
+
+ void setUp() {
+ interfaceRepo = Arts::Dispatcher::the()->interfaceRepo();
+ }
+ TEST(queryInterface) {
+ InterfaceDef def = interfaceRepo.queryInterface("Arts::InterfaceRepo");
+
+ testEquals("Arts::InterfaceRepo",def.name);
+ }
+ TEST(queryType) {
+ TypeDef def = interfaceRepo.queryType("Arts::MethodDef");
+
+ testEquals("Arts::MethodDef",def.name);
+ }
+ TEST(queryEnum) {
+ EnumDef def = interfaceRepo.queryEnum("Arts::AttributeType");
+
+ testEquals("Arts::AttributeType",def.name);
+ }
+ bool contains(vector<string>& sequence, const string& element)
+ {
+ vector<string>::iterator it;
+ it = find(sequence.begin(),sequence.end(), element);
+ return (it != sequence.end());
+ }
+ TEST(queryInterfaces) {
+ vector<string> *interfaces = interfaceRepo.queryInterfaces();
+
+ testAssert(contains(*interfaces,"Arts::InterfaceRepo"));
+ testAssert(!contains(*interfaces,"Arts::MethodDef"));
+ delete interfaces;
+ }
+ TEST(queryTypes) {
+ vector<string> *types = interfaceRepo.queryTypes();
+
+ testAssert(contains(*types,"Arts::MethodDef"));
+ testAssert(!contains(*types,"Arts::AttributeType"));
+ delete types;
+ }
+ TEST(queryEnums) {
+ vector<string> *enums = interfaceRepo.queryEnums();
+
+ testAssert(contains(*enums,"Arts::AttributeType"));
+ testAssert(!contains(*enums,"Arts::InterfaceRepo"));
+ delete enums;
+ }
+};
+
+TESTMAIN(TestInterfaceRepo);
diff --git a/tests/testnotification.cc b/tests/testnotification.cc
new file mode 100644
index 0000000..e36391f
--- /dev/null
+++ b/tests/testnotification.cc
@@ -0,0 +1,146 @@
+ /*
+
+ Copyright (C) 2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "notification.h"
+#include "dispatcher.h"
+#include "test.h"
+
+using namespace Arts;
+using namespace std;
+
+static string messagesReceived;
+static long messagesAlive;
+
+static void destroyString(const Notification& n)
+{
+ messagesAlive--;
+ delete (string *)n.data;
+}
+
+class Receiver : public NotificationClient {
+private:
+ long alive;
+
+public:
+ Receiver() { alive = 42; }
+ virtual ~Receiver() {
+ NotificationManager::the()->removeClient(this);
+ alive = 0;
+ }
+
+ void notify(const Notification& n) {
+ if(alive != 42) messagesReceived += "<dead>";
+
+ string *data = (string *)n.data;
+ messagesReceived += *data;
+ destroyString(n);
+
+ if(alive != 42) messagesReceived += "</dead>";
+ }
+};
+
+struct TestNotification : public TestCase
+{
+ TESTCASE(TestNotification);
+
+ Dispatcher dispatcher;
+
+ void setUp() {
+ messagesReceived = "";
+ messagesAlive = 0;
+ }
+ void tearDown() {
+ }
+ void sendNotification(Receiver& r, string text)
+ {
+ messagesAlive++;
+ Notification n;
+ n.receiver = &r;
+ n.data = new string(text);
+ n.internal = 0;
+ n.setDestroy(destroyString);
+ NotificationManager::the()->send(n);
+ }
+
+ /* sending a notification (should be asynchronous) */
+ TEST(send) {
+ Receiver r1;
+ sendNotification(r1,"r1");
+
+ testEquals(1,messagesAlive);
+ testEquals("",messagesReceived);
+ testEquals(true, NotificationManager::the()->pending());
+
+ NotificationManager::the()->run();
+
+ testEquals("r1",messagesReceived);
+ testEquals(false, NotificationManager::the()->pending());
+ testEquals(0,messagesAlive);
+ }
+
+ /* order of sending notifications (first-in-first-out) */
+ TEST(sendOrder) {
+ Receiver r1,r2;
+
+ sendNotification(r1,"r1");
+ sendNotification(r2,"r2");
+
+ testEquals(2,messagesAlive);
+ testEquals("",messagesReceived);
+ testEquals(true, NotificationManager::the()->pending());
+
+ NotificationManager::the()->run();
+
+ testEquals(false, NotificationManager::the()->pending());
+ testEquals(0,messagesAlive);
+ testEquals("r1r2",messagesReceived);
+ }
+
+ /* deletion of unprocessed notifications once a client dies */
+ TEST(clientDeletion) {
+ Receiver *r1 = new Receiver,
+ *r2 = new Receiver,
+ *r3 = new Receiver,
+ *r4 = new Receiver;
+
+ sendNotification(*r1,"r1");
+ sendNotification(*r2,"r2");
+ sendNotification(*r3,"r3");
+ sendNotification(*r4,"r4");
+
+ testEquals(4,messagesAlive);
+ testEquals("",messagesReceived);
+
+ delete r2;
+ delete r4;
+
+ testEquals(2,messagesAlive);
+ testEquals("",messagesReceived);
+
+ NotificationManager::the()->run();
+
+ testEquals("r1r3",messagesReceived);
+ testEquals(0,messagesAlive);
+ }
+};
+
+TESTMAIN(TestNotification);
diff --git a/tests/testremote.cc b/tests/testremote.cc
new file mode 100644
index 0000000..eeaa6a0
--- /dev/null
+++ b/tests/testremote.cc
@@ -0,0 +1,176 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "remotetest.h"
+#include "value.h"
+#include "test.h"
+#include "connect.h"
+#include <iostream.h>
+#include <stdio.h>
+
+using namespace std;
+using namespace Arts;
+
+class RemoteTest_impl: virtual public RemoteTest_skel {
+private:
+ bool alive;
+
+public:
+ RemoteTest_impl()
+ {
+ alive = true;
+ _copy();
+ }
+ ~RemoteTest_impl()
+ {
+ Dispatcher::the()->terminate();
+ }
+
+ Object createObject(const string& name)
+ {
+ return SubClass(name);
+ }
+ long fortyTwo()
+ {
+ return 42;
+ }
+ void die()
+ {
+ if(alive)
+ {
+ _release();
+ alive = false;
+ }
+ }
+};
+
+REGISTER_IMPLEMENTATION(RemoteTest_impl);
+
+/* name of the remote object - should be sufficiently unique */
+char objectName[60];
+
+struct TestRemote : public TestCase
+{
+ TESTCASE(TestRemote);
+
+ Arts::Dispatcher dispatcher;
+ RemoteTest remoteTest;
+
+ void setUp() {
+ string globalRef = "global:";
+ globalRef += objectName;
+
+ remoteTest = Arts::Reference(globalRef);
+ }
+ void tearDown() {
+ remoteTest = RemoteTest::null();
+ }
+
+ void process()
+ {
+ dispatcher.ioManager()->processOneEvent(false);
+ }
+
+
+ /* test whether the server is running, and we could connect ok */
+ TEST(connected) {
+ testEquals(false, remoteTest.isNull());
+ }
+
+ /* test method call */
+ TEST(fortyTwo) {
+ testEquals(42, remoteTest.fortyTwo());
+ }
+
+ /* test remote change notifications */
+ TEST(remoteChangeNotify) {
+ StringValue local;
+ local.value("local");
+ testEquals("local", local.value());
+
+ Object o = remoteTest.createObject("StringValue");
+ testAssert(!o.isNull());
+
+ StringValue remote = Arts::DynamicCast(o);
+ testAssert(!remote.isNull());
+ remote.value("remote");
+ testEquals("remote", remote.value());
+
+ connect(local,"value_changed",remote,"value");
+ local.value("transferme");
+
+ process();
+ sleep(1); /* change notifications are asynchronous */
+
+ testEquals("transferme", local.value());
+ testEquals("transferme", remote.value());
+
+ disconnect(local,"value_changed",remote,"value");
+
+ local.value("notransfer");
+
+ testEquals("notransfer", local.value());
+ testEquals("transferme", remote.value());
+ }
+
+ /* terminate server */
+ TEST(die) {
+ remoteTest.die();
+ remoteTest = RemoteTest::null();
+ sleep(1);
+ }
+
+ /* check if server is dead now */
+ TEST(dead) {
+ testEquals(true, remoteTest.isNull());
+ }
+};
+
+TESTMAINFUNC(TestRemote,performTests);
+
+/*
+ * this test case is a bit tricky because we need a client and a server
+ *
+ * we create the server in a fork()ed process, and then evaluate the test
+ * inside the client
+ */
+int main()
+{
+ /* create unique object name for test server/test client */
+ sprintf(objectName, "RemoteTest_%d_%ld", getpid(), time(0));
+
+ int pid = fork();
+ if(pid == 0) /* child process - we play the server here */
+ {
+ Dispatcher dispatcher(0, Dispatcher::startUnixServer);
+ ObjectManager::the()->addGlobalReference(RemoteTest(), objectName);
+ dispatcher.run();
+ return 0;
+ }
+ else if(pid >= 0) /* parent process - do the test here */
+ {
+ sleep(1);
+ return performTests();
+ }
+}
diff --git a/tests/testwrapper.cc b/tests/testwrapper.cc
new file mode 100644
index 0000000..c590f36
--- /dev/null
+++ b/tests/testwrapper.cc
@@ -0,0 +1,211 @@
+ /*
+
+ Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Permission is also granted to link this program with the Qt
+ library, treating Qt like a library that normally accompanies the
+ operating system kernel, whether or not that is in fact the case.
+
+ */
+
+#include "wrapper.h"
+#include "test.h"
+#include <iostream.h>
+#include <stdio.h>
+
+using namespace std;
+using namespace Arts;
+
+int active_d_objects = 0;
+
+class D_impl: virtual public D_skel {
+private:
+ long _value;
+public:
+ void value(long newVal) { _value = newVal; }
+ long value() { return _value; }
+
+ D_impl() :_value(0) { active_d_objects++; }
+ ~D_impl() { active_d_objects--; }
+ string a() { return "a"; }
+ string b() { return "b"; }
+ string c() { return "c"; }
+ string d() { return "d"; }
+ void dummy() { }
+
+ long sum(A v1, A v2) { return v1.value() + v2.value(); }
+ D self() { return D::_from_base(_copy()); }
+};
+
+REGISTER_IMPLEMENTATION(D_impl);
+
+class B_impl: virtual public B_skel {
+private:
+ long _value;
+public:
+ void value(long newVal) { _value = newVal; }
+ long value() { return _value; }
+ B_impl() :_value(0) {}
+ string a() { return "a"; }
+ string b() { return "b"; }
+};
+REGISTER_IMPLEMENTATION(B_impl);
+
+
+struct TestWrapper : public TestCase
+{
+ TESTCASE(TestWrapper);
+
+ Arts::Dispatcher dispatcher;
+
+ /*
+ generic inheritance test, tests that using a D object, you
+ can call the a,b,c,d methods without problems
+ */
+ TEST(genericInheritance)
+ {
+ D d;
+
+ /* implications of lazy creation */
+ testEquals(0, active_d_objects);
+
+ C c = d;
+ testEquals(0, active_d_objects);
+
+ string abcd = A(d).a()+d.b()+c.c()+d.d();
+ testEquals("abcd",abcd);
+
+ /*
+ should be exactly one here, not more than one through the various
+ assignments
+ */
+ testEquals(1, active_d_objects);
+
+ Object o = d;
+
+ /* dynamic casting tests */
+ c = DynamicCast(o); // operator
+ testEquals(false, c.isNull());
+ testEquals("c", c.c());
+
+ C cc = DynamicCast(o); // constructor
+ testEquals(false, cc.isNull());
+ testEquals("c", cc.c());
+
+ A a = Reference(d.toString());
+ cc = DynamicCast(a);
+ testEquals(false, cc.isNull());
+ testEquals("c", cc.c());
+
+ /* isNull() and error() */
+ testEquals(false, d.isNull());
+ testEquals(false, d.error());
+
+ d = D::null();
+ testEquals(true, d.isNull());
+ testEquals(false, c.isNull());
+ testEquals(false, d.error());
+
+ /* reference counting */
+ c = C::null();
+ o = Object::null();
+ cc = C::null();
+ a = A::null();
+ testEquals(0, active_d_objects);
+ }
+ TEST(nullInAssign) {
+ B b;
+ B b2 = b;
+ b = B::null();
+ testEquals(true, b.isNull());
+ testEquals(false, b2.isNull());
+ }
+ TEST(coreference) {
+ B b3;
+ B b4=b3;
+ b3.value(3);
+ testEquals(3, b4.value());
+ }
+
+ D afunc(D arg)
+ {
+ arg.value(42);
+ return arg;
+ }
+
+ TEST(cacheAndArgs) {
+ /* test cache invalidation */
+ B b;
+ b.value(3); // stores 3 using parent method
+ testEquals(0, active_d_objects);
+
+ D d;
+ d.value(6);
+ testEquals(1, active_d_objects);
+
+ b = d; // uses operator, not constructor. should invalidate A::cacheOK
+ testEquals(6, b.value());
+ testEquals(1, active_d_objects);
+
+ A a = afunc(d);
+ testEquals(1, active_d_objects);
+ testEquals(42, a.value());
+ testEquals(42, b.value());
+ testEquals(42, d.value());
+ }
+
+ TEST(dynamicCastNull) {
+ D normalD;
+ D nullD = D::null();
+ A aNormalD = normalD;
+ A aNullD = nullD;
+ D d;
+
+ d = DynamicCast(aNormalD);
+ testEquals(false, d.isNull());
+
+ d = DynamicCast(aNullD);
+ testEquals(true, d.isNull());
+ }
+
+ TEST(stringification) {
+ D d;
+ d.value(5);
+
+ string s = d.toString();
+
+ D anotherD = Arts::Reference(s);
+ testEquals(false, anotherD.isNull());
+ testEquals(5, anotherD.value());
+ }
+ /*
+ unfortunately, this currently fails, because resolving a reference to a
+ non-existing object is not handled properly by the dispatcher - I am not
+ sure whether it is worth fixing it (which might be complicated)
+
+ TEST(stringificationFailures) {
+ D d;
+ d.value(5);
+ string s = d.toString();
+ d = D::null();
+
+ D anotherD = Arts::Reference(s);
+ testEquals(true, anotherD.isNull());
+ }*/
+};
+
+TESTMAIN(TestWrapper);
diff --git a/tests/value.idl b/tests/value.idl
new file mode 100644
index 0000000..ae5e15c
--- /dev/null
+++ b/tests/value.idl
@@ -0,0 +1,18 @@
+interface FloatValue {
+ attribute float value;
+};
+
+interface StringValue {
+ attribute string value;
+};
+
+enum MyEnum { meIdle, meHelloWorld };
+
+interface MyEnumValue {
+ attribute MyEnum value;
+};
+
+interface FloatSender {
+ void send(sequence<float> data);
+ async out float stream outstream;
+};
diff --git a/tests/value_impl.cc b/tests/value_impl.cc
new file mode 100644
index 0000000..cdb4343
--- /dev/null
+++ b/tests/value_impl.cc
@@ -0,0 +1,94 @@
+ /*
+
+ Copyright (C) 2000-2001 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "value.h"
+
+using namespace std;
+
+class FloatValue_impl : virtual public FloatValue_skel {
+private:
+ float _value;
+public:
+ FloatValue_impl() : _value(0) { };
+ void value(float newvalue)
+ {
+ if(newvalue != _value)
+ {
+ _value = newvalue;
+ value_changed(_value);
+ }
+ }
+ float value() { return _value; }
+};
+
+REGISTER_IMPLEMENTATION(FloatValue_impl);
+
+class StringValue_impl : virtual public StringValue_skel {
+private:
+ string _value;
+public:
+ StringValue_impl() { };
+ void value(const string& newvalue)
+ {
+ if(newvalue != _value)
+ {
+ _value = newvalue;
+ value_changed(_value);
+ }
+ }
+ string value() { return _value; }
+};
+
+REGISTER_IMPLEMENTATION(StringValue_impl);
+
+class FloatSender_impl : virtual public FloatSender_skel {
+public:
+ void send(const vector<float>& data)
+ {
+ Arts::DataPacket<float> *packet = outstream.allocPacket(data.size());
+ copy(data.begin(), data.end(), packet->contents);
+ packet->size = data.size();
+ packet->send();
+ }
+};
+
+REGISTER_IMPLEMENTATION(FloatSender_impl);
+
+class MyEnumValue_impl : virtual public MyEnumValue_skel {
+private:
+ MyEnum _value;
+public:
+ MyEnumValue_impl() : _value(meIdle) { };
+ void value(MyEnum newvalue)
+ {
+ if(newvalue != _value)
+ {
+ _value = newvalue;
+ value_changed(_value);
+ }
+ }
+ MyEnum value() { return _value; }
+};
+
+REGISTER_IMPLEMENTATION(MyEnumValue_impl);
+
+
diff --git a/tests/wrapper.idl b/tests/wrapper.idl
new file mode 100644
index 0000000..dc0c0b6
--- /dev/null
+++ b/tests/wrapper.idl
@@ -0,0 +1,27 @@
+/*------------------- Test classes for smartwrappers ---------------------*/
+
+interface A {
+ attribute long value;
+ string a(); // returns "a"
+};
+
+interface B : A {
+ string b(); // returns "b"
+};
+
+interface C : A {
+ string c(); // returns "c"
+};
+
+interface D : B, C {
+ // returns the interface itself
+ readonly attribute D self;
+
+ string d(); // returns "d"
+
+ // returns sum of both interface values
+ long sum(A v1, A v2);
+
+ // dummy method
+ void dummy();
+};
diff --git a/x11/Makefile.am b/x11/Makefile.am
new file mode 100644
index 0000000..3a86768
--- /dev/null
+++ b/x11/Makefile.am
@@ -0,0 +1,29 @@
+if include_x11
+
+INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop $(all_includes)
+
+lib_LTLIBRARIES = libx11globalcomm.la
+
+libx11globalcomm_la_SOURCES = x11globalcomm.cc x11globalcomm_impl.cc
+libx11globalcomm_la_LIBADD = $(top_builddir)/mcop/libmcop.la $(LIB_X11)
+libx11globalcomm_la_LDFLAGS = -no-undefined -module -version-info 1:0 $(X_LDFLAGS) $(all_libraries)
+
+DISTCLEANFILES = x11globalcomm.cc x11globalcomm.h \
+ x11globalcomm.mcoptype x11globalcomm.mcopclass
+
+x11globalcomm.cc x11globalcomm.h: $(srcdir)/x11globalcomm.idl $(MCOPIDL)
+ $(MCOPIDL) -t $(INCLUDES) $(srcdir)/x11globalcomm.idl
+
+x11globalcomm_impl.lo: x11globalcomm.h
+x11globalcomm.mcoptype: x11globalcomm.h
+x11globalcomm.mcopclass: x11globalcomm.h
+
+mcopclassdir = $(libdir)/mcop/Arts
+mcopclass_DATA = X11GlobalComm.mcopclass
+
+######## install idl typeinfo files
+
+mcoptypedir = $(libdir)/mcop
+mcoptype_DATA = x11globalcomm.mcoptype x11globalcomm.mcopclass
+
+endif
diff --git a/x11/X11GlobalComm.mcopclass b/x11/X11GlobalComm.mcopclass
new file mode 100644
index 0000000..501a080
--- /dev/null
+++ b/x11/X11GlobalComm.mcopclass
@@ -0,0 +1,3 @@
+Language=C++
+Library=libx11globalcomm.la
+Interface=Arts::Object,Arts::GlobalComm,Arts::X11GlobalComm
diff --git a/x11/x11globalcomm.idl b/x11/x11globalcomm.idl
new file mode 100644
index 0000000..c799497
--- /dev/null
+++ b/x11/x11globalcomm.idl
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 1999 Stefan Westerfeld
+ stefan@space.twc.de
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <core.idl>
+
+module Arts {
+
+/**
+ * global communication based on an X11 server property on the root window
+ */
+interface X11GlobalComm : GlobalComm {
+};
+
+};
diff --git a/x11/x11globalcomm_impl.cc b/x11/x11globalcomm_impl.cc
new file mode 100644
index 0000000..66d6c5f
--- /dev/null
+++ b/x11/x11globalcomm_impl.cc
@@ -0,0 +1,184 @@
+/*
+ Copyright (C) 1997 Mark Donohoe (donohoe@kde.org)
+ Copyright (C) 2000 Stefan Westerfeld (stefan@space.twc.de)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * This is based on Mark Donohoe's nice KRootProp class (found in
+ * kdelibs/kdecore/krootprop.cpp). I couldn't use KRootProp directly, since
+ * I wanted aRts (and even it's X11 support) to work without KDE and/or Qt
+ * installed at all.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include "x11globalcomm.h"
+#include "debug.h"
+#include <iostream>
+
+using namespace std;
+using namespace Arts;
+
+class X11GlobalComm_impl : virtual public X11GlobalComm_skel {
+protected:
+ Display *X11display;
+ Window rootWin;
+ Atom atom;
+ map<string,string> propertyMap;
+ bool init;
+
+ void warn(const char *what)
+ {
+ arts_warning("X11GlobalComm: %s", what);
+ }
+public:
+ X11GlobalComm_impl() :rootWin(0), atom(0)
+ {
+ X11display = XOpenDisplay(NULL);
+ if(!X11display)
+ {
+ warn("Can't connect to the XServer - Initial references won't work.");
+ init = false;
+ }
+ else
+ {
+ rootWin = DefaultRootWindow(X11display);
+ atom = XInternAtom( X11display, "MCOPGLOBALS" , False);
+ init = true;
+ }
+ }
+
+ ~X11GlobalComm_impl()
+ {
+ if(X11display)
+ XCloseDisplay(X11display);
+ }
+
+ void read()
+ {
+ if(!init) return;
+
+ Atom type;
+ int format;
+ unsigned long nitems;
+ unsigned long bytes_after;
+ long offset;
+ unsigned char *buf;
+
+ propertyMap.clear();
+
+ // If a property has already been opened write
+ // the dictionary back to the root window
+
+ string s;
+ offset = 0; bytes_after = 1;
+ while (bytes_after != 0)
+ {
+ XGetWindowProperty( X11display, rootWin, atom, offset, 256,
+ False, XA_STRING, &type, &format, &nitems, &bytes_after,
+ &buf);
+
+ if(type == None) // no property -> no contents
+ return;
+
+ s += (char*) buf;
+ offset += nitems/4;
+ if (buf)
+ XFree((char*) buf);
+ }
+
+ // Parse through the property string stripping out key value pairs
+ // and putting them in the dictionary
+
+ while(s.length() >0 )
+ {
+ // parse the string for first key-value pair separator '\n'
+ int i = s.find("\n",0);
+
+ // extract the key-values pair and remove from string
+
+ string keypair = s.substr(0,i);
+ s = s.substr(i+1,s.size()-(i+1));
+
+ // split key and value and add to dictionary
+
+ i = keypair.find( "=" );
+ if( i != -1 )
+ {
+ string key = keypair.substr( 0, i );
+ string value = keypair.substr( i+1, keypair.size()-(i+1) );
+ propertyMap[key] = value;
+ }
+ }
+ }
+
+ void write()
+ {
+ if(!init) return;
+
+ // bring map in the variable=value form with \n as seperator
+ string propString;
+
+ map<string,string>::iterator i = propertyMap.begin();
+ for(i = propertyMap.begin(); i != propertyMap.end(); i++)
+ propString += i->first + "=" + i->second + "\n";
+
+ // send to the X11 server
+ XChangeProperty( X11display, rootWin, atom,
+ XA_STRING, 8, PropModeReplace,
+ (const unsigned char *)propString.c_str(),
+ propString.size()+1);
+ XFlush(X11display);
+ }
+
+ bool put(const string& variable, const string& value)
+ {
+ if(!init) return false;
+
+ read();
+ if(propertyMap[variable].empty())
+ {
+ propertyMap[variable] = value;
+ write();
+ return true;
+ }
+ return false;
+ }
+
+ string get(const string& variable)
+ {
+ if(!init) return "";
+
+ read();
+ return propertyMap[variable];
+ }
+
+ void erase(const string& variable)
+ {
+ if(!init) return;
+
+ read();
+ propertyMap.erase(variable);
+ write();
+ }
+};
+
+REGISTER_IMPLEMENTATION(X11GlobalComm_impl);