Initial revision

git-svn-id: svn://localhost/trunk/ardour2@4 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Taybin Rutkin 2005-05-13 20:47:18 +00:00
commit d09f6b3016
1253 changed files with 292928 additions and 0 deletions

5
.cvsignore Normal file
View file

@ -0,0 +1,5 @@
.sconf_temp
.sconsign.dblite
ardour.rc
config.log
scache.conf

340
COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

154
ChangeLog Normal file
View file

@ -0,0 +1,154 @@
2001-10-27 Paul Davis <pbd>
* gtk_ardour/editor_ops.cc (ensure_selection): fixed selection
start not-assigned error in ensure_selection().
2001-10-26 Paul Davis <pbd>
* gtk_ardour/editor.cc (Editor): use scroll timeut whenever the
editor is active, instead of stopping and starting it.
2001-10-23 Paul Davis <pbd>
* gtk_ardour/mixer_strip.cc (update_diskstream_display):
rationalize rec_enable button handling to be equivalent to same
code elswhere.
* gtk_ardour/trackview.cc (record_enable_blink): add rec enable button
* gtk_ardour/ardour_ui.cc (start_clocking): use SigC::Signals for
Clock and Blink updates
* gtk_ardour/marker.cc (set_position): fixed persistent error in
marker location, caused by not taking the shift into account
whenever the position was reset.
* gtk_ardour/editor.cc (initialize_canvas): make the playhead
cursor sit above the edit cursor.
2001-10-20 Paul Davis <pbd>
* gtk_ardour/editor_ops.cc (ensure_selection): make
add_location_from_selection work again (now ensure_selection()
works again).
* ardour_ui.rc: added styles for new rulers.
* gtk_ardour/regionview.cc (move_to): make gain control points be
rects
2001-10-19 Paul Davis <pbd>
* gtk_ardour/regionview.cc (ControlPoint): change colors of gain curves
* massively split up editor code to try to produce more
rapidly-compilable compilation units.
2001-10-17 Paul Davis <pbd>
* gtk_ardour/editor_mouse.cc (start_grab): clean up start grab
code, and make playhead cursor grab stop the transport, restarting
it again when done.
* gtk_ardour/ardour_ui.cc (add_diskstream): try to make recorder
window the correct size.
2001-10-13 Paul Davis <pbd>
* gtk_ardour/diskstream_ui.cc (DiskStream_UI): make sure that all
input buttons are the same width, regardless of their label contents.
2001-10-05 Paul Davis <pbd>
* gtk_ardour/editor_mouse.cc (button_release_handler): button2 on
a RegionItem always mutes/unmutes/raises/lowers, regardless of
mouse mode.
2001-10-04 Paul Davis <pbd>
* gtk_ardour/editor_mouse.cc (region_drag_motion_callback): edit
clock reflect region sync point rather than cursor during drag.
(button_release_handler): button press/release on cursors +
markers always initiate a grab, regardless of mouse mode.
* gtk_ardour/editor.cc (track_canvas_allocate): return the edit
cursor to a full height line.
* gtk_ardour/grouped_buttons.cc (GroupedButtons): backpedalled
from this being a GTK widget to just a C++ object that manipulates
a set of buttons.
* gtk_ardour/trackview.cc (set_height): put edit controls in their
own event window so that we can control color, etc.
* gtk_ardour/canvas-simplerect.c (gtk_canvas_simplerect_render):
don't draw vertical lines at end of box (kludge!)
* gtk_ardour/editor.cc (add_region_to_region_display): copy
Regions before putting them in the Region list. this prevents
playlist-edits from altering the state of the "original".
2001-10-03 Paul Davis <pbd>
* gtk_ardour/editor_ops.cc (split_region): operate only on the
uppermost region, not all those stacked at this location.
2001-09-30 Paul Davis <pbd>
* gtk_ardour/editor_mouse.cc (start_grab): don't raise the grabbed
item to the top of the canvas stack. it must already have been
visible, so don't do this - it confuses regionview stacking.
2001-09-28 Paul Davis <pbd>
* gtk_ardour/marker.cc (Marker): center marker shape on the actual
location; use frame position rather than canvas position in API.
* gtk_ardour/streamview.cc (StreamView): add a simplerect to show
the edge of the track *and* to help us get canvas events for the
track in areas where there is no region.
* gtk_ardour/editor_ops.cc (soundfile_chosen_for_insert): make
insert_sndfile() work again, including a working ensure_cursor()
* gtk_ardour/marker.cc (Marker): add black outline around marker shapes
2001-09-27 Paul Davis <pbd>
* gtk_ardour/editor_ops.cc: implement partial support for nudge variations
* gtk_ardour/editor_mouse.cc (start_selection): add initial
support for mouse-based selection.
* gtk_ardour/editor.cc (Editor): add support for GUI control of
edit groups.
* gtk_ardour/editor_keys.cc (install_keybindings): add KP_{6,4}
since we don't get KP_{Right,Left} by default.
* gtk_ardour/ardour_ui.cc (add_diskstream): put recorder stuff
(meters, etc) in a separate window.
* gtk_ardour/plugin_ui.cc (build_control_ui): fix problem with
destructor logic that caused double destruction of
ControlUIs. also use Gtk-- functions for PluginUIadjustment.
2001-09-26 Paul Davis <pbd>
* gtk_ardour/editor_keys.cc (install_keybindings): added some
more keybindings for the editor.
2001-09-25 Paul Davis <pbd>
* gtk_ardour/editor_mouse.cc (region_drag_motion_callback): fixed
segv caused by referencing a null drag_info.last_trackview
pointer. this occured when the mouse moved into an area where
no trackview was, and then back again.
* gtk_ardour/marker.cc: added initial support for Canvas-based markers
* gtk_ardour/keyboard_target.cc (translate_key_name):
differentiate between Alt and Meta, and Alt(R|L) and Meta(R|L)

2
DOCUMENTATION/.cvsignore Normal file
View file

@ -0,0 +1,2 @@
Makefile.in
Makefile

71
DOCUMENTATION/AUTHORS Normal file
View file

@ -0,0 +1,71 @@
Paul Davis (Philadelphia, PA) was and is the primary author of Ardour.
Taybin Rutkin (New York, NY) has contributed lots of code, and was
particularly responsible for the use of XML in the state persistence
aspect of the program. He also (re)wrote the soundfile library code to
use LRDF. In addition he was responsible for the integration of the
gettext system and the compose() templates that make Ardour's
internationalization possible. He has consistently made suggestions
that resulted in significantly more elegant code and design. Taybin
also set up and oversees the Mantis bug reporting system used by all
of us, and tends to take on "infrastructure" issues such as the switch
to SCons as the build system.
Jesse Chappell (Washington, DC) keeps on making major contributions to
Ardour. It almost seems pointless to list the things he has worked on
because there is so much of it. They include being able to handle
multichannel tracks, a major change in the program's design and
capabilities, and many additions/improvements to the GTK GUI,
including mouse zoom mode and the route params editor. Jesse was the
first person to just "walk in" and understand the Ardour codebase.
Marcus Andersson (Karlstad, Sweden) contributed a number of useful
patches and worked on the dB-related issues in the gain stages and
metering, other numeric computations, and much useful debugging, bug
reporting and analysis.
Jeremy Hall (Sterling, VA) contributed several patches and worked
intensively on ksi_ardour, the keystroke-based-interface to libardour
designed for sight-impaired and GUI-averse users.
Steve Harris (Southampton, UK) contributed code to handle speed-based
interpolation, an area I did not want to get my head around, as well
as dithering, panning, metering and other DSP-centric issues. He also
wrote the LRDF library used by Ardour's soundfile library code, not to
mention dozens of LADSPA plugins that make Ardour a genuinely useful
tool.
Tim Mayberry (Brisbane, Australia) did lots and lots and lots of work
on mouse-driven editing.
Nick Mainsbridge <beatroot@optushome.com.au> is responsible for many
improvements to the rulers, and several other tweaks.
Colin Law wrote the code that supports Ardour's integration with
the CMT Animatics engine. He was also very involved in refactoring the
GUI code design to support different kinds of tracks, thus laying the
groundwork for extending ardour's domain to include MIDI and video.
Gerard van Dongen (Rotterdam, Netherlands) has done a set of scattered
but critical work with a vague focus on the mouse. He has made some
particularly important fixes to the incredibly hairy code that draws
automation curves. Gerard also helped out with a workshop on Ardour
held at the Dutch Electronic Arts Festival, Rotterdam, in November
2004.
Smaller (but not necessarily minor) patches were received from the
following people:
Mark Stewart
Sam Chessman (Reston, VA)
Jack O'Quin (Austin, TX)
Matt Krai
Ben Bell
Thomas Charbonnel (Lyon, France)
Robert Jordens
Christopher George
Rob Holland
Joshua Leachman
Sampo Savolainen
Per Sigmond

78
DOCUMENTATION/AUTHORS.es Normal file
View file

@ -0,0 +1,78 @@
Paul Davis (de Philadelphia, PA) fue y es el principal autor de Ardour.
Taybin Rutkin (de New York, NY) ha contribuido grandes cantidades de
codigo y fue particularmente responsable por el uso de XML en el
aspecto de persistencia de estado del programa. Tambien escribio y
reescribio el codigo relativo a la libreria soundfile (archivo de
sonido) para que use LRDF. Ademas fue responsable por la integracion
del sistema gettext y los esquemas compose() que hacen posible la
internacionalizacion de Ardour. Ha hecho constantes sugerencias las
cuales resultaron en codigo y disenio significativamente mas elegantes.
Taybin tambien configuro y administra el sistema Mantis de reporte de
bugs (errores de codigo) usado por todos nosotros.
Jesse Chappell (de Washington, DC) continua haciendo grandes
contribuciones a Ardour, particularmente en el hecho de que Ardour sea
capaz de manejar pistas multicanal, un cambio mayor en el disenio del
programa y capacidades. Tambien hizo muchos agregados y mejoras a la
interfaz visual de GTK, incluyendo el modo de zoom mediante mouse y el
editor de parametros de ruteo. Jessie fue la primera persona en "pasar"
y entender las bases del codigo de Ardour.
Marcus Andersson (de Karlstad, Sweden) contribuyo un numero de patches
(actualizaciones) utiles y trabajo con los problemas relacionados a "dB"
en las etapas de gain (volumen) y vumetros, otras computaciones numericas
y muy util debugging, reporte de bugs y analisis.
Jeremy Hall (de Sterling, VA) contribuyo varios patches y trabajo
intensamente con ksi_ardour, que es la interfase basada en teclas de la
libreria libardour diseniada para no videntes y amantes de lineas de
comando (consolas).
Steve Harris (de Southampton, UK) contribuyo codigo para manejar
interpolacion basada en velocidad, un area en la cual no me queria meter,
asi como dithering, balance, vumetros y otros temas relacionados con
procesamiento de senial. Tambien escribio la libreria LRDF usada por
el codigo de Ardour de la libreria soundfile, sin mencionar docenas
de plugins LADSPA que hacen a Ardour una herramienta genuinamente util.
Tim Mayberry (de Brisbane, Australia) hizo mucho, mucho, mucho trabajo
en cuanto a edicion basada en mouse.
Nick Mainsbridge <beatroot@optushome.com.au> es responsable de muchas
mejoras a los medidores/lineas/referencias de tiempo.
Colin Law <> escribio el codigo que soporta la integracion de Ardour
al sistema de Animatics CMT. Tambien se ocupo en el redisenio del codigo
de la interfase visual para soportar diferentes tipos de pistas.
Mas pequenios (preo no necesariamente menores) patches fueron recividos
de las siguientes personas:
Mark Stewart
Sam Chessman (Reston, VA)
Jack O'Quin (Austin, TX)
Matt Krai
Ben Bell
Gerard vanDongen (Rotterdam, Netherlands)
Thomas Charbonnel (Lyon, France)
Robert Jordens
Nota de Traduccion (Spanish Translation Note)
---------------------------------------------
#Nota del tipeo:la letra pronunciada ENIE aparece en este archivo
#como ni (letra "n" y letra "i") para mayor compatibilidad con todos
#los visores de texto.
#Asi mismo no se han aplicado las tildes(acentos).
#Estos no son errores de tipeo. Si llegara a encontrar algun otro error
#en cualquiera de los archivos con extension ".es" por favor
#hagamelo saber a alexkrohn@fastmail.fm
# Muchas gracias
# Alex

145
DOCUMENTATION/BUILD Normal file
View file

@ -0,0 +1,145 @@
HOW TO BUILD ARDOUR FROM SOURCE
-------------------------------
Please: before you do anything else, take a moment to go and join the
ardour-dev mailing list (members only). It is very important that the
community of people using, testing and developing this software are on
the list, and I will NOT deal with questions relating to Ardour's
compilation or bugs that are not sent to that list. See
http://ardour.org/ for details on joining the mailing list.
You can also get in touch with developers and users on IRC. Joining
#ardour at irc.freenode.net. The core developers and several key users
hang out here on IRC, at pretty much any hour of the night or day.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Full information on building Ardour can be found at:
http://ardour.org/building.php
Information has been left in this file for those who do not have
network access but is not guaranteed to be accurate or up to date.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
COMPILING
------------
Please ensure that before attempting to compile Ardour, you have
installed:
* Tools:
gcc/g++ 3.x or above
scons 0.96 or above
gettext 0.12.1 or above
pkgconfig 0.8.0 or above
http://www.freedesktop.org/software/pkgconfig/
lex and yacc are also required.
any verison of bison >= 1.35 should work fine.
* Libraries:
Recommended versions, where applicable, are shown under the general
requirement.
JACK 0.99.50 (CVS or snapshot release) (http://jackit.sourceforge.net)
libxml2 2.5.X (http://xmlsoft.org/)
libart_lgpl 2.3.X
- available as part of gnome-libs, which you may already
have on your system.
- also available via download from GNOME source FTP sites.
- see ftp://ftp.gnome.org/pub/GNOME/MIRRORS.html
and then follow to sources/libart_lgpl
glib 1.2 (http://www.gtk.org)
glib-1.2.8 (included with most distributions)
GTK+ 1.2 (http://www.gtk.org)
gtk+-1.2.8 (included with most distributions)
libsndfile (http://www.mega-nerd.com/libsndfile/)
libsndfile-1.0 or higher
libsamplerate (http://www.mega-nerd.com/SRC/)
libsamplerate 0.0.13 or higher
the LADSPA SDK (http://www.ladspa.org/)
(See below)
raptor (http://librdf.org/raptor/)
lrdf (needs raptor) (http://plugin.org.uk/lrdf/)
liblrdf 0.4.0 or higher (earlier versions will
causes crashes when using plugin presets)
Getting LADSPA
---------------
The Linux Audio Developers Simple Plugin API (LADSPA) really only
consists of a header file, which is already included in the Ardour
source tree.
However, you may want the plugins that come the "full" LADSPA "SDK",
so go ahead and download the whole package (it's not big) from
www.ladspa.org.
I would also recommend getting Steve Harris' excellent set of LADSPA
plugins from http://plugin.org.uk/. They make Ardour into a truly
useful application. Other LADSPA plugins will be appearing - be sure
to watch the Linux Audio Development mailing list for announcements.
2A) COMPILING FROM CVS
---------------------
Checkout the source from Ardour CVS (the `%' here is meant to be your
shell prompt):
% cd /usr/local/src # just an example, it can be anywhere
% cvs -d:pserver:anoncvs@ardour.org:/cvsroot/ardour login
# you will need to contact
# paul at linuxaudiosystems dot com
# to get the passphrase. See
# http://ardour.org/download.html
# for details on why this is.
% cvs -d:pserver:anoncvs@ardour.org:/cvsroot/ardour -z3 co ardour
2B) COMPILING FROM A TARBALL
----------------------------
As usual, fetch and unpack the tarball. The directory it creates,
ardour-<version>, is referred to below as "$AD".
3) HOW TO COMPILE
-----------------
We use the wonderful scons build system, which is started by just typing:
scons
in the top level directory of the ardour source tree.
To speed things up, on a uniprocessor system, use "scons -j2", and on
an SMP system try "scons -j3", which will do a parallel build
(constructing more than one thing at a time).
If you want to build ardour so that it can be debugged, you may wish
to use the DEBUG=yes option. Without it, ardour is built with
extreme optimization turned on and the result cannot be debugged
effectively.
If you don't want the installation to happen in the "usual place", add
a PREFIX=/my/preferred/prefix option to scons.
Compilation takes a while. Running with scons -j3 on a dual PII-450,
the entire build takes about 20 minutes, about the same time with
scons -j2 on 2.6GHz P4.
Other scons options can be discovered using "scons --help"

215
DOCUMENTATION/BUILD.ru Normal file
View file

@ -0,0 +1,215 @@
КАК СОБРАТЬ ARDOUR ИЗ ИСХОДНЫХ ТЕКСТОВ
--------------------------------------
Пожалуйста внимание: прежде чем приступить к работе с Ardour, найдите
время чтобы подписаться на список рассылки разработчиков. Это очень
важно, потому что сообщество людей, использующих, тестирующих и
разрабатывающих Ardour, общаются в этом списке рассылки, и я НЕ БУДУ
отвечать на вопросы относительно сборки или ошибок в работе Ardour,
если они не будут заданы в этом списке. Подробнее об этом читайте на
странице http://ardour.sf.net/ или http://ardour.org/, где указано
как подписаться на список рассылки.
Этот документ написан для пользователей, хорошо знающих процесс сборки
программного обеспечения из исходных текстов с использованием пакетов
GNU automake и autoconf. Если Вы не знакомы с этим, тогда возможно вам
придётся подождать до тех пор, пока не появятся релизы Ardour, не требующие
сборки из исходных текстов (binary releases).
1) ПРАВИЛЬНОЕ ИСПОЛЬЗОВАНИЕ GNU AUTOCONF
----------------------------------------
GNU autoconf весьма мощная система, однако у неё имеется как минимум
один существенный недостаток. По умолчанию autoconf (aclocal) ведёт
поиск требуемых файлов только в ОДНОМ каталоге. Это нормально работает,
кроме случаев, когда в системе установлены другие пакеты, размещающие
свои файлы autoconf или в каталоге /usr/local/lib/share/aclocal,
или /usr/lib/share/aclocal.
В результате, autoconf часто не может найти файлы, требуемые для сборки
Ardour, к тому же у многих пользователей одновременно имеются копии
библиотек, установленных разными способами: из исходных текстов (файлы
autoconf обычно находятся в каталоге /usr/local/lib...) и из собранных
пакетов (в этом случае файлы располагаются в каталоге /usr/lib...).
Рекомендуется указать расположение каталогов autoconf путем определения
в переменной ACLOCAL_FLAGS всех путей поиска.
Сначала найдите все aclocal директории:
$ locate /aclocal/
и проверьте (найдите) все каталоги, содержащие файлы с расширением ".m4" .
Затем задайте переменную окружения ACLOCAL_FLAGS, как указано ниже
(в качестве примера):
export ACLOCAL_FLAGS="-I /usr/share/aclocal -I /usr/local/share/aclocal -I /opt/gnome/share/aclocal"
Вы можете добавить эту строку в файлы .bashrc или .profile в вашем домашнем
каталоге, она будет исполняться каждый раз при входе в систему.
-----
Грубое и менее деликатное решение, описанное ниже, подразумевает слияние
всех директорий aclocal. Это не может быть рекомендовано, хотя этот
вариант также работает.
Пожалуйста, проверьте содержимое обеих директорий перед тем как делать
"слияние", чтобы случайно не стереть корректную версию копий файлов
autoconf:
* Если у вас есть оба каталога:
cd /usr/lib/share/aclocal
cp *.m4 /usr/local/lib/share/aclocal
cd ..
rm -rf aclocal
ln -s /usr/local/lib/share/aclocal .
* Если имеется только /usr/lib/share/aclocal
cd /usr/local/lib
ln -s /usr/lib/share/aclocal .
В некоторые дистрибутивах linux aclocal находится в различных местах.
2. КОМПИЛЯЦИЯ
-------------
Перед тем как компилировать Ardour убедитесь, что у вас установлены
следующие компоненты:
* Программы и утилиты:
gcc/g++ версии 2.95.3 или выше (gcc/g++ 3.x works also)
autoconf 2.52 или выше
automake 1.5 или выше
libtool 1.4.2 или выше
gettext 0.11.5 или выше
pkgconfig 0.8.0 или выше
http://www.freedesktop.org/software/pkgconfig/
требуются также lex и yacc.
любая версия bison >= 1.35 должна работать.
* Библиотеки:
Рекомендуемые версии, которые должны работать, показаны ниже.
ALSA 0.9.X (CVS или текущий релиз) (http://www.alsa-project.org)
JACK (http://jackit.sourceforge.net)
libxml2 2.5.X (http://xmlsoft.org/)
libart_lgpl 2.3.X
- обычно является частью gnome-libs, которые как правило
уже установлены
- в противном случае вы можете загрузить библиотеку с FTP-сайта
исходных текстов GNOME.
- см. ftp://ftp.gnome.org/pub/GNOME/MIRRORS.html
и ищите в sources/libart_lgpl
glib 1.2 (http://www.gtk.org)
glib-1.2.8 (включено в большинство дистрибутивов)
GTK+ 1.2 (http://www.gtk.org)
gtk+-1.2.8 (включено в большинство дистрибутивов)
libsndfile (http://www.zip.com.au/~erikd/libsndfile)
libsndfile-1.0 или выше
libsamplerate (http://www.mega-nerd.com/SRC/)
libsamplerate 0.0.13 или выше
the LADSPA SDK (http://www.ladspa.org/)
(см. ниже)
raptor (http://www.redland.opensource.ac.uk/raptor/)
lrdf (needs raptor) (http://plugin.org.uk/lrdf/)
liblrdf 0.4.0 или выше
Установка LADSPA
----------------
Сегодня описание интерфейса Linux Audio Developers Simple Plugin API
(LADSPA) содержит только заголовочный файл (header file), который
уже включён в дерево исходных текстов Ardour.
Тем не менее, вы можете захотеть установить и модули LADSPA plugins,
которые входят в состав полного пакета LADSPA SDK. Его можно найти и
загрузить (размер пакета небольшой) по адресу www.ladspa.org.
Также, я рекомендую загрузить прекрасный набор модулей (plugins) LADSPA
от Steve Harris с сайта http://plugin.org.uk/. Это намного повысит
полезные возможности Ardour. Со временем появятся и другие модули LADSPA,
чтобы быть в курсе - следите за анонсами в списке рассылки Linux Audio
Development.
2A) Компилирование из CVS
-------------------------
Загрузите или обновите дерево исходных текстов Ardour из CVS. (В приведённом
ниже примере символ '%' означает приглашение командной строки):
% cd /usr/local/src # в качестве примера, вы можете сделать это где
пожелаете
% cvs -d:pserver:anoncvs@ardour.org:/cvsroot/ardour login
# (нажмите Enter/Return когда появится приглашение
к вводу пароля)
% cvs -d:pserver:anoncvs@ardour.org:/cvsroot/ardour -z3 co ardour
2A.1) ЧЕМ РАЗЛИЧАЮТСЯ СПОСОБЫ СБОРКИ ИЗ CVS ?
---------------------------------------------
Итак, вам нужно решить, являетесь ли вы разработчиком ardour или
пользователем. Если вы относите себя к первым из перечисленных, то возможно
ускорить работу, собрав библиотеку libardour как разделяемую. Это позволит
избавиться от перелинковки после каждого внесения изменений в эту библиотеку.
Если вы просто пользователь, этот шаг лишь осложнит вам жизнь. Итак,
если вы разработчик, тогда выполните следующую команду:
touch ardour/libs/ardour/BUILD_FOR_DEVELOPMENT
Теперь библиотека libardour будет скомпилирована как разделяемая (shared).
Также вы должны использовать ключ --enable-development-build в команде
configure.
2A.2) ПОДГОТОВКА К СБОРКЕ ИЗ ИСХОДНЫХ ТЕКСТОВ
---------------------------------------------
Создайте autoconf/automake файлы:
% cd ardour
% sh autogen.sh
Теперь переходим к пункту 3.
2B) СБОРКА ИЗ АРХИВА ИСХОДНЫХ ТЕКСТОВ (tar.gz)
----------------------------------------------
Всё как обычно, загрузите и распакуйте архив. Файлы исходных текстов
будут находиться в каталоге с именем ardour-<номер версии>.
3) КАК СКОМПИЛИРОВАТЬ
---------------------
./configure (с любыми опциями которые пожелаете)
make
make install
Если вы являетесь разработчиком и намереваетесь поработать над libardour,
используйте опцию --enable-development-build, которая включает динамическую
линковку ardour и его библиотек. Это позволит сэкономить время, так как
позволит избежать медленной процедуры статической линковки каждый раз, как
вы поменяете что-либо в libardour.
Если вы хотите скомпилировать Ardour так, чтобы в дальнейшем его можно
было запустить в отладчике, используйте опцию --disable-optimize.
В противном случае Ardour будет собран с максимальной оптимизацией,
что помешает эффективной отладке.
Как обычно в команде ./configure вы можете использовать опции --prefix
и --sysconfdir, чтобы изменить расположение файлов программы. Они будут
помещены по указанным путям командой "make install".
Компилирование исходных текстов может занять некоторое время. К примеру,
с ключом - j3 на системе dual PII-450 занимает около 20 минут.

View file

@ -0,0 +1,61 @@
In addition to those listed in the AUTHORS file, the following people
are among those who offered financial support, design insights and
ideas, encouragement, feedback, bug reports and much more during
Ardour's pre-release development. They generally suffered from days of
frustration, and withstood hundreds of CVS revisions without
complaint.
No thanks or praise is sufficient for their contributions to Ardour.
(in no particular order)
Joe Hartley
Marek Peteraj
Ryan Gallagher
Rob Holland
Jan Depner
Bryan Koschmann
Patrick Shirkey
Rob Fell
Ant <avan@uwm.edu>
Chris Ross
Joshua Pritikin
Rohan Drape
Johan De Groote
Bob Ham
I would particularly like to recognize:
Frank Carmickle
- first financial supporter of Ardour,
instigator of ardour/ksi.
Ron Parker (Minneapolis, MN)
- first user of Ardour in a commercial studio,
financial contributor, major initiator of
MTC and MMC functionality.
DuWayne Holsbeck
- an early financial and infrastructure sponsor
Havoc Pennington & Owen Taylor
- provided much assistance in understanding, diagnosing and
cajoling GTK+.
Tom Pincince (Shasta, CA)
- provided continuous, excellent design insights and
rationalizations, as well as info on the operation of some
existing DAW's.
I would also like to thank Jim Hamilton of Rittenhouse Recording,
Philadelphia, for the partnership, friendship and foresight he showed
in allowing me to use the studio as the development basis for
Ardour. I met Jim playing a jazz drumkit at a fundraiser to celebrate
the 30th anniversary of our children's nursery school. Since then, he
has continued to open my eyes to both music itself, the process of
making music, and the life of a working musician. Jim's the best and
most inventive percussionist I have ever seen, and one of the best
I've ever heard. He has always believed in the social and philosphical
implications of Ardour, and his support and interest have been vital
in Ardour's development. Although as of this writing, Rittenhouse
Recording is not running Ardour, its only a matter of time!

View file

@ -0,0 +1,82 @@
Ademas de aquellos que aparecen mencionados en el archivo AUTHORS.es,
las siguientes personas estan entre aquellas que ofrecieron soporte
financiero, observaciones de disenio e ideas, animo, aportes, reportes
de bugs (errores en codigo) y mucho mas durante el desarrollo del
pre lanzamiento de Ardour. Generalmente, ellos sufrieron de dias de
frustracion y soportaron cientas de revisiones de CVS sin quejas.
Ninguna plegaria o agradecimiento posible es suficiente por sus
contribuciones a Ardour.
(en ningun orden en particular)
Joe Hartley
Marek Peteraj
Ryan Gallagher
Rob Holland
Jan Depner
Bryan Koschmann
Patrick Shirkey
Rob Fell
Ant <avan@uwm.edu>
Chris Ross
Joshua Pritikin
Rohan Drape
Johan De Groote
Bob Ham
Quisiera destacar particularmente a:
Frank Carmickle
- primer brinadador de soporte financiero a Ardour,
instigador de ardour/ksi.
Ron Parker (de Minneapolis, MN)
- primer usuario de Ardour en un estudio comercial,
contribuidor financiero, iniciador mayor de
funcionalidad MTC and MMC.
DuWayne Holsbeck
- dominio de disenio de sponsors linuxaudiosystems.com ,
configuro la base de datos bugzilla y mas.
Havoc Pennington & Owen Taylor
- brindaron mucha asistencia en cuanto a comprension,
diagnostico y simplificacion de GTK+.
Tom Pincince (de Shasta, CA)
- contribuyo continuas y exceles observaciones de disenio y
racionalizaciones, asi como informacion acerca de
estaciones de trabajo de audio digital existentes.
Tambien quisiera agradecer a Jim Hamilton de Rittenhouse Recording,
Philadelphia, for el companierismo, amistad y vision que demostro
al permitirme usar el estudio como base de desarrollo para Ardour.
Conoci a Jim tocando percusion jazz en un evento de recaudacion de
fondos para celebrar el 30imo aniversario de la guarderia escolar de
nuestros hijos. Desde entonces me ha abierto los ojos a ambos, la musica
misma, el proceso de hacer musica y la vida de un musico trabajando.
Jim es el mejor y mas inventivo percusionista que haya visto, y uno
de los mejores que he oido. El siempre ha creido en las implicaciones
filosoficas y sociales de Ardoury su soporte e interes han sido vitales
en el desarrollo de Ardour. Es solo cuestion de tiempo hasta que
Rittenhouse Recording use Ardour.
Nota de Traduccion (Spanish Translation Note)
---------------------------------------------
#Nota del tipeo:la letra pronunciada ENIE aparece en este archivo
#como ni (letra "n" y letra "i") para mayor compatibilidad con todos
#los visores de texto.
#Asi mismo no se han aplicado las tildes(acentos).
#Estos no son errores de tipeo. Si llegara a encontrar algun otro error
#en cualquiera de los archivos con extension ".es" por favor
#hagamelo saber a alexkrohn@fastmail.fm
# Muchas gracias
# Alex

613
DOCUMENTATION/FAQ Normal file
View file

@ -0,0 +1,613 @@
The Ardour FAQ
January 23, 2004
--Problems--
1.1. Why can't I get configure to run when ...
1.2. I'm getting syntax errors during build.
1.3. I get the warning: "Gtk-WARNING **: Unable to locate image file in
1.4. What's an xrun?
1.5. The region area overlaps the buttons in the editor.
1.6. Ardour keeps freezing. Here's the strace...
1.7. What is "ardev" and why is it a shell script?
1.8. How do I debug this thing?
1.9. I want Ardour to run faster.
--Features--
2.1. Are plugins supported?
2.2. Are VST plugins supported?
2.3. Does Ardour run on non-Linux systems?
2.4. Ardour needs to have this feature now.
2.5. Why doesn't Ardour support MP3s?
2.6. Does Ardour support MIDI?
2.7. What soundfile formats are supported?
2.8. Can I use multiple cards?
2.9. How do I save captures across partitions?
--Usability--
3.1. How do I pan stereo outputs?
3.2. Where's the patch bay?
3.3. How do I do stuff?
--Misc--
4.1. What's the deal with JACK, LAAGA, and Audioengine?
4.2. Is Ardour internationalized?
4.3. How do I get support?
4.4. Well, where's the manual?
4.5. Why are all these libraries included? I already have ...
4.6. Why not another frontend to libardour? Why not QT?
--------------------------------------------------------------------------------
--Problems--
1.1. Why can't I get configure to run when ...
You can only run configure at the top level of the Ardour source
tree. You don't want to know why this is true. Don't try to work
around it.
1.2. I'm getting syntax errors during build.
This probably means that you are using an out of date library. Or you
might be using a very new library that has changed its API. Check the
version number. If it is lower than what is listed in the BUILD file,
update your library. If it is higher than what is listed in the BUILD file,
email the mailing list. Note that you have to be a member of the mailing
list to send mail to it, which is done to prevent the list from receiving
much spam.
1.3. I get the warning: "Gtk-WARNING **: Unable to locate image file in
pixmap_path: "set-next-button.xpm"
The most common cause of this error is simply that you have not set
the pixmap pathname correctly. It can be specified in the Ardour
config file. See the BUILD file.
1.4. What's an xrun?
It's a generic term used to describe a situation where the software
did not keep up with the hardware, either by feeding it data, or by
collecting data from it. It generally means that you're having
trouble with latency. This can be caused by several factors. You
could have a misconfigured system, you might be trying to do to much,
or both.
If you're haven't read http://www.linuxdj.com/audio/lad/resourceslatency.php3,
then your system is probably misconfigured.
If you are running many many tracks, with multiple LADSPA plugins, then it
is possible that your system just can't keep up with what you want to do.
Either simplify your music, or upgrade your machine. A dual processor does
wonders.
You can test your setup with the latencytest tool, available at
http://www.linuxdj.com .
Jan Depner's HOWTO is loaded with latency tuning tips for Ardour:
http://myweb.cableone.net/eviltwin69/ALSA_JACK_ARDOUR.html
1.5. The region area overlaps the buttons in the editor.
Make sure that you are using the appropriate font size for your monitor's
resolution. If you are running at 1024x768 or below, you should use the
75dpi package, not the 100dpi. This is usually set in /etc/X11/XF86Config.
1.6. Ardour keeps freezing. Here's the strace...
The results from strace aren't very useful. To provide helpful information
to the developers, run Ardour under gdb. If you don't know how to use
gdb, this isn't the time to learn. If you do know how to use gdb, read
section 1.8.
1.7. What is "ardev" and why is it a shell script?
This is only applicable if configure was run with --enable-development-build.
To speed up the process of developing Ardour, we do not statically
link Ardour and its library, libardour. Instead, we use dynamic
linking, which allows the developers to avoid the (very) long
relinking step when they make certain kinds of changes to libardour.
This means that the executable image for Ardour relies on the system
being able to find libardour whenever you start it. Rather than leave
this to chance and/or the whims of your system adminstrator (probably
yourself), we instead use a short shell script to make sure that the
connection between the two of them can be established.
This has almost zero impact on any aspect of Ardour's operation. The
only noticeable effect is that it makes debugging slightly more
difficult. See 1.8 for more on this.
1.8. How do I debug this thing?
+-------------------------------------------------------------------------+
| NOTE: Newer versions of gdb and/or glibc and/or the kernel have broken
| gdb in a critical way that make it impossible to run ardour. The gdb
| development group claim to have fixed this, but on many
| distributions, the version that is provided is still broken.
|
| Under such circumstances, you will have to get a core dump from
| ardour, and then use gdb to analyse the core dump, rather than
| using gdb as a "live tool".
|
| Many distributions set the default core dump size to 0, to prevent
| core dumps completely. So the first step is to do enter this
| at your shell prompt (in a terminal window):
|
| ulimit -c 9999999999
|
| Then run ardour in whatever way causes a crash. after the crash
| you should find a file called "core" in your working directory.
| then run:
|
| gdb ardour core
|
| When the gdb> prompt appears, type
|
| backtrace
|
| Collect the output, and file it as an attachment to a Mantis
| bug report at http://ardour.org/mantis
|
| Thanks for helping to improve Ardour.
+------------------------------------------------------------------------+
A) How to start gdb ....
A1) IF YOU DID NOT USE --enable-development-build
You can use gdb the usual way:
% cd /where/you/built/ardour
% gdb ardour
A2) IF YOU USE --enable-development-build
The first and most basic thing you need to know is how to invoke
gdb. Because of the dynamic linking between Ardour and its library you
can't just invoke Ardour and get it to work. Besides, "ardour" itself
is a shell script (see 1.10 for more on this). So, what you need to do
is to invoke gdb with LD_LIBRARY_PATH set to point to the place where
libardour is installed, and use the name of actual executable image.
If you installed in the default location, this command will invoke gdb
correctly:
env LD_LIBRARY_PATH=/usr/local/lib/ardour gdb /usr/local/lib/ardour/ardourx
If you used a --prefix argument during the build process so that
Ardour would be installed somewhere other than under /usr/local, then
replace /usr/local in the command above with whatever "prefix" you
used.
You could easily make the above a shell alias or a 1 line shell script
if you think you'll be debugging Ardour with gdb a lot.
A3) ABOUT LADSPA PLUGINS AND GDB
Moving all your LADSPA plugins out of the way will make gdb very much
quicker to start. For example, if you normally keep them in
/usr/local/lib/ladspa, you could do something like:
mkdir /usr/local/lib/LADSPA
mv /usr/local/lib/ladpsa/* /usr/local/lib/LADSPA
gdb doesn't do very well when forced to handle dozens of dynamically
loaded objects, as typically happens with LADSPA plugins.
It might be easier to redefine LADSPA_PATH to a dummy path.
B) What to do with gdb
When Ardour has crashed or is "stuck", issue the following command
to gdb (you will need to use Ctrl-C if its "stuck" to get back to the
gdb command prompt):
thread apply all bt
collect the output from this, and then go to
http://ardour.org/mantis
and file a new bug report with the output attached. This will allow
us to get the most out of your misfortune.
If you compiled ardour from source and want to be even more helpful,
recompile it after running
./configure --disable-optimize
at the top level. This will make the debugging output more useful.
1.9. I want Ardour to run faster.
The --enable-optimize flag is enabled by default which turns
on compiler features that can make Ardour run up to 50% faster.
If you downloaded Ardour as a binary package, it should have been
compiled with that flag already.
--Features--
2.1. Are plugins supported?
LADSPA plugins are supported. To use them, click the middle mouse
button in the top box at the top of the mixerstrip you wish to have a
plugin for. This opens up a window which lists all the plugins. Double
click on the one you wish to use. In the mixer window, click on the
plugin to toggle it on and off, option-click to edit its values, or
shift-click to remove it.
2.2. Are VST plugins supported?
There are several issues here:
1) Generic VST support
Many people have asked about VST support within Ardour. Work has been
done on this, but there are both license issues and technical
ones. The licensing issues seem relatively easy to resolve.
On the technical front, given that the goal is to not require VST
developers to build new native Linux versions of their plugins, the
most promising approach involves using Wine to support native
Windows VST plugins. It is already possible to run most VST plugins as
JACK clients and thus use them as inserts with Ardour, but the process
of doing so is not what most users would term "convenient".
However, Wine cannot currently be used within a complex
multithreaded application. The Wine development team are working on
this, and as a rough guess, I'd expect progress within about 6 months
(i.e end of 2003). At that time, it will be possible to use most VST
plugins that have their own GUI ("editor") from within Ardour.
However, initially, this functionality will be available only as
part of a for-cost distribution of Ardour.
2) Specific plugins
a) executable format issues
Plugins are pieces of executable code. The format used for
the files that store this code is different under windows
and macos than it is for linux. Some people have managed
to find workarounds for this --- there are reports of people
running windows-derived buzz plugins under linux, but nobody
has looked into trying it with vst plugins.
Linux also runs on a lot more hardware than windows or MacOS.
We assume that when you say linux, you mean "linux on an intel
compatible processor", but keep in mind that to most of us,
linux means more than that --- it includes the PPC, Sparc, Alpha,
ARM, MIPS and many other chip architectures. Of that list,
only PPC has any VST plugin support at all.
This problem would go away if a VST plugin was available as source
code, but to my knowledge, only 1 is (freeverb).
b) OS dependency issues
Most VST plugin writers do not follow Steinberg's design advice,
and write plugins that have operating system dependencies. As
a result, even if you could find a way to actually use, say,
a windows-format VST plugin on Linux on an Intel machine, the
plugin would contain calls to operating system services that
don't exist (in the same way) under Linux.
So, the basic answer is "no". I am an active member of the VST-plugins
mailing list, and I try to encourage people who write free plugins to
make their source code available so that we can use it under Linux, as
well as reminding people to try to avoid operating system dependencies
in their plugins. I think this mostly falls on deaf ears.
2.3. Does Ardour run on non-Linux systems?
Ardour depends on the JACK system to access the sound hardware. Jack
has (as of this writing) support for Linux, Solaris, and MacOSX. There
have not been any reports of running Ardour on any platforms besides Linux
though.
In addition, Ardour has abstracted the JACK dependency, so it can be ported
to use another sound library. But at the time, it only uses the JACK
library. The JACK website is http://jackit.sf.net/.
2.4. Ardour needs to have this feature now.
Paul accepts donations through his paypal account. The feature will
(probably) be added more quickly if you pay him. Contact him first.
2.5. Why doesn't Ardour support MP3s?
Ardour is meant for serious audio work. MP3 is a lossy format
unsuitable for this. Ardour does export sessions to wav format, which
is trivial to convert to MP3.
2.6. Does Ardour support MIDI?
Ardour currently supports MIDI in the sense of:
* functioning as a MIDI Timecode master (it generates MTC)
* functioning as a MIDI Timecode slave (experimental; send reports!)
* understanding MIDI Machine Control
* allowing the user to bind GUI controls (sliders, etc.) to
MIDI Continuous Controller and NoteOn/NoteOff messages
It does not offer any facilities for editing or arranging or recording
or playing MIDI data. There has been talk of integrating Midi
Mountain, an excellent midi editor. There hasn't been any progress in
this direction lately, mostly due to other areas that need to be fixed
up. It's not a trivial affair if the integration is going to proceed
in a way leaves the result feeling "natural".
2.7. What soundfile formats are supported?
It depends on what version of libsndfile is installed. This link lists the
latest formats: http://www.mega-nerd.com/libsndfile/#Features
Please note that Ardour requires the 1.x series of libsndfile.
2.8. Can I use multiple cards?
In a word: maybe.
The sync issues that arise even between the same make and model of a card
aren't worth the effort of fixing. If you want to have more than two
channels, buy a professional card.
On the other hand, if you already have two professional cards with word-sync,
you might be able to get them to work. This is several layers removed from
Ardour; the proper place to ask for help is at http://www.alsa-project.org .
There is more information at http://www.linuxdj.com/audio/quality/#multi
2.9. How do I save captures across partitions?
Ardour lets you specify multiple directories to save captured audio
in. In the options editor, in the session path box, specify the full
paths of the directories you wish to use, seperated by colons (:).
These can be on different partitions or even different disks. Using
this "software RAID"-like setup can greatly increase your disk
bandwidth.
--Usability--
3.1. How do I pan stereo outputs?
Panning works over JACK ports. So even if you have two outputs
connected to one port, Ardour doesn't consider this to be stereo. You
need to make sure that you have two ports, and then add one (or more)
destination to each port.
You need to think of the ports as if they were physical sockets to
which you can connect as many plugs as you want. A single port means
mono, even though you can send the signal to many different
places. Two ports means stereo, even though the right and left signals
can each go to any number of different places.
3.2. Where's the patch bay?
There is no separate dedicated patch bay. Patch bay functionality
is integral to the mixer. The mixer can have any number of inputs,
any number of busses, etc. In other words, it *is* the patchbay.
3.3. How do I do stuff?
Region Dragging (object mode)
-----------------------------
click-drag => moves region
shift-click-drag => moves region with time position held constant
(i.e. across tracks)
ctl-click-drag => moves a copy of the region
ctl-shift-click-drag => time-constrained movement of a copy of the
region
snapmod-click-drag => ignores current snap setting
Region Alignment (clicks without motion)
----------------
[ all alignment uses:
1) current region selection, if it exists
2) else the edit cursor
]
ctl-click => aligns start of region
ctl-shift-click => aligns end of region
ctl-alt-click => aligns sync point of region
Marks
-----
click in tempo track to create a new tempo mark
click in meter track to create a new meter mark
click in marker track to create a new marker
regular edit op for tempo/meter allows editing
regular delete op for all markers (except initial
tempo/meter markers)
snapmod-click-drag to move a marker while ignoring
current snap mode
Editing
-------
default is ctl-button3 click
Deletion
--------
default is shift-button3 click
Context Menu
------------
button3 click
Snap Modifier
-------------
default is mod3 (typically meta/windows/start key). using
ctl or shift or alt will cause problems. you can also
use combinations, but again, combinations using ctl and shift
will cause problems. mod3 or mod4 are probably your best
choices.
Selection (RANGE MODE required)
---------
click on a region => make a region selection
shift-click on a region => add region to region selection
click-drag => make a range selection
shift-click-drag => add to range selection
ctrl-click-drag => move selection
Separation
----------
in range mode:
a) make a single range selection
then, to split existing region apart
b) right click => Selection => Separate region
OR, to creates a new region without splitting original
b) switch to object mode
c) click on selection and drag
solo/mute/rec-enable
--------------------
to toggle solo/mute/RE for EVERYTHING:
ctl-shift-click on a solo/mute/RE button
to solo/mute/RE mix group (when group is not active)
ctl-click on solo/mute button
to toggle solo-safe status (which appears to not work
correctly right now)
shift-click on solo button
to momentarily engage solo while pressing a mouse button
use button2 instead of button1
gain sliders
------------
shift-click to reset to 0dB
ctl-click-drag for finer scale
ctl-alt-click-drag for even finer scale
panners
-------
(stereo): shift-click to reset to center
--Misc--
4.1. What's the deal with JACK?
JACK is the Jack Audio Connection Kit. There is a basic problem with
audio+MIDI apps on Linux at this time: they are not able to exchange
data with each other in situations where low latency is a system goal.
There are systems (aRts, MidiShare, parts of alsa-lib) that allow data
sharing, but not when the latencies get down below 20ms.
JACK is an API that solves this problem. Also, and quite importantly,
JACK drastically simplifies the programming of audio applications.
Applications that use JACK do not need to know anything about audio
hardware. They do not interact with it directly in any way
whatsoever. All they do is provide a few callbacks to the server they
connect with; the primary callback is responsible for producing and/or
consuming a specified amount of data whenever it is called. This is a
'callback' model, and is extremely different from ALSA, OSS, and
several other audio APIs. It is, however, very similar to Apple's
CoreAudio, Steinberg's ASIO, the PortAudio library, and most plugin
APIs. See http://jackit.sf.net/
4.2. Is Ardour internationalized?
Parts of Ardour are. Work is ongoing to fully internationlize Ardour. If
you speak a language besides English, feel free to volunteer to help
translate.
These languages have translations:
gtk-ardour:
French, German, Italian, Portuguese, Brazilian Portuguese, and Russian
libardour:
Italian
4.3. How do I get support?
Ardour is a volunteer project. There is no one devoted to providing
support. However, there is a members only mailing list where someone
might answer your question. You can join at Ardour's website:
http://ardour.org/
There is also the IRC #ardour channel on the FreeNode network.
Alternatively, you can pay Paul for specific support. Check with him
for hourly rates.
4.4. Well, where's the manual?
Currently, the existing documentation is sparse. You might want to check out
the Protools reference; Ardour is rather similar to it. Also, Paul wants
users to be able to complete the Mackie HDR tutorial using Ardour; so that
is another manual to check out. Both are available online from
<a href=http://digidesign.com/support/documents.html>DigiDesign</a> and <a
href=http://mackie.com>Mackie</a>.
There is the begining of a manual in Ardour's manual directory. Feel
free to create your own HOWTOs, tips and tricks sheets, tutorials, or
whatever you feel like adding.
A couple people have written some documentation to get people started with
Ardour. It is available at http://www.djcj.org/LAU/ardour/
4.5. Why are all these libraries included? I already have ...
Yes, we know that it's quite likely that you already have gtkmm or
sigc++ installed on your machine, let alone others. There
are 2 problems.
Ardour requires either the latest version of these libraries or even a
version with a patch that has not yet been incorporated into a release
of the library. Rather than require you to get the library source,
patch it, recompile and install it, Ardour keeps its own copy, builds
a static, private version of the library and links against it. That
way, we don't have to worry about crashes caused by you having the
wrong version of the library.
The second problem is more general. C++ does not yet have a unified
"Application Binary Interface", even on a single process
architecture+OS combination. This is unlikely to ever change (it was
encouraged by the inventor of C++). This means that libraries compiled
with one compiler are not always compatible with applications compiled
with another compiler. By "another compiler", we can mean something as
subtle as a different version of g++. Worse, because many C++
libraries feature inlined code, we even need to be sure you compile
against exactly the same version of the library as other parts of
Ardour will use. Even worse, there are compile time flags you or
someone else could give to a C++ compiler that would make the library
incompatible in subtle ways with code compiled with different flags.
After a year of trying to address these problems "the normal way", the
Ardour team gave up and decided to include every necessary library
that is written in C++ and/or has patches required. You may not like
this very much, but trust us, you would like the alternative even
less.
4.6. Why not another frontend to libardour? Why not QT?
The GTK+ frontend to libardour is almost 7 times the size of libardour. GUIs
for these sort of programs are very large and detail orientated. It would be
a waste of time to try to reimplement Ardour with another widget set. This is
also why there won't be a native port of Ardour to MacOS X.

101
DOCUMENTATION/README Normal file
View file

@ -0,0 +1,101 @@
ARDOUR README
Paul Davis <paul@linuxaudiosystems.com> June 2003
Welcome to Ardour. This program is still very much under development,
but has now reached the stage where it will be productive and useful
to have other people testing it out and perhaps (hopefully!) fixing
bugs and adding features.
**** SECURITY *******************************************************
To run Ardour with the lowest latencies, it's necessary to use POSIX
Real-Time Scheduling as well as locking all the memory it uses into
physical RAM. These requirements can only be met if Ardour is run with
root priviledges.
On the other hand, things are not so bad. If you don't attempt to
install it setuid root (which actually won't work anyway), then
someone needs to have gained root access in order to run it like this.
If they already have root access, Ardour is the least of your
problems. So relax. We'll use capabilities once Linux kernels start
arriving with them enabled, though this won't help too much with
security, since the relevant capabilities would still allow a wiley
cracker to do anything at all.
Alternatively, you can choose to run Ardour without RT scheduling, and
then there's no concern at all. It just won't be useful in low latency
situations, which are desirable in most studio environments. Note that
this is not so important if you have audio hardware that is capable of
doing "hardware monitoring" - in this case, a lack of low latency will
simply make response to Ardour's UI controls a little sluggish, but
monitoring during capture will be excellent.
**** HARDWARE COMPATIBILITY *****************************************
Ardour uses JACK for all its audio I/O, thus providing seamless
connections to both audio hardware and other applications. Its really
not the right place to discuss JACK, but in case you are wondering:
Although JACK uses the ALSA 0.9.0 API, it exercises this API in a way
that no other application to date has done, and it also tries to use
certain hardware features that again, no other existing applications
use. As a result, although complete portability to all ALSA supported
h/w is an eventual and very achievable goal, there may be issues
surrounding h/w compatibility. Please remember that my primary goal
with JACK is to build a professional audio system, and with Ardour, a
professional digital audio workstation. If they happen to be useful
for people with 2/4 channel cards, then great, but it's not my own
primary focus.
One other important issue is that your audio interface must support
full duplex i/o with the same sample format for both capture and
playback. This means, for example, that the SoundBlaster AWE cannot
be used with JACK in full duplex mode - it only supports full duplex
i/o if one of the two directions (capture or playback) is 8 bit and
the other is 16. Very few cards have this kind of limitation, and if
they do, they typically are not suitable for use with applications
like JACK or Ardour for other reasons.
To date, JACK has been run with:
RME Hammerfall (Digi9652) (26 channels in, 26 channels out)
RME Hammerfall DSP (hdsp) (26 channels in, 26 channels out)
RME Hammerfall Light (Digi9636) (18 channels in, 18 channels out)
Midiman Delta series (ice1712 chipset) (12 channels in, 10 channels out)
Various consumer grade audio interfaces, typically with 2 channels
in, 2/4 channels out, including:
Hoontech 4Dwave-NX (Trident chipset)
Ensoniq 5880
Soundblaster 32
Soundblaster 64
Creative SBLive64
and many more.
So, basically, it appears to work for just about all ALSA supported
cards, which is the goal.
**********************************************************************
BUG REPORTING
-------------
Bugs should be reported to http://ardour.org/mantis/ . They are more
likely to be remembered and dealt with there. Please check the existing bugs
to make sure it has not already been reported and/or fixed in CVS.
COMPILING ARDOUR
----------------
Please see the file "BUILD".
RUNNING ARDOUR
--------------
NOTE: You must have a running JACK server before starting Ardour.
-----------------------------------------------------------
Typing "ardour" will hopefully have some effect. "ardour --help" lists
available options.

139
DOCUMENTATION/README.es Normal file
View file

@ -0,0 +1,139 @@
ARDOUR README.es
Paul Davis <paul@linuxaudiosystems.com> June 2003
Bienvenido a Ardour. Este programa aun esta bajo desarrollo,
pero ha llegado a un estado en el cual es productivo y util tener
a otras personas probandolo y tal vez (con suerte!) arreglando errores
y agregando nuevas caracteristicas.
**** SEGURIDAD *******************************************************
Para ejecutar Ardour con la mas baja latencia posible, es necesario usar
POSIX Real-Time Scheduling (tiempo Real) como tambien bloquear toda la
memoria que usa en la memoria fisica de la RAM. Estos requerimientos solo
se pueden cumplir si Ardour es ejecutado con privilegios de usuario root.
Por otro lado, esto no es tan malo. Si no planea instalar a Ardour
usando el comando "setuid root"(lo cual no funcionaria de todas formas),
entonces alguna persona que use su estacion de trabajo debera tener
que haber "ganado" privilegios de acceso root para hacerlo funcionar
de esa forma.Si esa otra persona ya tiene acceso de tipo root, Ardour
es la menor de sus preocupaciones. Asi que, relajese. Usaremos
capabilities (privilegios root) una vez que los Kernels de Linux empiecen
a aparecer con estas ya activadas, aunque esto no ayudara mucho a la
seguridad, ya que las mencionadas "capabilities" habilitarian a cualquier
hacker astatuto a hacer lo que quiciera.
Alternativamente, usted puede elegir ejecutar a Ardour sin Scheduling
de Tiempo Real, lo cual no es tan terrible. Simplemente no va a ser util
en situaciones que demandan baja latencia, las cuales son deseables en
la mayoria de los ambientes de estudios.
Note que esto pierde importancia en el caso que usted disponga de
hardware de audio capaz de hacer "monitorizacion por hardware". Esto
hace recaer gran parte del peso de procesamiento sobre el dispositivo
de audio y no sobre el CPU como es el caso de la "monitorizacion por
software". En el caso de monitorizacion por hardware, la falta de baja
latencia hara que los controles de la interfaz visual de Ardour
reaccionen con menos fluidez, sin embargo la monitorizacion durante la
captura sera excelente.
**** COMPATIBILIDAD DE HARDWARE *************************************
Ardour usa JACK para todo el manejo de entradas y salidas de audio,
lo cual provee conecciones directas al hardware de audio y a otras
aplicaciones compatibles con JACK. Este no es el lugar mas apropiado
para discutir acerca de JACK, pero en caso de que se estubiera
preguntando:
Aunque JACK usa la libreria ALSA 0.9.0, JACK la aprovecha de una forma
que ninguna otra aplicacion lo ha hecho hasta ahora y, tambien intenta
usar ciertas caracteristicas de hardware que nuevamente, ninguna de las
actuales aplicaciones usa. Como resultado, aunque una completa
portabilidad a todo el hardware soportado por ALSA es un objetivo
eventualmente realizable, puede ser que nazcan problemas relacionados
con la compatibildad de hardware. Por favor recuerde que mi objetivo
principal con JCK es el de crear un sistema profesional de audio y, con
Ardour, una estacion de trabajo de audio digital profesional. Si estos
terminan siendo utiles para personas con placas de 2/4 canales, muy bien,
pero ese no es mi foco de interes principal.
Otro punto importante es que su dispositivo de sonido debe soportar
full duplex de entrada/salida (reproduccion y grabacion simultaneas)
con el mismo formato para la captura y la reproduccion (no se puede
usar una frecuencia de muestreo de 44.1 khz para reproducir y una
de 48khz para grabar, ambas deben ser iguales, lo mismo sucede para
la resolucion en bits. Esto significa, por ejemplo, que la placa
SoundBlaster AWE no puede ser usada con JACK en modo full duplex.
-Esta placa solo soporta fullduplex si una de las dos (grabacion o
reproduccion) usa 8 bits y la otra 16 bits.
Este tipo de limitacion existe solo en algunas placas y, de ser asi
no son adecuadas para el uso en aplicaciones como JACK y ARDOUR por
otras razones.
Hasta la fecha, JACK fue probado con las siguientes interfaces de audio:
RME Hammerfall (Digi9652) (26 channels in, 26 channels out)
RME Hammerfall DSP (hdsp) (26 channels in, 26 channels out)
RME Hammerfall Light (Digi9636) (18 channels in, 18 channels out)
Midiman Delta series (ice1712 chipset) (12 channels in, 10 channels out)
Varios chips de sonido de nivel de consumidor (relativamente baratas),
tipicamente con 2 canales de entrada y 2/4 de salida,incluyendo:
Hoontech 4Dwave-NX (chipset Trident)
Ensoniq 5880
Soundblaster 32
Soundblaster 64
Creative SBLive64
y muchas mas.
Asi que, basicamente, parece funcionar con practicamente todas aquellas
placas que son soportadas por ALSA, lo cual es el objetivo.
**********************************************************************
REPORTES DE ERRORES EN CODIGO (BUGS)
-------------------------------------
Los bugs deben ser reportados a http://ardour.org/mantis/ . Es mas probable
que estos sean recordados y analizados alli. Por favor, chequee alli la lista
de bugs ya reportados para asegurarse que el que usted encontro no haya sido
reportado aun o haya sido resuelto en CVS.
PARA COMPILAR ARDOUR
--------------------
Vea el archivo "BUILD" (por ahora en ingles, espaniol mas adelante).
EJECUTANDO ARDOUR
-----------------
NOTA: Debe haber ya un server JACK corriendo antes de ejecutar Ardour
---------------------------------------------------------------
* Escribiendo ardour en una consola y presionando ENTER o INTRO deberia iniciar
el programa.
* "ardour --help" muestra las opciones disponibles desde la linea de comando
Nota de Traduccion (Spanish Translation Note)
---------------------------------------------
#Nota del tipeo:la letra pronunciada ENIE aparece en este archivo
#como ni (letra "n" y letra "i") para mayor compatibilidad con todos
#los visores de texto.
#Asi mismo no se han aplicado las tildes(acentos).
#Estos no son errores de tipeo. Si llegara a encontrar algun otro error
#en cualquiera de los archivos con extension ".es" por favor
#hagamelo saber a alexkrohn@fastmail.fm
# Muchas gracias
# Alex

113
DOCUMENTATION/README.fr Normal file
View file

@ -0,0 +1,113 @@
ARDOUR -- LISEZ-MOI
Paul Davis <paul@linuxaudiosystems.com> Juin 2003
Bienvenue sur Ardour. Ce programme est encore en cours de développement,
mais a atteint un état où il peut être utile et productif afin que
d'autres personnes puissent le tester et peut-être (je l'espère !) corriger
les bogues et ajouter des fonctionnalités.
**** SÉCURITÉ *******************************************************
Afin d'utiliser Ardour avec un temps de latence le plus bas possible,
il est nécessaire d'utiliser l'ordonnancement temps réel POSIX ainsi
que de verrouiller toute la mémoire qu'il utilise en mémoire vive physique.
Ces pré requis ne peuvent être atteint que lorsque Ardour est lancé
avec les privilèges du super-utilisateur (root).
D'un autre côté, ce n'est pas si grave que ça. Si vous n'essayez pas
de l'installer en setuid root (ce qui ne marchera pas de toute façon),
alors les utilisateurs devront avoir obtenu l'accès root pour pouvoir le
lancer comme cela. S'ils ont déjà l'accès root, Ardour est bien le dernier
de vos problèmes. Donc tranquillisez-vous. Nous utiliserons les "capacités"
(capabilities en anglais, NdT) quand les noyaux Linux arriverons avec
leur support activé, bien que les capacités en question autoriserons
toujours un cracker mal intentionné à faire à peu près n'importe quoi.
L'alternative est de lancer Ardour sans ordonnancement temps-réel, dans
ce cas, il n'y a plus de souci. Ardour ne sera juste plus très utile
dans des conditions de faible latence, ce qui est désirable dans la
plupart des environnements de studio. Notez que cela n'est pas si important
lorsque vous avez du matériel audio qui est capable de faire du
"monitoring matériel" -- dans ce cas, un temps de latence trop important
provoquera juste des temps de réponse un peu longs pour l'interface
utilisateur d'Ardour, mais le monitoring pendant l'enregistrement
sera excellent.
**** COMPATIBILITÉ MATÉRIELLE *****************************************
Ardour utilise JACK pour toutes ses entrés/sorties audio, fournissant
ainsi des connexions transparentes au matériel audio ainsi qu'à d'autres
applications. Cela n'est pas du tout l'endroit pour parler de JACK,
mais dans le cas où vous vous poseriez la question :
Bien que JACK utilise l'API (Application Programming Interface, NdT) ALSA
0.9.0, il utilise cette API d'une manière que nulle autre application
ne l'a jamais fait jusqu'à présent, et essaie aussi d'utiliser certaines
possibilités matérielles qui également n'ont jamais été employées par
d'autres applications. En conséquence, bien que la portabilité complète de
tout matériel supporté par ALSA est un objectif très atteignable, il peut
y avoir des problèmes concernant la compatibilité matérielle. Veuillez
garder en mémoire que le but principal avec JACK est d'obtenir
un système audio professionnel, et avec Ardour, d'obtenir une station
de travail audio-numérique professionnelle. S'ils parviennent à être
utilisés par des gens avec des cartes audio ayant 2/4 canaux, génial,
mais ce n'est pas ma priorité.
Un autre problème important est que votre interface audio doit supporter
l'entrée/sortie en mode full duplex avec le même format d'échantillonage
pour l'enregistrement que pour la restitution. Cela veut dire, par exemple,
que la SoundBlaster AWE ne peut être utilisée par JACK en mode full duplex
-- elle supporte seulement l'entrée/sortie en full duplex si l'une des
deux directions (enregistrement ou restitution) est en 8 bits et
que l'autre est en 16 bits. Très peu de cartes ont cette limitation,
et si c'est le cas, elles ne sont de toute façon pas adéquates pour des
utilisations avec des applications telles que JACK ou Ardour pour d'autres
raisons.
À ce jour, JACK a été utilisé avec :
RME Hammerfall (Digi9652) (26 canaux en entrée, 26 canaux en sortie)
RME Hammerfall DSP (hdsp) (26 canaux en entrée, 26 canaux en sortie)
RME Hammerfall Light (Digi9636) (18 canaux en entrée, 18 canaux en sortie)
Midiman Delta series (ice1712 chipset) (12 canaux en entrée, 10 canaux en sortie)
Diverses interface audio grand public, généralement avec deux canaux d'entrée, deux
canaux de sortie, incluant :
Hoontech 4Dwave-NX (Trident chipset)
Ensoniq 5880
Soundblaster 32
Soundblaster 64
Creative SBLive64
et bien d'autres.
Donc, pour résumer, il semble fonctionner pour toute carte supporté par ALSA, ce qui
est le but.
**********************************************************************
RAPPORT DE BOGUES
-----------------
Les bogues doivent être rapportés sur http://ardour.org/mantis/. Ils seront
certainement plus à même d'être conservés et traités à cet endroit. Veuillez
consulter les bogues existant afin d'être sûr que le votre n'a pas déjà été
rapporté et/ou corrigé dans le CVS.
COMPILER ARDOUR
---------------
Veuillez consulter le fichier "BUILD".
LANCER ARDOUR
-------------
NOTE : Vous devez avoir un serveur JACK lancé avant de lancer Ardour.
--------------------------------------------------------------
Taper "ardour" devrait sans doute avoir quelque effet. "ardour --help" liste
les options disponibles.

276
DOCUMENTATION/README.it Normal file
View file

@ -0,0 +1,276 @@
ARDOUR README.it
Paul Davis <paul@linuxaudiosystems.com> June 2003
Italian Traslation by Vieri Verze <poe@softhome.net> August 2002
Update by Filippo Pappalardo <filippo@email.it> December 2003
Benvenuti in Ardour. Sebbene questo programma sia ancora in via di
sviluppo, e` pronto a rendervi produttivi, permettervi di testarlo
e (si spera!) risolvere i bug e aggiungere nuove caratteristiche.
**** SICUREZZA *******************************************************
Per eseguire Ardour con la latenza piu` bassa e` necessario usare il
POSIX Real-Time Scheduling e disporre di tutta la memoria di cui ha
bisogno sotto forma di RAM fisica. Queste richieste possono essere
soddisfatte soltanto se Ardour viene eseguito con i privilegi di root.
D'altra parte non tutto il male viene per nuocere. Se non installate
Ardour con setuid root (che comunque non funziona), gli altri avranno
bisogno dei privilegi di root per eseguirlo. Se li hanno Ardour e` il
vostro ultimo problema. Quindi rilassatevi. Implementeremo le
capabilities non appena il kernel le supportera`, benche` questo non
aiuti molto la sicurezza, dal momento che un cracker intelligente
potra` comunque fare di tutto.
In alternativa, potete scegliere di esguire Ardour senza il RT
scheduling e non avrete nessun problema. Non sara` molto utile nelle
situazioni in cui e` necessaria una bassa latenza. Praticamente nella
maggior parte dei casi. Ricordatevi che tutto questo e` irrilevante se
possedete una scheda audio capace di fare "hardware monitoring".
In questo caso una latenza piu` alta rendera` un po` lenti i controlli
della UI di Ardour, mentre il monitoring durante la capture saranno
eccellenti.
**** COMPATIBILITA` HARDWARE *****************************************
Ardour usa il server audio JACK per tutte le operazioni di I/O. In
questo modo fornisce un impareggiabile sistema di comunicazione con il
substrato hardware audio e le altre applicazioni. Non è certamente
questo il luogo per discutere di JACK, ma se vi state chiedendo:
JACK usa le ALSA 0.9.0 API. La particolarita` e` che le sfrutta in
un modo completamente nuovo soprattutto per quanto riguarda l' uso
dell' hardware. Come risultato, benche` il totale supporto delle
periferiche h/w da parte di ALSA sia un successo facilmente ottenibile,
potrebbero esserci problemi concernenti la compatiblita` h/w. Bisogna
tenere presente che il mio scopo principale e` di creare con JACK un
sistem audio professionale, e con Ardour un sistema professionale di
HDR. Se puo` essere utile a utenti con schede a 2/4 canali, ben venga,
ma ricordate che questo non e` l' interesse primo.
Un altro aspetto importante e` che la vostra interfaccia audio deve
supportare l' I/O in full duplex nello stesso formato sia in registrazione
che suonando. Significa, per esempio, che una Soundblaster AWE non
potra` essere usata con JACK in modalita` full duplex, a meno che una
delle due direzioni (registrazione o playback) e` a 8 bit e l' altra a 16.
Sono poche le schede che hanno questo tipo di limitazione, e non sono
generalmente adatte ad essere usate con JACK e Ardour per altri motivi.
Ad oggi, Ardour ha girato con:
RME Hammerfall (Digi9652) (26 canali in, 26 canali out)
RME Hammerfall Light (Digi9636) (18 canali in, 18 canali out)
Midiman Delta series (ice1712 chipset) (12 canali in, 10 canali out)
Diverse interfacce di fascia consumer, solitamente a 2 canali in,
2/4 canali out, incluse:
Hoontech 4Dwave-NX (Trident chipset)
Ensoniq 5880
Soundblaster 32
Soundblaster 64
Creative SBLive64
Al momento sembra funzionare con tutte le schede supportate da ALSA,
che e` l'obiettivo proposto.
**** SEGNALARE UN BUG ************************************************
I bug vanno segnalati ad http://ardour.org/mantis/ . Dove è
probabile che vengano presi in considerazione e trattati. Prima di
segnalare un bug è opportuno accertarsi che non sia gia` stato
segnalato e/o eliminato in cvs.
**** COMPILAZIONE E INSTALLAZIONE ************************************
1) GNU AUTOCONF RATIONALIZATION
-------------------------------
GNU autoconf e` un sistema intelligente, ma ha una grande lacuna.
Di default, autoconf (adesso aclocal) controlla UNA sola directory
alla ricerca dei file di cui ha bisogno. Sarebbe OK se non venissero
installati altri pacchetti che qualche volta mettono i loro file di
autoconf in /usr/local/lib/share/aclocal e altre volte in
/usr/lib/share/aclocal.
Succede che autoconf non riesce a trovare i file di cui ha bisogno per
costruire Ardour, dal momento che molta gente ha una moltitudine di
librerie installate dalla distribuzione (i file di autoconf finiscono
in /usr/local/lib...) e dai pacchetti pre-costruiti (in questo caso i
pacchetti finiscono solitamente in /usr/lib...).
Per la vostra tranquillita`, vi raccomando di eseguire i seguenti passi
da root. Controllate i contenuti di entrambe le direcroty prima di
eseguire questi comandi in modo da non cancellare accidentalmente la
corretta versione di un file autoconf:
* Se avete esntrambe le directory:
cd /usr/lib/share/aclocal
cp *.m4 /usr/local/lib/share/aclocal
cd ..
rm -rf aclocal
ln -s /usr/local/lib/share/aclocal .
* Se avete solo /usr/lib/share/aclocal
cd /usr/local/lib
ln -s /usr/lib/share/aclocal .
Alcune distribuzioni hanno aclocal in altre directory. YMMV.
2. COMPILARE
------------
Prima di compilare Ardour, accertatevi di avere installato:
* Strumenti:
gcc/g++ 2.95.3 o superiore (funziona anche gcc/g++ 3.x)
autoconf 2.52 o superiore
automake 1.5 o superiore
libtool 1.4.2 o superiore
gettext 0.11.5 o superiore
pkgconfig 0.8.0 o superiore
http://www.freedesktop.org/software/pkgconfig/
sono necessari anche lex e yacc
andra` bene qualsiasi versione di bison >= 1.35
* Librerie:
Le versioni raccomandate, quando necessario, sono presenti sotto le
versioni generiche.
ALSA 0.9.X (CVS o snapshot release) (http://www.alsa-project.org)
JACK (http://jackit.sourceforge.net)
libxml2 2.5.X (http://xmlsoft.org/)
libart_lgpl 2.3.X
- available as part of gnome-libs, which you may already
have on your system.
- also available via download from GNOME source FTP sites.
- see ftp://ftp.gnome.org/pub/GNOME/MIRRORS.htmland then
follow to sources/libart_lgpl
glib 1.2 (http://www.gtk.org)
glib-1.2.8 (inclusa nella maggior parte delle distribuzioni)
GTK+ 1.2 (http://www.gtk.org)
gtk+-1.2.8 (inclusa nella maggior parte delle distribuzioni)
libsndfile (http://www.zip.com.au/~erikd/libsndfile)
libsndfile-0.0-28
libsamplerate (http://www.mega-nerd.com/SRC/)
libsamplerate 0.0.13 o superiore
the LADSPA SDK (http://www.ladspa.org/)
(Guardate sotto)
raptor (http://www.redland.opensource.ac.uk/raptor/)
lrdf (richiede raptor) (http://plugin.org.uk/lrdf/)
liblrdf 0.3.1 or higher
Ottenere LADSPA
Nota: La Linux Audio Developers Simple Plugin API (LADSPA) consiste
in realta` di un semplice file header, già incluso nei sorgenti di
Ardour
Vorrete usare anche i suoi plugins, percui andate oltre e scaricate
l' intero pacchetto (non e` grande), da www.ladspa.org.
Vi raccomando di scaricare un eccelente set di plugins per LADSPA,
programmati da Steve Harris. Il link e` http://plugin.org.uk/.
Trasformeranno Ardour in una appicazione vermante utile. Altri plugins
di LADSPA sono in programmazione percui tenete d' occhio la Linux
Audio Development mailing list.
2A) COMPILARE DA CVS
---------------------
Posizionatevi nel path in cui volete copiare i CVS di Ardour (la '%'
e` il vostro shell prompt):
% cd /usr/local/src # e` un esempio, potete scegliere un path qualsiasi
% cvs -d:pserver:anoncvs@ardour.org:/cvsroot/ardour login
# (premete enter/return quando vi sara` chiesta
la password)
% cvs -d:pserver:anoncvs@ardour.org:/cvsroot/ardour -z3 co ardour
2A.1) CHE TIPO DI COMPILAZIONE?
--------------------------------
Il prossimo passo è quello di decidere se si vuole una installazione per
sviluppatori o per semplici utenti. Se siete sviluppatori, potrebbe essere
una buona idea compilare libardour come libreria condivisa, cosi` da evitare
di collegare l'eseguibile ogni volta che cambiate versione di libreria.
Se siete semplici utenti, questo renderebbe solo la vita più difficile.
In caso siate sviluppatori dunque eseguite:
touch ardour/libs/ardour/BUILD_FOR_DEVELOPMENT
Questo fara` si` che libardour sia compilata come libreria condivisa. Dovreste
conseguentemente passare il parametro --enable-development-build a configure.
2A.2) PREPARARE IL SISTEMA PER LA COMPILAZIONE
----------------------------------------------
Ora costruite i file autoconf/automake:
% cd ardour
% sh autogen.sh
Andate al passo 3.
2B) COMPILARE DA UN TARBALL
---------------------------
Come al solito: prelevate e scompattate il tarball. La directory creata,
ardour-<versione>, e` chiamata piu` sotto "$AD".
3) COME COMPILARE
-----------------
./configure (con tutte i parametri che vorrete passare)
make
make install
Se siete uno sviluppatore che intende lavorare su libardour, potreste
voler usare il parametro --enable-development-build, che colleghera`
dinamicamente l'eseguibile a libardour, risparmiando molto tempo
nell'evitare un collegamento statico da effettuare ogni volta che si
operano cambiamenti su libardour.
Se volete compilare ardour in modo che possiate farne il `debugging`,
dovreste usare anche il parametro --disable-optimize. Senza questo
Ardour viene compilato con ottimizzazioni estreme ed il risultato non
può essere oggetto di `debugging` in modo efficace.
Come tutti gli script di configurazione, se non volete che
l' installazione avvenga ne "solito posto", aggiungete un --prefix al
comando ./configure. Potreste anche considerare di aggiungere un
parametro --sysconfdir, dal momento che `make install` tenterà di
installare tutti i file di configurazione in un percorso che tiene
conti di questo parametro.
La compilazione ci mette un po`. Eseguendo make -j3 su un dual PII-450
l'intero processo impiega circa 10-15 minuti.
4. ESEGUIRE ARDOUR
------------------
NOTA: Dovete prima di tutto eseguire il server JACK.
----------------------------------------------
Se avete eseguito "make install", allora potete digitare "ardour" e
qualcosa succedera`. Col comando "ardour --help" otterrete una
lista delle possibili opzioni.

108
DOCUMENTATION/README.ru Normal file
View file

@ -0,0 +1,108 @@
ARDOUR README.ru
Paul Davis <paul@linuxaudiosystems.com> June 2003
Russian translation by Igor Blinov <pitstop@nm.ru> November 2003
Вас приветствует Ardour. Эта программа находится в стадии разработки,
но уже может использоваться на практике, к тому же полезно когда
другие люди тестируют её, если случается (почти уверен!) исправляют
ошибки и расширяют функциональные возможности.
**** БЕЗОПАСНОСТЬ ***************************************************
Работа Ardour требует минимальное время реакции на события (low latency),
что требует использования POSIX-подсистемы реального времени (POSIX
Real-Time Scheduling) и вдобавок блокирует всю используемую память
в ОЗУ (RAM). Эти требования выполнимы, только если Ardour запущен с
привилегиями пользователя root.
С другой стороны всё не так уж и плохо. Если вы не можете установить
флаг setuid root (который помогает не во всех случаях), тогда
необходимо повысить свои привилегии до root для того, чтобы с этими
правами запустить Ardour. Если вы уже имеете доступ как пользователь
root, в таком случае запуск Ardour будет наименьшей проблемой. Итак.
В работе используются некоторые возможности ядра linux, которые не
способствует безопасности, так как они могут помочь злоумышленнику
в его планах.
В другом варианте вы можете запустить Ardour без приоритета реального
времени и забыть про сказанное выше. Однако, это неудобно для ситуаций,
в которых требуется малое время задержки сигнала, что желательно в обычной
студийной работе. Замечу, что это не так важно, если ваше аппаратное
обеспечение поддерживает функцию "hardware monitoring" - в этом случае
возросшая задержка сигнала увеличивает время реакции при воздействии
на управляющие элементы графического интерфейса Ardour, зато контроль
(мониторинг) сигнала в процессе записи будет замечательным.
**** ТРЕБОВАНИЯ К АППАРАТУРЕ ****************************************
Ardour в своей работе для ввода/вывода аудиоданных использует JACK,
который обеспечивает идеальное подключение приложений к ресурсам
аппаратуры для работы со звуком. Мы не будем здесь обсуждать JACK,
но сказанное ниже позволит избежать недоразумений:
Несмотря на то, что JACK работает через ALSA 0.9.0 API, он использует
его таким образом, что другие приложения в этот момент не могут
работать с ним, к тому же задействуются некоторые особенности
аппаратуры, неиспользуемые другими приложениями. Полная совместимость
со всеми звуковыми картами, поддерживаемыми ALSA, является достижимой
и очень желательной целью. Следствием этого может явиться поддержка
оборудования с возможностями окружающего звука (surround sound).
Однако, моя основная цель - это построение на основе JACK
профессионального звукового сервера с Ardour в качестве не менее
профессиональной звукозаписывающей системы (HDR). Если это окажется
полезным для владельцев обычных 2/4 канальных звуковых карт, то это
великолепно, но я не заостряю внимание на этом.
Следующим важным моментом является то, что ваша звуковая карта должна
поддерживать полнодуплексный режим работы, причём одновременно в одном
формате аудиоданных, как на ввод, так и на вывод. Так, к примеру, карта
SoundBlaster AWE не может использоваться с JACK в полнодуплексном
режиме - ею поддерживается только такой полнодуплексный режим, в котором
одно из двух направлений (запись или воспроизведение сигнала) работает
в формате 8 бит данных, а другое в формате 16 бит. Очень немногие карты
имеют это ограничение, и в этом случае они обычно не подходят для работы
с такими приложениями как JACK или Ardour.
На сегодняшний день, JACK работает со следующими звуковыми картами:
RME Hammerfall (Digi9652) (26 входов, 26 выходов)
RME Hammerfall Light (Digi9636) (18 входов, 18 выходов)
Midiman Delta series (ice1712 chipset) (12 входов, 10 выходов)
широко распространённые звуковые карты, обычно 2 входных канала,
2/4 выходных канала, включая:
Hoontech 4Dwave-NX (Trident chipset)
Ensoniq 5880
Soundblaster 32
Soundblaster 64
Creative SBLive64
и многие другие.
Впоследствии он будет работать со всеми звуковыми картами, поддерживаемыми
ALSA. Это одно из направлений разработки.
**********************************************************************
СООБЩЕНИЯ ОБ ОШИБКАХ
--------------------
Чтобы сообщить об обнаруженых вами ошибках в работе программы воспользуйтесь
ссылкой http://ardour.org/mantis/ . Возможно о них было сообщено ранее.
Пожалуйста, проверьте существующие сообщения, чтобы убедиться в том, что
об обнаруженной вами ошибке уже не сообщалось и/или она не исправлена в CVS.
СБОРКА ARDOUR
-------------
Подробное описание в файле "BUILD".
ЗАПУСК ARDOUR
-------------
ЗАМЕЧАНИЕ: Вы должны запустить JACK сервер прежде, чем откроете Ardour.
------------------------------------------------------------
Если вы выполнили команду "make install", тогда набрав на клавиатуре
"ardour" получите желаемый результат. "ardour --help" выводит список
доступных ключей программы.

232
DOCUMENTATION/TODO Normal file
View file

@ -0,0 +1,232 @@
ARDOUR TO-DO: $Id$
----------------------------------------------------------------------
ITEMS REQUIRED FOR 1.0
----------------------
* Automation
- must be able to apply a fade to a selected range
* Drag handles for region/xfade curves
* ensure I/O port is selected in connection dialog
* add a small buffer near the left edge of the editor canvas to
make mouse operations near that edge easier to get right
* context menus everywhere
- edit groups
- mix groups
- track lists
- region list
- click button
(miscellany)
* propagate name changes to equivalent regions in region list
* destroy region removes equivalent regions from region list
* fix edit group visibility toggle
META ITEMS
----------
* there must be a manual
POST 1.0 WORK
-------------
* make region state of a playlist be position,length,layer, and save
that for BoundsChange or Layer change.
* automation modes (from protools):
- relative trim
- etc.
* 2-step file expunge
* allow sends/inserts and perhaps plugins to be named
* popup a big panner
* mix groups (adding new kinds of relationships to the groups, as per
old ideas from tom pincince)
* add meter range control
* change meter tap point
* cassowary-based constraints for edit groups
* serializing the edit history (i have a plan for this now)
* gtk2 port
* like, totally rock, dude.
* make rulers reorderable
* set of useful click sounds
* use snapshot mechanism to provide persistent undo/redo
- needs better integration of automation state
into session state.
* duplicate-with-gap
* panner multichannel backend code
* select new port display when its created
* copy/paste io configurations
* Better temporal navigation
* new region via plugin.
* digital input trim.
* possibly allow metering max-level adjustment at run-time
* use multi-loop-take ala Samplitude/PT
* song mode autonames for locate points
intro, verse1, verse N, chorus, bridge, outro/tag
* different clock display modes:
elapsed
remaining
time since location start
time till location end
* handle missing audio sources when loading
* option/action to snap selection to zero crossings
* pitch shift?
- Some global solo routing buttons and a sine/noise generator to
test all the connections. Possibly a talkback input and
control. Pretty much like the equivalent strip on a analog
console.
WAITING FOR GTK+/gtkmm 2.0:
---------------------------
general gtkmmext::ui solution to delete_event in recursive Gtk::Main::run()
float<->ulong conversion in a GtkAdjustment (GTK2 uses doubles)
* fix the problems caused by range (float) limits on Locations.
figure out how to get frames/timebars to extend to max_frames.
UNDO ITEMS
----------
track height?
capture?
I/O connection state, etc.
BUGS
----
initial Tempo marker can be dragged
duplicate region names can be created automatically
THREAD QUESTIONS
----------------
- which thread should:
- change playlists on a diskstream?
- change diskstreams on a track? (we don't support that in the UI)
- can we reliably construct a copy of the RT state, instead of
using locks everywhere?
NOTES FROM THE MAILING LISTS
----------------------------
-- gerard --
Region gain has some bugs. They dissappear when trimming. Don't always
playback correctly.
I had some strange things with a chunk where the last region seemed to use
the audio file as a peakfile. It played back correctly, but it showed up
frames_per_peak too large.
-- gerard2 ---
Automation.
I see that automation editing is in the TODO. How about the whole deal:
Changing it during aplay. relative or absolute, latch (is that the word) or
momentary override etc
Is this for >1.0 ? It is not that important for me but maybe for some
folks...
Better metering configurability. Post/pre etc.
Gui interface consistency.
more keyboard shortcuts for f.i. (are they hard to add?):
-arrow keys to move selection from region to region
-seperate region. This one can be the same for split region, if there is
a range selected seperate, if not split.
Should playhead also snap to grid?
Adding/removing snapshots through snapshot pane.
I would prefer to move the pre and post roll adjustments to the options
menu, and have a start/end/duration of selection clocks.
A way to deal with misbehaving plugins. They shouldn't be able to freeze
ardour.
What is the current (and planned) edit-group functionality? It doesn't seem
to much.
-----
make use of transients a run-time option
panning for export
mute automation event
region length/end editor clocks don't modify position
should we allow N-channels regions to be inserted into non-N-channel routes?
auto-crossfades are unreliable/hard to predict/confusing
reset declick curves when doing a region copy (only if auto-crossfading?)
audio clock editing
- make drag work again
- use tick field
post fader plug/inserts get into a very inconsistent state wrt active/not active
mixer strip widths are not persistent across state save/restore
automation-read updates in mixer-strip in editor
don't initiate MIDI binding if there is no MMC control
export to audiofile
- exports tracks not marked for export (?)
- contains clicks/pops even with no SRC/dither (FIXED?)
timefx region length error (check back with audacity crew)
send gain control is clicky.
some regionview names don't seem sensitive to canvas events
splice mode needs to work correctly all the time, at the right times
removing a port then adding a new one can cause duplicate names
plugin automation buttons don't update from a plugin signal
how to handle multichannel selections
apparently selected location on startup of locations window, or
when creating new location from selection is *not* selected
source/region naming/region list display
LONG TERM CHECKING
------------------
RT-ness of all RT-thread STL usage
GUI DETAILS
-----------
Use mouse wheel events (button4/5)
Remove regions from region list
Some location window ops need dbl click, some don't
CHROME
------
make prompters look nicer still.
make ladspa plugin selector look nicer
don't popup "no group" when there are no groups (mixer strip).
fix bug in Gtkmmext with wrapping on Gtkmmext::ClickBox
make region editors look nicer
region editor audition button doesn't pop up after audition is finished
allow same color for all streamviews
AUDIO STREAM
------------
[ These are JACK TODO's ]
* need to ensure that cards like the Hammerfall are really set
to the correct sample rate when connected to an external
clock source.
* ::connect_to_session() should indicate a problem if the
sample rate is wrong ....
MIDI Machine Control
-----------------------
* handle stupid Mackie TC buttons
* send MMC rec-enable messages
* allow control (MMC/Local) selection to work
* make sure that MMC ID works
EDITOR, etc.
------------
* "use location to define selection"

21
DOCUMENTATION/TRANSLATORS Normal file
View file

@ -0,0 +1,21 @@
If you would like to see Ardour in your native langauge, please contact
the Ardour development mailing list. It's members only, but can be joined
at http://ardour.org.
Many thanks to these translators for making Ardour available in other
languages:
French: Alain Fréhel <alain.frehel@free.fr>
German: Karsten Petersen <kapet@kapet.de>
Italian: Filippo Pappalardo <filippo@email.it>
Portuguese: Rui Nuno Capela <rncbc@rncbc.org>
Brazilian Portuguese: Alexander da Franca Fernandes <alexander@nautae.eti.br>
Chris Ross <chris@tebibyte.org>
Russian: Igor Blinov <pitstop@nm.ru>
Spanish: Alex Krohn <alexkrohn@fastmail.fm>

71
DOCUMENTATION/ardour.1 Normal file
View file

@ -0,0 +1,71 @@
.TH ARDOUR 1 2002-12-29
.SH NAME
ardour \- a digital audio workstation
.SH SYNOPSIS
ardour
.B \-b
.RB [ \-U
.IR file ]
.RI [ session ]
.br
ardour
.B \-\-help
.SH DESCRIPTION
Ardour is a multichannel hard disk recorder (HDR) and digital audio
workstation (DAW).
It is capable of simultaneous recording 24 or more channels of 32 bit audio at
48kHz.
Ardour is intended to function as a "professional" HDR system, replacing
dedicated hardware solutions such as the Mackie HDR, the Tascam 2424 and more
traditional tape systems like the Alesis ADAT series.
It is also intended to provide the same or better functionality as software
systems such as ProTools, Samplitude, Logic Audio, Nuendo and Cubase VST (we
acknowledge these and all other names as trademarks of their respective
owners).
It supports MIDI Machine Control, and so can be controlled from any MMC
controller, such as the Mackie Digital 8 Bus mixer and many other modern
digital mixers.
.SH OPTIONS
.TP
.B \-b
Print all possible keyboard binding names.
.TP
.B \-U
Specify the path to the GTK RC file to use.
The provided one is called
.B ardour_ui.rc
and lives in the top level Ardour source directory.
This file controls all color and font use within Ardour.
Ardour will run without it, but its appearance is, uhm, ugly.
.TP
.B \-\-help
Displays the help message.
.SH FILES
.TP
.B ardour.rc
Defaults and startup settings for Ardour.
.TP
.B ardour_ui.rc
Definitions for the Ardour interface.
.SH ENVIRONMENT
.TP
.B ARDOUR_RC
Path to ardour.rc.
.TP
.B ARDOUR_SYSTEM_RC
Path to the ardour_system.rc
.TP
.B LADSPA_PATH
Path to LADSPA plugins.
.SH BUGS
Yes.
.SH AUTHOR
Paul Davis.
Do
.I not
contact him directly.
Instead,
contact him at <ardour-dev@lists.ardour.org>.
You can subscribe here:
.br
http://lists.ardour.org/listinfo.cgi/ardour-dev-ardour.org

72
DOCUMENTATION/ardour.1.es Normal file
View file

@ -0,0 +1,72 @@
.TH ARDOUR 1 2002-12-29
.SH NOMBRE
ardour \- una estación de trabajo de audio digital
.SH SINOPSIS
ardour
.B \-b
.RB [ \-U
.IR archivo ]
.RI [ sesión ]
.br
ardour
.B \-\-help
.SH DESCRIPCIÓN
Ardour graba multiples canales simultáneos a disco rigido (HDR) y es una
estación de trabajo de audio digital (DAW).
Es capaz de grabar 24 o mas canales simultáneamente con calidad de audio
de 32 bit y a 48khz.
La inteción de Ardour es funcionar como un sistema HDR "profesional",
reemplazando soluciones de hardware dedicado como la Mackie HDR, el
Tascam 2424 y otros sistemas tradicionales que emplean cinta como la
linea de ADATs de Alesis.
Tambien se busca igualar o mejorar la funcionalidad de sistemas
basados en software como ProTools, Samplitude, Logic Audio,
Nuendo y Cubase VST (reconocemos a estos y a todos los nombres ya
mencionados, como marcas registradas de sus respectivos dueños).
Ardour soporta Control de Maquina MIDI, por lo que puede ser controlado
desde cualquier controladora MMC, como la "Mackie Digital 8 Bus Mixer"
y otros mixers digitales modernos.
.SH OPCIONES
.TP
.B \-b
Muestra todos los comandos asignables a teclas del teclado.
.TP
.B \-U
Especifica el archivo de interface visual.
El que viene provisto por Ardour se llama
.B ardour_ui.rc
y se lo puede encontrar en el primer nivel de la carpeta del código de Ardour.
Este archivo controla todos los colores y fuentes usados por Ardour.
Ardour funcionará sin este, pero se verá, uhm, feo.
.TP
.B \-\-help
Muestra el mensaje de ayuda.
.SH ARCHIVOS
.TP
.B ardour.rc
Configuraciones preestablecidas y de inicio de Ardour.
.TP
.B ardour_ui.rc
Configuraciones de la interface visual de Ardour.
.SH VARIABLES
.TP
.B ARDOUR_RC
Ubicación del archivo ardour.rc.
.TP
.B ARDOUR_SYSTEM_RC
Ubicación del archivo ardour_system.rc.
.TP
.B LADSPA_PATH
Ubicación de plugins LADSPA.
.SH BUGS (Errores en el codigo)
Si.
.SH AUTOR
Paul Davis.
.I No
intente
contactarlo directamente.
En cambio,
mande un email a <ardour-dev@lists.ardour.org>.
Usted puede suscribirse a:
.br
http://lists.ardour.org/listinfo.cgi/ardour-dev-ardour.org

71
DOCUMENTATION/ardour.1.fr Normal file
View file

@ -0,0 +1,71 @@
.TH ARDOUR 1 2002-12-29
.SH NOM
ardour \- une station de travail audio-numérique
.SH SYNOPSIS
ardour
.B \-b
.RB [ \-U
.IR fichier ]
.RI [ session ]
.br
ardour
.B \-\-help
.SH DESCRIPTION
Ardour est un enregistreur sur disque dur multi-canaux (HDR) et une station de
travail audio-numérique (DAW).
Il est capable d'enregistrer simultanément 24 ou plus canaux audio 32 bits à
48 kHz.
Ardour a pour vocation de fonctionner comme un enregistreur sur disque dur
"professionnel", en remplacement de solutions matérielles dédiées comme le
Mackie HDR, le Tascam 2424 et les plus traditionnels système à bande tels que
la série Alesis ADAT.
Il est aussi conçu pour procurer les mêmes ou de meilleures fonctionnalités
que des systèmes logiciels comme ProTools, Samplitude, Logic Audio, Nuendo et
Cubase VST (nous reconnaissons ces marques comme marques déposées appartenant
à leurs propriétaires respectifs).
Il supporte MIDI Machine Control, et peut ainsi être contrôlé depuis
n'importe quel contrôleur MMC, comme le Mackie Digital 8 Bus mixer et de nombreux autres mélangeurs audio-numériques modernes.
.SH OPTIONS
.TP
.B \-b
Affiche tous les noms des codes clavier possibles.
.TP
.B \-U
Indiquer le chemin vers le fichier GTK RC à utiliser.
Le fichier fourni s'appelle
.B ardour_ui.rc
et se trouve dans la racine du répertoire du code source d'Ardour.
Ce fichier gère l'utilisation de toutes les couleurs et polices de caractère
dans Ardour.
Ardour fonctionnera sans, mais son aspect sera, disons, affreux.
.TP
.B \-\-help
Affiche le message d'aide.
.SH FICHIERS
.TP
.B ardour.rc
Paramètre par défaut et de démarrage d'Ardour.
.TP
.B ardour_ui.rc
Définitions pour l'interface d'Ardour.
.SH ENVIRONNEMENT
.TP
.B ARDOUR_RC
Chemin vers ardour.rc.
.TP
.B ARDOUR_SYSTEM_RC
Chemin vers ardour_system.rc
.TP
.B LADSPA_PATH
Chemin vers les greffons LADSPA.
.SH BOGUES
Oui.
.SH AUTEUR
Paul Davis.
Ne
.I pas
le contacter directement.
Contactez-le plutôt à <ardour-dev@lists.ardour.org>.
Vous pouvez vous inscrire ici :
.br
http://lists.ardour.org/listinfo.cgi/ardour-dev-ardour.org

84
DOCUMENTATION/ardour.1.ru Normal file
View file

@ -0,0 +1,84 @@
.TH "ARDOUR" "1" "2004-05-10" "" ""
.SH "ИМЯ"
ardour \- рабочая станция для цифровой обработки звука
.SH "ОБЗОР"
ardour
.B \-b
.RB [ \-U
.I R файл ]
.RI [ сессия ]
.br
ardour
.B \-\-help
.SH "ОПИСАНИЕ"
Ardour \- это программа для многоканальной записи на жёсткий диск
(hard disk recorder \- HDR) и одновременно редактор для цифровой обработки звука
(digital audio workstation \- DAW).
.br
Он способен записывать одновременно до 24 или более каналов 32\-битных
аудиоданных с частотой дискретизации 48 кГц.
Ardour нацелен работать как "профессиональная" HDR\-система, способная
заменить такие аппаратные решения как Mackie HDR, Tascam 2424 и многие
традиционные системы записи на магнитную ленту, например серию Alesis ADAT.
Также преследуется цель обеспечить функциональность аналогичную или даже большую
по сравнению с такими программными продуктами как ProTools, Samplitude, Logic Audio,
Nuendo and Cubase VST (мы признаём, что эти и другие наименования являются
торговыми марками, которые принадлежат соответствующим обладателям).
.br
Имеется поддержка MIDI Machine Control (MMC), в том числе возможно и
управление от любого MMC\-контроллера, например, такого как микшер Mackie Digital
8 Bus или любого другого современного микшера.
.SH "КЛЮЧИ КОМАНДНОЙ СТРОКИ"
.TP
.B \-b, \-\-bindings
Вывести список доступных "горячих" клавиш.
.TP
.B \-n, \-\-no\-splash
Не выводить заставку.
.TP
.B \-U, \-\-ui\-rcfile путь
Указать путь к файлу описания графического интерфейса (GTK RC).
В нём определены все шрифты и цвета элементов интерфейса Ardour.
Файл должен именоваться как
.B ardour_ui.rc
, его шаблон находится в корневом каталоге исходных текстов Ardour.
Ardour можно запустить и без него, но внешний вид интерфейса будет безобразным.
.TP
.B \-c, \-\-jack\-client\-name имя
Использовать другое имя jack\-клиента, ardour по умолчанию.
.TP
.B \-v, \-\-version
Информация о версии программы.
.TP
.B \-h, \-\-help
Показать справку.
.SH "ФАЙЛЫ"
.TP
.B ardour.rc
Настройки по умолчанию и установки "горячих" клавиш для Ardour.
.TP
.B ardour_ui.rc
Описание пользовательского интерфейса Ardour.
.SH "ОКРУЖЕНИЕ"
.TP
.B ARDOUR_RC
Путь к файлу ardour.rc.
.TP
.B ARDOUR_SYSTEM_RC
Путь к файлу ardour_system.rc
.TP
.B LADSPA_PATH
Путь к модулям (плагинам) LADSPA.
.SH "ОШИБКИ В ПРОГРАММЕ"
Да, имеются.
.SH "АВТОР"
Paul Davis (Пол Дэвис).
Пожалуйста,
.I не обращайтесь
к нему напрямую.
Связаться с ним и другими разработчиками можно отправив сообщение в список рассылки,
<ardour-dev@lists.ardour.org>.
.br
Вы можете подписаться на него по адресу:
.br
http://lists.ardour.org/listinfo.cgi/ardour-dev-ardour.org

15
PACKAGER_README Normal file
View file

@ -0,0 +1,15 @@
(1) VST SUPPORT
You may not distribute binaries of Ardour with VST support. Doing so
is a violation of the license agreement for the Steinberg VST SDK. If
you are found to be distributing such binaries, you risk both
prosecution by Steinberg and public humiliation by me.
This is not my choice, and as soon as Steinberg change their
licensing, which they have indicated they will do, this policy (and
file) will be removed.
(2) STANDARD TEMPLATES
The templates in ./templates are intended for installation in
$prefix/share/ardour/templates.

5
README Normal file
View file

@ -0,0 +1,5 @@
Please see the DOCUMENTATION directory.
If you plan to compile ardour from scratch, BUILD is required reading.

294
ReleaseNotes-0.9betaX Normal file
View file

@ -0,0 +1,294 @@
RELEASE NOTES
***************
>>>> 0.9beta13
beta13 is mostly bug fixes and a few new features over beta12.
>>> 0.9beta12
Welcome to the 0.9beta12 release of Ardour. We are now moving ever
closer to a 1.0 release. This release includes an incredible number of
changes and improvements since beta11. We expect some instabilities
compared to beta11 to remain - please test, collect debug traces,
etc. etc.
+++++ FIRST IMPORTANT NOTICE +++++
Although beta12 will load sessions created by earlier versions of
Ardour, if it is allowed to save a session at any time, that session
will immediately be INCOMPATIBLE WITH ALL PRIOR VERSIONS OF ARDOUR.
If you have important sessions, you are advised to back up the session
state files (generally called <session-name>/<session-name>.ardour).
I repeat: if you care about being able to use prior versions of Ardour
on your existing sessions, you MUST BACKUP YOUR SESSION STATE FILES.
Please rest assured that after 1.0 appears, no incompatibility,
forward or backwards, will be tolerated in any future version.
+++++ SECOND IMPORTANT NOTICE +++++
Why the change in the session files? At some point as work on beta12
was in progress, we realized that Ardour's panning model was
fundamentally broken. Not just the mathematics of the pan law, but the
actual software architecture of panning. Fixing this has required a
massive set of changes to Ardour's basic data flow and a lot of subtle
and not-so-subtle changes to a lot of code. On the plus side, we now
have a completely modular panning architecture that will make it
trivial, mostly, to use plugins for panning in the future.
++++++ THIRD IMPORTANT NOTICE ++++++
ardour/ksi is no longer built by default. The changes to libardour are
massive and widespread, and I do not have the resources to spend time
getting ardour/ksi to catch up with them. I will reenable default
building if and when ardour/ksi compiles again. I wish I could spend
time on this, but the work is just too much at a time when I
desperately need to get Ardour to a reasonable 1.0 release.
+++++ FOURTH IMPORTANT NOTICE +++++
This version of ardour will NOT compile with gcc 2.95. we are now
using the standard C++ class "stringstream", which has no support in
gcc2.95. i will accept patches that attempt to use the gcc class
"strstream", but i am not willing to spend time on this myself.
Changes since 0.9beta11
------------------------
A) PANNING
* panning control is per-stream
code is now supporting the notion of the "number of active
streams" within various parts of a signal processing
"route". this is different and orthogonal from the number of
inputs and outputs the route has. if you put a 1in/2out
plugin into a 1in/1out route (which arguably should not be
possible), then before the plugin there is 1 active stream,
and afterwards there are 2.
* panner linkage
- panners for all streams/channels can be moved
together or in opposing motion.
* new "bar controllers" for controlling panning to
a stereo output, 1 per data stream
* dbl-click on the bar controller to get numerical
entry, then Return or Tab to get back
to graphics.
B) AUTOMATION
----------
* gain and pan automation now totally separated
- you can playback pan automation while
doing touch automation on gain.
* if playing automation, and playhead goes past
the last control point, value remains
at that level.
* one button for gain automation state and one for
pan automation state per mixer strip
* ignore the automation mode for now
* touch automation for panning now works.
* hide all automation control points, display them
only as mouse pointer moves through them
* automation values reflected after transport stop
or locate if automation is not off, or when
automation is turned on.
C) PLUGIN GUIs
-----------
* use bar controllers (see Panning above) instead of sliders
D) OTHER MAJOR FUNCTIONALITY
-------------------
* initial support for win32/x86 VST plugins as native objects
in Ardour
* Added exclusive solo operation (ctrl-alt click on solo button)
which sets that track to be the only soloed track. it has a
momentary counterpart (ctrl-alt middle-click) which temporarily
exclusively solos the track while the mouse button is pressed.
BTW, middle-clicking mute buttons is momentary mute as well.
* Added seamless looping. this can be enabled in the options editor
(misc tab). why is this an option you ask? well, our current
looping scheme simply does a transport reposition at the end of the
loop, and while completely sample accurate, there can be a time gap
between the end of the loop and the beginning. This happens due to
the slow-sync jack transport system, to allow all clients to
reposition in sync (including ardour). However, if you need truly
seamless looping with no gap, you can enable this option which will do
it within ardour only -- you must disable ardour as the jack
transport/time master for it to work. In the near future, the Jack
transport system may acquire a notion of looping, and at that time,
seamless may be used at any time.
Note that for full compatibility with other transport aware apps, the
normal (non-seamless) looping with ardour as jack transport master is
required and is still quite usable, so don't be discouraged from using it.
* drag-n-drop from a file manager implemented for
placing audio files into audio tracks
* LADSPA Presets are now saved in RDF format in
~/.ladspa/rdf/ardour-presets.n3. Ardour will also
read any other RDF files saved in that location.
* region list redesigned
* mouse wheel events now scroll canvas, not change mouse mode
* always store to current snapshot file, do not make read-only
anymore (might cause problems on older sessions with
snapshots if editing the snapshot)
* mouse shuttle mode (the return of "scrub")
a new widget replaces the ffwd/rev buttons to provide
continuous speed control in forward and reverse directions.
* Added option to update actively recording regions with waveforms.
Much cooler than just the pink boxes, eh? On by default, you
can turn it back to the plain pink boxes from the display tab
of the options window.
B) MINOR IMPROVEMENTS + BUG FIXES
------------------------------
* correct handling of JACK transport API when transport master
* improved handling of SMPTE timecode
- SMPTE frames-per-second can be edited from the options editor
- SMPTE offset (what absolute time with respect to audio frame
zero is SMPTE 0:0:0:0) can be edited from the options
editor
- correct drop frame calculations
* fix for "Destroy Last Capture" bug, plus a correction for
a thinko that caused a segv if DLC done twice between
captures.
* recent session dialog doesn't have "subtrees" for sessions
with just a single state (snapshot)
* xfade editor changes
- "shade under line"
- fix left offset of wave display
* buttons/arrows on editor vertical scrollbar now work
* template selector hidden in new session dialog if the user
has no templates
* fix problem with exporting caused by JACK transport fixes
* MMC buttton relabelled "External MIDI Control", and moved
to MIDI tab of Options editor, along with "Send MMC"
* Better implemented the momentary mute and solo operations so that
the previous state is restored on mouse-release.
* added "lock", "unlock", "normalize", "reverse" to region context
menu
* add new operation to return captured regions to their "captured"
location (does not work for embedded/imported regions). the
operation is in the region context menu as "Original position".
* fixes for region naming when handling external audio files
* redesign new session dialog to use a tabbed notebook
* make sure option editor's "follow playhead" button is in-sync
with follow playhead setting
* fix long-standing bug with MIDI request pool running out of
memory.
* fix export of 100% zeroes in 32 bit integer sample files
* added MMC command when in master MMC mode for transport
startup (Deferred Play)
* correct design flaw in creating regions from session file.
(fixes some odd behaviour when undoing close to
start of working on a session, because regions did
not have the correct history set up)
* limited shuttle speed when mouse departs the control box.
* keep JACK shutdown/kick message on top of editor window
* use "e" and "p" to position edit/playhead wherever mouse is
* fixes for transport button madness
* fix for autoloop indicator region visibility
* made the horizontal scrollbar be a standard one
* included new fader pixmaps from ryan (precursor to new theme)
* ExportDialog saves Track information. It doesn't restore it yet though.
* LRDF enumerations are displayed in a combo box in the PluginUI.
* Updated gtk-ardour Russian translation and added new libardour Russian translation.
* Recent Sessions dialog doesn't display sessions that have been deleted.
* Trying to sample a file in the AudioLibrary that has been moved or deleted won't crash.
* fix catastrophic, stupid, unbelievable and just plain ridiculous
bug in editor constructor that left edit_cursor and
playhead_cursor with random values when Editor::set_state()
was called.
* move "optimization flags" setting into a global autoconf file,
and call AM_OPT_FLAGS from most configure scripts
* increase size of UI request pool
* increase size of UI request ringbuffer
* finally get all tracks connected to ins+outs
when using "auto-connect" options.
(previously only the first N tracks
would be connected, where N was the
number of physical i/o's on
your audio interface)
* prevent GTK from loading its default
RC files at all costs.
* fix gcc 3.3 "bug" in libsoundtouch
* start to use the new BarController widget in plugin GUIs
* fixed the declick on transport stop. yes, it probably never
worked, which is why you heard clicks on stopping. this also
fixes the problem where plugins are interrupted briefly on stop...
now reverb tails are undisturbed on transport stop.
* Audition port names are looked up at runtime.
* Library UI uses the new jftw in libpbd.
* The plugin selector is now sortable by clicking on the different column
titles.
* "stop at session end" option is now saved
* "splash/about window" design changes - unfinished, and wow is it
ugly. but its also more flexible, and i'll finish it RSN.
* several dialog windows forced to float over the editor
* "wait for loading" message removed
* when adding multiple tracks, GUI runs between each track
(causes ugly flashing of mixer window, however)
* Select context menu now contains
"Select all in track"
"Select all"
"Invert in track"
"Invert all"
(invert is known not to work on automation tracks)
* incorrect handling of stereo streams through routes fixed.
* check for adequate version of JACK
* fix recursive call to DiskStream::set_name() that caused a crash
when renaming a track
* fix PortInsert to do a pure wire-level copy - no gain, no pan
* count cycles for plugins
* make sends meter correctly
* clean up (longstanding) late initialization of several variables
(thanks valgrind!)
* convert error log to popup messages, mostly
* run Gtk::Main event loop while embedding/linking an external file
(and use the "watch/wait" cursor too)
* add a half-working detent for panner bar controllers
* try to improve operation of gain/pan automation buttons
* Added spanish translation. Thank you Alex Krohn.
* change pan line colors
* fix display of slide/splice mode
* clicks on track canvas views do not select track
* pack IO CLists in IOSelector in a scrolled window (needs theme name)
* select next IO port after making connection to current one
(speeds and smooths UI interaction when doing IO setup)
* Added spanish translation of ardour.1.
* test plugin configuration and display a dialog if its incorrect
(even when loading ... work in progress)
* Added russian translation of man page.
* Added valgrind shortcut for ardour into gtk_ardour. (arval).
* correct problem with lack of playback in rec-enabled
tracks when not using s/w monitoring
* apply gain to s/w monitored rec-enabled tracks
* fix nasty thread synchronization bug related to
allocation+use of session-wide pan automation
buffers
* provide (not very good) warning if rec-enable attempt
made on a track with no input connections
* more tooltips
* pan muting via context menu
* fix potential segfault in ::~Session caused by
double delete of playlists
* MIDI control for panning added back (untested)

663
SConstruct Normal file
View file

@ -0,0 +1,663 @@
import os
import sys
import re
import shutil
import glob
import errno
import time
import SCons.Node.FS
SConsignFile()
EnsureSConsVersion(0, 96)
version = '1.9beta1'
subst_dict = { }
#
# Command-line options
#
opts = Options('scache.conf')
opts.AddOptions(
BoolOption('ALTIVEC', 'Compile using Altivec instructions', 0),
('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
BoolOption('DEBIAN', 'Debian build options (no internal versions of 3rd party libraries)', 0),
BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
BoolOption('DEVBUILD', 'Use shared libardour (developers only)', 0),
BoolOption('NLS', 'Set to turn on i18n support', 1),
BoolOption('NOARCH', 'Do not use architecture-specific compilation flags', 0),
PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
BoolOption('VST', 'Compile with support for VST', 0),
BoolOption('VERSIONED', 'Add version information to ardour/gtk executable name inside the build directory', 0)
)
#----------------------------------------------------------------------
# a handy helper that provides a way to merge compile/link information
# from multiple different "environments"
#----------------------------------------------------------------------
#
class LibraryInfo(Environment):
def __init__(self,*args,**kw):
Environment.__init__ (self,*args,**kw)
def Merge (self,others):
for other in others:
self.Append (LIBS = other.get ('LIBS',[]))
self.Append (LIBPATH = other.get ('LIBPATH', []))
self.Append (CPPPATH = other.get('CPPPATH', []))
self.Append (LINKFLAGS = other.get('LINKFLAGS', []))
env = LibraryInfo (options = opts,
CPPPATH = [ '.' ],
VERSION = version,
TARBALL='ardour-' + version + '.tar.bz2',
DISTFILES = [ ],
DISTTREE = '#ardour-' + version,
DISTCHECKDIR = '#ardour-' + version + '/check'
)
#----------------------------------------------------------------------
# Builders
#----------------------------------------------------------------------
# Handy subst-in-file builder
#
def do_subst_in_file(targetfile, sourcefile, dict):
"""Replace all instances of the keys of dict with their values.
For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
"""
try:
f = open(sourcefile, 'rb')
contents = f.read()
f.close()
except:
raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
for (k,v) in dict.items():
contents = re.sub(k, v, contents)
try:
f = open(targetfile, 'wb')
f.write(contents)
f.close()
except:
raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
return 0 # success
def subst_in_file(target, source, env):
if not env.has_key('SUBST_DICT'):
raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
d = dict(env['SUBST_DICT']) # copy it
for (k,v) in d.items():
if callable(v):
d[k] = env.subst(v())
elif SCons.Util.is_String(v):
d[k]=env.subst(v)
else:
raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
for (t,s) in zip(target, source):
return do_subst_in_file(str(t), str(s), d)
def subst_in_file_string(target, source, env):
"""This is what gets printed on the console."""
return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
for (t,s) in zip(target, source)])
def subst_emitter(target, source, env):
"""Add dependency from substituted SUBST_DICT to target.
Returns original target, source tuple unchanged.
"""
d = env['SUBST_DICT'].copy() # copy it
for (k,v) in d.items():
if callable(v):
d[k] = env.subst(v())
elif SCons.Util.is_String(v):
d[k]=env.subst(v)
Depends(target, SCons.Node.Python.Value(d))
# Depends(target, source) # this doesn't help the install-sapphire-linux.sh problem
return target, source
subst_action = Action (subst_in_file, subst_in_file_string)
env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
#
# internationalization
#
# po_helper
#
# this is not a builder. we can't list the .po files as a target,
# because then scons -c will remove them (even Precious doesn't alter
# this). this function is called whenever a .mo file is being
# built, and will conditionally update the .po file if necessary.
#
def po_helper(po,pot):
args = [ 'msgmerge',
'--update',
po,
pot,
]
print 'Updating ' + po
return os.spawnvp (os.P_WAIT, 'msgmerge', args)
# mo_builder: builder function for (binary) message catalogs (.mo)
#
# first source: .po file
# second source: .pot file
#
def mo_builder(target,source,env):
po_helper (source[0].get_path(), source[1].get_path())
args = [ 'msgfmt',
'-c',
'-o',
target[0].get_path(),
source[0].get_path()
]
return os.spawnvp (os.P_WAIT, 'msgfmt', args)
mo_bld = Builder (action = mo_builder)
env.Append(BUILDERS = {'MoBuild' : mo_bld})
# pot_builder: builder function for message templates (.pot)
#
# source: list of C/C++ etc. files to extract messages from
#
def pot_builder(target,source,env):
args = [ 'xgettext',
'--keyword=_',
'--keyword=N_',
'--from-code=UTF-8',
'-o', target[0].get_path(),
"--default-domain=" + env['PACKAGE'],
'--copyright-holder="Paul Davis"' ]
args += [ src.get_path() for src in source ]
return os.spawnvp (os.P_WAIT, 'xgettext', args)
pot_bld = Builder (action = pot_builder)
env.Append(BUILDERS = {'PotBuild' : pot_bld})
#
# utility function, not a builder
#
def i18n (buildenv, sources, installenv):
domain = buildenv['PACKAGE']
potfile = buildenv['POTFILE']
installenv.Alias ('potupdate', buildenv.PotBuild (potfile, sources))
p_oze = [ os.path.basename (po) for po in glob.glob ('po/*.po') ]
languages = [ po.replace ('.po', '') for po in p_oze ]
m_oze = [ po.replace (".po", ".mo") for po in p_oze ]
for mo in m_oze[:]:
po = 'po/' + mo.replace (".mo", ".po")
installenv.Alias ('install', buildenv.MoBuild (mo, [ po, potfile ]))
for lang in languages[:]:
modir = (os.path.join (install_prefix, 'share/locale/' + lang + '/LC_MESSAGES/'))
moname = domain + '.mo'
installenv.Alias('install', installenv.InstallAs (os.path.join (modir, moname), lang + '.mo'))
#
# A generic builder for version.cc files
#
# note: requires that DOMAIN, MAJOR, MINOR, MICRO are set in the construction environment
# note: assumes one source files, the header that declares the version variables
#
def version_builder (target, source, env):
text = "int " + env['DOMAIN'] + "_major_version = " + str (env['MAJOR']) + ";\n"
text += "int " + env['DOMAIN'] + "_minor_version = " + str (env['MINOR']) + ";\n"
text += "int " + env['DOMAIN'] + "_micro_version = " + str (env['MICRO']) + ";\n"
try:
o = file (target[0].get_path(), 'w')
o.write (text)
o.close ();
except IOError:
print "Could not open", target[0].get_path(), " for writing\n"
sys.exit (-1)
text = "#ifndef __" + env['DOMAIN'] + "_version_h__\n";
text += "#define __" + env['DOMAIN'] + "_version_h__\n";
text += "extern int " + env['DOMAIN'] + "_major_version;\n"
text += "extern int " + env['DOMAIN'] + "_minor_version;\n"
text += "extern int " + env['DOMAIN'] + "_micro_version;\n"
text += "#endif /* __" + env['DOMAIN'] + "_version_h__ */\n";
try:
o = file (target[1].get_path(), 'w')
o.write (text)
o.close ();
except IOError:
print "Could not open", target[1].get_path(), " for writing\n"
sys.exit (-1)
return None
version_bld = Builder (action = version_builder)
env.Append (BUILDERS = {'VersionBuild' : version_bld})
#
# a builder that makes a hard link from the 'source' executable to a name with
# a "build ID" based on the most recent CVS activity that might be reasonably
# related to version activity. this relies on the idea that the SConscript
# file that builds the executable is updated with new version info and committed
# to the source code repository whenever things change.
#
def versioned_builder(target,source,env):
# build ID is composed of a representation of the date of the last CVS transaction
# for this (SConscript) file
try:
o = file (source[0].get_dir().get_path() + '/CVS/Entries', "r")
except IOError:
print "Could not CVS/Entries for reading"
return -1
last_date = ""
lines = o.readlines()
for line in lines:
if line[0:12] == '/SConscript/':
parts = line.split ("/")
last_date = parts[3]
break
o.close ()
if last_date == "":
print "No SConscript CVS update info found - versioned executable cannot be built"
return -1
tag = time.strftime ('%Y%M%d%H%m', time.strptime (last_date));
print "The current build ID is " + tag
tagged_executable = source[0].get_path() + '-' + tag
if os.path.exists (tagged_executable):
print "Replacing existing executable with the same build tag."
os.unlink (tagged_executable)
return os.link (source[0].get_path(), tagged_executable)
verbuild = Builder (action = versioned_builder)
env.Append (BUILDERS = {'VersionedExecutable' : verbuild})
#
# source tar file builder
#
def distcopy (target, source, env):
treedir = str (target[0])
try:
os.mkdir (treedir)
except OSError, (errnum, strerror):
if errnum != errno.EEXIST:
print 'mkdir ', treedir, ':', strerror
cmd = 'tar cf - '
#
# we don't know what characters might be in the file names
# so quote them all before passing them to the shell
#
all_files = ([ str(s) for s in source ])
cmd += " ".join ([ "'%s'" % quoted for quoted in all_files])
cmd += ' | (cd ' + treedir + ' && tar xf -)'
p = os.popen (cmd)
return p.close ();
def tarballer (target, source, env):
cmd = 'tar -jcf ' + str (target[0]) + ' ' + str(source[0]) + " --exclude '*~'"
print 'running ', cmd, ' ... '
p = os.popen (cmd)
return p.close ()
dist_bld = Builder (action = distcopy,
target_factory = SCons.Node.FS.default_fs.Entry,
source_factory = SCons.Node.FS.default_fs.Entry,
multi = 1)
tarball_bld = Builder (action = tarballer,
target_factory = SCons.Node.FS.default_fs.Entry,
source_factory = SCons.Node.FS.default_fs.Entry)
env.Append (BUILDERS = {'Distribute' : dist_bld})
env.Append (BUILDERS = {'Tarball' : tarball_bld})
# ----------------------------------------------------------------------
# Construction environment setup
# ----------------------------------------------------------------------
libraries = { }
libraries['core'] = LibraryInfo (CPPPATH = [ '#libs'])
libraries['sndfile'] = LibraryInfo()
libraries['sndfile'].ParseConfig('pkg-config --cflags --libs sndfile')
libraries['lrdf'] = LibraryInfo()
libraries['lrdf'].ParseConfig('pkg-config --cflags --libs lrdf')
libraries['raptor'] = LibraryInfo()
libraries['raptor'].ParseConfig('pkg-config --cflags --libs raptor')
libraries['samplerate'] = LibraryInfo()
libraries['samplerate'].ParseConfig('pkg-config --cflags --libs samplerate')
libraries['jack'] = LibraryInfo()
libraries['jack'].ParseConfig('pkg-config --cflags --libs jack')
libraries['xml'] = LibraryInfo()
libraries['xml'].ParseConfig('pkg-config --cflags --libs libxml-2.0')
libraries['glib2'] = LibraryInfo()
libraries['glib2'].ParseConfig ('pkg-config --cflags --libs glib-2.0')
libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gobject-2.0')
libraries['glib2'].ParseConfig ('pkg-config --cflags --libs gmodule-2.0')
libraries['gtk2'] = LibraryInfo()
libraries['gtk2'].ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
libraries['pango'] = LibraryInfo()
libraries['pango'].ParseConfig ('pkg-config --cflags --libs pango')
libraries['libgnomecanvas2'] = LibraryInfo()
libraries['libgnomecanvas2'].ParseConfig ('pkg-config --cflags --libs libgnomecanvas-2.0')
libraries['ardour2'] = LibraryInfo (LIBS='ardour2', LIBPATH='#libs/ardour2', CPPPATH='#libs/ardour2')
libraries['midi++2'] = LibraryInfo (LIBS='midi++', LIBPATH='#libs/midi++2', CPPPATH='#libs/midi++2')
libraries['pbd3'] = LibraryInfo (LIBS='pbd', LIBPATH='#libs/pbd3', CPPPATH='#libs/pbd3')
libraries['gtkmm2ext'] = LibraryInfo (LIBS='gtkmm2ext', LIBPATH='#libs/gtkmm2ext', CPPPATH='#libs/gtkmm2ext')
libraries['fst'] = LibraryInfo()
if env['VST']:
libraries['fst'].ParseConfig('pkg-config --cflags --libs libfst')
#
# Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
#
conf = Configure(env)
if conf.CheckCHeader('alsa/asoundlib.h'):
libraries['sysmidi'] = LibraryInfo (LIBS='asound')
env['SYSMIDI'] = 'ALSA Sequencer'
subst_dict['%MIDITAG%'] = "seq"
subst_dict['%MIDITYPE%'] = "alsa/sequencer"
elif conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
# this line is needed because scons can't handle -framework in ParseConfig() yet.
libraries['sysmidi'] = LibraryInfo (LINKFLAGS= '-framework CoreMIDI -framework CoreFoundation -framework CoreAudio -framework CoreServices -framework AudioUnit')
env['SYSMIDI'] = 'CoreMIDI'
subst_dict['%MIDITAG%'] = "coremidi"
subst_dict['%MIDITYPE%'] = "coremidi"
env = conf.Finish()
if env['DEBIAN']:
libraries['soundtouch'] = LibraryInfo(LIBS='SoundTouch')
coredirs = [
'templates'
]
subdirs2 = [
'libs/pbd3',
'libs/midi++2',
]
gtk2_subdirs = [
'libs/gtkmm2ext',
]
else:
libraries['sigc2'] = LibraryInfo(LIBS='sigc++2',
LIBPATH='#libs/sigc++2',
CPPPATH='#libs/sigc++2')
libraries['glibmm2'] = LibraryInfo(LIBS='glibmm2',
LIBPATH='#libs/glibmm2',
CPPPATH='#libs/glibmm2')
libraries['pangomm'] = LibraryInfo(LIBS='pangomm',
LIBPATH='#libs/gtkmm2/pango',
CPPPATH='#libs/gtkmm2/pango')
libraries['atkmm'] = LibraryInfo(LIBS='atkmm',
LIBPATH='#libs/gtkmm2/atk',
CPPPATH='#libs/gtkmm2/atk')
libraries['gdkmm2'] = LibraryInfo(LIBS='gdkmm2',
LIBPATH='#libs/gtkmm2/gdk',
CPPPATH='#libs/gtkmm2/gdk')
libraries['gtkmm2'] = LibraryInfo(LIBS='gtkmm2',
LIBPATH='#libs/gtkmm2/gtk',
CPPPATH='#libs/gtkmm2/gtk')
libraries['libgnomecanvasmm'] = LibraryInfo(LIBS='libgnomecanvasmm',
LIBPATH='#libs/libgnomecanvasmm',
CPPPATH='#libs/libgnomecanvasmm')
libraries['soundtouch'] = LibraryInfo(LIBS='soundtouch',
LIBPATH='#libs/soundtouch',
CPPPATH='#libs/soundtouch')
coredirs = [
'libs/soundtouch',
'templates'
]
subdirs2 = [
'libs/sigc++2',
'libs/pbd3',
'libs/midi++2',
]
gtk2_subdirs = [
'libs/glibmm2',
'libs/gtkmm2/pango',
'libs/gtkmm2/atk',
'libs/gtkmm2/gdk',
'libs/gtkmm2/gtk',
'libs/libgnomecanvasmm',
'libs/gtkmm2ext',
]
opts.Save('scache.conf', env)
Help(opts.GenerateHelpText(env))
if os.environ.has_key('PATH'):
env.Append(PATH = os.environ['PATH'])
if os.environ.has_key('PKG_CONFIG_PATH'):
env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
final_prefix = '$PREFIX'
install_prefix = '$DESTDIR/$PREFIX'
if env['PREFIX'] == '/usr':
final_config_prefix = '/etc'
else:
final_config_prefix = env['PREFIX'] + '/etc'
config_prefix = '$DESTDIR' + final_config_prefix
#
# Compiler flags and other system-dependent stuff
#
opt_flags = []
# guess at the platform, used to define compiler flags
config_guess = os.popen("tools/config.guess").read()[:-1]
config_cpu = 0;
config_arch = 1;
config_kernel = 2;
config_os = 3;
config = config_guess.split ("-")
#
# on OS X darwinports puts things in /opt/local by default
#
if config[config_arch] == 'apple':
libraries['core'].Append (LIBPATH = [ '/opt/local/lib' ],
CPPPATH = [ '/opt/local/include' ])
if config[config_cpu] == 'powerpc':
#
# Apple/PowerPC optimization options
#
# -mcpu=7450 does not reliably work with gcc 3.*
#
if env['NOARCH'] == 0:
if env['ALTIVEC'] == 1:
opt_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec" ])
else:
opt_flags.extend([ "-mcpu=750", "-mmultiple" ])
opt_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
elif re.search ("i[0-9]86", config[config_cpu]) != None :
if env['NOARCH'] == 0:
if config[config_kernel] == 'linux' :
flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
x86_flags = flag_line.split (": ")[1:][0].split (' ')
if "mmx" in x86_flags:
opt_flags.append ("-mmmx")
if "sse" in x86_flags:
opt_flags.extend (["-msse", "-mfpmath=sse"])
if "3dnow" in x86_flags:
opt_flags.append ("-m3dnow")
if config[config_cpu] == "i586":
opt_flags.append ("-march=i586")
elif config[config_cpu] == "i686":
opt_flags.append ("-march=i686")
#
# ARCH="..." overrides all
#
if env['ARCH'] != '':
opt_flags = env['ARCH'].split()
#
# prepend boiler plate optimization flags
#
opt_flags[:0] = [
"-O3",
"-fomit-frame-pointer",
"-ffast-math",
"-fstrength-reduce"
]
if env['DEBUG'] == 1:
env.Append(CCFLAGS="-g")
else:
env.Append(CCFLAGS=" ".join (opt_flags))
env.Append(CCFLAGS="-Wall")
if env['VST']:
env.Append(CCFLAGS="-DVST_SUPPORT")
#
# everybody needs this
#
env.Merge ([ libraries['core'] ])
#
# i18n support
#
conf = Configure (env)
if env['NLS']:
if conf.CheckCHeader('libintl.h') == None:
print 'This system is not configured for internationalized applications. An english-only version will be built\n'
env['NLS'] = 0
env = conf.Finish()
if env['NLS'] == 1:
env.Append(CCFLAGS="-DENABLE_NLS")
Export('env install_prefix final_prefix config_prefix final_config_prefix libraries i18n version')
#
# the configuration file may be system dependent
#
conf = env.Configure ()
if conf.CheckCHeader('/System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudio.h'):
subst_dict['%JACK_BACKEND%'] = "coreaudio:Built-in Audio:in"
else:
subst_dict['%JACK_BACKEND%'] = "alsa_pcm:playback_"
env = conf.Finish()
rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour_system.rc'))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour.rc'))
Default (rcbuild)
# source tarball
Precious (env['DISTTREE'])
#
# note the special "cleanfirst" source name. this triggers removal
# of the existing disttree
#
env.Distribute (env['DISTTREE'],
[ 'SConstruct',
'COPYING', 'PACKAGER_README', 'README',
'ardour.rc.in',
'ardour_system.rc',
'tools/config.guess'
] +
glob.glob ('DOCUMENTATION/AUTHORS*') +
glob.glob ('DOCUMENTATION/CONTRIBUTORS*') +
glob.glob ('DOCUMENTATION/TRANSLATORS*') +
glob.glob ('DOCUMENTATION/BUILD*') +
glob.glob ('DOCUMENTATION/FAQ*') +
glob.glob ('DOCUMENTATION/README*')
)
srcdist = env.Tarball(env['TARBALL'], env['DISTTREE'])
env.Alias ('srctar', srcdist)
#
# don't leave the distree around
#
env.AddPreAction (env['DISTTREE'], Action ('rm -rf ' + str (File (env['DISTTREE']))))
env.AddPostAction (srcdist, Action ('rm -rf ' + str (File (env['DISTTREE']))))
#
# the subdirs
#
for subdir in coredirs:
SConscript (subdir + '/SConscript')
for sublistdir in [subdirs2, gtk2_subdirs]:
for subdir in sublistdir:
SConscript (subdir + '/SConscript')
# cleanup
env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])

136
ardour.rc.in Normal file
View file

@ -0,0 +1,136 @@
<?xml version="1.0"?>
<Ardour>
<MIDI-port tag="%MIDITAG%" device="ardour" type="%MIDITYPE%" mode="duplex"/>
<Config>
<Option name="minimum-disk-io-bytes" value="262144"/>
<Option name="track-buffer-seconds" value="5.000000"/>
<Option name="mute-affects-pre-fader" value="yes"/>
<Option name="mute-affects-post-fader" value="yes"/>
<Option name="mute-affects-control-outs" value="yes"/>
<Option name="mute-affects-main-outs" value="yes"/>
<Option name="solo-latch" value="yes"/>
<Option name="mtc-port" value="%MIDITAG%"/>
<Option name="mmc-port" value="%MIDITAG%"/>
<Option name="midi-port" value="%MIDITAG%"/>
<Option name="jack-time-master" value="yes"/>
<Option name="trace-midi-input" value="no"/>
<Option name="trace-midi-output" value="no"/>
<Option name="plugins-stop-with-transport" value="no"/>
<Option name="no-sw-monitoring" value="no"/>
<Option name="stop-recording-on-xrun" value="no"/>
<Option name="stop-at-session-end" value="no"/>
<Option name="auto-xfade" value="yes"/>
<Option name="no-new-session-dialog" value="yes"/>
<Option name="timecode-source-is-synced" value="yes"/>
<Option name="auditioner-left-out" value="%JACK_BACKEND%1"/>
<Option name="auditioner-right-out" value="%JACK_BACKEND%2"/>
<Option name="quieten-at-speed" value="1.000000"/>
<Option name="use-vst" value="yes"/>
</Config>
<Keys>
<context name="default">
<binding keys="Ctrl-w" action="close-dialog"/>
<binding keys="Ctrl-u" action="start-prefix"/>
<binding keys="Alt-e" action="toggle-editor-window"/>
<binding keys="Alt-m" action="toggle-mixer-window"/>
<binding keys="Alt-r" action="toggle-recorder-window"/>
<binding keys="Alt-l" action="toggle-locations-window"/>
<binding keys="Alt-c" action="toggle-big-clock-window"/>
<binding keys="Alt-o" action="toggle-options-window"/>
<binding keys=" " action="toggle-playback"/>
<binding keys="Ctrl-Shift- " action="toggle-playback-forget-capture"/>
<binding keys="Ctrl-n" action="new-session"/>
<binding keys="Ctrl-t" action="add-audio-track"/>
<binding keys="Ctrl-s" action="save-state"/>
<binding keys="Ctrl-q" action="quit"/>
<binding keys="Left" action="transport-rewind"/>
<binding keys="Shift-Left" action="transport-rewind-fast"/>
<binding keys="Ctrl-Left" action="transport-rewind-slow"/>
<binding keys="Right" action="transport-forward"/>
<binding keys="Shift-Right" action="transport-forward-fast"/>
<binding keys="Ctrl-Right" action="transport-forward-slow"/>
<binding keys="R" action="transport-record"/>
<binding keys="i" action="toggle-punch-in"/>
<binding keys="Home" action="transport-goto-start"/>
<binding keys="Ctrl-a" action="transport-goto-start"/>
<binding keys="End" action="transport-goto-end"/>
<binding keys="Ctrl-e" action="transport-goto-end"/>
<binding keys="Ctrl-m" action="send-all-midi-feedback"/>
</context>
<context name="editor">
<binding keys="Tab" action="playhead-to-next-region-start"/>
<binding keys="Ctrl-Tab" action="playhead-to-next-region-end"/>
<binding keys="`" action="playhead-to-previous-region-start"/>
<binding keys="Ctrl-`" action="playhead-to-previous-region-end"/>
<binding keys="[" action="edit-cursor-to-previous-region-start"/>
<binding keys="Ctrl-[" action="edit-cursor-to-previous-region-end"/>
<binding keys="]" action="edit-cursor-to-next-region-start"/>
<binding keys="Ctrl-]" action="edit-cursor-to-next-region-end"/>
<binding keys="'" action="edit-cursor-to-next-region-sync"/>
<binding keys=";" action="edit-cursor-to-previous-region-sync"/>
<binding keys="Left" action="scroll-backward"/>
<binding keys="Right" action="scroll-forward"/>
<binding keys="KP_2" action="start-range"/>
<binding keys="KP_8" action="finish-range"/>
<binding keys="KP_6" action="jump-forward-to-mark"/>
<binding keys="KP_Right" action="jump-forward-to-mark"/>
<binding keys="KP_4" action="jump-backward-to-mark"/>
<binding keys="KP_Left" action="jump-backward-to-mark"/>
<binding keys="KP_Enter" action="add-location-from-playhead"/>
<binding keys="KP_Add" action="nudge-forward"/>
<binding keys="Ctrl-KP_Add" action="nudge-next-forward"/>
<binding keys="KP_Subtract" action="nudge-backward"/>
<binding keys="Ctrl-KP_Subtract" action="nudge-next-backward"/>
<binding keys="=" action="temporal-zoom-out"/>
<binding keys="-" action="temporal-zoom-in"/>
<binding keys="Page_Up" action="scroll-tracks-up"/>
<binding keys="Page_Down" action="scroll-tracks-down"/>
<binding keys="a" action="align-regions-sync-relative"/>
<binding keys="Meta-a" action="align-regions-sync"/>
<binding keys="Meta-Ctrl-a" action="align-regions-end"/>
<binding keys="Ctrl-A" action="align-regions-start-relative"/>
<binding keys="Ctrl-b" action="brush-at-mouse"/>
<binding keys="e" action="set-edit-cursor"/>
<binding keys="f" action="toggle-follow-playhead"/>
<binding keys="r" action="set-mouse-mode-range"/>
<binding keys="g" action="set-mouse-mode-gain"/>
<binding keys="l" action="toggle-auto-loop"/>
<binding keys="o" action="set-mouse-mode-object"/>
<binding keys="p" action="set-playhead"/>
<binding keys="t" action="set-mouse-mode-timefx"/>
<binding keys="s" action="split-at-mouse"/>
<binding keys="Alt-s" action="split-at-edit-cursor"/>
<binding keys="z" action="set-mouse-mode-zoom"/>
<binding keys="Z" action="zoom-focus-playhead"/>
<binding keys="Ctrl-z" action="set-undo"/>
<binding keys="Ctrl-r" action="set-redo"/>
<binding keys="Ctrl-x" action="editor-cut"/>
<binding keys="Ctrl-c" action="editor-copy"/>
<binding keys="Ctrl-v" action="editor-paste"/>
<binding keys="Up" action="step-tracks-up"/>
<binding keys="Down" action="step-tracks-down"/>
<binding keys="Shift-Tab" action="extend-range-to-end-of-region"/>
<binding keys="Ctrl-Shift-Tab" action="extend-range-to-start-of-region"/>
<binding keys="Insert" action="insert-region"/>
<binding keys="Delete" action="editor-cut"/>
<binding keys="Meta-d" action="duplicate-region"/>
<binding keys="Meta-s" action="duplicate-range"/>
<binding keys="Alt-r" action="reverse-region"/>
<binding keys="Alt-n" action="normalize-region"/>
<binding keys="Ctrl-l" action="center-playhead"/>
<binding keys="Ctrl-g" action="goto"/>
<binding keys="Alt-f" action="playhead-forward"/>
<binding keys="Alt-b" action="playhead-backward"/>
<binding keys="Return" action="playhead-to-edit"/>
<binding keys="Alt-Return" action="edit-to-playhead"/>
<binding keys="F1" action="edit-cursor-to-range-start"/>
<binding keys="F2" action="edit-cursor-to-range-end"/>
<binding keys="F9" action="snap-to-beat"/>
<binding keys="F10" action="snap-to-bar"/>
<binding keys="." action="audition-at-mouse"/>
</context>
</Keys>
<extra>
<Keyboard edit-button="3" edit-modifier="4" delete-button="3" delete-modifier="1" snap-modifier="32"/>
</extra>
</Ardour>

94
ardour_system.rc Normal file
View file

@ -0,0 +1,94 @@
<?xml version="1.0"?>
<Ardour>
<Config>
<Option name="minimum-disk-io-bytes" value="262144"/>
<Option name="track-buffer-seconds" value="5.000000"/>
<Option name="mute-affects-pre-fader" value="yes"/>
<Option name="mute-affects-post-fader" value="yes"/>
<Option name="mute-affects-control-outs" value="yes"/>
<Option name="mute-affects-main-outs" value="yes"/>
<Option name="solo-latch" value="yes"/>
<Option name="pixmap-path" value="/usr/share/ardour/pixmaps:/usr/local/share/ardour/pixmaps"/>
<Option name="disk-choice-space-threshold" value="57600000"/>
<Option name="mtc-port" value="trident"/>
<Option name="mmc-port" value="trident"/>
<Option name="monitor-inputs" value="no"/>
</Config>
<Keys>
<context name="default">
<binding keys="Ctrl-w" action="close-dialog"/>
<binding keys="Ctrl-u" action="start-prefix"/>
<binding keys="Alt-e" action="toggle-editor-window"/>
<binding keys="Alt-m" action="toggle-mixer-window"/>
<binding keys="Alt-r" action="toggle-recorder-window"/>
<binding keys="Alt-l" action="toggle-locations-window"/>
<binding keys="Alt-c" action="toggle-big-clock-window"/>
<binding keys="Alt-o" action="toggle-options-window"/>
<binding keys=" " action="toggle-playback"/>
<binding keys="Ctrl-Shift- " action="toggle-playback-forget-capture"/>
<binding keys="Ctrl-n" action="new-session"/>
<binding keys="Ctrl-t" action="add-audio-track"/>
<binding keys="Ctrl-s" action="save-state"/>
<binding keys="Ctrl-q" action="quit"/>
<binding keys="Left" action="transport-rewind"/>
<binding keys="Right" action="transport-forward"/>
<binding keys="r" action="transport-record"/>
<binding keys="Home" action="transport-goto-start"/>
<binding keys="Ctrl-a" action="transport-goto-start"/>
<binding keys="End" action="transport-goto-end"/>
<binding keys="Ctrl-e" action="transport-goto-end"/>
</context>
<context name="editor">
<binding keys="Tab" action="playhead-to-next-region-start"/>
<binding keys="Ctrl-Tab" action="playhead-to-next-region-end"/>
<binding keys="`" action="playhead-to-previous-region-start"/>
<binding keys="Ctrl-`" action="playhead-to-previous-region-end"/>
<binding keys="[" action="edit-cursor-to-previous-region-start"/>
<binding keys="Ctrl-[" action="edit-cursor-to-previous-region-end"/>
<binding keys="]" action="edit-cursor-to-next-region-start"/>
<binding keys="Ctrl-]" action="edit-cursor-to-next-region-end"/>
<binding keys="'" action="edit-cursor-to-next-region-sync"/>
<binding keys=";" action="edit-cursor-to-previous-region-sync"/>
<binding keys="Left" action="scroll-backward"/>
<binding keys="Right" action="scroll-forward"/>
<binding keys="KP_6" action="jump-forward-to-mark"/>
<binding keys="KP_Right" action="jump-forward-to-mark"/>
<binding keys="KP_4" action="jump-backward-to-mark"/>
<binding keys="KP_Left" action="jump-backward-to-mark"/>
<binding keys="KP_Enter" action="add-location-from-playhead"/>
<binding keys="KP_Add" action="nudge-forward"/>
<binding keys="Ctrl-KP_Add" action="nudge-next-forward"/>
<binding keys="KP_Subtract" action="nudge-backward"/>
<binding keys="Ctrl-KP_Subtract" action="nudge-next-backward"/>
<binding keys="=" action="temporal-zoom-out"/>
<binding keys="-" action="temporal-zoom-in"/>
<binding keys="Page_Up" action="scroll-tracks-up"/>
<binding keys="Page_Down" action="scroll-tracks-down"/>
<binding keys="o" action="set-mouse-mode-object"/>
<binding keys="g" action="set-mouse-mode-range"/>
<binding keys="G" action="set-mouse-mode-gain"/>
<binding keys="t" action="set-mouse-mode-timefx"/>
<binding keys="f" action="toggle-follow-playhead"/>
<binding keys="z" action="set-mouse-mode-zoom"/>
<binding keys="Z" action="zoom-focus-playhead"/>
<binding keys="Ctrl-z" action="set-undo"/>
<binding keys="Ctrl-r" action="set-redo"/>
<binding keys="Ctrl-x" action="editor-cut"/>
<binding keys="Ctrl-c" action="editor-copy"/>
<binding keys="Ctrl-v" action="editor-paste"/>
<binding keys="Insert" action="insert-region"/>
<binding keys="Delete" action="editor-cut"/>
<binding keys="Meta-d" action="duplicate-region"/>
<binding keys="Alt-r" action="reverse-region"/>
<binding keys="Alt-n" action="normalize-region"/>
<binding keys="Ctrl-l" action="center-playhead"/>
<binding keys="Ctrl-g" action="goto"/>
<binding keys="Ctrl-f" action="scroll-forward"/>
<binding keys="Ctrl-b" action="scroll-backward"/>
<binding keys="Alt-f" action="playhead-forward"/>
<binding keys="Alt-b" action="playhead-backward"/>
<binding keys="Return" action="playhead-to-edit"/>
<binding keys="Alt-Return" action="edit-to-playhead"/>
</context>
</Keys>
</Ardour>

0
libs/.cvsignore Normal file
View file

15
libs/cassowary/.cvsignore Normal file
View file

@ -0,0 +1,15 @@
.deps
ClReader-lex.cc
ClReader.cc
ClReader.hh
ClReader.cc.h
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.h
config.h.in
config.log
config.status
configure
stamp-h1

37
libs/cassowary/ANNOUNCE Normal file
View file

@ -0,0 +1,37 @@
Announcing the release of a free (for research use) constraint solver:
Cassowary Constraint Solver for Smalltalk, C++, and Java
Version 0.60
Web Page: http://www.cs.washington.edu/research/constraints/cassowary
Distribution: ftp://ftp.cs.washington.edu:/pub/constraints/code/cassowary/
Contact: cassowary@cs.washington.edu
Greg J. Badros <gjb@cs.washington.edu> and
Alan Borning <borning@cs.washington.edu>
University of Washington
Computer Science and Engineering
15-December-1999
with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
Cassowary is an incremental constraint solving toolkit that efficiently
solves systems of linear equalities and inequalities. Constraints may
be either requirements or preferences. Client code specifies the
constraints to be maintained, and the solver updates the constrained
variables to have values that satisfy the constraints.
A technical report is included in the distribution that describes the
algorithm, interface, and implementation of the Cassowary solver.
Additionally, the distribution contains toy sample applications written
in Smalltalk, C++, Java, and Python, and a more complex example Java
applet, the "Constraint Drawing Application".
More information is available on our web page:
http://www.cs.washington.edu/research/constraints/cassowary
See README for more details on getting started using these packages.
See NEWS for a history of user-visible changes.
See LICENSE for legalese regarding use of this distribution.

12
libs/cassowary/AUTHORS Normal file
View file

@ -0,0 +1,12 @@
Cassowary Constraint Solving Toolkit was
Implemented by:
Greg J. Badros <gjb@cs.washington.edu> and
Alan Borning <borning@cs.washington.edu>
University of Washington
Computer Science and Engineering
Seattle, WA 98195-2350
with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
Please send bug reports to cassowary@cs.washington.edu

340
libs/cassowary/COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

444
libs/cassowary/COPYING.LGPL Normal file
View file

@ -0,0 +1,444 @@
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.
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.
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.
2. You may modify your copy or copies of the Library or any portion of
it, thus forming a work based on the Library, and copy and distribute
such modifications or work under the terms of Section 1 above, provided
that you also meet all of these conditions:
a) The modified work must itself be a software library. b) You
must cause the files modified to carry prominent notices stating
that you changed the files and the date of any change. c) You
must cause the whole of the work to be licensed at no charge to
all third parties under the terms of this License. d) If a
facility in the modified Library refers to a function or a table
of data to be supplied by an application program that uses the
facility, other than as an argument passed when the facility is
invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the
Library, and can be reasonably considered independent and
separate works in themselves, then this License, and its terms,
do not apply to those sections when you distribute them as
separate works. But when you distribute the same sections as part
of a whole which is a work based on the Library, the distribution
of the whole must be on the terms of this License, whose
permissions for other licensees extend to the entire whole, and
thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or
contest your rights to work written entirely by you; rather, the
intent is to exercise the right to control the distribution of
derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the
Library with the Library (or with a work based on the Library) on
a volume of a storage or distribution medium does not bring the
other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so that
they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in these
notices.
Once this change is made in a given copy, it is irreversible for that
copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the
Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative
of it, under Section 2) in object code or executable form under the
terms of Sections 1 and 2 above provided that you accompany it with the
complete corresponding machine-readable source code, which must be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange.
If distribution of object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source
code from the same place satisfies the requirement to distribute the
source code, even though third parties are not compelled to copy the
source along with the object code.
5. A program that contains no derivative of any portion of the Library,
but is designed to work with the Library by being compiled or linked
with it, is called a "work that uses the Library". Such a work, in
isolation, is not a derivative work of the Library, and therefore falls
outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates
an executable that is a derivative of the Library (because it contains
portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License. Section 6
states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is
not. Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure
layouts and accessors, and small macros and small inline functions (ten
lines or less in length), then the use of the object file is
unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section
6. Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also 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.
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.
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.
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

2002
libs/cassowary/ChangeLog Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClAbstractVariable.cc
#include <cassowary/ClAbstractVariable.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
long ClAbstractVariable::iVariableNumber = 0;
#ifdef CL_FIND_LEAK
long ClAbstractVariable::cAbstractVariables = 0;
#endif

102
libs/cassowary/ClBug0.cc Normal file
View file

@ -0,0 +1,102 @@
// $Id$
#include <cassowary/Cl.h>
/* This bug fixed --02/15/99 gjb
Replaced the parallel vectors for edit constraints
(the errorPlus..., errorMinus..., prevEditConstants vectors)
with a ClEditInfo class that is the Value of the _editVarMap map.
Later I realized that I need to go to a _editVars list so that
multiple edits on the same variable that nest are handled properly.
--09/19/99 gjb
*/
int main()
{
ClSimplexSolver solver;
ClVariable x("x",7);
ClVariable y("y",8);
ClVariable z("z",9);
solver
.AddStay(x)
.AddStay(y)
.AddStay(z);
try {
solver.AddEditVar(x);
solver.AddEditVar(y);
solver.AddEditVar(z);
solver.BeginEdit();
solver.SuggestValue(x,1);
solver.SuggestValue(z,2);
solver.RemoveEditVar(y);
solver.SuggestValue(x,3);
solver.SuggestValue(z,4);
solver.EndEdit();
} catch (ExCLError &e) {
cerr << e.description() << endl;
}
cout << x << endl << y << endl << z <<endl;
}
#if 0 /* Message below */
From: "Michael Kaufmann" <Michael.Kaufmann@ubs.com>
To: <noth@cs.washington.edu>
Subject: bugreport
Date: Thu, 1 Oct 1998 11:40:55 +0200
Message-Id: <000001bded1f$973a2060$230e1fac@itc_mk.sbcs.swissbank.com>
Mime-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Priority: 3 (Normal)
X-Msmail-Priority: Normal
X-Mailer: Microsoft Outlook 8.5, Build 4.71.2173.0
Importance: Normal
X-Mimeole: Produced By Microsoft MimeOLE V4.72.2106.4
Dear Mr Noth,
I am currently working with the Java implementation of Cassowary and found
the following bug:
If I Add several editConstraints, remove some of them again later and
perform a 'ClSimplexSolver.SuggestValue()', the indices of
'ClConstraintAndIndex' in the variable 'cai' are sometimes wrong (see
ClSimplexSolver.SuggestValue(ClVariable v, double x), the 3rd line). This is
because if you remove an element from a 'java.util.Vector', and the element
is somewhere in the middle of the Vector, the indices of the Vector change.
(see java.util.Vector.removeElementAt(int index):
public final synchronized void removeElementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
My workaround now is, that everytime when I remove an EditVariable from the
Solver, I have to remove all the EditVariables and Add then the ones again,
that I do not want to remove.
#endif

21
libs/cassowary/ClBug1.cc Normal file
View file

@ -0,0 +1,21 @@
#include <cassowary/Cl.h>
int main()
{
ClVariable *var = new ClVariable();
ClSimplexSolver *solver = new ClSimplexSolver();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),1.0);
cout << *solver;
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
/*
The result is a segmentation fault when the constraint is removed. I
don't understand why.
Anthony Beurive'" <beurive@labri.u-bordeaux.fr>
*/

130
libs/cassowary/ClBug2.cc Normal file
View file

@ -0,0 +1,130 @@
/* $Id$
From: "Anthony Beurive'" <beurive@labri.u-bordeaux.fr>
Subject: cassowary
To: gjb@cs.washington.edu
Date: Tue, 9 Mar 1999 12:42:24 +0100 (CET)
I believe there's a bug in cassowary. It seems to be related to the
previous one I encountered a while ago, concerning the removal of
constraints.
The three following examples may help you to track the bug, I hope.
--------------------------------------------------------------------------------
#include "Cl.h"
void main()
{
ClSimplexSolver *solver = new ClSimplexSolver();
ClVariable *var = new ClVariable();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),1.0);
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
--------------------------------------------------------------------------------
This works fine.
Now, the factor of the stay constraint is changed.
--------------------------------------------------------------------------------
#include "Cl.h"
void main()
{
ClSimplexSolver *solver = new ClSimplexSolver();
ClVariable *var = new ClVariable();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
--------------------------------------------------------------------------------
The result is:
test2: ClSimplexSolver.cc:1199: void ClSimplexSolver::Optimize(class ClVariable): Assertion \
`pzRow != __null' failed.
Aborted
Now, the solver is created after the variable.
--------------------------------------------------------------------------------
#include "Cl.h"
void main()
{
ClVariable *var = new ClVariable();
ClSimplexSolver *solver = new ClSimplexSolver();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
--------------------------------------------------------------------------------
This works again.
Can you reproduce the same results? Maybe the cause is my c++
compiler (egcs-2.90.29 980515 (egcs-1.0.3 release)). I don't know.
*/
#include <cassowary/Cl.h>
void foo1()
{
ClSimplexSolver *solver = new ClSimplexSolver();
ClVariable *var = new ClVariable();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),1.0);
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
void foo2()
{
ClSimplexSolver *solver = new ClSimplexSolver();
ClVariable *var = new ClVariable();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
void foo3()
{
ClVariable *var = new ClVariable();
ClSimplexSolver *solver = new ClSimplexSolver();
ClStayConstraint *stcn = new ClStayConstraint(*var,ClsWeak(),2.0);
solver->AddConstraint(*stcn);
cout << *solver;
solver->RemoveConstraint(*stcn);
cout << *solver;
}
int main()
{
cerr << "Test1: " << endl;
foo1();
cerr << "\nTest2: " << endl;
foo2();
cerr << "\nTest3: " << endl;
foo3();
}

View file

@ -0,0 +1,32 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClConstraint.cc
#include <cassowary/ClConstraint.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#ifndef CL_NO_IO
#include <cassowary/ClTableau.h> // for VarSet printing
ostream &
ClConstraint::PrintOn(ostream &xo) const
{
// Note that the trailing "= 0)" or ">= 0)" is missing, as derived classes will
// print the right thing after calling this function
xo << strength() << " w{" << weight() << "} ta{"
<< _times_added << "} RO" << _readOnlyVars << " " << "(" << Expression();
return xo;
}
#endif

View file

@ -0,0 +1,12 @@
// $Id$
#include <cassowary/ClDummyVariable.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#ifdef CL_FIND_LEAK
long ClDummyVariable::cDummyVariables = 0;
#endif

View file

@ -0,0 +1,140 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDBinaryOneWayConstraint.cc
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#include <cassowary/ClFDBinaryOneWayConstraint.h>
#include <cassowary/ClLinearConstraint.h>
#include <cassowary/ClTypedefs.h>
#include <cassowary/ClLinearExpression.h>
void
ClFDBinaryOneWayConstraint::EnsurePreconditionsForCn(const ClConstraint &cn)
{
ClVarSet setRO = cn.ReadOnlyVars();
if (setRO.size() > 1)
throw ExCLTooDifficultSpecial("Only 0 or 1 read only variables are allowed");
const ClLinearExpression &expr = cn.Expression();
const ClVarToNumberMap &terms = expr.Terms();
if (terms.size() > 2)
throw ExCLTooDifficultSpecial("Cannot have more than 2 variables");
if (terms.size() == 0)
throw ExCLTooDifficultSpecial("Must have at least 1 variable");
if (terms.size() == 2 && setRO.size() == 0)
throw ExCLTooDifficultSpecial("Both variables cannot be read-write, one must be read-only");
if (terms.size() == 1 && setRO.size() == 1)
throw ExCLTooDifficultSpecial("Single read-only variable in LinearConstraint -- must not be read-only.");
ClVariable clv = (*terms.begin()).first;
/* GJB:FIXME:: iterate over all the variables */
if (!clv->IsFDVariable()) {
throw ExCLTooDifficultSpecial("FD constraint contains non-FD variables");
}
}
bool
ClFDBinaryOneWayConstraint::FCanConvertCn(const ClConstraint &cn)
{
try {
EnsurePreconditionsForCn(cn);
return true;
} catch (...) {
return false;
}
}
ClFDBinaryOneWayConstraint::ClFDBinaryOneWayConstraint(const ClConstraint &cn)
:ClFDConstraint(cn.strength(), cn.weight())
{
EnsurePreconditionsForCn(cn);
list<FDNumber> l;
/* GJB:FIXME:: varargs inteface, with sentinel as first arg? */
l.push_back(9);
l.push_back(10);
l.push_back(12);
l.push_back(14);
l.push_back(20);
ClVarSet setRO = cn.ReadOnlyVars();
ClVariable clvRO = clvNil;
ClVariable clvROLinear = clvNil;
Number coeffRO = 0;
ClVariable clvRW = clvNil;
Number coeffRW = 0;
if (setRO.size() == 1) {
const ClVariable &clv = *(setRO.begin());
if (clv->IsFDVariable())
clvRO = clv;
else
clvRO = new ClFDVariable(clv.Name(),clv.IntValue(),l);
clvROLinear = clv;
}
const ClLinearExpression &expr = cn.Expression();
const ClVarToNumberMap &terms = expr.Terms();
for (ClVarToNumberMap::const_iterator it = terms.begin();
it != terms.end();
++it) {
ClVariable clv = (*it).first;
if (clv == clvROLinear) {
coeffRO = (*it).second;
} else {
if (clv->IsFDVariable())
clvRW = clv;
else
clvRW = new ClFDVariable(clv.Name(),clv.Value(),l);
coeffRW = (*it).second;
}
}
assert(!clvRW.IsNil());
if (coeffRW == 0) {
throw ExCLTooDifficultSpecial("RW variable's coefficient must be non-zero");
}
bool fInequality = cn.IsInequality();
bool fStrictInequality = cn.IsStrictInequality();
double rhs_constant = expr.Constant();
// now we have:
// coeffRW * clvRW + coeffRO * clvRO <REL> rhs_constant
// where <REL> is >= if fInequality, or = if !fInequality
//
// need:
// clvRW <REL> coefficient * clvRO + constant
//
// so:
// coefficient = -coeffRO/coeffRW
// constant = rhs_constant/coeffRW
if (fStrictInequality)
_rel = cnGT;
else if (fInequality)
_rel = cnGEQ;
else
_rel = cnEQ;
if (coeffRW < 0)
_rel = ReverseInequality(_rel);
_coefficient = -coeffRO/coeffRW;
_constant = -rhs_constant/coeffRW;
_vRW = clvRW;
_vRO = clvRO;
return;
}

View file

@ -0,0 +1,29 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDConnectorVariable.cc
#include <cassowary/ClFDConnectorVariable.h>
#include <cassowary/ClSolver.h> // for list<FDNumber> printing
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
// Use < > for ClFDConnector-s, instead of [ ]
#ifndef CL_NO_IO
ostream &ClFDConnectorVariable::PrintOn(ostream &xo) const
{
xo << "<" << Name() << "=" << Value()
<< "{" << _clvFloat << "}"
<< ":" << *PlfdnDomain() << ">";
return xo;
}
#endif

View file

@ -0,0 +1,364 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDSolver.cc
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#include <cassowary/Cassowary.h>
#include <cassowary/ClFDSolver.h>
#include <cassowary/ClFDBinaryOneWayConstraint.h>
#include <cassowary/ClVariable.h>
#include <cassowary/debug.h>
#include <GTL/topsort.h>
#include <pair.h>
#include <math.h>
#include <stdarg.h>
static int fDebugFDSolve;
ClFDSolver &
ClFDSolver::AddConstraint(ClConstraint *const pcn)
{
AddConstraintInternal(pcn);
if (_fAutosolve) Solve();
return *this;
}
ClFDSolver &
ClFDSolver::RemoveConstraint(ClConstraint *const pcn)
{
RemoveConstraintInternal(pcn);
if (_fAutosolve) Solve();
return *this;
}
ClFDSolver &
ClFDSolver::AddConstraintInternal(ClConstraint *const pcn)
{
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << *pcn << ")" << endl;
#endif
ClFDBinaryOneWayConstraint *const pcnfd =
dynamic_cast<ClFDBinaryOneWayConstraint *const>(pcn);
if (!pcnfd) {
throw ExCLTooDifficultSpecial("Can only add ClFDBinaryOneWayConstraint-s to ClFDSolvers");
}
ClVariable rw = pcnfd->ClvRW();
ClVariable ro = pcnfd->ClvRO();
if (!rw.IsFDVariable()) {
throw ExCLTooDifficultSpecial("RW variable must be an FDVariable");
}
if (!(ro.IsNil() || ro.IsFDVariable())) {
throw ExCLTooDifficultSpecial("RO variable must be an FDVariable or clvNil");
}
// add the constraint to our set of cns
_setCns.insert(pcn);
// and add the constraint to the cns that affect var rw
assert(!rw.IsNil());
_mapClvToCns[rw].insert(pcn);
node nRw = GetVarNode(rw);
if (!ro.IsNil()) {
node nRo = GetVarNode(ro);
edge e = G.new_edge(nRo, nRw);
_mapCnToEdge[pcn] = e;
if (!G.is_acyclic()) {
/* there is a cycle... give up after cleaning up */
RemoveConstraint(pcn);
throw ExCLCycleNotAllowed();
}
}
return *this;
}
ClFDSolver &
ClFDSolver::RemoveConstraintInternal(ClConstraint *const pcn)
{
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << *pcn << ")" << endl;
#endif
ClFDBinaryOneWayConstraint *const pcnfd =
dynamic_cast<ClFDBinaryOneWayConstraint *const>(pcn);
if (!pcnfd) {
throw ExCLInternalError("Could not downcast to a ClFDBinaryOneWayConstraint");
}
ClConstraintSet::iterator itCn = _setCns.find(pcnfd);
if (itCn == _setCns.end()) {
throw ExCLConstraintNotFound();
}
_setCns.erase(itCn);
ClVariable rw = pcnfd->ClvRW();
ClVariable ro = pcnfd->ClvRO();
ClConstraintSet &_cnsAffectingRW = _mapClvToCns[rw];
ClConstraintSet::iterator it = _cnsAffectingRW.find(pcnfd);
if (it == _cnsAffectingRW.end()) {
throw ExCLInternalError("Cannot find pcnfd");
}
_cnsAffectingRW.erase(it);
if (!ro.IsNil()) {
edge e = _mapCnToEdge[pcn];
G.del_edge(e);
_mapCnToEdge.erase(pcn);
if (_mapVarToNode.find(ro) != _mapVarToNode.end() &&
_mapVarToNode[ro].degree() == 0) {
G.del_node(_mapVarToNode[ro]);
_mapVarToNode.erase(ro);
}
}
if (_mapVarToNode.find(rw) != _mapVarToNode.end() &&
_mapVarToNode[rw].degree() == 0) {
G.del_node(_mapVarToNode[rw]);
_mapVarToNode.erase(rw);
}
if (_mapClvToCns[rw].size() == 0) {
_mapClvToCns.erase(rw);
}
return *this;
}
ClFDSolver &
ClFDSolver::Solve()
{
topsort t;
t.run(G);
topsort::topsort_iterator it = t.top_order_begin();
topsort::topsort_iterator end = t.top_order_end();
ClSymbolicWeight errorTotal;
ResetSetFlagsOnVariables();
for (; it != end; ++it) {
ClVariable clv = nodeToVar[*it];
ClFDVariable *pcldv = dynamic_cast<ClFDVariable*>(clv.get_pclv());
#ifndef NO_FDSOLVE_DEBUG
if (fDebugFDSolve) {
if (!clv.IsNil()) cout << "node " << (*it) << " is " << clv << endl;
cerr << "Set from: " << endl;
for (ClConstraintSet::iterator itCns = _mapClvToCns[clv].begin();
itCns != _mapClvToCns[clv].end();
++itCns) {
const ClConstraint *pcn = *itCns;
cerr << *pcn << endl;
}
cerr << endl;
}
#endif
pair<ClSymbolicWeight,FDNumber> p = ComputeBest(pcldv);
ClSymbolicWeight e = p.first;
FDNumber v = p.second;
if (v == FDN_NOTSET)
throw ExCLRequiredFailure();
pcldv->ChangeValue(v);
pcldv->SetFIsSet(true);
errorTotal += e;
}
return *this;
}
/* return the best (lowest) incremental error and the value
at which that error occurs */
pair<ClSymbolicWeight,FDNumber>
ClFDSolver::ComputeBest(ClFDVariable *pcldv)
{
assert(pcldv);
// assert(!pcldv->FIsSet()); //GJB:FIXME::
ClSymbolicWeight minError = ClsRequired().symbolicWeight();
FDNumber bestValue = FDN_NOTSET;
// ClVariable clv(pcldv);
// for each domain value
for (list<FDNumber>::const_iterator itVal= pcldv->PlfdnDomain()->begin();
itVal != pcldv->PlfdnDomain()->end();
++itVal) {
FDNumber value = *itVal;
ClSymbolicWeight error;
const ClConstraintSet &setCns = _mapClvToCns[pcldv];
// for each constraint affecting *pcldv
for (ClConstraintSet::const_iterator itCn = setCns.begin();
itCn != setCns.end();
++itCn) {
const ClConstraint *pcn = *itCn;
ClSymbolicWeight e = ErrorForClvAtValSubjectToCn(pcldv,value,*pcn);
error += e;
}
// now error is the total error for binding clv <- value
if (error < minError) {
minError = error;
bestValue = value;
}
}
// now minError is the lowest error we can get for clv
// and it occurs binding clv <- bestValue
if (bestValue == FDN_NOTSET)
throw ExCLRequiredFailure();
return pair<ClSymbolicWeight,FDNumber>(minError,bestValue);
}
ClSymbolicWeight
ClFDSolver::ErrorForClvAtValSubjectToCn(ClFDVariable *pcldv,FDNumber value,const ClConstraint &cn)
{
const ClFDBinaryOneWayConstraint *pcnFd = dynamic_cast<const ClFDBinaryOneWayConstraint*>(&cn);
if (!pcnFd) throw ExCLInternalError("Not a binary FD constraint.");
ClCnRelation rel = pcnFd->Relation();
double m = pcnFd->Coefficient();
double b = pcnFd->Constant();
ClVariable rw = pcnFd->ClvRW();
ClVariable ro = pcnFd->ClvRO();
assert(rw.get_pclv() == pcldv);
double e;
double x = ro.IsNil()? 0 : ro.Value();
// return the error in satisfying:
// value REL m*x + b
double rhs = m*x + b;
switch (rel) {
case cnLEQ:
if (value <= rhs) e = 0;
else e = 1 + value-rhs;
break;
case cnLT:
if (value < rhs) e = 0;
else e = 1 + value-rhs;
break;
case cnGEQ:
if (value >= rhs) e = 0;
else e = 1+ rhs-value;
break;
case cnGT:
if (value > rhs) e = 0;
else e = 1 + rhs-value;
break;
case cnEQ:
if (value == rhs) e = 0;
else e = 1 + fabs(rhs-value);
break;
case cnNEQ:
if (value != rhs) e = 0;
else e = 1; /* GJB:FIXME:: what makes sense here? */
break;
default:
e = 0; /* quiet warning */
assert(false);
}
ClSymbolicWeight err;
if (cn.IsRequired() && e > 0)
err = ClsRequired().symbolicWeight();
else
err = cn.symbolicWeight() * (e*cn._weight);
#ifndef NO_FDSOLVE_DEBUG
if (fDebugFDSolve) {
cerr << "Error at " << value << " = " << err << endl;
}
#endif
return err;
}
ClFDSolver &
ClFDSolver::ShowSolve()
{
topsort t;
t.run(G);
topsort::topsort_iterator it = t.top_order_begin();
topsort::topsort_iterator end = t.top_order_end();
for (; it != end; ++it) {
ClVariable clv = nodeToVar[*it];
if (!clv.IsNil()) cout << "Node " << (*it) << " is " << clv << endl;
cout << "Set from: " << endl;
for (ClConstraintSet::iterator itCns = _mapClvToCns[clv].begin();
itCns != _mapClvToCns[clv].end();
++itCns) {
const ClConstraint *pcn = *itCns;
cout << *pcn << endl;
}
cout << endl;
}
return *this;
}
/* Turn all FDVariable FIsSet() flags to false */
void
ClFDSolver::ResetSetFlagsOnVariables()
{
for (ClVarToConstraintSetMap::iterator it = _mapClvToCns.begin();
it != _mapClvToCns.end();
++it) {
ClVariable clv = (*it).first;
ClFDVariable *pcldv = dynamic_cast<ClFDVariable*>(clv.get_pclv());
assert(pcldv);
pcldv->SetFIsSet(false);
}
}
ostream &
ClFDSolver::PrintOn(ostream &xo) const
{
xo << "FDSolver: "
<< _setCns
<< "Graph nodes, edges = " << G.number_of_nodes() << ", " << G.number_of_edges()
<< endl;
return xo;
}
ostream &
ClFDSolver::PrintInternalInfo(ostream &xo) const
{ return xo; }
ostream &operator<<(ostream &xo, const ClFDSolver &clfds)
{ return clfds.PrintOn(xo); }
//// protected member functions
/* Create node for v in G, if necessary,
otherwise return the node we already created. */
node
ClFDSolver::GetVarNode(ClVariable v)
{
ClMap<ClVariable,node>::iterator it = _mapVarToNode.find(v);
if (it == _mapVarToNode.end()) {
node n = G.new_node();
_mapVarToNode[v] = n;
nodeToVar[n] = v;
return n;
} else {
return (*it).second;
}
}
void
ListPushOnto(list<FDNumber> *pl, ...)
{
va_list ap;
va_start(ap, pl);
FDNumber n;
while ( (n = va_arg(ap, FDNumber)) != FDN_EOL) {
pl->push_back(n);
}
va_end(ap);
}

View file

@ -0,0 +1,27 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDVariable.cc
#include <cassowary/ClFDVariable.h>
#include <cassowary/ClSolver.h> // for list<FDNumber> printing
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
// Use < > for ClFDVariable-s, instead of [ ]
#ifndef CL_NO_IO
ostream &ClFDVariable::PrintOn(ostream &xo) const
{
xo << "<" << Name() << "=" << Value() << ":" << *PlfdnDomain() << ">";
return xo;
}
#endif

View file

@ -0,0 +1,25 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFloatVariable.cc
#include <cassowary/ClFloatVariable.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#ifndef CL_NO_IO
ostream &ClFloatVariable::PrintOn(ostream &xo) const
{
xo << "[" << Name() << ":" << _value << "]";
return xo;
}
#endif

View file

@ -0,0 +1,473 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearExpression.cc
using namespace std;
#include <cassowary/ClLinearExpression.h>
#include <cassowary/ClSymbolicWeight.h> /// needed only to instantiate with T=ClSymbolicWeight
#include <cassowary/ClVariable.h>
#include <cassowary/ClTableau.h>
#include <cassowary/ClErrors.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
template <class T>
ClGenericLinearExpression<T>::ClGenericLinearExpression(T num) :
_constant(num)
{ }
// Convert from ClVariable to a ClLinearExpression
// this replaces ClVariable::asLinearExpression
template <class T>
ClGenericLinearExpression<T>::ClGenericLinearExpression(ClVariable clv, T value,
T Constant) :
_constant(Constant)
{
_terms[clv] = value;
}
template <class T>
ClGenericLinearExpression<T>::~ClGenericLinearExpression()
{ }
#ifndef CL_NO_IO
template <class T>
ostream &
ClGenericLinearExpression<T>::PrintOn(ostream &xo) const
{
typename ClVarToCoeffMap::const_iterator i = _terms.begin();
if (!ClApprox(_constant,0.0) || i == _terms.end())
{
xo << _constant;
}
else
{
if (i == _terms.end())
return xo;
xo << (*i).second << "*" << (*i).first;
++i;
}
for ( ; i != _terms.end(); ++i)
{
xo << " + " << (*i).second << "*" << (*i).first;
}
return xo;
}
#endif
// Destructively multiply self by x.
// (private memfn)
template <class T>
ClGenericLinearExpression<T> &
ClGenericLinearExpression<T>::MultiplyMe(T x)
{
_constant *= x;
typename ClVarToCoeffMap::const_iterator i = _terms.begin();
for ( ; i != _terms.end(); ++i)
{
_terms[(*i).first] = (*i).second * x;
}
return *this;
}
// Return a new linear expression formed by multiplying self by x.
// (Note that this result must be linear.)
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::Times(Number x) const
{
ClGenericLinearExpression<T> result = *this;
return result.MultiplyMe(x);
}
// Return a new linear expression formed by multiplying self by x.
// (Note that this result must be linear.)
// The above function optimizes the specific case of multiplying
// by a Constant, here is the more general case
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::Times(const ClGenericLinearExpression<T> &expr) const
{
if (IsConstant())
{
return expr.Times(_constant);
}
else if (!expr.IsConstant())
{
// neither are constants, so we'd introduce non-linearity
throw ExCLNonlinearExpression();
}
return Times(expr._constant);
}
// Return a new linear expression formed by adding x to self.
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::Plus(const ClGenericLinearExpression<T> &expr) const
{
ClGenericLinearExpression<T> result = *this;
result.AddExpression(expr,1.0);
return result;
}
// Return a new linear expression formed by subtracting x from self.
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::Minus(const ClGenericLinearExpression<T> &expr) const
{
ClGenericLinearExpression<T> result = *this;
result.AddExpression(expr,-1.0);
return result;
}
// Return a new linear expression formed by dividing self by x.
// (Note that this result must be linear.)
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::Divide(Number x) const
{
if (ClApprox(x,0.0))
{
throw ExCLNonlinearExpression();
}
return Times(1.0/x);
}
// Return a new linear expression formed by dividing self by x.
// (Note that this result must be linear.)
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::Divide(const ClGenericLinearExpression<T> &expr) const
{
if (!expr.IsConstant())
{
throw ExCLNonlinearExpression();
}
return Divide(expr._constant);
}
// Return a new linear expression (expr/this). Since the result
// must be linear, this is permissible only if 'this' is a Constant.
template <class T>
ClGenericLinearExpression<T>
ClGenericLinearExpression<T>::DivFrom(const ClGenericLinearExpression<T> &expr) const
{
if (!IsConstant() || ClApprox(_constant,0.0))
{
throw ExCLNonlinearExpression();
}
return expr.Divide(_constant);
}
// Add n*expr to this expression for another expression expr.
template <class T>
ClGenericLinearExpression<T> &
ClGenericLinearExpression<T>::AddExpression(const ClGenericLinearExpression<T> &expr, Number n)
{
IncrementConstant(expr.Constant()*n);
typename ClVarToCoeffMap::const_iterator i = expr._terms.begin();
for ( ; i != expr._terms.end(); ++i)
{
AddVariable((*i).first, (*i).second * n);
}
return *this;
}
// Add n*expr to this expression for another expression expr.
// Notify the solver if a variable is added or deleted from this
// expression.
template <class T>
ClGenericLinearExpression<T> &
ClGenericLinearExpression<T>::AddExpression(const ClGenericLinearExpression<T> &expr, Number n,
ClVariable subject,
ClTableau &solver)
{
IncrementConstant(expr.Constant() * n);
typename ClVarToCoeffMap::const_iterator i = expr._terms.begin();
for ( ; i != expr._terms.end(); ++i)
{
AddVariable((*i).first, (*i).second * n, subject, solver);
}
return *this;
}
// Add a term c*v to this expression. If the expression already
// contains a term involving v, Add c to the existing coefficient.
// If the new coefficient is approximately 0, delete v.
template <class T>
ClGenericLinearExpression<T> &
ClGenericLinearExpression<T>::AddVariable(ClVariable v, T c)
{ // body largely duplicated below
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << v << ", " << c << ")" << endl;
#endif
typename ClVarToCoeffMap::iterator i = _terms.find(v);
if (i != _terms.end())
{
// expression already contains that variable, so Add to it
T new_coefficient = 0;
new_coefficient = (*i).second + c;
if (ClApprox(new_coefficient,0.0))
{
// new coefficient is Zero, so erase it
_terms.erase(i);
}
else
{
(*i).second = new_coefficient;
}
}
else // expression did not contain that variable
{
if (!ClApprox(c,0.0))
{
_terms[v] = c;
}
}
return *this;
}
// Add a term c*v to this expression. If the expression already
// contains a term involving v, Add c to the existing coefficient.
// If the new coefficient is approximately 0, delete v. Notify the
// solver if v appears or disappears from this expression.
template <class T>
ClGenericLinearExpression<T> &
ClGenericLinearExpression<T>::AddVariable(ClVariable v, T c,
ClVariable subject,
ClTableau &solver)
{ // body largely duplicated above
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << v << ", " << c << ", " << subject << ", ...)" << endl;
#endif
typename ClVarToCoeffMap::iterator i = _terms.find(v);
if (i != _terms.end())
{
// expression already contains that variable, so Add to it
T new_coefficient = (*i).second + c;
if (ClApprox(new_coefficient,0.0))
{
// new coefficient is Zero, so erase it
solver.NoteRemovedVariable((*i).first,subject);
_terms.erase(i);
}
else
{
(*i).second = new_coefficient;
}
}
else // expression did not contain that variable
{
if (!ClApprox(c,0.0))
{
_terms[v] = c;
solver.NoteAddedVariable(v,subject);
}
}
#ifdef CL_TRACE
cerr << "Now *this == " << *this << endl;
#endif
return *this;
}
// Return a variable in this expression. (It is an error if this
// expression is Constant -- signal ExCLInternalError in that case).
template <class T>
ClVariable
ClGenericLinearExpression<T>::AnyPivotableVariable() const
{
if (IsConstant())
{
throw ExCLInternalError("(ExCLInternalError) No pivotable variables in Constant expression");
}
typename ClVarToCoeffMap::const_iterator i = _terms.begin();
for ( ; i != _terms.end(); ++i)
{
ClVariable v = (*i).first;
if (v.IsPivotable())
return v;
}
return clvNil;
}
// Replace var with a symbolic expression expr that is equal to it.
// If a variable has been added to this expression that wasn't there
// before, or if a variable has been dropped from this expression
// because it now has a coefficient of 0, inform the solver.
// PRECONDITIONS:
// var occurs with a non-Zero coefficient in this expression.
template <class T>
void
ClGenericLinearExpression<T>::SubstituteOut(ClVariable var,
const ClGenericLinearExpression<T> &expr,
ClVariable subject,
ClTableau &solver)
{
#ifdef CL_TRACE
cerr << "* ClGenericLinearExpression::";
Tracer TRACER(__FUNCTION__);
cerr << "(" << var << ", " << expr << ", " << subject << ", "
<< solver << ")" << endl;
cerr << "*this == " << *this << endl;
#endif
typename ClVarToCoeffMap::iterator pv = _terms.find(var);
#ifndef NDEBUG
if (pv == _terms.end())
{
#ifndef CL_NO_IO
cerr << "SubstituteOut: pv != _terms.end()" << endl;
cerr << "(" << var << ", " << expr << ", " << subject << ", "
<< ")" << endl;
cerr << "*this == " << *this << endl;
#endif
throw "SubstituteOut: pv != _terms.end()";
}
#endif
assert(pv != _terms.end());
// FIXGJB: this got thrown! assert(!ClApprox((*pv).second,0.0));
T multiplier = (*pv).second;
_terms.erase(pv);
IncrementConstant(multiplier * expr._constant);
typename ClVarToCoeffMap::const_iterator i = expr._terms.begin();
for ( ; i != expr._terms.end(); ++i)
{
ClVariable v = (*i).first;
T c = (*i).second;
typename ClVarToCoeffMap::iterator poc = _terms.find(v);
if (poc != _terms.end())
{ // if oldCoeff is not nil
#ifdef CL_TRACE
cerr << "Considering (*poc) == " << (*poc).second << "*" << (*poc).first << endl;
#endif
// found it, so new coefficient is old one Plus what is in *i
T newCoeff = (*poc).second + (multiplier*c);
if (ClApprox(newCoeff,0.0))
{
solver.NoteRemovedVariable((*poc).first,subject);
_terms.erase(poc);
}
else
{
(*poc).second = newCoeff;
}
}
else
{ // did not have that variable already (oldCoeff == nil)
#ifdef CL_TRACE
cerr << "Adding (*i) == " << (*i).second << "*" << (*i).first << endl;
#endif
_terms[v] = multiplier * c;
solver.NoteAddedVariable(v,subject);
}
}
#ifdef CL_TRACE
cerr << "Now (*this) is " << *this << endl;
#endif
}
// This linear expression currently represents the equation
// oldSubject=self. Destructively modify it so that it represents
// the equation NewSubject=self.
//
// Precondition: NewSubject currently has a nonzero coefficient in
// this expression.
//
// NOTES
// Suppose this expression is c + a*NewSubject + a1*v1 + ... + an*vn.
//
// Then the current equation is
// oldSubject = c + a*NewSubject + a1*v1 + ... + an*vn.
// The new equation will be
// NewSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn.
// Note that the term involving NewSubject has been dropped.
//
// Basically, we consider the expression to be an equation with oldSubject
// equal to the expression, then Resolve the equation for NewSubject,
// and destructively make the expression what NewSubject is then equal to
template <class T>
void
ClGenericLinearExpression<T>::ChangeSubject(ClVariable old_subject,
ClVariable new_subject)
{
_terms[old_subject] = NewSubject(new_subject);
}
inline double ReciprocalOf(double n)
{ return 1.0/n; }
// This linear expression currently represents the equation self=0. Destructively modify it so
// that subject=self represents an equivalent equation.
//
// Precondition: subject must be one of the variables in this expression.
// NOTES
// Suppose this expression is
// c + a*subject + a1*v1 + ... + an*vn
// representing
// c + a*subject + a1*v1 + ... + an*vn = 0
// The modified expression will be
// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
// representing
// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn = 0
//
// Note that the term involving subject has been dropped.
//
// Returns the reciprocal, so that NewSubject can be used by ChangeSubject
template <class T>
T
ClGenericLinearExpression<T>::NewSubject(ClVariable subject)
{
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << subject << ")" << endl;
#endif
typename ClVarToCoeffMap::iterator pnewSubject = _terms.find(subject);
assert(pnewSubject != _terms.end());
// assert(!ClApprox((*pnewSubject).second,0.0));
T reciprocal = ReciprocalOf((*pnewSubject).second);
_terms.erase(pnewSubject);
MultiplyMe(-reciprocal);
return reciprocal;
}
template <class T>
T
ClGenericLinearExpression<T>::Evaluate() const
{
T answer = _constant;
typename ClVarToCoeffMap::const_iterator i = _terms.begin();
for ( ; i != _terms.end(); ++i)
{
ClVariable v = (*i).first;
answer += (*i).second * v.Value();
}
return answer;
}
template class ClGenericLinearExpression<Number>;
// template class ClGenericLinearExpression<ClSymbolicWeight>;

87
libs/cassowary/ClReader.l Normal file
View file

@ -0,0 +1,87 @@
/* $Id$
Cassowary Incremental Constraint Solver
Original Smalltalk Implementation by Alan Borning
This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
http://www.cs.washington.edu/homes/gjb
(C) 1998, 1999 Greg J. Badros and Alan Borning
See ../LICENSE for legal details regarding this software
ClReader.l - Scanner for constraint parsing.
By Greg J. Badros
*/
%{
/* Get the token numbers that bison created for us
(uses the -d option of bison) */
#include <cassowary/ClReader.h>
#include "ClReader.cc.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
/* global variable for the istream we are reading from;
gets set by PcnParseConstraint */
istream *pxi_lexer;
/* Pass in an extra variable (ClParseData *) to cllex so that
it can look up variable names */
#define YY_DECL int cllex(YYSTYPE *lvalp, void *YYLEX_PARAM)
/* Make lexer reader from the global variable */
#define YY_INPUT(buf,result,max_size) \
do { if (pxi_lexer->get(buf[0]) && buf[0] > 0) result = 1; \
else result = YY_NULL; } while (0)
%}
%option noyywrap
DIGIT [0-9]
ALPHA [A-Za-z]
ALPHANUM [A-Za-z0-9]
ID_OK_PUNC [-_\[\]]
RO_ANNOTATION "?"
ID {ALPHA}({ALPHANUM}|{ID_OK_PUNC})*({RO_ANNOTATION})?
NUMID "{"{DIGIT}+"}"
ws [ \t\n]+
%%
{ws} /* skip whitespace */
\n|";" { return 0; }
">=" { return GEQ; }
">" { return GT; }
"<=" { return LEQ; }
"<" { return LT; }
"==" { return '='; }
"="|"-"|"+"|"*"|"/"|"("|")" { return yytext[0]; }
{DIGIT}+("."{DIGIT}*)? |
"."{DIGIT}+ { lvalp->num = strtod(yytext,0); return NUM; }
{ID} { /* Lookup the variable name */
ClParseData *pclpd = ((ClParseData *) YYLEX_PARAM);
int cch = strlen(yytext);
ClVariable *pclv = NULL;
bool fReadOnly = false;
if (yytext[cch-1] == '?') {
yytext[cch-1] = '\0';
fReadOnly = true;
}
const string str = string(yytext);
pclv = pclpd->_lookup_func(str);
if (!pclv->IsNil()) {
lvalp->pclv = pclv;
return fReadOnly?RO_VAR:VAR;
} else {
pxi_lexer = NULL;
yy_flush_buffer(YY_CURRENT_BUFFER);
throw ExCLParseErrorBadIdentifier(str);
return 0;
}
}
. { pxi_lexer = NULL; throw ExCLParseErrorMisc("Unrecognized character"); }

154
libs/cassowary/ClReader.y Normal file
View file

@ -0,0 +1,154 @@
/*
$Id$
Cassowary Incremental Constraint Solver
Original Smalltalk Implementation by Alan Borning
This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
http://www.cs.washington.edu/homes/gjb
(C) 1998, 1999 Greg J. Badros and Alan Borning
See ../LICENSE for legal details regarding this software
ClReader.y
Original implementation contributed by Steve Wolfman
Subsequently largely revised by Greg J. Badros
Supports parsing of read-only variables in constraints via "?" suffix
annotations on variables. If a variable is followed by "?" in any of
its occurrences in the constraint, that variable is deemed read-only
and entered into the constraint object as such. E.g.,
x = 2*y?
is a one-way constraint that sets x from y's value.
x = y + y?
and
x = y? + y
are identical one-way constraints with y read-only. One would prefer
to have it written like so:
x = y? + y?
but it need not be, and no warning or error is raised.
*/
%{
/* C Declarations */
#include <cassowary/Cl.h>
#include <string>
#include <map>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#ifdef USE_CRUMMY_LEXER
string current; /* Global to help in debugging/error messages */
#endif
/* Get yyparse, yylex to have an extra argument (type void *) */
#define YYPARSE_PARAM cl_parse_data
#define YYLEX_PARAM cl_parse_data
#ifndef YYERROR_VERBOSE
#define YYERROR_VERBOSE
#endif
#define YYDEBUG 1
%}
/* Bison Declarations */
%pure_parser
%union {
double num;
const ClVariable *pclv;
ClLinearExpression *pcle;
ClConstraint *pcn;
}
%{
int yylex(YYSTYPE *lvalp, void *YYLEX_PARAM);
void yyerror(const char *sz);
%}
%start constraint
%token <num> NUM
%token <pclv> VAR
%token <pclv> RO_VAR
%token GEQ
%token GT
%token LEQ
%token LT
%type <pcle> expr
%type <pcn> constraint equation inequality
%left '-' '+'
%left '*' '/'
%left NEG
%%
/* Grammar Rules */
constraint: equation { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; }
| inequality { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; }
;
equation: expr '=' expr { $$ = new ClLinearEquation(*$1, *$3); }
;
inequality: expr GEQ expr { $$ = new ClLinearInequality(*$1, cnGEQ, *$3); }
| expr LEQ expr { $$ = new ClLinearInequality(*$1, cnLEQ, *$3); }
| expr LT expr { $$ = new ClLinearInequality(*$1, cnLT, *$3); }
| expr GT expr { $$ = new ClLinearInequality(*$1, cnGT, *$3); }
;
expr: NUM { $$ = new ClLinearExpression($1); }
| VAR { $$ = new ClLinearExpression(*$1); }
| RO_VAR { $$ = new ClLinearExpression(*$1);
((ClParseData*)YYPARSE_PARAM)->_readOnlyVarsSoFar.insert(*$1); }
| expr '+' expr { $$ = new ClLinearExpression(*$1 + *$3); }
| expr '-' expr { $$ = new ClLinearExpression(*$1 - *$3); }
| expr '*' expr { $$ = new ClLinearExpression(*$1 * *$3); }
| expr '/' expr { $$ = new ClLinearExpression(*$1 / *$3); }
| '-' expr %prec NEG { $$ = new ClLinearExpression(-1 * *$2); }
| '(' expr ')' { $$ = $2; }
;
%%
void clerror(const char *sz)
{
throw ExCLParseErrorMisc(sz);
}
extern istream *pxi_lexer;
// xi is the stream from which to read the constraint.
// aVars is an array of variables large enough to account for
// each one that might be mentioned in a constraint
ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func,
const ClStrength &strength)
{
ClParseData cl_parse_data(xi, lookup_func);
pxi_lexer = &xi;
if (yyparse(&cl_parse_data) == 0) { // success
#ifdef DEBUG_PARSER
cerr << *cl_parse_data.Pcn() << endl;
#endif
cl_parse_data.Pcn()->ChangeStrength(strength);
cl_parse_data.Pcn()->AddROVars(cl_parse_data._readOnlyVarsSoFar);
return cl_parse_data.Pcn();
}
else { // failed
return 0;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
// $Id$
#include <cassowary/ClSlackVariable.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#ifdef CL_FIND_LEAK
long ClSlackVariable::cSlackVariables = 0;
#endif

View file

@ -0,0 +1,59 @@
// $Id$
using namespace std;
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
#include <cassowary/Cassowary.h>
#include <cassowary/ClSolver.h>
#include <cassowary/ClConstraint.h>
#include <cassowary/ClErrors.h>
#include <cassowary/ClTypedefs.h>
ClSolver &
ClSolver::AddConstraint(ClConstraint *const )
{
return *this;
}
ostream &
PrintTo(ostream &xo, const ClConstraintSet &setCn)
{
ClConstraintSet::const_iterator it = setCn.begin();
for (; it != setCn.end(); ++it) {
const ClConstraint *pcn = *it;
xo << *pcn << endl;
}
return xo;
}
ostream &
PrintTo(ostream &xo, const list<FDNumber> &listFDN)
{
list<FDNumber>::const_iterator it = listFDN.begin();
for (; it != listFDN.end(); ) {
FDNumber n = *it;
xo << n;
++it;
if (it != listFDN.end())
xo << ",";
}
return xo;
}
ostream &operator<<(ostream &xo, const ClConstraintSet &setCn)
{ return PrintTo(xo,setCn); }
ostream &operator<<(ostream &xo, const ClSolver &solver)
{ return solver.PrintOn(xo); }
ostream &operator<<(ostream &xo, const list<FDNumber> &listFDN)
{ return PrintTo(xo,listFDN); }

View file

@ -0,0 +1,52 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClStrength.cc
#include <cassowary/ClStrength.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
// Use the singleton pattern for the strength objects
const ClStrength &ClsRequired()
{
// required is distinct by equality to this static object,
// but I still use an especially high symbolic weight, just in case
// FIXGJB: hack?
static ClStrength required_strength("<Required>", 1000, 1000, 1000);
return required_strength;
}
const ClStrength &ClsStrong()
{
static ClStrength strong_strength("strong", 1.0, 0.0, 0.0);
return strong_strength;
}
const ClStrength &ClsMedium()
{
static ClStrength medium_strength("medium", 0.0, 1.0, 0.0);
return medium_strength;
}
const ClStrength &ClsWeak()
{
static ClStrength weak_strength("weak", 0.0, 0.0, 1.0);
return weak_strength;
}
// special case for when nLevels = 3, should assert nLevels() == 3
ClStrength::ClStrength(const string &Name, double w1, double w2, double w3) :
_name(Name), _symbolicWeight(w1, w2, w3)
{
}

View file

@ -0,0 +1,149 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClSymbolicWeight.cc
#include <cassowary/Cassowary.h>
#include <cassowary/ClSymbolicWeight.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
// Help g++ out, tell it to instantiate this
//template vector<double> &vector<double>::operator =(const vector<double> &);
ClSymbolicWeight::ClSymbolicWeight(unsigned int CLevels, double value) :
_values(CLevels, value)
{
assert(_values.size() == CLevels);
}
ClSymbolicWeight::ClSymbolicWeight(double w1, double w2, double w3)
{
_values.push_back(w1);
_values.push_back(w2);
_values.push_back(w3);
assert(_values.size() == 3);
}
ClSymbolicWeight::ClSymbolicWeight(const vector<double> &weights) :
_values(weights)
{ }
ClSymbolicWeight &
ClSymbolicWeight::Zero()
{
static ClSymbolicWeight Zero(0.0, 0.0, 0.0);
return Zero;
}
ClSymbolicWeight &
ClSymbolicWeight::negated()
{
vector<double>::iterator it = _values.begin();
for (; it != _values.end(); ++it)
{
*it = -*it;
}
return *this;
}
ClSymbolicWeight &
ClSymbolicWeight::MultiplyMe(Number n)
{
vector<double>::iterator it = _values.begin();
for (; it != _values.end(); ++it)
{
*it *= n;
}
return *this;
}
ClSymbolicWeight
ClSymbolicWeight::DivideBy(Number n) const
{
assert(n!=0);
ClSymbolicWeight clsw(0);
vector<double>::const_iterator i = _values.begin();
for (; i != _values.end(); ++i)
{
clsw.push_back(*i / n);
}
return clsw;
}
ClSymbolicWeight &
ClSymbolicWeight::addtoMe(const ClSymbolicWeight &cl)
{
assert(cl.CLevels() == CLevels());
vector<double>::iterator i1 = _values.begin();
vector<double>::const_iterator i2 = cl._values.begin();
for (; i1 != _values.end(); ++i1, ++i2)
{
*i1 += *i2;
}
return *this;
}
ClSymbolicWeight
ClSymbolicWeight::Subtract(const ClSymbolicWeight &cl) const
{
assert(cl.CLevels() == CLevels());
ClSymbolicWeight clsw(0);
vector<double>::const_iterator i1 = _values.begin();
vector<double>::const_iterator i2 = cl._values.begin();
for (; i1 != _values.end(); ++i1, ++i2)
{
clsw.push_back(*i1 - *i2);
}
return clsw;
}
bool
ClSymbolicWeight::lessThan(const ClSymbolicWeight &cl) const
{
return _values < cl._values;
}
bool
ClSymbolicWeight::lessThanOrEqual(const ClSymbolicWeight &cl) const
{
return _values <= cl._values;
}
bool
ClSymbolicWeight::equal(const ClSymbolicWeight &cl) const
{
return _values == cl._values;
}
bool
ClSymbolicWeight::greaterThan(const ClSymbolicWeight &cl) const
{
return _values > cl._values;
}
bool
ClSymbolicWeight::greaterThanOrEqual(const ClSymbolicWeight &cl) const
{
return _values >= cl._values;
}
bool
ClSymbolicWeight::isNegative() const
{
return _values < Zero()._values;
}

297
libs/cassowary/ClTableau.cc Normal file
View file

@ -0,0 +1,297 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClTableau.cc
using namespace std;
#include <cassowary/ClTableau.h>
#include <cassowary/debug.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
// delete the linear expressions
// let ClSimplexSolver worry about deleting the variables
ClTableau::~ClTableau()
{
ClTableauRowsMap::iterator it = _rows.begin();
for (; it != _rows.end(); ++it)
{
// free the ClLinearExpression that we new-ed
#ifdef CL_TRACE
cerr << "Deleting row delete@ " << ((*it).second) << endl;
#endif
delete (*it).second;
}
}
#ifndef CL_NO_IO
// Some extra debugging info
ostream &
ClTableau::PrintInternalInfo(ostream &xo) const
{
xo << "ncns:" << _rows.size() -1
<< "; cols:" << _columns.size()
<< "; infrows:" << _infeasibleRows.size()
<< "; ebvars:" << _externalRows.size()
<< "; epvars:" << _externalParametricVars.size();
return xo;
}
ostream &
ClTableau::printExternalVariablesTo(ostream &xo) const
{
xo << "Parametric: ";
ClVarSet::iterator itParVars = _externalParametricVars.begin();
for ( ; itParVars != _externalParametricVars.end(); ++itParVars ) {
ClVariable v = *itParVars;
xo << v << " ";
}
xo << "\nBasic: ";
ClVarSet::iterator itRowVars = _externalRows.begin();
for ( ; itRowVars != _externalRows.end() ; ++itRowVars ) {
ClVariable v = *itRowVars;
xo << v << " ";
}
return xo << endl;
}
#endif
// Add v, update column cross indices
// v becomes a basic variable
// expr is now owned by ClTableau class,
// and ClTableauis responsible for deleting it
// (also, expr better be allocated on the heap!)
void
ClTableau::addRow(ClVariable var, const ClLinearExpression &expr)
{
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << var << ", " << expr << ")" << endl;
#endif
_rows[var] = const_cast<ClLinearExpression *>(&expr);
ClVarToNumberMap::const_iterator it = expr.Terms().begin();
// for each variable in expr, Add var to the set of rows which have that variable
// in their Expression
for (; it != expr.Terms().end(); ++it)
{
ClVariable v = (*it).first;
_columns[v].insert(var);
if (v.IsExternal() && !FIsBasicVar(v))
{
_externalParametricVars.insert(v);
}
}
if (var.IsExternal())
{
_externalRows.insert(var);
}
#ifdef CL_TRACE
cerr << *this << endl;
#endif
}
// Remove var from the tableau -- remove the column cross indices for var
// and remove var from every Expression in rows in which v occurs
// Remove the parametric variable var, updating the appropriate column and row entries.
// (Renamed from Smalltalk implementation's `removeParametricVar')
ClVariable
ClTableau::RemoveColumn(ClVariable var)
{
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << var << ")" << endl;
#endif
ClTableauColumnsMap::iterator it_var = _columns.find(var);
if (it_var == _columns.end())
return var; // nothing to do
ClVarSet &varset = (*it_var).second;
// remove the rows with the variables in varset
ClVarSet::iterator it = varset.begin();
for (; it != varset.end(); ++it)
{
ClVariable v = (*it);
ClVarToNumberMap &Terms = _rows[v]->Terms();
Terms.erase(Terms.find(var));
}
if (var.IsExternal())
{
_externalRows.erase(var);
_externalParametricVars.erase(var);
}
_columns.erase(it_var);
return var;
}
// Remove the basic variable v from the tableau row v=expr
// Then update column cross indices
ClLinearExpression *
ClTableau::RemoveRow(ClVariable var)
{
#ifdef CL_TRACE
Tracer TRACER(__FUNCTION__);
cerr << "(" << var << ")" << endl;
#endif
ClTableauRowsMap::iterator it = _rows.find(var);
assert(it != _rows.end());
ClLinearExpression *pexpr = (*it).second;
ClVarToNumberMap &Terms = pexpr->Terms();
ClVarToNumberMap::iterator it_term = Terms.begin();
for (; it_term != Terms.end(); ++it_term)
{
ClVariable v = (*it_term).first;
_columns[v].erase(var);
if (_columns[v].size() == 0)
{
_columns.erase(v);
_externalParametricVars.erase(v);
}
}
_infeasibleRows.erase(var);
if (var.IsExternal())
{
_externalRows.erase(var);
_externalParametricVars.erase(var);
}
_rows.erase(it);
#ifdef CL_TRACE
cerr << "- returning " << *pexpr << endl;
#endif
return pexpr;
}
// Replace all occurrences of oldVar with expr, and update column cross indices
// oldVar should now be a basic variable
// Uses the Columns data structure and calls SubstituteOut on each
// row that has oldVar in it
// oldVar is leaving the basis, and becoming parametric
void
ClTableau::SubstituteOut(ClVariable oldVar, const ClLinearExpression &expr)
{
#ifdef CL_TRACE
cerr << "* ClTableau::";
Tracer TRACER(__FUNCTION__);
cerr << "(" << oldVar << ", " << expr << ")" << endl;
cerr << (*this) << endl;
#endif
ClTableauColumnsMap::iterator it_oldVar = _columns.find(oldVar);
if (it_oldVar == _columns.end())
return;
ClVarSet &varset = (*it_oldVar).second;
ClVarSet::iterator it = varset.begin();
for (; it != varset.end(); ++it)
{
ClVariable v = (*it);
ClLinearExpression *prow = _rows[v];
prow->SubstituteOut(oldVar,expr,v,*this);
if (v.IsRestricted() && prow->Constant() < 0.0)
{
_infeasibleRows.insert(v);
}
}
_columns.erase(it_oldVar);
if (oldVar.IsExternal())
{
if (_columns[oldVar].size() > 0)
{
_externalRows.insert(oldVar);
}
_externalParametricVars.erase(oldVar);
}
}
#ifndef CL_NO_IO
ostream &
PrintTo(ostream &xo, const ClVarSet & varset)
{
ClVarSet::const_iterator it = varset.begin();
xo << "{ ";
if (it != varset.end())
{
xo << *it;
++it;
}
for (; it != varset.end(); ++it)
{
xo << ", " << *it;
}
xo << " }";
return xo;
}
ostream &operator<<(ostream &xo, const ClVarSet & varset)
{ return PrintTo(xo,varset); }
ostream &
PrintTo(ostream &xo, const ClTableauColumnsMap & varmap)
{
ClTableauColumnsMap::const_iterator it = varmap.begin();
for (; it != varmap.end(); ++it)
{
xo << (*it).first << " -> " << (*it).second << endl;
}
return xo;
}
ostream &operator<<(ostream &xo, const ClTableauColumnsMap & varmap)
{ return PrintTo(xo,varmap); }
ostream &
PrintTo(ostream &xo, const ClTableauRowsMap & rows)
{
ClTableauRowsMap::const_iterator it = rows.begin();
for (; it != rows.end(); ++it)
{
ClVariable v = it->first;
const ClLinearExpression *pe = it->second;
xo << v << " <-=-> ";
if (pe) xo << *pe; else xo << "NilExpr";
xo << endl;
}
return xo;
}
ostream &operator<<(ostream &xo, const ClTableauRowsMap & rows)
{ return PrintTo(xo,rows); }
ostream &
ClTableau::PrintOn(ostream &xo) const
{
xo << "Tableau:\n"
<< _rows << endl;
xo << "Columns:\n"
<< _columns << endl;
xo << "Infeasible rows: "
<< _infeasibleRows << endl;
xo << "External basic variables: "
<< _externalRows << endl;
xo << "External parametric variables: "
<< _externalParametricVars << endl;
return xo;
}
ostream &operator<<(ostream &xo, const ClTableau &clt)
{ return clt.PrintOn(xo); }
#endif

884
libs/cassowary/ClTests.cc Normal file
View file

@ -0,0 +1,884 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClTests.cc
#include <cassowary/Cl.h>
#include <stdlib.h>
#include <cassowary/timer.h>
#include <iostream>
#include <iomanip>
inline
double UniformRandom()
{ return double(rand())/RAND_MAX; }
bool
simple1()
{
try
{
bool fOkResult = true;
ClVariable x(167);
ClVariable y(2);
ClSimplexSolver solver;
ClLinearEquation eq(x,y+0.0);
solver.AddStay(x);
solver.AddStay(y);
solver.AddConstraint(eq);
cout << "x = " << x.Value() << endl
<< "y = " << y.Value() << endl;
fOkResult = (x.Value() == y.Value());
return fOkResult;
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
/* Add an edit variable to an empty solver */
bool
simple2()
{
try
{
ClVariable x(167);
ClSimplexSolver solver;
solver.AddEditVar(x);
solver.BeginEdit();
solver.SuggestValue(x,100);
solver.EndEdit();
cout << "x = " << x.Value() << endl;
}
catch (ExCLEditMisuse &error)
{
cout << "Success: got the exception" << endl;
return true;
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
cerr << "Should have gotten an exception!" << endl;
return false;
}
bool
justStay1()
{
try
{
bool fOkResult = true;
ClVariable x(5);
ClVariable y(10);
ClSimplexSolver solver;
#if 0
solver.AddPointStay(x,y,1);
#else
solver.AddStay(x);
solver.AddStay(y);
#endif
fOkResult = fOkResult && ClApprox(x,5);
fOkResult = fOkResult && ClApprox(y,10);
cout << "x == " << x.Value() << endl;
cout << "y == " << y.Value() << endl;
return(fOkResult);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
addDelete1()
{
try
{
bool fOkResult = true;
ClVariable x("x");
ClSimplexSolver solver;
solver.AddConstraint(new ClLinearEquation( x, 100, ClsWeak() ));
ClLinearInequality c10(x,cnLEQ,10.0);
ClLinearInequality c20(x,cnLEQ,20.0);
solver
.AddConstraint(c10)
.AddConstraint(c20);
fOkResult = fOkResult && ClApprox(x,10.0);
cout << "x == " << x.Value() << endl;
cout << endl << solver << endl;
solver.RemoveConstraint(c10);
cout << endl << solver << endl;
fOkResult = fOkResult && ClApprox(x,20.0);
cout << "x == " << x.Value() << endl;
solver.RemoveConstraint(c20);
fOkResult = fOkResult && ClApprox(x,100.0);
cout << "x == " << x.Value() << endl;
ClLinearInequality c10again(x,cnLEQ,10.0);
solver
.AddConstraint(c10)
.AddConstraint(c10again);
fOkResult = fOkResult && ClApprox(x,10.0);
cout << "x == " << x.Value() << endl;
solver.RemoveConstraint(c10);
fOkResult = fOkResult && ClApprox(x,10.0);
cout << "x == " << x.Value() << endl;
solver.RemoveConstraint(c10again);
fOkResult = fOkResult && ClApprox(x,100.0);
cout << "x == " << x.Value() << endl;
return(fOkResult);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
addDelete2()
{
try
{
bool fOkResult = true;
ClVariable x("x");
ClVariable y("y");
ClSimplexSolver solver;
solver
.AddConstraint(new ClLinearEquation(x, 100.0, ClsWeak()))
.AddConstraint(new ClLinearEquation(y, 120.0, ClsStrong()));
ClLinearInequality c10(x,cnLEQ,10.0);
ClLinearInequality c20(x,cnLEQ,20.0);
solver
.AddConstraint(c10)
.AddConstraint(c20);
fOkResult = fOkResult && ClApprox(x,10.0) && ClApprox(y,120.0);
cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
solver.RemoveConstraint(c10);
fOkResult = fOkResult && ClApprox(x,20.0) && ClApprox(y,120.0);
cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
ClLinearEquation cxy( 2*x, y);
solver.AddConstraint(cxy);
fOkResult = fOkResult && ClApprox(x,20.0) && ClApprox(y,40.0);
cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
solver.RemoveConstraint(c20);
fOkResult = fOkResult && ClApprox(x,60.0) && ClApprox(y,120.0);
cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
solver.RemoveConstraint(cxy);
fOkResult = fOkResult && ClApprox(x,100.0) && ClApprox(y,120.0);
cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
return(fOkResult);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
casso1()
{
try
{
bool fOkResult = true;
ClVariable x("x");
ClVariable y("y");
ClSimplexSolver solver;
solver
.AddConstraint(new ClLinearInequality(x,cnLEQ,y))
.AddConstraint(new ClLinearEquation(y, x+3.0))
.AddConstraint(new ClLinearEquation(x,10.0,ClsWeak()))
.AddConstraint(new ClLinearEquation(y,10.0,ClsWeak()))
;
fOkResult = fOkResult &&
( ClApprox(x,10.0) && ClApprox(y,13.0) ||
ClApprox(x,7.0) && ClApprox(y,10.0) );
cout << "x == " << x.Value() << ", y == " << y.Value() << endl;
return(fOkResult);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
inconsistent1()
{
ClSimplexSolver solver;
ClVariable x("x");
ClLinearEquation eq1(x,10.0);
ClLinearEquation eq2(x,5.0);
try
{
solver.AddConstraint( eq1 );
solver.AddConstraint( eq2 );
// no exception, we failed!
return(false);
}
catch (ExCLRequiredFailure)
{
// we want this exception to get thrown
cout << "Success -- got the exception" << endl;
// solver.RemoveConstraint(eq2); this would throw a constraint not found exception
// cout << solver << endl;
return(true);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
inconsistent2()
{
try
{
ClVariable x("x");
ClSimplexSolver solver;
solver
.AddConstraint(new ClLinearInequality(x,cnGEQ,10.0))
.AddConstraint(new ClLinearInequality(x,cnLEQ, 5.0));
// no exception, we failed!
return(false);
}
catch (ExCLRequiredFailure &)
{
// we want this exception to get thrown
cout << "Success -- got the exception" << endl;
// cout << solver << endl;
return(true);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
inconsistent3()
{
try
{
ClVariable w("w");
ClVariable x("x");
ClVariable y("y");
ClVariable z("z");
ClSimplexSolver solver;
solver
.AddConstraint(new ClLinearInequality(w,cnGEQ,10.0))
.AddConstraint(new ClLinearInequality(x,cnGEQ,w))
.AddConstraint(new ClLinearInequality(y,cnGEQ,x))
.AddConstraint(new ClLinearInequality(z,cnGEQ,y))
.AddConstraint(new ClLinearInequality(z,cnLEQ,4.0));
// no exception, we failed!
return(false);
}
catch (ExCLRequiredFailure &)
{
// we want this exception to get thrown
cout << "Success -- got the exception" << endl;
// cout << solver << endl;
return(true);
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
bool
multiedit()
{
try
{
bool fOkResult = true;
ClVariable x("x",0);
ClVariable y("y",0);
ClVariable w("w",0);
ClVariable h("h",0);
ClSimplexSolver solver;
solver
.AddStay(x)
.AddStay(y)
.AddStay(w)
.AddStay(h);
solver
.AddEditVar(x)
.AddEditVar(y)
.BeginEdit();
solver
.SuggestValue(x,10)
.SuggestValue(y,20)
.Resolve();
cout << "x = " << x.Value() << "; y = " << y.Value() << endl
<< "w = " << w.Value() << "; h = " << h.Value() << endl;
fOkResult = fOkResult &&
ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,0) && ClApprox(h,0);
solver
.AddEditVar(w)
.AddEditVar(h)
.BeginEdit();
solver
.SuggestValue(w,30)
.SuggestValue(h,40)
.EndEdit();
cout << "x = " << x.Value() << "; y = " << y.Value() << endl
<< "w = " << w.Value() << "; h = " << h.Value() << endl;
fOkResult = fOkResult &&
ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,30) && ClApprox(h,40);
solver
.SuggestValue(x,50)
.SuggestValue(y,60)
.EndEdit();
cout << "x = " << x.Value() << "; y = " << y.Value() << endl
<< "w = " << w.Value() << "; h = " << h.Value() << endl;
fOkResult = fOkResult &&
ClApprox(x,50) && ClApprox(y,60) && ClApprox(w,30) && ClApprox(h,40);
return fOkResult;
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
cerr << "Should have gotten an exception!" << endl;
return false;
}
bool
multiedit2()
{
try
{
bool fOkResult = true;
ClVariable x("x",0);
ClVariable y("y",0);
ClVariable w("w",0);
ClVariable h("h",0);
ClSimplexSolver solver;
solver
.AddStay(x)
.AddStay(y)
.AddStay(w)
.AddStay(h);
solver
.AddEditVar(x)
.AddEditVar(y)
.BeginEdit();
solver
.SuggestValue(x,10)
.SuggestValue(y,20)
.Resolve();
cout << "x = " << x.Value() << "; y = " << y.Value() << endl
<< "w = " << w.Value() << "; h = " << h.Value() << endl;
fOkResult = fOkResult &&
ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,0) && ClApprox(h,0);
solver
.AddEditVar(x)
.AddEditVar(y)
.AddEditVar(w)
.AddEditVar(h)
.BeginEdit();
solver
.SuggestValue(w,30)
.SuggestValue(h,40)
.EndEdit();
cout << "x = " << x.Value() << "; y = " << y.Value() << endl
<< "w = " << w.Value() << "; h = " << h.Value() << endl;
fOkResult = fOkResult &&
ClApprox(x,10) && ClApprox(y,20) && ClApprox(w,30) && ClApprox(h,40);
solver
.SuggestValue(x,50)
.SuggestValue(y,60)
.EndEdit();
cout << "x = " << x.Value() << "; y = " << y.Value() << endl
<< "w = " << w.Value() << "; h = " << h.Value() << endl;
fOkResult = fOkResult &&
ClApprox(x,50) && ClApprox(y,60) && ClApprox(w,30) && ClApprox(h,40);
return fOkResult;
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(false);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
cerr << "Should have gotten an exception!" << endl;
return false;
}
// From a bug report from Steve Wolfman on his
// SAT project using "blackbox"
bool
blackboxsat()
{
try
{
ClSimplexSolver solver;
ClVariable r1("r1");
ClVariable r2("r2");
ClVariable r3("r3");
ClVariable r4("r4");
ClVariable r5("r5");
ClVariable r6("r6");
ClVariable r7("r7");
ClVariable r8("r8");
ClConstraint *rgpcn[30];
for (int i=0; i<int(sizeof(rgpcn)/sizeof(rgpcn[0])); ++i)
rgpcn[i] = NULL;
rgpcn[1] = new ClLinearEquation(r1,60);
rgpcn[2] = new ClLinearEquation(r2,30);
rgpcn[12] = new ClLinearEquation(r3,2.5);
rgpcn[13] = new ClLinearEquation(r6,0);
rgpcn[14] = new ClLinearInequality(r5, cnGEQ, 0);
rgpcn[15] = new ClLinearInequality(r8, cnLEQ, 2.5);
rgpcn[16] = new ClLinearInequality(r7, cnGEQ, r6);
rgpcn[17] = new ClLinearInequality(r8, cnGEQ, r7);
rgpcn[18] = new ClLinearEquation(r4, r3 - r2/60.0);
rgpcn[19] = new ClLinearEquation(r5, r4 - r1/60.0);
rgpcn[20] = new ClLinearInequality(r4, cnGEQ, 0);
rgpcn[21] = new ClLinearInequality(r5, cnGEQ, 0);
rgpcn[22] = new ClLinearEquation(r7, r6 + r2/20.0);
rgpcn[23] = new ClLinearEquation(r8, r7 + r1/20.0);
rgpcn[24] = new ClLinearEquation(r4, r3 - r2/30.0);
rgpcn[25] = new ClLinearEquation(r5, r4 - r1/30.0);
rgpcn[26] = new ClLinearInequality(r4, cnGEQ, 0);
rgpcn[27] = new ClLinearInequality(r5, cnGEQ, 0);
rgpcn[28] = new ClLinearEquation(r7, r6 + r2/60.0);
rgpcn[29] = new ClLinearEquation(r8, r7 + r1/60.0);
while (true)
{
char szCmd[1000];
int i;
cin >> szCmd;
if (!cin)
break;
if (szCmd[0] == '#')
{
cin.getline(szCmd,900);
continue;
}
if (strcasecmp(szCmd,"Add") == 0)
{
cin >> i;
cout << "eq" << i << ": " << solver.AddConstraintNoException(rgpcn[i])
<< "\t" << *(rgpcn[i]) << endl;
cout << r1 << " = " << r1.Value() << endl;
}
else if (strcasecmp(szCmd,"del") == 0)
{
cin >> i;
cout << "REMeq" << i << ": " << solver.RemoveConstraintNoException(rgpcn[i])
<< "\t" << *(rgpcn[i]) << endl;
cout << r1 << " = " << r1.Value() << endl;
}
else if (strcasecmp(szCmd,"dump") == 0)
{
cout << solver << endl;
}
else if (strcasecmp(szCmd,"val") == 0)
{
cout << r1 << " = " << r1.Value() << endl;
}
else if (strcasecmp(szCmd,"solve") == 0)
{
cout << solver.Solve() << endl;
}
else if (strcasecmp(szCmd,"autosolve") == 0)
{
solver.SetAutosolve(true);
}
else if (strcasecmp(szCmd,"noautosolve") == 0)
{
solver.SetAutosolve(true);
}
}
cout << r1 << " = " << r1.Value() << endl
<< r2 << " = " << r2.Value() << endl
<< r3 << " = " << r3.Value() << endl
<< r4 << " = " << r4.Value() << endl
<< r5 << " = " << r5.Value() << endl
<< r6 << " = " << r6.Value() << endl
<< r7 << " = " << r7.Value() << endl
<< r8 << " = " << r8.Value() << endl;
return false;
}
catch (ExCLError &error)
{
cerr << "Exception! " << error.description() << endl;
return(true);
}
catch (...)
{
cerr << "Unknown exception" << endl;
return(false);
}
}
typedef ClVariable *PClVariable;
bool
addDel(const int nCns = 900, const int nVars = 900, const int nResolves = 10000)
//addDel(int nCns = 300, int nVars = 300, int nResolves = 1000)
//addDel(int nCns = 30, int nVars = 30, int nResolves = 100)
{
Timer timer;
// FIXGJB: from where did .12 come?
static const double ineqProb = 0.12;
static const int maxVars = 3;
cout << "starting timing test. nCns = " << nCns
<< ", nVars = " << nVars << ", nResolves = " << nResolves << endl;
timer.Start();
ClSimplexSolver solver;
solver.SetAutosolve(false);
ClVariable **rgpclv = new PClVariable[nVars];
for (int i = 0; i < nVars; i++)
{
rgpclv[i] = new ClVariable(i,"x");
solver.AddStay(*rgpclv[i]);
}
ClConstraint **rgpcns = new PClConstraint[nCns];
int nvs = 0;
int k;
int j;
double coeff;
for (j = 0; j < nCns; j++)
{
// number of variables in this constraint
nvs = int(UniformRandom()*maxVars) + 1;
ClLinearExpression expr = UniformRandom()*20.0 - 10.0;
for (k = 0; k < nvs; k++)
{
coeff = UniformRandom()*10 - 5;
expr.AddExpression(*(rgpclv[int(UniformRandom()*nVars)]) * coeff);
}
if (UniformRandom() < ineqProb)
{
rgpcns[j] = new ClLinearInequality(expr);
}
else
{
rgpcns[j] = new ClLinearEquation(expr);
}
#ifdef CL_SHOW_CNS_IN_BENCHMARK
cout << "Cn[" << j << "]: " << *rgpcns[j] << endl;
#endif
}
cout << "done building data structures" << endl;
cout << "time = " << timer.ElapsedTime() << "\n" << endl;
timer.Start();
int cExceptions = 0;
#ifdef CL_SHOW_CNS_IN_BENCHMARK
cout << "Exceptions on: ";
#endif
for (j = 0; j < nCns; j++)
{
// Add the constraint -- if it's incompatible, just ignore it
try
{
solver.AddConstraint(rgpcns[j]);
}
catch (ExCLRequiredFailure &)
{
cExceptions++;
rgpcns[j] = NULL;
#ifdef CL_SHOW_CNS_IN_BENCHMARK
cout << j << " ";
#endif
}
}
#ifdef CL_SHOW_CNS_IN_BENCHMARK
cout << "\n" << endl;
#endif
solver.Solve();
cout << "done adding constraints [" << cExceptions << " exceptions]" << endl;
cout << "time = " << timer.ElapsedTime() << "\n" << endl;
cout << "time per cn = " << timer.ElapsedTime()/nCns << "\n" << endl;
cout << "time per actual cn = " << timer.ElapsedTime()/(nCns - cExceptions) << "\n" <<endl;
timer.Start();
int e1Index = int(UniformRandom()*nVars);
int e2Index = int(UniformRandom()*nVars);
ClVariable e1 = *(rgpclv[e1Index]);
ClVariable e2 = *(rgpclv[e2Index]);
solver
.AddEditVar(e1)
.AddEditVar(e2);
cout << "done creating edit constraints -- about to start resolves" << endl;
cout << "time = " << timer.ElapsedTime() << "\n" << endl;
timer.Start();
solver.BeginEdit();
// FIXGJB start = Timer.now();
for (int m = 0; m < nResolves; ++m)
{
solver
.SuggestValue(e1,e1->Value()*1.001)
.SuggestValue(e2,e2->Value()*1.001)
.Resolve();
}
solver.EndEdit();
// cout << "run time: " <<
cout << "done resolves -- now removing constraints" << endl;
cout << "time = " << timer.ElapsedTime() << "\n" <<endl;
cout << "time per Resolve = " << timer.ElapsedTime()/nResolves << "\n" <<endl;
timer.Start();
for (j = 0; j < nCns; j++)
{
if (rgpcns[j])
{
solver.RemoveConstraint(rgpcns[j]);
}
}
// FIXGJB end = Timer.now();
// cout << "Total remove time: "
// << "remove time per cn"
cout << "done removing constraints and addDel timing test" << endl;
cout << "time = " << timer.ElapsedTime() << "\n" <<endl;
cout << "time per cn = " << timer.ElapsedTime()/nCns << "\n" <<endl;
cout << "time per actual cn = " << timer.ElapsedTime()/(nCns - cExceptions) << "\n" <<endl;
for (int i = 0; i < nVars; i++)
{
delete rgpclv[i];
}
for (int j = 0; j < nCns; j++)
{
delete rgpcns[j];
}
return true;
}
int
main( int argc, char **argv )
{
try
{
bool fAllOkResult = true;
bool fResult;
// seed the random number generator for reproducible results
srand(123456789);
cout << "Cassowary version: " << szCassowaryVersion << endl;
#define RUN_TEST(x) \
cout << #x << ":" << endl; \
fResult = x(); fAllOkResult &= fResult; \
if (!fResult) cout << "Failed!" << endl;
RUN_TEST(simple1);
RUN_TEST(simple2);
RUN_TEST(justStay1);
RUN_TEST(addDelete1);
RUN_TEST(addDelete2);
RUN_TEST(casso1);
RUN_TEST(inconsistent1);
RUN_TEST(inconsistent2);
RUN_TEST(inconsistent3);
RUN_TEST(multiedit);
RUN_TEST(multiedit2);
// RUN_TEST(blackboxsat);
int cns = 90, vars = 90, resolves = 100;
if (argc > 1)
cns = atoi(argv[1]);
if (argc > 2)
vars = atoi(argv[2]);
if (argc > 3)
resolves = atoi(argv[3]);
if (cns > 0)
{
cout << "addDel" << ":" << endl;
fResult = addDel(cns,vars,resolves); fAllOkResult &= fResult;
if (!fResult) cout << "Failed!" << endl;
}
#undef RUN_TEST
#ifdef CL_FIND_LEAK
cout << "ClAbstractVariables: " << ClAbstractVariable::cAbstractVariables
<< "\nClDummyVariables: " << ClDummyVariable::cDummyVariables
<< "\nClSlackVariables: " << ClSlackVariable::cSlackVariables
<< endl;
#endif
return (fAllOkResult? 0 : 255);
}
catch (...)
{
cerr << "exception!" << endl;
}
}

View file

@ -0,0 +1,21 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClVariable.cc
#include <cassowary/ClVariable.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#define CONFIG_H_INCLUDED
#endif
StringToVarMap *ClVariable::pmapStrPclv = NULL;
ClVariable clvNil(static_cast<ClAbstractVariable*>(0));

26
libs/cassowary/IMPORTANT Normal file
View file

@ -0,0 +1,26 @@
Cassowary/C++ needs to be compiled using a modern C++ compiler.
At one time or another, it has compiled using:
o egcs-1.0.1, egcs-1.0.3, egcs-1.1b, gcc-2.8.1, gcc-2.95.2
o Visual C++ 5.0
Cassowary/Java was developed using Sun's JDK-1.1.3, ported to Linux
More recent versions should work fine, and it has been tested
with JDK-1.2pre2.
The included Makefiles depend upon features of GNU Make. See:
ftp://ftp.gnu.org/pub/gnu/
for a version that you can build.
To build the c++/qdemos/QuadDemo application, you'll need TrollTech's Qt
widget set for X11, available from:
http://www.troll.no/dl/qtfree-dl.html
See also the Scwm (Scheme Constraints Window Manager) web page for a use
of Cassowary in a substantial application:
http://scwm.mit.edu/scwm/

182
libs/cassowary/INSTALL Normal file
View file

@ -0,0 +1,182 @@
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.

18
libs/cassowary/LICENSE Normal file
View file

@ -0,0 +1,18 @@
Cassowary Constraint Solving Toolkit
Copyright (C) 1998-200 Greg J. Badros
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
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
See COPYING.LGPL

View file

@ -0,0 +1,32 @@
MAINTAINERCLEANFILES = autom4te.cache Makefile.in aclocal.m4 configure \
config.h.in stamp-h.in config.guess mkinstalldirs \
missing install-sh config.sub ltconfig \
ltmain.sh acinclude.m4 config.log config.status \
depcomp ClReader.cc ClReader.hh ClReader-lex.cc
EXTRA_DIST = ClReader.l ClReader.y
SUBDIRS = cassowary
noinst_LIBRARIES = libcassowary.a
libcassowary_a_SOURCES = \
ClAbstractVariable.cc \
ClConstraint.cc \
ClLinearExpression.cc \
ClSolver.cc \
ClSimplexSolver.cc \
ClStrength.cc \
ClSymbolicWeight.cc \
ClTableau.cc \
ClVariable.cc \
ClFloatVariable.cc \
ClSlackVariable.cc \
ClDummyVariable.cc \
ClReader-lex.cc
ClReader-lex.cc: ClReader.l cassowary/ClReader.h ClReader.cc
$(LEX) -Pcl -o$@ $<
ClReader.cc: ClReader.y cassowary/ClReader.h
$(YACC) -d -pcl --output-file $@ $<

229
libs/cassowary/NEWS Normal file
View file

@ -0,0 +1,229 @@
Cassowary NEWS -- history of user-visible changes. -*- text -*-
Cassowary Constraint Solving Toolkit was
Implemented by:
Greg J. Badros <gjb@cs.washington.edu> and
Alan Borning <borning@cs.washington.edu>
University of Washington
Computer Science and Engineering
Seattle, WA 98195-2350
with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
12-March-2000: Version 0.60 released.
* Changed license to LGPL!!!
* Added SetAutoResetStayConstants(), FIsAutoResetStayConstants(), make ResetStayConstants() public
29-Jan-2000: Version 0.55 released.
* Some bug fixes
* Added ClSimplexSolver::{ChangeStrength,ChangeStrengthAndWeight,ChangeWeight,
DisplayObjective,ExternalResetStayConstants} fns
From A. Beurivé.
16-Dec-1999: Version 0.54a released.
* Include correct version of OTI Smalltalk .dat file
(the source in the *.app files was right, the .dat file was old)
* Fix java build bug
15-Dec-1999: Version 0.54 released.
* Bug fixes
* auto-configuration improvements
* Support Java 2 (jdk-1.2)
* Improved ease of building Java demos
* Build guile wrapper as long as guile-config works, use new --disable-guile-build to force off
* Alpha-version of Java constraint parser contributed by Will Portnoy
24-October-1999: Version 0.53 released.
* Bug fixes
* License exception for linking with Scwm.
25-September-1999: Version 0.52 released.
* Bug fix for nested edits where a later edit includes an already-being-edited variable
14-September-1999: Version 0.51 released.
* Minor bug fixes
* Much better packaging, RPMs, etc. more forced reliance on GTL
26-August-1999: Version 0.51 pre-releases begin
12-July-1999: Version 0.50 released.
* Made only C++ version build by default, --enable-java-build is needed to turn java on
* Added restricted finite domain solver
** needs --with-gtl configure option, and libGTL.{a,so*} to be installed
* Added ClSolver base class, and use its type for pointers in callbacks
14-Apr-1999: Version 0.43 released.
* DEBUG_PARSE turned off by default
* Added cassowary.spec for RPM building
31-Mar-1999: Version 0.42 released.
* Fixed autoconf bugs (.41 was a buggy release)
* Added --disable-cpp-build,--disable-java-build, and disable Python/Guile builds
automatically if directories cannot be found
20-Mar-1999: Version 0.41 released.
* Fixed bug in autoconf support -- config.sub, config.guess to the
distribution so configure should actually work (they were symlinks
before, in error).
18-Mar-1999: Version 0.4 released.
18-Mar-1999: Changes since Cassowary v0.32 (for release v0.4)
* MUCH improved autoconf/automake support including numerous configure
options, added libtool support.
* Renamed many identifiers in the public API; this will break old code
using Cassowary. See the scripts/convert-ids script for help converting
your code (beware false positives; i.e., improper or unnecessary
changes).
10-Mar-1999: Changes since Cassowary v0.31 (for release v0.32)
* Added automake/autoconf support. Old Makefiles are now
Makefile.linux. This is not yet fully tested or correct, but I need to
make a release now for the bug fixes. Consider compiling with "make -f
Makefile.linux all" if you have problems running autoconf and/or
automake.
* Changes to C++
** Bug fix for problem Anthony Beurivé noticed regarding removing non-1
weight stay constraints.
** Minor bug fix for parser. Also renamed the creader files to ClReader.
* Changes to Java
** Bug fix for problem Emmanuel Pietriga reported regarding edit
constraints.
** Improved debugging support a bit by adding descriptions to
ExCLInternalError-s and assert()s
* Changes to guile wrapper
** changed name of library to libcassowaryguile.a from libconstraints.a
1-Mar-1999: Changes since Cassowary v0.3 (for release v0.31)
* Changes to C++
** Some bug fixes -- pass ClVariable-s around by value instead of const
& since they are now a handle class.
** Changed output format for ClEditConstraint, ClStayConstraint instances
** Use a function-object for controlling lookup/creation of variables in PcnParseConstraint
** Fix bugs in creader.y parser (did not accept parens or division
before). Introduced "==" as a a synonym for "="
** Added szCassowaryVersion id string as a public char *.
** Added ChangeStrength, ChangeWeight to ClConstraint's public
interface, and have it valid only when the constraint is not in a solver
** Added ClConstraint::FIsInSolver()
* Changes to Guile wrapper
** Fix bugs
** Wrap parsing functionality, including a lambda for lookup/creation of
variables
** Build a dynamically-loadable guile module, update cltests.scm to use it
23-Feb-1999: Version 0.3 released.
19-Feb-1999, Changes since Cassowary v0.23 (for release v0.3)
* Changes to Java and C++
** Bug fix for Michael Kaufmann's report (see ChangeLog for details)
** resolve(Vector..) procedure is now depracated; preferred interface is
suggestValue(...) calls followed by resolve() (the one taking no
arguments).
** Added ClVariable::SetVarMap(..), ClVariable::VarMap() to permit
ClVariable ctr to save the mapping between given name and actual object
in a symbol table (used for parsing ascii expressions in C++ version)
* Changes to just C++ implementation
** Use ClVariable as a handle class to a ClAbstractVariable-- old
ClVariable is now a ClFloatVariable. SetChangeClvCallback now takes a
function that takes a ClVariable handle, not a pointer.
** Passing ClConstraints's by const & is now deprecated -- pass by
pointer to the ClConstraint object
** Added creader.y, creader.l and function PcnParseConstraint(..) for
creating a constraint from an ASCII string.
** Added CL_NO_IO compile-time option to C++ version for preventing need
to link with the stream library (is not complete)
** Added CL_FIND_LEAK compile-time option for counting ctrs/dtr
invocations
** Added CL_USE_HASH_MAP compile-time option to permit using the GNU
hash_map class instead of the standard STL map (which is a sorted
associative container whose performance for lookups is logarithmic
rather than constant time). Still does not work for me --02/16/99 gjb.
* Changes to just Java implementation (updated to match changes to C++
version for .2)
** Added {get,set}AttachedObject for ClVariable, ClConstant
** Permit access to ClSimplexSolver.ConstraintMap()
** Permit nested beginEdit()s and handle them correctly
* Miscellaneous changes
** Updated copyright to include 1999
** Fixed wrappers/Makefile for building Python wrapper
** Reference Anthony Beurivé's STk wrapper
** Fix Scwm URL
30-Jan-1999, Changes since Cassowary v0.22 (for release v0.23)
* Bug fix (see ChangeLog for details)
23-Jan-1999, Changes since Cassowary v0.21 (for release v0.22)
* Minor code cleanup, additions of comments.
14-Sep-98, Changes since Cassowary v0.2 (for release v0.21)
* Make compile cleanly using egcs-1.1b -- use typename, and drop
unused templated instantiation
* Improved guile interface: add a void pointer to the solver objects,
and let the guile wrapper use it to keep a pointer to the scheme-level
object; also added clv-attach! and clv-attached-object for attaching
an object to a cl-variable (somewhat redundant with guile's
object properties)
* Wrap ClStayConstraints so they can be managed explicitly
* cl-add-stay, cl-add-editvar now take strength and factor arguments,
instead of a list of cl-vars
* Added weight option to addEditVar
6-Aug-98, Changes since Cassowary v0.1 (for release v0.2):
* Changes to the distribution for release v0.2
** added guile/scheme wrapper of C++ version
** mention SCWM in README
** mention non-maintenance of Smalltalk implementation unless we have users
* Changes to the C++ and Java implementations
** Fixed several bugs -- dummy variables were wrongly being pivoted into
the basis, and constraints that threw required failure exceptions
were mistakenly remaining in the tableau (now trying to remove an
exception that was not added because of a required-failure exception
will correctly throw a ConstraintNotFound exception); more -- see ChangeLog
** Added a virtual change_value function to permit applications to watch
for changes made to external variables.
* Changes to only the C++ version (Java version will catch up in 0.3)
** Added new test cases to ClTests, fixed bugs in ClTestColumns
** Added _pv (void *) field hanging off of ClConstraint and ClVariable
for associating arbitrary structs with those (needed by SCWM)
** Permit nested beginEdit()s, and do the right thing upon calling
endEdit() -- i.e., not all the edit variables are removed, only the
nested ones
** Permit access to ClSimplexSolver::ConstraintMap() (used by
guile-wrapper to efficiently get at a list of constraints in the
solver)
** Added ExCLEditMisuse exception

241
libs/cassowary/README Normal file
View file

@ -0,0 +1,241 @@
Cassowary Constraint Solving Toolkit for C++, Java, and Smalltalk
Version 0.60
Web Page: http://www.cs.washington.edu/research/constraints/cassowary
Contact: cassowary@cs.washington.edu
Greg J. Badros <gjb@cs.washington.edu> and
Alan Borning <borning@cs.washington.edu>
University of Washington
Computer Science and Engineering
Seattle, WA 98195-2350
12-March-2000
with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
See ANNOUNCE for a brief description and announcement of this distribution.
See NEWS for a history of user-visible changes.
See ChangeLog for a detailed listing of the changes to each source file.
See LICENSE for legalese regarding use of this distribution.
The Smalltalk implementation is in the public domain -- see smalltalk/README.
Please send bug reports to cassowary@cs.washington.edu
Also, send mail to cassowary@cs.washington.edu if you would like to be
informed about bug fixes, feature enhancements, etc. Let us know what
implementation(s) you are using, too.
------------------------------------------------------------------
HOW TO GET STARTED
The Cassowary library uses GNU autoconf to permit easy building on
various platforms. You should be able to do:
./configure
make
and everything will work. A more complex, but realistic example is:
./configure --with-prefix=/usr/contrib \
--with-guile-prefix=/usr/contrib \
--with-python-headers=/usr/include/python1.5 \
--enable-java-build \
--with-gtl=/usr/contrib \
--with-java-class-path=/usr/contrib/share/java/site \
--enable-warnings
make -k
Be sure to give the extra --enable-permissive flag to configure if
you are building with gcc-2.95 or more recent.
As yet another data point, I build Cassowary with:
./configure --with-guile-exec-prefix=/uns/bin \
--with-guile-prefix=/uns/share --prefix=/uns/share \
--exec-prefix=/uns --enable-maintainer-mode
See the file "INSTALL" for more details about
autoconf support and the options that the "configure" takes. You can
also do "./configure --help" for the list of the options that configure
accepts.
If the make in any of the subdirectories fails, you can turn on the "-k"
option to make, or just do make in the subdirectories that you want
build. E.g., if you do not have the JDK installed, the Java version of
Cassowary might not compile; if you still want the guile version, just
"cd guile; make -k".
Be sure that configure detects the validity of using the "-fpermissive"
flag of more recent g++/egcs compilers to work around some
const-discrepancies between the const-challenged guile header files and
Cassowary's more const-correct usage. You should get a message like:
checking whether gcc understands -fpermissive option... yes
when running configure if you're using, e.g., gcc-2.95 or later.
You need to apply GTL.h.patch to the installed GTL.h header file for
Cassowary to compile with recent versions of egcs/gcc (e.g., gcc-2.95).
Also, you may need to change libguile/gsubr.h from:
extern SCM scm_make_gsubr SCM_P ((char *name, int req, int opt,
int rst, SCM (*fcn)()));
to
extern SCM scm_make_gsubr SCM_P ((char *name, int req, int opt,
int rst, void*));
or patch guile's snarf.h to insert the appropriate case at each call to
SCM_PROC and SCM_PROC1. (Thanks to Alexandre Duret-Lutz for the above
information about more recent g++/egcs compilers).
Note that the generated Makefiles depend upon features of GNU Make. See:
ftp://ftp.gnu.org/pub/gnu/
for a version of make that you can build first to then build Cassowary.
Example applications exist in subdirectories of the top-level
implementation subdirectories (e.g., c++/qdemos contains demos for C++
that use the Qt Widget toolkit).
Please send mail to cassowary@cs.washington.edu if you are using this
toolkit so we know how to reach you for bug fixes, updates, etc.
------------------------------------------------------------------
WHAT THE DISTRIBUTION CONTAINS
This distribution contains 3 implementations of the Cassowary constraint
solving toolkit:
o C++
o Java
o Smalltalk
For each implementation language, there is at least one example program;
for some there are many.
There is a wrapping of the C++ solver in Guile-Scheme -- see the guile/
subdirectory. Also, Anthony Beurivé has wrapped Cassowary for
STk/Scheme. His code is available at:
http://dept-info.labri.u-bordeaux.fr/~beurive/Code
and the STk Scheme system is available at:
http://kaolin.unice.fr/STk/
There is also a SWIG-generated wrapper of the C++ library making the
solver available from the Python language.
A technical report describing the solver, its interface, and its
implementation is in cassowary-tr.ps (pdf version in cassowary-tr.pdf).
This paper is required reading if you intend to use the solver in your
own project(s).
See also the Scwm (Scheme Constraints Window Manager) web page:
http://scwm.mit.edu/scwm/
Scwm, also by Greg Badros (and Maciej Stachowiak), is the most
substantial application using this toolkit that we are aware of.
------------------------------------------------------------------
VARIOUS IMPLEMENTATION NOTES
Cassowary/C++ needs to be compiled using a modern C++ compiler.
At one time or another, it has compiled using:
o egcs-1.0.1
o egcs-1.0.3a
o egcs-1.1b
o egcs-1.1.1
o gcc-2.8.1 (needs libstdc++-2.8.x, too)
o Visual C++ 5.0 (not tried recently)
In particular, Cassowary will *not* build with gcc-2.7.x.x!
See c++/README for more details about building the C++ version.
The C++ implementation of the toolkit also has an optional finite domain
subsolver. You need to build and install the GTL -- the Graph Template
Library -- and use the "--with-gtl=DIR" configure option for the finite
domain subsolver to be built. GTL is available from:
http://www.fmi.uni-passau.de/Graphlet/GTL/
Cassowary was tested against GTL-0.3.1; it may work with later
versions, but I have not tried it. You need to apply GTL.h.patch to
the installed GTL.h header file for Cassowary to compile with recent
versions of egcs/gcc (e.g., gcc-2.95).
Cassowary/Java was developed using Sun's JDK-1.1.x, ported to Linux
More recent versions should work fine.
See java/README for more details about building the Java version.
Cassowary/Smalltalk was written under OTI Smalltalk-- other versions of
smalltalk will likely require (possibly significant) changes.
See smalltalk/README for more details about the Smalltalk version.
See guile/README for details about the Guile Scheme wrapper of the C++
implementation, and for a pointer to SCWM, the Scheme Constraints Window
Manager which uses Cassowary.
The Python bindings (by Tessa Lau) bindings for the Cassowary library
are in the wrappers/ subdirectory. SWIG was used in wrapping the
library. These bindings may no longer work, and are provided only for
your hacking pleasure (please send back useful patches if you do get the
code working).
For more information about SWIG, see:
http://www.swig.org/
For more information about the Python language, see:
http://www.python.org/
For more information about the Guile-Scheme language, see:
http://www.red-bean.com/guile/
http://www.fsf.org/software/guile/guile.html
------------------------------------------------------------------
DEMONSTRATION APPLICATION
A standard demonstration application is included for each implementation
of the Cassowary solver. The application builds a quadrilateral and
connects the neighboring midpoints of each of the outer edges to form an
interior quadrilateral which is provably a parallelogram. The
constraint solver manages the constraints to keep the outer
quadrilateral inside the window, keep the midpoints properly positioned,
and keep the outer quadrilateral from turning "inside out."
The user is able to select points (draggable boxes) and move them around
within the window (both midpoints and endpoints can be selected, of
course). The solver updates the figure, and redraws.
------------------------------------------------------------------
FUNDING ACKNOWLEDGEMENTS
This work has been funded in part by the National Science Foundation under
Grants IRI-9302249 and CCR-9402551, by Object Technology International, and
by a Fulbright Award from the Australian-American Educational
Foundation.
Additionally, Greg Badros is supported by a National Science Foundation
Graduate Research Fellowship. Parts of this material are based upon
work supported under that fellowship.

30
libs/cassowary/THANKS Normal file
View file

@ -0,0 +1,30 @@
Cassowary Constraint Solving Toolkit was
Implemented by:
Greg J. Badros <gjb@cs.washington.edu> and
Alan Borning <borning@cs.washington.edu>
University of Washington
Computer Science and Engineering
Seattle, WA 98195-2350
with Constraint Drawing Applet (CDA) by Michael Noth <noth@cs.washington.edu>
Please send bug reports to cassowary@cs.washington.edu
Bug reports, helpful testing, and/or code from:
Spencer Allain
Anthony Beurivé
Robert Chassell
Alexandre 'Pollux' Duret-Lutz
Michael Kaufmann
Brian Grant
Pengling He
Tessa Lau
John MacPhail
Larry Melia
Michael Noth
Emmanuel Pietriga
Will Portnoy
Steve Wolfman

View file

@ -0,0 +1,4 @@
#!/bin/sh
aclocal $ACLOCAL_FLAGS && autoheader && automake --add-missing && autoconf

102
libs/cassowary/cassowary-config Executable file
View file

@ -0,0 +1,102 @@
#!/bin/sh
# Modified from gtk-config
# --09/07/99 gjb
# gotten from LDADD in c++/Makefile.am
cassowary_gtllibs=""
cassowary_libs="-L/usr/local/lib $cassowary_gtllibs"
cassowary_cflags="-I/usr/local/include "
prefix=/usr/local
exec_prefix=${prefix}
exec_prefix_set=no
usage()
{
cat <<EOF
Usage: cassowary-config [OPTIONS]
Options:
[--prefix[=DIR]]
[--exec-prefix[=DIR]]
[--version]
[--libs]
[--gtllibs]
[--cflags]
EOF
exit $1
}
if test $# -eq 0; then
usage 1 1>&2
fi
while test $# -gt 0; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case $1 in
--prefix=*)
prefix=$optarg
if test $exec_prefix_set = no ; then
exec_prefix=$optarg
fi
;;
--prefix)
echo_prefix=yes
;;
--exec-prefix=*)
exec_prefix=$optarg
exec_prefix_set=yes
;;
--exec-prefix)
echo_exec_prefix=yes
;;
--version)
echo 0.60
;;
--cflags)
echo_cflags=yes
;;
--libs)
echo_libs=yes
;;
--gtllibs)
echo_gtllibs=yes
;;
*)
usage 1 1>&2
;;
esac
shift
done
if test "$echo_prefix" = "yes"; then
echo $prefix
fi
if test "$echo_exec_prefix" = "yes"; then
echo $exec_prefix
fi
if test "$echo_cflags" = "yes"; then
if test ${prefix}/include != /usr/include ; then
includes=-I${prefix}/include
for i in $cassowary_cflags ; do
if test $i = -I${prefix}/include ; then
includes=""
fi
done
fi
echo $includes $cassowary_cflags
fi
if test "$echo_libs" = "yes"; then
echo -L${exec_prefix}/lib -lcassowary -lstdc++ $cassowary_libs
fi
if test "$echo_gtllibs" = "yes"; then
echo $cassowary_gtllibs
fi

View file

@ -0,0 +1,102 @@
#!/bin/sh
# Modified from gtk-config
# --09/07/99 gjb
# gotten from LDADD in c++/Makefile.am
cassowary_gtllibs="@GTL_LIB@"
cassowary_libs="-L@prefix@/lib $cassowary_gtllibs"
cassowary_cflags="@GUILE_INCLUDES@ @GTL_INCLUDES@"
prefix=@prefix@
exec_prefix=@exec_prefix@
exec_prefix_set=no
usage()
{
cat <<EOF
Usage: cassowary-config [OPTIONS]
Options:
[--prefix[=DIR]]
[--exec-prefix[=DIR]]
[--version]
[--libs]
[--gtllibs]
[--cflags]
EOF
exit $1
}
if test $# -eq 0; then
usage 1 1>&2
fi
while test $# -gt 0; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case $1 in
--prefix=*)
prefix=$optarg
if test $exec_prefix_set = no ; then
exec_prefix=$optarg
fi
;;
--prefix)
echo_prefix=yes
;;
--exec-prefix=*)
exec_prefix=$optarg
exec_prefix_set=yes
;;
--exec-prefix)
echo_exec_prefix=yes
;;
--version)
echo @CASSOWARY_VERSION@
;;
--cflags)
echo_cflags=yes
;;
--libs)
echo_libs=yes
;;
--gtllibs)
echo_gtllibs=yes
;;
*)
usage 1 1>&2
;;
esac
shift
done
if test "$echo_prefix" = "yes"; then
echo $prefix
fi
if test "$echo_exec_prefix" = "yes"; then
echo $exec_prefix
fi
if test "$echo_cflags" = "yes"; then
if test @includedir@ != /usr/include ; then
includes=-I@includedir@
for i in $cassowary_cflags ; do
if test $i = -I@includedir@ ; then
includes=""
fi
done
fi
echo $includes $cassowary_cflags
fi
if test "$echo_libs" = "yes"; then
echo -L@libdir@ -lcassowary -lstdc++ $cassowary_libs
fi
if test "$echo_gtllibs" = "yes"; then
echo $cassowary_gtllibs
fi

View file

@ -0,0 +1,84 @@
# Note that this is NOT a relocatable package
%define ver 0.60
%define rel 2
%define prefix /usr
Name: cassowary-nofd
Summary: A Linear Arithmetic Constraint Solving Library.
Version: %ver
Release: %rel
# This source just has a different top-level directory name
Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-nofd-%ver.tar.gz
Group: Development/Libraries
BuildRoot: /tmp/cassowary-%ver-build
Copyright: Copyright (C) 1998,1999 Greg J. Badros
Packager: Greg J. Badros <gjb@cs.washington.edu>
URL: http://www.cs.washington.edu/research/constraints/cassowary
Requires: guile >= 1.3.2
Provides: cassowary-constraint-solver
%description
Cassowary is an advanced incremental constraint solving toolkit that
efficiently solves systems of linear equalities and inequalities.
Constraints may be either requirements or preferences. Client code
specifies the constraints to be maintained, and the solver updates the
constrained variables to have values that satisfy the constraints.
This package lacks the finite domain subsolver. The cassowary RPM
contains that solver as well, but also requires the GTL (Graph
Template Library) package.
%changelog
* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
- Added cassowary-nofd package to remove GTL dependence, added provides
virtual package "cassowary-constraint-solver" so that both this .spec
and cassowary.spec can provide it
* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
- Use -fpermissive if it is available, fix --enable-warnings
* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
- Rework spec file.
* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
- Initial release of this package.
%prep
%setup
%build
ln -sf . ./c++/cassowary
%ifarch alpha
./configure --host=alpha-linux --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
%else
./configure --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
%endif
make
%install
make prefix=$RPM_BUILD_ROOT%{prefix} install-strip
%clean
rm -rf $RPM_BUILD_ROOT
%post
%postun
%files
%defattr(-, root, root)
%{prefix}/bin/*
%{prefix}/lib/*
%{prefix}/include/*
%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
%doc guile/cassowary_scm.sgml

View file

@ -0,0 +1,84 @@
# Note that this is NOT a relocatable package
%define ver @VERSION@
%define rel 2
%define prefix /usr
Name: cassowary-nofd
Summary: A Linear Arithmetic Constraint Solving Library.
Version: %ver
Release: %rel
# This source just has a different top-level directory name
Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-nofd-%ver.tar.gz
Group: Development/Libraries
BuildRoot: /tmp/cassowary-%ver-build
Copyright: Copyright (C) 1998,1999 Greg J. Badros
Packager: Greg J. Badros <gjb@cs.washington.edu>
URL: http://www.cs.washington.edu/research/constraints/cassowary
Requires: guile >= 1.3.2
Provides: cassowary-constraint-solver
%description
Cassowary is an advanced incremental constraint solving toolkit that
efficiently solves systems of linear equalities and inequalities.
Constraints may be either requirements or preferences. Client code
specifies the constraints to be maintained, and the solver updates the
constrained variables to have values that satisfy the constraints.
This package lacks the finite domain subsolver. The cassowary RPM
contains that solver as well, but also requires the GTL (Graph
Template Library) package.
%changelog
* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
- Added cassowary-nofd package to remove GTL dependence, added provides
virtual package "cassowary-constraint-solver" so that both this .spec
and cassowary.spec can provide it
* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
- Use -fpermissive if it is available, fix --enable-warnings
* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
- Rework spec file.
* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
- Initial release of this package.
%prep
%setup
%build
ln -sf . ./c++/cassowary
%ifarch alpha
./configure --host=alpha-linux --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
%else
./configure --prefix=%prefix --enable-guile-build --enable-fsstd --enable-permissive
%endif
make
%install
make prefix=$RPM_BUILD_ROOT%{prefix} install-strip
%clean
rm -rf $RPM_BUILD_ROOT
%post
%postun
%files
%defattr(-, root, root)
%{prefix}/bin/*
%{prefix}/lib/*
%{prefix}/include/*
%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
%doc guile/cassowary_scm.sgml

View file

@ -0,0 +1,78 @@
# Note that this is NOT a relocatable package
%define ver 0.60
%define rel 1
%define prefix /usr
Name: cassowary
Summary: A Linear Arithmetic Constraint Solving Library.
Version: %ver
Release: %rel
Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-%ver.tar.gz
Group: Development/Libraries
BuildRoot: /tmp/cassowary-%ver-build
Copyright: Copyright (C) 1998,1999 Greg J. Badros
Packager: Greg J. Badros <gjb@cs.washington.edu>
URL: http://www.cs.washington.edu/research/constraints/cassowary
Requires: guile >= 1.3.4
Requires: GTL >= 0.3.1
Provides: cassowary-constraint-solver
%description
Cassowary is an advanced incremental constraint solving toolkit that
efficiently solves systems of linear equalities and inequalities.
Constraints may be either requirements or preferences. Client code
specifies the constraints to be maintained, and the solver updates the
constrained variables to have values that satisfy the constraints.
%changelog
* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
- added provides virtual package "cassowary-constraint-solver" so that
both this .spec and cassowary.spec can provide it
* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
- Use -fpermissive if it is available, fix --enable-warnings
* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
- Rework spec file.
* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
- Initial release of this package.
%prep
%setup
%build
ln -sf . ./c++/cassowary
%ifarch alpha
fake_root_for_install=$RPM_BUILD_ROOT ./configure --host=alpha-linux --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
%else
fake_root_for_install=$RPM_BUILD_ROOT ./configure --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
%endif
make
%install
make prefix=$RPM_BUILD_ROOT%{prefix} fake_root_for_install=$RPM_BUILD_ROOT install-strip
%clean
rm -rf $RPM_BUILD_ROOT
%post
%postun
%files
%defattr(-, root, root)
%{prefix}/bin/*
%{prefix}/lib/*
%{prefix}/include/*
%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
%doc guile/cassowary_scm.sgml

View file

@ -0,0 +1,78 @@
# Note that this is NOT a relocatable package
%define ver @VERSION@
%define rel 1
%define prefix /usr
Name: cassowary
Summary: A Linear Arithmetic Constraint Solving Library.
Version: %ver
Release: %rel
Source: http://www.cs.washington.edu/research/constraints/cassowary/cassowary-%ver.tar.gz
Group: Development/Libraries
BuildRoot: /tmp/cassowary-%ver-build
Copyright: Copyright (C) 1998,1999 Greg J. Badros
Packager: Greg J. Badros <gjb@cs.washington.edu>
URL: http://www.cs.washington.edu/research/constraints/cassowary
Requires: guile >= 1.3.4
Requires: GTL >= 0.3.1
Provides: cassowary-constraint-solver
%description
Cassowary is an advanced incremental constraint solving toolkit that
efficiently solves systems of linear equalities and inequalities.
Constraints may be either requirements or preferences. Client code
specifies the constraints to be maintained, and the solver updates the
constrained variables to have values that satisfy the constraints.
%changelog
* Tue Sep 7 1999 Greg J. Badros <gjb@cs.washington.edu)
- added provides virtual package "cassowary-constraint-solver" so that
both this .spec and cassowary.spec can provide it
* Sat Sep 4 1999 Greg J. Badros <gjb@cs.washington.edu)
- Use -fpermissive if it is available, fix --enable-warnings
* Wed Aug 25 1999 Greg J. Badros <gjb@cs.washington.edu>
- Rework spec file.
* Wed Apr 14 1999 Greg J. Badros <gjb@cs.washington.edu>
- Initial release of this package.
%prep
%setup
%build
ln -sf . ./c++/cassowary
%ifarch alpha
fake_root_for_install=$RPM_BUILD_ROOT ./configure --host=alpha-linux --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
%else
fake_root_for_install=$RPM_BUILD_ROOT ./configure --prefix=%prefix --with-gtl=%prefix --enable-fd-solver --enable-fsstd --enable-permissive
%endif
make
%install
make prefix=$RPM_BUILD_ROOT%{prefix} fake_root_for_install=$RPM_BUILD_ROOT install-strip
%clean
rm -rf $RPM_BUILD_ROOT
%post
%postun
%files
%defattr(-, root, root)
%{prefix}/bin/*
%{prefix}/lib/*
%{prefix}/include/*
%doc ANNOUNCE AUTHORS COPYING IMPORTANT INSTALL LICENSE NEWS README THANKS
%doc ChangeLog docs/cassowary-tr.pdf docs/cassowary-tr.ps.gz
%doc guile/cassowary_scm-procedures.txt guile/cassowary_scm-variables.txt
%doc guile/cassowary_scm.sgml

View file

@ -0,0 +1,2 @@
Makefile
Makefile.in

View file

@ -0,0 +1,40 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// Cassowary.h
#ifndef Cassowary_H
#define Cassowary_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#ifndef CL_PTR_HASH_DIVISOR
#define CL_PTR_HASH_DIVISOR 4
#endif
#include "ClConstraintHash.h"
#include <climits>
#include <string>
#include <cassert>
#include <iostream>
typedef double Number;
typedef long FDNumber;
enum { FDN_NOTSET = LONG_MIN };
#define NEWVAR(x) do { cerr << "line " << __LINE__ << ": new " << x << endl; } while (0)
#define DELVAR(x) do { cerr << "line " << __LINE__ << ": del " << x << endl; } while (0)
#endif // Cassowary_H

View file

@ -0,0 +1,49 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// Cl.h
// This is the top level include file for external clients
#ifndef CL_H
#define CL_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#ifdef CL_NO_IO
#undef CL_TRACE
#undef CL_SOLVER_STATS
#undef CL_DEBUG_FAILURES
#undef CL_TRACE_VERBOSE
#endif
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "cassowary/ClVariable.h"
#include "cassowary/ClSimplexSolver.h"
#include "cassowary/ClLinearEquation.h"
#include "cassowary/ClLinearInequality.h"
#include "cassowary/ClErrors.h"
#include "cassowary/ClEditConstraint.h"
#include "cassowary/ClStayConstraint.h"
#include "cassowary/ClReader.h"
#include "cassowary/ClConstraint.h"
#if defined(CL_HAVE_GTL) && defined(CL_BUILD_FD_SOLVER)
#include "cassowary/ClFDBinaryOneWayConstraint.h"
#include "cassowary/ClFDSolver.h"
#endif
extern const char *szCassowaryVersion;
#endif

View file

@ -0,0 +1,161 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClAbstractVariable.h
#ifndef ClAbstractVariable_H
#define ClAbstractVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <cstdio> /* for sprintf */
#include "Cassowary.h"
#include "ClErrors.h"
#include <memory>
#include <string>
#include <iostream>
#include "cl_auto_ptr.h"
using std::string;
using std::ostream;
class ClAbstractVariable {
public:
ClAbstractVariable(string Name = "") :
_name(Name), _pv(0)
{
++iVariableNumber;
#ifdef CL_FIND_LEAK
++cAbstractVariables;
#endif
if (Name.length() == 0)
{
char sz[16];
sprintf(sz,"v%ld",iVariableNumber);
_name = string(sz);
}
}
ClAbstractVariable(long varnumber, char *prefix) :
_pv(0)
{
cl_auto_ptr<char> pch (new char[16+strlen(prefix)]);
iVariableNumber++;
#ifdef CL_FIND_LEAK
++cAbstractVariables;
#endif
sprintf(pch.get(),"%s%ld",prefix,varnumber);
_name = string(pch.get());
}
virtual ~ClAbstractVariable()
#ifdef CL_FIND_LEAK
{ --cAbstractVariables; }
static long cAbstractVariables;
#else
{ }
#endif
// Return the Name of the variable
string Name() const
{ return _name; }
// Set the Name of the variable
virtual void SetName(string const &Name)
{ _name = Name; }
// Return true iff this variable is a ClFloatVariable
virtual bool IsFloatVariable() const
{ return false; }
// Return true iff this variable is a ClFDVariable
virtual bool IsFDVariable() const
{ return false; }
// Return true if this a dummy variable (used as a marker variable
// for required equality constraints). Such variables aren't
// allowed to enter the basis when pivoting.
virtual bool IsDummy() const
{ return false; }
// Return true if this a variable known outside the solver.
// (We need to give such variables a Value after solving is complete.)
virtual bool IsExternal() const
{ return false; }
// Return true if we can Pivot on this variable.
virtual bool IsPivotable() const
{ throw ExCLTooDifficultSpecial("Variable not usable inside SimplexSolver"); return false; }
// Return true if this is a restricted (or slack) variable. Such
// variables are constrained to be non-negative and occur only
// internally to the simplex solver.
virtual bool IsRestricted() const
{ throw ExCLTooDifficultSpecial("Variable not usable inside SimplexSolver"); return false; }
#ifndef CL_NO_IO
// Prints a semi-descriptive representation to the stream, using the
// Name if there is one, and otherwise the hash number of this
// object.
// EXAMPLES
// x[10.0] -- w/ Name
// x[0.0,100] -- w/ Name, bounds but no Value yet
// CV#345(10.0) -- w/o Name
virtual ostream &PrintOn(ostream &xo) const = 0;
friend ostream& operator<<(ostream &xos, const ClAbstractVariable &clv)
{ clv.PrintOn(xos); return xos; }
#endif // CL_NO_IO
friend bool operator<(const ClAbstractVariable &cl1, const ClAbstractVariable &cl2)
{ return &cl1 < &cl2; }
friend bool operator==(const ClAbstractVariable &cl1, const ClAbstractVariable &cl2)
{
return &cl1 == &cl2;
}
friend bool operator!=(const ClAbstractVariable &cl1, const ClAbstractVariable &cl2)
{
return !(cl1 == cl2);
}
virtual Number Value() const { return 0; }
virtual int IntValue() const { return 0; }
virtual void SetValue(Number)
{ assert(false); }
virtual void ChangeValue(Number)
{ assert(false); }
void SetPv(void *pv)
{ _pv = pv; }
void *Pv() const
{ return _pv; }
private:
string _name;
static long iVariableNumber;
// C-style extension mechanism so I
// don't have to wrap ScwmClVariables separately
void *_pv;
};
typedef ClAbstractVariable *PClAbstractVariable;
#endif

View file

@ -0,0 +1,198 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClConstraint.h
#ifndef ClConstraint_H
#define ClConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "debug.h"
#include "Cassowary.h"
#include "ClLinearExpression.h"
#include "ClStrength.h"
#include <string>
using std::string;
class ClSimplexSolver;
class ClFDSolver;
class ClBlueSolver;
// enum setup so additive inverse flips the direction of the inequality
enum ClCnRelation {cnEQ = 0, cnNEQ = 100, cnLEQ = 2, cnGEQ = -2, cnLT = 3, cnGT = -3 };
inline enum ClCnRelation
ReverseInequality(enum ClCnRelation c)
{
if (c != cnNEQ)
c = (enum ClCnRelation) (- int(c));
return c;
}
inline string
StrCnRelation(enum ClCnRelation rel) {
switch (rel) {
case cnEQ: return "=";
case cnNEQ: return "=/=";
case cnLEQ: return "<=";
case cnGEQ: return ">=";
case cnLT: return "<";
case cnGT: return ">";
default: assert(false);
}
}
class ClConstraint {
public:
ClConstraint(const ClStrength &strength = ClsRequired(), double weight = 1.0 ) :
_strength(strength),
_readOnlyVars(),
_weight(weight),
_pv(0),
_times_added(0)
{
CtrTracer(__FUNCTION__,this);
}
virtual ~ClConstraint()
{
DtrTracer(__FUNCTION__,this);
}
// Return my linear Expression. (For linear equations, this
// constraint represents Expression=0; for linear inequalities it
// represents Expression>=0.)
virtual ClLinearExpression Expression() const
{ assert(false); }
// Returns true if this is an edit constraint
virtual bool IsEditConstraint() const
{ return false; }
// Return true if this is an inequality constraint and
// false if it is an equality constraint. The default is
// that it is not.
virtual bool IsInequality() const
{ return false; }
virtual bool IsStrictInequality() const
{ return false; }
virtual bool IsRequired() const
{ return _strength.IsRequired(); }
virtual bool isStayConstraint() const
{ return false; }
virtual const ClStrength &strength() const
{ return _strength; }
virtual double weight() const
{ return _weight; }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const = 0;
friend ostream& operator<<(ostream &xos, const ClConstraint &constraint)
{ constraint.PrintOn(xos); return xos; }
#endif
void SetPv(void *pv)
{ _pv = pv; }
void *Pv() const
{ return _pv; }
virtual bool FIsSatisfied() const { return false; }
virtual bool FIsInSolver() const { return _times_added != 0; }
virtual bool FIsOkayForSimplexSolver() const { return true; }
void ChangeStrength( const ClStrength &strength)
{
if (_times_added == 0) {
setStrength(strength);
} else {
throw ExCLTooDifficult();
}
}
void ChangeWeight( double weight )
{
if (_times_added == 0) {
setWeight(weight);
} else {
throw ExCLTooDifficult();
}
}
bool FIsReadOnlyVar(ClVariable v) const {
return !(_readOnlyVars.find(v) == _readOnlyVars.end());
}
const ClVarSet &ReadOnlyVars() const {
return _readOnlyVars;
}
ClConstraint &AddROVars(const ClVarSet &setClv) {
for ( ClVarSet::const_iterator it = setClv.begin();
it != setClv.end(); ++it) {
_readOnlyVars.insert(*it);
}
return *this;
}
friend class ClSimplexSolver;
friend class ClFDSolver;
friend class ClBlueSolver;
private:
ClSymbolicWeight symbolicWeight() const {
return _strength.symbolicWeight();
}
void addedTo(const ClSimplexSolver &)
{ ++_times_added; }
void removedFrom(const ClSimplexSolver &)
{ --_times_added; }
void setStrength( const ClStrength &strength )
{ _strength = strength; }
void setWeight( double weight )
{ _weight = weight; }
/// instance variables
ClStrength _strength;
ClVarSet _readOnlyVars;
double _weight;
void *_pv;
int _times_added;
};
typedef ClConstraint* PClConstraint;
#endif

View file

@ -0,0 +1,39 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClHash.h
#ifndef CL_HASH_H__
#define CL_HASH_H__
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#ifdef CL_USE_HASH_MAP_AND_SET
#include <hash_map>
class ClConstraint;
struct hash<const ClConstraint *> {
size_t operator()(const ClConstraint * const p) const
{ return size_t((unsigned long)p/CL_PTR_HASH_DIVISOR); }
};
struct hash<ClConstraint *> {
size_t operator()(ClConstraint * const p) const
{ return size_t((unsigned long)p/CL_PTR_HASH_DIVISOR); }
};
#endif // CL_USE_HASH_MAP_AND_SET
#endif

View file

@ -0,0 +1,88 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClDummyVariable.h
#ifndef ClDummyVariable_H
#define ClDummyVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClAbstractVariable.h"
class ClTableau;
class ClSimplexSolver;
class ClDummyVariable : public ClAbstractVariable {
public:
#ifdef CL_FIND_LEAK
~ClDummyVariable() { --cDummyVariables; };
static long cDummyVariables;
#endif
protected:
friend class ClTableau;
friend class ClSimplexSolver;
ClDummyVariable(string Name = "") :
ClAbstractVariable(Name)
{
#ifdef CL_FIND_LEAK
++cDummyVariables;
#endif
}
ClDummyVariable(long number, char *prefix) :
ClAbstractVariable(number,prefix)
{
#ifdef CL_FIND_LEAK
++cDummyVariables;
#endif
}
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{
xo << "[" << Name() << ":dummy]";
return xo;
}
#endif
// Return true if this a dummy variable (used as a marker variable
// for required equality constraints). Such variables aren't
// allowed to enter the basis when pivoting.
virtual bool IsDummy() const
{ return true; }
// Return true if this a variable known outside the solver.
// (We need to give such variables a Value after solving is complete.)
virtual bool IsExternal() const
{ return false; }
// Return true if we can Pivot on this variable.
virtual bool IsPivotable() const
{ return false; }
// Return true if this is a restricted (or slack) variable. Such
// variables are constrained to be non-negative and occur only
// internally to the simplex solver.
virtual bool IsRestricted() const
{ return true; }
};
#endif

View file

@ -0,0 +1,45 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClEditConstraint.h
#ifndef ClEditConstraint_H
#define ClEditConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClEditOrStayConstraint.h"
class ClEditConstraint : public ClEditOrStayConstraint {
typedef ClEditOrStayConstraint super;
public:
ClEditConstraint(const ClVariable var,
const ClStrength &strength = ClsStrong(), double weight = 1.0 ) :
ClEditOrStayConstraint(var,strength,weight)
{ }
// Returns true if this is an edit constraint
virtual bool IsEditConstraint() const
{ return true; }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{ super::PrintOn(xo); return xo << "= edit)"; }
#endif
private:
};
#endif

View file

@ -0,0 +1,51 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClEditOrStayConstraint.h
#ifndef ClEditOrStayConstraint_H
#define ClEditOrStayConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "ClConstraint.h"
#include "ClLinearExpression.h"
class ClVariable;
class ClEditOrStayConstraint : public ClConstraint {
public:
ClEditOrStayConstraint(const ClVariable var,
const ClStrength &strength = ClsRequired(), double weight = 1.0 ) :
ClConstraint(strength,weight),
_variable(var)
{ }
const ClVariable variable() const
{ return _variable; }
ClLinearExpression Expression() const
{ return ClLinearExpression(_variable,-1,_variable.Value()); }
private:
void setVariable( const ClVariable v)
{ _variable = v; }
/// instance variables
ClVariable _variable;
};
#endif

View file

@ -0,0 +1,179 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClErrors.h
#ifndef ClErrors_H
#define ClErrors_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClTypedefs.h"
#include <string>
#include <exception>
using std::string;
using std::exception;
class ExCLError : public exception {
public:
ExCLError() : _msg(0) { }
virtual ~ExCLError() throw() {}
virtual string description() const
{ return "(ExCLError) An error has occured in CL"; }
protected:
char *_msg;
};
class ExCLInternalError : public ExCLError {
public:
ExCLInternalError(const char *sz)
{ _msg = strdup(sz); }
virtual string description() const
{
if (_msg) return _msg;
else return "(ExCLInternalError) An internal error has occurred";
}
};
class ExCLBadResolve : public ExCLError {
public:
ExCLBadResolve(const char *sz)
{ _msg = strdup(sz); }
virtual string description() const
{
if (_msg) return _msg;
else return "(ExCLBadResolve) Number of resolve values did not match number of edit vars";
}
};
class ExCLEditMisuse : public ExCLError {
public:
ExCLEditMisuse(const char *sz)
{ _msg = strdup(sz); }
virtual string description() const
{
if (_msg) return _msg;
return "(ExCLEditMisuse) Edit protocol usage violation";
}
};
class ExCLTooDifficult : public ExCLError {
public:
virtual string description() const
{ return "(ExCLTooDifficult) The constraints are too difficult to solve"; }
};
class ExCLTooDifficultSpecial : public ExCLTooDifficult {
public:
ExCLTooDifficultSpecial(const char *sz)
{ _msg = strdup(sz); }
virtual string description() const
{
if (_msg) return _msg;
else return "(ExCLTooDifficultSpecial) Solver requirements are not satisfied";
}
};
class ExCLReadOnlyNotAllowed : public ExCLTooDifficult {
public:
virtual string description() const
{ return "(ExCLReadOnlyNotAllowed) The read-only annotation is not permitted by the solver"; }
};
class ExCLCycleNotAllowed : public ExCLTooDifficult {
public:
virtual string description() const
{ return "(ExCLCycleNotAllowed) A cyclic constraint graph is not permitted by the solver"; }
};
class ExCLStrictInequalityNotAllowed : public ExCLTooDifficult {
public:
virtual string description() const
{ return "(ExCLStrictInequalityNotAllowed) The strict inequality is not permitted by the solver"; }
};
class ExCLRequiredFailure : public ExCLError {
public:
virtual ~ExCLRequiredFailure() throw() {}
virtual string description() const
{ return "(ExCLRequiredFailure) A required constraint cannot be satisfied"; }
};
class ExCLNotEnoughStays : public ExCLError {
public:
virtual string description() const
{ return "(ExCLNotEnoughStays) There are not enough stays to give specific values to every variable"; }
};
class ExCLNonlinearExpression : public ExCLError {
public:
virtual string description() const
{ return "(ExCLNonlinearExpression) The resulting expression would be nonlinear"; }
};
class ExCLConstraintNotFound : public ExCLError {
public:
virtual string description() const
{ return "(ExCLConstraintNotFound) Tried to remove a constraint that was never added"; }
};
class ExCLParseError : public ExCLError {
public:
virtual ~ExCLParseError() throw() {}
virtual string description() const
{ return "(ExCLParseError)"; }
};
class ExCLParseErrorMisc : public ExCLParseError {
public:
ExCLParseErrorMisc(const string &s)
: _msg("(ExCLParseError) ")
{ _msg += s; }
virtual ~ExCLParseErrorMisc() throw() {}
virtual string description() const
{ return _msg; }
private:
string _msg;
};
class ExCLParseErrorBadIdentifier : public ExCLParseError {
public:
ExCLParseErrorBadIdentifier(const string &id)
: _msg("(ExCLParseErrorBadIdentifier) Did not recognize identifier '")
{
_msg += id;
_msg += "'";
}
virtual ~ExCLParseErrorBadIdentifier() throw() {}
virtual string description() const
{ return _msg; }
private:
string _msg;
};
class ExCLRequiredFailureWithExplanation : public ExCLRequiredFailure
{
public:
virtual ~ExCLRequiredFailureWithExplanation() throw() {}
virtual string description() const
{ return "(ExCLRequiredFailureWithExplanation) A required constraint cannot be satisfied"; }
virtual void AddConstraint(const ClConstraint *cnExpl)
{ _explanation.insert(cnExpl); }
virtual const ClConstraintSet & explanation() const
{ return _explanation; }
protected:
ClConstraintSet _explanation;
};
#endif // ClErrors_H

View file

@ -0,0 +1,94 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDBinaryOneWayConstraint.h
#ifndef ClFDBinaryOneWayConstraint_H
#define ClFDBinaryOneWayConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClFDConstraint.h"
class ClLinearConstraint;
// Just a node in the class hierarchy for now
class ClFDBinaryOneWayConstraint : public ClFDConstraint {
private: typedef ClFDConstraint super;
public:
ClFDBinaryOneWayConstraint(ClVariable vRW, enum ClCnRelation rel, ClVariable vRO,
double coefficient = 1.0, double constant = 0.0,
const ClStrength &strength = ClsRequired(),
double weight = 1.0)
: ClFDConstraint(strength,weight), _vRW(vRW), _rel(rel), _vRO(vRO),
_coefficient(coefficient), _constant(constant)
{ }
ClFDBinaryOneWayConstraint(ClVariable vRW, enum ClCnRelation rel, double constant,
const ClStrength &strength = ClsRequired(),
double weight = 1.0)
: ClFDConstraint(strength,weight), _vRW(vRW), _rel(rel), _vRO(clvNil),
_coefficient(0), _constant(constant)
{ }
ClFDBinaryOneWayConstraint(const ClConstraint &cn);
static void EnsurePreconditionsForCn(const ClConstraint &cn);
static bool FCanConvertCn(const ClConstraint &cn);
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{
xo << "FDCn: " << _vRW << " " << StrCnRelation(_rel) << " ";
if (_coefficient != 0) {
if (_coefficient != 1) xo << _coefficient << "*";
if (_vRO != clvNil) xo << _vRO;
}
if (_constant != 0) xo << " + " << _constant;
return xo;
}
friend ostream& operator<<(ostream &xos, const ClFDBinaryOneWayConstraint &constraint)
{ return constraint.PrintOn(xos); }
#endif
ClVariable ClvRW() const
{ return _vRW; }
ClVariable ClvRO() const
{ return _vRO; }
enum ClCnRelation Relation() const
{ return _rel; }
double Coefficient() const
{ return _coefficient; }
double Constant() const
{ return _constant; }
bool IsInequality() const
{ return (_rel != cnEQ && _rel != cnNEQ); }
bool IsStrictInequality() const
{ return (_rel == cnGT || _rel == cnLT); }
protected:
ClVariable _vRW;
enum ClCnRelation _rel;
ClVariable _vRO;
double _coefficient;
double _constant;
};
#endif

View file

@ -0,0 +1,89 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDConnectorVariable.h
#ifndef ClFDConnectorVariable_H
#define ClFDConnectorVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <stdio.h>
#include <map>
#include <string>
#include <list>
#include "Cassowary.h"
#include "ClVariable.h"
#include "ClFDVariable.h"
#include "ClLinearEquation.h"
#include "ClSimplexSolver.h"
/* Creates a new variable in the FD region
that sets clvFloat in solver (simplex region)
when it changes */
class ClFDConnectorVariable : public ClFDVariable {
public:
typedef ClFDVariable super;
ClFDConnectorVariable(string name, FDNumber Value, const list<FDNumber> &initial_domain,
ClSimplexSolver &solver, ClVariable clvFloat) :
ClFDVariable(name,Value,initial_domain),
_solver(solver),
_clvFloat(clvFloat),
_pcnRequiredLink(new ClLinearEquation(clvFloat,Value))
{ solver.AddConstraint(_pcnRequiredLink); }
#ifndef CL_NO_IO
// Prints a semi-descriptive representation to the stream, using the
// name if there is one, and otherwise the hash number of this
// object.
// EXAMPLE
// [x:10.0] -- name = "x", Value = 10.0
virtual ostream &PrintOn(ostream &xo) const;
#endif
// permit overriding in subclasses in case something needs to be
// done when the Value is changed by the solver
// may be called when the Value hasn't actually changed -- just
// means the solver is setting the external variable
virtual void ChangeValue(FDNumber Value)
{
if (_value != Value) {
_value = Value;
cerr << "Updating " << _clvFloat << " now!" << endl;
_solver.RemoveConstraint(_pcnRequiredLink);
_pcnRequiredLink->ChangeConstant(_value);
_solver.AddConstraint(_pcnRequiredLink);
}
}
private:
// similar to SetValue -- see caveat above -- made private for now
// since it's probably the wrong thing and is too easy to invoke
FDNumber operator=(FDNumber Value)
{ _value = Value; return Value; }
// Copy constructor left undefined since we want to
// outlaw passing by Value! Will get a link error if you
// try to use within ClFDConnectorVariable.c, compile-time error everywhere else
ClFDConnectorVariable(const ClFDConnectorVariable &);
ClSimplexSolver &_solver;
ClVariable _clvFloat;
ClLinearEquation *_pcnRequiredLink;
};
#endif

View file

@ -0,0 +1,40 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDConstraint.h
#ifndef ClFDConstraint_H
#define ClFDConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClConstraint.h"
// Just a node in the class hierarchy for now
class ClFDConstraint : public ClConstraint {
private: typedef ClConstraint super;
public:
// Constructor
ClFDConstraint(const ClStrength &strength = ClsRequired(),
double weight = 1.0)
: ClConstraint(strength, weight) { }
virtual bool FIsOkayForSimplexSolver() const { return false; }
protected:
};
#endif

View file

@ -0,0 +1,120 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClSolver.h
#ifndef ClFDSolver_H
#define ClFDSolver_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClSolver.h"
#include "ClVariable.h"
#include "ClErrors.h"
#include "ClTypedefs.h"
#include "ClSymbolicWeight.h"
#include <GTL/graph.h>
#include <map>
using std::map;
class ClVariable;
class ClFDBinaryOneWayConstraint;
// ClFDSolver is a concrete class
// implementing a very restricted (for now --04/23/99 gjb)
// finite-domain constraint solving algorithm
class ClFDSolver: public ClSolver {
public:
ClFDSolver()
: _setCns(), _mapClvToCns(), G(), nodeToVar(G)
{ G.make_directed(); }
virtual ~ClFDSolver()
{ }
virtual ClFDSolver &AddConstraint(ClConstraint *const pcn);
virtual ClFDSolver &RemoveConstraint(ClConstraint *const pcn);
virtual ClFDSolver &Solve();
virtual ClFDSolver &ShowSolve();
void ChangeClv(ClVariable clv, FDNumber n) {
clv.ChangeValue(n);
if (_pfnChangeClvCallback) {
_pfnChangeClvCallback(&clv,this);
}
}
#ifndef CL_NO_IO
ostream &PrintOn(ostream &xo) const;
ostream &PrintInternalInfo(ostream &xo) const;
ostream &PrintOnVerbose(ostream &xo) const
{ PrintOn(xo); PrintInternalInfo(xo); xo << endl; return xo; }
friend ostream &operator<<(ostream &xo, const ClFDSolver &solver);
#endif
protected:
virtual ClFDSolver &AddConstraintInternal(ClConstraint *const pcn);
virtual ClFDSolver &RemoveConstraintInternal(ClConstraint *const pcn);
/* Create node for v in G, if necessary,
otherwise return the node we already created. */
node GetVarNode(ClVariable v);
/* return the best (lowest) incremental error and the value
at which that error occurs */
pair<ClSymbolicWeight,FDNumber> ComputeBest(ClFDVariable *pcldv);
ClSymbolicWeight ErrorForClvAtValSubjectToCn(ClFDVariable *pcldv,
FDNumber value,const ClConstraint &cn);
/* Turn all FDVariable FIsSet() flags to false */
void ResetSetFlagsOnVariables();
/* all the constraints in the solver */
ClConstraintSet _setCns;
/* _mapClvToCns maps variable to the constraints in which
it is rw (it omits where it is ro) */
ClVarToConstraintSetMap _mapClvToCns;
/* track what edges correspond to which constraints
so we can update the constraint graph when
removing a constraint */
map<ClConstraint *, edge> _mapCnToEdge;
/* track what nodes correspond to which variables */
map<ClVariable, node> _mapVarToNode;
/* directed graph that mirrors the structure of
the relations of the added constraints */
graph G;
node_map<ClVariable> nodeToVar;
};
#define FDN_EOL LONG_MIN
void ListPushOnto(list<FDNumber> *pl, ...);
#endif

View file

@ -0,0 +1,126 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFDVariable.h
#ifndef ClFDVariable_H
#define ClFDVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <cstdio>
#include <map>
#include <string>
#include <list>
#include "Cassowary.h"
#include "ClAbstractVariable.h"
using std::map;
using std::list;
using std::string;
class ClFDVariable : public ClAbstractVariable {
public:
typedef ClAbstractVariable super;
#if 0 /* GJB:FIXME:: */
ClFDVariable(string name, FDNumber Value) :
ClAbstractVariable(name),
_value(Value),
_fSet(true),
_desired_value(Value),
_plfdnInitialDomain(0)
{ }
#endif
ClFDVariable(string name, FDNumber Value, const list<FDNumber> &initial_domain) :
ClAbstractVariable(name),
_value(Value),
_fSet(true),
_desired_value(Value),
_plfdnInitialDomain(new list<FDNumber>())
{
*_plfdnInitialDomain = initial_domain;
}
virtual bool IsFDVariable() const
{ return true; }
// Return true if this a variable known outside the solver.
// (We need to give such variables a Value after solving is complete.)
virtual bool IsExternal() const
{ return true; }
#ifndef CL_NO_IO
// Prints a semi-descriptive representation to the stream, using the
// name if there is one, and otherwise the hash number of this
// object.
// EXAMPLE
// [x:10.0] -- name = "x", Value = 10.0
virtual ostream &PrintOn(ostream &xo) const;
#endif
// Return the current Value I hold.
Number Value() const
{ return _value; }
// Round the Value to an integer and return it
int IntValue() const
{ return _value; }
// change the Value held -- should *not* use this if the variable is
// in a solver -- instead use AddEditVar() and SuggestValue() interface
void SetValue(FDNumber Value)
{ _value = Value; }
// permit overriding in subclasses in case something needs to be
// done when the Value is changed by the solver
// may be called when the Value hasn't actually changed -- just
// means the solver is setting the external variable
virtual void ChangeValue(FDNumber Value)
{ _value = Value; }
virtual bool FIsSet()
{ return _fSet; }
virtual void SetFIsSet(bool f)
{ _fSet = f; }
virtual FDNumber DesiredValue() const
{ return _desired_value; }
virtual const list<FDNumber> *PlfdnDomain() const
{ return _plfdnInitialDomain; }
protected:
// similar to SetValue -- see caveat above -- made private for now
// since it's probably the wrong thing and is too easy to invoke
FDNumber operator=(FDNumber Value)
{ _value = Value; return Value; }
// Copy constructor left undefined since we want to
// outlaw passing by Value! Will get a link error if you
// try to use within ClFDVariable.c, compile-time error everywhere else
ClFDVariable(const ClFDVariable &);
FDNumber _value;
// has the _value been set? Used during solves.
bool _fSet;
FDNumber _desired_value;
list<FDNumber> *_plfdnInitialDomain;
};
#endif

View file

@ -0,0 +1,119 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClFloatVariable.h
#ifndef ClFloatVariable_H
#define ClFloatVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <cstdio>
#include <map>
#include <string>
#include "Cassowary.h"
#include "ClAbstractVariable.h"
using std::map;
using std::string;
class ClFloatVariable : public ClAbstractVariable {
public:
typedef ClAbstractVariable super;
ClFloatVariable(string name, Number Value = 0.0) :
ClAbstractVariable(name),
_value(Value)
{ }
ClFloatVariable(Number Value = 0.0) :
ClAbstractVariable(""),
_value(Value)
{ }
ClFloatVariable(long number, char *prefix, Number Value = 0.0) :
ClAbstractVariable(number,prefix),
_value(Value)
{ }
virtual bool IsFloatVariable() const
{ return true; }
// Return true if this a dummy variable (used as a marker variable
// for required equality constraints). Such variables aren't
// allowed to enter the basis when pivoting.
virtual bool IsDummy() const
{ return false; }
// Return true if this a variable known outside the solver.
// (We need to give such variables a Value after solving is complete.)
virtual bool IsExternal() const
{ return true; }
// Return true if we can Pivot on this variable.
virtual bool IsPivotable() const
{ return false; }
// Return true if this is a restricted (or slack) variable. Such
// variables are constrained to be non-negative and occur only
// internally to the simplex solver.
virtual bool IsRestricted() const
{ return false; }
#ifndef CL_NO_IO
// Prints a semi-descriptive representation to the stream, using the
// name if there is one, and otherwise the hash number of this
// object.
// EXAMPLE
// [x:10.0] -- name = "x", Value = 10.0
virtual ostream &PrintOn(ostream &xo) const;
#endif
// Return the current Value I hold.
Number Value() const
{ return _value; }
// Round the Value to an integer and return it
int IntValue() const
{ return int(_value + 0.5); }
// change the Value held -- should *not* use this if the variable is
// in a solver -- instead use AddEditVar() and SuggestValue() interface
void SetValue(Number Value)
{ _value = Value; }
// permit overriding in subclasses in case something needs to be
// done when the Value is changed by the solver
// may be called when the Value hasn't actually changed -- just
// means the solver is setting the external variable
virtual void ChangeValue(Number Value)
{ _value = Value; }
private:
// similar to SetValue -- see caveat above -- made private for now
// since it's probably the wrong thing and is too easy to invoke
Number operator=(Number Value)
{ _value = Value; return Value; }
// Copy constructor left undefined since we want to
// outlaw passing by Value! Will get a link error if you
// try to use within ClFloatVariable.c, compile-time error everywhere else
ClFloatVariable(const ClFloatVariable &);
Number _value;
};
#endif

View file

@ -0,0 +1,61 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearConstraint.h
#ifndef ClLinearConstraint_H
#define ClLinearConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClConstraint.h"
#include "ClLinearExpression.h"
// Add the ClLinearExpression member variable needed for both
// ClLinearEquation and ClLinearInequality
class ClLinearConstraint : public ClConstraint {
private: typedef ClConstraint super;
public:
// Constructor
ClLinearConstraint(const ClLinearExpression &cle,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClConstraint(strength, weight),
_expression(cle)
{ }
virtual ~ClLinearConstraint() {}
// Return my linear Expression. (For linear equations, this
// constraint represents Expression=0; for linear inequalities it
// represents Expression>=0.)
ClLinearExpression Expression() const
{ return _expression; }
// do not do this if *this is inside a solver
void ChangeConstant(Number constant)
{ _expression.Set_constant(constant); }
protected:
ClLinearExpression _expression;
virtual void setExpression( const ClLinearExpression &expr)
{ _expression = expr; }
};
#endif

View file

@ -0,0 +1,74 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearEquation.h
#ifndef ClLinearEquation_H
#define ClLinearEquation_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClLinearConstraint.h"
#include "ClLinearExpression.h"
class ClStrength;
class ClVariable;
class ClLinearEquation : public ClLinearConstraint {
private: typedef ClLinearConstraint super;
public:
//// Constructors
// ClLinearEquation(expr,...) is expr == 0
ClLinearEquation(const ClLinearExpression &cle,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint(cle,strength, weight)
{ }
// ClLinearEquation(var,expr,...) is var == expr
ClLinearEquation(ClVariable clv,
const ClLinearExpression &cle,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint(cle,strength,weight)
{ _expression.AddVariable(clv,-1.0); }
// ClLinearEquation(expr,var,...) is var == expr
ClLinearEquation(const ClLinearExpression &cle,
ClVariable clv,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint(cle,strength,weight)
{ _expression.AddVariable(clv,-1.0); }
// ClLinearEquation(expr,expr,...) is expr == expr
ClLinearEquation(const ClLinearExpression &cle1,
const ClLinearExpression &cle2,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint(cle1,strength,weight)
{ _expression.AddExpression(cle2,-1.0); }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{ super::PrintOn(xo); xo << " = 0 )"; return xo; }
#endif
virtual bool FIsSatisfied() const
{ return (_expression.Evaluate() == 0); }
};
#endif

View file

@ -0,0 +1,298 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearExpression.h
#ifndef ClLinearExpression_H
#define ClLinearExpression_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "debug.h"
#include "ClVariable.h"
#include "ClLinearExpression_fwd.h"
class ClSimplexSolver;
class ClTableau;
class ClSymbolicWeight;
ClLinearExpression &cleNil();
template <class T>
class ClGenericLinearExpression {
public:
typedef std::map<ClVariable,T> ClVarToCoeffMap;
// convert Number-s into ClLinearExpression-s
ClGenericLinearExpression(T num = 0.0);
// Convert from ClVariable to a ClLinearExpression
// this replaces ClVariable::asLinearExpression
ClGenericLinearExpression(ClVariable clv, T value = 1.0, T constant = 0.0);
// copy ctr
ClGenericLinearExpression(const ClGenericLinearExpression<T> &expr) :
_constant(expr._constant),
_terms(expr._terms)
{ }
virtual ~ClGenericLinearExpression();
// Return a new linear expression formed by multiplying self by x.
// (Note that this result must be linear.)
ClGenericLinearExpression<T> Times(Number x) const;
// Return a new linear expression formed by multiplying self by x.
// (Note that this result must be linear.)
ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &expr) const;
// Return a new linear expression formed by adding x to self.
ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &expr) const;
// Return a new linear expression formed by subtracting x from self.
ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &expr) const;
// Return a new linear expression formed by dividing self by x.
// (Note that this result must be linear.)
ClGenericLinearExpression<T> Divide(Number x) const;
// Return a new linear expression formed by multiplying self by x.
// (Note that this result must be linear.)
ClGenericLinearExpression<T> *P_times(Number x) const
{ return new ClGenericLinearExpression<T>(Times(x)); }
// Return a new linear expression formed by adding x to self.
ClGenericLinearExpression<T> *P_plus(const ClGenericLinearExpression<T> &expr) const
{ return new ClGenericLinearExpression<T>(Plus(expr)); }
// Return a new linear expression formed by subtracting x from self.
ClGenericLinearExpression<T> *P_minus(const ClGenericLinearExpression<T> &expr) const
{ return new ClGenericLinearExpression<T>(Minus(expr)); }
// Return a new linear expression formed by dividing self by x.
// (Note that this result must be linear.)
ClGenericLinearExpression<T> *P_divide(Number x) const
{ return new ClGenericLinearExpression<T>(Divide(x)); }
// Return a new linear expression formed by dividing self by x.
// (Note that this result must be linear.)
ClGenericLinearExpression<T> Divide(const ClGenericLinearExpression<T> &expr) const;
// Return a new linear expression (aNumber/this). Since the result
// must be linear, this is permissible only if 'this' is a constant.
ClGenericLinearExpression<T> DivFrom(const ClGenericLinearExpression<T> &expr) const;
// Return a new linear expression (aNumber-this).
ClGenericLinearExpression<T> SubtractFrom(const ClGenericLinearExpression<T> &expr) const
{ return expr.Minus(*this); }
// Add n*expr to this expression from another expression expr.
ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr,
Number n = 1.0);
// Add n*expr to this expression from another expression expr.
// Notify the solver if a variable is added or deleted from this
// expression.
ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr, Number n,
ClVariable subject,
ClTableau &solver);
// Add a term c*v to this expression. If the expression already
// contains a term involving v, Add c to the existing coefficient.
// If the new coefficient is approximately 0, delete v.
ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c = 1.0);
// Add a term c*v to this expression. If the expression already
// contains a term involving v, Add c to the existing coefficient.
// If the new coefficient is approximately 0, delete v.
ClGenericLinearExpression<T> &setVariable(ClVariable v, T c)
{assert(c != 0.0); _terms[v] = c; return *this; }
// Add a term c*v to this expression. If the expression already
// contains a term involving v, Add c to the existing coefficient.
// If the new coefficient is approximately 0, delete v. Notify the
// solver if v appears or disappears from this expression.
ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c,
ClVariable subject,
ClTableau &solver);
// Return a pivotable variable in this expression. (It is an error
// if this expression is constant -- signal ExCLInternalError in
// that case). Return NULL if no pivotable variables
ClVariable AnyPivotableVariable() const;
// Replace var with a symbolic expression expr that is equal to it.
// If a variable has been added to this expression that wasn't there
// before, or if a variable has been dropped from this expression
// because it now has a coefficient of 0, inform the solver.
// PRECONDITIONS:
// var occurs with a non-Zero coefficient in this expression.
void SubstituteOut(ClVariable v,
const ClGenericLinearExpression<T> &expr,
ClVariable subject,
ClTableau &solver);
// This linear expression currently represents the equation
// oldSubject=self. Destructively modify it so that it represents
// the equation NewSubject=self.
//
// Precondition: NewSubject currently has a nonzero coefficient in
// this expression.
//
// NOTES
// Suppose this expression is c + a*NewSubject + a1*v1 + ... + an*vn.
//
// Then the current equation is
// oldSubject = c + a*NewSubject + a1*v1 + ... + an*vn.
// The new equation will be
// NewSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn.
// Note that the term involving NewSubject has been dropped.
void ChangeSubject(ClVariable old_subject,
ClVariable new_subject);
// This linear expression currently represents the equation self=0. Destructively modify it so
// that subject=self represents an equivalent equation.
//
// Precondition: subject must be one of the variables in this expression.
// NOTES
// Suppose this expression is
// c + a*subject + a1*v1 + ... + an*vn
// representing
// c + a*subject + a1*v1 + ... + an*vn = 0
// The modified expression will be
// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
// representing
// subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
//
// Note that the term involving subject has been dropped.
// Returns the reciprocal, so ChangeSubject can use it, too
T NewSubject(ClVariable subject);
// Return the value of the linear expression
// given the current assignments of values to contained variables
T Evaluate() const;
// Return the coefficient corresponding to variable var, i.e.,
// the 'ci' corresponding to the 'vi' that var is:
// v1*c1 + v2*c2 + .. + vn*cn + c
T CoefficientFor(ClVariable var) const
{
typename ClVarToCoeffMap::const_iterator it = _terms.find(var);
if (it != _terms.end())
return (*it).second;
return 0.0;
}
T Constant() const
{ return _constant; }
void Set_constant(T c)
{ _constant = c; }
const ClVarToCoeffMap &Terms() const
{ return _terms; }
ClVarToCoeffMap &Terms()
{ return _terms; }
void IncrementConstant(T c)
{ _constant += c; }
bool IsConstant() const
{ return _terms.size() == 0; }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const;
friend ostream &operator<<(ostream &xo,const ClGenericLinearExpression<T> &cle)
{ return cle.PrintOn(xo); }
#endif
friend ClGenericLinearExpression<T> operator+(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Plus(e2); }
friend ClGenericLinearExpression<T> operator-(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Minus(e2); }
friend ClGenericLinearExpression<T> operator*(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Times(e2); }
friend ClGenericLinearExpression<T> operator/(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Divide(e2); }
// FIXGJB -- this may be wrong -- should test underlying expression for equality
friend bool operator==(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return &e1 == &e2; }
/// Named versions of the operator functions for ease of
/// wrapping, or expressing using prefix notation
friend ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Plus(e2); }
friend ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Minus(e2); }
friend ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return e1.Times(e2); }
friend ClGenericLinearExpression<T> *Divide(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return new ClGenericLinearExpression<T>(e1.Divide(e2)); }
friend ClGenericLinearExpression<T> *p_Plus(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return new ClGenericLinearExpression<T>(e1.Plus(e2)); }
friend ClGenericLinearExpression<T> *p_Minus(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return new ClGenericLinearExpression<T>(e1.Minus(e2)); }
friend ClGenericLinearExpression<T> *p_Times(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return new ClGenericLinearExpression<T>(e1.Times(e2)); }
friend ClGenericLinearExpression<T> *p_Divide(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return new ClGenericLinearExpression<T>(e1.Divide(e2)); }
// FIXGJB -- this may be wrong -- should test underlying expression for equality
friend bool FEquals(const ClGenericLinearExpression<T> &e1,
const ClGenericLinearExpression<T> &e2)
{ return &e1 == &e2; }
ClGenericLinearExpression<T> &MultiplyMe(T x);
private:
T _constant;
ClVarToCoeffMap _terms;
};
typedef ClGenericLinearExpression<Number>::ClVarToCoeffMap ClVarToNumberMap;
#endif

View file

@ -0,0 +1,26 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearExpression.h
#ifndef ClLinearExpression_fwd_H
#define ClLinearExpression_fwd_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
template <class T> class ClGenericLinearExpression;
typedef ClGenericLinearExpression<Number> ClLinearExpression;
typedef ClLinearExpression* PClLinearExpression;
#endif

View file

@ -0,0 +1,167 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClLinearInequality.h
#ifndef ClLinearInequality_H
#define ClLinearInequality_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "ClConstraint.h"
#include "ClLinearConstraint.h"
class ClVariable;
class ClLinearInequality : public ClLinearConstraint {
private: typedef ClLinearConstraint super;
public:
//// Constructors
// ClLinearInequality(expr,...) is expr >= 0
ClLinearInequality(const ClLinearExpression &cle,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint(cle,strength, weight),
_fStrictInequality(false)
{ }
// ClLinearInequality(var,OP,expr) is var >= expr
ClLinearInequality(const ClVariable clv,
enum ClCnRelation op,
const ClLinearExpression &cle,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint( cle, strength, weight),
_fStrictInequality(false)
{
if (op == cnGEQ || op == cnGT)
{
_expression.MultiplyMe(-1.0);
_expression.AddVariable(clv,1.0);
}
else if (op == cnLEQ || op == cnGEQ)
{
_expression.AddVariable(clv,-1.0);
}
else
{
throw ExCLEditMisuse("Cannot use that operator for ClLinearInequality objects");
}
if (op == cnLT || op == cnGT) {
_fStrictInequality = true;
}
}
#ifdef FIXGJB_AMBIGUOUS
// ClLinearInequality(expr,OP,var) is var ?<>? expr
ClLinearInequality(const ClLinearExpression &cle,
enum ClCnRelation op,
const ClVariable clv,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint( cle, strength, weight),
_fStrictInequality(false)
{
if (op == cnLEQ || op == cnLT)
{
_expression.MultiplyMe(-1.0);
_expression.AddVariable(clv,1.0);
}
else if (op == cnGEQ || op == cnGT)
{
_expression.AddVariable(clv,-1.0);
}
if (op == cnLT || op == cnGT) {
_fStrictInequality = true;
}
}
#endif
// ClLinearInequality(expr,OP,expr) is expr >= expr
ClLinearInequality(const ClLinearExpression &cle1,
enum ClCnRelation op,
const ClLinearExpression &cle2,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint( cle2, strength, weight),
_fStrictInequality(false)
{
if (op == cnGEQ || op == cnGT)
{
_expression.MultiplyMe(-1.0);
_expression.AddExpression(cle1);
}
else if (op == cnLEQ || op == cnLT)
{
_expression.AddExpression(cle1,-1.0);
}
if (op == cnLT || op == cnGT) {
_fStrictInequality = true;
}
}
#ifdef FIXGJB_AMBIGUOUS
// ClLinearInequality(var,OP,var) is var ?<>? var
ClLinearInequality(const ClVariable clv1,
enum ClCnRelation op,
const ClVariable clv2,
const ClStrength &strength = ClsRequired(),
double weight = 1.0) :
ClLinearConstraint( clv2, strength, weight),
_fStrictInequality(false)
{
if (op == cnGEQ || op == cnGT)
{
_expression.MultiplyMe(-1.0);
_expression.AddVariable(clv1,1.0);
}
else if (op == cnLEQ || op == cnLT)
{
_expression.AddVariable(clv1,-1.0);
}
if (op == cnLT || op == cnGT) {
_fStrictInequality = true;
}
}
#endif
// Return true if this is an inequality constraint and
// false if it is an equality constraint. The default is
// that it is not.
virtual bool IsInequality() const
{ return true; }
virtual bool IsStrictInequality() const
{ return _fStrictInequality; }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{ super::PrintOn(xo); xo << " >= 0 )"; return xo; }
#endif
virtual bool FIsSatisfied() const
{
Number v = _expression.Evaluate();
if (_fStrictInequality)
return (v > 0);
else
return (v >= 0);
}
private:
bool _fStrictInequality;
};
#endif

View file

@ -0,0 +1,63 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClObjectiveVariable.h
#ifndef ClObjectiveVariable_H
#define ClObjectiveVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClAbstractVariable.h"
class ClTableau;
class ClSimplexSolver;
class ClObjectiveVariable : public ClAbstractVariable {
protected:
friend class ClTableau;
friend class ClSimplexSolver;
ClObjectiveVariable(string name = "") :
ClAbstractVariable(name)
{ }
ClObjectiveVariable(long number, char *prefix) :
ClAbstractVariable(number,prefix)
{ }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{
xo << "[" << Name() << ":obj]";
return xo;
}
#endif
// We don't need to give such variables a Value after solving is complete.
virtual bool IsExternal() const
{ return false; }
// Return true if we can Pivot on this variable.
virtual bool IsPivotable() const
{ return false; }
// Return true if this is a restricted (or slack) variable. Such
// variables are constrained to be non-negative and occur only
// internally to the simplex solver.
virtual bool IsRestricted() const
{ return false; }
};
#endif

View file

@ -0,0 +1,74 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClPoint.h
#ifndef ClPoint_H
#define ClPoint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClVariable.h"
// ClPoint is just a convenience class for pairs of
// ClVariables -- often useful for coordinate pairs in 2-space
class ClPoint {
public:
ClPoint(Number x, Number y)
: _clv_x(x), _clv_y(y)
{ }
ClPoint()
{ }
ClVariable X()
{ return _clv_x; }
ClVariable Y()
{ return _clv_y; }
const ClVariable X() const
{ return _clv_x; }
const ClVariable Y() const
{ return _clv_y; }
void SetXY(Number x, Number y)
{ _clv_x.SetValue(x); _clv_y.SetValue(y); }
Number Xvalue() const
{ return X().Value(); }
Number Yvalue() const
{ return Y().Value(); }
private:
ClVariable _clv_x;
ClVariable _clv_y;
#ifndef CL_NO_IO
friend ostream &operator<<(ostream &xo, const ClPoint &clp);
#endif
};
#ifndef CL_NO_IO
inline ostream &
operator<<(ostream &xo, const ClPoint &clp)
{
xo << "(" << clp._clv_x << ", " << clp._clv_y << ")";
return xo;
}
#endif
#endif

View file

@ -0,0 +1,117 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClReader.h
// Original implementation contributed by Steve Wolfman
// Subsequently largely revised by Greg J. Badros
#ifndef CREADER_H
#define CREADER_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <string>
#include <map>
#include <algorithm>
#include <iostream>
#include "ClErrors.h"
#include "ClVariable.h"
#include "ClStrength.h"
#include "ClLinearExpression_fwd.h"
using std::string;
using std::istream;
class ClConstraint;
class ClVarLookupFunction : public std::unary_function<const string &,ClVariable *> {
public:
virtual ClVariable *operator()(const string &) const { return &clvNil; }
};
// Attempts to read a constraint of input stream in
// Returns constraint (freshly allocated, client responsibility to deallocate)
// if succesful. Otherwise, returns 0.
ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func,
const ClStrength &strength = ClsRequired());
class ClVarLookupInMap : public ClVarLookupFunction {
public:
ClVarLookupInMap(StringToVarMap *pmapVars, bool fAutoCreate)
: _pmapVars(pmapVars), _fAutoCreate(fAutoCreate) { }
ClVariable *operator()(const string &str) const
{
if (!_pmapVars)
return &clvNil;
StringToVarMap &_mapVars = *_pmapVars;
StringToVarMap::iterator it = _mapVars.find(str);
if (it != _mapVars.end()) {
return &it->second;
} else if (_fAutoCreate) {
// save the old symbol table, if any
StringToVarMap *pmapOld = ClVariable::VarMap();
// and set it to this one temporarily
ClVariable::SetVarMap(&_mapVars);
ClVariable *pclv = new ClVariable(str);
// now switch it back
ClVariable::SetVarMap(pmapOld);
return pclv;
} else {
return &clvNil;
}
}
private:
StringToVarMap *_pmapVars;
bool _fAutoCreate;
};
/* the "yyerror" function */
void clerror(const char *sz);
struct ClParseData {
ClParseData(istream &xi, const ClVarLookupFunction &lookup_func)
: _xi(xi), _lookup_func(lookup_func) { }
ClConstraint *Pcn() { return _pcn; }
ClVarSet _readOnlyVarsSoFar;
istream & _xi;
ClConstraint * _pcn;
const ClVarLookupFunction &_lookup_func;
};
inline
const ClStrength
&ClsFromSz(const char *sz)
{
const ClStrength *pcls = &ClsRequired();
double n1, n2, n3;
if (strcmp("required",sz) == 0)
; /* initialized to ClsRequired, above */
else if (strcasecmp("strong",sz) == 0) { pcls = &ClsStrong(); }
else if (strcasecmp("medium",sz) == 0) { pcls = &ClsMedium(); }
else if (strcasecmp("weak",sz) == 0) { pcls = &ClsWeak(); }
else if (sscanf(sz,"(%lf,%lf,%lf)",&n1,&n2,&n3) == 3) {
pcls = new ClStrength("parsed",n1,n2,n3);
} else {
throw ExCLParseErrorMisc("Error parsing strength");
}
return *pcls;
}
#endif

View file

@ -0,0 +1,588 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClSimplexSolver.h
#ifndef ClSimplexSolver_H
#define ClSimplexSolver_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <stack>
#include <list>
#include <iostream>
#include "Cassowary.h"
#include "ClSolver.h"
#include "ClTableau.h"
#include "ClLinearInequality.h"
#include "ClStrength.h"
#include "ClStayConstraint.h"
#include "ClEditConstraint.h"
#include "ClSlackVariable.h"
#include "ClObjectiveVariable.h"
#include "ClErrors.h"
#include "ClTypedefs.h"
using std::list;
using std::stack;
using std::ostream;
class ClVariable;
class ClPoint;
class ExCLRequiredFailureWithExplanation;
// ClSimplexSolver encapsulates the solving behaviour
// of the cassowary algorithm
class ClSimplexSolver : public ClSolver, public ClTableau {
protected:
class ClEditInfo;
typedef list<ClEditInfo *> ClEditInfoList;
ClEditInfo *PEditInfoFromClv(ClVariable clv) {
ClEditInfoList::iterator it = _editInfoList.begin();
for (; it != _editInfoList.end(); ++it) {
ClEditInfo *pei = (*it);
if (pei->_clv == clv)
return pei;
}
return 0;
}
public:
// Constructor
ClSimplexSolver() :
ClSolver(),
_objective(ClVariable(new ClObjectiveVariable("Z"))),
_slackCounter(0),
_artificialCounter(0),
#ifdef CL_FIND_LEAK
_cArtificialVarsDeleted(0),
#endif
_dummyCounter(0),
_epsilon(1e-8),
_fResetStayConstantsAutomatically(true),
_fNeedsSolving(false),
_fExplainFailure(false),
_pfnResolveCallback(0),
_pfnCnSatCallback(0)
{
_rows[_objective] = new ClLinearExpression();
// start out with no edit variables
_stkCedcns.push(0);
#ifdef CL_TRACE
std::cerr << "objective row new@ " << _rows[_objective] << std::endl;
#endif
}
virtual ~ClSimplexSolver();
// Add constraints so that lower<=var<=upper. (nil means no bound.)
ClSimplexSolver &AddLowerBound(ClVariable v, Number lower)
{
ClLinearInequality *pcn = new ClLinearInequality(ClLinearExpression(v - lower));
return AddConstraint(pcn);
}
ClSimplexSolver &AddUpperBound(ClVariable v, Number upper)
{
ClLinearInequality *pcn = new ClLinearInequality(ClLinearExpression(upper - v));
return AddConstraint(pcn);
}
ClSimplexSolver &AddBounds(ClVariable v, Number lower, Number upper)
{ AddLowerBound(v,lower); AddUpperBound(v,upper); return *this; }
// Add the constraint cn to the tableau
ClSimplexSolver &AddConstraint(ClConstraint *const pcn);
#ifndef CL_NO_DEPRECATED
// Deprecated! --02/19/99 gjb
ClSimplexSolver &AddConstraint(ClConstraint &cn)
{ return AddConstraint(&cn); }
#endif
// Add an edit constraint for "v" with given strength
ClSimplexSolver &AddEditVar(const ClVariable v, const ClStrength &strength = ClsStrong(),
double weight = 1.0 )
{
ClEditConstraint *pedit = new ClEditConstraint(v, strength, weight);
return AddConstraint(pedit);
}
ClSimplexSolver &RemoveEditVar(ClVariable v)
{
ClEditInfo *pcei = PEditInfoFromClv(v);
if (!pcei) {
throw ExCLEditMisuse("Removing edit variable that was not found");
}
ClConstraint *pcnEdit = pcei->_pconstraint;
RemoveConstraint(pcnEdit);
delete pcnEdit;
return *this;
}
// BeginEdit() should be called before sending
// Resolve() messages, after adding the appropriate edit variables
ClSimplexSolver &BeginEdit()
{
if (_editInfoList.size() == 0) {
throw ExCLEditMisuse("BeginEdit called, but no edit variable");
}
// may later want to do more in here
_infeasibleRows.clear();
ResetStayConstants();
_stkCedcns.push(_editInfoList.size());
return *this;
}
// EndEdit should be called after editing has finished
// for now, it just removes edit variables added from before the last BeginEdit
ClSimplexSolver &EndEdit()
{
if (_editInfoList.size() == 0)
throw ExCLEditMisuse("EndEdit called but no edit variables");
Resolve();
_stkCedcns.pop();
RemoveEditVarsTo(_stkCedcns.top());
// may later want to do more in here
return *this;
}
// RemoveAllEditVars() just eliminates all the edit constraints
// that were added
ClSimplexSolver &RemoveAllEditVars() { RemoveEditVarsTo(0); return *this; }
// remove the last added edit vars to leave only n edit vars left
ClSimplexSolver &RemoveEditVarsTo(unsigned int n);
int numEditVars() const
{ return _editInfoList.size(); }
// Add weak stays to the x and y parts of each point. These have
// increasing weights so that the solver will try to satisfy the x
// and y stays on the same point, rather than the x stay on one and
// the y stay on another.
ClSimplexSolver &AddPointStays(const vector<const ClPoint *> &listOfPoints,
const ClStrength &strength = ClsWeak());
ClSimplexSolver &AddPointStay(const ClVariable vx, const ClVariable vy,
const ClStrength &strength = ClsWeak(),
double weight = 1.0)
{ AddStay(vx,strength,weight); AddStay(vy,strength,weight); return *this; }
ClSimplexSolver &AddPointStay(const ClPoint &clp,
const ClStrength &strength = ClsWeak(),
double weight = 1.0);
// Add a stay of the given strength (default to weak) of v to the tableau
ClSimplexSolver &AddStay(const ClVariable v,
const ClStrength &strength = ClsWeak(), double weight = 1.0 )
{
ClStayConstraint *pcn = new ClStayConstraint(v,strength,weight);
return AddConstraint(pcn);
}
// Remove the constraint cn from the tableau
// Also remove any error variable associated with cn
ClSimplexSolver &RemoveConstraint(ClConstraint *const pcn)
{ RemoveConstraintInternal(pcn); pcn->removedFrom(*this); return *this; }
#ifndef CL_NO_DEPRECATED
// Deprecated! --02/19/99 gjb
ClSimplexSolver &RemoveConstraint(ClConstraint &cn)
{ return RemoveConstraint(&cn); }
#endif
// Re-initialize this solver from the original constraints, thus
// getting rid of any accumulated numerical problems. (Actually, we
// haven't definitely observed any such problems yet)
void Reset();
// Re-solve the current collection of constraints, given the new
// values for the edit variables that have already been
// suggested (see SuggestValue() method)
// This is not guaranteed to work if you remove an edit constraint
// from the middle of the edit constraints you added
// (e.g., edit A, edit B, edit C, remove B -> this will fail!)
// DEPRECATED
void Resolve();
// Re-solve the current collection of constraints for new values for
// the constants of the edit variables.
// This is implemented in terms of SuggestValue-s, and is
// less efficient than that more natural interface
void Resolve(const vector<Number> &newEditConstants);
// Convenience function for Resolve-s of two variables
void Resolve(Number x, Number y)
{
vector<Number> vals;
vals.push_back(x);
vals.push_back(y);
Resolve(vals);
}
// Suggest a new value for an edit variable
// the variable needs to be added as an edit variable
// and BeginEdit() needs to be called before this is called.
// The tableau will not be solved completely until
// after Resolve() has been called
ClSimplexSolver &SuggestValue(ClVariable v, Number x);
// Set and check whether or not the solver will attempt to compile
// an explanation of failure when a required constraint conflicts
// with another required constraint
ClSimplexSolver &SetExplaining(bool f)
{ _fExplainFailure = f; return *this; }
bool FIsExplaining() const
{ return _fExplainFailure; }
// If autosolving has been turned off, client code needs
// to explicitly call solve() before accessing variables
// values
ClSimplexSolver &Solve()
{
#ifdef CL_SOLVER_CHECK_INTEGRITY
AssertValid();
#endif
if (_fNeedsSolving)
{
Optimize(_objective);
SetExternalVariables();
#ifdef CL_TRACE_VERBOSE
std::cerr << "Manual solve actually solving." << std::endl;
#endif
}
return *this;
}
ClSimplexSolver &SetEditedValue(ClVariable v, double n)
{
if (!FContainsVariable(v))
{
ChangeClv(v,n);
return *this;
}
if (!ClApprox(n, v.Value()))
{
AddEditVar(v);
BeginEdit();
SuggestValue(v,n);
EndEdit();
}
return *this;
}
// Solver contains the variable if it's in either the columns
// list or the rows list
bool FContainsVariable(const ClVariable v)
{ return ColumnsHasKey(v) || RowExpression(v); }
ClSimplexSolver &AddVar(const ClVariable v)
{ if (!FContainsVariable(v))
{
AddStay(v);
#ifdef CL_TRACE
std::cerr << "added initial stay on " << v << std::endl;
#endif
}
return *this; }
typedef void (*PfnResolveCallback)(ClSimplexSolver *psolver);
void SetResolveCallback(PfnResolveCallback pfn)
{ _pfnResolveCallback = pfn; }
typedef void (*PfnCnSatCallback)(ClSimplexSolver *psolver,
ClConstraint *pcn, bool fSatisfied);
void SetCnSatCallback(PfnCnSatCallback pfn)
{ _pfnCnSatCallback = pfn; }
#ifndef CL_NO_IO
friend ostream &operator<<(ostream &xo, const ClSimplexSolver &tableau);
ostream &PrintOn(ostream &xo) const;
ostream &PrintInternalInfo(ostream &xo) const;
ostream &PrintOnVerbose(ostream &xo) const
{ PrintOn(xo); PrintInternalInfo(xo); xo << std::endl; return xo; }
#endif
const ClConstraintToVarMap &ConstraintMap() const
{ return _markerVars; }
const ClVarToConstraintMap &MarkerMap() const
{ return _constraintsMarked; }
bool FIsConstraintSatisfied(const ClConstraint *const pcn) const;
// DEPRECATED
bool FIsConstraintSatisfied(const ClConstraint &pcn) const
{ return FIsConstraintSatisfied(&pcn); }
// re-set all the external variables to their current values
// most importantly, this re-calls all the ChangeClv callbacks
// (which might be used to copy the ClVariable's value to another
// variable)
void UpdateExternalVariables()
{ SetExternalVariables(); }
// A. Beurive' Tue Jul 6 17:05:39 CEST 1999
void ChangeStrengthAndWeight(ClConstraint *pcn, const ClStrength &strength, double weight);
void ChangeStrength(ClConstraint *pcn, const ClStrength &strength);
void ChangeWeight(ClConstraint *pcn, double weight);
// void DisplayObjective();
// Each of the non-required stays will be represented by an equation
// of the form
// v = c + eplus - eminus
// where v is the variable with the stay, c is the previous value of
// v, and eplus and eminus are slack variables that hold the error
// in satisfying the stay constraint. We are about to change
// something, and we want to fix the constants in the equations
// representing the stays. If both eplus and eminus are nonbasic
// they have value 0 in the current solution, meaning the previous
// stay was exactly satisfied. In this case nothing needs to be
// changed. Otherwise one of them is basic, and the other must
// occur only in the Expression for that basic error variable.
// Reset the Constant in this Expression to 0.
void ResetStayConstants();
ClSimplexSolver &SetAutoResetStayConstants(bool f)
{ _fResetStayConstantsAutomatically = f; if (f) ResetStayConstants(); return *this; }
bool FIsAutoResetStayConstants() const
{ return _fResetStayConstantsAutomatically; }
protected:
// ClEditInfo is a privately-used class
// that just wraps a constraint, its positive and negative
// error variables, and its prior edit Constant.
// It is used as values in _editInfoList, and replaces
// the parallel vectors of error variables and previous edit
// constants from the smalltalk version of the code.
class ClEditInfo {
friend class ClSimplexSolver;
public:
// These instances own none of the pointers;
// the tableau row (the Expression) owns the peplus, peminus,
// and AddEditVar/RemoveEditVar pair or the client code owns
// the constraint object
ClEditInfo(ClVariable clv,
ClEditConstraint *pconstraint,
ClVariable eplus, ClVariable eminus,
Number prevEditConstant)
:_clv(clv),
_pconstraint(pconstraint),
_clvEditPlus(eplus), _clvEditMinus(eminus),
_prevEditConstant(prevEditConstant)
{ }
~ClEditInfo()
{ }
ostream &PrintOn(ostream &xo) const
{ xo << _clv << " -> [" << _clvEditPlus << ", " << _clvEditMinus << "]("
<< _prevEditConstant << ")@" << " -- "
<< *_pconstraint;
return xo; }
friend ostream &operator<<(ostream &xo, const ClEditInfo &cei)
{ return cei.PrintOn(xo); }
private:
ClVariable _clv;
ClConstraint *_pconstraint;
ClVariable _clvEditPlus;
ClVariable _clvEditMinus;
Number _prevEditConstant;
};
// Add the constraint expr=0 to the inequality tableau using an
// artificial variable. To do this, create an artificial variable
// av and Add av=expr to the inequality tableau, then make av be 0.
// (Raise an exception if we can't attain av=0.)
// (Raise an exception if we can't attain av=0.) If the Add fails,
// prepare an explanation in e that describes why it failed (note
// that an empty explanation is considered to mean the explanation
// encompasses all active constraints.
bool AddWithArtificialVariable(ClLinearExpression &pexpr,
ExCLRequiredFailureWithExplanation &e);
// Using the given equation (av = cle) build an explanation which
// implicates all constraints used to construct the equation. That
// is, everything for which the variables in the equation are markers.
// Thanks to Steve Wolfman for the implementation of the explanation feature
void BuildExplanation(ExCLRequiredFailureWithExplanation & e,
ClVariable av,
const ClLinearExpression * pcle);
// We are trying to Add the constraint expr=0 to the appropriate
// tableau. Try to Add expr directly to the tableax without
// creating an artificial variable. Return true if successful and
// false if not.
bool TryAddingDirectly(ClLinearExpression &pexpr);
// We are trying to Add the constraint expr=0 to the tableaux. Try
// to choose a subject (a variable to become basic) from among the
// current variables in expr. If expr contains any unrestricted
// variables, then we must choose an unrestricted variable as the
// subject. Also, if the subject is new to the solver we won't have
// to do any substitutions, so we prefer new variables to ones that
// are currently noted as parametric. If expr contains only
// restricted variables, if there is a restricted variable with a
// negative coefficient that is new to the solver we can make that
// the subject. Otherwise we can't find a subject, so return nil.
// (In this last case we have to Add an artificial variable and use
// that variable as the subject -- this is done outside this method
// though.)
//
// Note: in checking for variables that are new to the solver, we
// ignore whether a variable occurs in the objective function, since
// new slack variables are added to the objective function by
// 'NewExpression:', which is called before this method.
ClVariable ChooseSubject(ClLinearExpression &pexpr);
// Each of the non-required edits will be represented by an equation
// of the form
// v = c + eplus - eminus
// where v is the variable with the edit, c is the previous edit
// value, and eplus and eminus are slack variables that hold the
// error in satisfying the edit constraint. We are about to change
// something, and we want to fix the constants in the equations
// representing the edit constraints. If one of eplus and eminus is
// basic, the other must occur only in the Expression for that basic
// error variable. (They can't both be basic.) Fix the Constant in
// this Expression. Otherwise they are both nonbasic. Find all of
// the expressions in which they occur, and fix the constants in
// those. See the UIST paper for details.
// (This comment was for resetEditConstants(), but that is now
// gone since it was part of the screwey vector-based interface
// to resolveing. --02/15/99 gjb)
void DeltaEditConstant(Number delta, ClVariable pv1, ClVariable pv2);
// We have set new values for the constants in the edit constraints.
// Re-Optimize using the dual simplex algorithm.
void DualOptimize();
// Make a new linear Expression representing the constraint cn,
// replacing any basic variables with their defining expressions.
// Normalize if necessary so that the Constant is non-negative. If
// the constraint is non-required give its error variables an
// appropriate weight in the objective function.
ClLinearExpression *NewExpression(const ClConstraint *pcn,
/* output to */
ClVariable &clvEplus,
ClVariable &clvEminus,
Number &prevEConstant);
// Minimize the value of the objective. (The tableau should already
// be feasible.)
void Optimize(ClVariable zVar);
// Do a Pivot. Move entryVar into the basis (i.e. make it a basic variable),
// and move exitVar out of the basis (i.e., make it a parametric variable)
void Pivot(ClVariable entryVar, ClVariable exitVar);
// Set the external variables known to this solver to their appropriate values.
// Set each external basic variable to its value, and set each
// external parametric variable to 0. (It isn't clear that we will
// ever have external parametric variables -- every external
// variable should either have a stay on it, or have an equation
// that defines it in terms of other external variables that do have
// stays. For the moment I'll put this in though.) Variables that
// are internal to the solver don't actually store values -- their
// values are just implicit in the tableu -- so we don't need to set
// them.
void SetExternalVariables();
// this gets called by RemoveConstraint and by AddConstraint when the
// contraint we're trying to Add is inconsistent
ClSimplexSolver &RemoveConstraintInternal(const ClConstraint *const pcn);
void ChangeClv(ClVariable clv, Number n) {
clv.ChangeValue(n);
if (_pfnChangeClvCallback)
_pfnChangeClvCallback(&clv,this);
}
/// instance variables
// the arrays of positive and negative error vars for the stay constraints
// (need both positive and negative since they have only non-negative values)
ClVarVector _stayMinusErrorVars;
ClVarVector _stayPlusErrorVars;
// give error variables for a non required constraint,
// maps to ClSlackVariable-s
ClConstraintToVarSetMap _errorVars;
// Return a lookup table giving the marker variable for each
// constraint (used when deleting a constraint).
ClConstraintToVarMap _markerVars;
// Reverse of the above-- a lookup table giving the constraint
// for each marker variable (used when building failure explanations)
ClVarToConstraintMap _constraintsMarked;
ClVariable _objective;
// Map edit variables to their constraints, errors, and prior
// values
ClEditInfoList _editInfoList;
int _slackCounter;
int _artificialCounter;
#ifdef CL_FIND_LEAK
int _cArtificialVarsDeleted;
#endif
int _dummyCounter;
const double _epsilon;
bool _fResetStayConstantsAutomatically;
bool _fNeedsSolving;
bool _fExplainFailure;
PfnResolveCallback _pfnResolveCallback;
PfnCnSatCallback _pfnCnSatCallback;
// C-style extension mechanism so I
// don't have to wrap ScwmClSolver separately
void *_pv;
// a stack of the number of edit constraints
// that existed at the prior BeginEdit.
// an EndEdit needs to pop off the top value,
// then remove constraints to get down
// to the # of constraints as in _stkCedcns.top()
stack<int> _stkCedcns;
#ifndef CL_NO_IO
friend ostream &PrintTo(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo);
friend ostream &operator<<(ostream &xo, const ClSimplexSolver::ClEditInfoList &listPEditInfo);
#endif
};
#endif // ClSimplexSolver_H

View file

@ -0,0 +1,75 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClSlackVariable.h
#ifndef ClSlackVariable_H
#define ClSlackVariable_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClAbstractVariable.h"
class ClTableau;
class ClSimplexSolver;
class ClSlackVariable : public ClAbstractVariable {
public:
#ifdef CL_FIND_LEAK
~ClSlackVariable() { --cSlackVariables; };
static long cSlackVariables;
#endif
protected:
friend class ClTableau;
friend class ClSimplexSolver;
ClSlackVariable(string Name = "") :
ClAbstractVariable(Name)
{
#ifdef CL_FIND_LEAK
++cSlackVariables;
#endif
}
ClSlackVariable(long number, char *prefix) :
ClAbstractVariable(number,prefix)
{
#ifdef CL_FIND_LEAK
++cSlackVariables;
#endif
}
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{
xo << "[" << Name() << ":slack]";
return xo;
}
#endif
virtual bool IsExternal() const
{ return false; }
virtual bool IsPivotable() const
{ return true; }
virtual bool IsRestricted() const
{ return true; }
};
#endif

View file

@ -0,0 +1,167 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClSolver.h
#ifndef ClSolver_H
#define ClSolver_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClErrors.h"
#include "ClTypedefs.h"
#include <list>
#include <iostream>
using std::list;
using std::ostream;
class ClVariable;
// ClSolver is an abstract base class
class ClSolver {
public:
ClSolver() : _pv(0), _fAutosolve(true), _pfnChangeClvCallback(0) { }
virtual ~ClSolver()
{ }
// Add the constraint cn to the solver
virtual ClSolver &AddConstraint(ClConstraint *const pcn) = 0;
// Remove the constraint cn from the solver
virtual ClSolver &RemoveConstraint(ClConstraint *const pcn) = 0;
// Same as above, but returns false if the constraint cannot be solved
// (i.e., the resulting system would be unsatisfiable)
// The above function "AddConstraint" throws an exception in that case
// which may be inconvenient
virtual bool AddConstraintNoException(ClConstraint *const pcn)
{
try {
AddConstraint(pcn);
return true;
}
catch (const ExCLRequiredFailure &e)
{ return false; }
catch (const ExCLTooDifficult &e)
{ return false; }
}
#ifndef CL_NO_DEPRECATED
// Deprecated --02/22/99 gjb
bool AddConstraintNoException(ClConstraint &cn)
{ return AddConstraintNoException(&cn); }
#endif
virtual bool RemoveConstraintNoException(ClConstraint *const pcn)
{
try {
RemoveConstraint(pcn);
return true;
}
catch (const ExCLConstraintNotFound &e)
{ return false; }
}
#ifndef CL_NO_DEPRECATED
// Deprecated --02/22/99 gjb
bool RemoveConstraintNoException(ClConstraint &cn)
{ return RemoveConstraintNoException(&cn); }
#endif
virtual ClSolver &Solve()
{ assert(false); return *this; }
virtual bool SolveNoException()
{
try {
Solve();
return true;
}
catch (const ExCLTooDifficult &e)
{ return false; }
catch (const ExCLRequiredFailure &e)
{ return false; }
}
virtual void Resolve()
{ assert(false); }
void SetPv(void *pv)
{ _pv = pv; }
void *Pv() const
{ return _pv; }
typedef void (*PfnChangeClvCallback)(ClVariable *pclv, ClSolver *psolver);
void SetChangeClvCallback(PfnChangeClvCallback pfn)
{ _pfnChangeClvCallback = pfn; }
// Control whether optimization and setting of external variables
// is done automatically or not. By default it is done
// automatically and solve() never needs to be explicitly
// called by client code; if SetAutosolve is put to false,
// then solve() needs to be invoked explicitly before using
// variables' values
// (Turning off autosolve while adding lots and lots of
// constraints [ala the addDel test in ClTests] saved
// about 20% in runtime, from 68sec to 54sec for 900 constraints,
// with 126 failed adds)
ClSolver &SetAutosolve(bool f)
{ _fAutosolve = f; if (f) Solve(); return *this; }
// Tell whether we are autosolving
bool FIsAutosolving() const
{ return _fAutosolve; }
#ifndef CL_NO_IO
friend ostream &operator<<(ostream &xo, const ClSolver &solver);
virtual ostream &PrintOn(ostream &xo) const = 0;
#endif
protected:
// C-style extension mechanism so I
// don't have to wrap ScwmClSolver separately
void *_pv;
bool _fAutosolve;
PfnChangeClvCallback _pfnChangeClvCallback;
};
#ifndef CL_NO_IO
ostream &PrintTo(ostream &xo, const ClVarVector &varlist);
ostream &operator<<(ostream &xo, const ClVarVector &varlist);
ostream &PrintTo(ostream &xo, const ClConstraintToVarSetMap &mapCnToVarSet);
ostream &operator<<(ostream &xo, const ClConstraintToVarSetMap &mapCnToVarSet);
ostream &PrintTo(ostream &xo, const ClConstraintSet &setCn);
ostream &operator<<(ostream &xo, const ClConstraintSet &setCn);
ostream &PrintTo(ostream &xo, const list<FDNumber> &listFDN);
ostream &operator<<(ostream &xo, const list<FDNumber> &listFDN);
#endif
#endif

View file

@ -0,0 +1,43 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClStayConstraint.h
#ifndef ClStayConstraint_H
#define ClStayConstraint_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include "Cassowary.h"
#include "ClEditOrStayConstraint.h"
class ClStayConstraint : public ClEditOrStayConstraint {
typedef ClEditOrStayConstraint super;
public:
ClStayConstraint(const ClVariable var,
const ClStrength &strength = ClsWeak(), double weight = 1.0 ) :
ClEditOrStayConstraint(var,strength,weight)
{ }
virtual bool isStayConstraint() const
{ return true; }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{ super::PrintOn(xo); return xo << " STAY)"; }
#endif
private:
};
#endif

View file

@ -0,0 +1,91 @@
// $Id$
//
// Cassowary Incremental Constraint Solver
// Original Smalltalk Implementation by Alan Borning
// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
// http://www.cs.washington.edu/homes/gjb
// (C) 1998, 1999 Greg J. Badros and Alan Borning
// See ../LICENSE for legal details regarding this software
//
// ClStrength.h
#ifndef ClStrength_H
#define ClStrength_H
#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
#include <cassowary/config-inline.h>
#define CONFIG_INLINE_H_INCLUDED
#endif
#include <string>
#include "Cassowary.h"
#include "ClSymbolicWeight.h"
using std::string;
class ClStrength;
const ClStrength &ClsRequired();
const ClStrength &ClsStrong();
const ClStrength &ClsMedium();
const ClStrength &ClsWeak();
class ClStrength {
public:
ClStrength(const string &Name, const ClSymbolicWeight &symbolicWeight) :
_name(Name), _symbolicWeight(symbolicWeight)
{ }
// special case for when nLevels = 3, should assert nLevels() == 3
ClStrength(const string &Name, double w1, double w2, double w3);
virtual ~ClStrength()
{ }
virtual bool IsRequired() const
{ return (_symbolicWeight == ClsRequired()._symbolicWeight); }
#ifndef CL_NO_IO
virtual ostream &PrintOn(ostream &xo) const
{
xo << Name();
if (!IsRequired())
xo << ":" << symbolicWeight();
return xo;
}
friend ostream& operator<<(ostream &xos, const ClStrength &Cls)
{ Cls.PrintOn(xos); return xos; }
#endif
virtual const ClSymbolicWeight &symbolicWeight() const
{ return _symbolicWeight; }
void SetPv(void *pv)
{ _pv = pv; }
void *Pv() const
{ return _pv; }
private:
string Name() const
{ return _name; }
void SetName(string Name)
{ _name = Name; }
void SetSymbolicWeight(const ClSymbolicWeight &symbolicWeight)
{ _symbolicWeight = symbolicWeight; }
// instance variables
string _name;
ClSymbolicWeight _symbolicWeight;
void *_pv;
};
#endif

Some files were not shown because too many files have changed in this diff Show more