Marsyas-SWIG -- SWIG based bindings for Marsyas
ABOUT
This package provides bindings into the Marsyas C++ library for
other (Currently 2) programming languages. It allows Marsyas
to be used in these languages as native extensions to those
languages. Most of the code is generated by SWIG.
Currently only a subset of Marsyas' features are supported.
DEPENDENCIES
- Required
-
- Marsyas >= 0.2.8
- GNU Build System
- Optional
-
- Python >= 2.4 (For Python support)
- Ruby >= 1.8 (For Ruby support)
- SWIG >= 2 (To perform changes to *.i files)
INSTALATION
The Marsyas-SWIG package can be installed in one of two ways,
either after a user has installed Marsyas, or as part of the
Marsyas build.
* INDEPENDANTLY *
To install the wrappers on their own, after Marsyas has been
installed, just use the package as if it were any other autotools
package:
$ ./configure [options]
$ make [install]
You may need to pass various {CXX,LD}FLAGS to ./configure if
marsyas was installed to a non-standard location.
* AS PART OF MARSYAS *
If this package is inside the MARSYAS build tree at the root level
(folder with Marsyas' ./configure), then running this package's
configure with the --enable-bindings option will cause the
configure script to assume the containing folder has the marsyas
source code in it, and use the package's libmarsyas.a archive
instead. With a recently patched version of Marsyas, the top-level
configure script will automaticall call the wrapper's script
with the correct arguments if the folder is renamed to swig.
For an unpatched tree:
$ tar xzf marsyas-<version>.tar.gz
$ cd marsyas-<version>
$ tar xzf ../marsyas-swig-<version>.tar.gz
$ ./configure [options]
$ make [install]
$ cd marsyas-swig-<version>
$ ./configure [options] --enable-bindings
$ make [install]
For a patched tree:
$ cd marsyas-<version>
$ tar xzf ../marsyas-swig-<version>.tar.gz
$ mv marsyas-swig-<version> swig
$ ./configure [options] --enable bindings
$ make [install]
* EITHER METHOD *
To enable bindings for a given language pass --with-<language>
to ./configure. All languages are off by default. If SWIG is
present on your system, then modifying *.i files will cause the
appropriate *_wrap.cxx files to be remade.
Also due to the fact that Marsyas doesn't use either libtool or
pkg-config, there is no easy way for the wrappers to know if
support for libmad is enabled. As such the script has a --with-mad
option that must match the choice made for marsyas. Using the
non-standalone method on a patched marsyas tree does this
automatically, however. The same could be said about marsyas'
support for readline, but since that is only used in MSL, which
is not yet supported by this wrapper, the point is moot.
FOLDERS AND FILES OF INTEREST
common/ : The common folder holds the SWIG file marsyas.i which
has all the language neutral definitions of Marsyas objects. You
should read this file to find the list of classes/,ethod supported
by the wrapper.
ruby/ : This folder contains the ruby specific code.
ruby/marsyas-ruby.i : Ruby-Specific SWIG .i file. Includes common
marsyas.i file and adds conversions between C++ and Ruby types.
ruby/marsyas-ruby_wrap.cxx : File generated by SWIG from
marsyas-ruby.i.
ruby/marsyas.rb : Hand-Made Ruby wrapper. Loads the *.so file and
handle the "automagic" Ruby features.
ruby/test.rb : Test-script for a simple soundplayer.
python/ : Python specific code. Most of the stuff here is identical
to the ruby versions, just made to work with python instead.
Currently none of the files are documented.
FEATURES
Supported Languages:
- Ruby
- Python
All of the language bindings support the following :
* MarSystemManager
- The user can create a MarSystemManager object and use
it's create() method to generate any MarSystems than
have registered themselves with it.
- They can query the object for a list of supported
MarSystems.
- Since the user cannot create their own MarSystems
yet, there is no need for the ability to register new
MarSystems.
- Other features haven't been implemented beause I haven't
gotten arround to them, cannot see a need for them,
or haven't determined the best way to implement them.
* MarSystem
- There are no constructors provided for MarSystems since
they are created and managed by a MarSystemManager in
this implementation.
- The MarSystem acts as an abstract base class for all
MarSystems created by the MarSystemManager.
- Currenty supports listing, querying, and changing of
controls through a single set of commands.
- Supports the addMarSystem command for container
MarSystems (like Series)
* MarControlValue
- Most of the languages supported by SWIG (at least
the ones that I'm looking at first) support some form of
run-time dynamic typing (usually duck typing). And so
as a result MarControlValues are unnecessary.
- Languages that do not support this feature (Java, OCAML,
etc...) are not supported (yet..).
The Ruby version also has the following additional features:
* The generation of MarSystem subclasses
- Upon loading the Marsyas package (require "marsyas")
a global MarSystemManager is created and for each
registered MarSystem, a Class is generated in the
Marsyas:: namespace. This class simply calls the create()
method of the global MarSystemManager with the apropriate
arguments and returns the created object.
- This means that all the supported MarSystems can
be created with Marsyas::<MarSystem type>.new "name"
instead of <MarSystemManager instance>.create("<MarSystem
type>","name") which is similar to the supported feature
in the original C++ source.
- The advantage of this technique is that you don't have
to worry about a MarSystemManager at all, and all the
memory will be automatically be managed.
- The disadvantage is that you must still pass
a name to the MarSystem's constructor since the
MarSystemManager.create() method requires a name.
* The automatic generation of "properties" for a MarSystem's controls.
- A MarSystem will automatically have getter/setter
methods for all the controls returned by getControls().
- These methods have the names MarSystem.<control>
and MarSystem.<control>=value and so act like properties.
- Currently these are only supported by MarSystems
generated by the Classes created above, and not through
those generated by a MarSystemManager.
LIMITATIONS
Currently only support for the above exists, and some features
of these classes have not yet been implemented. No other classes
have been implemented, so support for MSL, CommandLineArguments,
etc... doesn't exist at all.
Although subclasses of these types can be created in the target
language, the additions/changes one makes will not be present
to the C++ code. So for example one can create a sub-class to a
MarSystem, but attempting to use it in a network will do nothing
since the methods you create/override will only be present in
the target language, and not be used by other C++ objects.
FAQ
Q: Why not just stick with C++, isn't it "Good Enough"?
A: Not everyone likes/knows C++, and other languages (esp. the
scipting languages supported by SWIG) support features C++ doesn't
have, like dynamic/duck typing, and automatic memory management.
Q: Doesn't the MarSystemManager handle memory management for me?
A: Indeed, the MarSystemManager does keep track of all the
MarSystems you create, and destroys them all upon it's destruction
(or at least it should.), but besides the problems with this
scheme, you still have the rest of your program to worry about.
Q: What about MSL (Marsyas Scripting Language)?
A: From what I can see, MSL will provide a way to describe
networks of MarSystems and make it easy to do things specifically
with Marsyas. These bindings intend to be an alternative to
C++, providing the programmer with access to most of the same
features in the Marsyas API as well as the support libraries
of the language. They are not an alternative/competitor to MSL,
whose purpose is to provide an easier/better alternative to the
Marsyas C++ API. In fact, the MSL classes can and may eventually be
added to the SWIG interface file, and thus MSL could be used
from within one of the wrapper's supported languages.
Q: Do I need Marsyas afterwards?
A: No! As long as the wrapper is built when Marsyas is built as
a static library (currently the only choice) then all the
Marsyas classes & code that the wrapper functions need will be
included as well. As a result the target-language specific shared
object file will have all of the marsyas code built-in, and not be
dependant on libmarsyas.a.
FUTURE
The addition of more methods to the existing classes will be
easy, as long as I can determine how these methods work, and are
supposed to be used. When this package was initially created,
I only had a moderate understanding of marsyas-0.2, and so
only implemented features I understood, and that existed. After
confering with some Marsyas developpers (including George),
I have a better understanding of some of the other features,
as well as the new additions. Eventually these will filter down
into new revisions.
Currently my high-priority concerns include:
- Fixing the Ruby code so all generated MarSystems
have properties for their controls, as well as a way of
accessing contained MarSystems.
Medium Priority:
- Supporting some of the Ruby features in other languages.
- Subclassing MarSystems
Low priority:
- Add new languages (Java,OCAML)
- Support for other classes in the Marsyas Package
Lowest priority:
- Support for languages in SWIG that arent OO
(Lisp,Lua,Scheme)
- Support for languages in SWIG I don't like (Perl,C#)
- Support for TCL (since there already appears to be
bindings in Marsyas)
HISTORY
Originally I created a python module (pysyas) to access some
of the basic features of Marsyas. It was designed using the
Python<->C interface, and was used primarily to add sound to an
OpenGL 3D spinning clock similar to the one found in the System
Configuration dialog of the Playstation 2 Console.
Although the access to the Marsyas system within python was
easy, the code for the module was HUGE (UGH! reference counting)
and UGLY (MACROS upon MACROS upon MACROS).
Upon learning of SWIG and Boost::Python, two easy to use (yet
very different) methods to automatically generate bindings for
Python I decided that I should at some point try again.
I decided to use SWIG since it supported more than just Python
as a target language, and doesn't require the user to have the
Boost::Python library. I then used it to create the marsyas
wrapper for Ruby (my new favorite scripting language).
