.svn folder removed.
Change-Id: I8ae32b3fa09d6a6a8d023e8b8518d0346a0e0aea
--- /dev/null
+Thanks to the following people, without whose advice and encouragement
+Remix would never have seen the light of day. -K.
+
+
+Carsten Haitzler (The Rasterman) <raster@rasterman.com>
+
+ Rasterman wrote Evas, a graphical canvas library. The simplicity of
+Remix's programming interface was inspired by that of Evas, and Rasterman
+has effusively explained the motivation for much of Evas' design to me.
+Having programmed with Evas, and having witnessed Rasterman code up complex
+graphical applications in no time flat using Evas, I knew that it would be
+well worth the effort to write a similarly powerful abstraction library for
+audio.
+
+
+Erik de Castro Lopo <erikd@zip.com.au>
+
+ Erik is the author of libsndfile, and has given excellent advice on
+optimisations for Remix.
+
+
+Silvia Pfeiffer <Silvia.Pfeiffer@CSIRO.AU>
+
+ Silvia supervised the construction of Remix, and has a knack for
+pinpointing obscure design problems and limitations. She prompted the
+creation of Remix after noticing the lack of genericity within early
+versions of Sweep, and she has guided the scope of Remix with an eye to
+ensuring its utility in a wide range of projects.
--- /dev/null
+Conrad Parker <conrad@metadecks.org>
--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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 Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ 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 Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+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 other code 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.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ 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, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 6. As an exception to the Sections above, you may also combine 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) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) 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.
+
+ d) 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.
+
+ e) 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 materials to be 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.
+\f
+ 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 with
+this License.
+\f
+ 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 Lesser 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.
+\f
+ 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
+\f
+ 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!
+
+
--- /dev/null
+Thu May 1 08:58:55 EST 2003 Conrad Parker <conrad@metadecks.org>
+
+ * changed name to libremix, type names to Remix*, funcs remix_*
+
+Sun Apr 27 20:23:15 EST 2003 Conrad Parker <conrad@metadecks.org>
+
+ * added ctxdata.pc
+
+Tue Apr 8 22:57:37 EST 2003 Conrad Parker <conrad@metadecks.org>
+
+ * merged in ALSA monitor support from Erik de Castro Lopo
+ * merged in tests subdir from Erik de Castro Lopo
+ * random bugfixes
+
+Wed Apr 2 22:34:07 EST 2003 Conrad Parker <conrad@metadecks.org>
+
+ * changed name to libmash
+ * made pointer types explicit
+ * changed all type and function names to Mash*/mash_*
+
+Mon Nov 25 2002 Conrad Parker <conrad@metadecks.org>
+
+ * updated to use libsndfile1
+
+Fri Aug 17 11:41:50 EST 2001 Conrad Parker <Conrad.Parker@CSIRO.AU>
+
+ * First build (5000 lines, 3 weeks, much coffee)
--- /dev/null
+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 awhile. 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/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' 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.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ 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. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--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.
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = doc include src
+DIST_SUBDIRS = $(SUBDIRS)
+
+EXTRA_DIST = ACKNOWLEDGEMENTS \
+ ctxdata.pc.in remix.pc.in \
+ remix.spec.in remix.spec
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = ctxdata.pc remix.pc
--- /dev/null
+About libremix
+==============
+
+libremix is a library for audio sequencing and mixing.
+
+More information is available online at the libremix homepage:
+
+http://www.metadecks.org/software/remix/
+
+To receive announcements about new libremix releases, please join the
+remix-announce mailing list listed on the homepage.
+
+Developers
+----------
+
+Please join the remix-devel mailing list, linked from the homepage.
+
+libremix is maintained in Subversion with anonymous read access. You can
+check out the most current version of libremix from:
+
+svn co http://svn.metadecks.org/libremix/trunk libremix
+
+A list of outstanding tasks is maintained in the TODO file of this source
+distribution. When implementing anything listed in this file, please update
+it by deleting that entry, and include that as part of the patch or commit
+that implements the fix.
+
+Copyrights
+----------
+
+Copyright (C) 2000-2010 Conrad Parker <conrad@metadecks.org>
+Copyright (C) 2001, 2002 Commonwealth Scientific and Industrial Research
+Organisation (CSIRO), Australia.
+
+Licence
+-------
+
+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
+
+Contact
+-------
+
+For technical and other queries, please contact the author:
+
+Conrad Parker <conrad@metadecks.org>
+(kfish on #lad or #sweep on Freenode).
--- /dev/null
+
+This is a loosely-categorized list of outstanding tasks and ideas for improving
+libremix. When implementing any of these, please include an update to this TODO
+file removing that task, in the same commit.
+
+* update with TODOs from paper file
+
+Memory leaks
+------------
+
+libremix:
+ * implement remix_destroy_list() in remix_context.c, and call it on
+ world->plugins and world->bases
+
+ladspa:
+ * free schemes created for each ladspa port
--- /dev/null
+#!/bin/sh
+
+package="remix"
+rm -rf autom4te.cache
+rm -f aclocal.m4 ltmain.sh
+
+touch README
+
+echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
+echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1
+echo "Running autoheader..." ; autoheader || exit 1
+echo "Running autoconf..." ; autoconf || exit 1
+echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
+
+if [ -z "$NOCONFIGURE" ]; then
+ ./configure "$@"
+fi
+
--- /dev/null
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to build experimental code */
+#undef ANX_CONFIG_EXPERIMENTAL
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if libsndfile version 1 found */
+#undef HAVE_LIBSNDFILE1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/soundcard.h> header file. */
+#undef HAVE_SYS_SOUNDCARD_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Set the plugin directory for remix */
+#undef PACKAGE_PLUGIN_DIR
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
--- /dev/null
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(src/libremix/remix_base.c)
+
+AM_INIT_AUTOMAKE(remix, 0.2.3)
+AM_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+AM_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AM_PROG_CC_C_O
+
+# Check for doxygen
+AC_CHECK_PROG(HAVE_DOXYGEN, doxygen, true, false)
+AM_CONDITIONAL(HAVE_DOXYGEN,$HAVE_DOXYGEN)
+if test $HAVE_DOXYGEN = "false"; then
+ AC_MSG_WARN([*** doxygen not found, docs will not be built])
+fi
+
+# Check for valgrind
+VALGRIND_ENVIRONMENT=""
+ac_enable_valgrind=no
+AC_ARG_ENABLE(valgrind-testing,
+ [ --enable-valgrind-testing enable running of tests inside Valgrind ], [ ac_enable_valgrind=yes ], [ ac_enable_valgrind=no] )
+
+if test "x${ac_enable_valgrind}" = xyes ; then
+ if test "x${enable_shared}" = xyes ; then
+ VALGRIND_ENVIRONMENT="libtool --mode=execute "
+ fi
+
+ AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no)
+ if test "x$HAVE_VALGRIND" = xyes ; then
+ VALGRIND_ENVIRONMENT="$VALGRIND_ENVIRONMENT valgrind -q --leak-check=yes --show-reachable=yes --num-callers=50"
+ AC_SUBST(VALGRIND_ENVIRONMENT)
+ TESTS_INFO="'make check' test suite will be run under:
+ ${VALGRIND_ENVIRONMENT}"
+ else
+ TESTS_INFO="'make check' to run test suite (Valgrind not found)"
+ fi
+else
+ TESTS_INFO="'make check' to run test suite (Valgrind testing not enabled)"
+fi
+
+dnl
+dnl Configuration option for building of experimental code.
+dnl
+
+ac_enable_experimental=no
+AC_ARG_ENABLE(experimental,
+ [ --enable-experimental enable building of experimental code ],
+ [ ac_enable_experimental=yes ])
+
+if test "x${ac_enable_experimental}" = xyes ; then
+ AC_DEFINE(ANX_CONFIG_EXPERIMENTAL, [], [Define to build experimental code])
+fi
+
+dnl Checks for libraries.
+
+dnl
+dnl Detect libsndfile 1.0
+dnl
+
+PKG_CHECK_MODULES(SNDFILE, sndfile >= 1.0.0,
+ HAVE_LIBSNDFILE1="yes", HAVE_LIBSNDFILE1="no")
+
+AC_SUBST(SNDFILE_LIBS)
+AC_SUBST(SNDFILE_CFLAGS)
+
+if test "$HAVE_LIBSNDFILE1" = "yes" ; then
+ AC_DEFINE([HAVE_LIBSNDFILE1], [], [Define if libsndfile version 1 found])
+ AC_SUBST(SNDFILE_LIBS)
+ AC_SUBST(SNDFILE_CFLAGS)
+else
+ AC_CHECK_LIB(sndfile, sf_open, HAVE_LIBSNDFILE1="maybe")
+ if test "$HAVE_LIBSNDFILE1" = "maybe" ; then
+ AC_MSG_ERROR([
+***
+*** libsndfile-1.0.0 or greater seems to exist on your system, however
+*** the pkg-config tool cannot find its build information.
+***
+*** Please set your PKG_CONFIG_PATH environment variable to include the
+*** directory in which sndfile.pc was installed. For example, sndfile.pc
+*** is installed in /usr/local/lib/pkgconfig by default; if that is the
+*** case do:
+***
+*** export PKG_CONFIG_PATH="\$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig"
+***
+*** then run this ./configure again. If you configured libsndfile with a
+*** different --prefix option, replace /usr/local above with that prefix.
+***
+])
+ fi
+fi
+
+AM_CONDITIONAL(HAVE_LIBSNDFILE1, test "x${HAVE_LIBSNDFILE1}" = xyes)
+
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(limits.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_TYPE_UID_T
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(strdup strerror)
+
+dnl Test for sys/soundcard.h -- if user doesn't have it, don't build remix_monitor
+HAVE_SYS_SOUNDCARD_H=0
+AC_CHECK_HEADERS(sys/soundcard.h)
+ if test "x${ac_cv_header_sys_soundcard_h}" = xyes ; then
+ HAVE_SYS_SOUNDCARD_H=1
+ BUILD_MONITOR=1
+ fi
+AC_SUBST(BUILD_MONITOR)
+AM_CONDITIONAL(BUILD_MONITOR, test -n "$BUILD_MONITOR")
+
+dnl
+dnl Set PACKAGE_PLUGIN_DIR in Makefiles and config.h.
+dnl
+
+PACKAGE_PLUGIN_DIR="${libdir}/remix"
+AC_SUBST(PACKAGE_PLUGIN_DIR)
+if test "x${prefix}" = "xNONE"; then
+ PACKAGE_PLUGIN_DIR="${ac_default_prefix}/lib/remix"
+else
+ PACKAGE_PLUGIN_DIR="${prefix}/lib/remix"
+fi
+AC_DEFINE_UNQUOTED(PACKAGE_PLUGIN_DIR, "$PACKAGE_PLUGIN_DIR",
+ [Set the plugin directory for remix])
+
+AC_ARG_ENABLE(gcc-werror,
+ AC_HELP_STRING([--enable-gcc-werror], [enable -Werror in all Makefiles]))
+
+dnl Use -Wall if we have gcc.
+
+if test "x$ac_cv_prog_gcc" = xyes ; then
+ CFLAGS="$CFLAGS -Wall"
+
+ if test x$enable_gcc_werror = "xyes" ; then
+ CFLAGS="$CFLAGS -Werror"
+ fi
+
+fi
+
+AC_OUTPUT([
+Makefile
+doc/Makefile
+doc/Doxyfile
+include/Makefile
+include/remix/Makefile
+src/Makefile
+src/ctxdata/Makefile
+src/libremix/Makefile
+src/plugins/Makefile
+src/plugins/ladspa/Makefile
+src/plugins/noise/Makefile
+src/examples/Makefile
+src/tests/Makefile
+ctxdata.pc
+remix.pc
+remix.spec
+])
+
+AC_MSG_RESULT([
+------------------------------------------------------------------------
+ $PACKAGE $VERSION: Automatic configuration OK.
+
+ General configuration:
+
+ Experimental code: ........... ${ac_enable_experimental}
+
+ Plugins:
+
+ ladspa noise
+
+ Example programs (./src/examples):
+
+ ${example_programs}
+
+ Installation paths:
+
+ libremix: .................... ${prefix}/lib
+ Plugins: ..................... ${PACKAGE_PLUGIN_DIR}
+ C header files: .............. ${prefix}/include/remix
+ Documentation: ............... ${prefix}/share/doc/$PACKAGE
+
+ Building:
+
+ Type 'make' to compile $PACKAGE.
+
+ Type 'make install' to install $PACKAGE.
+
+ Type 'make check' to test $PACKAGE using the unit tests
+ contained in the src/tests directory.
+ ${TESTS_INFO}
+
+ Example programs will be built but not installed.
+------------------------------------------------------------------------
+])
+
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ctxdata
+Description: data types with functional mappings and context callbacks
+Requires:
+Version: @VERSION@
+Libs: -L${libdir} -lctxdata
+Cflags: -I${includedir}
--- /dev/null
+libremix (0.2.3) unstable; urgency=low
+
+ * Initial Version.
+
+ -- Prince Kumar Dubey <prince.dubey@samsung.com> Govindaraju S M <govi.sm@samsung.com> Tue, 20 Sep 2011 15:00:00 +0900
\ No newline at end of file
--- /dev/null
+Source: libremix
+Section: libs
+Priority: optional
+Uploaders: Prince Kumar Dubey<prince.dubey@samsung.com> Govindaraju S M<govi.sm@samsung.com>
+Maintainer: Conrad Parker <conrad@metadecks.org>
+Build-Depends: cdbs, libsndfile1-dev, pkg-config, libtool
+Standards-Version: 0.2.3
+Homepage: http://www.metadecks.org/software/remix/
+
+Package: libremix
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libsndfile1-dev
+Suggests: libremix (= ${binary:Version})
+Description: Various binaries for use with libremix.
+ Remix is an audio sequencing and mixing library that provides a multichannel,
+ sparse audio data container (streams), a structured mixing abstraction (decks),
+ and widely useful means of generating control data (via envelopes) and of
+ caching audio data.
+
+
+Package: libremix-dev
+Architecture: any
+Section: libdevel
+Depends: ${misc:Depends}, libremix (= ${binary:Version}), libsndfile1-dev
+Description: libremix headers and static libraries
+ Remix is an audio sequencing and mixing library that provides a multichannel,
+ sparse audio data container (streams), a structured mixing abstraction (decks),
+ and widely useful means of generating control data (via envelopes) and of
+ caching audio data.
\ No newline at end of file
--- /dev/null
+This is libremix library, written and maintained by Conrad Parker <conrad@metadecks.org>
+on , Fri Aug 17 11:41:50 EST 2001
+
+The original source can always be found at:
+ http://www.metadecks.org/software/remix/
+
+Copyright (C) 2000-2010 Conrad Parker <conrad@metadecks.org>
+Copyright (C) 2001, 2002 Commonwealth Scientific and Industrial Research Organisation (CSIRO), Australia.
+
+License:
+ 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
--- /dev/null
+debian/tmp/usr/include/*
+debian/tmp/usr/lib/lib*.la
+debian/tmp/usr/lib/lib*.a
+debian/tmp/usr/lib/libremix.so
+debian/tmp/usr/lib/libctxdata.so
+debian/tmp/usr/lib/pkgconfig/*
--- /dev/null
+debian/tmp/usr/lib/libremix.so.*
+debian/tmp/usr/lib/libctxdata.so.*
--- /dev/null
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/class/autotools.mk
+include /usr/share/cdbs/1/rules/debhelper.mk
+
+DEB_CONFIGURE_SCRIPT := ./autogen.sh
+DEB_MAKE_CLEAN_TARGET := distclean
+DEB_CONFIGURE_EXTRA_FLAGS := --enable-dependency-tracking
+
+CFLAGS += -fvisibility=default -fPIC -W -Wall -Wextra
+LDFLAGS += -fvisibility=default -Wl,--hash-style=both -Wl,--as-needed
+
+clean::
+ [ ! -f Makefile ] || make distclean
+ rm -f libremix*.tar.bz2 libremix-*.tar.bz2.cdbs-config_list
--- /dev/null
+# Doxyfile 1.3.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = @PACKAGE@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = libremix
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @top_srcdir@/include/remix
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = ../COPYING ../INSTALL ../src/examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = .
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output dir.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assigments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similiar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
--- /dev/null
+docdir=$(prefix)/share/doc/@PACKAGE@
+
+EXTRA_DIST = Doxyfile.in
+
+doc_DATA = doxygen-build.stamp
+
+if HAVE_DOXYGEN
+doxygen-build.stamp: Doxyfile $(top_srcdir)/include/remix/*.h
+ doxygen
+ touch doxygen-build.stamp
+else
+doxygen-build.stamp:
+ echo "*** Warning: Doxygen not found; documentation will not be built."
+ touch doxygen-build.stamp
+endif
+
+dist_docdir = $(distdir)/libremix
+
+dist-hook:
+ if test -d libremix; then \
+ mkdir $(dist_docdir); \
+ for dir in libremix/*; do \
+ if test -d $$dir; then \
+ b=`basename $$dir`; \
+ mkdir $(dist_docdir)/$$b; \
+ for f in $$dir/*; do \
+ cp -p $$f $(dist_docdir)/$$b; \
+ done \
+ fi \
+ done \
+ fi
+
+
+install-data-local: doxygen-build.stamp
+ $(mkinstalldirs) $(docdir)
+ if test -d libremix; then \
+ for dir in libremix/*; do \
+ if test -d $$dir; then \
+ b=`basename $$dir`; \
+ $(mkinstalldirs) $(docdir)/$$b; \
+ for f in $$dir/*; do \
+ $(INSTALL_DATA) $$f $(docdir)/$$b; \
+ done \
+ fi \
+ done \
+ fi
+
+uninstall-local:
+ rm -rf $(docdir)
+
+clean-local:
+ if test -d libremix; then rm -rf libremix; fi
+ if test -f doxygen-build.stamp; then rm -f doxygen-build.stamp; fi
+
--- /dev/null
+
+SUBDIRS = remix
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+# Include files to install
+includedir = $(prefix)/include/remix
+
+include_HEADERS = \
+ remix.h remix_types.h remix_time.h remix_meta.h \
+ remix_deck.h remix_stream.h \
+ remix_envelope.h \
+ remix_plugin.h
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/** \file
+ * Base types and public interfaces to libremix
+ *
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_H__
+#define __REMIX_H__
+
+/** \mainpage
+ *
+ * \section Introduction
+ *
+ * Remix is an audio sequencing and mixing library that provides a
+ * multichannel, sparse audio data container (streams), a structured mixing
+ * abstraction (decks), and widely useful means of generating control data
+ * (via envelopes) and of caching audio data.
+ *
+ * \subsection contents Contents
+ *
+ * - \link remix_deck.h Decks \endlink:
+ * The Remix hierarchical mixing abstraction
+ *
+ * - \link remix_stream.h Streams \endlink:
+ * The multichannel PCM stream abstraction
+ *
+ * - \link remix.h remix.h \endlink:
+ * Documentation of the Remix C API
+ *
+ * - \link examples Examples \endlink:
+ * Annotated example programs
+ *
+ * - \link configuration Configuration \endlink:
+ * Customizing libremix.
+ *
+ * - \link building Building \endlink:
+ * Information related to building software that uses libremix.
+ *
+ * \section licensing Licensing
+ *
+ * libremix is provided under the
+ * \link lgpl GNU Lesser General Public License \endlink.
+ *
+ */
+
+/** \defgroup lgpl Licensing
+ * \section lgpl GNU Lesser General Public License
+ *
+ * \include COPYING
+ */
+
+/** \defgroup configuration Configuration
+ * \section ./configure ./configure
+ *
+ * It is possible to customize the functionality of libremix
+ * by using various ./configure flags when
+ * building it from source.
+ *
+ * For general information about using ./configure, see the file
+ * \link install INSTALL \endlink
+ */
+
+/** \defgroup install Installation
+ * \section install INSTALL
+ *
+ * \include INSTALL
+ */
+
+/** \defgroup building Building against libremix
+ *
+ *
+ * \section autoconf Using GNU autoconf
+ *
+ * If you are using GNU autoconf, you do not need to call pkg-config
+ * directly. Use the following macro to determine if libremix is
+ * available:
+ *
+ <pre>
+ PKG_CHECK_MODULES(REMIX, remix >= 0.2.0,
+ HAVE_REMIX="yes", HAVE_REMIX="no")
+ if test "x$HAVE_REMIX" = "xyes" ; then
+ AC_SUBST(REMIX_CFLAGS)
+ AC_SUBST(REMIX_LIBS)
+ fi
+ </pre>
+ *
+ * If libremix is found, HAVE_REMIX will be set to "yes", and
+ * the autoconf variables REMIX_CFLAGS and REMIX_LIBS will
+ * be set appropriately.
+ *
+ * \section pkg-config Determining compiler options with pkg-config
+ *
+ * If you are not using GNU autoconf in your project, you can use the
+ * pkg-config tool directly to determine the correct compiler options.
+ *
+ <pre>
+ REMIX_CFLAGS=`pkg-config --cflags remix`
+
+ REMIX_LIBS=`pkg-config --libs remix`
+ </pre>
+ *
+ */
+
+/** \defgroup examples Example programs
+ *
+ * Example programs are fun for all the family.
+ *
+ * Here's some examples.
+ * - \link noisedemo Noise demo \endlink
+ * - \link squaredemo Square demo \endlink
+ * - \link sndfiledemo Sndfile demo \endlink
+ */
+
+/** \defgroup noisedemo Noise demo
+ *
+ * Plays a sequence of short bursts of whitenoise.
+ *
+ * \include noisedemo.c noisedemo.c
+ */
+
+/** \defgroup squaredemo Square demo
+ *
+ * Plays a polyphonic sequence of musical notes generated by a builtin
+ * square wave synthesizer.
+ *
+ * \include squaredemo.c squaredemo.c
+ */
+
+/** \defgroup sndfiledemo Sndfile demo
+ *
+ * Plays a sequence of notes using sound files from disk.
+ *
+ * \include sndfiledemo.c sndfiledemo.c
+ */
+
+#include <remix/remix_types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+extern CDSet * REMIX_MONO;
+extern CDSet * REMIX_STEREO;
+
+
+/* RemixEnv */
+RemixEnv * remix_init (void);
+RemixEnv * remix_init_clone (RemixEnv * env);
+void remix_purge (RemixEnv * env);
+RemixError remix_last_error (RemixEnv * env);
+char * remix_error_string (RemixEnv * env, RemixError error);
+RemixSamplerate remix_set_samplerate (RemixEnv * env, RemixSamplerate samplerate);
+RemixSamplerate remix_get_samplerate (RemixEnv * env);
+RemixTempo remix_set_tempo (RemixEnv * env, RemixTempo tempo);
+RemixTempo remix_get_tempo (RemixEnv * env);
+CDSet * remix_set_channels (RemixEnv * env, CDSet * channelset);
+CDSet * remix_get_channels (RemixEnv * env);
+
+/* Base objects */
+
+RemixPlugin * remix_find_plugin (RemixEnv * env, char * identifier);
+
+RemixBase * remix_new (RemixEnv * env, RemixPlugin * plugin, CDSet * parameters);
+CDSet * remix_suggest (RemixEnv * env, RemixPlugin * plugin, CDSet * parameters);
+
+int remix_get_init_parameter_key (RemixEnv * env, RemixPlugin * plugin, char * name);
+int remix_get_parameter_key (RemixEnv * env, RemixBase * base, char * name);
+
+RemixParameter remix_set_parameter (RemixEnv * env, RemixBase * base, int key,
+ RemixParameter parameter);
+RemixParameter remix_get_parameter (RemixEnv * env, RemixBase * base, int key);
+RemixParameterType remix_get_parameter_type (RemixEnv * env, RemixBase * base, int key);
+
+
+RemixBase * remix_clone_subclass (RemixEnv * env, RemixBase * base);
+int remix_destroy (RemixEnv * env, RemixBase * base);
+int remix_destroy_list (RemixEnv * env, CDList * list);
+RemixBase * remix_prepare (RemixEnv * env, RemixBase * base);
+RemixCount remix_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output);
+RemixCount remix_length (RemixEnv * env, RemixBase * base);
+RemixCount remix_seek (RemixEnv * env, RemixBase * base, RemixCount offset, int whence);
+RemixCount remix_tell (RemixEnv * env, RemixBase * base);
+int remix_flush (RemixEnv * env, RemixBase * base);
+
+RemixCount remix_set_mixlength (RemixEnv * env, RemixCount mixlength);
+RemixCount remix_get_mixlength (RemixEnv * env);
+
+
+int remix_is_writeable (RemixEnv * env, RemixBase * base);
+int remix_is_seekable (RemixEnv * env, RemixBase * base);
+int remix_is_cacheable (RemixEnv * env, RemixBase * base);
+int remix_is_causal (RemixEnv * env, RemixBase * base);
+
+char * remix_set_name (RemixEnv * env, RemixBase * base, char * name);
+char * remix_get_name (RemixEnv * env, RemixBase * base);
+
+#include <remix/remix_deck.h>
+#include <remix/remix_envelope.h>
+#include <remix/remix_stream.h>
+
+/* SquareTone */
+RemixBase * remix_squaretone_new (RemixEnv * env, float frequency);
+float remix_squaretone_set_frequency (RemixEnv * env,
+ RemixBase * squaretone,
+ float frequency);
+float remix_squaretone_get_frequency (RemixEnv * env,
+ RemixBase * squaretone);
+
+/* Monitor */
+RemixMonitor * remix_monitor_new (RemixEnv * env);
+
+/* Scrubby */
+RemixBase * remix_scrubby_new (RemixEnv * env);
+RemixBase * remix_scrubby_set_source (RemixEnv * env, RemixBase * scrubby,
+ RemixBase * source);
+RemixBase * remix_scrubby_get_source (RemixEnv * env, RemixBase * scrubby);
+int remix_scrubby_set_direction (RemixEnv * env, RemixBase * scrubby, int direction);
+int remix_scrubby_get_direction (RemixEnv * env, RemixBase * scrubby);
+
+#include <remix/remix_time.h>
+
+#include <remix/remix_meta.h>
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_DECK_H__
+#define __REMIX_DECK_H__
+
+/** \file
+ *
+ * The top level structured mixing abstraction in libremix is known as a deck.
+ * A deck contains a number of tracks which are mixed in parallel. Each
+ * track may contain a number of layers which are mixed from bottom
+ * to top in series. Finally, these layers each contain a sequence of
+ * sounds with transparency.
+ *
+ * \image html decks.png
+ * \image latex decks.eps "Inside a Remix deck" width=10cm
+ *
+ * The sequence of sounds in a layer can be indexed by samples, seconds or
+ * tempo.
+ * Sounds provide audio data from any instrument or effect source, and these
+ * sources can each be reused multiple times. A sound can even source its
+ * audio data from another entire deck, thus decks can be used to sequence
+ * other decks. In this manner effects can be applied to sequences of decks,
+ * and sequences of decks can be stored as higher level units such as
+ * verses and choruses in a music application.
+ */
+
+
+#include <remix/remix_types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Decks */
+RemixDeck * remix_deck_new (RemixEnv * env);
+
+RemixCount remix_deck_set_mixlength (RemixEnv * env, RemixDeck * deck, RemixCount mixlength);
+RemixCount remix_deck_get_mixlength (RemixEnv * env, RemixDeck * deck);
+
+CDList * remix_deck_get_tracks (RemixEnv * env, RemixDeck * deck);
+
+/* Tracks */
+RemixTrack * remix_track_new (RemixEnv * env, RemixDeck * deck);
+RemixPCM remix_track_set_gain (RemixEnv * env, RemixTrack * track, RemixPCM gain);
+RemixPCM remix_track_get_gain (RemixEnv * env, RemixTrack * track);
+RemixCount remix_track_set_mixlength (RemixEnv * env, RemixTrack * track,
+ RemixCount mixlength);
+RemixCount remix_track_get_mixlength (RemixEnv * env, RemixTrack * track);
+void remix_remove_track (RemixEnv * env, RemixTrack * track);
+
+RemixDeck * remix_track_get_deck (RemixEnv * env, RemixTrack * track);
+
+
+/* Layers */
+RemixLayer * remix_layer_new_ontop (RemixEnv * env, RemixTrack * track,
+ RemixTimeType timetype);
+RemixLayer * remix_layer_new_above (RemixEnv * env, RemixLayer * above,
+ RemixTimeType timetype);
+RemixLayer * remix_layer_move_ontop (RemixEnv * env, RemixLayer * layer, RemixTrack * track);
+RemixLayer * remix_layer_move_above (RemixEnv * env, RemixLayer * layer, RemixLayer * above);
+RemixLayer * remix_layer_raise (RemixEnv * env, RemixLayer * layer);
+RemixLayer * remix_layer_lower (RemixEnv * env, RemixLayer * layer);
+RemixTrack * remix_layer_get_track (RemixEnv * env, RemixLayer * layer);
+RemixDeck * remix_layer_get_deck (RemixEnv * env, RemixLayer * layer);
+RemixTimeType remix_layer_set_timetype (RemixEnv * env, RemixLayer * layer,
+ RemixTimeType new_type);
+RemixTimeType remix_layer_get_timetype (RemixEnv * env, RemixLayer * layer);
+RemixSound * remix_layer_get_sound_before (RemixEnv * env, RemixLayer * layer,
+ RemixTime time);
+RemixSound * remix_layer_get_sound_at (RemixEnv * env, RemixLayer * layer, RemixTime time);
+RemixSound * remix_layer_get_sound_after (RemixEnv * env, RemixLayer * layer, RemixTime time);
+RemixLayer * remix_layer_below (RemixEnv * env, RemixLayer * layer);
+RemixLayer * remix_layer_above (RemixEnv * env, RemixLayer * layer);
+
+/* Sounds */
+RemixSound * remix_sound_new (RemixEnv * env, RemixBase * source,
+ RemixLayer * layer,
+ RemixTime start_time, RemixTime duration);
+
+RemixBase * remix_sound_set_source (RemixEnv * env, RemixSound * sound,
+ RemixBase * source);
+RemixBase * remix_sound_get_source (RemixEnv * env, RemixSound * sound);
+RemixLayer * remix_sound_get_layer (RemixEnv * env, RemixSound * sound);
+RemixTrack * remix_sound_get_track (RemixEnv * env, RemixSound * sound);
+RemixDeck * remix_sound_get_deck (RemixEnv * env, RemixSound * sound);
+
+RemixTime remix_sound_move (RemixEnv * env, RemixSound * sound,
+ RemixTime time);
+RemixSound * remix_sound_get_prev (RemixEnv * env, RemixSound * sound);
+RemixSound * remix_sound_get_next (RemixEnv * env, RemixSound * sound);
+
+RemixTime remix_sound_set_start_time (RemixEnv * env, RemixSound * sound,
+ RemixTime time);
+RemixTime remix_sound_get_start_time (RemixEnv * env, RemixSound * sound);
+RemixTime remix_sound_set_duration (RemixEnv * env, RemixSound * sound,
+ RemixTime time);
+RemixTime remix_sound_get_duration (RemixEnv * env, RemixSound * sound);
+
+RemixBase * remix_sound_set_rate_envelope (RemixEnv * env, RemixSound * sound,
+ RemixBase * rate_envelope);
+RemixBase * remix_sound_get_rate_envelope (RemixEnv * env, RemixSound * sound);
+RemixBase * remix_sound_set_gain_envelope (RemixEnv * env, RemixSound * sound,
+ RemixBase * gain_envelope);
+RemixBase * remix_sound_get_gain_envelope (RemixEnv * env, RemixSound * sound);
+RemixBase * remix_sound_set_blend_envelope (RemixEnv * env, RemixSound * sound,
+ RemixBase * blend_envelope);
+RemixBase * remix_sound_get_blend_envelope (RemixEnv * env, RemixSound * sound);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_DECK_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/** \file
+ * Base types and public interfaces to libremix
+ *
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_ENVELOPE_H__
+#define __REMIX_ENVELOPE_H__
+
+/** \file
+ *
+ * The information describing how a parameter changes over time appears
+ * as a generic data source. In order to create this mix automation information
+ * Remix provides linear and spline envelopes.
+ * However, parameters could alternatively be controlled by other means such
+ * as from a recording of physical slider values, from a sine wave
+ * generator, or from a deck constructed solely to generate interesting
+ * parameter values.
+ */
+
+#include <remix/remix_types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Envelopes */
+RemixEnvelope * remix_envelope_new (RemixEnv * env, RemixEnvelopeType type);
+RemixEnvelopeType remix_envelope_set_type (RemixEnv * env,
+ RemixEnvelope * envelope,
+ RemixEnvelopeType type);
+RemixEnvelopeType remix_envelope_get_type (RemixEnv * env, RemixEnvelope * envelope);
+RemixTimeType remix_envelope_set_timetype (RemixEnv * env,
+ RemixEnvelope * envelope,
+ RemixTimeType timetype);
+RemixTimeType remix_envelope_get_timetype (RemixEnv * env,
+ RemixEnvelope * envelope);
+RemixPCM remix_envelope_get_value (RemixEnv * env, RemixEnvelope * envelope,
+ RemixTime time);
+RemixTime remix_envelope_get_duration (RemixEnv * env,
+ RemixEnvelope * envelope);
+RemixPCM remix_envelope_get_integral (RemixEnv * env, RemixEnvelope * envelope,
+ RemixTime t1, RemixTime t2);
+RemixPoint * remix_envelope_add_point (RemixEnv * env,
+ RemixEnvelope * envelope,
+ RemixTime time, RemixPCM value);
+RemixEnvelope * remix_envelope_remove_point (RemixEnv * env,
+ RemixEnvelope * envelope,
+ RemixPoint * point);
+RemixEnvelope * remix_envelope_scale (RemixEnv * env, RemixEnvelope * envelope,
+ RemixPCM gain);
+RemixEnvelope * remix_envelope_shift (RemixEnv * env, RemixEnvelope * envelope,
+ RemixTime delta);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/** \file
+ * Metadata for RemixBase objects
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_META_H__
+#define __REMIX_META_H__
+
+char * remix_meta_text_get_identifier (RemixEnv * env, RemixMetaText * mt);
+char * remix_meta_text_set_identifier (RemixEnv * env, RemixMetaText * mt,
+ char * identifier);
+char * remix_meta_text_get_category (RemixEnv * env, RemixMetaText * mt);
+char * remix_meta_text_set_category (RemixEnv * env, RemixMetaText * mt,
+ char * category);
+char * remix_meta_text_get_description (RemixEnv * env, RemixMetaText * mt);
+char * remix_meta_text_set_description (RemixEnv * env, RemixMetaText * mt,
+ char * description);
+char * remix_meta_text_get_copyright (RemixEnv * env, RemixMetaText * mt);
+char * remix_meta_text_set_copyright (RemixEnv * env, RemixMetaText * mt,
+ char * copyright);
+char * remix_meta_text_get_url (RemixEnv * env, RemixMetaText * mt);
+char * remix_meta_text_set_url (RemixEnv * env, RemixMetaText * mt,
+ char * url);
+CDList * remix_meta_text_get_authors (RemixEnv * env, RemixMetaText * mt);
+void remix_meta_text_add_author (RemixEnv * env, RemixMetaText * mt,
+ char * name, char * email);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_META_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * remix_plugin.h -- libremix internal data types and functions.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_PLUGIN_H__
+#define __REMIX_PLUGIN_H__
+
+/*#define DEBUG*/
+
+#if defined(__REMIX_PLUGIN__) || defined(__REMIX__)
+
+#include <stdio.h>
+
+#include "ctxdata.h"
+
+#define REMIX_PLUGIN_API_MAJOR 1
+#define REMIX_PLUGIN_API_MINOR 0
+#define REMIX_PLUGIN_API_REVISION 0
+
+typedef struct _RemixMetaAuthor RemixMetaAuthor;
+typedef struct _RemixMetaText RemixMetaText;
+
+typedef struct _RemixParameterScheme RemixParameterScheme;
+typedef struct _RemixParameterRange RemixParameterRange;
+
+typedef struct _RemixNamedParameter RemixNamedParameter;
+
+typedef union _RemixConstraint RemixConstraint;
+
+typedef struct _RemixMethods RemixMethods;;
+
+#define REMIX_PLUGIN_WRITEABLE 1<<0
+#define REMIX_PLUGIN_SEEKABLE 1<<1
+#define REMIX_PLUGIN_CACHEABLE 1<<2
+#define REMIX_PLUGIN_CAUSAL 1<<3
+
+/* A base of a plugin */
+typedef struct _RemixPlugin RemixPlugin;
+/*typedef struct _RemixBase * RemixBase;*/
+
+typedef struct _RemixChunk RemixChunk;
+
+typedef struct _Remix_Sound_Data Remix_Sound_Data;
+
+#if defined (__REMIX__)
+#include "remix_private.h"
+#else
+typedef RemixOpaque RemixEnv;
+typedef RemixOpaque RemixPoint;
+typedef RemixOpaque RemixEnvelope;
+typedef RemixOpaque RemixStream;
+typedef RemixOpaque RemixChannel;
+typedef RemixOpaque RemixDeck;
+typedef RemixOpaque RemixTrack;
+typedef RemixOpaque RemixLayer;
+typedef RemixOpaque RemixSound;
+typedef RemixOpaque RemixSquareTone;
+typedef RemixOpaque RemixMonitor;
+#endif
+
+
+typedef CDList * (*RemixPluginInitFunc) (RemixEnv * env);
+typedef int (*RemixPluginDestroyFunc) (RemixEnv * env, RemixPlugin * plugin);
+
+typedef RemixBase * (*RemixInitFunc) (RemixEnv * env, RemixBase * base,
+ CDSet * parameters);
+
+typedef CDSet * (*RemixSuggestFunc) (RemixEnv * env, RemixPlugin * plugin,
+ CDSet * parameters,
+ void * plugin_data);
+
+typedef RemixBase * (*RemixCloneFunc) (RemixEnv * env, RemixBase * base);
+typedef int (*RemixDestroyFunc) (RemixEnv * env, RemixBase * base);
+typedef int (*RemixReadyFunc) (RemixEnv * env, RemixBase * base);
+typedef RemixBase * (*RemixPrepareFunc) (RemixEnv * env, RemixBase * base);
+typedef RemixCount (*RemixSeekFunc) (RemixEnv * env, RemixBase * base,
+ RemixCount count);
+typedef RemixCount (*RemixLengthFunc) (RemixEnv * env, RemixBase * base);
+typedef RemixCount (*RemixProcessFunc) (RemixEnv * env, RemixBase * base,
+ RemixCount count,
+ RemixStream * input,
+ RemixStream * output);
+typedef int (*RemixFlushFunc) (RemixEnv * env, RemixBase * base);
+
+#define REMIX_FLAGS_NONE (0)
+
+#define REMIX_AUTHOR(n,e) ((struct _RemixMetaAuthor){(n),(e)})
+#define REMIX_ONE_AUTHOR(n,e) CD_SINGLETON_LIST(CD_POINTER(&(REMIX_AUTHOR((n),(e)))))
+
+/* ChunkChunkFuncs and all the rest */
+
+/* RemixChunkFunc: a function to apply to one chunk */
+typedef RemixCount (*RemixChunkFunc) (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset,
+ RemixCount count, int channelname,
+ void * data);
+
+/* RemixChunkChunkFunc: a function to apply between two chunks :) */
+typedef RemixCount (*RemixChunkChunkFunc) (RemixEnv * env,
+ RemixChunk * src,
+ RemixCount src_offset,
+ RemixChunk * dest,
+ RemixCount dest_offset,
+ RemixCount count, int channelname,
+ void * data);
+
+/* RemixChunkChunkChunkFunc: a function to apply between THREE chunks !! */
+typedef RemixCount (*RemixChunkChunkChunkFunc) (RemixEnv * env,
+ RemixChunk * src1,
+ RemixCount src1_offset,
+ RemixChunk * src2,
+ RemixCount src2_offset,
+ RemixChunk * dest,
+ RemixCount dest_offset,
+ RemixCount count,
+ int channelname,
+ void * data);
+
+struct _RemixMetaAuthor {
+ char * name;
+ char * email;
+};
+
+struct _RemixMetaText {
+ char * identifier;
+ char * category;
+ char * description;
+ char * copyright;
+ char * url;
+ CDList * authors;
+};
+
+struct _RemixParameterRange {
+ RemixFlags valid_mask;
+ RemixParameter lower;
+ RemixParameter upper;
+ RemixParameter step;
+};
+
+struct _RemixNamedParameter {
+ char * name;
+ RemixParameter parameter;
+};
+
+#define REMIX_NAMED_PARAMETER(n,p) (&((struct _RemixNamedParameter){(n),(p)}))
+
+union _RemixConstraint {
+ CDList * list; /* list of RemixNamedParameter */
+ RemixParameterRange * range;
+};
+
+struct _RemixParameterScheme {
+ char * name;
+ char * description;
+ RemixParameterType type;
+ RemixConstraintType constraint_type;
+ RemixConstraint constraint;
+ RemixFlags hints;
+};
+
+struct _RemixPlugin {
+ RemixMetaText * metatext;
+ RemixFlags flags;
+ CDSet * init_scheme;
+ RemixInitFunc init;
+ CDSet * process_scheme;
+ RemixSuggestFunc suggest;
+ void * plugin_data;
+ RemixPluginDestroyFunc destroy;
+};
+
+struct _RemixMethods {
+ RemixCloneFunc clone;
+ RemixDestroyFunc destroy;
+ RemixReadyFunc ready;
+ RemixPrepareFunc prepare;
+ RemixProcessFunc process;
+ RemixLengthFunc length;
+ RemixSeekFunc seek;
+ RemixFlushFunc flush;
+};
+
+
+struct _RemixChunk {
+ RemixCount start_index;
+ RemixCount length;
+ RemixPCM * data;
+};
+
+
+/* debug */
+void remix_dprintf (const char * fmt, ...);
+
+/* SOUNDRENDER, remix_context */
+
+RemixError remix_set_error (RemixEnv * env, RemixError error);
+
+
+/* remix_base */
+RemixBase * remix_base_new (RemixEnv * env);
+
+RemixPlugin * remix_base_set_plugin (RemixEnv * env, RemixBase * base,
+ RemixPlugin * plugin);
+RemixPlugin * remix_base_get_plugin (RemixEnv * env, RemixBase * base);
+RemixMethods * remix_base_set_methods (RemixEnv * env, RemixBase * base,
+ RemixMethods * methods);
+void * remix_base_set_instance_data (RemixEnv * env, RemixBase * base,
+ void * data);
+void * remix_base_get_instance_data (RemixEnv * env, RemixBase * base);
+
+RemixCount remix_base_get_mixlength (RemixEnv * env, RemixBase * base);
+RemixSamplerate remix_base_get_samplerate (RemixEnv * env, RemixBase * base);
+RemixTempo remix_base_get_tempo (RemixEnv * env, RemixBase * base);
+CDSet * remix_base_get_channels (RemixEnv * env, RemixBase * base);
+
+int remix_base_has_samplerate (RemixEnv * env, RemixBase * base);
+int remix_base_has_tempo (RemixEnv * env, RemixBase * base);
+int remix_base_encompasses_mixlength (RemixEnv * env, RemixBase * base);
+int remix_base_encompasses_channels (RemixEnv * env, RemixBase * base);
+
+
+/* remix_meta */
+RemixMetaText * remix_meta_text_new (RemixEnv * env);
+void remix_meta_text_free (RemixEnv * env, RemixMetaText * mt);
+RemixMetaText * remix_get_meta_text (RemixEnv * env, RemixBase * base);
+RemixMetaText * remix_set_meta_text (RemixEnv * env, RemixBase * base,
+ RemixMetaText * mt);
+
+
+/* remix_null */
+RemixCount remix_null_length (RemixEnv * env, RemixBase * base);
+RemixCount remix_null_process (RemixEnv * env, RemixBase * base,
+ RemixCount count,
+ RemixStream * input, RemixStream * output);
+RemixCount remix_null_seek (RemixEnv * env, RemixBase * base,
+ RemixCount offset);
+
+
+/* remix_stream */
+RemixCount remix_stream_chunkfuncify (RemixEnv * env, RemixStream * stream,
+ RemixCount count,
+ RemixChunkFunc func, void * data);
+RemixCount remix_stream_chunkchunkfuncify (RemixEnv * env,
+ RemixStream * src,
+ RemixStream * dest,
+ RemixCount count,
+ RemixChunkChunkFunc func,
+ void * data);
+RemixCount remix_stream_chunkchunkchunkfuncify (RemixEnv * env,
+ RemixStream * src1,
+ RemixStream * src2,
+ RemixStream * dest,
+ RemixCount count,
+ RemixChunkChunkChunkFunc func,
+ void * data);
+
+/* RemixChannel */
+RemixChunk * remix_channel_get_chunk_at (RemixEnv * env,
+ RemixChannel * channel,
+ RemixCount offset);
+
+RemixCount remix_channel_chunkfuncify (RemixEnv * env, RemixChannel * channel,
+ RemixCount count, RemixChunkFunc func,
+ int channelname, void * data);
+RemixCount remix_channel_chunkchunkfuncify (RemixEnv * env,
+ RemixChannel * src,
+ RemixChannel * dest,
+ RemixCount count,
+ RemixChunkChunkFunc func,
+ int channelname, void * data);
+RemixCount remix_channel_chunkchunkchunkfuncify (RemixEnv * env,
+ RemixChannel * src1,
+ RemixChannel * src2,
+ RemixChannel * dest,
+ RemixCount count,
+ RemixChunkChunkChunkFunc func,
+ int channelname, void * data);
+/* RemixPCM */
+
+RemixCount _remix_pcm_clear_region (RemixPCM * data, RemixCount count,
+ void * unused);
+RemixCount _remix_pcm_set (RemixPCM * data, RemixPCM value, RemixCount count);
+RemixCount _remix_pcm_gain (RemixPCM * data, RemixCount count,
+ /* (RemixPCM *) */ void * gain);
+RemixCount _remix_pcm_copy (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused);
+RemixCount _remix_pcm_add (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused);
+RemixCount _remix_pcm_mult (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused);
+RemixCount _remix_pcm_fade (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused);
+RemixCount _remix_pcm_interleave_2 (RemixPCM * src1, RemixPCM * src2,
+ RemixCount count, void * data);
+RemixCount _remix_pcm_deinterleave_2 (RemixPCM * dest1, RemixPCM * dest2,
+ RemixCount count, void * data);
+RemixCount _remix_pcm_blend (RemixPCM * src, RemixPCM * blend, RemixPCM * dest,
+ RemixCount count, void * unused);
+RemixCount _remix_pcm_write_linear (RemixPCM * data, RemixCount x1,
+ RemixPCM y1, RemixCount x2, RemixPCM y2,
+ RemixCount offset, RemixCount count);
+
+#endif /* defined(__REMIX__) */
+
+#endif /* __REMIX_PLUGIN_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_STREAM_H__
+#define __REMIX_STREAM_H__
+
+/** \file
+ *
+ * The abstraction of multichannel audio data in libremix is known as a
+ * stream.
+ * A stream may consist of multiple channels, each of which can consist
+ * of an arbitrary number of sparsely placed chunks of raw audio data.
+ * The channels are named with spatial names such as LEFT, RIGHT and CENTRE
+ * as required for common home, studio and theatre environments.
+ *
+ * \image html streams.png
+ * \image latex streams.eps "Inside a Remix stream" width=10cm
+ *
+ * Generic routines are provided for mixing, multiplying and blending
+ * streams of data.
+ *
+ */
+
+#include <remix/remix_types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Streams */
+RemixStream * remix_stream_new (RemixEnv * env);
+RemixStream * remix_stream_new_contiguous (RemixEnv * env, RemixCount length);
+RemixStream * remix_stream_new_from_buffers (RemixEnv * env, RemixCount length,
+ RemixPCM ** buffers);
+RemixCount remix_stream_nr_channels (RemixEnv * env, RemixStream * stream);
+RemixChannel * remix_stream_find_channel (RemixEnv * env,
+ RemixStream * stream, int name);
+RemixChannel * remix_stream_add_channel (RemixEnv * env,
+ RemixStream * stream, int name);
+RemixStream * remix_stream_remove_channel (RemixEnv * env,
+ RemixStream * stream, int name);
+RemixStream * remix_stream_add_chunks (RemixEnv * env, RemixStream * stream,
+ RemixCount offset, RemixCount length);
+
+RemixCount remix_stream_write0 (RemixEnv * env, RemixStream * stream,
+ RemixCount count);
+RemixCount remix_stream_write (RemixEnv * env, RemixStream * stream,
+ RemixCount count, RemixStream * data);
+RemixCount remix_stream_copy (RemixEnv * env, RemixStream * src,
+ RemixStream * dest, RemixCount count);
+RemixCount remix_stream_gain (RemixEnv * env, RemixStream * stream,
+ RemixCount count, RemixPCM gain);
+RemixCount remix_stream_mix (RemixEnv * env, RemixStream * src,
+ RemixStream * dest, RemixCount count);
+RemixCount remix_stream_mult (RemixEnv * env, RemixStream * src,
+ RemixStream * dest, RemixCount count);
+RemixCount remix_streams_mix (RemixEnv * env, CDList * streams,
+ RemixStream * dest, RemixCount count);
+RemixCount remix_stream_fade (RemixEnv * env, RemixStream * src,
+ RemixStream * dest, RemixCount count);
+RemixCount remix_stream_blend (RemixEnv * env, RemixStream * src,
+ RemixStream * dest,
+ RemixStream * blend, RemixCount count);
+
+RemixCount remix_stream_interleave_2 (RemixEnv * env, RemixStream * stream,
+ int name1, int name2,
+ RemixPCM * dest, RemixCount count);
+RemixCount remix_stream_deinterleave_2 (RemixEnv * env, RemixStream * stream,
+ int name1, int name2,
+ RemixPCM * src, RemixCount count);
+
+/* Chunks */
+int remix_chunk_later (RemixEnv * env, RemixChunk * u1, RemixChunk * u2);
+RemixCount remix_chunk_clear (RemixEnv * env, RemixChunk * chunk);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_STREAM_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/** \file
+ * Base types and public interfaces to libremix
+ *
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_TIME_H__
+#define __REMIX_TIME_H__
+
+#include <remix/remix_types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Time */
+RemixTime remix_time_convert (RemixEnv * env, RemixTime time,
+ RemixTimeType old_type, RemixTimeType new_type);
+RemixTime remix_time_zero (RemixTimeType type);
+RemixTime remix_time_invalid (RemixTimeType type);
+int remix_time_is_invalid (RemixTimeType type, RemixTime time);
+RemixTime remix_time_add (RemixTimeType type, RemixTime t1, RemixTime t2);
+RemixTime remix_time_sub (RemixTimeType type, RemixTime t1, RemixTime t2);
+RemixTime remix_time_min (RemixTimeType type, RemixTime t1, RemixTime t2);
+RemixTime remix_time_max (RemixTimeType type, RemixTime t1, RemixTime t2);
+int remix_time_eq (RemixTimeType type, RemixTime t1, RemixTime t2);
+int remix_time_gt (RemixTimeType type, RemixTime t1, RemixTime t2);
+int remix_time_lt (RemixTimeType type, RemixTime t1, RemixTime t2);
+int remix_time_ge (RemixTimeType type, RemixTime t1, RemixTime t2);
+int remix_time_le (RemixTimeType type, RemixTime t1, RemixTime t2);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_TIME_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ * Copyright (C) 2003 Conrad Parker
+ *
+ * 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
+ *
+ */
+
+/** \file
+ * Base types and public interfaces to libremix
+ *
+ */
+
+/*
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_TYPES_H__
+#define __REMIX_TYPES_H__
+
+#include <limits.h>
+
+#include "ctxdata.h"
+
+#define RemixNone NULL
+
+typedef int RemixError;
+
+typedef float RemixPCM;
+
+typedef long RemixCount;
+#define REMIX_COUNT_MAX (LONG_MAX - 1L)
+#define REMIX_COUNT_MIN LONG_MIN
+#define REMIX_COUNT_INFINITE REMIX_COUNT_MAX
+
+//TODO xxx : Change this
+typedef struct _RemixOpaque RemixOpaque;
+
+#if defined (__REMIX__)
+typedef struct _RemixBase RemixBase;
+#else
+typedef RemixOpaque RemixBase;
+#endif
+
+//TODO xxx : Change this
+struct _RemixOpaque {
+ void * instance_data;
+};
+
+typedef CDScalar RemixParameter;
+
+typedef int RemixFlags;
+typedef double RemixSamplerate;
+typedef double RemixTempo;
+typedef union _RemixTime RemixTime;
+
+
+/* Errors */
+#define REMIX_ERROR_OK 0
+#define REMIX_ERROR_INVALID 1
+#define REMIX_ERROR_NOENTITY 2
+#define REMIX_ERROR_EXISTS 3
+#define REMIX_ERROR_SILENCE 4
+#define REMIX_ERROR_NOOP 5
+#define REMIX_ERROR_SYSTEM 6
+
+typedef enum {
+ REMIX_CHANNEL_LEFT,
+ REMIX_CHANNEL_RIGHT,
+ REMIX_CHANNEL_CENTRE,
+ REMIX_CHANNEL_REAR,
+ REMIX_CHANNEL_REAR_LEFT,
+ REMIX_CHANNEL_REAR_RIGHT,
+ REMIX_CHANNEL_REAR_CENTRE,
+ REMIX_CHANNEL_LFE /* Low Frequency Effects */
+} RemixChannelName;
+
+typedef enum {
+ REMIX_TIME_INVALID,
+ REMIX_TIME_SAMPLES,
+ REMIX_TIME_SECONDS,
+ REMIX_TIME_BEAT24S
+} RemixTimeType;
+
+/* Envelope types */
+typedef enum {
+ REMIX_ENVELOPE_LINEAR,
+ REMIX_ENVELOPE_SPLINE
+} RemixEnvelopeType;
+
+union _RemixTime {
+ long TIME;
+ RemixCount samples;
+ float seconds;
+ int beat24s;
+};
+
+typedef enum {
+ REMIX_TYPE_BOOL = 0,
+ REMIX_TYPE_INT,
+ REMIX_TYPE_FLOAT,
+ REMIX_TYPE_STRING,
+ REMIX_TYPE_BASE
+} RemixParameterType;
+
+typedef enum {
+ REMIX_CONSTRAINT_TYPE_NONE = 0,
+ REMIX_CONSTRAINT_TYPE_LIST,
+ REMIX_CONSTRAINT_TYPE_RANGE
+} RemixConstraintType;
+
+
+#define REMIX_RANGE_LOWER_BOUND_VALID (1<<0)
+#define REMIX_RANGE_UPPER_BOUND_VALID (1<<1)
+#define REMIX_RANGE_STEP_VALID (1<<2)
+#define REMIX_RANGE_ALL_VALID (REMIX_RANGE_LOWER_BOUND_VALID | \
+ REMIX_RANGE_UPPER_BOUND_VALID | \
+ REMIX_RANGE_STEP_VALID)
+
+#define REMIX_HINT_DEFAULT (0)
+#define REMIX_HINT_LOG (1<<0)
+#define REMIX_HINT_TIME (1<<1)
+#define REMIX_HINT_FILENAME (1<<2)
+#define REMIX_HINT_CHANNEL (1<<3)
+
+#define REMIX_CONSTRAINT_EMPTY ((RemixConstraint){NULL})
+
+#define REMIX_SAMPLES(x) ((RemixTime){(RemixCount)(x)})
+#define REMIX_SECONDS(x) ((RemixTime){(float)(x)})
+#define REMIX_BEAT24S(x) ((RemixTime){(int)(x)})
+
+
+#if (defined(__REMIX__) || defined(__REMIX_PLUGIN__))
+#include <remix/remix_plugin.h>
+#else
+typedef RemixOpaque RemixEnv;
+typedef RemixOpaque RemixPoint;
+typedef RemixOpaque RemixEnvelope;
+typedef RemixOpaque RemixChunk;
+typedef RemixOpaque RemixChannel;
+typedef RemixOpaque RemixStream;
+typedef RemixOpaque RemixDeck;
+typedef RemixOpaque RemixTrack;
+typedef RemixOpaque RemixLayer;
+typedef RemixOpaque RemixSound;
+typedef RemixOpaque RemixMetaAuthor;
+typedef RemixOpaque RemixMetaText;
+typedef RemixOpaque RemixPlugin;
+typedef RemixOpaque RemixSquareTone;
+typedef RemixOpaque RemixMonitor;
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __REMIX_TYPES_H__ */
--- /dev/null
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+echo=echo
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec "$SHELL" "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# Find the correct PATH separator. Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != "Xset"; then
+ UNAME=${UNAME-`uname 2>/dev/null`}
+ case X$UNAME in
+ *-DOS) PATH_SEPARATOR=';' ;;
+ *) PATH_SEPARATOR=':' ;;
+ esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
+
+if test "X${echo_test_string+set}" != "Xset"; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+ echo_test_string="`eval $cmd`" &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
+ test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH /usr/ucb; do
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running ltconfig again with it.
+ ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf "%s\n"'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# The name of this program.
+progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.3.3
+TIMESTAMP=" (1.385.2.181 1999/07/02 15:49:11)"
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+enable_static=yes
+enable_fast_install=yes
+enable_dlopen=unknown
+enable_win32_dll=no
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+ofile="$default_ofile"
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+need_locks=yes
+ac_ext=c
+objext=o
+libext=a
+exeext=
+cache_file=
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LDFLAGS="$LDFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_LIBS="$LIBS"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+old_DLLTOOL="$DLLTOOL"
+old_OBJDUMP="$OBJDUMP"
+old_AS="$AS"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+ case "$option" in
+ -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ eval "$prev=\$option"
+ prev=
+ continue
+ fi
+
+ case "$option" in
+ --help) cat <<EOM
+Usage: $progname [OPTION]... [HOST [LTMAIN]]
+
+Generate a system-specific libtool script.
+
+ --debug enable verbose shell tracing
+ --disable-shared do not build shared libraries
+ --disable-static do not build static libraries
+ --disable-fast-install do not optimize for fast installation
+ --enable-dlopen enable dlopen support
+ --enable-win32-dll enable building dlls on win32 hosts
+ --help display this help and exit
+ --no-verify do not verify that HOST is a valid host type
+-o, --output=FILE specify the output file [default=$default_ofile]
+ --quiet same as \`--silent'
+ --silent do not print informational messages
+ --srcdir=DIR find \`config.guess' in DIR
+ --version output version information and exit
+ --with-gcc assume that the GNU C compiler will be used
+ --with-gnu-ld assume that the C compiler uses the GNU linker
+ --disable-lock disable file locking
+ --cache-file=FILE configure cache file
+
+LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
+that provides basic libtool functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --disable-shared) enable_shared=no ;;
+
+ --disable-static) enable_static=no ;;
+
+ --disable-fast-install) enable_fast_install=no ;;
+
+ --enable-dlopen) enable_dlopen=yes ;;
+
+ --enable-win32-dll) enable_win32_dll=yes ;;
+
+ --quiet | --silent) silent=yes ;;
+
+ --srcdir) prev=srcdir ;;
+ --srcdir=*) srcdir="$optarg" ;;
+
+ --no-verify) verify_host=no ;;
+
+ --output | -o) prev=ofile ;;
+ --output=*) ofile="$optarg" ;;
+
+ --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
+
+ --with-gcc) with_gcc=yes ;;
+ --with-gnu-ld) with_gnu_ld=yes ;;
+
+ --disable-lock) need_locks=no ;;
+
+ --cache-file=*) cache_file="$optarg" ;;
+
+ -*)
+ echo "$progname: unrecognized option \`$option'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ if test -z "$ltmain"; then
+ ltmain="$option"
+ elif test -z "$host"; then
+# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+# echo "$progname: warning \`$option' is not a valid host type" 1>&2
+# fi
+ host="$option"
+ else
+ echo "$progname: too many arguments" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+done
+
+if test -z "$ltmain"; then
+ echo "$progname: you must specify a LTMAIN file" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+if test ! -f "$ltmain"; then
+ echo "$progname: \`$ltmain' does not exist" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+ case "$arg" in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ltconfig_args="$ltconfig_args '$arg'" ;;
+ *) ltconfig_args="$ltconfig_args $arg" ;;
+ esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+if test -n "$cache_file" && test -r "$cache_file"; then
+ echo "loading cache $cache_file within ltconfig"
+ . $cache_file
+fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+ # Assume the source directory is the same one as the path to LTMAIN.
+ srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
+ test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+ # Check for config.guess and config.sub.
+ ac_aux_dir=
+ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/config.guess; then
+ ac_aux_dir=$ac_dir
+ break
+ fi
+ done
+ if test -z "$ac_aux_dir"; then
+ echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+ ac_config_guess=$ac_aux_dir/config.guess
+ ac_config_sub=$ac_aux_dir/config.sub
+
+ # Make sure we can run config.sub.
+ if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
+ else
+ echo "$progname: cannot run $ac_config_sub" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+ host_alias=$host
+ case "$host_alias" in
+ "")
+ if host_alias=`$SHELL $ac_config_guess`; then :
+ else
+ echo "$progname: cannot guess host type; you must specify one" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+ host=`$SHELL $ac_config_sub $host_alias`
+ echo "$ac_t$host" 1>&6
+
+ # Make sure the host verified.
+ test -z "$host" && exit 1
+
+elif test -z "$host"; then
+ echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+else
+ host_alias=$host
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host_os" in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "${COLLECT_NAMES+set}" != set; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# Set a sane default for `OBJDUMP'.
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+ result=no
+
+ echo $ac_n "checking for ranlib... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
+ RANLIB="ranlib"
+ result="ranlib"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+fi
+
+# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$AS" && AS=as
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+ # If CC is not set, then try to find GCC or a usable CC.
+ if test -z "$CC"; then
+ echo $ac_n "checking for gcc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
+ CC="gcc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+ fi
+
+ # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+ if test -z "$CC"; then
+ echo $ac_n "checking for cc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ cc_rejected=no
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
+ if test "$dir/cc" = "/usr/ucb/cc"; then
+ cc_rejected=yes
+ continue
+ fi
+ CC="cc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test $cc_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same name, so the bogon will be chosen
+ # first if we set CC to just the name; use the full file name.
+ shift
+ set dummy "$dir/cc" "$@"
+ shift
+ CC="$@"
+ fi
+ fi
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$CC"; then
+ echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+ exit 1
+ fi
+ fi
+
+ # Now see if the compiler is really GCC.
+ with_gcc=no
+ echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+ echo "$progname:581: checking whether we are using GNU C" >&5
+
+ $rm conftest.c
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+ if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ with_gcc=yes
+ fi
+ $rm conftest.c
+ echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for object suffix... $ac_c" 1>&6
+$rm conftest*
+echo 'int i = 1;' > conftest.c
+echo "$progname:603: checking for object suffix" >& 5
+if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+ *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+else
+ cat conftest.err 1>&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+fi
+$rm conftest*
+echo "$ac_t$objext" 1>&6
+
+echo $ac_n "checking for executable suffix... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_exeext="no"
+ $rm conftest*
+ echo 'main () { return 0; }' > conftest.c
+ echo "$progname:629: checking for executable suffix" >& 5
+ if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c | *.err | *.$objext ) ;;
+ *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+ else
+ cat conftest.err 1>&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ $rm conftest*
+fi
+if test "X$ac_cv_exeext" = Xno; then
+ exeext=""
+else
+ exeext="$ac_cv_exeext"
+fi
+echo "$ac_t$ac_cv_exeext" 1>&6
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+ wl='-Wl,'
+ link_static_flag='-static'
+
+ case "$host_os" in
+ beos* | irix5* | irix6* | osf3* | osf4*)
+ # PIC is the default for these OSes.
+ ;;
+ aix*)
+ # Below there is a dirty hack to force normal static linking with -ldl
+ # The problem is because libdl dynamically linked with both libc and
+ # libC (AIX C++ library), which obviously doesn't included in libraries
+ # list by gcc. This cause undefined symbols with -static flags.
+ # This hack allows C programs to be linked with "-static -ldl", but
+ # we not sure about C++ programs.
+ link_static_flag="$link_static_flag ${wl}-lC"
+ ;;
+ cygwin* | mingw* | os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ pic_flag='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ pic_flag=-Kconform_pic
+ fi
+ ;;
+ *)
+ pic_flag='-fPIC'
+ ;;
+ esac
+else
+ # PORTME Check for PIC flags for the system compiler.
+ case "$host_os" in
+ aix3* | aix4*)
+ # All AIX code is PIC.
+ link_static_flag='-bnso -bI:/lib/syscalls.exp'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ # Is there a better link_static_flag that works with the bundled CC?
+ wl='-Wl,'
+ link_static_flag="${wl}-a ${wl}archive"
+ pic_flag='+Z'
+ ;;
+
+ irix5* | irix6*)
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ # PIC (with -KPIC) is the default.
+ ;;
+
+ cygwin* | mingw* | os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+
+ osf3* | osf4*)
+ # All OSF/1 code is PIC.
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ pic_flag='-Kpic'
+ link_static_flag='-dn'
+ special_shlib_compile_flags='-belf'
+ ;;
+
+ solaris*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ sunos4*)
+ pic_flag='-PIC'
+ link_static_flag='-Bstatic'
+ wl='-Qoption ld '
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ uts4*)
+ pic_flag='-pic'
+ link_static_flag='-Bstatic'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ pic_flag='-Kconform_pic'
+ link_static_flag='-Bstatic'
+ fi
+ ;;
+ *)
+ can_build_shared=no
+ ;;
+ esac
+fi
+
+if test -n "$pic_flag"; then
+ echo "$ac_t$pic_flag" 1>&6
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $pic_flag -DPIC"
+ echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
+ if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ case "$host_os" in
+ hpux9* | hpux10* | hpux11*)
+ # On HP-UX, both CC and GCC only warn that PIC is supported... then they
+ # create non-PIC objects. So, if there were any warnings, we assume that
+ # PIC is not supported.
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ can_build_shared=no
+ pic_flag=
+ else
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ fi
+ ;;
+ *)
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ ;;
+ esac
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ can_build_shared=no
+ pic_flag=
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ echo "$ac_t"none 1>&6
+fi
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+$rm conftest*
+echo "int some_variable = 0;" > conftest.c
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory. Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.o"
+echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
+if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_c_o=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_c_o=yes
+ fi
+else
+ # Append any errors to the config.log.
+ cat out/conftest.err 1>&5
+ compiler_c_o=no
+ echo "$ac_t"no 1>&6
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+ echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+ echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
+if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_o_lo=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_o_lo=yes
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ compiler_o_lo=no
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$ac_t$hard_links" 1>&6
+ $rm conftest*
+ if test "$hard_links" = no; then
+ echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+if test "$with_gcc" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+ echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
+ echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+ if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_rtti_exceptions=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_rtti_exceptions=yes
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ compiler_rtti_exceptions=no
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+
+ if test "$compiler_rtti_exceptions" = "yes"; then
+ no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+ else
+ no_builtin_flag=' -fno-builtin'
+ fi
+
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+ echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
+ else
+ echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+ can_build_shared=no
+ fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ echo "$ac_t$link_static_flag" 1>&6
+else
+ echo "$ac_t"none 1>&6
+ link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+ # Check to see if we can use ln -s, or we need hard links.
+ echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+ $rm conftest.dat
+ if ln -s X conftest.dat 2>/dev/null; then
+ $rm conftest.dat
+ LN_S="ln -s"
+ else
+ LN_S=ln
+ fi
+ if test "$LN_S" = "ln -s"; then
+ echo "$ac_t"yes 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+ ac_prog=ld
+ if test "$with_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+ echo "$progname:991: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we are not using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+ echo "$progname:1015: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+ echo "$progname:1018: checking for non-GNU ld" >&5
+ fi
+
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ fi
+
+ if test -n "$LD"; then
+ echo "$ac_t$LD" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$LD"; then
+ echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+ exit 1
+ fi
+fi
+
+# Check to see if it really is or is not GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced. Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+
+case "$host_os" in
+cygwin* | mingw*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$with_gcc" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case "$host_os" in
+ aix3* | aix4*)
+ # On AIX, the GNU linker is very broken
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+
+ # Extract the symbol export list from an `--export-all' def file,
+ # then regenerate the def file from the symbol export list, so that
+ # the compiled dll only exports the symbol export list.
+ export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+ $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~
+ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols'
+
+ archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
+ _lt_hint=1;
+ for symbol in `cat $export_symbols`; do
+ echo " \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def;
+ _lt_hint=`expr 1 + \$_lt_hint`;
+ done~
+ test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+ $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+ $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+ $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
+
+ old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a'
+ ;;
+
+ netbsd*)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
+ # can we support soname and/or expsyms with a.out? -oliva
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ case $host_os in
+ cygwin* | mingw*)
+ # dlltool doesn't understand --whole-archive et. al.
+ whole_archive_flag_spec=
+ ;;
+ *)
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ ;;
+ esac
+ fi
+else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case "$host_os" in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4*)
+ hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
+ hardcode_libdir_separator=':'
+ if test "$with_gcc" = yes; then
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ shared_flag='-shared'
+ else
+ shared_flag='${wl}-bM:SRE'
+ hardcode_direct=yes
+ fi
+ allow_undefined_flag=' ${wl}-berok'
+ archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
+ archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
+ case "$host_os" in aix4.[01]|aix4.[01].*)
+ # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
+ always_export_symbols=yes ;;
+ esac
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ cygwin* | mingw*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs'
+ fix_srcfile_path='`cygpath -w $srcfile`'
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ case "$host_os" in
+ hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
+ *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
+ esac
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_minus_L=yes # Not in the search PATH, but as the default
+ # location of the library.
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ irix5* | irix6*)
+ if test "$with_gcc" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF
+ fi
+ hardcode_libdir_flag_spec='${wl}-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+ ;;
+
+ osf3* | osf4*)
+ if test "$with_gcc" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case "$host_os" in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ # archive_cmds='$LD -G -z text -h $soname -o $lib$libobjs$deplibs'
+ archive_cmds='$LD -G -h $soname -o $lib$libobjs$deplibs'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+if test -z "$NM"; then
+ echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+ case "$NM" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -B"
+ break
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -p"
+ break
+ else
+ NM=${NM="$ac_dir/nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$NM" && NM=nm
+ ;;
+ esac
+ echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+ ;;
+irix*)
+ symcode='[BCDEGRST]'
+ ;;
+solaris*)
+ symcode='[BDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+ symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+ global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+ $rm conftest*
+ cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ echo "$progname:1592: checking if global_symbol_pipe works" >&5
+ if { (eval echo $progname:1593: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { echo "$progname:1596: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+ if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
+
+ cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
+ cat <<\EOF >> conftest.c
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$objext conftstm.$objext
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+ if { (eval echo $progname:1648: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ LIBS="$save_LIBS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ $rm conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ global_symbol_pipe=
+ fi
+done
+if test "$pipe_works" = yes; then
+ echo "${ac_t}ok" 1>&6
+else
+ echo "${ac_t}failed" 1>&6
+fi
+
+if test -z "$global_symbol_pipe"; then
+ global_symbol_to_cdecl=
+fi
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$hardcode_shlibpath_var" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+echo "$ac_t$hardcode_action" 1>&6
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linkers may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag" 1>&6
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+file_magic_cmd=
+file_magic_test_file=
+deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [regex]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}.so$major'
+ ;;
+
+aix4*)
+ version_type=linux
+ # AIX has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ # We preserve .a as extension for shared libraries though AIX4.2
+ # and later linker supports .so
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
+ shlibpath_var=LIBPATH
+ deplibs_check_method=pass_all
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}.so'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ deplibs_check_method=pass_all
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+bsdi4*)
+ version_type=linux
+ library_names_spec='${libname}.so$major ${libname}.so'
+ soname_spec='${libname}.so'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/shlib/libc.so
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw*)
+ version_type=windows
+ need_version=no
+ need_lib_prefix=no
+ if test "$with_gcc" = yes; then
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
+ else
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+ fi
+ dynamic_linker='Win32 ld.exe'
+ deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ file_magic_cmd='${OBJDUMP} -f'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case "$version_type" in
+ freebsd-elf*)
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /usr/lib/libc.so*`
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ deplibs_check_method=unknown
+ library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+ need_version=yes
+ ;;
+ esac
+ finish_cmds='PATH="\$PATH:/sbin" OBJFORMAT="'"$objformat"'" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ case "$host_os" in
+ freebsd2* | freebsd3.[01]*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ dynamic_linker="$host_os dld.sl"
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+ soname_spec='${libname}${release}.sl$major'
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6*)
+ version_type=irix
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}.so.$major'
+ library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
+ case "$host_os" in
+ irix5*)
+ libsuff= shlibsuff=
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+ ;;
+ *)
+ case "$LD" in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1"
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+ deplibs_check_method='pass_all'
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+
+ if test -f /lib/ld.so.1; then
+ dynamic_linker='GNU ld.so'
+ else
+ # Only the GNU ld.so supports shared libraries on MkLinux.
+ case "$host_cpu" in
+ powerpc*) dynamic_linker=no ;;
+ *) dynamic_linker='Linux ld.so' ;;
+ esac
+ fi
+ ;;
+
+netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+openbsd*)
+ version_type=sunos
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ need_version=no
+ fi
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+os2*)
+ libname_spec='$name'
+ need_lib_prefix=no
+ library_names_spec='$libname.dll $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4*)
+ version_type=osf
+ need_version=no
+ soname_spec='${libname}${release}.so'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method='file_magic COFF format alpha shared library'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/shlib/libc.so
+ deplibs_check_method='pass_all'
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/lib/libc.so
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case "$host_vendor" in
+ ncr)
+ deplibs_check_method='pass_all'
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ esac
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$ac_t$dynamic_linker" 1>&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
+# configure.in, otherwise build static only libraries.
+case "$host_os" in
+cygwin* | mingw* | os2*)
+ if test x$can_build_shared = xyes; then
+ test x$enable_win32_dll = xno && can_build_shared=no
+ echo "checking if package supports dlls... $can_build_shared" 1>&6
+ fi
+;;
+esac
+
+if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
+ case "$deplibs_check_method" in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ egrep "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+fi
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4*)
+ test "$enable_shared" = yes && enable_static=no
+ ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
+ lt_cv_dlopen=no lt_cv_dlopen_libs=
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "$progname:2170: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2178 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo $progname:2188: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+echo "$progname:2207: checking for dlopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2212 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+dlopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dlopen"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
+echo "$progname:2251: checking for dld_link in -ldld" >&5
+ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldld $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2259 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dld_link();
+
+int main() {
+dld_link()
+; return 0; }
+EOF
+if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+echo "$progname:2288: checking for shl_load" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2293 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+shl_load();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="shl_load"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+echo "$progname:2333: checking for shl_load in -ldld" >&5
+ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldld $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2341 "ltconfig"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char shl_load();
+
+int main() {
+shl_load()
+; return 0; }
+EOF
+if { (eval echo $progname:2352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+fi
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ fi
+
+ case "$lt_cv_dlopen" in
+ dlopen)
+for ac_hdr in dlfcn.h; do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "$progname:2395: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2400 "ltconfig"
+#include <$ac_hdr>
+int fnord = 0;
+EOF
+ac_try="$ac_compile conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo $progname:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test "x$ac_cv_header_dlfcn_h" = xyes; then
+ CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+ fi
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2433: checking whether a program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ lt_cv_dlopen_self=cross
+ else
+ cat > conftest.c <<EOF
+#line 2441 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LTDL_LAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LTDL_LAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LTDL_LAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LTDL_LAZY_OR_NOW DL_NOW
+# else
+# define LTDL_LAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+ if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+ if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
+
+EOF
+if { (eval echo $progname:2487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ lt_cv_dlopen_self=yes
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ lt_cv_dlopen_self=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self" 1>&6
+
+ if test "$lt_cv_dlopen_self" = yes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2506: checking whether a statically linked program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ lt_cv_dlopen_self_static=cross
+ else
+ cat > conftest.c <<EOF
+#line 2514 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LTDL_LAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LTDL_LAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LTDL_LAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LTDL_LAZY_OR_NOW DL_NOW
+# else
+# define LTDL_LAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+ if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+ if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
+
+EOF
+if { (eval echo $progname:2560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ lt_cv_dlopen_self_static=yes
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ lt_cv_dlopen_self_static=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
+fi
+ ;;
+ esac
+
+ case "$lt_cv_dlopen_self" in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case "$lt_cv_dlopen_self_static" in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+# Copy echo and quote the copy, instead of the original, because it is
+# used later.
+ltecho="$echo"
+if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ltecho="$CONFIG_SHELL \$0 --fallback-echo"
+fi
+LTSHELL="$SHELL"
+
+LTCONFIG_VERSION="$VERSION"
+
+# Only quote variables if we're using ltmain.sh.
+case "$ltmain" in
+*.sh)
+ # Now quote all the things that may contain metacharacters.
+ for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
+ old_LD old_LDFLAGS old_LIBS \
+ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
+ AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
+ reload_flag reload_cmds wl \
+ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+ thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+ library_names_spec soname_spec \
+ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
+ file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
+ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+ hardcode_libdir_flag_spec hardcode_libdir_separator \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+ case "$var" in
+ reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case "$ltecho" in
+ *'\$0 --fallback-echo"')
+ ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+ trap "$rm \"$ofile\"; exit 1" 1 2 15
+ echo "creating $ofile"
+ $rm "$ofile"
+ cat <<EOF > "$ofile"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi
+
+### BEGIN LIBTOOL CONFIG
+EOF
+ cfgfile="$ofile"
+ ;;
+
+*)
+ # Double-quote the variables that need it (for aesthetics).
+ for var in old_CC old_CFLAGS old_CPPFLAGS \
+ old_LD old_LDFLAGS old_LIBS \
+ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
+ eval "$var=\\\"\$var\\\""
+ done
+
+ # Just create a config file.
+ cfgfile="$ofile.cfg"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ echo "creating $cfgfile"
+ $rm "$cfgfile"
+ cat <<EOF > "$cfgfile"
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+EOF
+ ;;
+esac
+
+cat <<EOF >> "$cfgfile"
+# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
+# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
+# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
+# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
+# $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION=$LTCONFIG_VERSION
+
+# Shell to use when invoking shell scripts.
+SHELL=$LTSHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$ltecho
+
+# The archiver.
+AR=$AR
+
+# The default C compiler.
+CC=$CC
+
+# The linker used to build libraries.
+LD=$LD
+
+# Whether we need hard or soft links.
+LN_S=$LN_S
+
+# A BSD-compatible nm program.
+NM=$NM
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$reload_flag
+reload_cmds=$reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$wl
+
+# Object file suffix (normally "o").
+objext="$objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$pic_flag
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$RANLIB
+old_archive_cmds=$old_archive_cmds
+old_postinstall_cmds=$old_postinstall_cmds
+old_postuninstall_cmds=$old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$old_archive_from_new_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$archive_cmds
+archive_expsym_cmds=$archive_expsym_cmds
+postinstall_cmds=$postinstall_cmds
+postuninstall_cmds=$postuninstall_cmds
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$global_symbol_to_cdecl
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$include_expsyms
+
+EOF
+
+case "$ltmain" in
+*.sh)
+ echo '### END LIBTOOL CONFIG' >> "$ofile"
+ echo >> "$ofile"
+ case "$host_os" in
+ aix3*)
+ cat <<\EOF >> "$ofile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "${COLLECT_NAMES+set}" != set; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # Append the ltmain.sh script.
+ sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
+
+ chmod +x "$ofile"
+ ;;
+
+*)
+ # Compile the libtool program.
+ echo "FIXME: would compile $ltmain"
+ ;;
+esac
+
+test -n "$cache_file" || exit 0
+
+# AC_CACHE_SAVE
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
--- /dev/null
+dnl Copyright (C) 2004-2008 Kim Woelders
+dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
+dnl That code is public domain and can be freely used or copied.
+dnl Originally snatched from somewhere...
+
+dnl Macro for checking if the compiler supports __attribute__
+
+dnl Usage: AC_C___ATTRIBUTE__
+dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
+dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
+dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
+dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
+dnl defined to nothing.
+
+AC_DEFUN([AC_C___ATTRIBUTE__],
+[
+
+AC_MSG_CHECKING([for __attribute__])
+
+AC_CACHE_VAL([ac_cv___attribute__],
+ [AC_TRY_COMPILE(
+ [
+#include <stdlib.h>
+
+int func(int x);
+int foo(int x __attribute__ ((unused)))
+{
+ exit(1);
+}
+ ],
+ [],
+ [ac_cv___attribute__="yes"],
+ [ac_cv___attribute__="no"]
+ )])
+
+AC_MSG_RESULT($ac_cv___attribute__)
+
+if test "x${ac_cv___attribute__}" = "xyes" ; then
+ AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
+ AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
+ else
+ AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
+fi
+
+])
+
+dnl End of ac_attribute.m4
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: remix
+Description: An audio rendering library
+Requires: ctxdata sndfile
+Version: @VERSION@
+Libs: -L${libdir} -lremix -ldl
+Cflags: -I${includedir}
--- /dev/null
+
+%define name remix
+%define version 0.2.3
+%define release 1
+%define prefix /usr
+
+Summary: An audio rendering library
+Name: %{name}
+Version: %{version}
+Release: %{release}
+Prefix: %{prefix}
+Copyright: LGPL
+Group: Libraries/Sound
+Source: http://www.metadecks.org/software/remix/download/libremix-%{version}.tar.gz
+URL: http://www.metadecks.org/software/remix/
+BuildRoot: /var/tmp/%{name}-%{version}
+
+%description
+Remix is a library for rendering audio data.
+
+%package devel
+Summary: Libraries, includes, etc to develop remix applications
+Group: Libraries
+
+%description devel
+Libraries, include files, etc you can use to develop remix applications.
+
+%prep
+%setup
+
+%build
+./configure --prefix=%{prefix}
+make
+
+%install
+if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
+mkdir -p $RPM_BUILD_ROOT
+make prefix=$RPM_BUILD_ROOT%{prefix} install
+
+%clean
+if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README TODO doc
+%prefix/lib/libremix.so.*
+
+%files devel
+%defattr(-,root,root)
+%{prefix}/lib/libremix.a
+%{prefix}/lib/libremix.la
+%{prefix}/lib/libremix.so
+%{prefix}/include/remix.h
+%{prefix}/include/remix_plugin.h
+
+%changelog
+* Tue Sep 18 2001 Conrad Parker <Conrad.Parker@CSIRO.AU>
+- Created axel.spec.in (hacked from libsndfile.spec.in)
--- /dev/null
+
+%define name @PACKAGE@
+%define version @VERSION@
+%define release 1
+%define prefix /usr
+
+Summary: An audio rendering library
+Name: %{name}
+Version: %{version}
+Release: %{release}
+Prefix: %{prefix}
+Copyright: LGPL
+Group: Libraries/Sound
+Source: http://www.metadecks.org/software/remix/download/libremix-%{version}.tar.gz
+URL: http://www.metadecks.org/software/remix/
+BuildRoot: /var/tmp/%{name}-%{version}
+
+%description
+Remix is a library for rendering audio data.
+
+%package devel
+Summary: Libraries, includes, etc to develop remix applications
+Group: Libraries
+
+%description devel
+Libraries, include files, etc you can use to develop remix applications.
+
+%prep
+%setup
+
+%build
+./configure --prefix=%{prefix}
+make
+
+%install
+if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
+mkdir -p $RPM_BUILD_ROOT
+make prefix=$RPM_BUILD_ROOT%{prefix} install
+
+%clean
+if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README TODO doc
+%prefix/lib/libremix.so.*
+
+%files devel
+%defattr(-,root,root)
+%{prefix}/lib/libremix.a
+%{prefix}/lib/libremix.la
+%{prefix}/lib/libremix.so
+%{prefix}/include/remix.h
+%{prefix}/include/remix_plugin.h
+
+%changelog
+* Tue Sep 18 2001 Conrad Parker <Conrad.Parker@CSIRO.AU>
+- Created axel.spec.in (hacked from libsndfile.spec.in)
--- /dev/null
+
+SUBDIRS = ctxdata libremix plugins examples tests
--- /dev/null
+
+INCLUDES =
+
+lib_LTLIBRARIES = libctxdata.la
+
+libctxdata_la_SOURCES = \
+ ctxdata.h \
+ cd_list.c \
+ cd_scalar.c \
+ cd_set.c
+
+include_HEADERS = ctxdata.h
--- /dev/null
+/*
+ * CtxData -- Context oriented data types
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * CDList: A generic doubly-linked list implementation.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+
+#include "ctxdata.h"
+
+static CDList *
+cd_list_item_new (void * ctx, CDScalar data)
+{
+ CDList * l;
+
+ l = cd_malloc (sizeof (struct _CDList));
+ l->prev = l->next = NULL;
+ l->data = data;
+
+ return l;
+}
+
+CDList *
+cd_list_new (void * ctx)
+{
+ return NULL;
+}
+
+CDList *
+cd_list_copy (void * ctx, CDList * list)
+{
+ CDList * new_list = cd_list_new (ctx);
+ CDList * l;
+
+ for (l = list; l; l = l->next) {
+ new_list = cd_list_append (ctx, new_list, l->data);
+ }
+
+ return new_list;
+}
+
+CDList *
+cd_list_clone (void * ctx, CDList * list, CDCloneFunc clone)
+{
+ CDList * new_list = cd_list_new (ctx);
+ CDList * l;
+ CDScalar new_data;
+
+ for (l = list; l; l = l->next) {
+ new_data = CD_POINTER (clone (ctx, l->data.s_pointer));
+ new_list = cd_list_append (ctx, new_list, new_data);
+ }
+
+ return new_list;
+}
+
+CDList *
+cd_list_clone_with (void * ctx, CDList * list, CDCloneWithFunc clone,
+ void * with)
+{
+ CDList * new_list = cd_list_new (ctx);
+ CDList * l;
+ CDScalar new_data;
+
+ for (l = list; l; l = l->next) {
+ new_data = CD_POINTER (clone (ctx, l->data.s_pointer, with));
+ new_list = cd_list_append (ctx, new_list, new_data);
+ }
+
+ return new_list;
+}
+
+CDList *
+cd_list_last_item (void * ctx, CDList * list)
+{
+ CDList * l;
+ for (l = list; l; l = l->next)
+ if (l->next == NULL) return l;
+ return NULL;
+}
+
+CDScalar
+cd_list_last (void * ctx, CDList * list, CDScalarType type)
+{
+ CDList * l = cd_list_last_item (ctx, list);
+ return ((l == NULL) ? cd_scalar_invalid (ctx, type) : l->data);
+}
+
+CDList *
+cd_list_prepend (void * ctx, CDList * list, CDScalar data)
+{
+ CDList * l = cd_list_item_new (ctx, data);
+
+ if (list == NULL) return l;
+
+ l->next = list;
+ list->prev = l;
+
+ return l;
+}
+
+CDList *
+cd_list_append (void * ctx, CDList * list, CDScalar data)
+{
+ CDList * l = cd_list_item_new (ctx, data);
+ CDList * last;
+
+ if (list == NULL) return l;
+
+ last = cd_list_last_item (ctx, list);
+ if (last) last->next = l;
+ l->prev = last;
+ return list;
+}
+
+CDList *
+cd_list_add_before_item (void * ctx, CDList * list, CDScalar data,
+ CDList * item)
+{
+ CDList * l, * p;
+
+ if (list == NULL) return cd_list_item_new (ctx, data);
+ if (item == NULL) return cd_list_append (ctx, list, data);
+ if (item == list) return cd_list_prepend (ctx, list, data);
+
+ l = cd_list_item_new (ctx, data);
+ p = item->prev;
+
+ l->prev = p;
+ l->next = item;
+ if (p) p->next = l;
+ item->prev = l;
+
+ return list;
+}
+
+CDList *
+cd_list_add_after_item (void * ctx, CDList * list, CDScalar data,
+ CDList * item)
+{
+ CDList * l, * n;
+
+ if (item == NULL) return cd_list_prepend (ctx, list, data);
+
+ l = cd_list_item_new (ctx, data);
+ n = item->next;
+
+ l->prev = item;
+ l->next = n;
+ if (n) n->prev = l;
+ item->next = l;
+
+ return list;
+}
+
+CDList *
+cd_list_add_before (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data, CDScalar before)
+{
+ CDList * b = cd_list_find (ctx, list, type, before);
+ return cd_list_add_before_item (ctx, list, data, b);
+}
+
+CDList *
+cd_list_add_after (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data, CDScalar after)
+{
+ CDList * a = cd_list_find (ctx, list, type, after);
+ return cd_list_add_after_item (ctx, list, data, a);
+}
+
+
+CDList *
+cd_list_find (void * ctx, CDList * list, CDScalarType type, CDScalar data)
+{
+ CDList * l;
+
+ for (l = list; l; l = l->next)
+ if (cd_scalar_eq (ctx, type, l->data, data)) return l;
+
+ return NULL;
+}
+
+/*
+ * cd_list_find_first (ctx, list, f, data)
+ *
+ * Finds the first item l of 'list' for which f (ctx, l->data, data) is true.
+ * Returns NULL if the condition is not true for any item of 'list'.
+ */
+CDList *
+cd_list_find_first (void * ctx, CDList * list, CDScalarType type,
+ CDCmpFunc f, CDScalar data)
+{
+ CDList * l;
+
+ switch (type) {
+ case CD_TYPE_CHAR:
+ for (l = list; l; l = l->next)
+ if (((CDCmpCharFunc)f)(ctx, l->data.s_char, data.s_char)) return l;
+ break;
+ case CD_TYPE_UCHAR:
+ for (l = list; l; l = l->next)
+ if (((CDCmpUCharFunc)f)(ctx, l->data.s_uchar, data.s_uchar)) return l;
+ break;
+ case CD_TYPE_INT:
+ for (l = list; l; l = l->next)
+ if (((CDCmpIntFunc)f)(ctx, l->data.s_int, data.s_int)) return l;
+ break;
+ case CD_TYPE_UINT:
+ for (l = list; l; l = l->next)
+ if (((CDCmpUIntFunc)f)(ctx, l->data.s_uint, data.s_uint)) return l;
+ break;
+ case CD_TYPE_LONG:
+ for (l = list; l; l = l->next)
+ if (((CDCmpLongFunc)f)(ctx, l->data.s_long, data.s_long)) return l;
+ break;
+ case CD_TYPE_ULONG:
+ for (l = list; l; l = l->next)
+ if (((CDCmpULongFunc)f)(ctx, l->data.s_ulong, data.s_ulong)) return l;
+ break;
+ case CD_TYPE_FLOAT:
+ for (l = list; l; l = l->next)
+ if (((CDCmpFloatFunc)f)(ctx, l->data.s_float, data.s_float)) return l;
+ break;
+ case CD_TYPE_DOUBLE:
+ for (l = list; l; l = l->next)
+ if (((CDCmpDoubleFunc)f)(ctx, l->data.s_double, data.s_double)) return l;
+ break;
+ case CD_TYPE_STRING:
+ for (l = list; l; l = l->next)
+ if (((CDCmpStringFunc)f)(ctx, l->data.s_string, data.s_string)) return l;
+ break;
+ case CD_TYPE_POINTER:
+ for (l = list; l; l = l->next)
+ if (((CDCmpFunc)f)(ctx, l->data.s_pointer, data.s_pointer)) return l;
+ break;
+ default: break;
+ }
+
+ return NULL;
+}
+
+/*
+ * cd_list_find_last (ctx, list, f, data)
+ *
+ * Finds the last item l of 'list' for which f (ctx, l->data, data) is true.
+ * Returns NULL if no items are found for which the condition is true
+ * before an item is found for which it is false.
+ */
+CDList *
+cd_list_find_last (void * ctx, CDList * list, CDScalarType type,
+ CDCmpFunc f, CDScalar data)
+{
+ CDList * l, * lp = NULL;
+
+ switch (type) {
+ case CD_TYPE_CHAR:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpCharFunc)f)(ctx, l->data.s_char, data.s_char))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_UCHAR:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpUCharFunc)f)(ctx, l->data.s_uchar, data.s_uchar))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_INT:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpIntFunc)f)(ctx, l->data.s_int, data.s_int))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_UINT:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpUIntFunc)f)(ctx, l->data.s_uint, data.s_uint))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_LONG:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpLongFunc)f)(ctx, l->data.s_long, data.s_long))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_ULONG:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpULongFunc)f)(ctx, l->data.s_ulong, data.s_ulong))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_FLOAT:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpFloatFunc)f)(ctx, l->data.s_float, data.s_float))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_DOUBLE:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpDoubleFunc)f)(ctx, l->data.s_double, data.s_double))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_STRING:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpStringFunc)f)(ctx, l->data.s_string, data.s_string))
+ return lp;
+ lp = l;
+ }
+ break;
+ case CD_TYPE_POINTER:
+ for (l = list; l; l = l->next) {
+ if (!((CDCmpFunc)f)(ctx, l->data.s_pointer, data.s_pointer))
+ return lp;
+ lp = l;
+ }
+ break;
+ default: break;
+ }
+
+ return lp;
+}
+
+/*
+ * cd_list_insert (ctx, list, data, f)
+ *
+ * Inserts data into sorted list 'list' using the comparison function 'f'.
+ * 'data' is inserted before the first item l found for which f(ctx, l, data)
+ * is true.
+ */
+CDList *
+cd_list_insert (void * ctx, CDList * list, CDScalarType type, CDScalar data,
+ CDCmpFunc f)
+{
+ CDList * l;
+ if (list == NULL) return cd_list_prepend (ctx, list, data);
+ if ((l = cd_list_find_first (ctx, list, type, f, data)) == NULL)
+ return cd_list_append (ctx, list, data);
+ return cd_list_add_before_item (ctx, list, data, l);
+}
+
+CDList *
+cd_list_remove (void * ctx, CDList * list, CDScalarType type, CDScalar data)
+{
+ CDList * l = cd_list_find (ctx, list, type, data);
+
+ if (l == NULL) return list;
+
+ if (l->prev) l->prev->next = l->next;
+ if (l->next) l->next->prev = l->prev;
+
+ if (l == list) return list->next;
+ else return list;
+}
+
+CDList *
+cd_list_join (void * ctx, CDList * l1, CDList * l2)
+{
+ CDList * l1_last = cd_list_last_item (ctx, l1);
+
+ if (l1_last == NULL) return l2;
+
+ l1_last->next = l2;
+ if (l2 != NULL) l2->prev = l1_last;
+
+ return l1;
+}
+
+int
+cd_list_length (void * ctx, CDList * list)
+{
+ CDList * l;
+ int c = 0;
+
+ for (l = list; l; l = l->next)
+ c++;
+
+ return c;
+}
+
+int
+cd_list_is_empty (void * ctx, CDList * list)
+{
+ return (list == NULL);
+}
+
+int
+cd_list_is_singleton (void * ctx, CDList * list)
+{
+ if (list == NULL) return 0;
+ if (list->next == NULL) return 1;
+ else return 0;
+}
+
+/*
+ * cd_list_destroy_with (ctx, list, destroy)
+ *
+ * Step through list 'list', destroying each item using AxDestroyFunc destroy,
+ * and also free the list structure itself.
+ */
+CDList *
+cd_list_destroy_with (void * ctx, CDList * list, CDDestroyFunc destroy)
+{
+ CDList * l, * ln;
+
+ for (l = list; l; l = ln) {
+ ln = l->next;
+// destroy (ctx, l->data.s_pointer);
+ cd_free (l);
+ }
+
+ return NULL;
+}
+
+/*
+ * cd_list_free_all (ctx, list)
+ *
+ * Step through list 'list', freeing each item using cd_free(), and
+ * also free the list structure itself.
+ */
+CDList *
+cd_list_free_all (void * ctx, CDList * list)
+{
+ return cd_list_destroy_with (ctx, list, (CDDestroyFunc)cd_free);
+}
+
+/*
+ * cd_list_free (list)
+ *
+ * Free the list structure 'list', but not its items.
+ */
+CDList *
+cd_list_free (void * ctx, CDList * list)
+{
+ CDList * l, * ln;
+
+ for (l = list; l; l = ln) {
+ ln = l->next;
+ cd_free (l);
+ }
+
+ return NULL;
+}
+
+void
+cd_list_apply (void * ctx, CDList * list, CDFunc func)
+{
+ CDList * l;
+
+ for (l = list; l; l = l->next) {
+ func (ctx, l->data.s_pointer);
+ }
+}
--- /dev/null
+/*
+ * CtxData -- Context oriented data types
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * CDScalar: Polymorphic scalar values
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+
+#include "ctxdata.h"
+
+CDScalar
+cd_scalar_invalid (void * ctx, CDScalarType type)
+{
+ return CD_POINTER(NULL);
+}
+
+int
+cd_scalar_eq (void * ctx, CDScalarType type, CDScalar d1, CDScalar d2)
+{
+ switch (type) {
+ case CD_TYPE_CHAR: return (d1.s_char == d2.s_char); break;
+ case CD_TYPE_UCHAR: return (d1.s_uchar == d2.s_uchar); break;
+ case CD_TYPE_INT: return (d1.s_int == d2.s_int); break;
+ case CD_TYPE_UINT: return (d1.s_uint == d2.s_uint); break;
+ case CD_TYPE_LONG: return (d1.s_long == d2.s_long); break;
+ case CD_TYPE_ULONG: return (d1.s_ulong == d2.s_ulong); break;
+ case CD_TYPE_FLOAT: return (d1.s_float == d2.s_float); break;
+ case CD_TYPE_DOUBLE: return (d1.s_double == d2.s_double); break;
+ case CD_TYPE_STRING: return (d1.s_string == d2.s_string); break;
+ case CD_TYPE_POINTER: return (d1.s_pointer == d2.s_pointer); break;
+ default: return 0;
+ }
+}
--- /dev/null
+/*
+ * CtxData -- Context oriented data types
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * CDSet: A keyed set implementation.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+
+#include "ctxdata.h"
+
+static CDSet *
+cd_set_item_new (void * ctx, int key, CDScalar data)
+{
+ CDSet * s;
+
+ s = cd_malloc (sizeof (struct _CDSet));
+ s->prev = s->next = NULL;
+ s->key = key;
+ s->data = data;
+
+ return s;
+}
+
+CDSet *
+cd_set_new (void * ctx)
+{
+ return NULL;
+}
+
+CDSet *
+cd_set_clone (void * ctx, CDSet * set, CDCloneFunc clone)
+{
+ CDSet * new_set = cd_set_new (ctx);
+ CDSet * s;
+ void * new_data;
+
+ for (s = set; s; s = s->next) {
+ new_data = clone (ctx, s->data.s_pointer);
+ new_set = cd_set_insert (ctx, new_set, s->key, CD_POINTER(new_data));
+ }
+
+ return new_set;
+}
+
+CDSet *
+cd_set_clone_keys (void * ctx, CDSet * set)
+{
+ CDSet * new_set = cd_set_new (ctx);
+ CDSet * s;
+
+ for (s = set; s; s = s->next) {
+ new_set = cd_set_insert (ctx, new_set, s->key, CD_INT(0));
+ }
+
+ return new_set;
+}
+
+CDSet *
+cd_set_clone_with (void * ctx, CDSet * set, CDCloneWithFunc clone,
+ void * with)
+{
+ CDSet * new_set = cd_set_new (ctx);
+ CDSet * s;
+ void * new_data;
+
+ for (s = set; s; s = s->next) {
+ new_data = clone (ctx, s->data.s_pointer, with);
+ new_set = cd_set_insert (ctx, new_set, s->key, CD_POINTER(new_data));
+ }
+
+ return new_set;
+}
+
+static CDSet *
+cd_set_find_item (void * ctx, CDSet * set, int key)
+{
+ CDSet * s;
+
+ for (s = set; s; s = s->next)
+ if (s->key == key) return s;
+
+ return NULL;
+}
+
+int
+cd_set_contains (void * ctx, CDSet * set, int key)
+{
+ CDSet * s = cd_set_find_item (ctx, set, key);
+ return (s != NULL);
+}
+
+CDScalar
+cd_set_find (void * ctx, CDSet * set, int key)
+{
+ CDSet * s = cd_set_find_item (ctx, set, key);
+ if (s == NULL) return CD_POINTER(NULL);
+ return s->data;
+}
+
+
+/*
+ * cd_set_insert (ctx, set, key, data)
+ *
+ * Inserts data into set 'set'.
+ */
+CDSet *
+cd_set_insert (void * ctx, CDSet * set, int key, CDScalar data)
+{
+ CDSet * check, * s;
+
+ check = cd_set_find_item (ctx, set, key);
+ if (check != NULL) return NULL; /* already contained */
+
+ s = cd_set_item_new (ctx, key, data);
+
+ if (set == NULL) return s;
+
+ s->next = set;
+ set->prev = s;
+
+ return s;
+}
+
+CDSet *
+cd_set_remove (void * ctx, CDSet * set, int key)
+{
+ CDSet * s = cd_set_find_item (ctx, set, key);
+
+ if (s == NULL) return set;
+
+ if (s->prev) s->prev->next = s->next;
+ if (s->next) s->next->prev = s->prev;
+
+ if (s == set) return set->next;
+ else return set;
+}
+
+CDSet *
+cd_set_replace (void * ctx, CDSet * set, int key, CDScalar data)
+{
+ CDSet * s = cd_set_find_item (ctx, set, key);
+
+ if (s == NULL) { /* Not previously contained */
+ return cd_set_insert (ctx, set, key, data);
+ }
+
+ s->data = data;
+
+ return set;
+}
+
+int
+cd_set_size (void * ctx, CDSet * set)
+{
+ CDSet * s;
+ int n = 0;
+
+ for (s = set; s; s = s->next)
+ n++;
+
+ return n;
+}
+
+int
+cd_set_is_empty (void * ctx, CDSet * set)
+{
+ return (set == NULL);
+}
+
+int
+cd_set_is_singleton (void * ctx, CDSet * set)
+{
+ if (set == NULL) return 0;
+ if (set->next == NULL) return 1;
+ else return 0;
+}
+
+/*
+ * cd_set_destroy_with (ctx, set, destroy)
+ *
+ * Step through set 'set', destroying each item using CDDestroyFunc destroy,
+ * and also free the set structure itself.
+ */
+CDSet *
+cd_set_destroy_with (void * ctx, CDSet * set, CDDestroyFunc destroy)
+{
+ CDSet * s, * sn;
+
+ for (s = set; s; s = sn) {
+ sn = s->next;
+ destroy (ctx, s->data.s_pointer);
+ cd_free (s);
+ }
+
+ return NULL;
+}
+
+/*
+ * cd_set_free_all (ctx, set)
+ *
+ * Step through set 'set', freeing each item using cd_free(), and
+ * also free the set structure itself.
+ */
+CDSet *
+cd_set_free_all (void * ctx, CDSet * set)
+{
+ return cd_set_destroy_with (ctx, set, (CDDestroyFunc)cd_free);
+}
+
+/*
+ * cd_set_free (set)
+ *
+ * Free the set structure 'set', but not its items.
+ */
+CDSet *
+cd_set_free (void * ctx, CDSet * set)
+{
+ CDSet * s, * sn;
+
+ for (s = set; s; s = sn) {
+ sn = s->next;
+ cd_free (s);
+ }
+
+ return NULL;
+}
--- /dev/null
+/*
+ * CtxData -- Context dependent data types
+ *
+ * Copyright (C) 2001 Conrad Parker <conrad@vergenet.net>
+ *
+ * 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 __CTXDATA_H__
+#define __CTXDATA_H__
+
+#include <stdlib.h>
+
+#define cd_malloc malloc
+#define cd_free free
+
+#ifdef FALSE
+#undef FALSE
+#endif
+#define FALSE (0)
+
+#ifdef TRUE
+#undef TRUE
+#endif
+#define TRUE (!FALSE)
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+typedef int CDScalarType;
+typedef union _CDScalar CDScalar;
+typedef struct _CDSet CDSet;
+typedef struct _CDList CDList;
+
+#define CD_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+
+typedef void * (*CDOpaqueFunc) (void);
+
+typedef void * (*CDFunc) (void * ctx, void * data);
+typedef void * (*CDCloneFunc) (void * ctx, void * data);
+typedef void * (*CDCloneWithFunc) (void * ctx, void * data, void * with);
+typedef void (*CDFreeFunc) (void * ctx, void * data);
+typedef int (*CDDestroyFunc) (void * ctx, void * data);
+
+typedef int (*CDCmpBoolFunc) (void * ctx, int data1, int data2);
+typedef int (*CDCmpCharFunc) (void * ctx, char data1, char data2);
+typedef int (*CDCmpUCharFunc) (void * ctx, unsigned char data1,
+ unsigned char data2);
+typedef int (*CDCmpIntFunc) (void * ctx, int data1, int data2);
+typedef int (*CDCmpUIntFunc) (void * ctx, unsigned int data1,
+ unsigned int data2);
+typedef int (*CDCmpLongFunc) (void * ctx, long data1, long data2);
+typedef int (*CDCmpULongFunc) (void * ctx, unsigned long data1,
+ unsigned long data2);
+typedef int (*CDCmpFloatFunc) (void * ctx, float data1, float data2);
+typedef int (*CDCmpDoubleFunc) (void * ctx, double data1, double data2);
+typedef int (*CDCmpStringFunc) (void * ctx, char * data1, char * data2);
+
+typedef int (*CDCmpFunc) (void * ctx, void * data1, void * data2);
+
+enum _CDScalarType {
+ CD_TYPE_CHAR,
+ CD_TYPE_UCHAR,
+ CD_TYPE_INT,
+ CD_TYPE_UINT,
+ CD_TYPE_LONG,
+ CD_TYPE_ULONG,
+ CD_TYPE_FLOAT,
+ CD_TYPE_DOUBLE,
+ CD_TYPE_STRING,
+ CD_TYPE_POINTER
+};
+
+union _CDScalar {
+ int s_bool;
+ char s_char;
+ unsigned char s_uchar;
+ int s_int;
+ unsigned int s_uint;
+ long s_long;
+ unsigned long s_ulong;
+ float s_float;
+ double s_double;
+ char * s_string;
+ void * s_pointer;
+};
+
+#define CD_BOOL(x) ((CDScalar)((unsigned char)(x)))
+#define CD_CHAR(x) ((CDScalar)((char)(x)))
+#define CD_UCHAR(x) ((CDScalar)((unsigned char)(x)))
+#define CD_INT(x) ((CDScalar)((int)(x)))
+#define CD_UINT(x) ((CDScalar)((unsigned int)(x)))
+#define CD_LONG(x) ((CDScalar)((long)(x)))
+#define CD_ULONG(x) ((CDScalar)((unsigned long)(x)))
+#define CD_FLOAT(x) ((CDScalar)((float)(x)))
+#define CD_DOUBLE(x) ((CDScalar)((double)(x)))
+#define CD_STRING(x) ((CDScalar)((char *)(x)))
+#define CD_POINTER(x) ((CDScalar)((void *)(x)))
+
+struct _CDSet {
+ CDSet * prev;
+ CDSet * next;
+ int key;
+ CDScalar data;
+};
+
+struct _CDList {
+ CDList * prev;
+ CDList * next;
+ CDScalar data;
+};
+
+/* cd_type */
+
+CDScalar cd_scalar_invalid (void * ctx, CDScalarType type);
+int cd_scalar_eq (void * ctx, CDScalarType type, CDScalar d1, CDScalar d2);
+
+/* cd_set */
+
+#define CD_EMPTY_SET NULL
+#define CD_SINGLETON_SET(k,x) (&(((struct _CDSet){NULL, NULL, (k), (x)})))
+
+CDSet * cd_set_new (void * ctx);
+CDSet * cd_set_clone (void * ctx, CDSet * set, CDCloneFunc clone);
+CDSet * cd_set_clone_keys (void * ctx, CDSet * set);
+CDSet * cd_set_clone_with (void * ctx, CDSet * set, CDCloneWithFunc clone,
+ void * with);
+int cd_set_contains (void * ctx, CDSet * set, int key);
+CDScalar cd_set_find (void * ctx, CDSet * set, int key);
+CDSet * cd_set_insert (void * ctx, CDSet * set, int key, CDScalar data);
+CDSet * cd_set_remove (void * ctx, CDSet * set, int key);
+CDSet * cd_set_replace (void * ctx, CDSet * set, int key, CDScalar data);
+int cd_set_is_empty (void * ctx, CDSet * set);
+int cd_set_is_singleton (void * ctx, CDSet * set);
+int cd_set_size (void * ctx, CDSet * set);
+CDSet * cd_set_destroy_with (void * ctx, CDSet * set, CDDestroyFunc destroy);
+CDSet * cd_set_free_all (void * ctx, CDSet * set);
+CDSet * cd_set_free (void * ctx, CDSet * set);
+
+
+/* cd_list */
+
+#define CD_EMPTY_LIST NULL
+#define CD_SINGLETON_LIST(x) (&(((struct _CDList){NULL, NULL, (x)})))
+
+CDList * cd_list_new (void * ctx);
+CDList * cd_list_copy (void * ctx, CDList * list);
+CDList * cd_list_clone (void * ctx, CDList * list, CDCloneFunc clone);
+CDList * cd_list_clone_with (void * ctx, CDList * list, CDCloneWithFunc clone,
+ void * with);
+CDList * cd_list_last_item (void * ctx, CDList * list);
+CDScalar cd_list_last (void * ctx, CDList * list, CDScalarType type);
+CDList * cd_list_prepend (void * ctx, CDList * list, CDScalar data);
+CDList * cd_list_add_before_item (void * ctx, CDList * list, CDScalar data,
+ CDList * item);
+CDList * cd_list_add_after_item (void * ctx, CDList * list, CDScalar data,
+ CDList * item);
+CDList * cd_list_add_before (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data, CDScalar before);
+CDList * cd_list_add_after (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data, CDScalar after);
+CDList * cd_list_append (void * ctx, CDList * list, CDScalar data);
+CDList * cd_list_find (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data);
+CDList * cd_list_find_first (void * ctx, CDList * list, CDScalarType type,
+ CDCmpFunc f, CDScalar data);
+CDList * cd_list_find_last (void * ctx, CDList * list, CDScalarType type,
+ CDCmpFunc f, CDScalar data);
+CDList * cd_list_insert (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data, CDCmpFunc f);
+CDList * cd_list_remove (void * ctx, CDList * list, CDScalarType type,
+ CDScalar data);
+CDList * cd_list_join (void * ctx, CDList * l1, CDList * l2);
+int cd_list_length (void * ctx, CDList * list);
+int cd_list_is_empty (void * ctx, CDList * list);
+int cd_list_is_singleton (void * ctx, CDList * list);
+CDList * cd_list_destroy_with (void * ctx, CDList * list,
+ CDDestroyFunc destroy);
+CDList * cd_list_free_all (void * ctx, CDList * list);
+CDList * cd_list_free (void * ctx, CDList * list);
+
+void cd_list_apply (void * ctx, CDList * list, CDFunc func);
+
+#endif /* __CTXDATA_H__ */
--- /dev/null
+
+INCLUDES = -I$(top_srcdir)/src/ctxdata -I$(top_srcdir)/include -I../ctxdata
+
+if BUILD_MONITOR
+monitor_programs = noisedemo squaredemo mysquaredemo
+if HAVE_LIBSNDFILE1
+sndfile_programs = sndfiledemo simple_sndfiledemo
+endif
+
+endif
+
+noinst_PROGRAMS = cd_list_test $(monitor_programs) $(sndfile_programs)
+
+EXTRA_DIST = 909_cl.wav 1052.wav
+
+REMIX_LIBS = ../ctxdata/libctxdata.la ../libremix/libremix.la ../ctxdata/libctxdata.la -ldl
+
+cd_list_test_SOURCES = cd_list_test.c
+cd_list_test_LDADD = ../ctxdata/libctxdata.la
+
+noisedemo_SOURCES = noisedemo.c
+noisedemo_LDADD = $(REMIX_LIBS)
+
+squaredemo_SOURCES = squaredemo.c
+squaredemo_LDADD = $(REMIX_LIBS)
+
+mysquaredemo_SOURCES = simple_squaredemo.c
+mysquaredemo_LDADD = $(REMIX_LIBS)
+
+sndfiledemo_CFLAGS = -DSAMPLEDIR=\"$(srcdir)\"
+sndfiledemo_SOURCES = sndfiledemo.c
+sndfiledemo_LDADD = $(REMIX_LIBS) @SNDFILE_LIBS@
+
+simple_sndfiledemo_CFLAGS = -DSAMPLEDIR=\"$(srcdir)\"
+simple_sndfiledemo_SOURCES = simple_sndfiledemo.c
+simple_sndfiledemo_LDADD = $(REMIX_LIBS) @SNDFILE_LIBS@
--- /dev/null
+#include <stdio.h>
+
+#include <ctxdata.h>
+
+void
+ildump (void * ctx, CDList * list)
+{
+ CDList * l;
+ int *i;
+
+ if (list == NULL) {
+ printf ("NULL");
+ } else {
+ for (l=list; l; l = l->next) {
+ i = (int *)l->data.s_pointer;
+ printf ("%d ", *i);
+ }
+ }
+
+ printf ("\n\t[length %d, %s, %s]\n", cd_list_length (ctx, list),
+ cd_list_is_empty (ctx, list) ? "empty" : "non-empty",
+ cd_list_is_singleton (ctx, list) ? "singleton" : "non-singleton");
+}
+
+int
+int_gt (void * ctx, void * d1, void * d2)
+{
+ int i1 = *(int *)d1;
+ int i2 = *(int *)d2;
+ return (i1 > i2);
+}
+
+void *
+int_clone (void * ctx, void * data)
+{
+ int * n = cd_malloc (sizeof (int));
+ *n = *(int *)data;
+ return (void *)n;
+}
+
+int
+main (int argc, char ** argv)
+{
+ CDList * list, * list2;
+ void * ctx;
+ int a=1, b=2, d=4, f=6, g=7, k=11;
+ int v=22, w=23;
+ int z=26;
+
+ ctx = NULL;
+
+ printf ("creating new list\n");
+ list = cd_list_new (ctx);
+ ildump (ctx, list);
+
+ printf ("appending %d\n", f);
+ list = cd_list_append (ctx, list, (CDScalar)(void *)(&f));
+ ildump (ctx, list);
+
+ printf ("appending %d\n", k);
+ list = cd_list_append (ctx, list, CD_POINTER(&k));
+ ildump (ctx, list);
+
+ printf ("inserting %d\n", g);
+ list = cd_list_insert (ctx, list, CD_TYPE_POINTER, CD_POINTER(&g), int_gt);
+ ildump (ctx, list);
+
+ printf ("inserting %d\n", w);
+ list = cd_list_insert (ctx, list, CD_TYPE_POINTER, CD_POINTER(&w), int_gt);
+ ildump (ctx, list);
+
+ printf ("inserting %d\n", z);
+ list = cd_list_insert (ctx, list, CD_TYPE_POINTER, CD_POINTER(&z), int_gt);
+ ildump (ctx, list);
+
+ printf ("inserting %d\n", b);
+ list = cd_list_insert (ctx, list, CD_TYPE_POINTER, CD_POINTER(&b), int_gt);
+ ildump (ctx, list);
+
+ printf ("prepending %d\n", a);
+ list = cd_list_prepend (ctx, list, CD_POINTER(&a));
+ ildump (ctx, list);
+
+ printf ("removing %d\n", g);
+ list = cd_list_remove (ctx, list, CD_TYPE_POINTER, CD_POINTER(&g));
+ ildump (ctx, list);
+
+ printf ("adding %d after %d\n", d, b);
+ list = cd_list_add_after (ctx, list, CD_TYPE_POINTER, CD_POINTER(&d),
+ CD_POINTER(&b));
+ ildump (ctx, list);
+
+ printf ("adding %d before %d\n", v, w);
+ list = cd_list_add_before (ctx, list, CD_TYPE_POINTER, CD_POINTER(&v),
+ CD_POINTER(&w));
+ ildump (ctx, list);
+
+ printf ("cloning list\n");
+ list2 = cd_list_clone (ctx, list, int_clone);
+ ildump (ctx, list2);
+
+ printf ("freeing cloned list\n");
+ list2 = cd_list_free_all (ctx, list2);
+ ildump (ctx, list2);
+
+ exit (0);
+}
--- /dev/null
+/*
+ * noisedemo.c
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <remix/remix.h>
+
+int
+main (int argc, char ** argv)
+{
+ RemixEnv * env;
+ RemixDeck * deck;
+ RemixTrack * track;
+ RemixLayer * l1, * l2;
+ RemixPlugin * noise_plugin;
+ RemixBase * noise1, * noise2;
+ RemixCount length;
+ RemixMonitor * monitor;
+ int i;
+
+ env = remix_init ();
+ remix_set_channels (env, REMIX_MONO);
+
+ deck = remix_deck_new (env);
+ track = remix_track_new (env, deck);
+
+ noise_plugin = remix_find_plugin (env, "envstd::noise");
+
+ if (noise_plugin == NULL) {
+ fprintf (stderr, "Noise plugin not found. You must do 'make install' to install it.\n");
+ exit (1);
+ }
+
+ noise1 = remix_new (env, noise_plugin, NULL);
+ noise2 = remix_new (env, noise_plugin, NULL);
+
+ l1 = remix_layer_new_ontop (env, track, REMIX_TIME_SAMPLES);
+ for (i=0; i < 10; i++) {
+ remix_sound_new (env, noise1, l1, REMIX_SAMPLES(i*2500),
+ REMIX_SAMPLES(1250));
+ }
+
+ length = remix_length (env, deck);
+
+ monitor = remix_monitor_new (env);
+
+ l2 = remix_layer_new_ontop (env, track, REMIX_TIME_SAMPLES);
+ remix_sound_new (env, monitor, l2, REMIX_SAMPLES(0), REMIX_SAMPLES(length));
+
+ remix_process (env, deck, length, RemixNone, RemixNone);
+
+ remix_purge (env);
+
+ exit (0);
+}
--- /dev/null
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <remix/remix.h>
+
+int
+main (int argc, char ** argv)
+{
+ RemixEnv * env;
+ RemixDeck * deck;
+ RemixTrack * track;
+ RemixLayer * l1, * l2, * sample_layer;
+ RemixBase * sf1;
+ RemixBase * player;
+ RemixCount length;
+ RemixPlugin * sf_plugin;
+ RemixPlugin * player_plugin;
+
+ CDSet * sf_parms;
+ int i;
+ int sf_path_key;
+ RemixSound * sound;
+
+ env = remix_init ();
+ remix_set_samplerate(env, 8000);
+ printf( "remix sample rate: %f\n", remix_get_samplerate(env));
+ remix_set_channels (env, REMIX_STEREO);
+
+
+ //############################ Setting files for MIXING ########################
+ sf_plugin = remix_find_plugin (env, "builtin::sndfile_reader"); // keep the plugin list, no need to lookup everytime
+ if (sf_plugin == NULL) {
+ fprintf (stderr, "sf_plugin == NULL\n");
+ exit (1);
+ }
+ sf_parms = cd_set_new (env);
+ sf_path_key = remix_get_init_parameter_key (env, sf_plugin, "path");
+ sf_parms = cd_set_insert (env, sf_parms, sf_path_key, CD_STRING(SAMPLEDIR "/M1F1-int16-AFsp.wav"));
+ sf1 = remix_new (env, sf_plugin, sf_parms);
+
+ deck = remix_deck_new (env);
+ track = remix_track_new (env, deck);
+ l1 = remix_layer_new_ontop (env, track, REMIX_TIME_SAMPLES);
+ remix_sound_new (env, (RemixBase *)sf1, l1, REMIX_SAMPLES(7000), REMIX_SAMPLES(35000) );
+ //################################################################################
+
+ ///////////////////////////////// ADDING PLAYER ////////////////
+ sample_layer = remix_layer_new_ontop (env, track, REMIX_TIME_SAMPLES);
+ player_plugin = remix_find_plugin (env, "stream_player"); // keep the plugin list, no need to lookup everytime
+ if (player_plugin == NULL) {
+ fprintf (stderr, "player_plugin == NULL\n");
+ exit (1);
+ }
+ player = remix_new (env, player_plugin, NULL);
+ remix_sound_new (env, (RemixBase *)player, sample_layer, REMIX_SAMPLES(0), REMIX_SAMPLES(35000));
+ //////////////////////////////////////////////////////////////////
+
+ remix_process (env, deck, 35000, RemixNone, RemixNone);
+ exit (0);
+}
--- /dev/null
+/*
+ * squaredemo.c
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <remix/remix.h>
+
+#define remix_add_sound_B(a,s,l,t1,t2) \
+ remix_sound_new ((a), (s), (l), REMIX_BEAT24S(t1), REMIX_BEAT24S(t2))
+
+#define BEAT 24
+#define HALF_BEAT 12
+#define QUARTER_BEAT 6
+#define EIGHTH_BEAT 3
+
+int
+main (int argc, char ** argv)
+{
+ RemixEnv * env;
+ RemixDeck * deck, * deck2;
+ RemixTrack * track, * track2, * track3, * track4;
+ RemixLayer * l1, * l2, * l3, * l4, * l5;
+ RemixSound * s;
+ RemixSquareTone * square1, * square2, * square3, * square4, * square5;
+ RemixPlugin * noise_plugin;
+ RemixBase * noise;
+ RemixEnvelope * env1, * env2, * env3;
+ RemixEnvelope * ge;
+ RemixCount length;
+ RemixMonitor * monitor;
+ int b = 0, b2 = 0, mb;
+
+ env = remix_init ();
+
+ remix_set_tempo (env, 500);
+ remix_set_channels (env, REMIX_STEREO);
+
+ square1 = remix_squaretone_new (env, 100.0);
+ remix_squaretone_add_channel (env, square1, 0 );
+
+ square2 = remix_squaretone_new (env, 200.0);
+ remix_squaretone_add_channel (env, square2, 0 );
+ remix_squaretone_add_channel (env, square2, 1 );
+
+ square3 = remix_squaretone_new (env, 385.0);
+ remix_squaretone_add_channel (env, square3, 0 );
+
+ // square4 = remix_squaretone_new (env, 231.0);
+ // square5 = remix_squaretone_new (env, 165.0);
+
+ monitor = remix_monitor_new (env);
+
+ deck = remix_deck_new (env);
+ track = remix_track_new (env, deck);
+ l1 = remix_layer_new_ontop (env, track, REMIX_TIME_BEAT24S);
+ s = remix_sound_new (env, square1, l1, REMIX_BEAT24S(0), REMIX_BEAT24S(6));
+ s = remix_sound_new (env, square2, l1, REMIX_BEAT24S(8), REMIX_BEAT24S(12));
+ s = remix_sound_new (env, square3, l1, REMIX_BEAT24S(21), REMIX_BEAT24S(12));
+
+/*
+ remix_track_set_gain (env, track2, 0.6);
+
+ ge = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, ge, REMIX_TIME_SAMPLES);
+ remix_envelope_add_point (env, ge, REMIX_BEAT24S(2), 0.6);
+*/
+
+
+ length = remix_length (env, deck);
+
+ l2 = remix_layer_new_ontop (env, track, REMIX_TIME_SAMPLES);
+ s = remix_sound_new (env, monitor, l2, REMIX_SAMPLES(0), REMIX_SAMPLES(length));
+ //remix_sound_set_gain_envelope (env, s, ge);
+
+ remix_process (env, deck, length, RemixNone, RemixNone);
+
+ remix_purge (env);
+
+ exit (0);
+}
+
--- /dev/null
+/*
+ * sndfiledemo.c
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <remix/remix.h>
+
+int
+main (int argc, char ** argv)
+{
+ RemixEnv * env;
+ RemixDeck * deck, * deck2;
+ RemixTrack * track, * track2, * track3;
+ RemixLayer * l1, * l2, * l3, * l4, * l5;
+ RemixBase * sf1, * sf2;
+ RemixSquareTone * square;
+ RemixCount length;
+ RemixMonitor * monitor;
+ RemixSound * sm;
+ RemixEnvelope * envelope;
+ RemixPlugin * gain_plugin;
+ RemixPlugin * sf_plugin;
+ RemixBase * gain;
+ CDSet * sf_parms;
+ int i;
+ int gain_key;
+ int sf_path_key;
+
+ env = remix_init ();
+ remix_set_tempo (env, 140);
+ remix_set_channels (env, REMIX_STEREO);
+
+#if 0
+ sf1 = remix_sndfile_new (env, "./1052.wav", 0);
+ sf2 = remix_sndfile_new (env, "./909_cl.wav", 0);
+#else
+ sf_plugin = remix_find_plugin (env, "builtin::sndfile_reader");
+ sf_parms = cd_set_new (env);
+ sf_path_key = remix_get_init_parameter_key (env, sf_plugin, "path");
+ sf_parms = cd_set_insert (env, sf_parms, sf_path_key, CD_STRING(SAMPLEDIR "/1052.wav"));
+ if (sf_plugin == NULL) {
+ fprintf (stderr, "sf_plugin == NULL\n");
+ exit (1);
+ }
+ sf1 = remix_new (env, sf_plugin, sf_parms);
+ sf_parms = cd_set_replace (env, sf_parms, 1, CD_STRING(SAMPLEDIR "/909_cl.wav"));
+ sf2 = remix_new (env, sf_plugin, sf_parms);
+#endif
+ square = remix_squaretone_new (env, 220);
+ monitor = remix_monitor_new (env);
+
+#if 0
+ gain = remix_gain_new (env);
+#else
+ gain_plugin = remix_find_plugin (env, "builtin::gain");
+ gain = remix_new (env, gain_plugin, NULL);
+#endif
+
+ envelope = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, envelope, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, envelope, REMIX_BEAT24S(0), 0.1);
+ remix_envelope_add_point (env, envelope, REMIX_BEAT24S(48), 1.3);
+ remix_envelope_add_point (env, envelope, REMIX_BEAT24S(96), 0.1);
+
+#if 0
+ remix_gain_set_envelope (env, gain, env);
+#else
+ gain_key = remix_get_parameter_key (env, gain, "Gain envelope");
+ printf ("got gain key: %d\n", gain_key);
+ remix_set_parameter (env, gain, gain_key, (CDScalar)((void *)envelope));
+#endif
+
+ deck = remix_deck_new (env);
+ track = remix_track_new (env, deck);
+
+ l1 = remix_layer_new_ontop (env, track, REMIX_TIME_BEAT24S);
+ for (i=0; i < 4; i++) {
+ remix_sound_new (env, (RemixBase *)sf1, l1, REMIX_BEAT24S(i*24), REMIX_BEAT24S(18));
+ }
+
+ track2 = remix_track_new (env, deck);
+ l2 = remix_layer_new_ontop (env, track2, REMIX_TIME_BEAT24S);
+ for (i=0; i < 16; i++) {
+ remix_sound_new (env, (RemixBase *)sf2, l2, REMIX_BEAT24S(i*6), REMIX_BEAT24S(4));
+ }
+
+ deck2 = remix_deck_new (env);
+ track3 = remix_track_new (env, deck2);
+
+ l3 = remix_layer_new_ontop (env, track3, REMIX_TIME_BEAT24S);
+ remix_sound_new (env, (RemixBase *)deck, l3, REMIX_BEAT24S(0), REMIX_BEAT24S(96));
+
+#if 1
+ l4 = remix_layer_new_ontop (env, track3, REMIX_TIME_BEAT24S);
+ remix_sound_new (env, (RemixBase *)gain, l4, REMIX_BEAT24S(0), REMIX_BEAT24S(96));
+#endif
+
+ l5 = remix_layer_new_ontop (env, track3, REMIX_TIME_SAMPLES);
+
+ length = remix_length (env, (RemixBase *)deck);
+ sm = remix_sound_new (env, monitor, l5, REMIX_SAMPLES(0), REMIX_SAMPLES(length));
+
+ printf ("deck: %p\ttrack: %p\tl1: %p\nl3: %p\tmonitor: %p\n",
+ deck, track, l1, l3, monitor);
+
+ remix_process (env, deck2, length, RemixNone, RemixNone);
+
+ remix_set_tempo (env, 105);
+ length = remix_length (env, (RemixBase *)deck);
+ remix_sound_set_duration (env, sm, REMIX_SAMPLES(length));
+ remix_seek (env, deck2, 0, SEEK_SET);
+ remix_process (env, deck2, length, RemixNone, RemixNone);
+
+ remix_set_tempo (env, 168);
+ length = remix_length (env, (RemixBase *)deck);
+ remix_sound_set_duration (env, sm, REMIX_SAMPLES(length));
+ remix_seek (env, deck2, 0, SEEK_SET);
+ remix_process (env, deck2, length, RemixNone, RemixNone);
+
+ remix_purge (env);
+
+ exit (0);
+}
--- /dev/null
+/*
+ * squaredemo.c
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <remix/remix.h>
+
+#define remix_add_sound_B(a,s,l,t1,t2) \
+ remix_sound_new ((a), (s), (l), REMIX_BEAT24S(t1), REMIX_BEAT24S(t2))
+
+#define BEAT 24
+#define HALF_BEAT 12
+#define QUARTER_BEAT 6
+#define EIGHTH_BEAT 3
+
+int
+main (int argc, char ** argv)
+{
+ RemixEnv * env;
+ RemixDeck * deck, * deck2;
+ RemixTrack * track, * track2, * track3, * track4;
+ RemixLayer * l1, * l2, * l3, * l4, * l5;
+ RemixSound * s;
+ RemixSquareTone * square1, * square2, * square3, * square4, * square5;
+ RemixPlugin * noise_plugin;
+ RemixBase * noise;
+ RemixEnvelope * env1, * env2, * env3;
+ RemixEnvelope * be1, * be2, * be3;
+ RemixCount length;
+ RemixMonitor * monitor;
+ int b = 0, b2 = 0, mb;
+
+ env = remix_init ();
+
+ remix_set_tempo (env, 160);
+ remix_set_channels (env, REMIX_STEREO);
+
+ square1 = remix_squaretone_new (env, 220.0);
+ square2 = remix_squaretone_new (env, 440.0);
+ square3 = remix_squaretone_new (env, 385.0);
+ square4 = remix_squaretone_new (env, 231.0);
+ square5 = remix_squaretone_new (env, 165.0);
+
+ noise_plugin = remix_find_plugin (env, "builtin::noise");
+ noise = remix_new (env, noise_plugin, NULL);
+
+ monitor = remix_monitor_new (env);
+
+ deck = remix_deck_new (env);
+
+#if 1
+ track = remix_track_new (env, deck);
+
+ l1 = remix_layer_new_ontop (env, track, REMIX_TIME_BEAT24S);
+ remix_add_sound_B (env, square1, l1, b, BEAT); b += BEAT;
+#if 1
+ remix_add_sound_B (env, square2, l1, b, QUARTER_BEAT); b += HALF_BEAT;
+ remix_add_sound_B (env, square2, l1, b, HALF_BEAT); b += HALF_BEAT;
+ remix_add_sound_B (env, square1, l1, b, HALF_BEAT); b += HALF_BEAT;
+ remix_add_sound_B (env, square2, l1, b, QUARTER_BEAT); b += HALF_BEAT;
+ remix_add_sound_B (env, square3, l1, b, HALF_BEAT); b += HALF_BEAT;
+ remix_add_sound_B (env, square2, l1, b, HALF_BEAT); b += HALF_BEAT;
+#endif
+#endif
+
+#if 1
+#if 1
+ track2 = remix_track_new (env, deck);
+ remix_track_set_gain (env, track2, 0.6);
+#else
+ track2 = track;
+#endif
+ l2 = remix_layer_new_ontop (env, track2, REMIX_TIME_BEAT24S);
+ s = remix_add_sound_B (env, square4, l2, b2, HALF_BEAT); b2 += BEAT;
+
+ be1 = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, be1, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, be1, REMIX_BEAT24S(0), 0.9);
+ remix_sound_set_blend_envelope (env, s, be1);
+
+#if 1
+ s = remix_add_sound_B (env, square5, l2, b2, HALF_BEAT); b2 += BEAT;
+ be2 = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, be2, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, be2, REMIX_BEAT24S(0), 0.6);
+ remix_sound_set_blend_envelope (env, s, be2);
+
+ s = remix_add_sound_B (env, square4, l2, b2, BEAT); b2 += 48;
+ be3 = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, be3, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, be3, REMIX_BEAT24S(0), 0.8);
+ remix_sound_set_blend_envelope (env, s, be3);
+#endif
+#endif
+
+#if 1
+ track4 = remix_track_new (env, deck);
+ remix_track_set_gain (env, track4, 0.1);
+ l5 = remix_layer_new_ontop (env, track4, REMIX_TIME_BEAT24S);
+ remix_add_sound_B (env, noise, l5, 0, b);
+#endif
+
+ mb = MAX (b, b2);
+
+ length = remix_length (env, deck);
+ printf ("deck has length %ld\n", length);
+
+ deck2 = remix_deck_new (env);
+ track3 = remix_track_new (env, deck2);
+ l3 = remix_layer_new_ontop (env, track3, REMIX_TIME_BEAT24S);
+
+ s = remix_add_sound_B (env, deck, l3, 0, mb);
+
+#if 1
+ env1 = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, env1, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, env1, REMIX_BEAT24S(0), 0.0);
+ remix_envelope_add_point (env, env1, REMIX_BEAT24S(mb), 0.9);
+ remix_sound_set_gain_envelope (env, s, env1);
+#endif
+
+ s = remix_add_sound_B (env, deck, l3, mb, mb);
+
+#if 1
+ env2 = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, env2, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, env2, REMIX_BEAT24S(0), 0.9);
+ remix_sound_set_gain_envelope (env, s, env2);
+#endif
+
+ s = remix_add_sound_B (env, deck, l3, 2*mb, mb);
+
+#if 1
+ env3 = remix_envelope_new (env, REMIX_ENVELOPE_LINEAR);
+ remix_envelope_set_timetype (env, env3, REMIX_TIME_BEAT24S);
+ remix_envelope_add_point (env, env3, REMIX_BEAT24S(0), 0.9);
+ remix_envelope_add_point (env, env3, REMIX_BEAT24S(mb), 0.0);
+ remix_sound_set_gain_envelope (env, s, env3);
+#endif
+
+ length = remix_length (env, deck2);
+
+ l4 = remix_layer_new_ontop (env, track3, REMIX_TIME_SAMPLES);
+ remix_sound_new (env, monitor, l4, REMIX_SAMPLES(0), REMIX_SAMPLES(length));
+
+ printf ("deck: %p\ttrack: %p\tl1: %p\ttrack2: %p\tl2: %p\n",
+ deck, track, l1, track2, l2);
+ printf ("deck2: %p\ttrack3: %p\tl3: %p\tl4: %p\n", deck2, track3, l3, l4);
+ printf ("square1: %p\tsquare2: %p\tsquare3: %p\nsquare4: %p\tsquare5: %p\n",
+ square1, square2, square3, square4, square5);
+ printf ("monitor: %p\n", monitor);
+
+ remix_process (env, deck2, length, RemixNone, RemixNone);
+
+ remix_purge (env);
+
+ exit (0);
+}
--- /dev/null
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/include/remix $(SNDFILE_CFLAGS) -I$(top_srcdir)/src/ctxdata
+
+lib_LTLIBRARIES = libremix.la
+
+if BUILD_MONITOR
+monitor_sources = remix_monitor.c
+endif
+
+if HAVE_LIBSNDFILE1
+sndfile_sources = remix_sndfile.c
+endif
+
+libremix_la_SOURCES = \
+ $(monitor_sources) \
+ $(sndfile_sources) \
+ remix_base.c \
+ remix_channel.c \
+ remix_channelset.c \
+ remix_chunk.c \
+ remix_context.c \
+ remix_debug.c \
+ remix_deck.c \
+ remix_envelope.c \
+ remix_error.c \
+ remix_gain.c \
+ remix_layer.c \
+ remix_meta.c \
+ remix_null.c \
+ remix_pcm.c \
+ remix_plugin.c \
+ remix_sound.c \
+ remix_squaretone.c \
+ remix_stream.c \
+ remix_time.c \
+ remix_track.c \
+ remix_private.h \
+ remix_compat.h
+
+libremix_la_LIBADD = @SNDFILE_LIBS@
+
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixBase: A generic interface for sound generation and processing.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#include <string.h>
+
+#define __REMIX__
+#include "remix.h"
+
+
+RemixBase *
+remix_new (RemixEnv * env, RemixPlugin * plugin, CDSet * parameters)
+{
+ RemixBase * base;
+
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ base = remix_base_new (env);
+
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ base->plugin = plugin;
+
+ if (plugin->init != NULL) {
+ if (plugin->init (env, base, parameters) == RemixNone) {
+ remix_destroy (env, base);
+ return RemixNone;
+ }
+ }
+
+ return base;
+}
+
+CDSet *
+remix_suggest (RemixEnv * env, RemixPlugin * plugin, CDSet * parameters)
+{
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ if (!plugin->suggest) {
+ /* XXX: should remix_set_error: is NOOP appropriate ?? */
+ return RemixNone;
+ }
+
+ return plugin->suggest (env, plugin, parameters, plugin->plugin_data);
+}
+
+static int
+remix_parameter_scheme_get_key (RemixEnv * env, CDSet * scheme_set, char * name)
+{
+ CDSet * s;
+ RemixParameterScheme * scheme;
+
+ for (s = scheme_set; s; s = s->next) {
+ scheme = (RemixParameterScheme *)s->data.s_pointer;
+ if (!strcmp (scheme->name, name)) return s->key;
+ }
+
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+
+ return -1;
+}
+
+int
+remix_get_init_parameter_key (RemixEnv * env, RemixPlugin * plugin, char * name)
+{
+ if (plugin == RemixNone) {
+ remix_dprintf ("[remix_get_init_parameter_key] plugin == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return remix_parameter_scheme_get_key (env, plugin->init_scheme, name);
+}
+
+int
+remix_get_parameter_key (RemixEnv * env, RemixBase * base, char * name)
+{
+ if (base == RemixNone) {
+ remix_dprintf ("[remix_get_parameter_key] base == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ if (base->plugin == RemixNone) {
+ remix_dprintf ("[remix_get_parameter_key] base->plugin == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return remix_parameter_scheme_get_key (env, base->plugin->process_scheme, name);
+}
+
+RemixParameter
+remix_set_parameter (RemixEnv * env, RemixBase * base, int key,
+ RemixParameter parameter)
+{
+ if (base == RemixNone) {
+ remix_dprintf ("[remix_set_parameter] base == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return (RemixParameter)-1;
+ }
+
+ remix_dprintf ("[remix_set_parameter] base %p, [%d] ==> %p\n", base, key,
+ parameter.s_pointer);
+ base->parameters = cd_set_replace (env, base->parameters, key, parameter);
+ return parameter;
+}
+
+RemixParameter
+remix_get_parameter (RemixEnv * env, RemixBase * base, int key)
+{
+ RemixParameter p;
+
+ if (base == RemixNone) {
+ remix_dprintf ("[remix_get_parameter] base == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return (RemixParameter)-1;
+ }
+
+ p = cd_set_find (env, base->parameters, key);
+ remix_dprintf ("[remix_get_parameter] base %p, [%d] == %p\n", base, key,
+ p.s_pointer);
+ return p;
+}
+
+RemixParameterType
+remix_get_parameter_type (RemixEnv * env, RemixBase * base, int key)
+{
+ RemixPlugin * plugin;
+ CDScalar k;
+ RemixParameterScheme * scheme;
+
+ if (base == RemixNone) {
+ remix_dprintf ("[remix_get_parameter_type] base == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ plugin = base->plugin;
+
+ if (plugin == RemixNone) {
+ remix_dprintf ("[remix_get_parameter_type] base->plugin == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ k = cd_set_find (env, plugin->process_scheme, key);
+ scheme = (RemixParameterScheme *)k.s_pointer;
+
+ if (scheme == RemixNone) {
+ remix_dprintf ("[remix_get_parameter_type] scheme == RemixNone\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return scheme->type;
+}
+
+RemixBase *
+remix_base_new_subclass (RemixEnv * env, size_t size)
+{
+ RemixBase * base = remix_malloc (size);
+ _remix_context_copy (env, &base->context_limit);
+ _remix_register_base (env, base);
+ return base;
+}
+
+RemixBase *
+remix_base_new (RemixEnv * env)
+{
+ return remix_base_new_subclass (env, sizeof (struct _RemixBase));
+}
+
+RemixCount
+remix_base_get_mixlength (RemixEnv * env, RemixBase * base)
+{
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return _remix_base_get_mixlength (env, base);
+}
+
+RemixSamplerate
+remix_base_get_samplerate (RemixEnv * env, RemixBase * base)
+{
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return _remix_base_get_samplerate (env, base);
+}
+
+RemixTempo
+remix_base_get_tempo (RemixEnv * env, RemixBase * base)
+{
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return _remix_base_get_tempo (env, base);
+}
+
+CDSet *
+remix_base_get_channels (RemixEnv * env, RemixBase * base)
+{
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ return _remix_base_get_channels (env, base);
+}
+
+void *
+remix_base_set_instance_data (RemixEnv * env, RemixBase * base, void * data)
+{
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ return _remix_set_instance_data (env, base, data);
+}
+
+void *
+remix_base_get_instance_data (RemixEnv * env, RemixBase * base)
+{
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ return _remix_get_instance_data (env, base);
+}
+
+int
+remix_base_has_samplerate (RemixEnv * env, RemixBase * base)
+{
+ RemixSamplerate asr, bsr;
+
+ asr = remix_get_samplerate (env);
+ bsr = _remix_base_get_samplerate (env, base);
+
+ return (asr == bsr);
+}
+
+int
+remix_base_has_tempo (RemixEnv * env, RemixBase * base)
+{
+ RemixTempo at, bt;
+
+ at = remix_get_tempo (env);
+ bt = _remix_base_get_tempo (env, base);
+
+ return (at == bt);
+}
+
+int
+remix_base_encompasses_mixlength (RemixEnv * env, RemixBase * base)
+{
+ RemixCount aml, bml;
+
+ aml = remix_get_mixlength (env);
+ bml = _remix_base_get_mixlength (env, base);
+
+ return (aml < bml);
+}
+
+int
+remix_base_encompasses_channels (RemixEnv * env, RemixBase * base)
+{
+ CDSet * s, * as, * bs;
+ CDScalar k;
+
+ as = remix_get_channels (env);
+ bs = _remix_base_get_channels (env, base);
+
+ for (s = as; s; s = s->next) {
+ k = cd_set_find (env, bs, s->key);
+ if (k.s_pointer == NULL) return 0;
+ }
+
+ return 1;
+}
+
+RemixMethods *
+remix_base_set_methods (RemixEnv * env, RemixBase * base, RemixMethods * methods)
+{
+ RemixMethods * old = base->methods;
+ _remix_set_methods (env, base, methods);
+ return old;
+}
+
+RemixMethods *
+remix_base_get_methods (RemixEnv * env, RemixBase * base)
+{
+ return _remix_get_methods (env, base);
+}
+
+RemixPlugin *
+remix_base_set_plugin (RemixEnv * env, RemixBase * base, RemixPlugin * plugin)
+{
+ RemixPlugin * old = base->plugin;
+ _remix_set_plugin (env, base, plugin);
+ return old;
+}
+
+RemixPlugin *
+remix_base_get_plugin (RemixEnv * env, RemixBase * base)
+{
+ return _remix_get_plugin (env, base);
+}
+
+RemixBase *
+remix_clone_subclass (RemixEnv * env, RemixBase * base)
+{
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return NULL;
+ }
+ if (!base->methods || !base->methods->clone) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return NULL;
+ }
+ return _remix_clone (env, base);
+}
+
+int
+remix_destroy (RemixEnv * env, RemixBase * base)
+{
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ _remix_unregister_base (env, base);
+
+ if (!base->methods || !base->methods->destroy) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+ return _remix_destroy (env, base);
+}
+
+int
+remix_destroy_list (RemixEnv * env, CDList * list)
+{
+ cd_list_destroy_with (env, list, (CDDestroyFunc)remix_destroy);
+ return 0;
+}
+
+/*
+ * Prepare the methods for process, seek and length calls.
+ *
+ * "Prepare" means to make sure the base has enough internal buffers
+ * to deal with the current context (sample rate, mixlength).
+ *
+ * If the methods has a ready() function, that is checked first. If it
+ * does not have a ready() function, it is assumed to always be ready.
+ */
+RemixBase *
+remix_prepare (RemixEnv * env, RemixBase * base)
+{
+ int is_ready = 0;
+
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return NULL;
+ }
+ if (base->methods && base->methods->prepare) {
+ if (base->methods->ready) {
+ is_ready = base->methods->ready (env, base);
+ }
+
+ _remix_context_merge (env, &base->context_limit);
+
+ if (!is_ready) base =_remix_prepare (env, base);
+ }
+
+ return base;
+}
+
+RemixCount
+remix_process_fast (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixCount n;
+
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+ if (!base->methods || !base->methods->process) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+
+ remix_get_meta_text (env, base);
+
+ n = _remix_process (env, base, count, input, output);
+ if (n > 0) base->offset += n;
+ return n;
+}
+
+RemixCount
+remix_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixCount processed;
+ RemixCount n;
+ RemixError error;
+ char * str;
+
+ remix_debug_down ();
+
+ processed = remix_process_fast (env, base, count, input, output);
+
+ if (processed == -1) {
+ error = remix_last_error (env);
+ str = remix_error_string (env, error);
+ remix_dprintf ("*** ERROR in remix_process: %s\n", str);
+ switch (error) {
+ case REMIX_ERROR_NOOP:
+ n = remix_stream_write (env, output, count, input);
+ if (n > 0) {
+ base->offset += n;
+ processed = n;
+ }
+ break;
+ case REMIX_ERROR_SILENCE:
+ n = remix_stream_write0 (env, output, count);
+ if (n > 0) {
+ base->offset += n;
+ processed = n;
+ }
+ break;
+ default: break;
+ }
+ }
+
+ remix_debug_up ();
+
+ return processed;
+}
+
+RemixCount
+remix_length (RemixEnv * env, RemixBase * base)
+{
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+ if (!base->methods || !base->methods->length) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+ return _remix_length (env, base);
+}
+
+RemixCount
+remix_seek (RemixEnv * env, RemixBase * base, RemixCount offset, int whence)
+{
+ RemixCount new_offset, len;
+
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ new_offset = base->offset;
+
+ switch (whence) {
+ case SEEK_SET: new_offset = offset; break;
+ case SEEK_CUR: new_offset += offset; break;
+ case SEEK_END:
+ len = remix_length (env, base);
+ if (len == -1) return -1;
+ new_offset = len + offset;
+ break;
+ default:
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ break;
+ }
+
+ if (new_offset == base->offset) return new_offset;
+
+ remix_dprintf ("SEEK %p @ %ld\n", base, new_offset);
+
+ if (base->methods && base->methods->seek)
+ base->offset = base->methods->seek (env, base, new_offset);
+ else
+ base->offset = new_offset;
+
+ return base->offset;
+}
+
+RemixCount
+remix_tell (RemixEnv * env, RemixBase * base)
+{
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+ return base->offset;
+}
+
+int
+remix_flush (RemixEnv * env, RemixBase * base)
+{
+ if (!base) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+ if (!base->methods || !base->methods->flush) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+ return _remix_flush (env, base);
+}
+
+RemixMetaText *
+remix_get_meta_text (RemixEnv * env, RemixBase * base)
+{
+ RemixPlugin * plugin = base->plugin;
+ return (plugin ? plugin->metatext : NULL);
+}
+
+RemixMetaText *
+remix_set_meta_text (RemixEnv * env, RemixBase * base, RemixMetaText * mt)
+{
+ RemixPlugin * plugin;
+ RemixMetaText * old;
+
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ plugin = base->plugin;
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ old = plugin->metatext;
+ plugin->metatext = mt;
+ return old;
+}
+
+int
+remix_is_writeable (RemixEnv * env, RemixBase * base)
+{
+ RemixPlugin * plugin;
+
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ plugin = base->plugin;
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return (plugin->flags & REMIX_PLUGIN_WRITEABLE);
+}
+
+int
+remix_is_seekable (RemixEnv * env, RemixBase * base)
+{
+ RemixPlugin * plugin;
+
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ plugin = base->plugin;
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return (plugin->flags & REMIX_PLUGIN_SEEKABLE);
+}
+
+int
+remix_is_cacheable (RemixEnv * env, RemixBase * base)
+{
+ RemixPlugin * plugin;
+
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ plugin = base->plugin;
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return (plugin->flags & REMIX_PLUGIN_CACHEABLE);
+}
+
+int
+remix_is_causal (RemixEnv * env, RemixBase * base)
+{
+ RemixPlugin * plugin;
+
+ if (base == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ plugin = base->plugin;
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return (plugin->flags & REMIX_PLUGIN_CAUSAL);
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixChannel: An indexed, sparse, monophonic PCM data container.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A channel contains a sequence of chunks which contain raw PCM data.
+ *
+ * Channels are named, such that when streams are mixed together their
+ * correspondingly named channels are mixed together.
+ *
+ * A channel is indexed by sample count. When reading a channel, all
+ * index points for which no chunk is defined are defined as zero. Writing
+ * to a channel stops early if no chunk is available at a required point.
+ *
+ * If two or more chunks overlap, the chunk with the latest start index
+ * is always used for both reading and writing data values for the region
+ * of overlap.
+ *
+ * Invariants
+ * ----------
+ *
+ * A channel must be contained within a stream.
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+/* RemixChannel */
+
+RemixChannel *
+remix_channel_new (RemixEnv * env)
+{
+ RemixChannel * c;
+
+ c = (RemixChannel *) remix_malloc (sizeof (struct _RemixChannel));
+
+ c->chunks = cd_list_new (env);
+ c->_current_offset = 0;
+ c->_current_chunk = RemixNone;
+
+ return c;
+}
+
+RemixChannel *
+remix_channel_clone (RemixEnv * env, RemixChannel * channel)
+{
+ RemixChannel * new_channel = remix_channel_new (env);
+ new_channel->chunks = cd_list_clone (env, channel->chunks,
+ (CDCloneFunc)remix_chunk_clone);
+ return new_channel;
+}
+
+int
+remix_channel_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixChannel * channel = (RemixChannel *)base;
+ CDList * l;
+
+ for (l = channel->chunks; l; l = l->next) {
+ remix_chunk_free (env, (RemixChunk *)l->data.s_pointer);
+ }
+
+ cd_list_free (env, channel->chunks);
+ remix_free (channel);
+ return 0;
+}
+
+RemixChunk *
+remix_channel_add_chunk (RemixEnv * env, RemixChannel * channel,
+ RemixChunk * chunk)
+{
+ channel->chunks = cd_list_insert (env, channel->chunks, CD_TYPE_POINTER,
+ CD_POINTER(chunk),
+ (CDCmpFunc)remix_chunk_later);
+ return chunk;
+}
+
+RemixChunk *
+remix_channel_add_new_chunk (RemixEnv * env, RemixChannel * channel,
+ RemixCount offset, RemixCount length)
+{
+ RemixChunk * chunk = remix_chunk_new (env, offset, length);
+ return remix_channel_add_chunk (env, channel, chunk);
+}
+
+void
+remix_channel_remove_chunk (RemixEnv * env, RemixChannel * channel,
+ RemixChunk * chunk)
+{
+ channel->chunks = cd_list_remove (env, channel->chunks, CD_TYPE_POINTER,
+ CD_POINTER(chunk));
+}
+
+RemixChunk *
+remix_channel_find_chunk_before (RemixEnv * env, RemixChannel * channel,
+ RemixCount index)
+{
+ CDList * l;
+ RemixChunk * u, * up = RemixNone;
+
+ for (l = channel->chunks; l; l = l->next) {
+ u = (RemixChunk *)l->data.s_pointer;
+ if (u->start_index > index) return up;
+ up = u;
+ }
+
+ return up;
+}
+
+/*
+ * remix_chunk_item_valid_length (l)
+ *
+ * Returns the length for which the chunk item 'l' is valid. The valid
+ * length of a chunk item in a channel is defined as the minimum of
+ * (the chunk's actual length) and (the difference between the offset
+ * of the chunk and the offset of the following chunk). ie. if the
+ * chunk is followed by another chunk that cuts it off early, the valid
+ * length is the difference between the two chunk offsets. Crikey, email
+ * me if you're confused.
+ */
+static RemixCount
+remix_chunk_item_valid_length (CDList * l)
+{
+ CDList * ln = l->next;
+ RemixChunk * u = (RemixChunk *)l->data.s_pointer, * un;
+
+ if (ln == RemixNone) {
+ return u->length;
+ } else {
+ un = (RemixChunk *)ln->data.s_pointer;
+ return MIN (u->length, un->start_index - u->start_index);
+ }
+}
+
+RemixChunk *
+remix_channel_get_chunk_at (RemixEnv * env, RemixChannel * channel,
+ RemixCount offset)
+{
+ CDList * l;
+ RemixChunk * u;
+ RemixCount vl; /* valid length */
+
+ for (l = channel->chunks; l; l = l->next) {
+ u = (RemixChunk *)l->data.s_pointer;
+ vl = remix_chunk_item_valid_length (l);
+ if (u->start_index <= offset && u->start_index + vl > offset) {
+ /* chunk validly spans offset: return it */
+ return u;
+ }
+ }
+
+ /* No chunks found spanning offset */
+ return RemixNone;
+}
+
+CDList *
+remix_channel_get_chunk_item_at (RemixChannel * channel, RemixCount offset)
+{
+ CDList * l;
+ RemixChunk * u;
+ RemixCount vl; /* valid length */
+
+ for (l = channel->chunks; l; l = l->next) {
+ u = (RemixChunk *)l->data.s_pointer;
+ vl = remix_chunk_item_valid_length (l);
+ if (u->start_index <= offset && u->start_index + vl > offset) {
+ /* chunk validly spans offset: return its item */
+ return l;
+ }
+ }
+
+ /* No chunks found spanning offset */
+ return RemixNone;
+}
+
+CDList *
+remix_channel_get_chunk_item_after (RemixChannel * channel, RemixCount offset)
+{
+ CDList * l;
+ RemixChunk * u;
+
+ for (l = channel->chunks; l; l = l->next) {
+ u = (RemixChunk *)l->data.s_pointer;
+ if (u->start_index >= offset) return l;
+ }
+
+ return RemixNone;
+}
+
+RemixCount
+remix_channel_write0 (RemixEnv * env, RemixChannel * channel, RemixCount length)
+{
+ CDList * l = channel->_current_chunk;
+ RemixChunk * u;
+ RemixCount remaining = length, n, vl;
+ RemixCount offset = channel->_current_offset;
+
+ while (remaining > 0) {
+ if (l == RemixNone) break; /* No more chunks */
+
+ u = (RemixChunk *)l->data.s_pointer;
+
+ if (u->start_index > offset) { /* skip ahead to start of next chunk */
+ n = MIN (remaining, u->start_index - offset);
+ offset += n;
+ remaining -= n;
+ }
+
+ if (remaining > 0) {
+ vl = remix_chunk_item_valid_length (l);
+ n = _remix_chunk_clear_region (env, u, offset, MIN(remaining, vl),
+ 0, NULL);
+ offset += n;
+ remaining -= n;
+ }
+
+ l = l->next;
+ }
+
+ channel->_current_chunk = l;
+ channel->_current_offset += length;
+
+ return length;
+}
+
+/*
+ * remix_channel_chunkfuncify (env, channel, count, func, data)
+ *
+ * Apply the RemixChunkFunc func to 'count' samples from consecutive chunks
+ * of 'channel'.
+ * Stops early if the channel runs out of chunks.
+ * Returns the number of samples func'ed.
+ */
+RemixCount
+remix_channel_chunkfuncify (RemixEnv * env, RemixChannel * channel,
+ RemixCount count, RemixChunkFunc func,
+ int channelname, void * data)
+{
+ RemixChunk * u;
+ RemixCount remaining = count, funced = 0, n, vl;
+ RemixError error;
+
+ remix_dprintf ("[remix_channel_chunkfuncify] (%p, +%ld) @ %ld\n",
+ channel, count, channel->_current_offset);
+
+ while (remaining > 0) {
+ channel->_current_chunk =
+ remix_channel_get_chunk_item_at (channel, channel->_current_offset);
+ if (channel->_current_chunk == RemixNone) {
+ remix_dprintf ("[remix_channel_chunkfuncify] channel incomplete, funced %ld\n",
+ funced);
+ return funced; /* Channel incomplete */
+ }
+
+ u = (RemixChunk *)channel->_current_chunk->data.s_pointer;
+ vl = remix_chunk_item_valid_length (channel->_current_chunk);
+
+ n = func (env, u, channel->_current_offset, MIN(remaining, vl),
+ channelname, data);
+
+ if (n == -1) {
+ error = remix_last_error (env);
+ switch (error) {
+ case REMIX_ERROR_SILENCE:
+ n = _remix_chunk_clear_region (env, u, channel->_current_offset,
+ MIN(remaining, vl), 0, NULL);
+ break;
+ default:
+ n = 0;
+ }
+ }
+
+ funced += n;
+ remaining -= n;
+ channel->_current_offset += n;
+ }
+
+ return funced;
+}
+
+/*
+ * remix_channel_chunkchunkfuncify (env, src, dest, count, func, data)
+ *
+ * Apply the RemixChunkChunkFunc func to corresponding chunks of 'src' and
+ * 'dest' to 'count' samples.
+ * Stops early if 'dest' cannot contain part of the region for which
+ * 'src' is defined. Copies zeroes to 'dest' wherever 'src' is empty.
+ * Returns the number of samples func'ed.
+ */
+RemixCount
+remix_channel_chunkchunkfuncify (RemixEnv * env, RemixChannel * src, RemixChannel * dest,
+ RemixCount count, RemixChunkChunkFunc func,
+ int channelname, void * data)
+{
+ RemixChunk * su, * du;
+ RemixCount remaining = count, funced = 0, n, vl;
+ RemixError error;
+
+ remix_dprintf ("[remix_channel_ccf...] (%p -> %p, +%ld), src @ %ld, dest @ %ld\n",
+ src, dest, count, src->_current_offset, dest->_current_offset);
+
+ while (remaining > 0) {
+ n = 0; /* watch for early changes to n */
+
+ dest->_current_chunk =
+ remix_channel_get_chunk_item_at (dest, dest->_current_offset);
+ if (dest->_current_chunk == RemixNone) {
+ remix_dprintf ("[remix_channel_ccf...] channel incomplete after %ld\n", funced);
+ return funced; /* Destination channel incomplete */
+ }
+
+ src->_current_chunk =
+ remix_channel_get_chunk_item_at (src, src->_current_offset);
+ if (src->_current_chunk == RemixNone) { /* No source data at offset */
+ src->_current_chunk =
+ remix_channel_get_chunk_item_after (src, src->_current_offset);
+
+ if (src->_current_chunk == RemixNone) {
+ /* No following source data at all */
+ remix_dprintf ("[remix_channel_ccf...] no source data after %ld\n",
+ src->_current_offset);
+ n = remix_channel_write0 (env, dest, remaining);
+ funced += n;
+ remaining -= n;
+ return funced;
+ } else {
+ remix_dprintf ("[remix_channel_ccf...] no source data at %ld\n",
+ src->_current_offset);
+ }
+ }
+
+ /* *** Now, sl is the current or following source chunk item *** */
+
+ su = (RemixChunk *)src->_current_chunk->data.s_pointer;
+
+ if (su->start_index > src->_current_offset) { /* No source data at offset */
+ remix_dprintf ("[remix_channel_ccf...] no source data at %ld (warn 2)\n",
+ src->_current_offset);
+ n = remix_channel_write0 (env, dest, su->start_index - src->_current_offset);
+ funced += n;
+ remaining -= n;
+ src->_current_offset += n;
+ }
+
+ if (remaining > 0) {
+ if (n > 0) {
+ dest->_current_chunk =
+ remix_channel_get_chunk_item_at (dest, dest->_current_offset);
+ if (dest->_current_chunk == RemixNone) {
+ remix_dprintf ("[remix_channel_ccf...] dest incomplete after %ld\n",
+ dest->_current_chunk);
+ return funced; /* Destination channel incomplete */
+ }
+ }
+
+ du = (RemixChunk *)dest->_current_chunk->data.s_pointer;
+
+ vl = remix_chunk_item_valid_length (dest->_current_chunk);
+ n = func (env, su, src->_current_offset, du, dest->_current_offset,
+ MIN(remaining, vl), channelname, data);
+
+ if (n == -1) {
+ error = remix_last_error (env);
+ switch (error) {
+ case REMIX_ERROR_SILENCE:
+ n = _remix_chunk_clear_region (env, du, dest->_current_offset,
+ MIN(remaining, vl), 0, NULL);
+ break;
+ default:
+ n = 0;
+ }
+ }
+
+ funced += n;
+ remaining -= n;
+ src->_current_offset += n;
+ dest->_current_offset += n;
+ }
+ }
+
+ remix_dprintf ("[remix_channel_ccf...] funced %ld\n", funced);
+
+ return funced;
+}
+
+/*
+ * remix_channel_chunkchunkchunkfuncify (env, src1, src2, dest, count, func,
+ * data)
+ *
+ * Apply the RemixChunkChunkChunkFunc func to corresponding chunks of 'src1',
+ * 'src2' and 'dest' to 'count' samples.
+ * Stops early if 'dest' cannot contain part of the region for which
+ * both 'src1' and 'src2' is defined. Copies zeroes to 'dest' wherever
+ * either 'src1' or 'src2' are empty.
+ * Returns the number of samples func'ed.
+ */
+RemixCount
+remix_channel_chunkchunkchunkfuncify (RemixEnv * env,
+ RemixChannel * src1, RemixChannel * src2,
+ RemixChannel * dest, RemixCount count,
+ RemixChunkChunkChunkFunc func,
+ int channelname, void * data)
+{
+ RemixChunk * s1u, * s2u, * du;
+ RemixCount remaining = count, funced = 0, n, vl, undef_length;
+ RemixError error;
+
+ while (remaining > 0) {
+ n = 0; /* watch for early changes to n */
+
+ dest->_current_chunk =
+ remix_channel_get_chunk_item_at (dest, dest->_current_offset);
+ if (dest->_current_chunk == RemixNone)
+ return funced; /* Destination channel incomplete */
+
+ src1->_current_chunk =
+ remix_channel_get_chunk_item_at (src1, src1->_current_offset);
+ if (src1->_current_chunk == RemixNone) {
+ src1->_current_chunk =
+ remix_channel_get_chunk_item_after (src1, src1->_current_offset);
+ }
+
+ src2->_current_chunk =
+ remix_channel_get_chunk_item_at (src2, src2->_current_offset);
+ if (src2->_current_chunk == RemixNone) {
+ src2->_current_chunk =
+ remix_channel_get_chunk_item_after (src2, src2->_current_offset);
+ }
+
+ if (src1->_current_chunk == RemixNone || src2->_current_chunk == RemixNone) {
+ n = remix_channel_write0 (env, dest, remaining);
+ funced += n;
+ remaining -= n;
+ return funced;
+ }
+
+ s1u = (RemixChunk *)src1->_current_chunk->data.s_pointer;
+ s2u = (RemixChunk *)src2->_current_chunk->data.s_pointer;
+
+ if (s1u->start_index > src1->_current_offset ||
+ s2u->start_index > src2->_current_offset) {
+ undef_length = MAX (s1u->start_index - src1->_current_offset,
+ s2u->start_index - src2->_current_offset);
+ n = remix_channel_write0 (env, dest, undef_length);
+ funced += n;
+ remaining -= n;
+ src1->_current_offset += n;
+ src2->_current_offset += n;
+ }
+
+ if (remaining > 0) {
+ if (n > 0) {
+ dest->_current_chunk =
+ remix_channel_get_chunk_item_at (dest, dest->_current_offset);
+ if (dest->_current_chunk == RemixNone)
+ return funced; /* Destination channel incomplete */
+ }
+
+ du = (RemixChunk *)dest->_current_chunk->data.s_pointer;
+
+ vl = remix_chunk_item_valid_length (dest->_current_chunk);
+ n = func (env, s1u, src1->_current_offset, s2u, src2->_current_offset,
+ du, dest->_current_offset, MIN(remaining, vl), channelname,
+ data);
+
+ if (n == -1) {
+ error = remix_last_error (env);
+ switch (error) {
+ case REMIX_ERROR_SILENCE:
+ n = _remix_chunk_clear_region (env, du, dest->_current_offset,
+ MIN(remaining, vl), 0, NULL);
+ break;
+ default:
+ n = 0;
+ }
+ }
+
+ funced += n;
+ remaining -= n;
+ src1->_current_offset += n;
+ src2->_current_offset += n;
+ dest->_current_offset += n;
+ }
+ }
+
+ return funced;
+}
+
+/*
+ * remix_channel_copy (src, dest, count)
+ *
+ * Copies 'count' samples from 'src' to 'dest'.
+ * Stops early if 'dest' cannot contain part of 'src'. Copies zeroes to
+ * 'dest' wherever 'src' is correspondingly empty.
+ * Returns the count of samples actually copied.
+ */
+RemixCount
+remix_channel_copy (RemixEnv * env, RemixChannel * src, RemixChannel * dest, RemixCount count)
+{
+ return
+ remix_channel_chunkchunkfuncify (env, src, dest, count,
+ (RemixChunkChunkFunc)_remix_chunk_copy,
+ 0, NULL);
+}
+
+RemixCount
+remix_channel_mix (RemixEnv * env, RemixChannel * src, RemixChannel * dest, RemixCount count)
+{
+ return remix_channel_chunkchunkfuncify (env, src, dest, count,
+ (RemixChunkChunkFunc)_remix_chunk_add_inplace,
+ 0, NULL);
+}
+
+RemixCount
+remix_channel_interleave_2 (RemixEnv * env, RemixChannel * src1, RemixChannel * src2,
+ RemixPCM * dest, RemixCount count)
+{
+ return
+ remix_channel_chunkchunkfuncify (env, src1, src2, count,
+ (RemixChunkChunkFunc)_remix_chunk_interleave_2,
+ 0, dest);
+}
+
+RemixCount
+remix_channel_deinterleave_2 (RemixEnv * env, RemixChannel * dest1, RemixChannel * dest2,
+ RemixPCM * src, RemixCount count)
+{
+ return
+ remix_channel_chunkchunkfuncify (env, dest1, dest2, count,
+ (RemixChunkChunkFunc)_remix_chunk_deinterleave_2,
+ 0, src);
+}
+
+RemixCount
+_remix_channel_write (RemixEnv * env, RemixChannel * channel, RemixCount count,
+ RemixChannel * data)
+{
+ RemixCount n = remix_channel_copy (env, data, channel, count);
+ data->_current_offset += n;
+ data->_current_chunk =
+ remix_channel_get_chunk_item_after (data, data->_current_offset);
+ channel->_current_offset += n;
+ channel->_current_chunk =
+ remix_channel_get_chunk_item_after (channel, channel->_current_offset);
+ return n;
+}
+
+RemixCount
+_remix_channel_length (RemixEnv * env, RemixChannel * channel)
+{
+ RemixChunk * last = (RemixChunk *)
+ (cd_list_last (env, channel->chunks, CD_TYPE_POINTER)).s_pointer;
+ if (last == RemixNone) return 0;
+ return (last->start_index + last->length);
+}
+
+RemixCount
+_remix_channel_seek (RemixEnv * env, RemixChannel * channel, RemixCount offset)
+{
+ if (offset == channel->_current_offset) return offset;
+ channel->_current_offset = offset;
+ /* Cache the current chunk */
+ channel->_current_chunk =
+ remix_channel_get_chunk_item_after (channel, offset);
+ return offset;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * remix_channelset: default channel sets.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+CDSet * REMIX_MONO = RemixNone;
+CDSet * REMIX_STEREO = RemixNone;
+
+void
+remix_channelset_defaults_initialise (RemixEnv * env)
+{
+ if (REMIX_MONO == NULL) {
+ REMIX_MONO = cd_set_new (env);
+ REMIX_MONO = cd_set_insert (env, REMIX_MONO, REMIX_CHANNEL_LEFT,
+ CD_POINTER(NULL));
+ }
+
+ if (REMIX_STEREO == NULL) {
+ REMIX_STEREO = cd_set_new (env);
+ REMIX_STEREO = cd_set_insert (env, REMIX_STEREO, REMIX_CHANNEL_LEFT,
+ CD_POINTER(NULL));
+ REMIX_STEREO = cd_set_insert (env, REMIX_STEREO, REMIX_CHANNEL_RIGHT,
+ CD_POINTER(NULL));
+ }
+
+ return;
+}
+
+void
+remix_channelset_defaults_destroy (RemixEnv * env)
+{
+ if (REMIX_MONO != NULL) {
+ cd_set_free (env, REMIX_MONO);
+ REMIX_MONO = NULL;
+ }
+
+ if (REMIX_STEREO != NULL) {
+ cd_set_free (env, REMIX_STEREO);
+ REMIX_STEREO = NULL;
+ }
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixChunk: A contiguous chunk of monophonic PCM data.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A chunk contains raw PCM data.
+ *
+ * Invariants
+ * ----------
+ *
+ * A chunk must always be contained within a channel. The data within
+ * a chunk is only valid where it is not overlapped by a later chunk
+ * in the same channel; elsewhere, the chunk's data is not used.
+ *
+ */
+
+#include <string.h>
+
+#define __REMIX__
+#include "remix.h"
+
+typedef RemixCount
+ (*RemixPFunc) (RemixPCM * src, RemixCount count, void * data);
+
+typedef RemixCount
+ (*RemixPPFunc) (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * data);
+typedef RemixCount
+ (*RemixPPPFunc) (RemixPCM * src1, RemixPCM * src2, RemixPCM * dest,
+ RemixCount count, void * data);
+
+
+RemixChunk *
+remix_chunk_new (RemixEnv * env, RemixCount start_index, RemixCount length)
+{
+ RemixChunk * u;
+
+ u = (RemixChunk *) remix_malloc (sizeof (struct _RemixChunk));
+ u->start_index = start_index;
+ u->length = length;
+
+ u->data = (RemixPCM *) remix_malloc (length * sizeof (RemixPCM));
+
+ return u;
+}
+
+RemixChunk *
+remix_chunk_new_from_buffer (RemixEnv * env, RemixCount start_index,
+ RemixCount length, RemixPCM * buffer)
+{
+ RemixChunk * u;
+
+ u = (RemixChunk *) remix_malloc (sizeof (struct _RemixChunk));
+ u->start_index = start_index;
+ u->length = length;
+
+ u->data = buffer;
+
+ return u;
+}
+
+RemixChunk *
+remix_chunk_clone (RemixEnv * env, RemixChunk * chunk)
+{
+ RemixChunk * u = remix_chunk_new (env, chunk->start_index, chunk->length);
+ memcpy (u->data, chunk->data, (chunk->length * sizeof (RemixPCM)));
+ return u;
+}
+
+void
+remix_chunk_free (RemixEnv * env, RemixChunk * chunk)
+{
+ remix_free (chunk->data);
+ remix_free (chunk);
+}
+
+int
+remix_chunk_later (RemixEnv * env, RemixChunk * u1, RemixChunk * u2)
+{
+ return (u1->start_index > u2->start_index);
+}
+
+RemixCount
+remix_chunk_clear (RemixEnv * env, RemixChunk * chunk)
+{
+ RemixCount len = chunk->length;
+ memset (chunk->data, (RemixPCM)0, len * sizeof (RemixPCM));
+ return len;
+}
+
+
+/*
+ * FUNCTION APPLIERS
+ */
+
+static RemixCount
+_remix_pfunc_apply (RemixEnv * env, RemixPFunc func, RemixChunk * chunk,
+ RemixCount start, RemixCount count, void * data)
+{
+ RemixCount chunk_start = start - chunk->start_index;
+
+ /* chunk_start: 'start' relative to chunk */
+ if (chunk_start < 0) {
+ count += chunk_start;
+ chunk_start = 0;
+ }
+
+ if (chunk_start + count > chunk->length) {
+ count = chunk->length - chunk_start;
+ }
+
+ func (&chunk->data[chunk_start], count, data);
+
+ return (count);
+}
+
+/*
+ * _remix_ppfunc_apply (env, func, src, src_offset, dest, dest_offset, count,
+ * data)
+ *
+ * Apply RemixPCMPCMFunc 'func' to 'count' samples of chunks 'src' and 'dest'.
+ */
+static RemixCount
+_remix_ppfunc_apply (RemixEnv * env, RemixPPFunc func,
+ RemixChunk * src, RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, void * data)
+{
+ RemixCount dest_start = dest_offset - dest->start_index;
+ RemixCount src_start;
+ RemixPCM *s, *d;
+
+ if (dest_start < 0) {
+ count += dest_start;
+ dest_offset -= dest_start;
+ src_offset -= dest_start;
+ dest_start = 0;
+ }
+
+ src_start = src_offset - src->start_index;
+
+ /* Shorten count if either chunk is shorter than required */
+ if (src_start + count > src->length)
+ count = src->length - src_start;
+
+ if (dest_start + count > dest->length)
+ count = dest->length - dest_start;
+
+ s = &src->data[src_start];
+ d = &dest->data[dest_start];
+
+ func (s, d, count, data);
+
+ return count;
+}
+
+/*
+ * _remix_pppfunc_apply (env, func, src, src_offset, dest, dest_offset, count,
+ * data)
+ *
+ * Apply RemixPPPFunc 'func' to 'count' samples of chunks 'src1', 'src2'
+ * and 'dest'.
+ */
+static RemixCount
+_remix_pppfunc_apply (RemixEnv * env, RemixPPPFunc func,
+ RemixChunk * src1, RemixCount src1_offset,
+ RemixChunk * src2, RemixCount src2_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, void * data)
+{
+ RemixCount dest_start = dest_offset - dest->start_index;
+ RemixCount src1_start, src2_start;
+ RemixPCM *s1, *s2, *d;
+
+ if (dest_start < 0) {
+ count += dest_start;
+ dest_offset -= dest_start;
+ src1_offset -= dest_start;
+ src2_offset -= dest_start;
+ dest_start = 0;
+ }
+
+ src1_start = src1_offset - src1->start_index;
+ src2_start = src2_offset - src2->start_index;
+
+ /* Shorten count if any chunk is shorter than required */
+ if (src1_start + count > src1->length)
+ count = src1->length - src1_start;
+
+ if (src2_start + count > src2->length)
+ count = src2->length - src2_start;
+
+ if (dest_start + count > dest->length)
+ count = dest->length - dest_start;
+
+ s1 = &src1->data[src1_start];
+ s2 = &src2->data[src2_start];
+ d = &dest->data[dest_start];
+
+ func (s1, s2, d, count, data);
+
+ return count;
+}
+
+/* PFunc appliers */
+
+/*
+ * _remix_chunk_clear_region (chunk, start, length, unused)
+ *
+ * Clear 'chunk' from stream index 'start' for 'length' samples.
+ * Returns the count of samples actually cleared.
+ */
+RemixCount
+_remix_chunk_clear_region (RemixEnv * env, RemixChunk * chunk,
+ RemixCount start, RemixCount length,
+ int channelname, void * unused)
+{
+ return _remix_pfunc_apply (env,_remix_pcm_clear_region,
+ chunk, start, length, NULL);
+}
+
+/*
+ * _remix_chunk_gain (chunk, start, length, gain)
+ *
+ * Multiply by gain all samples in 'chunk' from stream index 'start' for
+ * 'length' samples.
+ * Returns the count of samples modified.
+ */
+RemixCount
+_remix_chunk_gain (RemixEnv * env, RemixChunk * chunk,
+ RemixCount start, RemixCount count,
+ int channelname, /* (RemixPCM *) */ void * gain)
+{
+ return _remix_pfunc_apply (env, _remix_pcm_gain, chunk, start, count, gain);
+}
+
+
+/* PPFunc appliers */
+
+/*
+ * _remix_chunk_copy (env, src+offset, dest+offset, count, channelname)
+ *
+ * Copy data from 'src' to 'dest' from stream index 'offset' for
+ * 'count'. Returns the count of samples actually copied.
+ */
+RemixCount
+_remix_chunk_copy (RemixEnv * env, RemixChunk * src, RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset, RemixCount count,
+ int channelname, void * unused)
+{
+ return _remix_ppfunc_apply (env, _remix_pcm_copy, src, src_offset,
+ dest, dest_offset, count, NULL);
+}
+
+/*
+ * _remix_chunk_add_inplace (env, src+offset, dest+offset, count, channelname)
+ *
+ * Add data from 'src' to data in 'dest' from stream index 'start' for
+ * 'count' samples. Returns the count of samples actually added.
+ */
+RemixCount
+_remix_chunk_add_inplace (RemixEnv * env,
+ RemixChunk * src, RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname, void * unused)
+{
+ return _remix_ppfunc_apply (env, _remix_pcm_add, src, src_offset,
+ dest, dest_offset, count, NULL);
+}
+
+/*
+ * _remix_chunk_mult_inplace (src, dest, start, count, unused)
+ *
+ * Multiply data of 'dest' by that of 'src' from stream index 'start' for
+ * 'count' samples. Returns the count of samples actually multiplied.
+ */
+RemixCount
+_remix_chunk_mult_inplace (RemixEnv * env,
+ RemixChunk * src, RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname, void * unused)
+{
+ return _remix_ppfunc_apply (env, _remix_pcm_mult, src, src_offset,
+ dest, dest_offset, count, NULL);
+}
+
+/*
+ * _remix_chunk_fade_inplace (src, src_offset, dest, dest_offset, count, unused)
+ *
+ * Fade data of 'dest' by that of 'src' from stream index 'start' for
+ * 'count' samples. Returns the count of samples actually faded.
+ */
+RemixCount
+_remix_chunk_fade_inplace (RemixEnv * env,
+ RemixChunk * src, RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname, void * unused)
+{
+ return _remix_ppfunc_apply (env, _remix_pcm_fade, src, src_offset,
+ dest, dest_offset, count, NULL);
+}
+
+/*
+ * _remix_chunk_interleave_2 (env, src1+offset, src2+offset, count, dest)
+ *
+ * Interleave data of 'src1' from stream index 'src1_offset' with that
+ * of 'src2' from stream index 'src2_offset' for 'count' samples, storing
+ * the resulting interleaved PCM data in 'dest'.
+ *
+ * Returns the count of sample frames interleaved.
+ */
+RemixCount
+_remix_chunk_interleave_2 (RemixEnv * env,
+ RemixChunk * src1, RemixCount src1_offset,
+ RemixChunk * src2, RemixCount src2_offset,
+ RemixCount count, int unused, void * dest)
+{
+ return _remix_ppfunc_apply (env, _remix_pcm_interleave_2, src1, src1_offset,
+ src2, src2_offset, count, dest);
+}
+
+/*
+ * _remix_chunk_deinterleave_2 (env, dest1+offset, dest2+offset, count, src)
+ *
+ * Deinterleave data of 'src' and store the result in streams 'dest1' (from
+ * stream index 'dest1_offset') and 'dest2' (from stream index
+ * 'dest2_offset').
+ *
+ * Returns the number of sample frames deinterleaved.
+ */
+RemixCount
+_remix_chunk_deinterleave_2 (RemixEnv * env,
+ RemixChunk * dest1, RemixCount dest1_offset,
+ RemixChunk * dest2, RemixCount dest2_offset,
+ RemixCount count, int unused, void * src)
+{
+ return _remix_ppfunc_apply (env, _remix_pcm_deinterleave_2,
+ dest1, dest1_offset, dest2, dest2_offset,
+ count, src);
+}
+
+/* PPPFunc appliers */
+
+/*
+ * _remix_chunk_blend_inplace (env, src+offset, blend+offset,
+ * dest+offset, count, unused)
+ *
+ * Blend data of 'src' into that of 'dest' by blend values given in
+ * 'blend'.
+ */
+RemixCount
+_remix_chunk_blend_inplace (RemixEnv * env,
+ RemixChunk * src, RemixCount src_offset,
+ RemixChunk * blend, RemixCount blend_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname, void * unused)
+{
+ return _remix_pppfunc_apply (env, _remix_pcm_blend, src, src_offset,
+ blend, blend_offset, dest, dest_offset,
+ count, NULL);
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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 "config.h"
+
+#ifndef WIN32
+# define remix_stat_regular(mode) (S_ISREG((mode)) || S_ISLNK((mode)))
+#else
+# define remix_stat_regular(mode) ((mode) & S_IFREG)
+#endif
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixContext: REMIX core context.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#include <string.h>
+
+#define __REMIX__
+#include "remix.h"
+
+static void
+remix_plugin_destroy (RemixEnv * env, RemixPlugin * plugin)
+{
+ if (plugin->destroy) {
+ plugin->destroy (env, plugin);
+ }
+}
+
+static void
+remix_context_destroy (RemixEnv * env)
+{
+ RemixContext * ctx = env->context;
+ RemixWorld * world = env->world;
+
+ world->purging = 1;
+
+ world->plugins = cd_list_destroy_with (env, world->plugins, remix_plugin_destroy);
+ remix_plugin_defaults_unload (env);
+//need to analyse why its commented in svn version ???
+ //world->bases = cd_list_destroy_with (env, world->bases, remix_destroy);
+
+ remix_channelset_defaults_destroy (env);
+ remix_free (ctx);
+ remix_free (world);
+}
+
+static RemixEnv *
+remix_add_thread_context (RemixContext * ctx, RemixWorld * world)
+{
+ RemixEnv * env = remix_malloc (sizeof (struct _RemixThreadContext));
+ env->context = ctx;
+ env->world = world;
+ world->refcount++;
+ return env;
+}
+
+RemixContext *
+_remix_context_copy (RemixEnv * env, RemixContext * dest)
+{
+ RemixContext * ctx = env->context;
+
+ if (dest == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ dest->samplerate = ctx->samplerate;
+ dest->tempo = ctx->tempo;
+ dest->mixlength = ctx->mixlength;
+ dest->channels = cd_set_clone_keys (env, ctx->channels);
+
+ return dest;
+}
+
+/*
+ * _remix_context_merge (env, dest)
+ *
+ * Merges the context of env into context 'dest'. Copies over the samplerate
+ * and tempo, and expands the mixlength and channels if they are greater in
+ * 'env's context than in 'dest'.
+ */
+RemixContext *
+_remix_context_merge (RemixEnv * env, RemixContext * dest)
+{
+ RemixContext * ctx = env->context;
+ CDSet * s;
+ CDScalar k;
+
+ if (dest == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ dest->samplerate = ctx->samplerate;
+ dest->tempo = ctx->tempo;
+
+ if (ctx->mixlength > dest->mixlength)
+ dest->mixlength = ctx->mixlength;
+
+ for (s = ctx->channels; s; s = s->next) {
+ k = cd_set_find (env, dest->channels, s->key);
+ if (k.s_pointer == NULL)
+ dest->channels = cd_set_insert (env, dest->channels, s->key,
+ CD_POINTER(NULL));
+ }
+
+ return dest;
+}
+
+/*
+ * remix_init ()
+ */
+RemixEnv *
+remix_init (void)
+{
+ RemixEnv * env;
+ RemixWorld * world =
+ (RemixWorld *) remix_malloc (sizeof (struct _RemixWorld));
+ RemixContext * ctx =
+ (RemixContext *) remix_malloc (sizeof (struct _RemixContext));
+
+ world->refcount = 0;
+ world->plugins = cd_list_new (ctx);
+ world->bases = cd_list_new (ctx);
+ world->purging = FALSE;
+
+ ctx->mixlength = REMIX_DEFAULT_MIXLENGTH;
+ ctx->samplerate = REMIX_DEFAULT_SAMPLERATE;
+ ctx->tempo = REMIX_DEFAULT_TEMPO;
+
+ env = remix_add_thread_context (ctx, world);
+ remix_channelset_defaults_initialise (env);
+ ctx->channels = REMIX_MONO;
+
+ remix_plugin_defaults_initialise (env);
+
+ return env;
+}
+
+/*
+ * remix_init_clone ()
+ */
+RemixEnv *
+remix_init_clone (RemixEnv * env)
+{
+ RemixEnv * new_env = remix_add_thread_context (env->context, env->world);
+ return new_env;
+}
+
+void
+remix_purge (RemixEnv * env)
+{
+ RemixWorld * world = env->world;
+ world->refcount--;
+ if (world->refcount <= 0) {
+ remix_context_destroy (env);
+ }
+ remix_free (env);
+}
+
+RemixError
+remix_set_error (RemixEnv * env, RemixError error)
+{
+ RemixError old = env->last_error;
+ env->last_error = error;
+ return old;
+}
+
+RemixError
+remix_last_error (RemixEnv * env)
+{
+ return env->last_error;
+}
+
+RemixCount
+remix_set_mixlength (RemixEnv * env, RemixCount mixlength)
+{
+ RemixContext * ctx = env->context;
+ RemixCount old = ctx->mixlength;
+ ctx->mixlength = mixlength;
+ return old;
+}
+
+RemixCount
+remix_get_mixlength (RemixEnv * env)
+{
+ RemixContext * ctx = env->context;
+ return ctx->mixlength;
+}
+
+RemixSamplerate
+remix_set_samplerate (RemixEnv * env, RemixSamplerate samplerate)
+{
+ RemixContext * ctx = env->context;
+ RemixSamplerate old = ctx->samplerate;
+ ctx->samplerate = samplerate;
+ return old;
+}
+
+RemixSamplerate
+remix_get_samplerate (RemixEnv * env)
+{
+ RemixContext * ctx = env->context;
+ return ctx->samplerate;
+}
+
+RemixTempo
+remix_set_tempo (RemixEnv * env, RemixTempo tempo)
+{
+ RemixContext * ctx = env->context;
+ RemixTempo old = ctx->tempo;
+ ctx->tempo = tempo;
+ return old;
+}
+
+RemixTempo
+remix_get_tempo (RemixEnv * env)
+{
+ RemixContext * ctx = env->context;
+ return ctx->tempo;
+}
+
+CDSet *
+remix_set_channels (RemixEnv * env, CDSet * channels)
+{
+ RemixContext * ctx = env->context;
+ CDSet * old = ctx->channels;
+ ctx->channels = cd_set_clone_keys (env, channels);
+ return old;
+}
+
+CDSet *
+remix_get_channels (RemixEnv * env)
+{
+ RemixContext * ctx = env->context;
+ return ctx->channels;
+}
+
+RemixEnv *
+_remix_register_plugin (RemixEnv * env, RemixPlugin * plugin)
+{
+ RemixWorld * world = env->world;
+ remix_dprintf ("[_remix_register_plugin] REGISTERING %s\n",
+ plugin->metatext ? plugin->metatext->identifier : "(\?\?\?)");
+ world->plugins = cd_list_append (env, world->plugins, CD_POINTER(plugin));
+ return env;
+}
+
+RemixEnv *
+_remix_unregister_plugin (RemixEnv * env, RemixPlugin * plugin)
+{
+ RemixWorld * world = env->world;
+ if (world->purging) return env;
+
+ world->plugins = cd_list_remove (env, world->plugins, CD_TYPE_POINTER,
+ CD_POINTER(plugin));
+ return env;
+}
+
+RemixEnv *
+_remix_register_base (RemixEnv * env, RemixBase * base)
+{
+ RemixWorld * world = env->world;
+ world->bases = cd_list_append (env, world->bases, CD_POINTER(base));
+ return env;
+}
+
+RemixEnv *
+_remix_unregister_base (RemixEnv * env, RemixBase * base)
+{
+ RemixWorld * world = env->world;
+ if (world->purging) return env;
+
+ world->bases = cd_list_remove (env, world->bases, CD_TYPE_POINTER,
+ CD_POINTER(base));
+ return env;
+}
+
+static int
+plugin_id_eq (RemixEnv * env, RemixPlugin * plugin, char * identifier)
+{
+ if (plugin == RemixNone) return FALSE;
+ if (plugin->metatext == RemixNone) return FALSE;
+ return !(strcmp(plugin->metatext->identifier, identifier));
+}
+
+RemixPlugin *
+remix_find_plugin (RemixEnv * env, char * identifier)
+{
+ RemixWorld * world = env->world;
+ CDList * l = cd_list_find_first (env, world->plugins, CD_TYPE_POINTER,
+ (CDCmpFunc)plugin_id_eq,
+ CD_POINTER(identifier));
+
+ if (l == RemixNone) return RemixNone;
+ return (RemixPlugin *)l->data.s_pointer;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * remix_debug.c -- Debuggin routines for Remix
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * This file contains printing routines for formatted debugging.
+ *
+ */
+
+#include <string.h>
+#include <stdarg.h>
+
+#define __REMIX__
+#include "remix.h"
+
+static int indent = 0;
+
+/*
+ * remix_debug_down (void)
+ */
+void
+remix_debug_down (void)
+{
+ indent ++;
+}
+
+/*
+ * remix_debug_up (void)
+ */
+void
+remix_debug_up (void)
+{
+ indent --;
+}
+
+/*
+ * remix_dprintf (fmt)
+ *
+ * Print a formatted debugging message to stdout at the current indent
+ */
+void
+remix_dprintf (const char * fmt, ...)
+{
+#if 0
+ va_list ap;
+ char buf[4096];
+ int i, n;
+
+ va_start (ap, fmt);
+
+ n = MIN (4096, indent);
+
+ for (i = 0; i < n; i++) {
+ buf[i] = ' ';
+ }
+
+ vsnprintf (buf+n, 4096-n, fmt, ap);
+
+ fputs (buf, stdout);
+ fflush (NULL);
+
+ va_end (ap);
+#endif
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixDeck: A high level audio mixing abstraction.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A deck contains a number of tracks which are mixed in parallel.
+ *
+ * Invariants
+ * ----------
+ *
+ * Decks are independent entities. The creation of a new deck does not
+ * depend on the existence of any other bases. Any tracks (and, by
+ * extension, layers and sounds) added to a deck become part of that
+ * deck and are destroyed when the deck is destroyed.
+ *
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+/* Optimisation dependencies: optimise on change of nr. tracks */
+static RemixDeck * remix_deck_optimise (RemixEnv * env, RemixDeck * deck);
+
+static RemixDeck *
+remix_deck_replace_mixstream (RemixEnv * env, RemixDeck * deck)
+{
+ RemixCount mixlength = _remix_base_get_mixlength (env, deck);
+
+ if (deck->_mixstream != RemixNone)
+ remix_destroy (env, (RemixBase *)deck->_mixstream);
+
+ deck->_mixstream = remix_stream_new_contiguous (env, mixlength);
+
+ return deck;
+}
+
+RemixBase *
+remix_deck_init (RemixEnv * env, RemixBase * base)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ deck->tracks = cd_list_new (env);
+ deck->_mixstream = RemixNone;
+ remix_deck_replace_mixstream (env, deck);
+ remix_deck_optimise (env, deck);
+ return (RemixBase *)deck;
+}
+
+RemixDeck *
+remix_deck_new (RemixEnv * env)
+{
+ RemixDeck * deck =
+ (RemixDeck *) remix_base_new_subclass (env, sizeof (struct _RemixDeck));
+ return (RemixDeck *)remix_deck_init (env, (RemixBase *)deck);
+}
+
+RemixBase *
+remix_deck_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ RemixDeck * new_deck = remix_deck_new (env);
+ new_deck->tracks = cd_list_clone (env, deck->tracks,
+ (CDCloneFunc)remix_track_clone);
+ return (RemixBase *)new_deck;
+}
+
+static int
+remix_deck_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ remix_destroy_list (env, deck->tracks);
+ remix_destroy (env, (RemixBase *)deck->_mixstream);
+ remix_free (deck);
+ return 0;
+}
+
+static int
+remix_deck_ready (RemixEnv * env, RemixBase * base)
+{
+ return (remix_base_encompasses_mixlength (env, base) &&
+ remix_base_encompasses_channels (env, base));
+}
+
+static RemixBase *
+remix_deck_prepare (RemixEnv * env, RemixBase * base)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ remix_deck_replace_mixstream (env, deck);
+ return base;
+}
+
+RemixTrack *
+_remix_deck_add_track (RemixEnv * env, RemixDeck * deck, RemixTrack * track)
+{
+ deck->tracks = cd_list_prepend (env, deck->tracks, CD_POINTER(track));
+ remix_deck_optimise (env, deck);
+ return track;
+}
+
+RemixTrack *
+_remix_deck_remove_track (RemixEnv * env, RemixDeck * deck, RemixTrack * track)
+{
+ deck->tracks = cd_list_remove (env, deck->tracks, CD_TYPE_POINTER,
+ CD_POINTER(track));
+ remix_deck_optimise (env, deck);
+ return track;
+}
+
+int
+remix_deck_nr_tracks (RemixEnv * env, RemixDeck * deck)
+{
+ return cd_list_length (env, deck->tracks);
+}
+
+static RemixCount
+remix_deck_length (RemixEnv * env, RemixBase * base)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ RemixCount length, maxlength = 0;
+ CDList * l;
+ RemixBase * track;
+
+ for (l = deck->tracks; l; l = l->next) {
+ track = (RemixBase *)l->data.s_pointer;
+ length = remix_length (env, track);
+ remix_dprintf ("[remix_deck_length] found track %p length %ld\n",
+ track, length);
+ maxlength = MAX (maxlength, length);
+ }
+
+ return maxlength;
+}
+
+CDList *
+remix_deck_get_tracks (RemixEnv * env, RemixDeck * deck)
+{
+ return cd_list_copy (env, deck->tracks);
+}
+
+#if 0
+static RemixCount
+remix_deck_process (RemixEnv * env, RemixBase base, RemixCount count, RemixStream input,
+ RemixStream output)
+{
+ RemixDeck deck = (RemixDeck)base;
+ CDList tl, ml;
+ RemixTrack track;
+ RemixStream mixstream;
+ RemixCount processed = 0, remaining = count, n, minn;
+ RemixCount input_offset;
+
+ remix_dprintf ("PROCESS DECK (%p, +%ld, %p -> %p) @ %ld\n",
+ deck, count, input, output, remix_tell (env, base));
+
+ while (remaining > 0) {
+ /* Get mixlength from each track */
+ minn = deck->mixlength;
+ input_offset = remix_tell (env, (RemixBase)input);
+ for (tl = deck->tracks, ml = deck->mixstreams; tl && ml;
+ tl = tl->next, ml = ml->next) {
+ track = (RemixTrack)tl->data;
+ mixstream = (RemixStream)ml->data;
+ remix_seek (env, (RemixBase)input, input_offset);
+ n = remix_process (env, (RemixBase)track, MIN (remaining, deck->mixlength),
+ input, mixstream);
+ minn = MIN (minn, n);
+ }
+
+
+ if (output != RemixNone) {
+ /* mix tracks together to the output */
+ n = remix_streams_mix (env, deck->mixstreams, output, minn);
+ } else {
+ /* don't need to create output */
+ n = minn;
+ }
+
+ processed += n;
+ remaining -= n;
+ }
+
+ remix_dprintf ("[remix_deck_process] processed %ld\n", processed);
+
+ return processed;
+}
+#endif
+
+static RemixCount
+remix_deck_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ CDList * l;
+ RemixTrack * track;
+ RemixCount remaining = count, processed = 0, n;
+ RemixCount current_offset = remix_tell (env, base);
+ RemixCount input_offset = remix_tell (env, (RemixBase *)input);
+ RemixCount output_offset = remix_tell (env, (RemixBase *)output);
+ RemixCount mixlength = _remix_base_get_mixlength (env, deck);
+ RemixStream * mixstream = deck->_mixstream;
+
+ remix_dprintf ("PROCESS DECK (%p, +%ld, %p -> %p) @ %ld\n",
+ deck, count, input, output, current_offset);
+
+ while (remaining > 0) {
+
+ l = deck->tracks;
+ track = (RemixTrack *)l->data.s_pointer;
+
+ n = MIN (remaining, mixlength);
+
+ n = remix_process (env, (RemixBase *)track, n, input, output);
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = remix_stream_gain (env, output, n, track->gain);
+
+ for (l = l->next; l; l = l->next) {
+ track = (RemixTrack *)l->data.s_pointer;
+
+ remix_seek (env, (RemixBase *)input, input_offset, SEEK_SET);
+ remix_seek (env, (RemixBase *)mixstream, 0, SEEK_SET);
+ n = remix_process (env, (RemixBase *)track, n, input, mixstream);
+
+ remix_seek (env, (RemixBase *)mixstream, 0, SEEK_SET);
+ n = remix_stream_gain (env, mixstream, n, track->gain);
+
+ remix_seek (env, (RemixBase *)mixstream, 0, SEEK_SET);
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = remix_stream_mix (env, mixstream, output, n);
+ }
+
+ processed += n;
+ remaining -= n;
+ }
+
+ remix_dprintf ("[remix_deck_process] processed %ld\n", processed);
+
+ return processed;
+}
+
+static RemixCount
+remix_deck_twotrack_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ CDList * l;
+ RemixTrack * track1, * track2;
+ RemixCount n;
+ RemixCount current_offset = remix_tell (env, base);
+ RemixCount input_offset = remix_tell (env, (RemixBase *)input);
+ RemixCount output_offset = remix_tell (env, (RemixBase *)output);
+ RemixStream * mixstream = deck->_mixstream;
+
+ remix_dprintf ("PROCESS DECK [twotrack] (%p, +%ld, %p -> %p) @ %ld\n",
+ deck, count, input, output, current_offset);
+
+ l = deck->tracks;
+ track1 = (RemixTrack *)l->data.s_pointer;
+
+ l = l->next;
+ track2 = (RemixTrack *)l->data.s_pointer;
+
+ n = remix_process (env, (RemixBase *)track1, count, input, output);
+
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = remix_stream_gain (env, output, n, track1->gain);
+
+ remix_seek (env, (RemixBase *)input, input_offset, SEEK_SET);
+ remix_seek (env, (RemixBase *)mixstream, 0, SEEK_SET);
+ n = remix_process (env, (RemixBase *)track2, n, input, mixstream);
+
+ remix_seek (env, (RemixBase *)mixstream, 0, SEEK_SET);
+ n = remix_stream_gain (env, mixstream, n, track2->gain);
+
+ remix_seek (env, (RemixBase *)mixstream, 0, SEEK_SET);
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = remix_stream_mix (env, mixstream, output, n);
+
+ remix_dprintf ("[remix_deck_twotrack_process] processed %ld\n", n);
+
+ return n;
+}
+
+static RemixCount
+remix_deck_onetrack_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ RemixTrack * track = (RemixTrack *)deck->tracks->data.s_pointer;
+ RemixCount n;
+
+ remix_dprintf ("PROCESS DECK [onetrack] (%p, +%ld, %p -> %p) @ %ld\n",
+ deck, count, input, output, remix_tell (env, base));
+
+ n = remix_process (env, (RemixBase *)track, count, input, output);
+
+ remix_dprintf ("*** deck @ %ld\ttrack @ %ld\n", remix_tell (env, base),
+ remix_tell (env, (RemixBase *)track));
+
+ remix_dprintf ("[remix_deck_onetrack_process] processed %ld\n", n);
+
+ return n;
+}
+
+static RemixCount
+remix_deck_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ CDList * l;
+ RemixTrack * track;
+
+ for (l = deck->tracks; l; l = l->next) {
+ track = (RemixTrack *)l->data.s_pointer;
+ remix_seek (env, (RemixBase *)track, offset, SEEK_SET);
+ }
+
+ return offset;
+}
+
+static int
+remix_deck_flush (RemixEnv * env, RemixBase * base)
+{
+ RemixDeck * deck = (RemixDeck *)base;
+ CDList * l;
+ RemixTrack * track;
+
+ for (l = deck->tracks; l; l = l->next) {
+ track = (RemixTrack *)l->data.s_pointer;
+ remix_flush (env, (RemixBase *)track);
+ }
+
+ return 0;
+}
+
+static struct _RemixMethods _remix_deck_empty_methods = {
+ remix_deck_clone, /* clone */
+ remix_deck_destroy, /* destroy */
+ remix_deck_ready, /* ready */
+ remix_deck_prepare, /* preapre */
+ remix_null_process, /* process */
+ remix_null_length, /* length */
+ NULL, /* seek */
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_deck_methods = {
+ remix_deck_clone, /* clone */
+ remix_deck_destroy, /* destroy */
+ remix_deck_ready, /* ready */
+ remix_deck_prepare, /* preapre */
+ remix_deck_process, /* process */
+ remix_deck_length, /* length */
+ remix_deck_seek, /* seek */
+ remix_deck_flush, /* flush */
+};
+
+static struct _RemixMethods _remix_deck_onetrack_methods = {
+ remix_deck_clone, /* clone */
+ remix_deck_destroy, /* destroy */
+ remix_deck_ready, /* ready */
+ remix_deck_prepare, /* preapre */
+ remix_deck_onetrack_process, /* process */
+ remix_deck_length, /* length */
+ remix_deck_seek, /* seek */
+ remix_deck_flush, /* flush */
+};
+
+static struct _RemixMethods _remix_deck_twotrack_methods = {
+ remix_deck_clone, /* clone */
+ remix_deck_destroy, /* destroy */
+ remix_deck_ready, /* ready */
+ remix_deck_prepare, /* preapre */
+ remix_deck_twotrack_process, /* process */
+ remix_deck_length, /* length */
+ remix_deck_seek, /* seek */
+ remix_deck_flush, /* flush */
+};
+
+static RemixDeck *
+remix_deck_optimise (RemixEnv * env, RemixDeck * deck)
+{
+ int nr_tracks = cd_list_length (env, deck->tracks);
+
+ switch (nr_tracks) {
+ case 0: _remix_set_methods (env, deck, &_remix_deck_empty_methods); break;
+ case 1: _remix_set_methods (env, deck, &_remix_deck_onetrack_methods); break;
+ case 2: _remix_set_methods (env, deck, &_remix_deck_twotrack_methods); break;
+ default: _remix_set_methods (env, deck, &_remix_deck_methods); break;
+ }
+
+ return deck;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixEnvelope: Generic mathy envelopes for env.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+/* Optimisation dependencies: optimise when adding and removing points
+ * or changing envelope type */
+static RemixEnvelope *
+remix_envelope_optimise (RemixEnv * env, RemixEnvelope * envelope);
+
+static void
+remix_envelope_debug (RemixEnv * env, RemixEnvelope * envelope)
+{
+#ifdef DEBUG
+ CDList * l;
+ RemixPoint * point;
+
+ printf ("envelope %p\n", envelope);
+ printf ("envelope->points: %p\n", envelope->points);
+
+ /* printf (" has %d points\n", cd_list_length (env, envelope->points));*/
+ for (l = envelope->points; l; l = l->next) {
+ point = (RemixPoint *)l->data.s_pointer;
+ switch (envelope->timetype) {
+ case REMIX_TIME_SAMPLES:
+ printf ("%ld samples, %f\n", point->time.samples, point->value);
+ break;
+ case REMIX_TIME_SECONDS:
+ printf ("%f seconds, %f\n", point->time.seconds, point->value);
+ break;
+ case REMIX_TIME_BEAT24S:
+ printf ("%d beat24s, %f\n", point->time.beat24s, point->value);
+ break;
+ default:
+ printf ("*** unknown envelope->timetype ***\n");
+ break;
+ }
+ }
+#endif
+}
+
+static RemixPoint *
+remix_point_new (RemixTime time, RemixPCM value)
+{
+ RemixPoint * point = remix_malloc (sizeof (struct _RemixPoint));
+ point->time = time;
+ point->value = value;
+ return point;
+}
+
+static RemixPoint *
+remix_point_clone (RemixEnv * env, RemixPoint * point)
+{
+ return remix_point_new (point->time, point->value);
+}
+
+static int
+remix_point_later_X (RemixEnv * env, RemixPoint * p1, RemixPoint * p2)
+{
+ return _remix_time_gt(REMIX_TIME_SAMPLES, p1->time, p2->time);
+}
+
+static int
+remix_point_later_S (RemixEnv * env, RemixPoint * p1, RemixPoint * p2)
+{
+ return _remix_time_gt(REMIX_TIME_SECONDS, p1->time, p2->time);
+}
+
+static int
+remix_point_later_B (RemixEnv * env, RemixPoint * p1, RemixPoint * p2)
+{
+ return _remix_time_gt(REMIX_TIME_BEAT24S, p1->time, p2->time);
+}
+
+RemixBase *
+remix_envelope_init (RemixEnv * env, RemixBase * base)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ envelope->type = REMIX_ENVELOPE_LINEAR;
+ envelope->points = cd_list_new (env);
+ remix_envelope_optimise (env, envelope);
+ return (RemixBase *)envelope;
+}
+
+RemixEnvelope *
+remix_envelope_new (RemixEnv * env, RemixEnvelopeType type)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)
+ remix_base_new_subclass (env, sizeof (struct _RemixEnvelope));
+ remix_envelope_init (env, (RemixBase *)envelope);
+ envelope->type = type;
+ remix_envelope_debug (env, envelope);
+
+ return envelope;
+}
+
+RemixBase *
+remix_envelope_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ RemixEnvelope * new_envelope = remix_envelope_new (env, envelope->type);
+ new_envelope->points = cd_list_clone (env, envelope->points,
+ (CDCloneFunc)remix_point_clone);
+ remix_envelope_optimise (env, new_envelope);
+ return (RemixBase *)new_envelope;
+}
+
+static int
+remix_envelope_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ cd_list_free_all (env, envelope->points);
+ remix_free (envelope);
+ return 0;
+}
+
+RemixEnvelopeType
+remix_envelope_set_type (RemixEnv * env, RemixEnvelope * envelope, RemixEnvelopeType type)
+{
+ RemixEnvelopeType old = envelope->type;
+ envelope->type = type;
+ remix_envelope_optimise (env, envelope);
+ return old;
+}
+
+RemixEnvelopeType
+remix_envelope_get_type (RemixEnv * env, RemixEnvelope * envelope)
+{
+ return envelope->type;
+}
+
+RemixTimeType
+remix_envelope_set_timetype (RemixEnv * env, RemixEnvelope * envelope,
+ RemixTimeType timetype)
+{
+ RemixTimeType old = envelope->timetype;
+ envelope->timetype = timetype;
+ return old;
+}
+
+RemixTimeType
+remix_envelope_get_timetype (RemixEnv * env, RemixEnvelope * envelope)
+{
+ return envelope->timetype;
+}
+
+RemixTime
+remix_envelope_get_duration (RemixEnv * env, RemixEnvelope * envelope)
+{
+ CDList * l = cd_list_last_item (env, envelope->points);
+ RemixPoint * p;
+
+ if (l == RemixNone) return _remix_time_zero (envelope->timetype);
+
+ p = (RemixPoint *)l->data.s_pointer;
+ if (p == RemixNone) return _remix_time_zero (envelope->timetype);
+
+ return p->time;
+}
+
+RemixPoint *
+remix_envelope_add_point (RemixEnv * env, RemixEnvelope * envelope,
+ RemixTime time, RemixPCM value)
+{
+ RemixPoint * point = remix_point_new (time, value);
+ switch (envelope->timetype) {
+ case REMIX_TIME_SAMPLES:
+ envelope->points = cd_list_insert (env, envelope->points,
+ CD_TYPE_POINTER, CD_POINTER(point),
+ (CDCmpFunc)remix_point_later_X);
+ break;
+ case REMIX_TIME_SECONDS:
+ envelope->points = cd_list_insert (env, envelope->points,
+ CD_TYPE_POINTER, CD_POINTER(point),
+ (CDCmpFunc)remix_point_later_S);
+ break;
+ case REMIX_TIME_BEAT24S:
+ envelope->points = cd_list_insert (env, envelope->points,
+ CD_TYPE_POINTER, CD_POINTER(point),
+ (CDCmpFunc)remix_point_later_B);
+ break;
+ default: /* uncommon, we should hope */
+ remix_free (point); point = RemixNone;
+ break;
+ }
+ remix_envelope_debug (env, envelope);
+ remix_envelope_optimise (env, envelope);
+ return point;
+}
+
+RemixEnvelope *
+remix_envelope_remove_point (RemixEnv * env, RemixEnvelope * envelope,
+ RemixPoint * point)
+{
+ envelope->points = cd_list_remove (env, envelope->points,
+ CD_TYPE_POINTER, CD_POINTER(point));
+ remix_free (point);
+ remix_envelope_debug (env, envelope);
+ remix_envelope_optimise (env, envelope);
+ return envelope;
+}
+
+RemixEnvelope *
+remix_envelope_scale (RemixEnv * env, RemixEnvelope * envelope, RemixPCM gain)
+{
+ CDList * l;
+ RemixPoint * p;
+
+ for (l = envelope->points; l; l = l->next) {
+ p = (RemixPoint *)l->data.s_pointer;
+ p->value *= gain;
+ }
+
+ return envelope;
+}
+
+RemixEnvelope *
+remix_envelope_shift (RemixEnv * env, RemixEnvelope * envelope, RemixTime delta)
+{
+ CDList * l;
+ RemixPoint * p;
+
+ for (l = envelope->points; l; l = l->next) {
+ p = (RemixPoint *)l->data.s_pointer;
+ p->time = _remix_time_add (envelope->timetype, p->time, delta);
+ }
+
+ return envelope;
+}
+
+static CDList *
+remix_envelope_point_item_before (RemixEnv * env, RemixEnvelope * envelope,
+ RemixCount offset)
+{
+ CDList * l, * lp = RemixNone;
+ RemixPoint * point;
+ RemixTime ptime;
+
+ for (l = envelope->points; l; l = l->next) {
+ point = (RemixPoint *)l->data.s_pointer;
+ ptime = remix_time_convert (env, point->time, envelope->timetype,
+ REMIX_TIME_SAMPLES);
+ if (ptime.samples > offset) break;
+ lp = l;
+ }
+ return lp;
+}
+
+static RemixCount
+remix_envelope_constant_write_chunk (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset, RemixCount count,
+ int channelname, void * data)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)data;
+ RemixPoint * point;
+ RemixPCM value;
+ RemixPCM * d;
+ RemixCount n;
+
+ point = (RemixPoint *)envelope->points->data.s_pointer;
+ value = point->value;
+ d = &chunk->data[offset];
+
+ n = _remix_pcm_set (d, value, count);
+ envelope->_current_offset += n;
+ return n;
+}
+
+#if 0
+static RemixCount
+remix_envelope_spline_write_chunk (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset, RemixCount count,
+ int channelname, void * data)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)data;
+ /* XXX: Implement ;) */
+ return -1;
+}
+#endif
+
+/* A RemixChunkFunc for creating envelope data */
+static RemixCount
+remix_envelope_linear_write_chunk (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset, RemixCount count,
+ int channelname, void * data)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)data;
+ RemixCount remaining = count, written = 0;
+ RemixCount pos = envelope->_current_offset;
+ CDList * l, * nl;
+ RemixPoint * point, * next_point;
+ RemixCount px, npx, n;
+ RemixTime t;
+ RemixPCM py, npy, gradient;
+ RemixPCM * d;
+
+ remix_dprintf ("[remix_envelope_linear_write_chunk] (%ld, +%ld) @ %ld\n",
+ offset, count, pos);
+
+
+ l = envelope->_current_point_item;
+
+ if (l == RemixNone) {/* No points before start */
+ l = envelope->points;
+ if (l == RemixNone) {/* No points at all */
+ n = _remix_chunk_clear_region (env, chunk, offset, count, 0, NULL);
+ envelope->_current_offset += n;
+ return n;
+ }
+ }
+
+ nl = l->next;
+ if (nl == RemixNone) {
+ /* if the last point was before offset, and there were
+ * more points, set l to the second last and nl to the last */
+ nl = l; l = l->prev;
+ if (l == RemixNone) {/* Constant envelope (one point) */
+ return remix_envelope_constant_write_chunk (env, chunk, offset, count,
+ channelname, envelope);
+ }
+ }
+
+ point = (RemixPoint *)l->data.s_pointer;
+ t = remix_time_convert (env, point->time, envelope->timetype,
+ REMIX_TIME_SAMPLES);
+ px = t.samples;
+ py = point->value;
+
+ next_point = (RemixPoint *)nl->data.s_pointer;
+ t = remix_time_convert (env, next_point->time, envelope->timetype,
+ REMIX_TIME_SAMPLES);
+ npx = t.samples;
+ npy = next_point->value;
+
+ while (remaining > 0) {
+ if (nl->next == RemixNone) {
+ /* These are the last two points, so fill out with this gradient */
+ n = remaining;
+ } else {
+ n = MIN (remaining, npx - pos);
+ }
+ gradient = (npy - py) / (RemixPCM)(npx - px);
+
+ d = &chunk->data[offset];
+ /* _remix_pcm_write_linear (d, px - chunk->start_index, py, gradient, n);*/
+ n = _remix_pcm_write_linear (d, px, py, npx, npy, pos, n);
+
+ remaining -= n;
+ written += n;
+ pos += n;
+ offset += n;
+
+ if (remaining > 0) {
+ l = nl; point = next_point; px = npx; py = npy;
+
+ nl = nl->next;
+ next_point = (RemixPoint *)nl->data.s_pointer;
+ t = remix_time_convert (env, next_point->time, envelope->timetype,
+ REMIX_TIME_SAMPLES);
+ npx = t.samples;
+ npy = next_point->value;
+ }
+ }
+
+ envelope->_current_point_item = l;
+ envelope->_current_offset = pos;
+
+ return written;
+}
+
+static RemixCount
+remix_envelope_constant_process (RemixEnv * env, RemixBase * base,
+ RemixCount count, RemixStream * input,
+ RemixStream * output)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ return remix_stream_chunkfuncify (env, output, count,
+ remix_envelope_constant_write_chunk,
+ envelope);
+}
+
+static RemixCount
+remix_envelope_spline_process (RemixEnv * env, RemixBase * base,
+ RemixCount count, RemixStream * input,
+ RemixStream * output)
+{
+ /* XXX: Implement */
+ return -1;
+}
+
+static RemixCount
+remix_envelope_linear_process (RemixEnv * env, RemixBase * base,
+ RemixCount count, RemixStream * input,
+ RemixStream * output)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ return remix_stream_chunkfuncify (env, output, count,
+ remix_envelope_linear_write_chunk,
+ envelope);
+}
+
+static RemixCount
+remix_envelope_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+
+ switch (envelope->type) {
+ case REMIX_ENVELOPE_LINEAR:
+ return remix_envelope_linear_process (env, base, count, input, output);
+ break;
+ case REMIX_ENVELOPE_SPLINE:
+ return remix_envelope_spline_process (env, base, count, input, output);
+ break;
+ default:
+ break;
+ }
+ remix_set_error (env, REMIX_ERROR_NOOP);
+ return 0;
+}
+
+static RemixCount
+remix_envelope_length (RemixEnv * env, RemixBase * base)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ RemixTime duration = remix_envelope_get_duration (env, envelope);
+ RemixTime t = remix_time_convert (env, duration, envelope->timetype,
+ REMIX_TIME_SAMPLES);
+ return t.samples;
+}
+
+static RemixCount
+remix_envelope_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixEnvelope * envelope = (RemixEnvelope *)base;
+ envelope->_current_point_item =
+ remix_envelope_point_item_before (env, envelope, offset);
+ envelope->_current_offset = offset;
+ return offset;
+}
+
+static struct _RemixMethods _remix_envelope_empty_methods = {
+ remix_envelope_clone,
+ remix_envelope_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_null_process,
+ remix_null_length,
+ remix_envelope_seek,
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_envelope_constant_methods = {
+ remix_envelope_clone,
+ remix_envelope_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_envelope_constant_process,
+ remix_envelope_length,
+ remix_envelope_seek,
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_envelope_linear_methods = {
+ remix_envelope_clone,
+ remix_envelope_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_envelope_linear_process,
+ remix_envelope_length,
+ remix_envelope_seek,
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_envelope_spline_methods = {
+ remix_envelope_clone,
+ remix_envelope_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_envelope_spline_process,
+ remix_envelope_length,
+ remix_envelope_seek,
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_envelope_methods = {
+ remix_envelope_clone,
+ remix_envelope_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_envelope_process,
+ remix_envelope_length,
+ remix_envelope_seek,
+ NULL, /* flush */
+};
+
+static RemixEnvelope *
+remix_envelope_optimise (RemixEnv * env, RemixEnvelope * envelope)
+{
+ if (cd_list_is_empty (env, envelope->points)) {
+ _remix_set_methods (env, envelope, &_remix_envelope_empty_methods);
+ } else if (cd_list_is_singleton (env, envelope->points)) {
+ _remix_set_methods (env, envelope, &_remix_envelope_constant_methods);
+ } else {
+ switch (envelope->type) {
+ case REMIX_ENVELOPE_LINEAR:
+ _remix_set_methods (env, envelope, &_remix_envelope_linear_methods); break;
+ case REMIX_ENVELOPE_SPLINE:
+ _remix_set_methods (env, envelope, &_remix_envelope_spline_methods); break;
+ default:
+ _remix_set_methods (env, envelope, &_remix_envelope_methods); break;
+ }
+ }
+
+ return envelope;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixError -- SOUNDRENDER error handling.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+char *
+remix_error_string (RemixEnv * env, RemixError error)
+{
+ switch (error) {
+ case REMIX_ERROR_OK: return "OK"; break;
+ case REMIX_ERROR_INVALID: return "Invalid base"; break;
+ case REMIX_ERROR_NOENTITY: return "No such base"; break;
+ case REMIX_ERROR_SILENCE: return "Operation would yield silence"; break;
+ case REMIX_ERROR_NOOP: return "Operation would not modify data"; break;
+ case REMIX_ERROR_SYSTEM: return "System error"; break;
+ default: return "Unknown error"; break;
+ }
+}
+
+/*
+ * remix_exit_err (fmt)
+ *
+ * Print a formatted error message and errno information to stderr,
+ * then exit with return code 1.
+ */
+void
+remix_exit_err (const char * fmt, ...)
+{
+ va_list ap;
+ int errno_save;
+ char buf[REMIX_MAXLINE];
+ int n;
+
+ errno_save = errno;
+
+ va_start (ap, fmt);
+
+ snprintf (buf, REMIX_MAXLINE, "Remix: ");
+ n = strlen (buf);
+
+ vsnprintf (buf+n, REMIX_MAXLINE-n, fmt, ap);
+ n = strlen (buf);
+
+ snprintf (buf+n, REMIX_MAXLINE-n, ": %s\n", strerror (errno_save));
+
+ fflush (stdout); /* in case stdout and stderr are the same */
+ fputs (buf, stderr);
+ fflush (NULL);
+
+ va_end (ap);
+ exit (1);
+}
+
+/*
+ * remix_print_err (fmt)
+ *
+ * Print a formatted error message to stderr.
+ */
+void
+remix_print_err (const char * fmt, ...)
+{
+ va_list ap;
+ int errno_save;
+ char buf[REMIX_MAXLINE];
+ int n;
+
+ errno_save = errno;
+
+ va_start (ap, fmt);
+
+ snprintf (buf, REMIX_MAXLINE, "SOUNDRENDER: ");
+ n = strlen (buf);
+
+ vsnprintf (buf+n, REMIX_MAXLINE-n, fmt, ap);
+ n = strlen (buf);
+
+ fflush (stdout); /* in case stdout and stderr are the same */
+ fputs (buf, stderr);
+ fputc ('\n', stderr);
+ fflush (NULL);
+
+ va_end (ap);
+}
+
+/*
+ * print_debug (level, fmt)
+ *
+ * Print a formatted debugging message of level 'level' to stderr
+ */
+
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixGain: a gain filter
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#include <stdlib.h>
+
+#define __REMIX_PLUGIN__
+#include "remix.h"
+
+#define GAIN_ENVELOPE_KEY 1
+
+typedef struct _RemixGain RemixGain;
+
+struct _RemixGain {
+ RemixStream * _gain_envstream;
+};
+
+/* Optimisation dependencies: none */
+static RemixBase * remix_gain_optimise (RemixEnv * env, RemixBase * gain);
+
+static void
+remix_gain_replace_mixstream (RemixEnv * env, RemixBase * gain)
+{
+ RemixCount mixlength = remix_base_get_mixlength (env, gain);
+ RemixGain * gi = (RemixGain *)remix_base_get_instance_data (env, gain);
+
+ if (gi->_gain_envstream != RemixNone)
+ remix_destroy (env, (RemixBase *)gi->_gain_envstream);
+
+ gi->_gain_envstream =
+ remix_stream_new_contiguous (env, mixlength);
+}
+
+static RemixBase *
+remix_gain_init (RemixEnv * env, RemixBase * base, CDSet * parameters)
+{
+ remix_base_set_instance_data (env, base,
+ calloc (1, sizeof (struct _RemixGain)));
+ remix_gain_replace_mixstream (env, base);
+ remix_gain_optimise (env, base);
+ return base;
+}
+
+static RemixBase *
+remix_gain_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixBase * new_gain = remix_base_new (env);
+ remix_gain_init (env, new_gain, CD_EMPTY_SET);
+ remix_gain_optimise (env, new_gain);
+ return (RemixBase *)new_gain;
+}
+
+static int
+remix_gain_destroy (RemixEnv * env, RemixBase * base)
+{
+ free (remix_base_get_instance_data (env, base));
+ free (base);
+ return 0;
+}
+
+static int
+remix_gain_ready (RemixEnv * env, RemixBase * base)
+{
+ return (remix_base_encompasses_mixlength (env, base) &&
+ remix_base_encompasses_channels (env, base));
+}
+
+static RemixBase *
+remix_gain_prepare (RemixEnv * env, RemixBase * base)
+{
+ remix_gain_replace_mixstream (env, base);
+ return base;
+}
+
+static RemixCount
+remix_gain_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixCount remaining = count, processed = 0, n;
+ RemixCount output_offset;
+ RemixCount mixlength = remix_base_get_mixlength (env, base);
+ RemixBase * gain_envelope;
+ RemixGain * gi = remix_base_get_instance_data (env, base);
+
+ remix_dprintf ("PROCESS GAIN (%p, +%ld) @ %ld\n", base, count,
+ remix_tell (env, base));
+
+ gain_envelope =
+ (RemixBase *) (remix_get_parameter (env, base, GAIN_ENVELOPE_KEY)).s_pointer;
+
+ if (gain_envelope == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOOP);
+ return -1;
+ }
+
+ while (remaining > 0) {
+ n = MIN (remaining, mixlength);
+
+ output_offset = remix_tell (env, (RemixBase *)output);
+ n = remix_stream_copy (env, input, output, n);
+
+ remix_seek (env, (RemixBase *)gi->_gain_envstream, 0, SEEK_SET);
+ n = remix_process (env, gain_envelope, n, RemixNone,
+ gi->_gain_envstream);
+
+ remix_seek (env, (RemixBase *)gi->_gain_envstream, 0, SEEK_SET);
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = remix_stream_mult (env, gi->_gain_envstream, output, n);
+
+ remaining -= n;
+ processed += n;
+ }
+
+ remix_dprintf ("[remix_gain_process] processed %ld\n", processed);
+
+ return processed;
+}
+
+static RemixCount
+remix_gain_length (RemixEnv * env, RemixBase * base)
+{
+ RemixBase * gain_envelope =
+ (RemixBase *) (remix_get_parameter (env, base, GAIN_ENVELOPE_KEY)).s_pointer;
+
+ if (gain_envelope == RemixNone) {
+ return REMIX_COUNT_INFINITE;
+ }
+
+ return remix_length (env, gain_envelope);
+}
+
+static RemixCount
+remix_gain_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixBase * gain_envelope =
+ (RemixBase *) (remix_get_parameter (env, base, GAIN_ENVELOPE_KEY)).s_pointer;
+
+ return remix_seek (env, (RemixBase *)gain_envelope, offset, SEEK_SET);
+}
+
+static struct _RemixMethods _remix_gain_methods = {
+ remix_gain_clone,
+ remix_gain_destroy,
+ remix_gain_ready,
+ remix_gain_prepare,
+ remix_gain_process,
+ remix_gain_length,
+ remix_gain_seek,
+};
+
+static RemixBase *
+remix_gain_optimise (RemixEnv * env, RemixBase * gain)
+{
+ remix_base_set_methods (env, gain, &_remix_gain_methods);
+ return gain;
+}
+
+static int
+remix_gain_plugin_destroy (RemixEnv * env, RemixPlugin * plugin)
+{
+ cd_set_free (env, plugin->process_scheme);
+ return 0;
+}
+
+static struct _RemixParameterScheme gain_envelope_scheme = {
+ "Gain envelope",
+ "An envelope to control the amplitude",
+ REMIX_TYPE_BASE,
+ REMIX_CONSTRAINT_TYPE_NONE,
+ REMIX_CONSTRAINT_EMPTY,
+ REMIX_HINT_DEFAULT,
+};
+
+static struct _RemixMetaText gain_metatext = {
+ "builtin::gain",
+ "Processors::Gain Adjustment",
+ "Adjusts the gain of its input",
+ "Copyright (C) 2001 CSIRO Australia",
+ "http://www.metadecks.org/env/plugins/gain.html",
+ REMIX_ONE_AUTHOR ("Conrad Parker", "conrad@metadecks.org"),
+};
+
+static struct _RemixPlugin gain_plugin = {
+ &gain_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* new scheme */
+ remix_gain_init,
+ CD_EMPTY_SET, /* process_scheme */
+ NULL, /* suggests */
+ NULL, /* plugin_data */
+ remix_gain_plugin_destroy /* destroy */
+};
+
+/* module init function */
+CDList *
+__gain_init (RemixEnv * env)
+{
+ CDList * plugins = cd_list_new (env);
+
+ gain_plugin.process_scheme =
+ cd_set_insert (env, gain_plugin.process_scheme, GAIN_ENVELOPE_KEY,
+ CD_POINTER(&gain_envelope_scheme));
+
+ plugins = cd_list_prepend (env, plugins, CD_POINTER(&gain_plugin));
+
+ return plugins;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixLayer: A sound sequence abstraction.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A layer is contained within a track. It consists of a sequence of
+ * sounds. A layer has a time type (RemixTimeType) with which its sounds
+ * are indexed.
+ * XXX: Overlapping sounds in a layer should be mixed together.
+ *
+ * Invariants
+ * ----------
+ *
+ * A layer must be contained in a track.
+ *
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+/* Optimisation dependencies: none */
+static RemixLayer * remix_layer_optimise (RemixEnv * env, RemixLayer * layer);
+
+/* Coherency dependencies: ensure coherency on addition+removal of sounds */
+static RemixLayer * remix_layer_ensure_coherency (RemixEnv * env, RemixLayer * layer);
+
+void
+remix_layer_debug (RemixEnv * env, RemixLayer * layer)
+{
+#ifdef DEBUG
+ CDList * l;
+ RemixSound * s;
+
+ remix_dprintf ("Layer (0x%p): ", layer);
+ if (layer == RemixNone) return;
+
+ for (l = layer->sounds; l; l = l->next) {
+ s = (RemixSound *)l->data.s_pointer;
+ /* XXX: assumes samples */
+ remix_dprintf ("[0x%p: %ld, +%ld] ", s, s->start_time.samples,
+ s->duration.samples);
+ }
+ remix_dprintf ("\n");
+#endif
+}
+
+static RemixBase *
+remix_layer_init (RemixEnv * env, RemixBase * base)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ layer->timetype = REMIX_TIME_SAMPLES;
+ layer->sounds = cd_list_new (env);
+ /* layer->_current_time = _remix_time_zero (layer->timetype);*/
+ layer->_current_sound_item = RemixNone;
+ layer->_current_tempo = remix_get_tempo (env);
+ layer->_current_offset = 0;
+ remix_layer_optimise (env, layer);
+ return (RemixBase *)layer;
+}
+
+static RemixBase *
+_remix_layer_new (RemixEnv * env)
+{
+ return (RemixBase *)
+ remix_base_new_subclass (env, sizeof (struct _RemixLayer));
+}
+
+RemixBase *
+remix_layer_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ RemixLayer * new_layer = (RemixLayer *)_remix_layer_new (env);
+ RemixCount offset = remix_tell (env, base);
+
+ new_layer->timetype = layer->timetype;
+ new_layer->sounds =
+ cd_list_clone_with (env, layer->sounds,
+ (CDCloneWithFunc)remix_sound_clone_with_layer,
+ new_layer);
+ remix_seek (env, (RemixBase *)new_layer, offset, SEEK_SET);
+
+ new_layer->track = layer->track;
+ _remix_track_add_layer_above (env, layer->track, new_layer, layer);
+
+ return (RemixBase *)new_layer;
+}
+
+static int
+remix_layer_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ if (layer->track)
+ _remix_track_remove_layer (env, layer->track, layer);
+ remix_destroy_list (env, layer->sounds);
+ remix_free (layer);
+ return 0;
+}
+
+RemixLayer *
+remix_layer_new_ontop (RemixEnv * env, RemixTrack * track,
+ RemixTimeType timetype)
+{
+ RemixLayer * layer = (RemixLayer *)_remix_layer_new (env);
+
+ layer->track = track;
+ _remix_track_add_layer_above (env, track, layer, RemixNone);
+ remix_layer_init (env, (RemixBase *)layer);
+ layer->timetype = timetype;
+
+ return layer;
+}
+
+RemixLayer *
+remix_layer_new_above (RemixEnv * env, RemixLayer * above,
+ RemixTimeType timetype)
+{
+ RemixLayer * layer;
+ if (above == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ layer = (RemixLayer *)_remix_layer_new (env);
+ layer->track = above->track;
+ _remix_track_add_layer_above (env, above->track, layer, above);
+ remix_layer_init (env, (RemixBase *)layer);
+ layer->timetype = timetype;
+
+ return layer;
+}
+
+RemixLayer *
+remix_layer_move_ontop (RemixEnv * env, RemixLayer * layer, RemixTrack * track)
+{
+ if (layer->track)
+ _remix_track_remove_layer (env, layer->track, layer);
+
+ if (track)
+ _remix_track_add_layer_above (env, track, layer, RemixNone);
+
+ return layer;
+}
+
+RemixLayer *
+remix_layer_move_above (RemixEnv * env, RemixLayer * layer, RemixLayer * above)
+{
+ if (layer->track)
+ _remix_track_remove_layer (env, layer->track, layer);
+
+ if (above->track)
+ _remix_track_add_layer_above (env, above->track, layer, above);
+
+ return layer;
+}
+
+RemixLayer *
+remix_layer_raise (RemixEnv * env, RemixLayer * layer)
+{
+ RemixLayer * above;
+
+ if (layer->track) {
+ above = _remix_track_get_layer_above (env, layer->track, layer);
+ remix_layer_move_above (env, layer, above);
+ }
+
+ return layer;
+}
+
+RemixLayer *
+remix_layer_lower (RemixEnv * env, RemixLayer * layer)
+{
+ RemixLayer * below;
+
+ if (layer->track) {
+ below = _remix_track_get_layer_below (env, layer->track, layer);
+ remix_layer_move_above (env, below, layer);
+ }
+
+ return layer;
+}
+
+RemixLayer *
+_remix_remove_layer (RemixEnv * env, RemixLayer * layer)
+{
+ if (layer->track)
+ _remix_track_remove_layer (env, layer->track, layer);
+
+ layer->track = RemixNone;
+ return layer;
+}
+
+RemixTrack *
+remix_layer_get_track (RemixEnv * env, RemixLayer * layer)
+{
+ return layer->track;
+}
+
+RemixDeck *
+remix_layer_get_deck (RemixEnv * env, RemixLayer * layer)
+{
+ RemixTrack * track = layer->track;
+ if (track == RemixNone) return RemixNone;
+ return remix_track_get_deck (env, track);
+}
+
+RemixTimeType
+remix_layer_set_timetype (RemixEnv * env, RemixLayer * layer, RemixTimeType new_type)
+{
+ RemixTimeType old_type = layer->timetype;
+ CDList * l;
+ RemixDeck * deck;
+ RemixSound * sound;
+
+ if (old_type == new_type) return old_type;
+
+ deck = remix_layer_get_deck (env, layer);
+
+ for (l = layer->sounds; l; l = l->next) {
+ sound = (RemixSound *)l->data.s_pointer;
+ sound->start_time = remix_time_convert (env, sound->start_time, old_type,
+ new_type);
+ sound->duration = remix_time_convert (env, sound->duration, old_type,
+ new_type);
+ }
+
+ layer->timetype = new_type;
+
+ return old_type;
+}
+
+RemixTimeType
+remix_layer_get_timetype (RemixEnv * env, RemixLayer * layer)
+{
+ return layer->timetype;
+}
+
+RemixSound *
+_remix_layer_add_sound (RemixEnv * env, RemixLayer * layer, RemixSound * sound,
+ RemixTime start_time)
+{
+ sound->start_time = start_time;
+ layer->sounds = cd_list_insert (env, layer->sounds, CD_TYPE_POINTER,
+ CD_POINTER(sound),
+ (CDCmpFunc)remix_sound_later);
+ remix_layer_ensure_coherency (env, layer);
+ return sound;
+}
+
+RemixSound *
+_remix_layer_remove_sound (RemixEnv * env, RemixLayer * layer, RemixSound * sound)
+{
+ layer->sounds = cd_list_remove (env, layer->sounds, CD_TYPE_POINTER,
+ CD_POINTER(sound));
+ remix_layer_ensure_coherency (env, layer);
+ return sound;
+}
+
+/*
+ * remix_layer_get_sound_item_before (layer, time)
+ *
+ * Finds the last sound with a start_time before 'time'.
+ */
+static CDList *
+remix_layer_get_sound_item_before (RemixEnv * env, RemixLayer * layer, RemixTime time)
+{
+ RemixSound * s;
+ CDList * l, * lp = RemixNone;
+
+ for (l = layer->sounds; l; l = l->next) {
+ s = (RemixSound *)l->data.s_pointer;
+ if (_remix_time_gt (layer->timetype, s->start_time, time)) return lp;
+ lp = l;
+ }
+
+ return lp;
+}
+
+/*
+ * remix_layer_get_sound_item_at (layer, time)
+ *
+ * Finds the sound occurring at 'time'. If no sound is playing at 'time',
+ * returns RemixNone.
+ */
+CDList *
+remix_layer_get_sound_item_at (RemixEnv * env, RemixLayer * layer, RemixTime time)
+{
+ RemixTime t;
+ CDList * l = remix_layer_get_sound_item_before (env, layer, time);
+ RemixSound * s;
+
+ if (l == RemixNone) return RemixNone;
+
+ s = (RemixSound *)l->data.s_pointer;
+
+ t = _remix_time_add (layer->timetype, s->start_time, s->duration);
+ if (_remix_time_le (layer->timetype, t, time)) l = RemixNone;
+
+ return l;
+}
+
+/*
+ * remix_layer_get_sound_item_after (layer, time)
+ *
+ * Finds the first sound at or after 'time' and returns its list item.
+ */
+static CDList *
+remix_layer_get_sound_item_after (RemixEnv * env, RemixLayer * layer, RemixTime time)
+{
+ RemixSound * s;
+ CDList * l;
+
+ for (l = layer->sounds; l; l = l->next) {
+ s = (RemixSound *)l->data.s_pointer;
+ if (_remix_time_ge (layer->timetype, s->start_time, time)) return l;
+ }
+
+ return RemixNone;
+}
+
+/*
+ * remix_layer_get_sound_after (layer, time)
+ *
+ * Finds the first sound with a start_time at or after 'time'.
+ */
+RemixSound *
+remix_layer_get_sound_after (RemixEnv * env, RemixLayer * layer, RemixTime time)
+{
+ CDList * l = remix_layer_get_sound_item_after (env, layer, time);
+
+ if (l == RemixNone) return RemixNone;
+ else return (RemixSound *)l->data.s_pointer;
+}
+
+RemixSound *
+_remix_layer_get_sound_prev (RemixEnv * env, RemixLayer * layer, RemixSound * sound)
+{
+ CDList * sound_item;
+ RemixSound * sn;
+
+ if (layer->sounds == NULL) return RemixNone;
+
+ if (sound == RemixNone) {
+ sn = (RemixSound *) layer->sounds->data.s_pointer;
+ } else {
+ sound_item = cd_list_find (env, layer->sounds, CD_TYPE_POINTER,
+ CD_POINTER(sound));
+ if (sound_item == NULL) return RemixNone;
+ sound_item = sound_item->prev;
+ if (sound_item == NULL) return RemixNone;
+ sn = (RemixSound *) sound_item->data.s_pointer;
+ }
+
+ return sn;
+}
+
+RemixSound *
+_remix_layer_get_sound_next (RemixEnv * env, RemixLayer * layer, RemixSound * sound)
+{
+ CDList * sound_item;
+ RemixSound * sn;
+
+ if (layer->sounds == NULL) return RemixNone;
+
+ if (sound == NULL) {
+ sn = (RemixSound *)
+ (cd_list_last (env, layer->sounds, CD_TYPE_POINTER)).s_pointer;
+ } else {
+ sound_item = cd_list_find (env, layer->sounds, CD_TYPE_POINTER,
+ CD_POINTER(sound));
+ if (sound_item == NULL) return RemixNone;
+ sound_item = sound_item->next;
+ if (sound_item == NULL) return RemixNone;
+ sn = (RemixSound *) sound_item->data.s_pointer;
+ }
+
+ return sn;
+}
+
+RemixLayer *
+remix_layer_below (RemixEnv * env, RemixLayer * layer)
+{
+ if (layer->track)
+ return _remix_track_get_layer_below (env, layer->track, layer);
+ else
+ return RemixNone;
+}
+
+RemixLayer *
+remix_layer_above (RemixEnv * env, RemixLayer * layer)
+{
+ if (layer->track)
+ return _remix_track_get_layer_above (env, layer->track, layer);
+ else
+ return RemixNone;
+}
+
+static RemixCount
+remix_layer_length (RemixEnv * env, RemixBase * base)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ RemixSound * sound = (RemixSound *)
+ (cd_list_last (env, layer->sounds, CD_TYPE_POINTER)).s_pointer;
+ RemixTime end, t;
+
+ if (sound == RemixNone) {
+ remix_dprintf ("[remix_layer_length] layer %p has no sounds\n", layer);
+ return 0;
+ }
+
+ /* Convert sound's end time to offset and return that */
+ end = _remix_time_add (layer->timetype, sound->start_time, sound->duration);
+ t = remix_time_convert (env, end, layer->timetype, REMIX_TIME_SAMPLES);
+
+ remix_dprintf ("[remix_layer_length] (%p) last sound ends at %d ticks == %ld samples\n",
+ layer, end.beat24s, t.samples);
+
+ return t.samples;
+}
+
+static RemixCount
+remix_layer_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ RemixTime current_time;
+
+ /* Evaluate this offset as a time value using the current samplerate and
+ * tempo */
+ current_time = remix_time_convert (env, (RemixTime)offset, REMIX_TIME_SAMPLES,
+ layer->timetype);
+
+ /* Cache the current sound item */
+ layer->_current_sound_item =
+ remix_layer_get_sound_item_at (env, layer, current_time);
+
+ if (layer->_current_sound_item == RemixNone)
+ layer->_current_sound_item =
+ remix_layer_get_sound_item_after (env, layer, current_time);
+
+ layer->_current_offset = offset;
+
+ return offset;
+}
+
+static RemixCount
+remix_layer_process_sound (RemixEnv * env, RemixLayer * layer,
+ RemixCount current_offset, RemixSound * sound,
+ RemixCount sound_offset, RemixCount sound_length,
+ RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixCount remaining = count, processed = 0, n;
+
+ /* If the next sound starts after the current offset, fill up to it */
+ if (sound_offset > current_offset) {
+ n = MIN (remaining, sound_offset - current_offset);
+
+ remix_dprintf ("[remix_layer_process_sound] %p is after offset, filling %ld\n",
+ sound, n);
+
+ if (output != RemixNone)
+ n = remix_stream_write (env, output, n, input);
+ current_offset += n;
+ processed += n;
+ remaining -= n;
+ }
+
+ /* If that didn't fill the output, process part of the next sound */
+ if (processed < count) {
+ n = MIN (remaining, sound_offset + sound_length - current_offset);
+ /* XXX: fix following line to use SEEK_CUR ??? */
+ remix_seek (env, (RemixBase *)sound, current_offset - sound_offset,
+ SEEK_SET);
+ n = remix_process (env, (RemixBase *)sound, n, input, output);
+ processed += n;
+ remaining -= n;
+ }
+
+ return processed;
+}
+
+static RemixCount
+remix_layer_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ RemixTempo tempo = remix_get_tempo (env);
+ RemixCount processed = 0, remaining = count, n;
+ RemixCount sound_offset, sound_length, next_offset;
+ RemixCount current_offset = remix_tell (env, (RemixBase *)layer);
+ RemixSound * sound, * sn;
+ RemixTime t;
+
+ remix_dprintf ("PROCESS LAYER (%p, +%ld, %p -> %p) @ %ld\n",
+ layer, count, input, output, current_offset);
+
+
+ if (layer->timetype == REMIX_TIME_BEAT24S && layer->_current_tempo != tempo) {
+#if 0
+ RemixCount new_offset;
+
+#if 0
+ if (layer->_current_sound_item == RemixNone) {
+ RemixSamplerate samplerate = remix_get_samplerate (env);
+ int beat24s;
+
+ beat24s = ((int)((float)remix_tell (env, (RemixBase *)layer) *
+ layer->_current_tempo * 24.0 / (samplerate * 60.0)));
+ new_offset = (RemixCount)(beat24s * samplerate * 60.0 / (tempo * 24.0));
+ } else {
+ sound = (RemixSound *)layer->_current_sound_item->data.s_pointer;
+ t = remix_time_convert (env, sound->start_time, layer->timetype,
+ REMIX_TIME_SAMPLES);
+
+ new_offset = t.samples + remix_tell (env, (RemixBase *)sound);
+ }
+#else
+ new_offset = layer->_current_offset * tempo / layer->_current_tempo;
+#endif
+
+ remix_layer_seek (env, (RemixBase *)layer, new_offset);
+ layer->_current_tempo = tempo;
+#else
+ if (layer->_current_sound_item != RemixNone)
+ remix_layer_ensure_coherency (env, layer);
+#endif
+ }
+
+ while (remaining > 0) {
+
+ if (layer->_current_sound_item == RemixNone) {
+ /* No more sounds */
+ remix_dprintf ("[remix_layer_process] ## no more sounds!\n");
+
+ n = (output == RemixNone) ? remaining :
+ remix_stream_write (env, output, remaining, input);
+ current_offset += n;
+ processed += n;
+ remaining -= n;
+ break;
+ }
+
+ sound = (RemixSound *)layer->_current_sound_item->data.s_pointer;
+ t = remix_time_convert (env, sound->start_time, layer->timetype,
+ REMIX_TIME_SAMPLES);
+ sound_offset = t.samples;
+
+ t = remix_time_convert (env, sound->duration, layer->timetype,
+ REMIX_TIME_SAMPLES);
+ sound_length = t.samples;
+
+ if (layer->_current_sound_item->next) {
+ sn = (RemixSound *)(layer->_current_sound_item->next->data.s_pointer);
+ t = remix_time_convert (env, sn->start_time, layer->timetype,
+ REMIX_TIME_SAMPLES);
+ next_offset = t.samples;
+ if (next_offset < sound_offset + sound_length)
+ sound_length = next_offset - sound_offset;
+ }
+
+ /* *** We now have the next sound and its valid length *** */
+ remix_dprintf ("[remix_layer_process] to process sound %p, [%ld, +%ld]\n",
+ sound, sound_offset, sound_length);
+
+ n = remix_layer_process_sound (env, layer, current_offset,
+ sound, sound_offset, sound_length,
+ remaining, input, output);
+ current_offset += n;
+ processed += n;
+ remaining -= n;
+
+ if (current_offset >= sound_offset + sound_length)
+ layer->_current_sound_item = layer->_current_sound_item->next;
+ }
+
+ remix_dprintf ("[remix_layer_process] processed %ld\n", processed);
+
+ if (processed == 0) {
+ remix_set_error (env, REMIX_ERROR_NOOP);
+ return -1;
+ }
+
+ layer->_current_offset = current_offset;
+
+ return processed;
+}
+
+static int
+remix_layer_flush (RemixEnv * env, RemixBase * base)
+{
+ RemixLayer * layer = (RemixLayer *)base;
+ RemixBase * sound;
+
+ if (layer->_current_sound_item == RemixNone) return 0;
+
+ sound = (RemixBase *)layer->_current_sound_item->data.s_pointer;
+
+ return remix_flush (env, sound);
+}
+
+static RemixLayer *
+remix_layer_ensure_coherency (RemixEnv * env, RemixLayer * layer)
+{
+ RemixCount offset = remix_tell (env, (RemixBase *)layer);
+
+ remix_layer_seek (env, (RemixBase *)layer, offset);
+ layer->_current_tempo = remix_get_tempo (env);
+
+ return layer;
+}
+
+static struct _RemixMethods _remix_layer_methods = {
+ remix_layer_clone, /* clone */
+ remix_layer_destroy, /* destroy */
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_layer_process, /* process */
+ remix_layer_length, /* length */
+ remix_layer_seek, /* seek */
+ remix_layer_flush, /* flush */
+};
+
+static RemixLayer *
+remix_layer_optimise (RemixEnv * env, RemixLayer * layer)
+{
+ _remix_set_methods (env, layer, &_remix_layer_methods);
+ return layer;
+}
+
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixMetaText: Metadata for RemixBases.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+
+#define __REMIX__
+#include "remix.h"
+
+#include <string.h>
+
+RemixMetaText *
+remix_meta_text_new (RemixEnv * env)
+{
+ RemixMetaText * mt;
+
+ mt = (RemixMetaText *) remix_malloc (sizeof (struct _RemixMetaText));
+ mt->authors = cd_list_new (env);
+
+ return mt;
+}
+
+char *
+remix_meta_text_get_identifier (RemixEnv * env, RemixMetaText * mt)
+{
+ return mt->identifier;
+}
+
+char *
+remix_meta_text_set_identifier (RemixEnv * env, RemixMetaText * mt, char * identifier)
+{
+ char * old = mt->identifier;
+ mt->identifier = (identifier == NULL) ? NULL : strdup(identifier);
+ return old;
+}
+
+char *
+remix_meta_text_get_category (RemixEnv * env, RemixMetaText * mt)
+{
+ return mt->category;
+}
+
+char *
+remix_meta_text_set_category (RemixEnv * env, RemixMetaText * mt, char * category)
+{
+ char * old = mt->category;
+ mt->category = (category == NULL) ? NULL : strdup(category);
+ return old;
+}
+
+char *
+remix_meta_text_get_description (RemixEnv * env, RemixMetaText * mt)
+{
+ return mt->description;
+}
+
+char *
+remix_meta_text_set_description (RemixEnv * env, RemixMetaText * mt, char * description)
+{
+ char * old = mt->description;
+ mt->description = (description == NULL) ? NULL : strdup(description);
+ return old;
+}
+
+char *
+remix_meta_text_get_copyright (RemixEnv * env, RemixMetaText * mt)
+{
+ return mt->copyright;
+}
+
+char *
+remix_meta_text_set_copyright (RemixEnv * env, RemixMetaText * mt, char * copyright)
+{
+ char * old = mt->copyright;
+ mt->copyright = (copyright == NULL) ? NULL : strdup(copyright);
+ return old;
+}
+
+char *
+remix_meta_text_get_url (RemixEnv * env, RemixMetaText * mt)
+{
+ return mt->url;
+}
+
+char *
+remix_meta_text_set_url (RemixEnv * env, RemixMetaText * mt, char * url)
+{
+ char * old = mt->url;
+ mt->url = (url == NULL) ? NULL : strdup(url);
+ return old;
+}
+
+static RemixMetaAuthor *
+remix_meta_author_new (RemixEnv * env, char * name, char * email)
+{
+ RemixMetaAuthor * ma = remix_malloc (sizeof (struct _RemixMetaAuthor));
+ ma->name = (name == NULL) ? NULL : strdup(name);
+ ma->email = (email == NULL) ? NULL: strdup(email);
+ return ma;
+}
+
+CDList *
+remix_meta_text_get_authors (RemixEnv * env, RemixMetaText * mt)
+{
+ return mt->authors;
+}
+
+void
+remix_meta_text_add_author (RemixEnv * env, RemixMetaText * mt,
+ char * name, char * email)
+{
+ RemixMetaAuthor * ma = remix_meta_author_new (env, name, email);
+ mt->authors = cd_list_append (env, mt->authors, CD_POINTER(ma));
+}
+
+void
+remix_meta_text_free (RemixEnv * env, RemixMetaText * mt)
+{
+ cd_list_free_all (env, mt->authors);
+ remix_free (mt);
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixMonitor: device output
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <config.h>
+
+#define __REMIX__
+#include "remix.h"
+
+#define DEFAULT_FORMAT AFMT_S16_LE
+#define DEFAULT_STEREO 1
+#define DEFAULT_FREQUENCY 44100
+#define DEFAULT_NUMFRAGS 4
+#define DEFAULT_FRAGSIZE 10
+
+/* Must be either 1 or 0. */
+#define DEBUG_FILE 0
+
+#if (DEBUG_FILE == 1)
+/* make sure this file exists; we're not using O_CREAT! */
+#define FILENAME "/tmp/env.out"
+#else
+#define FILENAME "/dev/dsp"
+#endif
+
+/* Optimisation dependencies: none */
+static RemixMonitor * remix_monitor_optimise (RemixEnv * env, RemixMonitor * monitor);
+
+static RemixBase *
+remix_monitor_reset_device (RemixEnv * env, RemixBase * base)
+{
+ RemixMonitor * monitor = (RemixMonitor *)base;
+ CDSet * channels = remix_get_channels (env);
+ RemixCount nr_channels;
+ int fragmentsize;
+
+ nr_channels = cd_set_size (env, channels);
+
+ if (nr_channels == 1)
+ monitor->stereo = 0;
+ else if (nr_channels > 1)
+ monitor->stereo = 1;
+
+ monitor->mask = 0;
+ monitor->format = DEFAULT_FORMAT;
+
+ monitor->frequency = remix_get_samplerate (env);
+ monitor->numfrags = DEFAULT_NUMFRAGS;
+ monitor->fragsize = DEFAULT_FRAGSIZE;
+
+ if (DEBUG_FILE == 1) {
+ monitor->format = AFMT_S16_LE;
+ return base;
+ }
+
+ if (ioctl (monitor->dev_dsp_fd, SNDCTL_DSP_GETFMTS, &monitor->mask) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ if (monitor->mask & AFMT_U8) {
+ monitor->format = AFMT_U8;
+ }
+ if (monitor->mask & AFMT_U16_LE) {
+ monitor->format = AFMT_U16_LE;
+ }
+ if (monitor->mask & AFMT_S16_LE) {
+ monitor->format = AFMT_S16_LE;
+ }
+ if (monitor->mask & AFMT_U16_BE) {
+ monitor->format = AFMT_U16_BE;
+ }
+ if (monitor->mask & AFMT_S16_BE) {
+ monitor->format = AFMT_S16_BE;
+ }
+ if (monitor->mask & AFMT_S8) {
+ monitor->format = AFMT_S8;
+ }
+ if (monitor->mask & AFMT_S16_LE) {
+ monitor->format = AFMT_S16_LE;
+ }
+
+ if (ioctl(monitor->dev_dsp_fd, SNDCTL_DSP_SETFMT, &monitor->format) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ if (ioctl(monitor->dev_dsp_fd, SNDCTL_DSP_STEREO, &(monitor->stereo)) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ if (ioctl(monitor->dev_dsp_fd, SNDCTL_DSP_SPEED, &(monitor->frequency)) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ fragmentsize = (monitor->numfrags << 16) | monitor->fragsize;
+ if (ioctl(monitor->dev_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragmentsize) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ return base;
+}
+
+static RemixBase *
+remix_monitor_init (RemixEnv * env, RemixBase * base)
+{
+ RemixMonitor * monitor = (RemixMonitor *)base;
+
+ monitor->dev_dsp_fd = -1;
+
+ monitor->dev_dsp_fd = open (FILENAME, O_WRONLY, 0);
+ if (monitor->dev_dsp_fd == -1) {
+ printf ("Couldn't open any output device.\n");
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return RemixNone;
+ }
+
+ remix_monitor_reset_device (env, base);
+
+ remix_monitor_optimise (env, monitor);
+
+ return (RemixBase *)monitor;
+}
+
+RemixMonitor *
+remix_monitor_new (RemixEnv * env)
+{
+ RemixBase * monitor = remix_base_new_subclass (env, sizeof (struct _RemixMonitor));
+
+ remix_monitor_init (env, monitor);
+ return (RemixMonitor *)monitor;
+}
+
+static RemixBase *
+remix_monitor_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixMonitor * new_monitor = remix_monitor_new (env);
+
+ remix_monitor_optimise (env, new_monitor);
+ return (RemixBase *)new_monitor;
+}
+
+static int
+remix_monitor_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixMonitor * monitor = (RemixMonitor *)base;
+
+ if (monitor->dev_dsp_fd != -1) {
+ close (monitor->dev_dsp_fd);
+ }
+ remix_free (monitor);
+ return 0;
+}
+
+static int
+remix_monitor_ready (RemixEnv * env, RemixBase * base)
+{
+ RemixMonitor * monitor = (RemixMonitor *) base;
+ CDSet * channels = remix_get_channels (env);
+ int samplerate = (int) remix_get_samplerate (env);
+ RemixCount nr_channels;
+
+ nr_channels = cd_set_size (env, channels);
+
+ return (samplerate == monitor->frequency &&
+ ((nr_channels == 1 && monitor->stereo == 0) ||
+ (nr_channels > 1 && monitor->stereo == 1)));
+}
+
+static RemixBase *
+remix_monitor_prepare (RemixEnv * env, RemixBase * base)
+{
+ remix_monitor_reset_device (env, base);
+ return base;
+}
+
+static RemixCount
+remix_monitor_write_short (RemixEnv * env, RemixMonitor * monitor, RemixCount count)
+{
+ static struct timeval tv_instant = {0, 0};
+
+ RemixCount n = 0;
+ fd_set fds;
+
+ if (!(monitor->format & AFMT_S16_LE)) {
+ printf ("###### device cannot play AFMT_S16_LE nicely\n");
+ return count;
+ }
+
+ FD_ZERO (&fds);
+ FD_SET (monitor->dev_dsp_fd, &fds);
+
+ if ((select (monitor->dev_dsp_fd + 1, NULL, &fds, NULL, &tv_instant) == 0));
+#if 0
+ {
+ printf ("select error\n");
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return -1;
+ }
+#endif
+
+ n = write (monitor->dev_dsp_fd, monitor->playbuffer, count * sizeof(short));
+ if (n == -1) {
+ printf ("####### system error writing to fd %d #######\n",
+ monitor->dev_dsp_fd);
+
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return -1;
+ }
+
+ return n;
+}
+
+static RemixCount
+remix_monitor_playbuffer (RemixEnv * env, RemixMonitor * monitor, RemixPCM * data,
+ RemixCount count)
+{
+ RemixCount i;
+ RemixPCM value;
+ const RemixPCM max_value = (RemixPCM)SHRT_MAX / 2;
+
+ for (i = 0; i < count; i++) {
+ value = *data++ * max_value;
+ monitor->playbuffer[i] = (short)value;
+ }
+
+ count = remix_monitor_write_short (env, monitor, count);
+
+ return count;
+}
+
+/* An RemixChunkFunc for making noise */
+static RemixCount
+remix_monitor_chunk (RemixEnv * env, RemixChunk * chunk, RemixCount offset,
+ RemixCount count, int channelname, void * data)
+{
+ RemixMonitor * monitor = (RemixMonitor *)data;
+ RemixCount remaining = count, written = 0, n, playcount;
+ RemixPCM * d;
+
+ if (monitor->dev_dsp_fd == -1) {
+ remix_dprintf ("[remix_monitor_chunk] no file\n");
+ remix_set_error (env, REMIX_ERROR_NOENTITY); /* XXX: different error ? */
+ return -1;
+ }
+
+ remix_dprintf ("[remix_monitor_chunk] (%p [chunk %p], +%ld), @ %ld\n",
+ monitor, chunk, count, offset);
+
+ while (remaining > 0) {
+ playcount = MIN (remaining, REMIX_MONITOR_BUFFERLEN);
+ d = &chunk->data[offset];
+ n = remix_monitor_playbuffer (env, monitor, d, playcount);
+
+ if (n == -1) {
+ return -1;
+ } else {
+ n /= sizeof (short);
+ }
+
+ offset += n;
+ written += n;
+ remaining -= n;
+ }
+
+ return written;
+}
+
+static RemixCount
+remix_monitor_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixMonitor * monitor = (RemixMonitor *)base;
+ RemixCount nr_channels = remix_stream_nr_channels (env, input);
+ RemixCount remaining = count, processed = 0, n, nn;
+
+ if (nr_channels == 1 && monitor->stereo == 0) { /* MONO */
+ return remix_stream_chunkfuncify (env, input, count,
+ remix_monitor_chunk, monitor);
+ } else if (nr_channels == 2 && monitor->stereo == 1) { /* STEREO */
+
+ while (remaining > 0) {
+ n = MIN (remaining, REMIX_MONITOR_BUFFERLEN/2);
+ n = remix_stream_interleave_2 (env, input,
+ REMIX_CHANNEL_LEFT, REMIX_CHANNEL_RIGHT,
+ monitor->databuffer, n);
+ nn = 2 * n;
+ nn = remix_monitor_playbuffer (env, monitor, monitor->databuffer, nn);
+
+ processed += n;
+ remaining -= n;
+ }
+ return processed;
+ } else {
+ printf ("[remix_monitor_process] unsupported stream/output channel\n");
+ printf ("combination %ld / %d\n", nr_channels, monitor->stereo ? 2 : 1);
+ return -1;
+ }
+}
+
+static RemixCount
+remix_monitor_length (RemixEnv * env, RemixBase * base)
+{
+ return REMIX_COUNT_INFINITE;
+}
+
+static RemixCount
+remix_monitor_seek (RemixEnv * env, RemixBase * base, RemixCount count)
+{
+ return count;
+}
+
+static int
+remix_monitor_flush (RemixEnv * env, RemixBase * base)
+{
+ RemixMonitor * monitor = (RemixMonitor *)base;
+
+ if (DEBUG_FILE == 1)
+ return 0;
+
+ if (ioctl(monitor->dev_dsp_fd, SNDCTL_DSP_POST, NULL) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct _RemixMethods _remix_monitor_methods = {
+ remix_monitor_clone,
+ remix_monitor_destroy,
+ remix_monitor_ready,
+ remix_monitor_prepare,
+ remix_monitor_process,
+ remix_monitor_length,
+ remix_monitor_seek,
+ remix_monitor_flush,
+};
+
+static RemixMonitor *
+remix_monitor_optimise (RemixEnv * env, RemixMonitor * monitor)
+{
+ _remix_set_methods (env, (RemixBase *)monitor, &_remix_monitor_methods);
+ return monitor;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixNull: A RemixBase with no processing
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * This is a small set of base functions (process, length and seek)
+ * which are useful as optimised versions of an empty container base;
+ * see eg. RemixDeck.
+ * The process function always returns with error REMIX_ERROR_NOOP.
+ * The length function always returns 0
+ * The seek function always returns its argument. Note the seek function
+ * is not needed; you may define an base's seek function as NULL for
+ * the same effect.
+ *
+ * Invariants
+ * ----------
+ *
+ * There is nothing to be invariant about here :)
+ *
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+RemixCount
+remix_null_length (RemixEnv * env, RemixBase * base)
+{
+ return 0;
+}
+
+RemixCount
+remix_null_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ remix_set_error (env, REMIX_ERROR_NOOP);
+ return 0;
+}
+
+RemixCount
+remix_null_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ return offset;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixPCM: generic functions for anonymous blocks of PCM data.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * This file contains only generic functions to manipulate blocks of
+ * RemixPCM data. The RemixPCM type is defined in <remix_types.h>, usually as
+ * a floating point value (float).
+ *
+ * The functions in this file are an excellent target for short vector
+ * machine optimisations.
+ *
+ * Invariants
+ * ----------
+ *
+ * N/A
+ *
+ */
+
+#include <string.h>
+
+#define __REMIX__
+#include "remix.h"
+
+
+/* PFunc */
+
+/*
+ * _remix_pcm_clear_region (data, count)
+ */
+RemixCount
+_remix_pcm_clear_region (RemixPCM * data, RemixCount count, void * unused)
+{
+ memset (data, (RemixPCM)0, count * sizeof (RemixPCM));
+ return count;
+}
+
+
+/* PVFunc */
+
+RemixCount
+_remix_pcm_set (RemixPCM * data, RemixPCM value, RemixCount count)
+{
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *data++ = value;
+ }
+
+ return count;
+}
+
+RemixCount
+_remix_pcm_gain (RemixPCM * data, RemixCount count, void * gain)
+{
+ RemixPCM _gain = *(RemixPCM *)gain;
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *data++ *= _gain;
+ }
+
+ return count;
+}
+
+
+/* PPFunc */
+
+/*
+ * _remix_pcm_copy (src, dest, count)
+ *
+ * Copy PCM data from src to dest.
+ */
+RemixCount
+_remix_pcm_copy (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused)
+{
+ memcpy (dest, src, count * sizeof (RemixPCM));
+ return count;
+}
+
+/*
+ * _remix_pcm_add (src, dest, count)
+ *
+ * Add PCM data from src to dest.
+ */
+RemixCount
+_remix_pcm_add (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused)
+{
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *dest++ += *src++;
+ }
+
+ return count;
+}
+
+/*
+ * _remix_pcm_mult (src, dest, count)
+ *
+ * Multiply PCM data of dest by that in src.
+ */
+RemixCount
+_remix_pcm_mult (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused)
+{
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *dest++ *= *src++;
+ }
+
+ return count;
+}
+
+/*
+ * _remix_pcm_fade (src, dest, count)
+ *
+ * Fade PCM data of dest by that in src.
+ */
+RemixCount
+_remix_pcm_fade (RemixPCM * src, RemixPCM * dest, RemixCount count,
+ void * unused)
+{
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *dest++ *= (1.0 - *src++);
+ }
+
+ return count;
+}
+
+/*
+ * _remix_pcm_interleave_2 (src1, src2, count, dest)
+ *
+ * Interleave data of src1 and src2, storing result in dest
+ */
+RemixCount
+_remix_pcm_interleave_2 (RemixPCM * src1, RemixPCM * src2, RemixCount count,
+ void * data)
+{
+ RemixPCM * dest = (RemixPCM *)data;
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *dest++ = *src1++;
+ *dest++ = *src2++;
+ }
+
+ return count;
+}
+
+/*
+ * _remix_pcm_deinterleave_2 (dest1, dest2, count, src)
+ *
+ * Deinterleave data of src, storing result in dest1 and dest2
+ */
+RemixCount
+_remix_pcm_deinterleave_2 (RemixPCM * dest1, RemixPCM * dest2,
+ RemixCount count, void * data)
+{
+ RemixPCM * src = (RemixPCM *)data;
+ RemixCount i;
+
+ for (i = 0; i < count; i++) {
+ *dest1++ = *src++;
+ *dest2++ = *src++;
+ }
+
+ return count;
+}
+
+/* PPPFunc */
+
+/*
+ * _remix_pcm_blend (src, blend, dest, count)
+ *
+ * Blend PCM data of 'src' into 'dest' by blend values in 'blend'.
+ */
+RemixCount
+_remix_pcm_blend (RemixPCM * src, RemixPCM * blend, RemixPCM * dest,
+ RemixCount count, void * unused)
+{
+ RemixCount i;
+ RemixPCM b, d;
+
+ for (i = 0; i < count; i++) {
+ b = *blend++;
+ d = (*dest * b) + (*src++ * (1.0 - b));
+ *dest++ = d;
+ }
+
+ return count;
+}
+
+
+/* Miscellaneous */
+
+/*
+ * remix_pcm_write_linear (data, x1, y1, x2, y2, offset, count)
+ *
+ * Write 'count' samples at 'data' following line passing through (x1, y1)
+ * and (x2, y2), with writing starting at x = 'offset'.
+ */
+RemixCount
+_remix_pcm_write_linear (RemixPCM * data, RemixCount x1, RemixPCM y1,
+ RemixCount x2, RemixPCM y2,
+ RemixCount offset, RemixCount count)
+{
+ RemixCount i;
+
+ remix_dprintf ("[remix_pcm_write_linear] ((%ld, %f) -> (%ld, %f), %ld +%ld)\n",
+ x1, y1, x2, y2, offset, count);
+
+ for (i = 0; i < count; i++) {
+ *data++ = y1 + (RemixPCM)(i + offset - x1) * (y2 - y1) / (x2 - x1);
+ }
+
+ return count;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixPlugin: A container for RemixBase types.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#define __REMIX__
+#include "remix.h"
+
+static CDList * modules_list = CD_EMPTY_LIST;
+
+static CDList *
+remix_plugin_initialise_static (RemixEnv * env)
+{
+ CDList * plugins = cd_list_new (env);
+
+ plugins = cd_list_join (env, plugins, __gain_init (env));
+
+#ifdef HAVE_LIBSNDFILE1
+ plugins = cd_list_join (env, plugins, __sndfile_init (env));
+#endif
+
+ return plugins;
+}
+
+static CDList *
+remix_plugin_init (RemixEnv * env, const char * path)
+{
+ void * module;
+ CDList * l;
+ RemixPluginInitFunc init;
+
+ module = dlopen (path, RTLD_NOW);
+
+ if (!module) {
+ remix_dprintf ("[remix_plugin_init] Unable to open %s: %s\n", path,
+ dlerror ());
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ return CD_EMPTY_LIST;
+ }
+
+ /* Check that this module has not already been loaded (eg. if it is
+ * a symlink etc.) */
+ for (l = modules_list; l; l = l->next) {
+ if (l->data.s_pointer == module) {
+ dlclose (module);
+ return CD_EMPTY_LIST;
+ }
+ }
+
+ modules_list = cd_list_append (env, modules_list, CD_POINTER(module));
+
+ if ((init = dlsym (module, "remix_load")) != NULL) {
+ return init (env);
+ }
+
+ return CD_EMPTY_LIST;
+}
+
+#define BUFLEN 256
+
+static CDList *
+init_dynamic_plugins_dir (RemixEnv * env, char * dirname)
+{
+ CDList * plugins = cd_list_new (env);
+ DIR * dir;
+ struct dirent * dirent;
+ char * name;
+ static char buf[BUFLEN];
+ struct stat statbuf;
+
+ dir = opendir (dirname);
+ if (!dir) {
+ /* fail silently */
+ return CD_EMPTY_LIST;
+ }
+
+ while ((dirent = readdir (dir)) != NULL) {
+ name = dirent->d_name;
+
+ remix_dprintf ("[init_dynamic_plugins_dir] trying %s ... ", name);
+ snprintf (buf, BUFLEN, "%s/%s", dirname, name);
+
+ if (stat (buf, &statbuf) == -1) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ } else if (remix_stat_regular (statbuf.st_mode)) {
+ plugins = cd_list_join (env, plugins, remix_plugin_init (env, buf));
+ }
+ }
+
+ closedir (dir);
+
+ return plugins;
+}
+
+static CDList *
+remix_plugin_initialise_dynamic (RemixEnv * env)
+{
+ return init_dynamic_plugins_dir (env, PACKAGE_PLUGIN_DIR);
+}
+
+void
+remix_plugin_defaults_initialise (RemixEnv * env)
+{
+ CDList * plugins = cd_list_new (env);
+
+ plugins = cd_list_join (env, plugins, remix_plugin_initialise_static (env));
+ plugins = cd_list_join (env, plugins, remix_plugin_initialise_dynamic (env));
+
+ cd_list_apply (env, plugins, (CDFunc)_remix_register_plugin);
+
+ cd_list_free (env, plugins);
+}
+
+static int
+remix_plugin_unload (RemixEnv * env, void * module)
+{
+ RemixPluginInitFunc unload; /* TODO: make new unload type */
+
+ if ((unload = dlsym (module, "remix_unload")) != NULL) {
+ unload (env);
+ }
+
+ dlclose (module);
+
+ return 0;
+}
+
+void
+remix_plugin_defaults_unload (RemixEnv * env)
+{
+ CDList * l;
+
+ modules_list = cd_list_destroy_with (env, modules_list, (CDDestroyFunc)remix_plugin_unload);
+}
+
+#if 0
+
+RemixPlugin
+remix_plugin_new (void)
+{
+ RemixPlugin plugin = remix_malloc (sizeof (struct _RemixPlugin));
+#if 0
+ plugin->text = remix_meta_text_new ();
+#endif
+ return plugin;
+}
+
+RemixMetaText *
+remix_plugin_get_meta_text (RemixPlugin * plugin)
+{
+ return plugin->text;
+}
+
+RemixMetaText *
+remix_plugin_set_meta_text (RemixPlugin * plugin, RemixMetaText * mt)
+{
+ RemixMetaText * old = plugin->text;
+ plugin->text = mt;
+ return old;
+}
+
+int
+remix_plugin_writeable (RemixPlugin * plugin)
+{
+ return (plugin->flags & REMIX_PLUGIN_WRITEABLE);
+}
+
+int
+remix_plugin_seekable (RemixPlugin * plugin)
+{
+ return (plugin->flags & REMIX_PLUGIN_SEEKABLE);
+}
+
+int
+remix_plugin_cacheable (RemixPlugin * plugin)
+{
+ return (plugin->flags & REMIX_PLUGIN_CACHEABLE);
+}
+
+int
+remix_plugin_causal (RemixPlugin * plugin)
+{
+ return (plugin->flags & REMIX_PLUGIN_CAUSAL);
+}
+
+#endif
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * remix_private.h -- libremix internal data types and functions.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#ifndef __REMIX_PRIVATE_H__
+#define __REMIX_PRIVATE_H__
+
+/*#define DEBUG*/
+
+#if defined(__REMIX__)
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ctxdata.h"
+
+#include "remix_compat.h"
+#include "remix_plugin.h"
+
+/* Max line length for error messages etc. */
+#define REMIX_MAXLINE 4096
+
+#define REMIX_DEFAULT_MIXLENGTH 1024
+#define REMIX_DEFAULT_SAMPLERATE 44100
+#define REMIX_DEFAULT_TEMPO 120
+
+typedef struct _RemixThreadContext RemixThreadContext;
+typedef struct _RemixWorld RemixWorld;
+typedef struct _RemixContext RemixContext;
+
+typedef RemixThreadContext RemixEnv;
+
+typedef struct _RemixPoint RemixPoint;
+typedef struct _RemixEnvelope RemixEnvelope;
+/*typedef struct _RemixChunk RemixChunk;*/
+typedef struct _RemixChannel RemixChannel;
+typedef struct _RemixStream RemixStream;
+typedef struct _RemixDeck RemixDeck;
+typedef struct _RemixTrack RemixTrack;
+typedef struct _RemixLayer RemixLayer;
+typedef struct _RemixSound RemixSound;
+
+
+struct _RemixThreadContext {
+ RemixError last_error;
+ RemixContext * context;
+ RemixWorld * world;
+};
+
+struct _RemixWorld {
+ RemixCount refcount;
+ CDList * plugins;
+ CDList * bases;
+ int purging;
+};
+
+struct _RemixContext {
+ RemixSamplerate samplerate;
+ RemixTempo tempo;
+ CDSet * channels;
+ RemixCount mixlength;
+};
+
+struct _RemixBase {
+ RemixPlugin * plugin;
+ RemixMethods * methods;
+ CDSet * parameters;
+ RemixCount offset; /* current position */
+ RemixContext context_limit;
+ void * instance_data;
+};
+
+struct _RemixPoint {
+ RemixTime time;
+ RemixPCM value;
+};
+
+struct _RemixEnvelope {
+ RemixBase base;
+ RemixEnvelopeType type;
+ RemixTimeType timetype;
+ CDList * points;
+ CDList * _current_point_item;
+ RemixCount _current_offset;
+};
+
+/* XXX: multichannel envelopes ? */
+
+
+struct _RemixStream {
+ RemixBase base;
+ CDSet * channels;
+};
+
+struct _RemixChannel {
+ CDList * chunks;
+ RemixCount _current_offset;
+ CDList * _current_chunk;
+};
+
+struct _RemixDeck {
+ RemixBase base;
+ CDList * tracks;
+ RemixStream * _mixstream;
+};
+
+struct _RemixTrack {
+ RemixBase base;
+ RemixDeck * deck;
+ RemixPCM gain;
+ CDList * layers;
+ RemixStream * _mixstream_a;
+ RemixStream * _mixstream_b;
+};
+
+struct _RemixLayer {
+ RemixBase base;
+ RemixTrack * track;
+ RemixTimeType timetype;
+ CDList * sounds;
+ /*RemixTime _current_time;*/
+ CDList * _current_sound_item;
+ RemixTempo _current_tempo;
+ RemixCount _current_offset;
+};
+
+struct _RemixSound {
+ RemixBase base;
+ RemixBase * source;
+ RemixBase * rate_envelope;
+ RemixBase * gain_envelope;
+ RemixBase * blend_envelope;
+ RemixLayer * layer;
+ RemixTime start_time; /* position in layer */
+ RemixTime duration; /* maximum time length */
+ RemixCount cutin; /* start offset into sound source */
+ RemixCount cutlength;
+ RemixCount _current_source_offset;
+ RemixStream * _rate_envstream;
+ RemixStream * _gain_envstream;
+ RemixStream * _blend_envstream;
+};
+
+typedef struct _RemixMonitor RemixMonitor;
+
+#define REMIX_MONITOR_BUFFERLEN 2048
+
+struct _RemixMonitor {
+ RemixBase base;
+ RemixPCM databuffer[REMIX_MONITOR_BUFFERLEN];
+ short playbuffer[REMIX_MONITOR_BUFFERLEN];
+ int dev_dsp_fd;
+ int mode;
+ int mask;
+ int format;
+ int stereo;
+ int frequency;
+ int numfrags;
+ int fragsize;
+};
+
+#define _remix_time_zero(t) (RemixTime)\
+ (((t)==REMIX_TIME_SAMPLES) ? ((RemixCount)0) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((float)0.0) : \
+ ((int)0)))
+
+#define _remix_time_invalid(t) (RemixTime)\
+ (((t)==REMIX_TIME_SAMPLES) ? ((RemixCount)-1) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((float)-1.0) : \
+ ((int)-1)))
+
+#define _remix_time_is_invalid(t,ti) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((ti).samples < (RemixCount)0) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((ti).seconds < (float)0.0) : \
+ ((ti).beat24s < (int)0)))
+
+#define _remix_time_add(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? REMIX_SAMPLES((t1).samples + (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? REMIX_SECONDS((t1).seconds + (t2).seconds) : \
+ REMIX_BEAT24S((t1).beat24s + (t2).beat24s)))
+
+#define _remix_time_sub(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? REMIX_SAMPLES((t1).samples - (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? REMIX_SECONDS((t1).seconds - (t2).seconds) : \
+ REMIX_BEAT24S((t1).beat24s - (t2).beat24s)))
+
+#define _remix_time_eq(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples == (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds == (t2).seconds) : \
+ ((t1).beat24s == (t2).beat24s)))
+
+#define _remix_time_gt(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples > (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds > (t2).seconds) : \
+ ((t1).beat24s > (t2).beat24s)))
+
+#define _remix_time_lt(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples < (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds < (t2).seconds) : \
+ ((t1).beat24s < (t2).beat24s)))
+
+#define _remix_time_ge(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples >= (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds >= (t2).seconds) : \
+ ((t1).beat24s >= (t2).beat24s)))
+
+#define _remix_time_le(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples <= (t2).samples) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds <= (t2).seconds) : \
+ ((t1).beat24s <= (t2).beat24s)))
+
+#define _remix_time_min(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples < (t2).samples ? (t1) : (t2)) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds < (t2).seconds ? (t1) : (t2)) : \
+ ((t1).beat24s < (t2).beat24s ? (t1) : (t2))))
+
+#define _remix_time_max(t,t1,t2) \
+ (((t)==REMIX_TIME_SAMPLES) ? ((t1).samples > (t2).samples ? (t1) : (t2)) : \
+ (((t)==REMIX_TIME_SECONDS) ? ((t1).seconds > (t2).seconds ? (t1) : (t2)) : \
+ ((t1).beat24s > (t2).beat24s ? (t1) : (t2))))
+
+#define _remix_base_get_samplerate(a,b) (((RemixBase*)b)->context_limit.samplerate)
+#define _remix_base_get_tempo(a,b) (((RemixBase*)b)->context_limit.tempo)
+#define _remix_base_get_mixlength(a,b) (((RemixBase*)b)->context_limit.mixlength)
+#define _remix_base_get_channels(a,b) (((RemixBase*)b)->context_limit.channels)
+
+#define _remix_set_plugin(a,b,p) (((RemixBase*)b)->plugin = (p))
+#define _remix_get_plugin(a,b) (((RemixBase*)b)->plugin)
+#define _remix_set_methods(a,b,m) (((RemixBase*)b)->methods = (m))
+#define _remix_get_methods(a,b) (((RemixBase*)b)->methods)
+#define _remix_set_instance_data(a,b,d) (((RemixBase*)b)->instance_data = (d))
+#define _remix_get_instance_data(a,b) (((RemixBase*)b)->instance_data)
+#define _remix_set_name(a,b,n) (((RemixBase*)b)->name = (n))
+#define _remix_get_name(a,b) (((RemixBase*)b)->name)
+#define _remix_clone(a,b) (((RemixBase*)b)->methods->clone ((a), ((RemixBase*)b)))
+#define _remix_destroy(a,b) (((RemixBase*)b)->methods->destroy ((a), ((RemixBase*)b)))
+#define _remix_prepare(a,b) (((RemixBase*)b)->methods->prepare ((a), ((RemixBase*)b)))
+#define _remix_process(a,b,c,i,o) \
+ (((RemixBase*)b)->methods->process ((a),((RemixBase*)b),(c),(i),(o)))
+#define _remix_length(a,b) (((RemixBase*)b)->methods->length ((a), ((RemixBase*)b)))
+#define _remix_flush(a,b) (((RemixBase*)b)->methods->flush ((a), ((RemixBase*)b)))
+
+
+/* util */
+#define remix_malloc(x) calloc(1, x)
+#define remix_free free
+
+/* debug */
+void remix_debug_down (void);
+void remix_debug_up (void);
+
+/* RemixEnv, remix_context */
+
+RemixBase * remix_base_new_subclass (RemixEnv * env, size_t size);
+
+RemixContext * _remix_context_copy (RemixEnv * env, RemixContext * dest);
+RemixContext * _remix_context_merge (RemixEnv * env, RemixContext * dest);
+RemixEnv * _remix_register_plugin (RemixEnv * env, RemixPlugin * plugin);
+RemixEnv * _remix_unregister_plugin (RemixEnv * env, RemixPlugin * plugin);
+RemixEnv * _remix_register_base (RemixEnv * env, RemixBase * base);
+RemixEnv * _remix_unregister_base (RemixEnv * env, RemixBase * base);
+
+/* remix_plugin */
+void remix_plugin_defaults_initialise (RemixEnv * env);
+void remix_plugin_defaults_unload (RemixEnv * env);
+
+/* remix_deck */
+RemixTrack * _remix_deck_add_track (RemixEnv * env, RemixDeck * deck,
+ RemixTrack * track);
+RemixTrack * _remix_deck_remove_track (RemixEnv * env, RemixDeck * deck,
+ RemixTrack * track);
+
+/* remix_track */
+RemixBase * remix_track_clone (RemixEnv * env, RemixBase * base);
+RemixLayer * _remix_track_add_layer_above (RemixEnv * env, RemixTrack * track,
+ RemixLayer * layer, RemixLayer * above);
+RemixLayer * _remix_track_remove_layer (RemixEnv * env, RemixTrack * track,
+ RemixLayer * layer);
+RemixLayer * _remix_track_get_layer_above (RemixEnv * env, RemixTrack * track,
+ RemixLayer * above);
+RemixLayer * _remix_track_get_layer_below (RemixEnv * env, RemixTrack * track,
+ RemixLayer * below);
+
+/* remix_layer */
+RemixLayer * _remix_remove_layer (RemixEnv * env, RemixLayer * layer);
+RemixBase * remix_layer_clone (RemixEnv * env, RemixBase * base);
+RemixSound * _remix_layer_add_sound (RemixEnv * env, RemixLayer * layer,
+ RemixSound * sound, RemixTime position);
+RemixSound * _remix_layer_remove_sound (RemixEnv * env, RemixLayer * layer,
+ RemixSound * sound);
+RemixSound * _remix_layer_get_sound_prev (RemixEnv * env, RemixLayer * layer,
+ RemixSound * sound);
+RemixSound * _remix_layer_get_sound_next (RemixEnv * env, RemixLayer * layer,
+ RemixSound * sound);
+
+/* remix_sound */
+RemixBase * remix_sound_clone_with_layer (RemixEnv * env, RemixBase * base,
+ RemixLayer * new_layer);
+int remix_sound_later (RemixEnv * env, RemixSound * s1, RemixSound * s2);
+
+/* remix_envelope */
+RemixBase * remix_envelope_clone (RemixEnv * env, RemixBase * base);
+
+
+/* remix_channel */
+RemixChannel * remix_channel_new (RemixEnv * env);
+RemixChannel * remix_channel_clone (RemixEnv * env, RemixChannel * channel);
+int remix_channel_destroy (RemixEnv * env, RemixBase * base);
+
+RemixChunk * remix_channel_add_chunk (RemixEnv * env, RemixChannel * channel,
+ RemixChunk * chunk);
+RemixChunk * remix_channel_add_new_chunk (RemixEnv * env,
+ RemixChannel * channel,
+ RemixCount offset,
+ RemixCount length);
+
+RemixCount remix_channel_write0 (RemixEnv * env, RemixChannel * channel,
+ RemixCount length);
+
+RemixCount _remix_channel_write (RemixEnv * env, RemixChannel * channel,
+ RemixCount count, RemixChannel * data);
+RemixCount _remix_channel_length (RemixEnv * env, RemixChannel * channel);
+RemixCount _remix_channel_seek (RemixEnv * env, RemixChannel * channel,
+ RemixCount offset);
+
+RemixCount remix_channel_interleave_2 (RemixEnv * env,
+ RemixChannel * src1,
+ RemixChannel * src2,
+ RemixPCM * dest, RemixCount count);
+RemixCount remix_channel_deinterleave_2 (RemixEnv * env,
+ RemixChannel * dest1,
+ RemixChannel * dest2,
+ RemixPCM * src, RemixCount count);
+RemixCount remix_channel_mix (RemixEnv * env, RemixChannel * src,
+ RemixChannel * dest, RemixCount count);
+
+
+/* remix_channelset */
+void remix_channelset_defaults_initialise (RemixEnv * env);
+void remix_channelset_defaults_destroy (RemixEnv * env);
+
+/* remix_chunk */
+RemixChunk * remix_chunk_new (RemixEnv * env, RemixCount start_index,
+ RemixCount length);
+RemixChunk * remix_chunk_new_from_buffer (RemixEnv * env,
+ RemixCount start_index,
+ RemixCount length,
+ RemixPCM * buffer);
+RemixChunk * remix_chunk_clone (RemixEnv * env, RemixChunk * chunk);
+void remix_chunk_free (RemixEnv * env, RemixChunk * chunk);
+RemixCount _remix_chunk_clear_region (RemixEnv * env, RemixChunk * chunk,
+ RemixCount start, RemixCount length,
+ int channelname, void * unused);
+RemixCount _remix_chunk_gain (RemixEnv * env, RemixChunk * chunk,
+ RemixCount start, RemixCount count,
+ int channelname, /* (RemixPCM *) */ void * gain);
+RemixCount _remix_chunk_copy (RemixEnv * env, RemixChunk * src,
+ RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname,
+ void * unused);
+RemixCount _remix_chunk_add_inplace (RemixEnv * env, RemixChunk * src,
+ RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname,
+ void * unused);
+RemixCount _remix_chunk_mult_inplace (RemixEnv * env, RemixChunk * src,
+ RemixCount src_offset,
+ RemixChunk * dest,
+ RemixCount dest_offset,
+ RemixCount count, int channelname,
+ void * unused);
+RemixCount _remix_chunk_fade_inplace (RemixEnv * env, RemixChunk * src,
+ RemixCount src_offset,
+ RemixChunk * dest,
+ RemixCount dest_offset,
+ RemixCount count, int channelname,
+ void * unused);
+RemixCount _remix_chunk_interleave_2 (RemixEnv * env,
+ RemixChunk * src1,
+ RemixCount src1_offset,
+ RemixChunk * src2,
+ RemixCount src2_offset,
+ RemixCount count,
+ int unused, void * dest);
+RemixCount _remix_chunk_deinterleave_2 (RemixEnv * env,
+ RemixChunk * dest1,
+ RemixCount dest1_offset,
+ RemixChunk * dest2,
+ RemixCount dest2_offset,
+ RemixCount count,
+ int unused, void * src);
+RemixCount _remix_chunk_blend_inplace (RemixEnv * env,
+ RemixChunk * src, RemixCount src_offset,
+ RemixChunk * blend,
+ RemixCount blend_offset,
+ RemixChunk * dest,
+ RemixCount dest_offset,
+ RemixCount count,
+ int channelname, void * unused);
+
+/* XXX: remove these when dynamic! */
+CDList * __gain_init (RemixEnv * env);
+CDList * __sndfile_init (RemixEnv * env);
+CDList * __ogg_init (RemixEnv * env);
+
+#endif /* defined(__REMIX__) */
+
+#endif /* __REMIX_PRIVATE_H__ */
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixSndfile: a libsndfile handler
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#include <stdio.h>
+#include <sndfile.h>
+#include <string.h>
+
+#define __REMIX__
+#include "remix.h"
+
+#define PATH_KEY 1
+#define BLOCK_FRAMES 4096
+
+typedef struct _RemixSndfileInstance RemixSndfileInstance;
+
+struct _RemixSndfileInstance {
+ char * path;
+ int writing;
+ SNDFILE * file;
+ SF_INFO info;
+ float * pcm;
+ sf_count_t pcm_n;
+ CDSet * channels;
+};
+
+
+/* Optimisation dependencies: none */
+static RemixBase * remix_sndfile_optimise (RemixEnv * env, RemixBase * sndfile);
+
+
+static RemixBase *
+remix_sndfile_create (RemixEnv * env, RemixBase * sndfile,
+ const char * path, int writing)
+{
+ RemixSndfileInstance * si =
+ remix_malloc (sizeof (struct _RemixSndfileInstance));
+
+ si->path = strdup (path);
+ si->writing = writing;
+
+ if (writing) {
+ si->info.samplerate = remix_get_samplerate (env);
+ si->info.channels = 1; /* XXX: how many channels, or specify? */
+ si->info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; /* XXX: assumes WAV */
+
+ si->file = sf_open (path, SFM_WRITE, &si->info);
+ si->pcm = NULL;
+ si->pcm_n = 0;
+ } else {
+ si->file = sf_open (path, SFM_READ, &si->info);
+ si->pcm = (float *) malloc (BLOCK_FRAMES * si->info.channels *
+ sizeof(float));
+ si->pcm_n = 0;
+ }
+
+ if (si->file == NULL) {
+ remix_set_error (env, REMIX_ERROR_SYSTEM);
+ remix_destroy (env, (RemixBase *)sndfile);
+ return RemixNone;
+ }
+
+ sf_command (si->file, SFC_SET_NORM_FLOAT, NULL, SF_TRUE);
+
+ if (writing)
+ sf_command (si->file, SFC_SET_ADD_DITHER_ON_WRITE, NULL, SF_TRUE);
+
+ sndfile->instance_data = si;
+
+ return sndfile;
+}
+
+static RemixBase *
+remix_sndfile_reader_init (RemixEnv * env, RemixBase * base, CDSet * parameters)
+{
+ char * path;
+
+ path = (cd_set_find (env, parameters, PATH_KEY)).s_string;
+
+ if (remix_sndfile_create (env, base, path, 0) == RemixNone)
+ return RemixNone;
+
+ remix_sndfile_optimise (env, base);
+ return base;
+}
+
+static RemixBase *
+remix_sndfile_writer_init (RemixEnv * env, RemixBase * base, CDSet * parameters)
+{
+ char * path;
+
+ path = (cd_set_find (env, parameters, PATH_KEY)).s_string;
+
+ remix_sndfile_create (env, base, path, 1);
+ remix_sndfile_optimise (env, base);
+ return base;
+}
+
+static RemixBase *
+remix_sndfile_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixBase * new_sndfile = remix_base_new (env);
+ RemixSndfileInstance * si = (RemixSndfileInstance *)base->instance_data;
+ remix_sndfile_create (env, new_sndfile, si->path, si->writing);
+ remix_sndfile_optimise (env, new_sndfile);
+ return new_sndfile;
+}
+
+static int
+remix_sndfile_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixSndfileInstance * si = (RemixSndfileInstance *)base->instance_data;
+ if (si->file != NULL) sf_close (si->file);
+ remix_free (si);
+ remix_free (base);
+ return 0;
+}
+
+/* An RemixChunkFunc for creating sndfile */
+
+static RemixCount
+remix_sndfile_read_update (RemixEnv * env, RemixBase * sndfile,
+ RemixCount count)
+{
+ RemixSndfileInstance * si = (RemixSndfileInstance *)sndfile->instance_data;
+
+ si->pcm_n = sf_readf_float (si->file, si->pcm, count);
+
+ return si->pcm_n;
+}
+
+static RemixCount
+remix_sndfile_read_into_chunk (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset, RemixCount count,
+ int channelname, void * data)
+{
+ RemixBase * sndfile = (RemixBase *)data;
+ RemixPCM * d, * p;
+ RemixCount remaining = count, written = 0, n, i;
+ RemixSndfileInstance * si = (RemixSndfileInstance *)sndfile->instance_data;
+
+ remix_dprintf ("[remix_sndfile_read_into_chunk] (%p, +%ld) @ %ld\n",
+ sndfile, count, remix_tell (env, sndfile));
+
+ d = &chunk->data[offset];
+
+ n = MIN (remaining, BLOCK_FRAMES);
+ if (channelname == 0)
+ remix_sndfile_read_update (env, sndfile, n);
+
+ n = MIN (si->pcm_n, remaining);
+
+ p = si->pcm;
+ p += channelname;
+
+ for (i = 0; i < n; i++) {
+ *d++ = *p;
+ p += si->info.channels;
+ }
+
+ if (n == 0) { /* EOF */
+ n = _remix_pcm_set (d, 0.0, remaining);
+ }
+
+ remaining -= n;
+ written += n;
+
+#if 0 /* mono only */
+ d = &chunk->data[offset];
+
+ while (remaining > 0) {
+ n = MIN (remaining, BLOCK_FRAMES);
+ n = sf_readf_float (si->file, d, n);
+
+ if (n == 0) { /* EOF */
+ n = _remix_pcm_set (d, 0.0, remaining);
+ }
+
+ remaining -= n;
+ written += n;
+
+ d += n;
+ }
+#endif
+
+ return written;
+}
+
+static RemixCount
+remix_sndfile_write_from_chunk (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset, RemixCount count,
+ int channelname, void * data)
+{
+ RemixBase * sndfile = (RemixBase *)data;
+ RemixPCM * d;
+ RemixCount remaining = count, read = 0, n;
+ RemixSndfileInstance * si = (RemixSndfileInstance *) sndfile->instance_data;
+
+ remix_dprintf ("[remix_sndfile_write_from_chunk] (%p, +%ld) @ %ld\n",
+ sndfile, count, remix_tell (env, sndfile));
+
+ d = &chunk->data[offset];
+
+ while (remaining > 0) {
+ n = MIN (remaining, BLOCK_FRAMES);
+ n = sf_write_float (si->file, d, n);
+
+ if (n == 0) { /* EOF */
+ n = remaining;
+ }
+
+ remaining -= n;
+ read += n;
+
+ d += n;
+ }
+
+ return read;
+}
+
+static RemixCount
+remix_sndfile_reader_process (RemixEnv * env, RemixBase * base,
+ RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ return remix_stream_chunkfuncify (env, output, count,
+ remix_sndfile_read_into_chunk, base);
+}
+
+static RemixCount
+remix_sndfile_writer_process (RemixEnv * env, RemixBase * base,
+ RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ return remix_stream_chunkfuncify (env, output, count,
+ remix_sndfile_write_from_chunk, base);
+}
+
+static RemixCount
+remix_sndfile_length (RemixEnv * env, RemixBase * base)
+{
+ RemixSndfileInstance * si = (RemixSndfileInstance *)base->instance_data;
+ return si->info.frames;
+}
+
+static RemixCount
+remix_sndfile_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixSndfileInstance * si = (RemixSndfileInstance *)base->instance_data;
+ return sf_seek (si->file, offset, SEEK_SET);
+}
+
+static struct _RemixMethods _remix_sndfile_reader_methods = {
+ remix_sndfile_clone,
+ remix_sndfile_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_sndfile_reader_process,
+ remix_sndfile_length,
+ remix_sndfile_seek,
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_sndfile_writer_methods = {
+ remix_sndfile_clone,
+ remix_sndfile_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_sndfile_writer_process,
+ remix_sndfile_length,
+ remix_sndfile_seek,
+ NULL, /* flush */
+};
+
+static RemixBase *
+remix_sndfile_optimise (RemixEnv * env, RemixBase * sndfile)
+{
+ RemixSndfileInstance * si = (RemixSndfileInstance *)sndfile->instance_data;
+
+ if (si->writing)
+ remix_base_set_methods (env, sndfile, &_remix_sndfile_writer_methods);
+ else
+ remix_base_set_methods (env, sndfile, &_remix_sndfile_reader_methods);
+
+ return sndfile;
+}
+
+
+static struct _RemixParameterScheme path_scheme = {
+ "path",
+ "Path to sound file",
+ REMIX_TYPE_STRING,
+ REMIX_CONSTRAINT_TYPE_NONE,
+ REMIX_CONSTRAINT_EMPTY,
+ REMIX_HINT_FILENAME,
+};
+
+
+static struct _RemixParameterScheme channels_scheme = {
+ "channels",
+ "Channel List to play file",
+ REMIX_TYPE_BOOL,
+ REMIX_CONSTRAINT_TYPE_NONE,
+ REMIX_CONSTRAINT_EMPTY,
+ REMIX_HINT_CHANNEL,
+};
+
+
+#if 0
+static RemixNamedParameter types[] = {
+ REMIX_NAMED_PARAMETER ("WAV", CD_INT(SF_FORMAT_WAV)),
+ REMIX_NAMED_PARAMETER ("AIFF", CD_INT(SF_FORMAT_AIFF)),
+ REMIX_NAMED_PARAMETER ("Sun/NeXT AU format (big endian)", CD_INT(SF_FORMAT_AU)),
+ REMIX_NAMED_PARAMETER ("DEC AU format (little endian)", CD_INT(SF_FORMAT_AULE)),
+ REMIX_NAMED_PARAMETER ("RAW PCM data", CD_INT(SF_FORMAT_RAW)),
+ REMIX_NAMED_PARAMETER ("Ensoniq PARIS", CD_INT(SF_FORMAT_PAF)),
+ REMIX_NAMED_PARAMETER ("Amiga IFF / SVX8 / SV16", CD_INT(SF_FORMAT_SVX)),
+ REMIX_NAMED_PARAMETER ("Sphere NIST", CD_INT(SF_FORMAT_NIST)),
+ REMIX_NAMED_PARAMETER ("Windows Media Audio", CD_INT(SF_FORMAT_WMA)),
+ REMIX_NAMED_PARAMETER ("Sekd Samplitude", CD_INT(SF_FORMAT_SMPLTD)),
+ REMIX_NAMED_PARAMETER ("VOC", CD_INT(SF_FORMAT_VOC)),
+ REMIX_NAMED_PARAMETER ("Sound Designer 2", CD_INT(SF_FORMAT_SD2)),
+ REMIX_NAMED_PARAMETER ("Rex2", CD_INT(SF_FORMAT_REX2)),
+ REMIX_NAMED_PARAMETER ("PCM", CD_INT(SF_FORMAT_PCM)),
+ REMIX_NAMED_PARAMETER ("32 bit floats", CD_INT(SF_FORMAT_FLOAT)),
+ REMIX_NAMED_PARAMETER ("U-Law encoded", CD_INT(SF_FORMAT_ULAW)),
+ REMIX_NAMED_PARAMETER ("A-Law encoded", CD_INT(SF_FORMAT_ALAW)),
+ REMIX_NAMED_PARAMETER ("IMA ADPCM", CD_INT(SF_FORMAT_IMA_ADPCM)),
+ REMIX_NAMED_PARAMETER ("Microsoft ADPCM", CD_INT(SF_FORMAT_MS_ADPCM)),
+ REMIX_NAMED_PARAMETER ("Big endian PCM", CD_INT(SF_FORMAT_PCM_BE)),
+ REMIX_NAMED_PARAMETER ("Little endian PCM", CD_INT(SF_FORMAT_PCM_LE)),
+ REMIX_NAMED_PARAMETER ("Signed 8 bit PCM", CD_INT(SF_FORMAT_PCM_S8)),
+ REMIX_NAMED_PARAMETER ("Unsigned 8 bit PCM", CD_INT(SF_FORMAT_PCM_U8)),
+ REMIX_NAMED_PARAMETER ("SVX Fibonacci Delta", CD_INT(SF_FORMAT_SVX_FIB)),
+ REMIX_NAMED_PARAMETER ("SVX Exponential Delta", CD_INT(SF_FORMAT_SVX_EXP)),
+ REMIX_NAMED_PARAMETER ("GSM 6.10 Encoding", CD_INT(SF_FORMAT_GSM610)),
+ REMIX_NAMED_PARAMETER ("32kbs G721 ADPCM", CD_INT(SF_FORMAT_G721_32)),
+ REMIX_NAMED_PARAMETER ("24kbs G723 ADPCM", CD_INT(SF_FORMAT_G723_24)),
+};
+#endif
+
+static struct _RemixParameterScheme format_scheme = {
+ "format",
+ "Format of sound file",
+ REMIX_TYPE_INT,
+ REMIX_CONSTRAINT_TYPE_LIST,
+ REMIX_CONSTRAINT_EMPTY,
+ REMIX_HINT_DEFAULT,
+};
+
+static struct _RemixMetaText sndfile_reader_metatext = {
+ "builtin::sndfile_reader",
+ "File::Sndfile Reader",
+ "Reads PCM audio files using libsndfile",
+ "Copyright (C) 2001, 2002 CSIRO Australia",
+ "http://www.metadecks.org/software/env/plugins/sndfile.html",
+ REMIX_ONE_AUTHOR ("Conrad Parker", "conrad@metadecks.org"),
+};
+
+static struct _RemixMetaText sndfile_writer_metatext = {
+ "builtin::sndfile_writer",
+ "File::Sndfile Writer",
+ "Writes PCM audio files using libsndfile",
+ "Copyright (C) 2001, 2002 CSIRO Australia",
+ "http://www.metadecks.org/software/env/plugins/sndfile.html",
+ REMIX_ONE_AUTHOR ("Conrad Parker", "conrad@metadecks.org"),
+};
+
+static struct _RemixPlugin sndfile_reader_plugin = {
+ &sndfile_reader_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* init scheme */
+ remix_sndfile_reader_init,
+ CD_EMPTY_SET, /* process scheme */
+ NULL, /* suggests */
+ NULL, /* plugin data */
+ NULL /* destroy */
+};
+
+static struct _RemixPlugin sndfile_writer_plugin = {
+ &sndfile_writer_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* init scheme */
+ remix_sndfile_writer_init,
+ CD_EMPTY_SET, /* process scheme */
+ NULL, /* suggests */
+ NULL, /* plugin data */
+ NULL /* destroy */
+};
+
+/* module init function */
+CDList *
+__sndfile_init (RemixEnv * env)
+{
+ CDList * plugins = cd_list_new (env);
+ int i, count;
+ SF_FORMAT_INFO info;
+ RemixNamedParameter * param;
+
+ sndfile_reader_plugin.init_scheme =
+ cd_set_insert (env, sndfile_reader_plugin.init_scheme, PATH_KEY,
+ CD_POINTER(&path_scheme));
+
+ plugins = cd_list_prepend (env, plugins,
+ CD_POINTER(&sndfile_reader_plugin));
+
+ format_scheme.constraint.list = cd_list_new (env);
+
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int)) ;
+
+ for (i = 0; i < count ; i++) {
+ info.format = i ;
+ sf_command (NULL, SFC_GET_FORMAT_MAJOR, &info, sizeof (info)) ;
+
+ param = remix_malloc (sizeof(RemixNamedParameter));
+ param->name = strdup (info.name);
+ param->parameter = CD_INT(info.format);
+
+ format_scheme.constraint.list =
+ cd_list_append (env, format_scheme.constraint.list, CD_POINTER(param));
+ }
+
+ sndfile_writer_plugin.init_scheme =
+ cd_set_insert (env, sndfile_writer_plugin.init_scheme, PATH_KEY,
+ CD_POINTER(&path_scheme));
+
+ plugins = cd_list_prepend (env, plugins,
+ CD_POINTER(&sndfile_writer_plugin));
+
+ return plugins;
+}
+
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixSound: An instance of an base within an RemixLayer sequence.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A sound is contained within a layer. Each sound is a unique entity, but
+ * many sounds may have the same source base.
+ *
+ * Invariants
+ * ----------
+ *
+ * A sound must be contained in a layer.
+ */
+
+#include <string.h>
+
+#define __REMIX__
+#include "remix.h"
+
+/* Optimisation dependencies: none */
+static RemixSound * remix_sound_optimise (RemixEnv * env, RemixSound * sound);
+
+/*
+ * remix_sound_replace_mixstreams (env, sound)
+ *
+ * Replaces mix- (and envelope-) streams of 'sound' with new ones of
+ * the env's mixlength.
+ */
+static void
+remix_sound_replace_mixstreams (RemixEnv * env, RemixSound * sound)
+{
+ RemixCount mixlength = _remix_base_get_mixlength (env, sound);
+
+ if (sound->_rate_envstream != RemixNone)
+ remix_destroy (env, (RemixBase *)sound->_rate_envstream);
+ if (sound->_gain_envstream != RemixNone)
+ remix_destroy (env, (RemixBase *)sound->_gain_envstream);
+ if (sound->_blend_envstream != RemixNone)
+ remix_destroy (env, (RemixBase *)sound->_blend_envstream);
+
+ sound->_rate_envstream =
+ remix_stream_new_contiguous (env, mixlength);
+ sound->_gain_envstream =
+ remix_stream_new_contiguous (env, mixlength);
+ sound->_blend_envstream =
+ remix_stream_new_contiguous (env, mixlength);
+}
+
+static RemixBase *
+remix_sound_init (RemixEnv * env, RemixBase * base)
+{
+ RemixSound * sound = (RemixSound *)base;
+ sound->rate_envelope = sound->gain_envelope = sound->blend_envelope =
+ RemixNone;
+ sound->cutin = sound->cutlength = 0;
+ sound->_rate_envstream = sound->_gain_envstream = sound->_blend_envstream =
+ RemixNone;
+ remix_sound_replace_mixstreams (env, sound);
+ remix_sound_optimise (env, sound);
+ return (RemixBase *)sound;
+}
+
+static RemixSound *
+_remix_sound_new (RemixEnv * env)
+{
+ return (RemixSound *)
+ remix_base_new_subclass (env, sizeof (struct _RemixSound));
+}
+
+RemixBase *
+remix_sound_clone_invalid (RemixEnv * env, RemixBase * base)
+{
+ RemixSound * sound = (RemixSound *)base;
+ RemixSound * new_sound = _remix_sound_new (env);
+
+ memcpy (new_sound, sound, sizeof (struct _RemixSound));
+ new_sound->layer = RemixNone;
+
+ return (RemixBase *)new_sound;
+}
+
+RemixBase *
+remix_sound_clone_with_layer (RemixEnv * env, RemixBase * base,
+ RemixLayer * new_layer)
+{
+ RemixSound * sound = (RemixSound *)base;
+ RemixSound * new_sound = _remix_sound_new (env);
+
+ memcpy (new_sound, sound, sizeof (struct _RemixSound));
+ new_sound->layer = new_layer;
+ _remix_layer_add_sound (env, new_layer, new_sound, new_sound->start_time);
+
+ return (RemixBase *)new_sound;
+}
+
+/* XXX: This breaks sound invariant */
+RemixSound *
+_remix_sound_remove (RemixEnv * env, RemixSound * sound)
+{
+ if (sound->layer == RemixNone) return RemixNone;
+ return _remix_layer_remove_sound (env, sound->layer, sound);
+}
+
+
+static int
+remix_sound_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixSound * sound = (RemixSound *)base;
+
+ _remix_sound_remove (env, sound);
+
+ if (sound->rate_envelope)
+ remix_destroy (env, sound->rate_envelope);
+ if (sound->gain_envelope)
+ remix_destroy (env, sound->gain_envelope);
+ if (sound->blend_envelope)
+ remix_destroy (env, sound->blend_envelope);
+ if (sound->_rate_envstream)
+ remix_destroy (env, (RemixBase *)sound->_rate_envstream);
+ if (sound->_gain_envstream)
+ remix_destroy (env, (RemixBase *)sound->_gain_envstream);
+ if (sound->_blend_envstream)
+ remix_destroy (env, (RemixBase *)sound->_blend_envstream);
+ remix_free (sound);
+
+ return 0;
+}
+
+static int
+remix_sound_ready (RemixEnv * env, RemixBase * base)
+{
+ return 0;
+}
+
+static RemixBase *
+remix_sound_prepare (RemixEnv * env, RemixBase * base)
+{
+ RemixSound * sound = (RemixSound *)base;
+ remix_sound_replace_mixstreams (env, sound);
+ return base;
+}
+
+RemixBase *
+remix_sound_set_source (RemixEnv * env, RemixSound * sound, RemixBase * source)
+{
+ RemixBase * old = sound->source;
+ sound->source = source;
+ return old;
+}
+
+RemixBase *
+remix_sound_get_source (RemixEnv * env, RemixSound * sound)
+{
+ return sound->source;
+}
+
+RemixSound *
+remix_sound_new (RemixEnv * env, RemixBase * source, RemixLayer * layer,
+ RemixTime start_time, RemixTime duration)
+{
+ RemixSound * sound = _remix_sound_new (env);
+
+ sound->layer = layer;
+ sound->start_time = start_time;
+ sound->duration = duration;
+ _remix_layer_add_sound (env, layer, sound, start_time);
+ sound->source = source;
+ remix_sound_init (env, (RemixBase *)sound);
+ return sound;
+}
+
+RemixLayer *
+remix_sound_get_layer (RemixEnv * env, RemixSound * sound)
+{
+ return sound->layer;
+}
+
+RemixTrack *
+remix_sound_get_track (RemixEnv * env, RemixSound * sound)
+{
+ if (sound->layer == RemixNone) return RemixNone;
+ return remix_layer_get_track (env, sound->layer);
+}
+
+RemixDeck *
+remix_sound_get_deck (RemixEnv * env, RemixSound * sound)
+{
+ if (sound->layer == RemixNone) return RemixNone;
+ return remix_layer_get_deck (env, sound->layer);
+}
+
+RemixTime
+remix_sound_move (RemixEnv * env, RemixSound * sound, RemixTime start_time)
+{
+ RemixTime old = sound->start_time;
+ RemixLayer * layer = sound->layer;
+ if (_remix_sound_remove (env, sound) != RemixNone) {
+ _remix_layer_add_sound (env, layer, sound, start_time);
+ return old;
+ } else {
+ return _remix_time_invalid (sound->layer->timetype);
+ }
+}
+
+RemixSound *
+remix_sound_get_prev (RemixEnv * env, RemixSound * sound)
+{
+ if (sound->layer)
+ return _remix_layer_get_sound_prev (env, sound->layer, sound);
+ else
+ return RemixNone;
+}
+
+RemixSound *
+remix_sound_get_next (RemixEnv * env, RemixSound * sound)
+{
+ if (sound->layer)
+ return _remix_layer_get_sound_next (env, sound->layer, sound);
+ else
+ return RemixNone;
+}
+
+int
+remix_sound_later (RemixEnv * env, RemixSound * s1, RemixSound * s2)
+{
+ RemixLayer * layer = remix_sound_get_layer (env, s1);
+ return _remix_time_gt (layer->timetype, s1->start_time, s2->start_time);
+}
+
+RemixTime
+remix_sound_set_start_time (RemixEnv * env, RemixSound * sound,
+ RemixTime start_time)
+{
+ RemixTime old = sound->start_time;
+ RemixLayer * layer = sound->layer;
+ _remix_layer_remove_sound (env, layer, sound);
+ _remix_layer_add_sound (env, layer, sound, start_time);
+ return old;
+}
+
+RemixTime
+remix_sound_get_start_time (RemixEnv * env, RemixSound * sound)
+{
+ return sound->start_time;
+}
+
+RemixTime
+remix_sound_set_duration (RemixEnv * env, RemixSound * sound,
+ RemixTime duration)
+{
+ RemixTime old = sound->duration;
+ sound->duration = duration;
+ return old;
+}
+
+RemixTime
+remix_sound_get_duration (RemixEnv * env, RemixSound * sound)
+{
+ return sound->duration;
+}
+
+RemixBase *
+remix_sound_set_rate_envelope (RemixEnv * env, RemixSound * sound,
+ RemixBase * rate_envelope)
+{
+ RemixBase * old = sound->rate_envelope;
+ sound->rate_envelope = rate_envelope;
+ return old;
+}
+
+RemixBase *
+remix_sound_get_rate_envelope (RemixEnv * env, RemixSound * sound)
+{
+ if (sound == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return RemixNone;
+ }
+ return sound->rate_envelope;
+}
+
+RemixBase *
+remix_sound_set_gain_envelope (RemixEnv * env, RemixSound * sound,
+ RemixBase * gain_envelope)
+{
+ RemixBase * old;
+
+ if (sound == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return RemixNone;
+ }
+ old = sound->gain_envelope;
+ sound->gain_envelope = gain_envelope;
+
+ return old;
+}
+
+RemixBase *
+remix_sound_get_gain_envelope (RemixEnv * env, RemixSound * sound)
+{
+ if (sound == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return RemixNone;
+ }
+ return sound->gain_envelope;
+}
+
+RemixBase *
+remix_sound_set_blend_envelope (RemixEnv * env, RemixSound * sound,
+ RemixBase * blend_envelope)
+{
+ RemixBase * old = sound->blend_envelope;
+ sound->blend_envelope = blend_envelope;
+ return old;
+}
+
+RemixBase *
+remix_sound_get_blend_envelope (RemixEnv * env, RemixSound * sound)
+{
+ if (sound == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return RemixNone;
+ }
+ return sound->blend_envelope;
+}
+
+static RemixCount
+_remix_sound_fade (RemixEnv * env, RemixSound * sound, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixCount output_offset, n;
+
+ output_offset = remix_tell (env, (RemixBase *)output);
+
+ /* XXX: this wanted to use 'block' not 'count': have we bounds
+ * checked the sound ?? */
+
+ remix_seek (env, (RemixBase *)sound->_blend_envstream, 0, SEEK_SET);
+ n = remix_process (env, sound->blend_envelope, count, RemixNone,
+ sound->_blend_envstream);
+ remix_stream_write (env, output, count, input);
+ remix_seek (env, (RemixBase *)sound->_blend_envstream, 0, SEEK_SET);
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = remix_stream_fade (env, sound->_blend_envstream, output, count);
+
+ return n;
+}
+
+/* Do rate conversion, handle offset etc.: get raw sound data */
+static RemixCount
+_remix_sound_get_raw (RemixEnv * env, RemixSound * sound, RemixCount offset,
+ RemixCount count, RemixStream * input,
+ RemixStream * output)
+{
+ RemixCount block, n;
+
+ remix_dprintf ("[_remix_sound_get_raw] (%p, +%ld, %p -> %p) @ %ld\n",
+ sound, count, input, output, offset);
+
+ /* XXX: deal with rate conversion!! */
+
+ if (sound->cutlength > 0) {
+ if (offset > sound->cutlength) {
+ remix_set_error (env, REMIX_ERROR_SILENCE);
+ return -1;
+ }
+ block = MIN (count, sound->cutlength - offset);
+ } else {
+ block = count;
+ }
+
+ remix_dprintf ("[_remix_sound_get_raw] block +%ld (cutin: %ld, cutlength: %ld)\n",
+ block, sound->cutin, sound->cutlength);
+
+ remix_seek (env, sound->source, sound->cutin + offset, SEEK_SET);
+ n = remix_process (env, sound->source, block, input, output);
+
+ if (n == -1) {
+ remix_dprintf ("error getting source data: %s\n",
+ remix_error_string(env, remix_last_error(env)));
+ } else {
+
+ if (block < count)
+ n += remix_stream_write0 (env, output, count - block);
+ }
+
+ remix_dprintf ("[_remix_sound_get_raw] got %ld raw samples\n", n);
+
+ return n;
+}
+
+static RemixCount
+_remix_sound_apply_gain (RemixEnv * env, RemixSound * sound,
+ RemixCount offset, RemixCount count,
+ RemixStream * data, RemixCount data_offset)
+{
+ RemixCount n;
+
+ remix_dprintf ("in _remix_sound_apply_gain (%p, +%ld)\n", sound, count);
+
+ remix_seek (env, sound->gain_envelope, offset, SEEK_SET);
+ remix_seek (env, (RemixBase *)sound->_gain_envstream, 0, SEEK_SET);
+ n = remix_process (env, sound->gain_envelope, count,
+ RemixNone, sound->_gain_envstream);
+ remix_dprintf ("Got %ld values from gain_envelope %p onto stream %p\n",
+ n, sound->gain_envelope, sound->_gain_envstream);
+
+ remix_seek (env, (RemixBase *)data, data_offset, SEEK_SET);
+ remix_seek (env, (RemixBase *)sound->_gain_envstream, 0, SEEK_SET);
+ n = remix_stream_mult (env, sound->_gain_envstream, data, n);
+ remix_dprintf ("Multiplied %ld values of gain\n", n);
+
+ return n;
+}
+
+static RemixCount
+_remix_sound_blend (RemixEnv * env, RemixSound * sound, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixCount n;
+
+ /* XXX: this wanted to use 'block' not 'count': have we bounds
+ * checked the sound ?? */
+
+ remix_seek (env, (RemixBase * )sound->_blend_envstream, 0, SEEK_SET);
+ n = remix_process (env, sound->blend_envelope, count, RemixNone,
+ sound->_blend_envstream);
+ remix_seek (env, (RemixBase *)sound->_blend_envstream, 0, SEEK_SET);
+ n = remix_stream_blend (env, input, sound->_blend_envstream, output,
+ count);
+
+ return n;
+}
+
+static RemixCount
+remix_sound_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixSound * sound = (RemixSound *)base;
+ RemixCount remaining = count, processed = 0, block, m, n;
+ RemixCount offset, input_offset, output_offset;
+ RemixCount mixlength = _remix_base_get_mixlength (env, sound);
+
+ offset = remix_tell (env, (RemixBase *)sound);
+
+ remix_dprintf ("PROCESS SOUND (%p [%p], +%ld, %p -> %p) @ %ld\n",
+ sound, sound ? sound->source : NULL, count, input, output, offset);
+
+ /* if we're beyond the source's actual length, then
+ * just fade the input to the output using the sound's blend
+ * envelope */
+ if (offset > remix_length (env, sound->source)) {
+ remix_dprintf ("## offset %ld > length %ld\n", offset,
+ remix_length (env, sound->source));
+
+ /* Fade input and copy to output */
+ if (sound->blend_envelope == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOOP);
+ return -1;
+ } else {
+ return _remix_sound_fade (env, sound, count, input, output);
+ }
+ }
+
+ while (remaining > 0) {
+ block = MIN (remaining, mixlength);
+
+ input_offset = remix_tell (env, (RemixBase *)input);
+ output_offset = remix_tell (env, (RemixBase *)output);
+
+ /* Get raw sound data; handle rate conversion etc. */
+ m = _remix_sound_get_raw (env, sound, offset, block, input, output);
+ if (m == -1) {
+ remix_dprintf ("error getting raw sound data\n");
+ break;
+ } else {
+ n = m;
+ }
+
+ /* Apply gain envelope */
+ if (sound->gain_envelope != RemixNone) {
+ m = _remix_sound_apply_gain (env, sound, offset, n, output, output_offset);
+ if (m == -1) {
+ remix_dprintf ("error applying gain!\n");
+ } else {
+ n = m;
+ }
+ }
+
+ /* Blend input back in */
+ if (sound->blend_envelope != RemixNone) {
+ remix_seek (env, (RemixBase *)input, input_offset, SEEK_SET);
+ remix_seek (env, (RemixBase *)output, output_offset, SEEK_SET);
+ n = _remix_sound_blend (env, sound, n, input, output);
+ }
+
+ offset += n;
+ processed += n;
+ remaining -= n;
+ }
+
+ remix_dprintf ("[remix_sound_process] processed %ld from sound %p\n",
+ processed, sound);
+
+ return processed;
+}
+
+static RemixCount
+remix_sound_length (RemixEnv * env, RemixBase * base)
+{
+ RemixSound * sound = (RemixSound *)base;
+ RemixTime duration = remix_sound_get_duration (env, sound);
+ RemixTime t = remix_time_convert (env, duration, sound->layer->timetype,
+ REMIX_TIME_SAMPLES);
+ return t.samples;
+}
+
+static RemixCount
+remix_sound_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixSound * sound = (RemixSound *)base;
+ if (sound->cutlength > 0 && offset > sound->cutlength) {
+ offset = sound->cutlength;
+ }
+ remix_seek (env, sound->source, sound->cutin + offset, SEEK_SET);
+ return offset;
+}
+
+static int
+remix_sound_flush (RemixEnv * env, RemixBase * base)
+{
+ RemixSound * sound = (RemixSound *)base;
+ return remix_flush (env, sound->source);
+}
+
+static struct _RemixMethods _remix_sound_methods = {
+ remix_sound_clone_invalid, /* clone */
+ remix_sound_destroy, /* destroy */
+ remix_sound_ready, /* ready */
+ remix_sound_prepare, /* prepare */
+ remix_sound_process, /* process */
+ remix_sound_length, /* length */
+ remix_sound_seek, /* seek */
+ remix_sound_flush, /* flush */
+};
+
+static RemixSound *
+remix_sound_optimise (RemixEnv * env, RemixSound * sound)
+{
+ _remix_set_methods (env, sound, &_remix_sound_methods);
+ return sound;
+}
+
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixSquareTone: a square wave tone generator
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+typedef struct _RemixSquareToneChannelData RemixSquareToneChannelData;
+typedef struct _RemixSquareTone RemixSquareTone;
+
+struct _RemixSquareToneChannelData {
+ RemixCount _cycle_offset;
+};
+
+struct _RemixSquareTone {
+ RemixBase base;
+ float frequency;
+ CDSet * channel_data;
+ CDSet * channels;
+};
+
+/* Optimisation dependencies: none */
+static RemixSquareTone * remix_squaretone_optimise (RemixEnv * env,
+ RemixSquareTone * squaretone);
+
+static RemixSquareTone *
+remix_squaretone_replace_channels (RemixEnv * env, RemixSquareTone * squaretone)
+{
+ RemixSquareToneChannelData * sqch;
+ CDSet * s, * channels = remix_get_channels (env);
+ RemixCount offset = remix_tell (env, (RemixBase *)squaretone);
+
+ cd_set_free_all (env, squaretone->channel_data);
+
+ for (s = channels; s; s = s->next) {
+ remix_dprintf ("[remix_squaretone_replace_channels] %p replacing channel %d\n",
+ squaretone, s->key);
+ sqch = (RemixSquareToneChannelData *)
+ remix_malloc (sizeof (struct _RemixSquareToneChannelData));
+ sqch->_cycle_offset = 0;
+ squaretone->channel_data =
+ cd_set_insert (env, squaretone->channel_data, s->key, CD_POINTER(sqch));
+ }
+
+ if (offset > 0) remix_seek (env, (RemixBase *)squaretone, offset, SEEK_SET);
+
+ return squaretone;
+}
+
+static RemixBase *
+remix_squaretone_init (RemixEnv * env, RemixBase * base)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ squaretone->channel_data = NULL;
+ remix_squaretone_replace_channels (env, squaretone);
+ remix_squaretone_optimise (env, squaretone);
+ return base;
+}
+
+RemixBase *
+remix_squaretone_new (RemixEnv * env, float frequency)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)
+ remix_base_new_subclass (env, sizeof (struct _RemixSquareTone));
+ remix_squaretone_init (env, (RemixBase *)squaretone);
+ squaretone->frequency = frequency;
+
+ return (RemixBase *)squaretone;
+}
+
+static RemixBase *
+remix_squaretone_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ RemixBase * new_squaretone =
+ remix_squaretone_new (env, squaretone->frequency);
+ remix_squaretone_optimise (env, (RemixSquareTone *)new_squaretone);
+ return new_squaretone;
+}
+
+static int
+remix_squaretone_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ remix_free (squaretone);
+ return 0;
+}
+
+static int
+remix_squaretone_ready (RemixEnv * env, RemixBase * base)
+{
+ return (remix_base_has_samplerate (env, base) &&
+ remix_base_encompasses_channels (env, base));
+}
+
+static RemixBase *
+remix_squaretone_prepare (RemixEnv * env, RemixBase * base)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ remix_squaretone_replace_channels (env, squaretone);
+ return base;
+}
+
+float
+remix_squaretone_set_frequency (RemixEnv * env, RemixBase * base,
+ float frequency)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ float old = squaretone->frequency;
+ squaretone->frequency = frequency;
+ return old;
+}
+
+float
+remix_squaretone_get_frequency (RemixEnv * env, RemixBase * base)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ return squaretone->frequency;
+}
+
+void
+remix_squaretone_add_channel (RemixEnv * env, RemixBase * base, RemixChannelName channel )
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ squaretone->channels = cd_set_replace (env, squaretone->channels, channel, CD_POINTER(NULL));;
+}
+
+void
+remix_squaretone_remove_channel (RemixEnv * env, RemixBase * base, RemixChannelName channel )
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ squaretone->channels = cd_set_remove(env, squaretone->channels, channel );
+}
+
+CDSet *
+remix_squaretone_get_channels (RemixEnv * env, RemixBase * base )
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ return squaretone->channels;
+}
+
+
+/* An RemixChunkFunc for creating squaretone data */
+static RemixCount
+remix_squaretone_write_chunk (RemixEnv * env, RemixChunk * chunk,
+ RemixCount offset, RemixCount count,
+ int channelname, void * data)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)data;
+ RemixSquareToneChannelData * sqch;
+ RemixCount remaining = count, written = 0, n;
+ RemixCount wavelength;
+ RemixPCM * d, value;
+ CDScalar k;
+ int channel_enabled = 0;
+
+ remix_dprintf ("[remix_squaretone_write_chunk] (+%ld) @ %ld\n",
+ count, offset);
+
+ k = cd_set_find (env, squaretone->channel_data, channelname);
+ sqch = k.s_pointer;
+
+ channel_enabled = cd_set_contains (env, squaretone->channels, channelname);
+
+ if (sqch == RemixNone) {
+ remix_dprintf ("[remix_squaretone_write_chunk] channel %d not found\n",
+ channelname);
+ remix_set_error (env, REMIX_ERROR_SILENCE);
+ return -1;
+ }
+
+ wavelength = (RemixCount)(remix_get_samplerate (env) / squaretone->frequency);
+
+ remix_dprintf ("[remix_squaretone_write_chunk] wavelength %ld, cycle_offset %ld\n",
+ wavelength, sqch->_cycle_offset);
+
+ if (sqch->_cycle_offset < wavelength/2) {
+ n = MIN (remaining, wavelength/2 - sqch->_cycle_offset);
+ value = 1.0;
+ } else {
+ n = MIN (remaining, wavelength - sqch->_cycle_offset);
+ value = -1.0;
+ }
+
+ if(!channel_enabled ) value = 0;
+
+ d = &chunk->data[offset];
+ _remix_pcm_set (d, value, n);
+ remaining -= n; written += n; offset += n;
+
+ while (remaining > 0) {
+ n = MIN (remaining, wavelength/2);
+ value = -(value);
+ d = &chunk->data[offset];
+ _remix_pcm_set (d, value, n);
+ remaining -= n; written += n; offset += n;
+ }
+
+ sqch->_cycle_offset += written;
+ sqch->_cycle_offset %= wavelength;
+
+ remix_dprintf ("[remix_squaretone_write_chunk] written %ld\n", written);
+
+ return written;
+}
+
+static RemixCount
+remix_squaretone_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ return remix_stream_chunkfuncify (env, output, count,
+ remix_squaretone_write_chunk, squaretone);
+}
+
+static RemixCount
+remix_squaretone_length (RemixEnv * env, RemixBase * base)
+{
+ return REMIX_COUNT_INFINITE;
+}
+
+static RemixCount
+remix_squaretone_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixSquareTone * squaretone = (RemixSquareTone *)base;
+ RemixCount wavelength;
+ CDSet * s;
+ RemixCount cycle_offset;
+ RemixSquareToneChannelData * sqch;
+
+ wavelength = (RemixCount)(remix_get_samplerate (env) / squaretone->frequency);
+ cycle_offset = offset % wavelength;
+
+ for (s = squaretone->channel_data; s; s = s->next) {
+ sqch = (RemixSquareToneChannelData *)s->data.s_pointer;
+ sqch->_cycle_offset = cycle_offset;
+ }
+
+ return offset;
+}
+
+static struct _RemixMethods _remix_squaretone_methods = {
+ remix_squaretone_clone,
+ remix_squaretone_destroy,
+ remix_squaretone_ready,
+ remix_squaretone_prepare,
+ remix_squaretone_process,
+ remix_squaretone_length,
+ remix_squaretone_seek,
+ NULL, /* flush */
+};
+
+static RemixSquareTone *
+remix_squaretone_optimise (RemixEnv * env, RemixSquareTone * squaretone)
+{
+ _remix_set_methods (env, squaretone, &_remix_squaretone_methods);
+ return squaretone;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixStream: An indexed, sparse, polyphonic PCM data container.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A stream consists of multiple channels of PCM data.
+ *
+ * Invariants
+ * ----------
+ *
+ * A stream is an independent entity.
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+/* RemixStream */
+
+/* Optimisation dependencies: none */
+static RemixStream * remix_stream_optimise (RemixEnv * env,
+ RemixStream * stream);
+
+RemixBase *
+remix_stream_init (RemixEnv * env, RemixBase * base)
+{
+ RemixStream * stream = (RemixStream *)base;
+ CDSet * s, * channels = remix_get_channels (env);
+
+ stream->channels = cd_set_new (env);
+
+ for (s = channels; s; s = s->next) {
+ remix_stream_add_channel (env, stream, s->key);
+ }
+
+ remix_stream_optimise (env, stream);
+ return (RemixBase *)stream;
+}
+
+static RemixStream *
+remix_stream_add_channel_unchecked (RemixEnv * env, RemixStream * stream,
+ int name, RemixChannel * channel)
+{
+ stream->channels = cd_set_insert (env, stream->channels, name,
+ CD_POINTER(channel));
+ return stream;
+}
+
+RemixChannel *
+remix_stream_add_channel (RemixEnv * env, RemixStream * stream, int name)
+{
+ RemixChannel * channel = remix_stream_find_channel (env, stream, name);
+
+ if (channel == RemixNone) {
+ channel = remix_channel_new (env);
+ remix_stream_add_channel_unchecked (env, stream, name, channel);
+ }
+
+ return channel;
+}
+
+RemixStream *
+remix_stream_new (RemixEnv * env)
+{
+ RemixStream * stream =
+ (RemixStream *)remix_base_new_subclass (env, sizeof (struct _RemixStream));
+
+ remix_stream_init (env, (RemixBase *)stream);
+
+ return stream;
+}
+
+RemixStream *
+remix_stream_new_contiguous (RemixEnv * env, RemixCount length)
+{
+ RemixStream * stream = remix_stream_new (env);
+ remix_stream_add_chunks (env, stream, 0, length);
+ return stream;
+}
+
+RemixStream *
+remix_stream_new_from_buffers (RemixEnv * env, RemixCount length,
+ RemixPCM ** buffers)
+{
+ CDSet * s;
+ RemixStream * stream = remix_stream_new (env);
+ RemixChannel * channel;
+ RemixChunk * chunk;
+ int i = 0;
+
+ for (s = stream->channels; s; s = s->next) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ chunk = remix_chunk_new_from_buffer (env, 0, length, buffers[i++]);
+ remix_channel_add_chunk (env, channel, chunk);
+ }
+
+ return stream;
+}
+
+static RemixBase *
+remix_stream_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixStream * stream = (RemixStream *)base;
+ RemixStream * new_stream;
+ CDSet * s;
+ RemixChannel * channel, * new_channel;
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ new_stream = (RemixStream *)remix_stream_new (env);
+
+ /* clone channels */
+ for (s = stream->channels; s; s = s->next) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ new_channel = remix_channel_clone (env, channel);
+ remix_stream_add_channel_unchecked (env, new_stream, s->key, new_channel);
+ }
+ return (RemixBase *)new_stream;
+}
+
+static int
+remix_stream_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixStream * stream = (RemixStream *)base;
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ cd_set_destroy_with (env, stream->channels, (CDDestroyFunc)remix_destroy);
+
+ remix_free (stream);
+ return 0;
+}
+
+RemixCount
+remix_stream_nr_channels (RemixEnv * env, RemixStream * stream)
+{
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ return (RemixCount)cd_set_size (env, stream->channels);
+}
+
+RemixChannel *
+remix_stream_find_channel (RemixEnv * env, RemixStream * stream, int name)
+{
+ CDScalar k;
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ k = cd_set_find (env, stream->channels, name);
+ return (RemixChannel *)k.s_pointer;
+}
+
+
+RemixStream *
+remix_stream_remove_channel (RemixEnv * env, RemixStream * stream, int name)
+{
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ stream->channels = cd_set_remove (env, stream->channels, name);
+
+ return stream;
+}
+
+RemixStream *
+remix_stream_add_chunks (RemixEnv * env, RemixStream * stream,
+ RemixCount offset, RemixCount length)
+{
+ CDSet * s;
+ RemixChannel * channel;
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ for (s = stream->channels; s; s = s->next) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ remix_channel_add_new_chunk (env, channel, offset, length);
+ }
+
+ return stream;
+}
+
+RemixCount
+remix_stream_write0 (RemixEnv * env, RemixStream * stream, RemixCount count)
+{
+ CDSet * s;
+ RemixChannel * channel;
+ RemixCount offset;
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ offset = remix_tell (env, (RemixBase *)stream);
+
+ for (s = stream->channels; s; s = s->next) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ remix_channel_write0 (env, channel, count);
+ }
+
+ remix_seek (env, (RemixBase *)stream, offset + count, SEEK_SET);
+
+ remix_dprintf ("[remix_stream_write0] (%p) written %ld\n", stream, count);
+
+ return count;
+}
+
+/*
+ * remix_stream_process (env, stream, count, input, output)
+ *
+ * RemixProcessFunc for RemixStream.
+ * Ignores input. Copies data from 'stream' to 'output'.
+ */
+static RemixCount
+remix_stream_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixStream * stream = (RemixStream *)base;
+ return remix_stream_write (env, output, count, stream);
+}
+
+static RemixCount
+remix_stream_length (RemixEnv * env, RemixBase * base)
+{
+ RemixStream * stream = (RemixStream *)base;
+ RemixCount length, maxlength = 0;
+ CDSet * s;
+ RemixChannel * channel;
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ for (s = stream->channels; s; s = s->next) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ length = _remix_channel_length (env, channel);
+ maxlength = MAX (maxlength, length);
+ }
+
+ return maxlength;
+}
+
+static RemixCount
+remix_stream_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixStream * stream = (RemixStream *)base;
+ CDSet * s;
+ RemixChannel * channel;
+
+ for (s = stream->channels; s; s = s->next) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ _remix_channel_seek (env, channel, offset);
+ }
+
+ return offset;
+}
+
+static struct _RemixMethods _remix_stream_methods = {
+ remix_stream_clone,
+ remix_stream_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_stream_process,
+ remix_stream_length,
+ remix_stream_seek,
+};
+
+static RemixStream *
+remix_stream_optimise (RemixEnv * env, RemixStream * stream)
+{
+ _remix_set_methods (env, stream, &_remix_stream_methods);
+ return stream;
+}
+
+
+/*
+ * remix_stream_chunkfuncify (stream, count, func, data)
+ *
+ */
+RemixCount
+remix_stream_chunkfuncify (RemixEnv * env, RemixStream * stream,
+ RemixCount count,
+ RemixChunkFunc func, void * data)
+{
+ RemixCount n, minn = count, offset = remix_tell (env, (RemixBase *)stream);
+ CDSet * s, * channels = remix_get_channels (env);
+ RemixChannel * channel;
+
+ for (s = channels; s; s = s->next) {
+ remix_dprintf ("[remix_stream_chunkfuncify] thinking of channel %d\n",
+ s->key);
+ }
+
+ if (stream == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ remix_dprintf ("[remix_stream_chunkfuncify] (%p, +%ld) @ %ld\n",
+ stream, count, offset);
+
+ for (s = stream->channels; s; s = s->next) {
+ if (cd_set_contains (env, channels, s->key)) {
+ channel = (RemixChannel *)s->data.s_pointer;
+ n = remix_channel_chunkfuncify (env, channel, minn, func, s->key, data);
+ minn = MIN (n, minn);
+ } else {
+ remix_dprintf ("[remix_stream_chunkfuncify] channel %d not funced\n", s->key);
+ }
+ }
+
+ remix_seek (env, (RemixBase *)stream, offset + minn, SEEK_SET);
+
+ return minn;
+}
+
+RemixCount
+remix_stream_chunkchunkfuncify (RemixEnv * env, RemixStream * src,
+ RemixStream * dest, RemixCount count,
+ RemixChunkChunkFunc func, void * data)
+{
+ RemixCount n, minn = count;
+ RemixCount src_offset = remix_tell (env, (RemixBase *)src);
+ RemixCount dest_offset = remix_tell (env, (RemixBase *)dest);
+ CDSet * s, * channels = remix_get_channels (env);
+ RemixChannel * sch, * dch;
+
+ if (dest == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ remix_dprintf ("[remix_stream_ccf...] (%p -> %p, +%ld), src @ %ld, dest @ %ld\n",
+ src, dest, count, src_offset, dest_offset);
+
+ for (s = dest->channels; s; s = s->next) {
+ if (cd_set_contains (env, channels, s->key)) {
+ dch = (RemixChannel *)s->data.s_pointer;
+ sch = remix_stream_find_channel (env, src, s->key);
+ if (sch != RemixNone) {
+ n = remix_channel_chunkchunkfuncify (env, sch, dch, count, func, s->key,
+ data);
+ if (n == -1) {
+ return -1;
+ }
+
+ minn = MIN (n, minn);
+ }
+ }
+ }
+
+ remix_seek (env, (RemixBase *)src, src_offset + minn, SEEK_SET);
+ remix_seek (env, (RemixBase *)dest, dest_offset + minn, SEEK_SET);
+
+ return minn;
+}
+
+RemixCount
+remix_stream_chunkchunkchunkfuncify (RemixEnv * env,
+ RemixStream * src1, RemixStream * src2,
+ RemixStream * dest, RemixCount count,
+ RemixChunkChunkChunkFunc func, void * data)
+{
+ RemixCount n, minn = count;
+ RemixCount src1_offset = remix_tell (env, (RemixBase *)src1);
+ RemixCount src2_offset = remix_tell (env, (RemixBase *)src2);
+ RemixCount dest_offset = remix_tell (env, (RemixBase *)dest);
+ CDSet * s, * channels = remix_get_channels (env);
+ RemixChannel * s1ch, * s2ch, * dch;
+
+ if (dest == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ for (s = dest->channels; s; s = s->next) {
+ if (cd_set_contains (env, channels, s->key)) {
+ dch = (RemixChannel *)s->data.s_pointer;
+ s1ch = remix_stream_find_channel (env, src1, s->key);
+ s2ch = remix_stream_find_channel (env, src2, s->key);
+ if (s1ch != RemixNone && s2ch != RemixNone) {
+ n = remix_channel_chunkchunkchunkfuncify (env, s1ch, s2ch, dch,
+ count, func, s->key, data);
+ minn = MIN (n, minn);
+ }
+ }
+ }
+
+ remix_seek (env, (RemixBase *)src1, src1_offset + minn, SEEK_SET);
+ remix_seek (env, (RemixBase *)src2, src2_offset + minn, SEEK_SET);
+ remix_seek (env, (RemixBase *)dest, dest_offset + minn, SEEK_SET);
+
+ return minn;
+}
+
+/*
+ * remix_stream_gain (env, src, dest, count, gain)
+ */
+RemixCount
+remix_stream_gain (RemixEnv * env, RemixStream * stream, RemixCount count,
+ RemixPCM gain)
+{
+ return remix_stream_chunkfuncify (env, stream, count,
+ _remix_chunk_gain, &gain);
+}
+
+/*
+ * remix_stream_copy (env, src, dest, count)
+ *
+ * Copy 'count' samples from 'src' to 'dest'
+ */
+RemixCount
+remix_stream_copy (RemixEnv * env, RemixStream * src, RemixStream * dest,
+ RemixCount count)
+{
+ remix_dprintf ("[remix_stream_copy] (%p -> %p, +%ld)\n", src, dest, count);
+
+ return remix_stream_chunkchunkfuncify (env, src, dest, count,
+ _remix_chunk_copy, NULL);
+}
+
+/*
+ * remix_stream_write (env, stream, count, data)
+ *
+ * Write 'count' samples of 'data' to the stream 'stream'.
+ */
+/* XXX: this is a wrapper to obsolete remix_stream_write above */
+RemixCount
+remix_stream_write (RemixEnv * env, RemixStream * stream, RemixCount count,
+ RemixStream * data)
+{
+ remix_dprintf ("[remix_stream_write] (%p -> %p, +%ld)\n", data, stream, count);
+
+ if (data == RemixNone)
+ return remix_stream_write0 (env, stream, count);
+
+ return remix_stream_copy (env, data, stream, count);
+}
+
+/*
+ * remix_stream_mix (src, dest, count)
+ *
+ * Mix 'count' samples from 'src' into 'dest'.
+ */
+RemixCount
+remix_stream_mix (RemixEnv * env, RemixStream * src, RemixStream * dest,
+ RemixCount count)
+{
+ remix_dprintf ("[remix_stream_mix] (%p -> %p, +%ld)\n", src, dest, count);
+
+ return remix_stream_chunkchunkfuncify (env, src, dest, count,
+ _remix_chunk_add_inplace, NULL);
+}
+
+/*
+ * remix_stream_mult (src, dest, count)
+ *
+ * Multiply 'count' samples of 'src' into 'dest'.
+ */
+RemixCount
+remix_stream_mult (RemixEnv * env, RemixStream * src, RemixStream * dest,
+ RemixCount count)
+{
+ remix_dprintf ("[remix_stream_mult] (%p -> %p, +%ld)\n", src, dest, count);
+
+ return remix_stream_chunkchunkfuncify (env, src, dest, count,
+ _remix_chunk_mult_inplace, NULL);
+}
+
+/*
+ * remix_stream_fade (src, dest, count)
+ *
+ * Fade 'count' samples of 'dest' by values in 'src'.
+ */
+RemixCount
+remix_stream_fade (RemixEnv * env, RemixStream * src, RemixStream * dest,
+ RemixCount count)
+{
+ remix_dprintf ("[remix_stream_fade] (%p -> %p, +%ld)\n", src, dest, count);
+
+ return remix_stream_chunkchunkfuncify (env, src, dest, count,
+ _remix_chunk_fade_inplace, NULL);
+}
+
+/*
+ * remix_stream_blend (env, src, blend, dest, count)
+ *
+ * Blend 'count' samples of 'src' into 'dest' by amounts in 'blend'.
+ */
+RemixCount
+remix_stream_blend (RemixEnv * env, RemixStream * src, RemixStream * blend,
+ RemixStream * dest, RemixCount count)
+{
+ remix_dprintf ("[remix_stream_blend] (%p -> (%p) -> %p, +%ld)\n", src, blend,
+ dest, count);
+
+ return remix_stream_chunkchunkchunkfuncify (env, src, blend, dest, count,
+ _remix_chunk_blend_inplace, NULL);
+}
+
+
+/*
+ * remix_streams_mix (streams, dest, count)
+ *
+ * Mix 'count' samples from all streams in list 'streams' together into
+ * 'dest'.
+ */
+RemixCount
+remix_streams_mix (RemixEnv * env, CDList * streams, RemixStream * dest,
+ RemixCount count)
+{
+ CDList * sl;
+ CDSet * s;
+ RemixChannel * sch, * dch;
+ RemixStream * stream;
+ RemixCount dest_start = remix_tell (env, (RemixBase *)dest);
+ RemixCount stream_start;
+
+ if (dest == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ for (s = dest->channels; s; s = s->next) {
+ dch = (RemixChannel *)s->data.s_pointer;
+ for (sl = streams; sl; sl = sl->next) {
+ stream = (RemixStream *)sl->data.s_pointer;
+ stream_start = remix_tell (env, (RemixBase *)stream);
+ sch = remix_stream_find_channel (env, stream, s->key);
+ if (sch != RemixNone) {
+ _remix_channel_seek (env, dch, dest_start);
+ remix_channel_mix (env, sch, dch, count);
+ remix_seek (env, (RemixBase *)stream, stream_start, SEEK_SET);
+ }
+ }
+ }
+
+ for (sl = streams; sl; sl = sl->next) {
+ stream = (RemixStream *)sl->data.s_pointer;
+ stream_start = remix_tell (env, (RemixBase *)stream);
+ remix_seek (env, (RemixBase *)stream, stream_start + count, SEEK_SET);
+ }
+
+ remix_seek (env, (RemixBase *)dest, dest_start+count, SEEK_SET);
+
+ return count;
+}
+
+/*
+ * remix_stream_interleave_2 (env, stream, name1, name2, dest, count)
+ *
+ * Interleave 'count' frames of the channels named 'name1' and 'name2' in
+ * 'stream', placing the resulting PCM data in the memory region pointed
+ * to by 'dest'.
+ */
+RemixCount
+remix_stream_interleave_2 (RemixEnv * env, RemixStream * stream,
+ int name1, int name2,
+ RemixPCM * dest, RemixCount count)
+{
+ RemixChannel * channel1, * channel2;
+ RemixCount n = 0;
+
+ channel1 = remix_stream_find_channel (env, stream, name1);
+ channel2 = remix_stream_find_channel (env, stream, name2);
+
+ if (channel1 != RemixNone && channel2 != RemixNone) {
+ n = remix_channel_chunkchunkfuncify (env, channel1, channel2,
+ count, _remix_chunk_interleave_2,
+ 0, dest);
+ }
+
+ if (n > 0) remix_seek (env, (RemixBase *)stream, n, SEEK_CUR);
+
+ return n;
+}
+
+/*
+ * remix_stream_deinterleave_stereo (env, stream, name1, name2, src, count)
+ *
+ * Deinterleave 'count' frames from the memory region pointed to by 'src',
+ * placing the resulting channels into those named 'name1' and 'name2' in
+ * 'stream'.
+ */
+RemixCount
+remix_stream_deinterleave_2 (RemixEnv * env, RemixStream * stream,
+ int name1, int name2,
+ RemixPCM * src, RemixCount count)
+{
+ RemixChannel * channel1, * channel2;
+ RemixCount n = 0;
+
+ channel1 = remix_stream_find_channel (env, stream, name1);
+ channel2 = remix_stream_find_channel (env, stream, name2);
+
+ if (channel1 != RemixNone && channel2 != RemixNone) {
+ n = remix_channel_chunkchunkfuncify (env, channel1, channel2,
+ count, _remix_chunk_deinterleave_2,
+ 0, src);
+ }
+
+ if (n > 0) remix_seek (env, (RemixBase *)stream, n, SEEK_CUR);
+
+ return n;
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixTime: A generic time abstraction for sequencing information.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+RemixTime
+remix_time_zero (RemixTimeType type)
+{
+ return _remix_time_zero (type);
+}
+
+RemixTime
+remix_time_invalid (RemixTimeType type)
+{
+ return _remix_time_invalid (type);
+}
+
+int
+remix_time_is_invalid (RemixTimeType type, RemixTime time)
+{
+ return _remix_time_is_invalid (type, time);
+}
+
+RemixTime
+remix_time_add (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_add (type, t1, t2);
+}
+
+RemixTime
+remix_time_sub (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_sub (type, t1, t2);
+}
+
+RemixTime
+remix_time_min (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_min (type, t1, t2);
+}
+
+RemixTime
+remix_time_max (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_max (type, t1, t2);
+}
+
+int
+remix_time_eq (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_eq (type, t1, t2);
+}
+
+int
+remix_time_gt (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_gt (type, t1, t2);
+}
+
+int
+remix_time_lt (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_lt (type, t1, t2);
+}
+
+int
+remix_time_ge (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_ge (type, t1, t2);
+}
+
+int
+remix_time_le (RemixTimeType type, RemixTime t1, RemixTime t2)
+{
+ return _remix_time_le (type, t1, t2);
+}
+
+
+static float
+remix_samples_to_seconds (RemixCount samples, RemixSamplerate samplerate)
+{
+ return ((float)samples / samplerate);
+}
+
+static int
+remix_samples_to_beat24s (RemixCount samples, RemixSamplerate samplerate,
+ RemixTempo tempo)
+{
+ return ((int)((float)samples * tempo * 24.0 / (samplerate * 60.0)));
+}
+
+static RemixCount
+remix_seconds_to_samples (float seconds, RemixSamplerate samplerate)
+{
+ return (RemixCount)(seconds * samplerate);
+}
+
+static int
+remix_seconds_to_beat24s (float seconds, RemixTempo tempo)
+{
+ return (int)(seconds * tempo * 24.0 / 60.0);
+}
+
+static RemixCount
+remix_beat24s_to_samples (int beat24s, RemixSamplerate samplerate,
+ RemixTempo tempo)
+{
+ return (RemixCount)(beat24s * samplerate * 60.0 / (tempo * 24.0));
+}
+
+static float
+remix_beat24s_to_seconds (int beat24s, RemixTempo tempo)
+{
+ return ((float)beat24s * 60.0 / (tempo * 24.0));
+}
+
+
+RemixTime
+remix_time_convert (RemixEnv * env, RemixTime time, RemixTimeType old_type,
+ RemixTimeType new_type)
+{
+ RemixSamplerate samplerate;
+ RemixTempo tempo;
+
+ if (old_type == new_type) return time;
+
+ samplerate = remix_get_samplerate (env);
+ tempo = remix_get_tempo (env);
+
+ switch (old_type) {
+ case REMIX_TIME_SAMPLES:
+ switch (new_type) {
+ case REMIX_TIME_SECONDS:
+ return (RemixTime) remix_samples_to_seconds (time.samples, samplerate);
+ break;
+ case REMIX_TIME_BEAT24S:
+ return (RemixTime)
+ remix_samples_to_beat24s (time.samples, samplerate, tempo);
+ break;
+ default: break;
+ }
+ break;
+ case REMIX_TIME_SECONDS:
+ switch (new_type) {
+ case REMIX_TIME_SAMPLES:
+ return (RemixTime) remix_seconds_to_samples (time.seconds, samplerate);
+ break;
+ case REMIX_TIME_BEAT24S:
+ return (RemixTime) remix_seconds_to_beat24s (time.seconds, tempo);
+ break;
+ default: break;
+ }
+ break;
+ case REMIX_TIME_BEAT24S:
+ switch (new_type) {
+ case REMIX_TIME_SAMPLES:
+ return (RemixTime)
+ remix_beat24s_to_samples (time.beat24s, samplerate, tempo);
+ break;
+ case REMIX_TIME_SECONDS:
+ return (RemixTime) remix_beat24s_to_seconds (time.beat24s, tempo);
+ break;
+ default: break;
+ }
+ break;
+ default:
+ /* Cannot convert invalid time type to anything */
+ break;
+ }
+
+ return remix_time_invalid (new_type);
+}
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixTrack: An RemixLayer mixing abstraction.
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ *
+ * Description
+ * -----------
+ *
+ * A track is contained within a deck. A track contains a number of
+ * layers which are mixed in series.
+ *
+ * Invariants
+ * ----------
+ *
+ * A track must be contained within a deck.
+ */
+
+#define __REMIX__
+#include "remix.h"
+
+/* Optimisation dependencies: optimise on change of nr. layers */
+static RemixTrack * remix_track_optimise (RemixEnv * env, RemixTrack * track);
+
+static void
+remix_track_replace_mixstreams (RemixEnv * env, RemixTrack * track)
+{
+ RemixCount mixlength = _remix_base_get_mixlength (env, track);
+
+ if (track->_mixstream_a != RemixNone)
+ remix_destroy (env, (RemixBase *)track->_mixstream_a);
+ if (track->_mixstream_b != RemixNone)
+ remix_destroy (env, (RemixBase *)track->_mixstream_b);
+
+ track->_mixstream_a = remix_stream_new_contiguous (env, mixlength);
+ track->_mixstream_b = remix_stream_new_contiguous (env, mixlength);
+}
+
+static RemixBase *
+remix_track_init (RemixEnv * env, RemixBase * base)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ track->gain = 1.0;
+ track->layers = cd_list_new (env);
+ track->_mixstream_a = track->_mixstream_b = RemixNone;
+ remix_track_replace_mixstreams (env, track);
+ remix_track_optimise (env, track);
+ return (RemixBase *)track;
+}
+
+static RemixTrack *
+_remix_track_new (RemixEnv * env)
+{
+ return (RemixTrack *)
+ remix_base_new_subclass (env, sizeof (struct _RemixTrack));
+}
+
+RemixBase *
+remix_track_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ RemixTrack * new_track = _remix_track_new (env);
+
+ new_track->gain = track->gain;
+ new_track->layers = cd_list_clone (env, track->layers,
+ (CDCloneFunc)remix_layer_clone);
+ remix_track_optimise (env, track);
+
+ return (RemixBase *)new_track;
+}
+
+static int
+remix_track_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ remix_destroy_list (env, track->layers);
+ remix_free (track);
+ return 0;
+}
+
+static int
+remix_track_ready (RemixEnv * env, RemixBase * base)
+{
+ return (remix_base_encompasses_mixlength (env, base) &&
+ remix_base_encompasses_channels (env, base));
+}
+
+static RemixBase *
+remix_track_prepare (RemixEnv * env, RemixBase * base)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ remix_track_replace_mixstreams (env, track);
+ return base;
+}
+
+RemixTrack *
+remix_track_new (RemixEnv * env, RemixDeck * deck)
+{
+ RemixTrack * track;
+
+ track = _remix_track_new (env);
+ track->deck = deck;
+ remix_track_init (env, (RemixBase *)track);
+ _remix_deck_add_track (env, deck, track);
+
+ return track;
+}
+
+static RemixCount
+remix_track_length (RemixEnv * env, RemixBase * base)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ RemixCount length, maxlength = 0;
+ CDList * l;
+ RemixLayer * layer;
+
+ for (l = track->layers; l; l = l->next) {
+ layer = (RemixLayer *)l->data.s_pointer;
+ length = remix_length (env, (RemixBase *)layer);
+ remix_dprintf ("[remix_track_length] found layer %p length %ld\n",
+ layer, length);
+ maxlength = MAX (maxlength, length);
+ }
+
+ return maxlength;
+}
+
+RemixPCM
+remix_track_set_gain (RemixEnv * env, RemixTrack * track, RemixPCM gain)
+{
+ RemixPCM old = track->gain;
+ track->gain = gain;
+ return old;
+}
+
+RemixPCM
+remix_track_get_gain (RemixEnv * env, RemixTrack * track)
+{
+ return track->gain;
+}
+
+void
+remix_remove_track (RemixEnv * env, RemixTrack * track)
+{
+ RemixDeck * deck = track->deck;
+
+ if (deck)
+ _remix_deck_remove_track (env, deck, track);
+}
+
+RemixDeck *
+remix_track_get_deck (RemixEnv * env, RemixTrack * track)
+{
+ return track->deck;
+}
+
+/*
+ * _remix_track_add_layer_above (env, track, layer, above)
+ *
+ * Adds 'layer' above 'above'. If above is RemixNone, adds 'layer' on top
+ * of 'track'.
+ */
+RemixLayer *
+_remix_track_add_layer_above (RemixEnv * env, RemixTrack * track,
+ RemixLayer * layer, RemixLayer * above)
+{
+ layer->track = track;
+ if (above == RemixNone)
+ above = (RemixLayer *)
+ (cd_list_last (env, track->layers, CD_TYPE_POINTER)).s_pointer;
+ track->layers = cd_list_add_after (env, track->layers, CD_TYPE_POINTER,
+ CD_POINTER(layer), CD_POINTER(above));
+ remix_track_optimise (env, track);
+ return layer;
+}
+
+RemixLayer *
+_remix_track_remove_layer (RemixEnv * env, RemixTrack * track,
+ RemixLayer * layer)
+{
+ track->layers = cd_list_remove (env, track->layers, CD_TYPE_POINTER,
+ CD_POINTER(layer));
+ remix_track_optimise (env, track);
+ return layer;
+}
+
+/*
+ * gets layer above 'above'. If above is RemixNone, returns topmost layer
+ */
+RemixLayer *
+_remix_track_get_layer_above (RemixEnv * env, RemixTrack * track,
+ RemixLayer * above)
+{
+ CDList * above_item;
+ RemixLayer * layer;
+
+ if (track->layers == NULL) return RemixNone;
+
+ if (above == RemixNone) {
+ layer = (RemixLayer *)
+ (cd_list_last (env, track->layers, CD_TYPE_POINTER)).s_pointer;
+ } else {
+ above_item = cd_list_find (env, track->layers, CD_TYPE_POINTER,
+ CD_POINTER(above));
+ if (above_item == NULL) return RemixNone;
+ above_item = above_item->next;
+ if (above_item == NULL) return RemixNone;
+ layer = (RemixLayer *) above_item->data.s_pointer;
+ }
+
+ return layer;
+}
+
+/*
+ * gets layer below 'below'. If below is RemixNone, returns lowest layer
+ */
+RemixLayer *
+_remix_track_get_layer_below (RemixEnv * env, RemixTrack * track,
+ RemixLayer * below)
+{
+ CDList * below_item;
+ RemixLayer * layer;
+
+ if (track->layers == NULL) return RemixNone;
+
+ if (below == RemixNone) {
+ layer = (RemixLayer *) track->layers->data.s_pointer;
+ } else {
+ below_item = cd_list_find (env, track->layers, CD_TYPE_POINTER,
+ CD_POINTER(below));
+ if (below_item == NULL) return RemixNone;
+ below_item = below_item->prev;
+ if (below_item == NULL) return RemixNone;
+ layer = (RemixLayer *) below_item->data.s_pointer;
+ }
+
+ return layer;
+}
+
+
+static RemixCount
+remix_track_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ CDList * l;
+ RemixBase * layer;
+ RemixStream * si, * so, * swap_stream;
+ RemixCount remaining = count, processed = 0, n = 0;
+ RemixCount mixlength = _remix_base_get_mixlength (env, track);
+
+ remix_dprintf ("PROCESS TRACK (%p, +%ld, %p -> %p) @ %ld\n",
+ track, count, input, output, remix_tell (env, base));
+
+ if (track->layers == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOOP);
+ return 0;
+ }
+
+ while (remaining > 0) {
+ l = track->layers;
+ si = input;
+ so = track->_mixstream_a;
+ n = MIN (remaining, mixlength);
+
+ while (l) {
+ layer = (RemixBase *)l->data.s_pointer;
+
+ if (si == input) {
+ swap_stream = track->_mixstream_b;
+ } else {
+ swap_stream = si;
+ remix_seek (env, (RemixBase *)si, 0, SEEK_SET);
+ }
+
+ if (l->next == RemixNone) {
+ so = output;
+ } else {
+ remix_seek (env, (RemixBase *)so, 0, SEEK_SET);
+ }
+
+ n = remix_process (env, layer, n, si, so);
+
+ l = l->next;
+
+ /* swap si, st using swap_stream as evaluated above */
+ si = so; so = swap_stream;
+ }
+ remaining -= n;
+ processed += n;
+ }
+
+ remix_dprintf ("[remix_track_process] processed %ld\n", processed);
+
+ return processed;
+}
+
+static RemixCount
+remix_track_twolayer_process (RemixEnv * env, RemixBase * base,
+ RemixCount count, RemixStream * input,
+ RemixStream * output)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ CDList * l;
+ RemixBase * layer1, * layer2;
+ RemixCount remaining = count, processed = 0, n = 0;
+ RemixStream * mix = track->_mixstream_a;
+ RemixCount current_offset = remix_tell (env, base);
+ RemixCount mixlength = _remix_base_get_mixlength (env, track);
+
+ remix_dprintf ("PROCESS TRACK [twolayer] (%p, +%ld, %p -> %p) @ %ld\n",
+ track, count, input, output, current_offset);
+
+ l = track->layers;
+ layer1 = (RemixBase *)l->data.s_pointer;
+ remix_seek (env, (RemixBase *)layer1, current_offset, SEEK_SET);
+
+ l = l->next;
+ layer2 = (RemixBase *)l->data.s_pointer;
+ remix_seek (env, (RemixBase *)layer2, current_offset, SEEK_SET);
+
+ while (remaining > 0) {
+ n = MIN (remaining, mixlength);
+
+ remix_seek (env, (RemixBase *)mix, 0, SEEK_SET);
+ n = remix_process (env, layer1, n, input, mix);
+
+ remix_seek (env, (RemixBase *)mix, 0, SEEK_SET);
+ n = remix_process (env, layer2, n, mix, output);
+
+ remaining -= n;
+ processed += n;
+ }
+
+ remix_dprintf ("*** PRE-SEEK: track @ %ld\n", remix_tell (env, base));
+
+ /*remix_seek (env, base, current_offset + processed, SEEK_SET);*/
+
+ remix_dprintf ("*** POST-SEEK: track @ %ld\n", remix_tell (env, base));
+
+ remix_dprintf ("[remix_track_twolayer_process] processed %ld\n", processed);
+
+ return processed;
+}
+
+static RemixCount
+remix_track_onelayer_process (RemixEnv * env, RemixBase * base,
+ RemixCount count, RemixStream * input,
+ RemixStream * output)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ CDList * l = track->layers;
+ RemixBase * layer = (RemixBase *)l->data.s_pointer;
+ RemixCount n;
+
+ remix_dprintf ("PROCESS TRACK [onelayer] (%p, +%ld, %p -> %p) @ %ld\n",
+ track, count, input, output, remix_tell (env, base));
+
+ n = remix_process (env, layer, count, input, output);
+
+ remix_dprintf ("[remix_track_onelayer_process] processed %ld\n", n);
+
+ return n;
+}
+
+static RemixCount
+remix_track_seek (RemixEnv * env, RemixBase * base, RemixCount offset)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ CDList * l;
+ RemixLayer * layer;
+
+ for (l = track->layers; l; l = l->next) {
+ layer = (RemixLayer *)l->data.s_pointer;
+ remix_seek (env, (RemixBase *)layer, offset, SEEK_SET);
+ }
+
+ return offset;
+}
+
+static int
+remix_track_flush (RemixEnv * env, RemixBase * base)
+{
+ RemixTrack * track = (RemixTrack *)base;
+ CDList * l;
+ RemixLayer * layer;
+
+ for (l = track->layers; l; l = l->next) {
+ layer = (RemixLayer *)l->data.s_pointer;
+ remix_flush (env, (RemixBase *)layer);
+ }
+
+ return 0;
+}
+
+static struct _RemixMethods _remix_track_empty_methods = {
+ remix_track_clone, /* clone */
+ remix_track_destroy, /* destroy */
+ remix_track_ready, /* ready */
+ remix_track_prepare, /* prepare */
+ remix_null_process, /* process */
+ remix_null_length, /* length */
+ remix_null_seek, /* seek */
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_track_methods = {
+ remix_track_clone, /* clone */
+ remix_track_destroy, /* destroy */
+ remix_track_ready, /* ready */
+ remix_track_prepare, /* prepare */
+ remix_track_process, /* process */
+ remix_track_length, /* length */
+ remix_track_seek, /* seek */
+ remix_track_flush, /* flush */
+};
+
+static struct _RemixMethods _remix_track_onelayer_methods = {
+ remix_track_clone, /* clone */
+ remix_track_destroy, /* destroy */
+ remix_track_ready, /* ready */
+ remix_track_prepare, /* prepare */
+ remix_track_onelayer_process, /* process */
+ remix_track_length, /* length */
+ remix_track_seek, /* seek */
+ remix_track_flush, /* flush */
+};
+
+static struct _RemixMethods _remix_track_twolayer_methods = {
+ remix_track_clone, /* clone */
+ remix_track_destroy, /* destroy */
+ remix_track_ready, /* ready */
+ remix_track_prepare, /* prepare */
+ remix_track_twolayer_process, /* process */
+ remix_track_length, /* length */
+ remix_track_seek, /* seek */
+ remix_track_flush, /* flush */
+};
+
+static RemixTrack *
+remix_track_optimise (RemixEnv * env, RemixTrack * track)
+{
+ RemixCount nr_layers = cd_list_length (env, track->layers);
+
+ switch (nr_layers) {
+ case 0:
+ _remix_set_methods (env, track, &_remix_track_empty_methods); break;
+ case 1:
+ _remix_set_methods (env, track, &_remix_track_onelayer_methods); break;
+ case 2:
+ _remix_set_methods (env, track, &_remix_track_twolayer_methods); break;
+ default:
+ _remix_set_methods (env, track, &_remix_track_methods); break;
+ }
+
+ return track;
+}
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = ladspa noise
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include -I$(CTXDATADIR)
+
+libdir = $(PACKAGE_PLUGIN_DIR)
+
+CTXDATADIR = $(top_srcdir)/src/ctxdata
+CTXDATA_LIBS = $(top_builddir)/src/ctxdata/libctxdata.la
+
+REMIXDIR = ../../libremix
+REMIX_LIBS = $(REMIXDIR)/libremix.la
+
+lib_LTLIBRARIES = \
+ libremix_ladspa.la
+
+libremix_ladspa_la_SOURCES = remix_ladspa.c ladspa.h
+libremix_ladspa_la_LDFLAGS = -module -version-info 1:0:0
+libremix_ladspa_la_LIBADD = $(REMIX_LIBS) $(CTXDATA_LIBS)
--- /dev/null
+/* ladspa.h
+
+ Version 1. Copyright 2000 Richard W.E. Furse, Paul Barton-Davis,
+ Stefan Westerfeld. */
+
+#ifndef LADSPA_INCLUDED
+#define LADSPA_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+
+/* Overview:
+
+ There is a large number of synthesis packages in use or development
+ on the Linux platform at this time. This API (`The Linux Audio
+ Developer's Simple Plugin API') attempts to give programmers the
+ ability to write simple `plugin' audio processors in C/C++ and link
+ them dynamically (`plug') into a range of these packages (`hosts').
+ It should be possible for any host and any plugin to communicate
+ completely through this interface. The LADSPA plugin API is free to
+ use.
+
+ This API is deliberately short and simple. To achieve compatibility
+ with a range of promising Linux sound synthesis packages it
+ attempts to find the `greatest common divisor' in their logical
+ behaviour. Having said this, certain limiting decisions are
+ implicit, notably the use of a fixed type (LADSPA_Data) for all
+ data transfer and absence of a parameterised `initialisation'
+ phase. See below for the LADSPA_Data typedef.
+
+ Plugins are expected to distinguish between control and audio
+ data. Plugins have `ports' that are inputs or outputs for audio or
+ control data and each plugin is `run' for a `block' corresponding
+ to a short time interval measured in samples. Audio data is
+ communicated using arrays of LADSPA_Data, allowing a block of audio
+ to be processed by the plugin in a single pass. Control data is
+ communicated using single LADSPA_Data values. Control data has a
+ single value at the start of a call to the `run()' or `run_adding()'
+ function, and may be considered to remain this value for its
+ duration. The plugin may assume that all its input and output ports
+ have been connected to the relevant data location (see the
+ `connect_port()' function below) before it is asked to run.
+
+ Plugins will reside in shared object files suitable for dynamic
+ linking by dlopen() and family. The file will provide a number of
+ `plugin types' that can be used to instantiate actual plugins
+ (sometimes known as `plugin instances') that can be connected
+ together to perform tasks.
+
+ This API contains very limited error-handling. */
+
+/*****************************************************************************/
+
+/* Fundamental data type passed in and out of plugin. This data type
+ is used to communicate audio samples and control values. It is
+ assumed that the plugin will work sensibly given any numeric input
+ value although it may have a preferred range (see hints below). */
+
+typedef float LADSPA_Data;
+
+/*****************************************************************************/
+
+/* Special Plugin Properties:
+
+ Optional features of the plugin type are encapsulated in the
+ LADSPA_Properties type. This is assembled by ORing individual
+ properties together. */
+
+typedef int LADSPA_Properties;
+
+/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a
+ real-time dependency (e.g. listens to a MIDI device) and so its
+ output must not be cached or subject to significant latency. */
+#define LADSPA_PROPERTY_REALTIME 0x1
+
+/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin
+ may cease to work correctly if the host elects to use the same data
+ location for both input and output (see connect_port()). This
+ should be avoided as enabling this flag makes it impossible for
+ hosts to use the plugin to process audio `in-place.' */
+#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2
+
+/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin
+ is capable of running not only in a conventional host but also in a
+ `hard real-time' environment. To qualify for this the plugin must
+ satisfy all of the following:
+
+ (1) The plugin must not use malloc(), free() or other heap memory
+ management within its run() or run_adding() functions. All new
+ memory used in run() must be managed via the stack. These
+ restrictions only apply to the run() function.
+
+ (2) The plugin will not attempt to make use of any library
+ functions with the exceptions of functions in the ANSI standard C
+ and C maths libraries, which the host is expected to provide.
+
+ (3) The plugin will not access files, devices, pipes, sockets, IPC
+ or any other mechanism that might result in process or thread
+ blocking.
+
+ (4) The plugin will take an amount of time to execute a run() or
+ run_adding() call approximately of form (A+B*SampleCount) where A
+ and B depend on the machine and host in use. This amount of time
+ may not depend on input signals or plugin state. The host is left
+ the responsibility to perform timings to estimate upper bounds for
+ A and B. */
+#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4
+
+#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME)
+#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN)
+#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE)
+
+/*****************************************************************************/
+
+/* Plugin Ports:
+
+ Plugins have `ports' that are inputs or outputs for audio or
+ data. Ports can communicate arrays of LADSPA_Data (for audio
+ inputs/outputs) or single LADSPA_Data values (for control
+ input/outputs). This information is encapsulated in the
+ LADSPA_PortDescriptor type which is assembled by ORing individual
+ properties together.
+
+ Note that a port must be an input or an output port but not both
+ and that a port must be a control or audio port but not both. */
+
+typedef int LADSPA_PortDescriptor;
+
+/* Property LADSPA_PORT_INPUT indicates that the port is an input. */
+#define LADSPA_PORT_INPUT 0x1
+
+/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */
+#define LADSPA_PORT_OUTPUT 0x2
+
+/* Property LADSPA_PORT_CONTROL indicates that the port is a control
+ port. */
+#define LADSPA_PORT_CONTROL 0x4
+
+/* Property LADSPA_PORT_AUDIO indicates that the port is a audio
+ port. */
+#define LADSPA_PORT_AUDIO 0x8
+
+#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT)
+#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT)
+#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL)
+#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO)
+
+/*****************************************************************************/
+
+/* Plugin Port Range Hints:
+
+ The host may wish to provide a representation of data entering or
+ leaving a plugin (e.g. to generate a GUI automatically). To make
+ this more meaningful, the plugin should provide `hints' to the host
+ describing the usual values taken by the data.
+
+ Note that these are only hints. The host may ignore them and the
+ plugin must not assume that data supplied to it is meaningful. If
+ the plugin receives invalid input data it is expected to continue
+ to run without failure and, where possible, produce a sensible
+ output (e.g. a high-pass filter given a negative cutoff frequency
+ might switch to an all-pass mode).
+
+ Hints are meaningful for all input and output ports but hints for
+ input control ports are expected to be particularly useful.
+
+ More hint information is encapsulated in the
+ LADSPA_PortRangeHintDescriptor type which is assembled by ORing
+ individual hint types together. Hints may require further
+ LowerBound and UpperBound information.
+
+ All the hint information for a particular port is aggregated in the
+ LADSPA_PortRangeHint structure. */
+
+typedef int LADSPA_PortRangeHintDescriptor;
+
+/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field
+ of the LADSPA_PortRangeHint should be considered meaningful. The
+ value in this field should be considered the (inclusive) lower
+ bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
+ specified then the value of LowerBound should be multiplied by the
+ sample rate. */
+#define LADSPA_HINT_BOUNDED_BELOW 0x1
+
+/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field
+ of the LADSPA_PortRangeHint should be considered meaningful. The
+ value in this field should be considered the (inclusive) upper
+ bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also
+ specified then the value of UpperBound should be multiplied by the
+ sample rate. */
+#define LADSPA_HINT_BOUNDED_ABOVE 0x2
+
+/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be
+ considered a Boolean toggle. Data less than or equal to zero should
+ be considered `off' or `false,' and data above zero should be
+ considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in
+ conjunction with any other hint. */
+#define LADSPA_HINT_TOGGLED 0x4
+
+/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified
+ should be interpreted as multiples of the sample rate. For
+ instance, a frequency range from 0Hz to the Nyquist frequency (half
+ the sample rate) could be requested by this hint in conjunction
+ with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds
+ at all must support this hint to retain meaning. */
+#define LADSPA_HINT_SAMPLE_RATE 0x8
+
+/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the
+ user will find it more intuitive to view values using a logarithmic
+ scale. This is particularly useful for frequencies and gains. */
+#define LADSPA_HINT_LOGARITHMIC 0x10
+
+/* Hint LADSPA_HINT_INTEGER indicates that a user interface would
+ probably wish to provide a stepped control taking only integer
+ values. Any bounds set should be slightly wider than the actual
+ integer range required to avoid floating point rounding errors. For
+ instance, the integer set {0,1,2,3} might be described as [-0.1,
+ 3.1]. */
+#define LADSPA_HINT_INTEGER 0x20
+
+#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW)
+#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE)
+#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED)
+#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE)
+#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC)
+#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER)
+
+typedef struct _LADSPA_PortRangeHint {
+
+ /* Hints about the port. */
+ LADSPA_PortRangeHintDescriptor HintDescriptor;
+
+ /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When
+ LADSPA_HINT_SAMPLE_RATE is also active then this value should be
+ multiplied by the relevant sample rate. */
+ LADSPA_Data LowerBound;
+
+ /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When
+ LADSPA_HINT_SAMPLE_RATE is also active then this value should be
+ multiplied by the relevant sample rate. */
+ LADSPA_Data UpperBound;
+
+} LADSPA_PortRangeHint;
+
+/*****************************************************************************/
+
+/* Plugin Handles:
+
+ This plugin handle indicates a particular instance of the plugin
+ concerned. It is valid to compare this to NULL (0 for C++) but
+ otherwise the host should not attempt to interpret it. The plugin
+ may use it to reference internal instance data. */
+
+typedef void * LADSPA_Handle;
+
+/*****************************************************************************/
+
+/* Descriptor for a Type of Plugin:
+
+ This structure is used to describe a plugin type. It provides a
+ number of functions to examine the type, instantiate it, link it to
+ buffers and workspaces and to run it. */
+
+typedef struct _LADSPA_Descriptor {
+
+ /* This numeric identifier indicates the plugin type
+ uniquely. Plugin programmers may reserve ranges of IDs from a
+ central body to avoid clashes. Hosts may assume that IDs are
+ below 0x1000000. */
+ unsigned long UniqueID;
+
+ /* This identifier can be used as a unique, case-sensitive
+ identifier for the plugin type within the plugin file. Plugin
+ types should be identified by file and label rather than by index
+ or plugin name, which may be changed in new plugin
+ versions. Labels must not contain white-space characters. */
+ const char * Label;
+
+ /* This indicates a number of properties of the plugin. */
+ LADSPA_Properties Properties;
+
+ /* This member points to the null-terminated name of the plugin
+ (e.g. "Sine Oscillator"). */
+ const char * Name;
+
+ /* This member points to the null-terminated string indicating the
+ maker of the plugin. This can be an empty string but not NULL. */
+ const char * Maker;
+
+ /* This member points to the null-terminated string indicating any
+ copyright applying to the plugin. If no Copyright applies the
+ string "None" should be used. */
+ const char * Copyright;
+
+ /* This indicates the number of ports (input AND output) present on
+ the plugin. */
+ unsigned long PortCount;
+
+ /* This member indicates an array of port descriptors. Valid indices
+ vary from 0 to PortCount-1. */
+ const LADSPA_PortDescriptor * PortDescriptors;
+
+ /* This member indicates an array of null-terminated strings
+ describing ports (e.g. "Frequency (Hz)"). Valid indices vary from
+ 0 to PortCount-1. */
+ const char * const * PortNames;
+
+ /* This member indicates an array of range hints for each port (see
+ above). Valid indices vary from 0 to PortCount-1. */
+ const LADSPA_PortRangeHint * PortRangeHints;
+
+ /* This may be used by the plugin developer to pass any custom
+ implementation data into an instantiate call. It must not be used
+ or interpreted by the host. It is expected that most plugin
+ writers will not use this facility as LADSPA_Handle should be
+ used to hold instance data. */
+ void * ImplementationData;
+
+ /* This member is a function pointer that instantiates a plugin. A
+ handle is returned indicating the new plugin instance. The
+ instantiation function accepts a sample rate as a parameter. The
+ plugin descriptor from which this instantiate function was found
+ must also be passed. This function must return NULL if
+ instantiation fails.
+
+ Note that instance initialisation should generally occur in
+ activate() rather than here. */
+ LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor,
+ unsigned long SampleRate);
+
+ /* This member is a function pointer that connects a port on an
+ instantiated plugin to a memory location at which a block of data
+ for the port will be read/written. The data location is expected
+ to be an array of LADSPA_Data for audio ports or a single
+ LADSPA_Data value for control ports. Memory issues will be
+ managed by the host. The plugin must read/write the data at these
+ locations every time run() or run_adding() is called and the data
+ present at the time of this connection call should not be
+ considered meaningful.
+
+ connect_port() may be called more than once for a plugin instance
+ to allow the host to change the buffers that the plugin is
+ reading or writing. These calls may be made before or after
+ activate() or deactivate() calls.
+
+ connect_port() must be called at least once for each port before
+ run() or run_adding() is called. When working with blocks of
+ LADSPA_Data the plugin should pay careful attention to the block
+ size passed to the run function as the block allocated may only
+ just be large enough to contain the block of samples.
+
+ Plugin writers should be aware that the host may elect to use the
+ same buffer for more than one port and even use the same buffer
+ for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN).
+ However, overlapped buffers or use of a single buffer for both
+ audio and control data may result in unexpected behaviour. */
+ void (*connect_port)(LADSPA_Handle Instance,
+ unsigned long Port,
+ LADSPA_Data * DataLocation);
+
+ /* This member is a function pointer that initialises a plugin
+ instance and activates it for use. This is separated from
+ instantiate() to aid real-time support and so that hosts can
+ reinitialise a plugin instance by calling deactivate() and then
+ activate(). In this case the plugin instance must reset all state
+ information dependent on the history of the plugin instance
+ except for any data locations provided by connect_port() and any
+ gain set by set_run_adding_gain(). If there is nothing for
+ activate() to do then the plugin writer may provide a NULL rather
+ than an empty function.
+
+ When present, hosts must call this function once before run() (or
+ run_adding()) is called for the first time. This call should be
+ made as close to the run() call as possible and indicates to
+ real-time plugins that they are now live. Plugins should not rely
+ on a prompt call to run() after activate(). activate() may not be
+ called again unless deactivate() is called first. Note that
+ connect_port() may be called before or after a call to
+ activate(). */
+ void (*activate)(LADSPA_Handle Instance);
+
+ /* This method is a function pointer that runs an instance of a
+ plugin for a block. Two parameters are required: the first is a
+ handle to the particular instance to be run and the second
+ indicates the block size (in samples) for which the plugin
+ instance may run.
+
+ Note that if an activate() function exists then it must be called
+ before run() or run_adding(). If deactivate() is called for a
+ plugin instance then the plugin instance may not be reused until
+ activate() has been called again.
+
+ If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE
+ then there are various things that the plugin should not do
+ within the run() or run_adding() functions (see above). */
+ void (*run)(LADSPA_Handle Instance,
+ unsigned long SampleCount);
+
+ /* This method is a function pointer that runs an instance of a
+ plugin for a block. This has identical behaviour to run() except
+ in the way data is output from the plugin. When run() is used,
+ values are written directly to the memory areas associated with
+ the output ports. However when run_adding() is called, values
+ must be added to the values already present in the memory
+ areas. Furthermore, output values written must be scaled by the
+ current gain set by set_run_adding_gain() (see below) before
+ addition.
+
+ run_adding() is optional. When it is not provided by a plugin,
+ this function pointer must be set to NULL. When it is provided,
+ the function set_run_adding_gain() must be provided also. */
+ void (*run_adding)(LADSPA_Handle Instance,
+ unsigned long SampleCount);
+
+ /* This method is a function pointer that sets the output gain for
+ use when run_adding() is called (see above). If this function is
+ never called the gain is assumed to default to 1. Gain
+ information should be retained when activate() or deactivate()
+ are called.
+
+ This function should be provided by the plugin if and only if the
+ run_adding() function is provided. When it is absent this
+ function pointer must be set to NULL. */
+ void (*set_run_adding_gain)(LADSPA_Handle Instance,
+ LADSPA_Data Gain);
+
+ /* This is the counterpart to activate() (see above). If there is
+ nothing for deactivate() to do then the plugin writer may provide
+ a NULL rather than an empty function.
+
+ Hosts must deactivate all activated units after they have been
+ run() (or run_adding()) for the last time. This call should be
+ made as close to the last run() call as possible and indicates to
+ real-time plugins that they are no longer live. Plugins should
+ not rely on prompt deactivation. Note that connect_port() may be
+ called before or after a call to deactivate().
+
+ Deactivation is not similar to pausing as the plugin instance
+ will be reinitialised when activate() is called to reuse it. */
+ void (*deactivate)(LADSPA_Handle Instance);
+
+ /* Once an instance of a plugin has been finished with it can be
+ deleted using the following function. The instance handle passed
+ ceases to be valid after this call.
+
+ If activate() was called for a plugin instance then a
+ corresponding call to deactivate() must be made before cleanup()
+ is called. */
+ void (*cleanup)(LADSPA_Handle Instance);
+
+} LADSPA_Descriptor;
+
+/**********************************************************************/
+
+/* Accessing a Plugin: */
+
+/* The exact mechanism by which plugins are loaded is host-dependent,
+ however all most hosts will need to know is the name of shared
+ object file containing the plugin types. To allow multiple hosts to
+ share plugin types, hosts may wish to check for environment
+ variable LADSPA_PATH. If present, this should contain a
+ colon-separated path indicating directories that should be searched
+ (in order) when loading plugin types.
+
+ A plugin programmer must include a function called
+ "ladspa_descriptor" with the following function prototype within
+ the shared object file. This function will have C-style linkage (if
+ you are using C++ this is taken care of by the `extern "C"' clause
+ at the top of the file).
+
+ A host will find the plugin shared object file by one means or
+ another, find the ladspa_descriptor() function, call it, and
+ proceed from there.
+
+ Plugin types are accessed by index (not ID) using values from 0
+ upwards. Out of range indexes must result in this function
+ returning NULL, so the plugin count can be determined by checking
+ for the least index that results in NULL being returned. */
+
+const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index);
+
+/* Datatype corresponding to the ladspa_descriptor() function. */
+typedef const LADSPA_Descriptor *
+(*LADSPA_Descriptor_Function)(unsigned long Index);
+
+/**********************************************************************/
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* LADSPA_INCLUDED */
+
+/* EOF */
--- /dev/null
+/*
+ * LADSPA wrapper plugin for libremix
+ *
+ * Copyright (C) 2000 Conrad Parker
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * This file assumes that both LADSPA and libremix are built with
+ * an audio datatype of 'float'.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <math.h> /* for ceil() */
+
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#define __REMIX_PLUGIN__
+#include <remix/remix.h>
+
+#include "ladspa.h"
+
+#define PATH_LEN 1024
+
+/* Compile in support for inplace processing? */
+#define _PROCESS_INPLACE
+
+#ifdef _PROCESS_INPLACE
+#define LADSPA_WRAPPER_IS_INPLACE_BROKEN(x) LADSPA_IS_INPLACE_BROKEN(x)
+#else
+#define LADSPA_WRAPPER_IS_INPLACE_BROKEN(x) (1L)
+#endif
+
+#define LADSPA_IS_CONTROL_INPUT(x) (LADSPA_IS_PORT_INPUT(x) && LADSPA_IS_PORT_CONTROL(x))
+#define LADSPA_IS_AUDIO_INPUT(x) (LADSPA_IS_PORT_INPUT(x) && LADSPA_IS_PORT_AUDIO(x))
+#define LADSPA_IS_CONTROL_OUTPUT(x) (LADSPA_IS_PORT_OUTPUT(x) && LADSPA_IS_PORT_CONTROL(x))
+#define LADSPA_IS_AUDIO_OUTPUT(x) (LADSPA_IS_PORT_OUTPUT(x) && LADSPA_IS_PORT_AUDIO(x))
+
+#define LADSPA_frames_to_bytes(f) (f * sizeof(LADSPA_Data))
+
+static char * default_ladspa_path = "/usr/lib/ladspa:/usr/local/lib/ladspa:/opt/ladspa/lib";
+
+#ifndef WIN32
+# define remix_stat_regular(mode) (S_ISREG((mode)) || S_ISLNK((mode)))
+#else
+# define remix_stat_regular(mode) ((mode) & S_IFREG)
+#endif
+
+/* Dummy control output, used to connect all LADSPA control outputs to */
+static LADSPA_Data dummy_control_output;
+
+static CDList * modules_list = CD_EMPTY_LIST;
+static int ladspa_wrapper_initialised = FALSE;
+
+
+typedef struct _RemixLADSPA RemixLADSPA;
+
+struct _RemixLADSPA {
+ unsigned long samplerate; /* samplerate initialised at */
+ LADSPA_Descriptor * d;
+ LADSPA_Handle * handle;
+ LADSPA_Data * control_inputs;
+};
+
+static RemixBase * remix_ladspa_optimise (RemixEnv * env, RemixBase * base);
+
+/*
+ * is_usable (d)
+ *
+ * Determine if a LADSPA_Descriptor * d is usable by this remix ladspa
+ * wrapper plugin. Currently this means that there is not more than 1
+ * audio input or more than 1 audio output.
+ */
+static int
+is_usable(const LADSPA_Descriptor * d)
+{
+ LADSPA_PortDescriptor pd;
+ int i;
+ int
+ nr_ai=0, /* audio inputs */
+ nr_ao=0; /* audio outputs */
+
+ for (i=0; i < d->PortCount; i++) {
+ pd = d->PortDescriptors[i];
+ if (LADSPA_IS_AUDIO_INPUT(pd))
+ nr_ai++;
+ if (LADSPA_IS_AUDIO_OUTPUT(pd))
+ nr_ao++;
+ }
+
+ /* Sanity checks */
+ if (! d->run) return FALSE; /* plugin does nothing! */
+ if (! d->instantiate) return FALSE; /* plugin cannot be instantiated */
+ if (! d->connect_port) return FALSE; /* plugin cannot be wired up */
+
+ if (nr_ao == 1 && nr_ai == 1) return TRUE;
+ if (nr_ao == 0 && nr_ai == 1) return TRUE;
+ if (nr_ao == 1 && nr_ai == 0) return TRUE;
+
+ return FALSE;
+}
+
+static RemixParameterType
+convert_type (const LADSPA_PortRangeHintDescriptor prhd)
+{
+ if (LADSPA_IS_HINT_TOGGLED(prhd))
+ return REMIX_TYPE_BOOL;
+ else if (LADSPA_IS_HINT_INTEGER(prhd))
+ return REMIX_TYPE_INT;
+ else
+ return REMIX_TYPE_FLOAT;
+}
+
+static RemixFlags
+get_valid_mask (const LADSPA_PortRangeHintDescriptor prhd)
+{
+ RemixFlags ret = 0;
+
+ if (LADSPA_IS_HINT_BOUNDED_BELOW(prhd))
+ ret &= REMIX_RANGE_LOWER_BOUND_VALID;
+ if (LADSPA_IS_HINT_BOUNDED_ABOVE(prhd))
+ ret &= REMIX_RANGE_UPPER_BOUND_VALID;
+
+ return ret;
+}
+
+static RemixParameterRange *
+convert_constraint (const LADSPA_PortRangeHint * prh)
+{
+ RemixParameterRange * pr;
+ LADSPA_PortRangeHintDescriptor prhd = prh->HintDescriptor;
+
+ if (LADSPA_IS_HINT_TOGGLED(prhd))
+ return NULL;
+
+ pr = malloc (sizeof (*pr));
+
+ pr->valid_mask = get_valid_mask (prhd);
+
+ if (LADSPA_IS_HINT_INTEGER(prhd)) {
+ if (LADSPA_IS_HINT_BOUNDED_BELOW(prhd))
+ pr->lower.s_int = (int)prh->LowerBound;
+ if (LADSPA_IS_HINT_BOUNDED_ABOVE(prhd))
+ pr->upper.s_int = (int)prh->UpperBound;
+ } else {
+ if (LADSPA_IS_HINT_BOUNDED_BELOW(prhd))
+ pr->lower.s_float = (float)prh->LowerBound;
+ if (LADSPA_IS_HINT_BOUNDED_ABOVE(prhd))
+ pr->upper.s_float = (float)prh->UpperBound;
+ }
+
+ return pr;
+}
+
+static RemixBase *
+remix_ladspa_replace_handle (RemixEnv * env, RemixBase * base)
+{
+ RemixPlugin * plugin = remix_base_get_plugin (env, base);
+ RemixLADSPA * al = (RemixLADSPA *) remix_base_get_instance_data (env, base);
+ LADSPA_Descriptor * d;
+
+ if (al == NULL) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ if (al->d != NULL)
+ if (al->d->deactivate) al->d->deactivate (al->handle);
+
+ al->samplerate = (unsigned long) remix_get_samplerate (env);
+
+ al->d = d = (LADSPA_Descriptor *) plugin->plugin_data;
+
+ if (d != NULL) {
+ al->handle = d->instantiate (d, al->samplerate);
+ if (d->activate) d->activate (al->handle);
+ }
+
+ return base;
+}
+
+static RemixBase *
+remix_ladspa_init (RemixEnv * env, RemixBase * base, CDSet * parameters)
+{
+ RemixLADSPA * al = malloc (sizeof (*al));
+
+ remix_base_set_instance_data (env, base, al);
+ al->d = NULL; /* let this get set in replace_handle() */
+
+ remix_ladspa_replace_handle (env, base);
+ remix_ladspa_optimise (env, base);
+ return base;
+}
+
+static RemixBase *
+remix_ladspa_clone (RemixEnv * env, RemixBase * base)
+{
+ /* XXX: Most of this should really be handled in remix_base.c */
+ RemixPlugin * plugin = remix_base_get_plugin (env, base);
+ RemixBase * new_base = remix_base_new (env);
+ remix_base_set_plugin (env, new_base, plugin);
+ remix_ladspa_init (env, new_base, CD_EMPTY_SET);
+ return new_base;
+}
+
+static int
+remix_ladspa_destroy (RemixEnv * env, RemixBase * base)
+{
+ RemixLADSPA * al = (RemixLADSPA *) remix_base_get_instance_data (env, base);
+
+ if (al->d) {
+ if (al->d->deactivate) al->d->deactivate (al->handle);
+ }
+
+ free (al->control_inputs);
+ free (al);
+ free (base);
+
+ return 0;
+}
+
+static int
+remix_ladspa_ready (RemixEnv * env, RemixBase * base)
+{
+ unsigned long samplerate = (unsigned long)remix_get_samplerate (env);
+ RemixLADSPA * al = (RemixLADSPA *) remix_base_get_instance_data (env, base);
+ return (samplerate == al->samplerate);
+}
+
+static RemixBase *
+remix_ladspa_prepare (RemixEnv * env, RemixBase * base)
+{
+ remix_ladspa_replace_handle (env, base);
+ return base;
+
+}
+
+/*
+ * remix_ladspa_1_0:
+ * A RemixChunkChunkFunc for a mono LADSPA sound consumer.
+ */
+static RemixCount
+remix_ladspa_1_0 (RemixEnv * env, RemixChunk * chunk, RemixCount offset,
+ RemixCount count, int channelname, void * data)
+{
+ RemixLADSPA * al = (RemixLADSPA *) data;
+ LADSPA_Descriptor * d;
+ LADSPA_PortDescriptor pd;
+ unsigned long port_i;
+
+ d = al->d;
+
+ /* Connect audio input */
+ for (port_i = 0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_AUDIO_INPUT(pd)) {
+ d->connect_port (al->handle, port_i, &chunk->data[offset]);
+ }
+ }
+
+ d->run (al->handle, count);
+
+ return count;
+}
+
+/*
+ * remix_ladspa_0_1:
+ * A RemixChunkChunkFunc for a mono LADSPA sound generator.
+ */
+static RemixCount
+remix_ladspa_0_1 (RemixEnv * env, RemixChunk * chunk, RemixCount offset,
+ RemixCount count, int channelname, void * data)
+{
+ RemixLADSPA * al = (RemixLADSPA *) data;
+ LADSPA_Descriptor * d;
+ LADSPA_PortDescriptor pd;
+ unsigned long port_i;
+
+ d = al->d;
+
+ /* Connect audio output */
+ for (port_i = 0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_AUDIO_OUTPUT(pd)) {
+ d->connect_port (al->handle, port_i, &chunk->data[offset]);
+ }
+ }
+
+ d->run (al->handle, count);
+
+ return count;
+}
+
+/*
+ * remix_ladspa_1_1:
+ * A RemixChunkChunkFunc for filtering with a mono LADSPA plugin.
+ */
+static RemixCount
+remix_ladspa_1_1 (RemixEnv * env, RemixChunk * src, RemixCount src_offset,
+ RemixChunk * dest, RemixCount dest_offset,
+ RemixCount count, int channelname, void * data)
+{
+ RemixLADSPA * al = (RemixLADSPA *) data;
+ LADSPA_Descriptor * d;
+ LADSPA_PortDescriptor pd;
+ unsigned long port_i;
+
+ d = al->d;
+
+ if (al == NULL) {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+
+ for (port_i = 0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_AUDIO_INPUT(pd)) {
+ d->connect_port (al->handle, port_i, &src->data[src_offset]);
+ }
+ if (LADSPA_IS_AUDIO_OUTPUT(pd)) {
+ d->connect_port (al->handle, port_i, &dest->data[dest_offset]);
+ }
+ }
+
+ d->run (al->handle, count);
+
+ return count;
+}
+
+
+#if 0
+static void
+ladspa_wrapper_apply_region (RemixEnv * env, gpointer pcmdata, sw_format * format,
+ gint nr_frames,
+ sw_param_set pset, void * custom_data)
+{
+ lm_custom * lm = (lm_custom *)custom_data;
+ const LADSPA_Descriptor * d = lm->d;
+ sw_param_spec * param_specs = lm->param_specs;
+
+ LADSPA_Handle * handle;
+ LADSPA_Data ** input_buffers, ** output_buffers;
+ LADSPA_Data * mono_input_buffer=NULL;
+ LADSPA_Data * p;
+ LADSPA_Data * control_inputs;
+ LADSPA_Data dummy_control_output;
+ LADSPA_PortDescriptor pd;
+ long length_b;
+ unsigned long port_i; /* counter for iterating over ports */
+ int i, j, n;
+
+ /* The number of times the plugin will be run; ie. if the number of
+ * channels in the input pcmdata is greater than the number of
+ * audio ports on the ladspa plugin, the plugin will be run
+ * multiple times until enough output channels have been calculated.
+ */
+ gint iterations;
+
+ /* Enumerate the numbers of each type of port on the ladspa plugin */
+ gint
+ nr_ci=0, /* control inputs */
+ nr_ai=0, /* audio inputs */
+ nr_co=0, /* control outputs */
+ nr_ao=0; /* audio outputs */
+
+ /* The number of audio channels to be processed */
+ gint nr_channels = format->channels;
+
+ /* The number of input and output buffers to use */
+ gint nr_i=0, nr_o=0;
+
+ /* Counters for allocating input and output buffers */
+ gint ibi=0, obi=0;
+
+
+ /* instantiate the ladspa plugin */
+ handle = d->instantiate (d, (long)format->rate);
+
+ /* Cache how many of each type of port this ladspa plugin has */
+ for (port_i=0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_CONTROL_INPUT(pd))
+ nr_ci++;
+ if (LADSPA_IS_AUDIO_INPUT(pd))
+ nr_ai++;
+ if (LADSPA_IS_CONTROL_OUTPUT(pd))
+ nr_co++;
+ if (LADSPA_IS_AUDIO_OUTPUT(pd))
+ nr_ao++;
+ }
+
+ /* Basic assumption of this wrapper plugin, which was
+ * checked above in is_usable(); nb. for future expansion
+ * much of this routine is written to accomodate this
+ * assumption being incorrect.
+ */
+ g_assert (nr_ai == nr_ao);
+
+ /* Basic assumption that this plugin has audio output.
+ * Also important as we are about to divide by nr_ao.
+ */
+ g_assert (nr_ao > 0);
+
+ iterations = (gint) ceil(((double)nr_channels) / ((double)nr_ao));
+
+ /* Numbers of input and output buffers: ensure
+ * nr_i >= nr_channels && nr_o >= nr_channels
+ */
+ nr_i = iterations * nr_ai;
+ nr_o = iterations * nr_ao;
+
+ if ((nr_channels == 1) && (nr_ai == 1) && (nr_ao >= 1)) {
+ /*
+ * Processing a mono sample with a mono filter.
+ * Attempt to do this in place.
+ */
+
+ /* Copy PCM data if this ladspa plugin cannot work inplace */
+ if (LADSPA_WRAPPER_IS_INPLACE_BROKEN(d->Properties)) {
+ length_b = frames_to_bytes (format, nr_frames);
+ mono_input_buffer = g_malloc (length_b);
+ input_buffers = &mono_input_buffer;
+ } else {
+ input_buffers = (LADSPA_Data **)&pcmdata;
+ }
+
+ output_buffers = (LADSPA_Data **)&pcmdata;
+
+ } else {
+ length_b = LADSPA_frames_to_bytes (nr_frames);
+
+ /* Allocate zeroed input buffers; these will remain zeroed
+ * if there aren't enough channels in the input pcmdata
+ * to use them.
+ */
+ input_buffers = g_malloc (sizeof(LADSPA_Data *) * nr_i);
+ for (i=0; i < nr_i; i++) {
+ input_buffers[i] = g_malloc0 (length_b);
+ }
+
+ output_buffers = g_malloc(sizeof(LADSPA_Data *) * nr_o);
+
+ /* Create separate output buffers if this ladspa plugin cannot
+ * work inplace */
+ if (LADSPA_WRAPPER_IS_INPLACE_BROKEN(d->Properties)) {
+ for (i=0; i < nr_o; i++) {
+ output_buffers[i] = g_malloc (length_b);
+ }
+ } else {
+ /* Re-use the input buffers, directly mapping them to
+ * corresponding output buffers
+ */
+ for (i=0; i < MIN(nr_i, nr_o); i++) {
+ output_buffers[i] = input_buffers[i];
+ }
+ /* Create some extra output buffers if nr_o > nr_i */
+ for (; i < nr_o; i++) {
+ output_buffers[i] = g_malloc (length_b);
+ }
+ }
+ }
+
+ /* Copy data into input buffers */
+ if (nr_channels == 1) {
+ if (!LADSPA_WRAPPER_IS_INPLACE_BROKEN(d->Properties)) {
+ length_b = frames_to_bytes (format, nr_frames);
+ memcpy (input_buffers[0], pcmdata, length_b);
+ } /* else we're processing in-place, so we haven't needed to set
+ * up a separate input buffer; input_buffers[0] actually
+ * points to pcmdata hence we don't do any copying here.
+ */
+ } else {
+ /* de-interleave multichannel data */
+
+ p = (LADSPA_Data *)pcmdata;
+
+ for (n=0; n < nr_channels; n++) {
+ for (i=0; i < nr_frames; i++) {
+ input_buffers[n][i] = *p++;
+ }
+ }
+ }
+
+ /* connect control ports */
+ control_inputs = g_malloc (nr_ci * sizeof(LADSPA_Data));
+ j=0;
+ for (port_i=0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_CONTROL_INPUT(pd)) {
+ /* do something with pset! */
+ switch (param_specs[j].type) {
+ case SWEEP_TYPE_BOOL:
+ /* from ladspa.h:
+ * Data less than or equal to zero should be considered
+ * `off' or `false,'
+ * and data above zero should be considered `on' or `true.'
+ */
+ control_inputs[j] = pset[j].b ? 1.0 : 0.0;
+ break;
+ case SWEEP_TYPE_INT:
+ control_inputs[j] = (LADSPA_Data)pset[j].i;
+ break;
+ case SWEEP_TYPE_FLOAT:
+ control_inputs[j] = pset[j].f;
+ break;
+ default:
+ /* This plugin should produce no other types */
+ g_assert_not_reached ();
+ break;
+ }
+ d->connect_port (handle, port_i, &control_inputs[j]);
+ j++;
+ }
+ if (LADSPA_IS_CONTROL_OUTPUT(pd)) {
+ d->connect_port (handle, port_i, &dummy_control_output);
+ }
+ }
+
+ /* run the plugin as many times as necessary */
+ while (iterations--) {
+
+ /* connect input and output audio buffers to the
+ * audio ports of the ladspa plugin */
+ for (port_i=0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_AUDIO_INPUT(pd)) {
+ d->connect_port (handle, port_i, input_buffers[ibi++]);
+ }
+ if (LADSPA_IS_AUDIO_OUTPUT(pd)) {
+ d->connect_port (handle, port_i, output_buffers[obi++]);
+ }
+ }
+
+ /* activate the ladspa plugin */
+ if (d->activate)
+ d->activate (handle);
+
+ /* run the ladspa plugin */
+ d->run (handle, nr_frames);
+
+ /* deactivate the ladspa plugin */
+ if (d->deactivate)
+ d->deactivate (handle);
+ }
+
+ /* re-interleave data */
+ if (nr_channels > 1) {
+ p = (LADSPA_Data *)pcmdata;
+
+ for (n=0; n < nr_channels; n++) {
+ for (i=0; i < nr_frames; i++) {
+ *p++ = output_buffers[n][i];
+ }
+ }
+ }
+
+ /* let the ladspa plugin clean up after itself */
+ if (d->cleanup)
+ d->cleanup (handle);
+
+ /* free the input and output buffers */
+ if (control_inputs) g_free (control_inputs);
+
+ if ((nr_channels == 1) && (nr_ai == 1) && (nr_ao >= 1)) {
+ if (LADSPA_WRAPPER_IS_INPLACE_BROKEN(d->Properties)) {
+ g_free (mono_input_buffer);
+ }
+ } else {
+
+ /* free the output buffers */
+ for (i=0; i < nr_o; i++) {
+ g_free (output_buffers[i]);
+ }
+ g_free (output_buffers);
+
+ /* free the input buffers, if we created some */
+ if (LADSPA_WRAPPER_IS_INPLACE_BROKEN(d->Properties)) {
+ for (i=0; i < nr_i; i++) {
+ g_free (input_buffers[i]);
+ }
+ } else {
+ /* inplace worked, but if (nr_i > nr_o), then
+ * we still need to free the last input buffers
+ */
+ for (i=nr_o; i < nr_i; i++) {
+ g_free (input_buffers[i]);
+ }
+ }
+ g_free (input_buffers);
+ }
+}
+#endif
+
+static RemixBase *
+remix_ladspa_connect_control_inputs (RemixEnv * env, RemixBase * base)
+{
+ RemixLADSPA * al = (RemixLADSPA *) remix_base_get_instance_data (env, base);
+ LADSPA_Descriptor * d;
+ LADSPA_PortDescriptor pd;
+ RemixParameter parameter;
+ RemixParameterType type;
+ int j;
+ unsigned long port_i;
+
+ d = al->d;
+
+ if (d == NULL) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ j=0;
+ for (port_i=0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_CONTROL_INPUT(pd)) {
+ type = remix_get_parameter_type (env, base, j);
+ parameter = remix_get_parameter (env, base, j);
+ switch (type) {
+ case REMIX_TYPE_BOOL:
+ /* from ladspa.h:
+ * Data less than or equal to zero should be considered
+ * `off' or `false,'
+ * and data above zero should be considered `on' or `true.'
+ */
+ al->control_inputs[j] = parameter.s_bool ? 1.0 : 0.0;
+ break;
+ case REMIX_TYPE_INT:
+ al->control_inputs[j] = (LADSPA_Data)parameter.s_int;
+ break;
+ case REMIX_TYPE_FLOAT:
+ al->control_inputs[j] = parameter.s_float;
+ break;
+ default:
+ /* This plugin should produce no other types */
+ break;
+ }
+ d->connect_port (al->handle, port_i, &al->control_inputs[j]);
+ j++;
+ }
+ if (LADSPA_IS_CONTROL_OUTPUT(pd)) {
+ d->connect_port (al->handle, port_i, &dummy_control_output);
+ }
+ }
+
+ return base;
+}
+
+static RemixCount
+remix_ladspa_1_0_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixLADSPA * al = remix_base_get_instance_data (env, base);
+ remix_ladspa_connect_control_inputs (env, base);
+ return remix_stream_chunkfuncify (env, input, count, remix_ladspa_1_0, al);
+}
+
+static RemixCount
+remix_ladspa_0_1_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixLADSPA * al = remix_base_get_instance_data (env, base);
+ remix_ladspa_connect_control_inputs (env, base);
+ return remix_stream_chunkfuncify (env, output, count, remix_ladspa_0_1, al);
+}
+
+static RemixCount
+remix_ladspa_1_1_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixLADSPA * al = remix_base_get_instance_data (env, base);
+ remix_ladspa_connect_control_inputs (env, base);
+ return remix_stream_chunkchunkfuncify (env, input, output, count,
+ remix_ladspa_1_1, al);
+}
+
+static RemixCount
+remix_ladspa_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ RemixPlugin * plugin = remix_base_get_plugin (env, base);
+ RemixLADSPA * al;
+ LADSPA_PortDescriptor pd;
+ unsigned long port_i; /* counter for iterating over ports */
+
+ /* Enumerate the numbers of each type of port on the ladspa plugin */
+ int
+ nr_ci=0, /* control inputs */
+ nr_ai=0, /* audio inputs */
+ nr_co=0, /* control outputs */
+ nr_ao=0; /* audio outputs */
+
+ if (plugin == RemixNone) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return -1;
+ }
+
+ remix_ladspa_connect_control_inputs (env, base);
+
+ al = remix_base_get_instance_data (env, base);
+
+ /* Cache how many of each type of port this ladspa plugin has */
+ for (port_i=0; port_i < al->d->PortCount; port_i++) {
+ pd = al->d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_CONTROL_INPUT(pd))
+ nr_ci++;
+ if (LADSPA_IS_AUDIO_INPUT(pd))
+ nr_ai++;
+ if (LADSPA_IS_CONTROL_OUTPUT(pd))
+ nr_co++;
+ if (LADSPA_IS_AUDIO_OUTPUT(pd))
+ nr_ao++;
+ }
+
+ if (nr_ai == 1 && nr_ao == 1) {
+ return remix_stream_chunkchunkfuncify (env, input, output, count,
+ remix_ladspa_1_1, al);
+ } else if (nr_ai == 1 && nr_ao == 0) {
+ return remix_stream_chunkfuncify (env, input, count, remix_ladspa_1_0, al);
+ } else if (nr_ai == 0 && nr_ao == 1) {
+ return remix_stream_chunkfuncify (env, output, count, remix_ladspa_0_1, al);
+ } else {
+ remix_set_error (env, REMIX_ERROR_INVALID);
+ return -1;
+ }
+}
+
+static RemixCount
+remix_ladspa_length (RemixEnv * env, RemixBase * base)
+{
+ return REMIX_COUNT_INFINITE;
+}
+
+static struct _RemixMethods _remix_ladspa_1_0_methods = {
+ remix_ladspa_clone,
+ remix_ladspa_destroy,
+ remix_ladspa_ready, /* ready */
+ remix_ladspa_prepare, /* prepare */
+ remix_ladspa_1_0_process,
+ remix_ladspa_length,
+ NULL, /* seek */
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_ladspa_0_1_methods = {
+ remix_ladspa_clone,
+ remix_ladspa_destroy,
+ remix_ladspa_ready, /* ready */
+ remix_ladspa_prepare, /* prepare */
+ remix_ladspa_0_1_process,
+ remix_ladspa_length,
+ NULL, /* seek */
+ NULL, /* flush */
+};
+
+static struct _RemixMethods _remix_ladspa_1_1_methods = {
+ remix_ladspa_clone,
+ remix_ladspa_destroy,
+ remix_ladspa_ready, /* ready */
+ remix_ladspa_prepare, /* prepare */
+ remix_ladspa_1_1_process,
+ remix_ladspa_length,
+ NULL, /* seek */
+ NULL, /* flush */
+};
+
+
+static struct _RemixMethods _remix_ladspa_methods = {
+ remix_ladspa_clone,
+ remix_ladspa_destroy,
+ remix_ladspa_ready, /* ready */
+ remix_ladspa_prepare, /* prepare */
+ remix_ladspa_process,
+ remix_ladspa_length,
+ NULL, /* seek */
+ NULL, /* flush */
+};
+
+static RemixBase *
+remix_ladspa_optimise (RemixEnv * env, RemixBase * base)
+{
+ RemixLADSPA * al = remix_base_get_instance_data (env, base);
+ LADSPA_Descriptor * d;
+ LADSPA_PortDescriptor pd;
+ unsigned long port_i; /* counter for iterating over ports */
+
+ /* Enumerate the numbers of each type of port on the ladspa plugin */
+ int
+ nr_ci=0, /* control inputs */
+ nr_ai=0, /* audio inputs */
+ nr_co=0, /* control outputs */
+ nr_ao=0; /* audio outputs */
+
+ if (al == NULL) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ d = al->d;
+
+ if (d == NULL) {
+ remix_set_error (env, REMIX_ERROR_NOENTITY);
+ return RemixNone;
+ }
+
+ /* Cache how many of each type of port this ladspa plugin has */
+ for (port_i=0; port_i < d->PortCount; port_i++) {
+ pd = d->PortDescriptors[(int)port_i];
+ if (LADSPA_IS_CONTROL_INPUT(pd))
+ nr_ci++;
+ if (LADSPA_IS_AUDIO_INPUT(pd))
+ nr_ai++;
+ if (LADSPA_IS_CONTROL_OUTPUT(pd))
+ nr_co++;
+ if (LADSPA_IS_AUDIO_OUTPUT(pd))
+ nr_ao++;
+ }
+
+ al->control_inputs = malloc (nr_ci * sizeof (LADSPA_Data));
+
+ if (nr_ai == 1 && nr_ao == 1) {
+ remix_base_set_methods (env, base, &_remix_ladspa_1_1_methods);
+ } else if (nr_ai == 1 && nr_ao == 0) {
+ remix_base_set_methods (env, base, &_remix_ladspa_1_0_methods);
+ } else if (nr_ai == 0 && nr_ao == 1) {
+ remix_base_set_methods (env, base, &_remix_ladspa_0_1_methods);
+ } else {
+ remix_base_set_methods (env, base, &_remix_ladspa_methods);
+ }
+
+ return base;
+}
+
+
+/*
+ * ladspa_wrapper_load_plugins (dir, name, gl)
+ *
+ * form RemixPlugins to describe the ladspa plugin functions that
+ * are in the shared library file "dir/name"
+ */
+static CDList *
+ladspa_wrapper_load_plugins (RemixEnv * env, char * dir, char * name)
+{
+ char path[PATH_LEN];
+ void * module;
+ LADSPA_Descriptor_Function desc_func;
+ const LADSPA_Descriptor * d;
+ LADSPA_PortDescriptor pd;
+ int i, j, k;
+ int valid_mask;
+ RemixPlugin * plugin;
+ RemixMetaText * mt;
+ RemixParameterScheme * scheme;
+ CDList * l, * plugins = CD_EMPTY_LIST;
+#define BUF_LEN 256
+ static char buf[BUF_LEN];
+ struct stat statbuf;
+
+ snprintf (path, PATH_LEN, "%s/%s", dir, name);
+
+ if (stat (path, &statbuf) == -1) return CD_EMPTY_LIST;
+ if (!remix_stat_regular (statbuf.st_mode)) return CD_EMPTY_LIST;
+
+ module = dlopen (path, RTLD_NOW);
+ if (!module) return CD_EMPTY_LIST;
+
+ /* Check that this module has not already been loaded (eg. if it is
+ * a symlink etc.) */
+ for (l = modules_list; l; l = l->next) {
+ if (l->data.s_pointer == module) {
+ dlclose (module);
+ return CD_EMPTY_LIST;
+ }
+ }
+
+ modules_list = cd_list_append (env, modules_list, CD_POINTER(module));
+
+ if ((desc_func = dlsym (module, "ladspa_descriptor"))) {
+ for (i=0; (d = desc_func (i)) != NULL; i++) {
+
+ if (!is_usable(d))
+ continue;
+
+ remix_dprintf ("[ladspa_wrapper_load_plugins] adding %s [%lu] by %s\n",
+ d->Name, d->UniqueID, d->Maker);
+
+ plugin = malloc (sizeof (*plugin));
+
+ mt = remix_meta_text_new (env);
+
+ snprintf (buf, BUF_LEN, "ladspa::%lu", d->UniqueID);
+ remix_meta_text_set_identifier (env, mt, strdup (buf));
+
+ snprintf (buf, BUF_LEN, "Miscellaneous::%s", d->Name);
+ remix_meta_text_set_category (env, mt, strdup (buf));
+
+ remix_meta_text_set_copyright (env, mt, (char *)d->Copyright);
+ remix_meta_text_add_author (env, mt, (char *)d->Maker, NULL);
+
+ plugin->metatext = mt;
+
+ plugin->init_scheme = CD_EMPTY_SET;
+ plugin->process_scheme = CD_EMPTY_SET;
+
+ k=0;
+ for (j=0; j < d->PortCount; j++) {
+ pd = d->PortDescriptors[j];
+ if (LADSPA_IS_CONTROL_INPUT(pd)) {
+ scheme = malloc (sizeof (*scheme));
+
+ scheme->name = (char *)d->PortNames[j];
+ scheme->description = (char *)d->PortNames[j];
+ scheme->type = convert_type (d->PortRangeHints[j].HintDescriptor);
+ valid_mask = get_valid_mask (d->PortRangeHints[j].HintDescriptor);
+ if (valid_mask == 0) {
+ scheme->constraint_type = REMIX_CONSTRAINT_TYPE_NONE;
+ } else {
+ scheme->constraint_type = REMIX_CONSTRAINT_TYPE_RANGE;
+ scheme->constraint.range =
+ convert_constraint (&d->PortRangeHints[j]);
+ }
+ plugin->process_scheme = cd_set_insert (env, plugin->process_scheme,
+ k, CD_POINTER(scheme));
+ k++;
+ }
+ }
+
+ plugin->init = remix_ladspa_init;
+
+ plugin->plugin_data = (void *)d;
+
+ plugin->destroy = NULL;
+
+ plugins = cd_list_append (env, plugins, CD_POINTER(plugin));
+ }
+ }
+
+ return plugins;
+
+#undef BUF_LEN
+}
+
+/*
+ * ladspa_wrapper_load_dir (dir, gl)
+ *
+ * scan a directory "dirname" for LADSPA plugins, and attempt to load
+ * each of them.
+ */
+static CDList *
+ladspa_wrapper_load_dir (RemixEnv * env, char * dirname)
+{
+ DIR * dir;
+ struct dirent * dirent;
+ CDList * plugins = CD_EMPTY_LIST, * l;
+
+ if (!dirname) return plugins;
+
+ dir = opendir (dirname);
+ if (!dir) {
+ return plugins;
+ }
+
+ while ((dirent = readdir (dir)) != NULL) {
+ l = ladspa_wrapper_load_plugins (env, dirname, dirent->d_name);
+ plugins = cd_list_join (env, plugins, l);
+ }
+
+ closedir (dir);
+
+ return plugins;
+}
+
+CDList *
+remix_load (RemixEnv * env)
+{
+ CDList * plugins = CD_EMPTY_LIST, * l;
+ char * ladspa_path=NULL;
+ char * next_sep=NULL;
+ char * saved_lp=NULL;
+
+ /* If this ladspa_wrapper module has already been initialised, don't
+ * initialise again until cleaned up.
+ */
+ if (ladspa_wrapper_initialised)
+ return CD_EMPTY_LIST;
+
+ ladspa_path = getenv ("LADSPA_PATH");
+ if (!ladspa_path)
+ ladspa_path = saved_lp = strdup(default_ladspa_path);
+
+ do {
+ next_sep = strchr (ladspa_path, ':');
+ if (next_sep != NULL) *next_sep = '\0';
+
+ l = ladspa_wrapper_load_dir (env, ladspa_path);
+ plugins = cd_list_join (env, plugins, l);
+
+ if (next_sep != NULL) ladspa_path = ++next_sep;
+
+ } while ((next_sep != NULL) && (*next_sep != '\0'));
+
+ ladspa_wrapper_initialised = TRUE;
+
+ /* free string if dup'd for ladspa_path */
+ if (saved_lp != NULL) free(saved_lp);
+
+ return plugins;
+}
+
+void
+remix_unload (RemixEnv * env)
+{
+ CDList * l;
+
+ if (!ladspa_wrapper_initialised) return;
+
+ for (l = modules_list; l; l = l->next) {
+ dlclose(l->data.s_pointer);
+ }
+
+ modules_list = NULL;
+}
+
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = -I$(top_srcdir)/include -I$(CTXDATADIR)
+
+libdir = $(PACKAGE_PLUGIN_DIR)
+
+CTXDATADIR = $(top_srcdir)/src/ctxdata
+CTXDATA_LIBS = $(top_builddir)/src/ctxdata/libctxdata.la
+
+REMIXDIR = ../../libremix
+REMIX_LIBS = $(REMIXDIR)/libremix.la
+
+lib_LTLIBRARIES = libremix_noise.la
+
+libremix_noise_la_SOURCES = remix_noise.c
+libremix_noise_la_LDFLAGS = -module -version-info 1:0:0
+libremix_noise_la_LIBADD = $(REMIX_LIBS) $(CTXDATA_LIBS)
--- /dev/null
+/*
+ * libremix -- An audio mixing and sequencing library.
+ *
+ * Copyright (C) 2001 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * 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
+ *
+ */
+
+/*
+ * RemixNoise: a noise generator
+ *
+ * Conrad Parker <conrad@metadecks.org>, August 2001
+ */
+
+#include <stdlib.h>
+
+#define __REMIX_PLUGIN__
+#include <remix/remix.h>
+
+/* Optimisation dependencies: none */
+static RemixBase * remix_noise_optimise (RemixEnv * env, RemixBase * noise);
+
+static RemixBase *
+remix_noise_init (RemixEnv * env, RemixBase * base, CDSet * parameters)
+{
+ remix_noise_optimise (env, base);
+ return base;
+}
+
+static RemixBase *
+remix_noise_clone (RemixEnv * env, RemixBase * base)
+{
+ RemixBase * new_noise = remix_base_new (env);
+ remix_noise_optimise (env, new_noise);
+ return new_noise;
+}
+
+static int
+remix_noise_destroy (RemixEnv * env, RemixBase * base)
+{
+ free (base);
+ return 0;
+}
+
+/* An RemixChunkFunc for creating noise */
+static RemixCount
+remix_noise_write_chunk (RemixEnv * env, RemixChunk * chunk, RemixCount offset,
+ RemixCount count, int channelname, void * data)
+{
+ RemixPCM * d;
+ RemixPCM r, rmax = (RemixPCM)RAND_MAX;
+ RemixCount i;
+
+ remix_dprintf ("[remix_noise_write_chunk] (%p, +%ld) @ %ld\n", data, count,
+ offset);
+
+ d = &chunk->data[offset];
+ for (i = 0; i < count; i++) {
+ r = (RemixPCM) random ();
+ r *= 2.0;
+ r /= rmax;
+ *d++ = r - 1.0;
+ }
+
+ return count;
+}
+
+static RemixCount
+remix_noise_process (RemixEnv * env, RemixBase * base, RemixCount count,
+ RemixStream * input, RemixStream * output)
+{
+ return remix_stream_chunkfuncify (env, output, count,
+ remix_noise_write_chunk, base);
+}
+
+static RemixCount
+remix_noise_length (RemixEnv * env, RemixBase * base)
+{
+ return REMIX_COUNT_INFINITE;
+}
+
+static struct _RemixMethods _remix_noise_methods = {
+ remix_noise_clone,
+ remix_noise_destroy,
+ NULL, /* ready */
+ NULL, /* prepare */
+ remix_noise_process,
+ remix_noise_length,
+ NULL, /* seek */
+ NULL, /* flush */
+};
+
+static RemixBase *
+remix_noise_optimise (RemixEnv * env, RemixBase * noise)
+{
+ remix_base_set_methods (env, noise, &_remix_noise_methods);
+ return noise;
+}
+
+static struct _RemixMetaText noise_metatext = {
+ "envstd::noise",
+ "Generators::Noise",
+ "White noise generator",
+ "Copyright (C) 2001 CSIRO Australia",
+ "http://www.metadecks.org/remix/plugins/noise.html",
+ REMIX_ONE_AUTHOR ("Conrad Parker", "conrad@metadecks.org"),
+};
+
+static struct _RemixPlugin noise_plugin = {
+ &noise_metatext,
+ REMIX_FLAGS_NONE,
+ CD_EMPTY_SET, /* new scheme */
+ remix_noise_init,
+ CD_EMPTY_SET, /* process scheme */
+ NULL, /* suggests */
+ NULL, /* plugin data */
+ NULL /* destroy */
+};
+
+CDList *
+remix_load (RemixEnv * env)
+{
+ CDList * plugins = cd_list_new (env);
+
+ plugins = cd_list_prepend (env, plugins, CD_POINTER(&noise_plugin));
+
+ return plugins;
+}
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+AM_CFLAGS = -Wall -pedantic
+
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/ctxdata
+
+REMIX_LIBS = ../ctxdata/libctxdata.la ../libremix/libremix.la ../ctxdata/libctxdata.la -ldl
+
+# Test programs
+
+TESTS_ENVIRONMENT = $(VALGRIND_ENVIRONMENT)
+
+test: check
+
+TESTS = noop sndfiletest
+
+noinst_PROGRAMS = $(TESTS)
+noinst_HEADERS = tests.h
+
+noop_SOURCES = noop.c
+noop_LDADD = $(REMIX_LIBS)
+
+sndfiletest_SOURCES = sndfiletest.c
+sndfiletest_LDADD = $(REMIX_LIBS) @SNDFILE_LIBS@
--- /dev/null
+/*
+ * noop.c
+ *
+ * Copyright (C) 2006 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <remix/remix.h>
+
+#include "tests.h"
+
+int
+main (int argc, char ** argv)
+{
+ RemixEnv * env;
+
+ INFO ("+ Creating new RemixEnv");
+ env = remix_init ();
+
+ INFO ("+ Purging RemixEnv");
+ remix_purge (env);
+
+ return 0;
+}
--- /dev/null
+/*
+ * sndfiletest.c
+ *
+ * Copyright (C) 2006 Commonwealth Scientific and Industrial Research
+ * Organisation (CSIRO), Australia.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <remix/remix.h>
+
+#include "tests.h"
+
+static void non_existant_file (void);
+
+static void
+non_existant_file (void)
+{
+ RemixEnv * env;
+ RemixBase * sf1;
+ RemixPlugin * sf_plugin;
+ CDSet * sf_parms;
+ int sf_path_key;
+ CDScalar name;
+
+ INFO ("Attempting to read non existant file") ;
+
+ env = remix_init ();
+ remix_set_tempo (env, 120);
+ remix_set_channels (env, REMIX_STEREO);
+
+ sf_plugin = remix_find_plugin (env, "builtin::sndfile_reader");
+ sf_parms = cd_set_new (env);
+ sf_path_key = remix_get_init_parameter_key (env, sf_plugin, "path");
+ name.s_string = "bad_file_name.wav" ;
+ sf_parms = cd_set_insert (env, sf_parms, sf_path_key, name);
+ if (sf_plugin == NULL) {
+ FAIL ("Newly created sndfile plugin NULL");
+ }
+
+ sf1 = remix_new (env, sf_plugin, sf_parms);
+}
+
+int
+main (int argc, char ** argv)
+{
+ non_existant_file () ;
+
+ return 0;
+}
--- /dev/null
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# define PRId64 "I64d"
+#endif
+
+/* FIXME: on Mac OS X, off_t is 64-bits. Obviously we want a nicer
+ * way to do it than this, but a quick fix is a good fix */
+#ifdef __APPLE__
+# define PRI_off_t "q"
+#else
+# define PRI_off_t "l"
+#endif
+
+#define INFO(str) \
+ { printf ("---- %s ...\n", (str)); }
+
+#define WARN(str) \
+ { printf ("%s:%d: warning: %s\n", __FILE__, __LINE__, (str)); }
+
+#define FAIL(str) \
+ { printf ("%s:%d: %s\n", __FILE__, __LINE__, (str)); exit(1); }
+
+#undef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))